agentleFS
heietsheiets/universal-debug-mode-skill/SKILL.md

debug-mode

Skill0 starsChanged 59 days agoMITView on GitHub

Evidence-driven runtime debugging loop. Generates competing hypotheses, instruments the code with session-tagged probes that stream to an isolated local log sink, has the user reproduce the bug, then confirms or rejects each hypothesis from real runtime data before fixing and removing every probe. Use when a bug's cause is not obvious from reading the code, when a fix attempt has already failed, for heisenbugs, race conditions, state corruption, "works locally but not in prod", or whenever the user says debug mode, find the root cause, or add logging to figure this out.

8 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

10 rules. 0 are common, 5 are distinctive, and 5 are very specific to this project.

  • 0

    Common

    Most of the 8 edited versions we read keep these.

  • 5

    Distinctive

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never guess from source once instrumented: If zero logs arrived, run doctor and fix the pipeline.

    line 23
  2. Distinctive:

    Probes must be inert: never block, never throw, never mutate program state, never swallow an exception belonging to the code under test.

    line 27
  3. Very specific:

    If start reports that listening sockets are forbidden, re-run with --no-server — the rest of the loop is identical.

    line 46
  4. Distinctive:

    Read the relevant code first.

    line 50
  5. Distinctive:

    Read the NOTE the snippet prints — several runtimes send detached, and a short-lived process can exit before the probe lands.

    line 71
  6. Very specific:

    Every probe line must contain the sentinel — that is how cleanup finds it.

    line 75
  7. Distinctive:

    Write a marker so this attempt's evidence is separable from the last:

    line 96
  8. Very specific:

    If reproduced reports 0 log entries, the probes never reached the sink.

    line 124
  9. Distinctive:

    Leave the instrumentation in place — you need it to verify.

    line 151
  10. Very specific:

    Run $DBG doctor first — it checks the sink, the health endpoint, the capture count, and whether probes are present, then prints targeted …

    line 198

“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Debug Mode

Most debugging fails because the agent guesses from source code and ships a plausible fix that does not address the real cause. This skill forbids that. No fix may be proposed until runtime evidence has confirmed a specific hypothesis.

The loop: hypothesize → instrument → reproduce → read evidence → fix → verify → clean up.

Everything runs through one dependency-free CLI:

scripts/debugctl.py

Set DBG="python3 <abs path to>/scripts/debugctl.py" once and reuse it. Run it from inside the project being debugged.

Non-negotiables

  1. Hypotheses before probes. A probe exists to discriminate between competing explanations. If you cannot say which hypothesis a probe kills, do not add it.
  2. Never guess from source once instrumented. If zero logs arrived, run doctor and fix the pipeline. Do not fall back to reading code and calling it a root cause.
  3. The user reproduces, not you — unless they have handed you a command that triggers the bug. Stop and wait at the repro gate.
  4. A rejected hypothesis is a result. Record it. Do not quietly drop it.
  5. The session is not done until verify-clean exits 0. Leaving probes in the tree is the single most common failure of this style of debugging.
  6. Probes must be inert: never block, never throw, never mutate program state, never swallow an exception belonging to the code under test.

Phase 0 — Open an isolated session

$DBG start --goal "<one-line bug description>"

Prints a session id, a sentinel (e.g. DBG_A1B2C3D4), an ingest URL, and a log file. Everything is scoped to .debugsessions/<session-id>/ and auto-gitignored. Concurrent sessions get separate ports, separate logs, and separate sentinels, so they never interfere.

Flags that matter:

SituationFlag
Android emulator--host 10.0.2.2
Docker / compose--host host.docker.internal
Physical device--host <your LAN IP>
No network, sandbox, or bind denied--no-server (file sink)

If start reports that listening sockets are forbidden, re-run with --no-server — the rest of the loop is identical.

Phase 1 — Generate competing hypotheses

Read the relevant code first. Then record 3–5 hypotheses that disagree with each other. One hypothesis is not a hypothesis, it is a hunch.

$DBG hypo add "<what is actually wrong>" --signal "<the log line that would confirm or reject this>"

The --signal is the contract. Writing it forces the probe design: if you cannot name the observation that would settle the question, the hypothesis is too vague to test.

Aim for hypotheses at different layers — bad input, wrong branch taken, wrong order of operations, stale or shared state, boundary/type coercion, async timing. See references/hypotheses.md.

Phase 2 — Instrument

Get a correct emitter for the language, already carrying the right URL and sentinel:

$DBG snippet python              # with notes and a usage example
$DBG snippet python --helper     # just the helper block, safe to pipe into a file

Languages: python node browser typescript go java kotlin swift ruby php rust csharp c cpp shell dart elixir file, plus aliases (js, ts, react, android, ios, flutter, bash, golang, dotnet, …).

Read the NOTE the snippet prints — several runtimes send detached, and a short-lived process can exit before the probe lands.

Paste the helper once, then place one probe per hypothesis at the decision point that discriminates it. Rules:

  • Every probe line must contain the sentinel — that is how cleanup finds it. Multi-line helpers go between <SENTINEL>:begin and <SENTINEL>:end.
  • Put every probe on its own line. Cleanup deletes sentinel-bearing lines in full, so a probe appended to a line that also holds program logic would take that logic with it. Never do this:

    if (user.plan === "free") { return (_dbg("H1","b",{x}),"basic"); } // DBG_XXXX  ← deletes the branch

    Expand the block and give the probe its own line instead. cleanup refuses (exit 3) when it detects this and leaves the file untouched, but it is far cheaper to avoid.

  • Tag every probe with its hypothesis id (H1, H2, …).
  • Log values, not prose: the actual variable, the branch taken, the length, the id, the timestamp. "got here" proves nothing.
  • Capture both sides of a comparison — the expected and the actual.
  • Probe the boundary and the interior, so a silent probe tells you the code never reached it.

Then record what you touched:

$DBG instrumented    # lists every line carrying this session's sentinel

Phase 3 — The reproduce gate

Write a marker so this attempt's evidence is separable from the last:

$DBG mark "repro-1"

Then give the user exact, numbered reproduction steps and stop. Tell them what you expect to see. Wait.

The two actions that drive every cycle

The user comes back with exactly one of these:

A. "The issue reproduced" → the bug happened, evidence was captured.

$DBG reproduced --note "<what the user observed>"

Go to Phase 4.

B. "The issue is fixed" → the bug no longer happens.

$DBG fixed --note "<what the user observed>"

Go to Phase 6 — cleanup. This is a terminal action: stop investigating and remove the instrumentation.

If reproduced reports 0 log entries, the probes never reached the sink. Run $DBG doctor and repair the pipeline before drawing any conclusion.

Phase 4 — Read the evidence

$DBG summary                      # which probes fired, which stayed silent
$DBG logs --since-last-mark       # only this repro attempt
$DBG logs --hypothesis H2         # evidence for one hypothesis
$DBG logs --grep "user_id|null"   # regex across the payload

summary lists silent hypotheses — probes that never fired. A silent probe is evidence: that code path did not execute. That frequently is the bug.

Adjudicate every hypothesis, quoting the actual log values:

$DBG hypo set H1 confirmed  --evidence "tax_base=25.0 == subtotal while discounted=22.5"
$DBG hypo set H2 rejected   --evidence "apply_discount returned 22.5, the correct total"
$DBG hypo set H3 inconclusive --evidence "probe never fired; path not reached"

If every hypothesis is rejected, that is progress, not failure. You have eliminated the obvious. Form a new round from what the logs did show, add probes, and return to Phase 3. Do not start guessing.

Phase 5 — Root cause and targeted fix

State the root cause in one sentence, grounded in a specific log line. Then make the smallest change that addresses that cause. Do not refactor, do not fix adjacent things you noticed, do not "improve" the code while you are in there.

Leave the instrumentation in place — you need it to verify.

Mark a fresh attempt and hand the user verification steps:

$DBG mark "verify-1"

Then wait for one of the two actions again. If the bug still reproduces, the logs now tell you why the fix missed; iterate.

Phase 6 — Clean up (mandatory)

$DBG cleanup              # dry run: exactly what will be removed
$DBG cleanup --apply      # removes only THIS session's sentinel lines
$DBG verify-clean         # exits 0 only if the tree is clean
$DBG end                  # refuses to close while probes remain

cleanup backs up every modified file under the session directory first. It matches only this session's sentinel, so a concurrent debug session's probes are untouched.

Exit codes: cleanup returns 3 and changes nothing if any probe is mixed into a line of real code — hand-edit those lines to separate the probe, then re-run. verify-clean returns 2 while any probe remains, 0 when the tree is clean.

Read the final diff before reporting done. verify-clean proves the sentinel is gone; it does not prove the surrounding code is intact. Confirm the diff contains your fix and nothing else.

Finish by reporting: the root cause, the evidence that proved it, the hypotheses you rejected, and the diff you are shipping. Confirm verify-clean passed.

Command reference

CommandPurpose
start --goal "..."open an isolated session
status / listcurrent state / all sessions
snippet <lang> [--helper]ready-to-paste probe for that language
hypo add/set/listthe hypothesis ledger
mark <label>split one repro attempt from the next
reproduced / fixedthe two cycle actions
logs / summaryread and aggregate evidence
instrumentedlist every probe in the tree
doctorwhy no logs are arriving
cleanup --apply / verify-cleanremove probes, prove it
stop [--all] / endstop one sink (or every one in the project) / close the session

Global flags work on either side of the subcommand: --session <id> targets a specific session, --json gives machine-readable output, --root <dir> sets the project root.

When logs do not arrive

Run $DBG doctor first — it checks the sink, the health endpoint, the capture count, and whether probes are present, then prints targeted hints. Full matrix in references/transports.md.

The usual culprits: the app was never restarted after instrumenting; a browser page on https blocked from posting to an http sink; an Android emulator dialing 127.0.0.1 (itself) instead of 10.0.2.2; a container with no route to the host; or a process too short-lived for an async send to land — use --no-server and the file sink for that last one.

Further reading

  • references/hypotheses.md — how to generate hypotheses that actually discriminate
  • references/instrumentation.md — probe placement patterns, and what to log for races, state corruption, and performance
  • references/transports.md — getting logs out of browsers, emulators, containers, remote hosts, and CI

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.