Red, then green.

DebugBrief records what you run and what you notice while you debug, then turns it into a brief for your pull request, your handoff, or your incident review. Every line comes from something that actually happened.

No AI. No guessed root causes. No uploads.

pipx install debugbrief

Python 3.9+ on macOS and Linux

A recorded debugging session

$ debugbrief start "Handle an expired cache entry"
Started DebugBrief session.
$ debugbrief run -- python -m pytest -q tests/test_cache.py
F [100%]
E AssertionError: expired entry returned instead of a cache miss
1 failed in 0.40s
  status:    failed (exit 1)
  next:      edit, then debugbrief redo
$ debugbrief note "Expired entries still reach the read path. Check the expiry boundary."
Noted locally · 1 note · session 11111111
$ debugbrief redo
$ python -m pytest -q tests/test_cache.py  (redo)
. [100%]
1 passed in 0.40s
  status:    passed (exit 0)
$ debugbrief end --format html --open
Session completed: Handle an expired cache entry
  html:      .debugbrief/reports/11111111…-pr.html

# what gets recorded

  1. {
  2. "command": "python -m pytest -q tests/test_cache.py",// the exact command
  3. "exit_code": 1,// the real exit code, the only source of pass or fail
  4. "status": "failed",
  5. "duration_seconds": 0.4,// how long it ran
  6. "stdout_preview": "E AssertionError: expired entry returned instead of a cache miss\n1 failed",// a bounded preview of the output
  7. "stdout_truncated": false,
  8. "redacted": false,// secrets are masked before anything is written
  9. "git": { "branch": "fix/cache-expiry", "initial_sha": "a7c40e1" }// git state
  10. }
Excerpt from data/sample-pr.json: the first recorded command and the session's git block.

# reports

Recorded session, 12:02:00 to 12:06:00 pytest failed at 12:02:12 and passed at 12:04:12. ruff passed at 12:05:12. Two notes were recorded between the pytest attempts. Verified. 2m 0s src/cache.py · tests/test_cache.py pytest · exit 1 pytest · exit 0 ruff · exit 0 12:02:00 12:06:00
  • 12:02:12 pytest failed, exit 1
  • 12:04:12 pytest passed, exit 0
  • 12:05:12 ruff passed, exit 0
  • red to green: 2m 0s · src/cache.py, tests/test_cache.py
Files changed between the failing and passing check: correlation, not proven cause.
Mode
pull request
Session
11111111-2222-4333-8444-555555555555
Project
cache-service
Branch
fix/cache-expiry
Commit
a7c40e1
Started
2026-01-01 12:02:00 UTC
Ended
2026-01-01 12:06:00 UTC
Commands
3 (1 failed)
Notes
2

Handle an expired cache entry

Summary

Failing check python -m pytest -q tests/test_cache.py passed; 3 commands recorded in the session over 4m 0s, changes touched src/cache.py, tests/test_cache.py.

Evidence status

verified

Basis
the same recorded check failed and later passed
Scope
This verifies the recorded check, not the whole issue.
Root cause
Not inferred by DebugBrief.

Red to green

A check failed at 12:02:12 and python -m pytest -q tests/test_cache.py passed at 12:04:12 (window 2m 0s).

Between the failing and passing checks, these files changed (correlation, not proven cause):

  • src/cache.py
  • tests/test_cache.py

Timeline

  1. commandpython -m pytest -q tests/test_cache.py failed (exit 1)
  2. noteExpired entries still reach the read path. Check the expiry boundary.
  3. noteReturn a cache miss when the entry expires. Added the boundary case to the test.
  4. commandpython -m pytest -q tests/test_cache.py passed (exit 0)
  5. commandpython -m ruff check src tests passed (exit 0)

Generated by DebugBrief. This report is built from explicitly recorded notes, executed commands, and Git state when available. DebugBrief does not use AI and does not infer root causes, intent, or results.

# what it will never do

--- the usual way
+++ debugbrief

  1. an AI summary of what probably happened
  2. a record of what actually happened
  3. "tests pass" because someone said so
  4. pass or fail from the exit code, nothing else
  5. a guessed root cause
  6. Root cause: Not inferred by DebugBrief.
  7. your session uploaded somewhere
  8. everything stays in .debugbrief/ on your machine

# works with your checks

Anything else counts as a check with --verify.

# evidence explorer

Open a JSON report in your browser to search commands, read output and review changes. It is parsed in this tab only and is never uploaded or stored.

Open the Explorer
sample-pr.json3 recorded attempts

Handle an expired cache entry

failed
exit 1
python -m pytest -q tests/test_cache.py

12:02:12 · 0.4s

passed
exit 0
python -m pytest -q tests/test_cache.py

12:04:12 · 0.4s

passed
exit 0
python -m ruff check src tests

12:05:12 · 0.08s

# limits

  • No full-screen TUI capture, such as vim or htop.
  • No passive shell-history capture.
  • Redaction is best effort. Review reports before sharing.
  • No native Windows or PowerShell support.
  • No inferred root cause.

# install