TL;DR: faf-cli's drift check is now a function you import, not a command you
scrape. computeDrift() joins the public API next to scoreFafYaml, findFafFile, and generateProjectHtml. faf drift --json is the CLI mirror. Plus faf export --llms for an llms.txt view.
In Plain English
Old state. faf drift printed a table — is your CLAUDE.md ahead of your project.faf? Any other tool that wanted
the answer had to run the CLI and parse text.
Fix. The comparison moved into a pure function, computeDrift(fafPath), exported from the package. And faf drift --json for scripts and CI.
New state. An editor extension reads your score, tier, and drift
in-process — import { computeDrift } from 'faf-cli'. No subprocess,
no text-scraping.
npm install -g faf-cli@7.11.0 faf drift --jsonTry it without installing: bunx faf-cli@7.11.0 drift --json (or npx --yes faf-cli@7.11.0). Pin the version in
scripts — @latest drifts.
faf-cli is a library now, not only a CLI
faf-cli has quietly exported its engine for a while — scoreFafYaml, findFafFile, generateProjectHtml. The
scoring is a Rust → WASM kernel; you compose it, you never reimplement it. 7.11.0
adds drift to that surface.
import { computeDrift, scoreFafYaml, findFafFile } from 'faf-cli'; const report = computeDrift('/path/to/project.faf');computeDrift(fafPath, dir?) takes an explicit path — it never reads process.cwd(). It compares the modification time of project.faf against the four files your AI actually reads (CLAUDE.md, AGENTS.md, .cursorrules, GEMINI.md) and returns a plain
object: per-file status, raw mtimes, deltas, and the counts.
The extension is live
Update — September 8. The reason for the edition name: FAF — Project Context is on the VS Code Marketplace and Open VSX (Cursor / VSCodium / Windsurf). Score, tier, and drift in the status bar and a sidebar;
the context card rendered in a webview — all of it computeDrift, scoreFafYaml, and generateProjectHtml called in process, no
shell-out.
code --install-extension faf.faf-contextfaf drift --json
The same report, on the command line, self-describing:
{ "faf_version": "3.0", "project": "my-app", "source": "/abs/project.faf", "targets": [ { "file": "CLAUDE.md", "status": "newer", "delta_ms": 12043 }, { "file": "AGENTS.md", "status": "in-sync", "delta_ms": 0 } ], "drifted": 1, "in_sync": 1, "missing": 2 }Raw *_ms numbers — no Date.now() in the payload, so the shape is
stable and the consumer formats its own "5d ago". A newer target means someone
edited the context file and the .faf hasn't caught up; run faf sync. With no project.faf, --json returns { error, hint } and exits 2 — a --json consumer never has to parse a stderr string. Bare faf drift output is unchanged.
faf export --llms
A new export target: faf export --llms writes llms.txt in the llmstxt.org shape, from the
authored six W's in your project.faf. Opt-in, like --grok — not on
bare faf export or --all. A view, not a format.
Also in 7.11.0
faf hooks --install and faf diff --install now wire the canonical faf-cli bin, not the faf alias — so the pre-commit hook and the git
diff driver can't be shadowed by another faf on your PATH.
Try it
Install (global):
npm install -g faf-cli@7.11.0 # short name, same bits: npm install -g faf@7.11.0Try (no install):
bunx faf-cli@7.11.0 auto bunx faf-cli@7.11.0 scoreMore: docs.faf.one/drift · v7.11.0 release · repo.
Technical details
- Version: 7.11.0 (September 7, 2026)
- New export:
computeDrift+DriftReport/DriftTargettypes, fromfaf-cli - CLI:
faf drift --json·faf export --llms - Packages: dual-published —
faf-cliandfaf, same version - Tests: 1402/1402
- Score: ✪ Trophy 100%
Feedback welcome
Questions, nits, suggestions — guide the next version. Tell us what you want to see.
