Skip to content

Repository files navigation

FDML — a code navigation index and feature-to-evidence chain for AI coding agents

FDML is a local-first Rust CLI for working on a codebase with coding agents. It has three parts that work today:

  1. A code index (fdml index, search, get, outline, impact): tree-sitter symbols, call graph and a per-symbol micro-map in one SQLite file, so an agent asks "where is X" once instead of grepping and reading files. Works for C/C++, Rust, TypeScript/JavaScript, Python, Go, Java, C#.
  2. Project memory (note, dossier, history): postmortems, invariants, playbooks and pending work anchored to symbols or features, restored in one command after a context reset.
  3. A product model with proof (vision.fdml, work, evidence, gap, research, serve): features and scenarios in YAML, an operations journal a human accepts, and a join evidence → test → scenario → feature that says PROVEN, FAILED, UNKNOWN or NOT VERIFIED.

No cloud, no daemon, no LLM in the core path. A model is optional and only ever proposes typed operations; it never writes the spec.

Keywords: code navigation for LLM agents, repository index, semantic code search, feature specification language, requirements traceability, BDD scenarios to test evidence, agent memory, Rust CLI, tree-sitter, SQLite.

Install

git clone https://github.com/kolanski/FDML && cd FDML   # tag v0.6.3 is the current release
cargo install --path .                                  # the toolchain is pinned in rust-toolchain.toml (1.86)
fdml --version

Five minutes on your repository

Every line below is real output on a two-file TypeScript repo.

$ fdml index .
Indexed …/shop: 2 parsed, 0 unchanged, 0 removed, 7 symbols

$ fdml search "charge the card" --limit 3
payments.ts:1: export function chargeCard(order) {
payments.ts:5: export function validateCard(card) {
checkout.ts:1: import { chargeCard } from "./payments";

$ fdml get chargeCard
payments.chargeCard  payments.ts:1-4
export function chargeCard(order) {
  validateCard(order.card);
  return capture(order.total);
}
callers: checkout.checkout

$ fdml impact chargeCard
CALLERS
checkout.checkout
CALLEES / DEPENDS ON
payments.capture
payments.validateCard

Search is grep-shaped on purpose (path:line: source) so it drops into the same habit. Several phrasings go in one call: fdml search "charge card" "capture payment". Several symbols too: fdml get chargeCard validateCard --lines 80. A big function is read phase by phase with fdml outline <symbol>.

The index heals itself: if the code moved since the last run, any command reindexes first (about 15 ms when current, no watcher, no hook). When nothing useful is found the tool says so — ⚠ no useful result … fall back to grep — and you can teach it: fdml mark "<the query that failed>" <symbol>.

Remember what you learned

$ fdml note "card number missing" "Thrown by validateCard when the form sends an empty number; the fix is in the form, not here" --kind postmortem --at validateCard
Recorded postmortem "card number missing" @ validateCard

$ fdml search "card number missing" --limit 1
payments.validateCard  [marked]
  ↳ [postmortem] Thrown by validateCard when the form sends an empty number; the fix is in the form, not here

$ fdml dossier
ANCHOR   payments.validateCard
FLOW     checkout.checkout → payments.chargeCard → payments.validateCard
SYMPTOMS «card number missing»

Note kinds: postmortem, invariant, method, rejected, playbook, pending, link, domain, solution. A note anchored to a symbol is marked stale when that symbol's source changes. fdml dossier is the restore point: run it first when you pick up work, leave a --kind pending note when you stop mid-task.

Look at it in the browser

fdml serve --v2 --no-open .        # http://localhost:3000

One page: the product's features traced to code, research history, the work queue. It is rebuilt on every load from the index and the spec; nothing is cached.

The flow from code to a proven feature

This is how FDML is developed with FDML. Six of its own features are PROVEN this way.

fdml propose --out -                        # 1. candidate features from the code's behavioral units
# write vision.fdml by hand: 5–10 features with value and scenarios (see below)
fdml validate vision.fdml                   # 2. ids resolve, closed enums, value graph
fdml gap                                    # 3. what the vision declares vs what the scan observed

fdml work add '{"kind":"add_test_plan","scenario":"tool.research.s1",
  "test":{"id":"t.research.citations","reference":"research::tests::citations_by_id_become_packet_numbers","runner":"cargo-test"}}' --accept
fdml work export                            # 4. the journal reaches the file; accepted ops are visible to every reader before that
fdml evidence run --runner cargo-test       # 5. run the tests, translate the result into evidence
fdml evidence report                        # 6. the join
Feature: tool.research — Research: a question answered from the model
  ✓ proven                 Citations by id become packet numbers  (then 1 · tests 1)
      evidence: test research::tests::citations_by_id_become_packet_numbers… → verified
  Feature status: PROVEN  (1/1 scenarios with a passing linked test; then 1 · tests 1 across the feature)
  Conditions: runner=cargo test · profile=release · suites=5

Runners today: cargo-test, make-check. A runner is a small adapter that turns a checker's output into verified / failed / unknown per reference; the spec does the rest.

The journal is the third writer of the model after the human and the scanner. Operations are a closed set — add_scenario, add_test_plan, link_code, add_rule, add_feature, set_feature, add_decision — proposed as JSON, validated and dry-run against the model, accepted by a human, overlaid on every load, exported when the file should catch up. A model may emit an operation; it may never emit a document.

fdml research "<how does X work>" answers a product question from the index and the spec: a numbered evidence packet, coverage by layer (feature · scenario · code · rule · test), gaps with draft operations, and optionally a model's answer citing packet numbers. Every answer records what it cost.

A feature in vision.fdml

features:
  - id: tool.journal
    title: "The operations journal"
    description: "Typed operations proposed, accepted by a human, overlaid on every load, exported to the file; via add_op, accept_op, export_products"
    realizes: [tool]
    scenarios:
      - id: tool.journal.s1
        title: "An accepted scenario is visible before export"
        given: ["a pending add_scenario operation"]
        when: ["a human accepts it"]
        then: ["every reader sees the scenario", "the file is unchanged until export"]

Root features carry a value block (beneficiary, statement, metric); every feature must reach a value-bearing root through realizes. The language is specified in FDML-1.3-en.md with the 1.4 extensions in fmdl-spec/.

Using it with a coding agent

  • Working notes for agents live in CLAUDE.md: index first, grep second; Edit tool over heredoc patches; dossier at the start of a session. Any agent that reads markdown can follow it.
  • Skills ship in .claude/skills/ (Claude Code skill format, plain markdown, portable to other agents):
    • fdml-nav — navigation: dossier → search → get/outline → impact, grep only after an honest miss, mark after a grep that found what search did not;
    • fdml-cpo — what to build next, from telemetry, failed queries and the gap rather than opinion;
    • fdml-visionary — judge an idea against the vision and the non-negotiables (deterministic core, local-first, spec is the product).
  • Install the navigation skill into another repository: fdml skill --install (or --global); check with fdml skill.
  • Every search is logged. fdml log shows the hit rate and the failed queries; fdml candidates shows the shell work an agent rebuilt by hand three or more times in this repo — the tool that is missing.

Commands

command what it does
index, status build or update the SQLite index; statistics
search, get, outline, impact find, read the smallest range, segment a big function, callers and callees
mark, heal, log teach the index a query; turn failed queries into marks; telemetry
note, dossier, history, candidates project memory; restore point; commits joined to the asks that caused them; repeated shell work
validate, parse, trace the spec: parse, validate, traceability checks
propose, gap reverse flow: candidate features from code; vision vs scan
work the operations journal: add, list, accept, reject, export
evidence `run --runner cargo-test
research a product question answered from the model, with coverage and gaps
serve --v2 the product page
scan-platform, parse-code, link-code, facts scanning and linking an existing codebase; facts from external analysers
generate, migrate, add, list, init legacy: code generation and file-level CRUD, scheduled for removal

fdml <command> --help for flags. Most commands take --json and --path <root>.

What has been measured

Measured on this repository with fresh agents, frozen snapshots, five runs per cell, cost in input-token equivalents.

  • The index cuts shell navigation: 22 grep/read actions became 8 on three tasks, with the same answers.
  • It does not lower an agent's cost on a small, well-named repository: four of five comparisons were statistically indistinguishable, one was 18 % cheaper. A benchmark on a large unfamiliar codebase is the next experiment.
  • Writing the feature draft or the verification plan before the code did not make implementation faster; real defects were found by running the result.
  • Project memory after a context reset is the part agents consistently used.

What it does not do yet

  • The journal cannot edit or remove a scenario.
  • PROVEN means "the linked test passed", not "every then clause was checked".
  • Export rewrites the vision file in machine form.
  • Code generation and migrations are legacy from an earlier direction and will be removed.

Contributing

cargo test --release must pass (five suites). Navigate with the index, not grep — see CLAUDE.md. Design notes: docs/navigator.md, docs/evidence.md, docs/two-flows.md.

License

MIT — see LICENSE.

About

Local-first code navigation index and feature-to-evidence chain for AI coding agents: tree-sitter symbol index, project memory, YAML feature specs, an operations journal and PROVEN/FAILED proof from test runs. Rust CLI.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages