Ongoing capability tracker for
fallow-rs/fallow. Complement toresearch/competitive-scan-2026-04.md, which captured the first three-tool scan (fallow, AZidan/codemap, JordanCoin/codemap) and the items it drove into PR #23.Last refreshed: 2026-04-30 against fallow
v2.56.0(npm; ~1.6k stars at refresh). Why a separate tracker: fallow ships rapidly (149 releases as of 2026-04-29); a per-tool note keeps the comparison surface re-runnable without dragging the dated scan along. AZidan and JordanCoin haven't moved; they stay in the dated scan.
This refresh is grounded in a third-party graph audit run against a TanStack-Router / TS app, where both Codemap and Fallow were used side-by-side across ~14 sections (ownership map, owner→owner dependency matrix, fan-in / fan-out hotspots, hook-heavy components, file LoC, external consumers, cycles, folder-size discipline, dead code, public-surface barrel usage). The exercise is the most recent bottom-up evidence of where each tool stops and the other starts.
Findings worth importing here (the rest is methodology-specific):
- Codemap is irreplaceable for ad-hoc graph shape questions. Sections 1–7 of the audit (owner partition, owner→owner matrix, top-30 fan-in, top-15 fan-out, hook-heavy components, ≥300-LoC files, cross-feature edges) were Codemap-only — there is no Fallow command that produces an arbitrary owner-bucketed dependency matrix. SQL flexibility is the moat.
- Codemap mis-classifies closed dead sub-graphs as live. The audit found an 8-file widget pack created in an earlier refactor that no consumer ever wired up. Each file imported the others, so every file had non-zero fan-in by the codemap dependency table; the codemap "zero-fan-in" recipe missed the entire pack. Fallow's re-export-aware analysis (
fallow dead-code --unused-files) caught all 8. This is the canonical case where Codemap's structural-only posture leaves true gaps. Adoption candidates A.4 and (much further out) E.15 below address it. - PR-scoped delta is the most-felt gap. Hydrating the audit twice (once after PR #1474–#1477, again after PR #1478) required hand-computing every section's delta vs the prior commit. Fallow's
audit --base <ref>does this with one command. §B.5 below is the single highest-leverage candidate this refresh. - Per-row
actionshints save the agent a derivation step. Every Fallow finding in--format jsoncarries anactions: [{type, auto_fixable, description, comment?}]array. When the audit needed to write recommendations ("delete this file", "drop this export"), the action was already named in the JSON; the agent just transcribed it. Codemap rows currently force the agent to re-derive what to do with each row.
Action hints in this section are proposals — not commitments. Tier hints reflect rough effort vs. payoff at the time of the refresh; promote into roadmap.md § Backlog only when designed.
| # | Candidate | Sketch | Why this tier |
|---|---|---|---|
| A.1 | Per-row actions array on common recipes |
Each row from query --recipe <id> optionally carries actions: [{type, auto_fixable, description}]. Examples: zero-fan-in-files row → [{type:"delete-file", auto_fixable:false}]; deprecated-symbols row → [{type:"open-deprecation-issue"}]; barrel-files row → [{type:"split-barrel"}]. Recipe authors define the action template; the SQL stays untouched. Future ad-hoc SQL doesn't get actions automatically — that's fine, it's a recipe-only feature. |
Mirrors fallow's killer agent-facing detail. Pure recipe-layer change in src/cli/query-recipes.ts — no schema impact. |
| A.2 | --changed-since <ref> on query |
Filters every query result row to files whose path matches git diff --name-only <ref>...HEAD. Implementation: pre-compute the changed-file set, append AND <left-table>.file_path IN (...) (or from_path / to_path for dependencies queries) to the SQL. Same primitive fallow uses for --changed-since main. |
Unlocks PR-scoped queries without codemap audit (which is bigger — see B.5). Cheap; no schema impact. |
| A.3 | --group-by owner|directory|package |
Partition any file_path-bearing query result by CODEOWNERS first-owner / first directory component / workspace package. Implementation: post-process at JSON emit time; no SQL change required. |
Layered on top of existing query output; no schema impact. CODEOWNERS reading is the only new bit. |
| A.4 | --summary flag |
Counts only, no rows. Useful pair with --recipe for dashboards / agent context windows. |
Trivial; aligns with codemap context --compact. |
| # | Candidate | Sketch | Why this tier |
|---|---|---|---|
| B.5 | codemap audit --base <ref> — structural-drift verdict |
Single command returning {verdict: "pass"|"warn"|"fail", deltas: {…}}. Built-in deltas: new files / deleted files / new edges in dependencies / new boundary crossings against a glob list / new cycles / top-N hot-file movements / new @deprecated symbols. Highest-leverage candidate this refresh — the audit hydrate loop hand-computed every one of these. Verdict thresholds are config-driven (per-delta error|warn|off). Don't try to compete with fallow audit on dead-code or duplication; stay structural. |
This is the gap that hurt most in real use. Architecture work needed: where delta computation lives, how thresholds are configured, what the "two-snapshot diff" abstraction looks like (probably temp DB on the base ref, similar to fallow's git-worktree approach). Worth a plans/<name>.md. |
| B.6 | --save-baseline / --baseline on query |
Save current row-set to a JSON file; on next run compare and emit only the diff. Fallow ships this for all of dead-code / dupes / health. Codemap users would use it to baseline the dependency-edge count, the hot-file top-30, the boundary-violation set — anything queryable that should not regress. |
Independent of B.5 but composes well with it. JSON snapshot file (probably under .codemap/baselines/<recipe>.json) is straightforward. |
| B.7 | JSDoc visibility extracted as structured exports.visibility column |
Already partially shipped: PR #23's visibility-tags recipe parses @public / @internal / @beta / @alpha / @private from doc_comment. Promote the parser output into a real column on exports (or symbols) so queries like WHERE visibility = 'beta' don't need a LIKE '%@beta%' regex. Schema bump — counts as a minor per .agents/lessons.md "changesets bump policy". |
Removes the two-step recipe (parse + filter) that the current setup forces. Aligns Codemap's surface with fallow's first-class JSDoc handling without copying fallow's rule machinery. |
| B.8 | --format sarif and --format annotations (GitHub PR inline) |
SARIF gives --format json consumers a path into GitHub Code Scanning without an Action wrapper. --format annotations emits the ::warning file=…,line=…::msg GitHub-Actions output format — Fallow uses this to write inline PR comments without needing a custom Action. |
Both are pure output-formatter additions on top of the existing JSON pipeline. The reason this is B not A: deciding the SARIF rule-id taxonomy for arbitrary recipes needs a small design pass. |
| # | Candidate | Sketch | Why this tier |
|---|---|---|---|
| C.9 | Framework plugin layer (entry-point + convention-export awareness) | Fallow's 91 plugins teach it that a Next.js app/page.tsx default export is a live entry, that Storybook stories are entries, that Vite vite.config.ts aliases mean ~/foo resolves to src/foo, etc. Codemap currently treats every file equally — that's why the audit's hands-on §10 had to hand-maintain a "4 known re-export false positives" list. A plugin layer is the only feature that closes the §10 gap structurally. Don't replicate fallow's full plugin API; start with entry-point hints (each plugin contributes a glob → is_entry: true annotation on files), expand to convention exports if demand emerges. Plugin contract should be small enough that the community can add plugins without forking the core. Cross-references: existing roadmap item "Community language adapters" is adjacent (per-language adapters) but distinct (per-framework conventions). |
The single feature that would let Codemap's dependencies table be authoritative for "is this file dead" instead of advisory. Big surface — plugin contract design, registry mechanism, version negotiation. Worth a plans/<name>.md before any code. |
| C.10 | LSP server + Code Lens with reference counts | Hover an import statement → "fan-in: 17 callers, fan-out: 3"; gutter badge on @deprecated symbols using existing doc_comment; "go to N callers" code action backed by the calls table. Fallow ships LSP + a VS Code extension with status bar / tree views. Codemap has neither. The data is already in the SQLite index — this is presentation, not analysis. |
Independent of B.5 / C.9 but very visible. Adds runtime requirements (LSP needs a long-lived process or quick-start) — interacts with the persistent daemon non-goal. LSP is a separate process model from "one-shot CLI"; design carefully. |
| C.11 | Static coverage ingestion (coverage-final.json → symbols.coverage_pct) |
Add coverage_pct REAL and is_runtime_hot INTEGER columns to symbols (or files), populated from an Istanbul coverage-final.json if --coverage <path> is passed at index time. Then queries like "find unused exports with 0% test coverage" or "rank hot files by fan-in × coverage" become single SQL queries. Fallow's runtime-coverage layer is paid; the static side (Istanbul ingestion) is free and complements Codemap's structural posture nicely. |
Schema bump (minor per lessons.md). One-time ingester, no continuous integration with V8 traces. Production beacons (fallow's paid moat) explicitly out of scope. |
| # | Candidate | Reason |
|---|---|---|
| D.12 | Suppression comments (// codemap-ignore-next-line) |
Only relevant if Codemap pivots toward shipping opinionated rules / verdicts. Today Codemap ships SQL primitives, not assertions — there's nothing to suppress. Reconsider only after B.5 (codemap audit) lands and starts producing pass/warn/fail. |
| D.13 | Per-rule severity in config ({rules: {…: "error"|"off"}}) |
Same condition as D.12 — meaningless without first-class assertions. If B.5 lands, this becomes the natural config shape for the audit thresholds. |
| D.14 | fallow fix --dry-run equivalent |
Codemap doesn't own behaviour to fix. Per-row actions (A.1) carries fix suggestions; executing them is the agent's job, not Codemap's. Don't grow a fix engine — the structural-index thesis stays cleaner without one. |
| D.15 | Suffix-array duplication detection | Codemap is not a duplication tool — that's covered by roadmap.md § Non-goals (v1) and the user reaches for fallow dupes or jscpd. Replicating fallow's suffix-array engine would dilute the structural-index thesis. Same logic as the dead-code non-goal. |
| D.16 | Runtime intelligence (V8 / production beacons) | Fallow's paid moat. Static coverage ingestion (C.11) is in scope; production beacons are not. |
These overlap with what fallow does, but were already on roadmap.md § Backlog before this refresh — go there for the latest status:
- MCP server wrapping
query— agents callquery/recipe/schema/indexdirectly without a Bash round-trip. Same UX shape as fallow's MCP integration with Claude Code / Cursor / Codex. - HTTP API (
codemap serve) — adjacent transport for non-MCP consumers. - Watch mode — re-analyse on file changes; fallow has
fallow watchwith the same shape. - Monorepo / workspace awareness — fallow has
--workspace,--changed-workspaces. Codemap's roadmap item targets per-workspace dependency graphs. - Targeted-read CLI (
codemap show <symbol>) — adjacent to A.1 actions but a separate ergonomic affordance.
If any of these get prioritised, fallow's CLI flag shape is the closest precedent — copying it where it doesn't cost anything keeps the surface familiar to fallow users.
PR #23 shipped fallow-inspired items in 2026-04 — see research/competitive-scan-2026-04.md § 3. Highlights:
deprecated-symbolsandvisibility-tagsrecipes (inspired by fallow's JSDoc visibility tags) — currently regex-based ondoc_comment; B.7 above proposes promoting to a structured column.- "Grep/Read vs Codemap" capability table in the root README (inspired by fallow's "Linter vs Fallow" framing).
The dated scan stays the canonical record of that pass; this file picks up where it left off.
These are the things fallow does that Codemap should explicitly not adopt — copying them would dilute the SQL-index thesis:
| Fallow capability | Why Codemap should skip it |
|---|---|
| Pre-baked verdicts as the foundation | Fallow's posture is "the tool wrote the predicate, you read the verdict." Codemap's posture is "you write the predicate." Don't lose that. B.5 (codemap audit) is fine because it's a wrapper over query recipes — query itself stays the foundation. |
| Suffix-array clone detection / Rust-native speed | Different stack, different optimisation choices. Codemap is fast enough for incremental TS via oxc — chasing fallow's perf would require a rewrite. See also D.15. |
| Runtime intelligence (V8 / Istanbul beacons) | Fallow's paid moat. Static coverage ingestion (C.11) is fine; production runtime tracking is out of scope. See also D.16. |
| Embedded fix engine | Fallow has fallow fix that mutates code. Codemap should stay read-only — fix suggestions via A.1 actions are enough; execution is the agent's job. See also D.14. |
Captured here so the symmetry is honest — the audit exercise made these visible too:
- Ad-hoc SQL on the structural index. Fallow ships pre-baked verdicts; Codemap lets you write any predicate. Owner→owner matrix, fan-in top-30, public-surface importer counts — all Codemap-only because no fallow command produces them.
components.hooks_usedJSON column. React hook usage per component is a Codemap extraction; fallow doesn't surface this.- CSS variables / classes / keyframes. Fallow doesn't model CSS at all.
markerstable. TODO / FIXME / HACK as queryable rows with line + content. Fallow doesn't surface markers.type_memberstable. Field-level type inventory queryable. Fallow's analysis doesn't go to this depth.callstable. Caller→callee at the symbol level. Fallow's analysis is module-level.
Don't trade these away for fallow parity — they're the moat. The Tier A / B candidates above are explicitly designed to layer on top of these strengths, not replace them.
- Should
actions(A.1) live in recipe definitions or be derived? Two shapes: (a) recipe author hand-writes theactionstemplate alongside the SQL — predictable, every row gets the same actions; (b) a small action-derivation layer keyed off recipe id + row shape — less code, less control. Bias toward (a) for the first pass. - How invasive should the framework plugin layer (C.9) be? Two extreme shapes: (i) plugins only contribute entry-point globs (
is_entry: trueannotation onfiles); (ii) plugins can contribute arbitrarydependenciesedges (e.g. "Next.js'snext/linkhref references this route"). (i) keeps the surface small and composable; (ii) catches more but explodes the contract surface and risks plugin drift. Bias toward (i) — see how far it gets us before reaching for (ii). codemap audit(B.5) verdict threshold defaults. Fallow defaults topass / warn / failwith reasonable thresholds. Codemap's structural deltas don't have obvious thresholds yet ("how many new dependency edges is too many?" depends entirely on the project). First pass probably exposes raw deltas only and lets the consumer set thresholds incodemap.config.*.- Coverage ingestion (C.11) — column on
symbolsor separatecoveragetable? Puttingcoverage_pctonsymbolskeeps queries simple but couples schema bumps to coverage shape changes. Acoveragetable with(symbol_id, coverage_pct, last_updated)is more flexible but forces every coverage query to JOIN. Probably worth prototyping both before committing.
- Prior three-tool scan:
research/competitive-scan-2026-04.md - Fallow upstream:
fallow-rs/fallow(refresh hash:v2.56.0, 2026-04-29) - Fallow's audit-on-PR thresholds (the closest cousin to Codemap's B.5 candidate):
fallowREADME § Audit - Codemap roadmap items already overlapping with fallow:
roadmap.md § Backlogandroadmap.md § Non-goals (v1) - Adjacent ongoing work:
agents.md(thecodemap agents initsurface that fallow's MCP / Skill packaging mirrors)