Promptheus/commands36 commands · free · CC0Promptheus hub ↗
← All commands
/trace <symbol | value | flow>

Understand

Trace it

Follow a value or request through the whole flow.

tracedata-flow
CategoryUnderstand
Arguments<symbol | value | flow>
Allowed toolsReadGrepGlob
What it does

Trace a value, request or flow end to end through the code — where it starts, every transformation, where it ends.

.claude/commands/trace.md.claude/commands/ (project) · ~/.claude/commands/ (global)
Install into your repo
npx promptheus-commands add trace

The prompt

Trace $ARGUMENTS end to end through this codebase: where it originates, every transformation and handler it passes through, and where it terminates.

If $ARGUMENTS is empty, ask the user what to trace (a variable/field, a function or symbol, an HTTP route, an event, a config value, or a user request like "the checkout total") and stop until they answer.

Method

  1. Classify the target. Decide what $ARGUMENTS is: a data value/field, a symbol (function/class/method), an entry point (route, CLI command, event/message handler, cron), or a described flow. This dictates the search strategy.
  2. Learn the conventions first. Skim the manifest and structure (package.json / pyproject / go.mod / Cargo.toml, framework config, folder layout) to identify the stack, the router/DI/event mechanism, and naming patterns. Follow what the code actually does — do not assume a framework.
  3. Find the origin. Locate where the target first enters the system: its definition, the request/event that produces it, a DB read, an env/config load, or a literal assignment. Prefer language-server navigation when available — go-to-definition, find-all-references, go-to-implementation, call-hierarchy — for precise, type-aware resolution. Where no LSP exists, grep for the identifier and its aliases (renamed vars, destructured fields, wrapper functions, serialized/DTO names, snake_case↔camelCase, string keys) — but treat grep as lossy: discard over-matches on common identifiers, and because it silently misses runtime-resolved references, search separately for reflection, string-keyed dispatch tables, config-driven wiring, and codegen.
  4. Walk it forward, one hop at a time. From the origin, follow each step the data/control takes: assignments, function/method calls, returns, parameter passing, mutations, serialization, storage writes, network/queue emits. Open each file to confirm — never infer a hop you haven't read.
  5. Cross boundaries deliberately. At each indirection (interface/abstract method, DI-injected impl, event emit→listener, HTTP client→server route, RPC, dynamic dispatch, callback/promise/await), resolve the concrete implementation actually wired up — use go-to-implementation or find-all-references, or trace the registration/DI config, when grep alone can't disambiguate — and continue there. Note where a boundary leaves the next hop ambiguous.
  6. Record branches and side effects. At every conditional fork, early return, retry, catch/error path, or guard, note the condition and each outcome. Flag side effects: DB writes, cache updates, external calls, logs, file/state mutations, events emitted.
  7. Terminate when the value is stored, returned to the caller, rendered, sent over the wire, or discarded — for each distinct branch.

Output

  • Summary (2-3 lines): what the target is, where it starts, where it ends.
  • Trace as an ordered list, one line per hop: N. path/to/file.ext:LINE — <the exact transformation, call, or check>.
  • Number the primary path 1, 2, 3…. At a fork, do not indent or draw connectors — open a labeled sub-trace on its own line: Branch A [condition]:, then number that branch's hops A1, A2, A3…. If a branch forks again, start a new label (Branch A.1 [condition]:) at the same left margin rather than nesting deeper — never exceed one indent level; deep or multi-fork traces get labels, not stairsteps. List branches in the order they diverge.
  • Side effects: bullet list of every write/emit/external call encountered, each with file:line.
  • Gaps: anything you could not resolve (dynamic dispatch with multiple impls, reflection, config-driven wiring, missing code) — state the ambiguity and the candidates, do not guess a single answer.

Rules

  • Read-only: never edit, run, or stage anything — grep, open files, navigate, and report only.
  • Every hop and side effect MUST cite file:line. No claim without a location you actually opened.
  • Prefer showing the real call chain over prose. If a hop is uncertain, mark it uncertain rather than asserting it.
  • Do not stop at the first match — follow the target to every terminus, including error and edge branches.
  • If the target has multiple distinct origins or flows (e.g. same field set in several places), trace each and label them.

Add it to your toolkit

Save it as .claude/commands/trace.md or .cursor/commands/trace.md, then invoke it with /trace and your arguments.

Back to top ↑