Quickstart
Five minutes, ending in a real finding on a file you write yourself, not a canned demo.
1. Clone and build
chaff is pre-release and not on npm yet, so this step builds the workspace-local CLI instead of installing a package.
git clone https://github.com/jamessuuu/chaff
cd chaff
pnpm install
pnpm --filter chaff build2. Write a small, deliberately imperfect CLAUDE.md
In a scratch directory (not this repo, anywhere is fine), create two files: a CLAUDE.md with one import that points at nothing and one version number in prose, plus the one doc it does import.
mkdir chaff-quickstart && cd chaff-quickstart
mkdir docs
cat > CLAUDE.md <<'EOF'
# Project notes
See @docs/style.md for house style.
See @docs/missing.md for the deploy checklist.
Deployed on build 1.4.2 last night.
EOF
cat > docs/style.md <<'EOF'
Use imperative sentences.
EOFdocs/missing.md is never created. That is the point.
3. Discover a config
node /path/to/chaff/packages/chaff/dist/cli/main.js initReal output from this exact scenario:
chaff.config.json written · 1 discovered:
CLAUDE.mdchaff init writes chaff.config.json by discovery. It found one entry point (this directory’s CLAUDE.md) and declared it as the session set, harness claude-code, gate enforced.
4. Analyze
node /path/to/chaff/packages/chaff/dist/cli/main.js analyze --today 2026-08-09Real output. Nothing here is invented:
chaff · set "session" · o200k_base
RESIDENT 41 ref tok (o200k_base) · 2 files
CLAUDE.md 41 (@imports 4)
CHAFF 5 / 41 ref tok (o200k_base) = 12.2% · enforced findings only, spans deduped
UNVERIFIED 5 ref tok (o200k_base) flagged by heuristics, excluded from the score above
FINDINGS (2)
import.broken-target [enforced · structural · high] resident CLAUDE.md:4:5
@docs/missing.md: import target not found: docs/missing.md
stale.version-pin [heuristic · unmeasured · low] resident CLAUDE.md:6:19
pinned version "1.4.2" in prose: build/version pins go stale silently; state the behavior or
move the pin into tool-owned config
exit code: 1Exit code 1 because the default gate (--fail-on enforced) blocks on the one enforced finding: import.broken-target. The version-pin finding is tier heuristic, so it is reported and excluded from the chaff% score (the UNVERIFIED line), but it does not fail the build by default.
5. Read the finding, offline
node /path/to/chaff/packages/chaff/dist/cli/main.js explain import.broken-targetimport.broken-target · enforced · structural · high
CLAIM
An @-import names a target file that does not exist, so content the author
expects to be resident never loads.
RATIONALE
Claude Code inlines @path/to/import references (relative and absolute) at
launch, skipping code spans and fenced code blocks
(code.claude.com/docs/en/memory). A missing target fails silently from the
author's point of view.
FIX
Fix the path, or remove the import if the target is gone for good
(mechanical: remove the dead import line).
STATUS
structural: a deterministic fact about the artifact that asserts nothing
about behavior, so it needs no eval (SPEC §6).Fix it either way and re-run analyze: delete the @docs/missing.md line, or write the file. Either fix drops the finding count to one (the heuristic, non-blocking version pin) and exits 0.
Next
Concepts explains what RESIDENT and the chaff% line actually mean. Rule tiers explains why one finding blocked the build and the other did not. Or skip straight to /analyze to try this in a browser tab instead of a terminal.