Patterns observed across Claude Code sessions that current tracedecay tools don't cover well. Each entry explains what triggered it, what the workaround looked like, and what the tool should do.
Cross-project scan of ~32 project transcripts (~161 MB) backing the gap analysis below:
| Metric | Count |
|---|---|
| Total Bash invocations | 4591 |
| Total Read calls | 2023 (1571 with offset/limit) |
| Total tracedecay tool calls | ~200 |
cargo check/test/clippy/build |
777 |
grep for source code |
1049 (618 for symbol-skeleton extraction) |
find -name for files |
92 |
sed -n 'A,Bp' line-range reads |
52 |
git log / show / blame |
130 / 32 / 1 |
The 23× ratio of Bash : tracedecay for code research is the headline. Three highest-volume
gaps — compile diagnostics, file-symbol skeletons, and AST-pattern search — are responsible
for roughly 60% of it. New entries below (tracedecay_diagnostics, tracedecay_unsafe_patterns,
tracedecay_signature_search, etc.) target each in turn; the existing tracedecay_outline
proposal already covers the symbol-skeleton case and is reinforced by the new evidence.
Trigger: Evolving a struct field — adding last_sync_duration_ms to GraphStats required
finding every place last_sync_at was written across the codebase. After tracedecay_search
identified the symbol, 4 separate grep passes were needed to locate all write sites in different
files and function bodies.
Gap: tracedecay_callers covers call sites of functions/methods. Nothing covers field
reads vs. writes.
Proposed API:
{ "field": "last_sync_at" }
{ "field": "GraphStats::last_sync_at" }Returns: Two lists — write_sites and read_sites — each with file, line, enclosing
function, and a short code snippet. Optionally filterable to writes-only.
Value: Any time a field is renamed, removed, or gets a new invariant, the write-site list is the exact blast radius. Currently requires multi-file grep + manual triage.
Trigger: Adding 9 new language extractors required understanding the existing extractor
interface. Multiple grep -r "fn extensions" and grep -r "fn language_name" passes were made
across all *_extractor.rs files to see how existing types implement the trait.
Gap: tracedecay_type_hierarchy handles class inheritance. Nothing returns "all types that
implement method X" with their concrete bodies.
Proposed API:
{ "trait": "LanguageExtractor" }
{ "method": "extensions" }
{ "method": "count_complexity" }Returns: For each implementing type: the type name, file, and the method body (or bodies, if overloaded). When querying by trait, returns all method implementations grouped by type.
Value: The canonical "how does an existing implementation look?" question when adding a new implementor to an interface. Currently answered by grepping for each method name separately.
Trigger: Adding a required field last_sync_duration_ms to GraphStats required finding
every struct literal GraphStats { ... } to add the new field. tracedecay_callers doesn't cover
struct construction — only function calls.
Gap: Struct literal construction sites are invisible to the existing call-graph tools.
Proposed API:
{ "struct": "GraphStats" }Returns: Every location where the struct is instantiated as a literal (not via a constructor function), with file, line, and the field list present in that literal. Bonus: flag sites that are missing the requested field (useful when you've just added one).
Value: Making a struct field required is a frequent refactor. The cargo check error list
covers this for Rust, but the tool gives the list before compilation, with context, and works
for languages without exhaustive struct checking.
Trigger: In quality-improvement sessions, the common opening move was
wc -l src/main.rs && grep -n "^pub fn\|^pub struct\|^pub enum\|^impl" — a "get bearings"
sweep before diving into a large file. tracedecay_module_api shows only the public API;
tracedecay_context is heavier than needed when you just want navigation landmarks.
The cross-project scan found 618 invocations of this pattern, the single largest
grep category — confirming it as a recurring opening move on essentially any large file.
Gap: No lightweight "what's in this file?" dump that includes private symbols with line numbers.
Proposed API:
{ "file": "src/tracedecay.rs" }
{ "file": "src/tracedecay.rs", "kinds": ["function", "struct", "impl"] }Backend: The outline uses the optional external ast-grep CLI capability,
the same dependency family as structural refactor tools such as
tracedecay_ast_grep_rewrite. It requires ast-grep >= 0.44 on PATH because
outline support depends on the CLI's outline command. There is no
backend-selection argument.
Returns: A flat list of {kind, name, line, visibility} for every top-level symbol in the
file, sorted by line. No code bodies — just the map. The response should also preserve the
DB-backed TraceDecay symbols for the same file in the same payload, so callers get the fresh
CLI outline without losing indexed graph symbols, ids, or qualified names needed for
follow-up graph calls.
Install guidance: tracedecay doctor should report when ast-grep is
missing or older than 0.44. After installing or updating ast-grep, rerun
tracedecay install or tracedecay update-plugin as appropriate so agent
integrations refresh their generated tool surfaces and guidance.
Value: Turns "where is X defined in this file?" from a Read + manual scan into a single
call. Also useful as a pre-flight before tracedecay_context — orient first, then zoom.
Trigger: Investigating whether logging was implemented required
grep -r "setLevel\|logging\|log_level\|LoggingLevel\|set_level" across the entire project.
The concept could live in function names, config keys, environment variable names, string
literals, or comments — tracedecay_search only matches symbol names.
Gap: Symbol search only covers named graph nodes. Concepts encoded in string literals, env var names, config keys, and comments are invisible.
Proposed API:
{ "concept": "logging" }
{ "concept": "authentication", "keywords": ["auth", "token", "session", "credential"] }Returns: Matching symbols (as tracedecay_search would), plus: string literal occurrences,
comment occurrences, and config key matches — each with file and line. Grouped by match type
so symbol hits stay prominent.
Value: The "is feature X even present in this codebase?" probe. Especially useful for inherited or unfamiliar codebases where the feature may not use the obvious identifier names.
Trigger: cargo check, cargo test, cargo clippy, and cargo build were invoked
777 times across all scanned conversations, with single sessions hitting 100+. Each
invocation re-compiles, dumps raw error text into the conversation, and Claude then has to
parse it back into structured form — usually then Read the offending file to see context.
The same loop repeats in TypeScript projects via tsc and Python via pyright.
Gap: No tracedecay tool wraps the compiler / type-checker. Errors arrive as flat text
disconnected from the graph; affected-set narrowing (already available via
tracedecay_affected) is not used to scope checks.
Proposed API:
{ "scope": "workspace" }
{ "scope": "affected", "since": "HEAD~1" }
{ "scope": "package", "name": "tracedecay" }
{ "scope": "file", "path": "src/mcp/tools/handlers.rs" }Returns: errors, warnings, each with file, line_start, line_end, code
(e.g. E0599, unused_imports), message, enclosing_symbol (graph node id), and a
short pre-extracted snippet. Caches the last clean state and the result digest so a
no-op re-run is free.
Value: Replaces a 3-step loop (run cargo → parse text → read file) with a single structured response that's already mapped to graph nodes. The biggest single Bash : tracedecay gap by raw count. Affected-set scoping turns 30-second full builds into sub-second incremental checks during refactor cycles.
Trigger: Security and quality-review conversations repeatedly grep for
panic!, unwrap(), expect(, todo!(), unimplemented!(), and unsafe blocks.
Same pattern surfaces under "production-validator" and "rust-performance-reviewer"
agent runs. Regex grep produces false positives (string literals containing the word,
identifiers like unwrapped_value).
Gap: No AST-aware finder for these markers. tracedecay_todos covers comment-style
markers (TODO, FIXME) but not call-expression patterns like .unwrap() or panic!().
Proposed API:
{ "kinds": ["unwrap", "expect", "panic", "todo", "unimplemented", "unsafe_block"] }
{ "kinds": ["unwrap"], "path": "src/mcp/" }
{ "kinds": ["panic"], "exclude_tests": true }Returns: Per match: kind, file, line, enclosing_symbol, snippet, and
in_test flag. AST-matched, so let unwrapped = ... and "do not unwrap" don't false-fire.
Value: Replaces a class of recurring greps in review/audit work. The in_test flag
matters because a .unwrap() in a test is fine; in lib.rs it's a panic site.
Pairs with tracedecay_test_risk for "what risky paths aren't tested?"
Trigger: Refactor questions of the form "find all functions returning
Result<_, MyError>", "find all impl Display for ...", "find every async function
that takes &mut self". Currently answered by tracedecay_search (name-only) plus
multi-file Read to inspect signatures one by one.
Gap: tracedecay_search matches on symbol names. tracedecay_implementations
(also proposed) covers trait/method implementor lists. Neither searches by
signature shape — return types, parameter types, generic bounds, attributes.
Proposed API:
{ "returns": "Result<_, anyhow::Error>" }
{ "returns": "impl Future" }
{ "params": ["&mut self", "_"], "async": true }
{ "attribute": "#[tokio::test]" }Returns: Matching symbols with file, line, signature, kind, and the matched
sub-pattern. Implementation can reuse the AST matcher already feeding tracedecay_ast_grep_rewrite.
Value: Unlocks signature-based refactoring questions that currently force a grep
- manual filter. Smaller volume than
tracedecay_outlinebut high token cost when it does come up — a single signature query can replace dozens of file Reads.
Trigger: Release work repeatedly hits patterns like
git show v3.4.4:Cargo.lock | grep -A5 'name = "zip"' to figure out what dep versions
changed between two refs. Same pattern for package-lock.json, pnpm-lock.yaml, uv.lock.
Gap: No tool parses lockfiles. tracedecay_branch_diff covers symbol-level diffs
but not dependency version changes.
Proposed API:
{ "from": "v3.4.4", "to": "v3.4.5" }
{ "from": "main", "to": "HEAD", "package": "zip" }Returns: Lists of added, removed, bumped (with old/new version), and
yanked. Detects lockfile format from the path.
Value: Single call to answer "what shifted in deps for this release?", which today
takes 2-3 git show | grep invocations per package.
Trigger: Many conversations dive into ~/.cargo/registry/src/... to read the source
of a dependency (figuring out an API, debugging a panic from inside a crate). This requires
find plus path navigation plus Read. Matching pattern in TS via node_modules/.
Gap: TraceDecay's graph is project-local. External symbols are unreachable; users have to leave the graph entirely.
Proposed API:
{ "crate": "tokio", "symbol": "spawn" }
{ "crate": "anyhow", "version": "1.0.86", "symbol": "Error::root_cause" }Returns: Resolved file path inside the registry, signature, body, and doc
when present. Optionally indexes the crate on demand into a side graph so subsequent
tracedecay_callers-style queries work against external code.
Value: Removes the registry-spelunking workaround. On-demand indexing is a larger investment but turns "I need to read a dep's source" into a single graph query.
Trigger: This repo (and most others) sees frequent greps over Cargo.toml,
.github/workflows/*.yml, tsconfig.json, pyproject.toml, package.json during
release/CI work — 62 such greps recorded. TraceDecay's tree-sitter pipeline doesn't
parse YAML/TOML structurally.
Gap: No structured query into config files. Users grep for keys, then re-read to verify the value.
Proposed API:
{ "path": "Cargo.toml", "key": "package.version" }
{ "path": ".github/workflows/release.yml", "key": "jobs.publish.steps[*].uses" }
{ "glob": "**/Cargo.toml", "key": "dependencies.tokio" }Returns: Parsed value(s), file, line of the key, and on glob queries a
list of matches across the workspace.
Value: Replaces a recurring grep + re-read pattern in release / CI conversations. Smaller blast radius than diagnostics but disproportionately common in the tracedecay repo's own conversation history.
Trigger: Rust-specific. When debugging a macro-heavy file (procedural macros, derive,
custom macro_rules!), tracedecay's tree-sitter view shows pre-expansion source — which
hides the actual generated code that produces the compiler error. Workaround is cargo expand,
which is slow and dumps an entire crate's worth of post-macro source.
Gap: No expanded-source view tied to a specific symbol or file region.
Proposed API:
{ "symbol": "MyStruct" }
{ "file": "src/foo.rs", "line": 42 }Returns: Expanded source for the requested region only, with file, line_range,
and source (post-expansion). Caches per-revision so repeated queries on a clean tree
are free.
Value: Niche but high token-cost when it does come up — a single cargo expand
on a workspace can be tens of thousands of lines. Region-scoped expansion is the difference
between "usable" and "fall back to raw source."
Not a tool proposal — but the scan found single-conversation Read counts of 76× for
src/tracedecay.rs, 85× for claurst/src-rust/crates/api/src/lib.rs, 47× for the
since-removed src/daemon.rs. This suggests either (a) the assistant doesn't trust prior cached snippets
to still be current, or (b) it lacks a "what's changed in this file since my last call"
signal and re-reads defensively. Worth investigating before adding more tools — could be
a tracedecay_context mode flag (incremental: true) that returns only deltas since the
last call within a session, rather than a new top-level tool.
Status: Shipped. Handler at src/mcp/tools/handlers.rs:handle_body, definition at
src/mcp/tools/definitions.rs:def_body. Tests in tests/mcp_handler_test.rs (3 cases).
Trigger: In claurst (a Rust project separate from tracedecay), the dominant navigation
pattern was grep -A 20 "pub fn resolve_provider_api_key" — reading a function or constant body
by name without knowing which file it lives in. The same grep -A N form appeared 15+ times for
functions, constants (CCH_SEED, ANTHROPIC_BETA_HEADER, CLIENT_ID), and struct fields.
TraceDecay was not active for that project, but the pattern maps directly to what
tracedecay_search + file offset Read + manual body extraction would do in three steps.
Gap (closed): No tool took a symbol name and returned its source body in a single call.
The previous flow was: tracedecay_search → read file:line → Read with offset → extract
manually.
Shipped API:
{ "symbol": "resolve_provider_api_key" }
{ "symbol": "CCH_SEED", "limit": 5 }
{ "symbol": "GraphStats::last_sync_at" }Returns: match_count and a matches array. Each match has: id, name,
qualified_name, kind, file, start_line, end_line, signature, body. Exact name
matches are preferred over fuzzy matches; falls back to ranked search results when no exact
match exists.
Status: Shipped. Handler at src/mcp/tools/handlers.rs:handle_todos, definition at
src/mcp/tools/definitions.rs:def_todos. Tests in tests/mcp_handler_test.rs (3 cases).
Trigger: In bruto-pascal-lang, three separate grep passes were made across the whole source
tree to find TODO, FIXME, XXX, HACK, WIP, and unimplemented!() markers — each
refining the pattern to catch more variants. These were used to build a "what needs finishing"
picture before starting a work session.
Gap (closed): No tool queried the project for annotation/comment markers with structured output including the enclosing symbol.
Shipped API:
{}
{ "kinds": ["TODO", "FIXME", "UNIMPLEMENTED"] }
{ "path": "src/codegen.rs", "limit": 50 }Returns: match_count, by_kind count summary, and a markers array. Each marker has:
kind, file, line, text (trimmed line content), enclosing (qualified name of the
smallest enclosing symbol, or null if at file scope). Word-boundary matching prevents
false positives like todoist.
Defaults: TODO, FIXME, XXX, HACK, WIP, NOTE, UNIMPLEMENTED. Matched
case-insensitively. Default limit is 200, max 2000.
Observed across all projects (tracedecay + claurst + bruto-pascal + amexx + others). The
Evidence column shows raw count of the workaround pattern from the 2026-05-04 telemetry
scan, where measurable.
| Tool | Status | Evidence | Complexity | Impact |
|---|---|---|---|---|
tracedecay_body |
✅ shipped | 1571 targeted Reads + 52 sed -n | Low | High |
tracedecay_todos |
✅ shipped | scattered across projects | Low | Medium |
tracedecay_diagnostics |
proposed | 777 cargo invocations | High (compiler integration) | Very high |
tracedecay_outline |
proposed | 618 symbol-skeleton greps | Low (optional ast-grep CLI outline + DB symbols) | High |
tracedecay_unsafe_patterns |
proposed | recurring in review/audit | Low (AST predicates) | High |
tracedecay_implementations |
proposed | tracedecay 22ff55cd, 67f09223 | Low (method edges) | High |
tracedecay_signature_search |
proposed | smaller volume, high token cost | Medium (AST matcher) | High |
tracedecay_field_sites |
proposed | tracedecay e790d3c4, 67f09223 | Medium (field write edges) | High |
tracedecay_constructors |
proposed | tracedecay e790d3c4 | Low (struct-literal node kind) | Medium |
tracedecay_feature_map |
proposed | tracedecay 67f09223, others | High (full-text index) | Medium |
tracedecay_config |
proposed | 62 config greps | Medium (TOML/YAML parser) | Medium |
tracedecay_lockfile_diff |
proposed | 6 lockfile greps | Low (lockfile parser) | Low-Medium |
tracedecay_external_node |
proposed | recurring registry spelunking | High (on-demand indexing) | Medium |
tracedecay_macro_expand |
proposed | niche, high cost when used | High (cargo expand integration) | Low-Medium |
Build order recommendation (revised after telemetry scan):
tracedecay_outline— optionalast-grepCLI outline with DB-backed TraceDecay symbols preserved in the same payload; requiresast-grep>= 0.44 and addresses the single largest grep category (618 hits). One afternoon.tracedecay_unsafe_patterns— AST predicates on top of the existing matcher. Replaces a recurring review-time grep family. Half-day.tracedecay_diagnostics— biggest single Bash : tracedecay gap. Highest impact even though complexity is the highest in this set; structured cargo errors mapped to graph nodes compress hundreds of recurring tool cycles. Multi-day.tracedecay_implementations— query existing method edges filtered by implementor. Low risk.tracedecay_signature_search— extends the matcher used byast_grep_rewrite; small surface.tracedecay_constructors— depends on struct-literal edge kind; check schema.tracedecay_field_sites— requires field-level read/write edges; may need schema work.tracedecay_config— TOML/YAML parsers exist; mostly path-and-key resolution.tracedecay_lockfile_diff— small, isolated, parser-bound.tracedecay_feature_map— requires a parallel full-text index; largest investment.tracedecay_external_node— on-demand indexing of registry crates is a meaningful design project; defer until prior items show whether the demand is sustained.tracedecay_macro_expand— niche; integratecargo expandonly iftracedecay_diagnosticswork surfaces a clear tie-in (macro-generated errors).
Before starting, also weigh the heavy re-read observation above — solving that signal
inside tracedecay_context (incremental delta mode) might remove a class of redundant Reads
without any new tool.
tracedecay_field_sites, tracedecay_feature_map, and tracedecay_external_node may need a
graph schema audit before scoping. The others should be buildable against the existing
node/edge model.