@albinocrabs/feynman
v1.4.0
Published
Claude Code, Codex, and OpenCode plugin that auto-injects ASCII diagram rules via SessionStart hook (startup, resume, compact, clear)
Maintainers
Readme
A Claude Code, Codex, and OpenCode plugin that automatically injects ASCII diagram rules at session start.
npx -y @albinocrabs/feynman@latest install --target all
npx -y @albinocrabs/feynman@latest doctor --target opencodeWhy feynman
Structured information explained in prose forces you to rebuild the structure in your head before you can reason about it. feynman intercepts every Claude Code, Codex, or OpenCode prompt and injects rules that turn flows into arrows, hierarchies into trees, comparisons into columns, and status into the smallest fitting visual — dot-leader by default, markdown table for larger sets, frame only when lighter forms lose information. The structure is visible before you have to think about it.
Conceptually, feynman is inspired by prompt-compression ideas from the Caveman agent style: smaller prompts, clearer intent, and explicit diagram-first thinking.
How feynman survives context compaction
Claude Code's SessionStart hook fires not only at startup and resume, but also
after /compact and /clear (matchers compact and clear). feynman
registers all four matchers, so the diagram rules are re-injected automatically
whenever the context window is reset — no per-turn overhead, no noise in every
user message.
Governance docs
AGENTS.md— project execution contract for Codex-aware tooling.CLAUDE.md— canonical project memory, stack, and architecture constraints.- Global instructions are loaded from user-level runtime configuration before repo-specific overrides.
Before / After
Without feynman
"The deployment pipeline has three stages: first the code is built, then tests run, then it deploys to prod."
With feynman
[Build] --> [Test] --> [Deploy]Without feynman
"Option A is fast but stateless. Option B is slower but persists data. Option C gives you both at higher cost."
With feynman
Option A | Option B | Option C
---------------|---------------|----------
fast startup | slow startup | medium
stateless | persistent | persistent
free | free | $$$Without feynman
"Fix the auth bug first since it's a security issue, then the memory leak, then the slow query."
With feynman
▲ high
auth bug (security)
memory leak
▼ low
slow queryWithout feynman
"The auth service talks to Redis for rate limiting and Postgres for user data."
With feynman
[Auth Service]
├── [Redis] rate limiter
└── [Postgres] user dataInstall
Install to Codex by default (when --target is omitted):
npx @albinocrabs/feynman installCodex via npx:
npx @albinocrabs/feynman install --target codexOpenCode via npx:
npx @albinocrabs/feynman install --target opencodeOpenCode has no stdout hook API, so feynman injects rules by writing
~/.config/opencode/.feynman/rules.md and registering its absolute path in the
instructions[] array of ~/.config/opencode/opencode.json. OpenCode reads
instructions entries as additive system context at startup — the same mechanism
as a custom system prompt file. Run /clear inside an OpenCode session after
changing intensity so the new rules take effect.
All three clients:
npx @albinocrabs/feynman install --target allThe install command is idempotent: running it again updates the existing
feynman hook instead of adding duplicates. For OpenCode, a second install is a
no-op if the path is already in instructions[].
Claude Code via bash one-liner:
git clone https://github.com/apolenkov/feynman && bash feynman/install.shRestart Claude Code, Codex, or OpenCode after install so a fresh session can prime the rules.
Uninstall: npx @albinocrabs/feynman uninstall --target claude|codex|opencode|both|all|*
Plugin manifests: this repo also ships .claude-plugin/plugin.json,
hooks/hooks.json, .codex-plugin/plugin.json, and hooks.json for direct
client integrations. The npx installer remains the production fallback because
both clients still support direct user hook registration.
Add to ~/.claude/settings.json — use the absolute path, not ~/
(bug #8810):
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|compact|clear",
"hooks": [
{
"type": "command",
"command": "node \"/absolute/path/to/feynman/hooks/feynman-session-start.js\"",
"timeout": 5
}
]
}
]
}
}For Codex, add the same shape to ~/.codex/hooks.json and set
FEYNMAN_HOME so state lives under ~/.codex:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|compact|clear",
"hooks": [
{
"type": "command",
"command": "FEYNMAN_HOME=\"$HOME/.codex\" node \"/absolute/path/to/feynman/hooks/feynman-session-start.js\"",
"timeout": 5
}
]
}
]
}
}After install, feynman starts in full mode by default. Disable or change it
explicitly with /feynman off, /feynman lite, /feynman full, or
/feynman ultra.
IDE Support
feynman also installs into project-local rules folders for Cline, Cursor, and
Windsurf. These targets write a single rules file in the current working
directory — no global hook, no settings mutation. The rules file is derived
from the full intensity block of rules/feynman-activate.md.
| Target | Output path (relative to CWD) | Frontmatter |
|--------|-------------------------------|-------------|
| claude | ~/.claude/settings.json (hook) | — |
| codex | ~/.codex/hooks.json (hook) | — |
| cline | .clinerules/feynman-rules.md | none |
| cursor | .cursor/rules/feynman.mdc | alwaysApply: true, globs: "**" |
| windsurf | .windsurf/rules/feynman.md | none |
Install:
cd your-project
npx @albinocrabs/feynman install --target cline
npx @albinocrabs/feynman install --target cursor
npx @albinocrabs/feynman install --target windsurfDoctor (verify):
npx @albinocrabs/feynman doctor --target cline
npx @albinocrabs/feynman doctor --target cursor
npx @albinocrabs/feynman doctor --target windsurfdoctor exits 0 when the rules file is present (and, for Cursor, when
the YAML frontmatter has alwaysApply: true). Otherwise it exits 1 with
a [FAIL] reason.
To regenerate after upstream changes — just re-run install. The command
is idempotent: it overwrites the rules file in place. No uninstall path
is provided for IDE targets (delete the directory if you need to undo).
Verify the install
Run doctor after installing or after manually editing hooks:
npx @albinocrabs/feynman doctor --target codex
npx @albinocrabs/feynman doctor --target claude
npx @albinocrabs/feynman doctor --target allA healthy target reports the hook event and hook script file as OK:
[OK] hook registered (feynman-session-start.js in SessionStart)
[OK] session hook script file exists and is readable
Status: OKFor Codex, runtime state should live under ~/.codex:
cat ~/.codex/.feynman/state.json
test -f ~/.codex/.feynman-activeFor Claude Code, use ~/.claude instead of ~/.codex. doctor fails if a
registered hook command cannot be parsed to a real hook script, which catches
stale or broken manual installs.
Intensity Levels
| Level | What draws | Use when | |-------|-----------|----------| | lite | Flows + trees only | Minimal, subtle | | full | All 5 diagram types (default) | Normal use | | ultra | Force diagram even for short answers | Maximum visual structure |
Toggle via /feynman:
/feynman lite — flows and trees only
/feynman full — all diagram types
/feynman ultra — force diagrams always
/feynman off — disable
/feynman on — re-enable
/feynman status — show current state (intensity + output_style)Output-Style Presets
Orthogonal axis to intensity. Intensity controls how much instruction the model sees (rules-file size). Output style controls how heavy the model's visuals can be (runtime hint).
| Preset | Visuals allowed | Token cost vs. full | Use when | |--------|-----------------|---------------------|----------| | short | Inline glyphs + dot-leader only | ~−60% on status-heavy replies | Mobile, dense chat, voice input | | middle | + trees + markdown tables for ≥6 status items | ~−25% | Balanced default | | full | + side-by-side columns + ASCII art; frame only when lighter form loses information | baseline (current default) | Spec docs, retros, design |
Toggle:
/feynman style short — minimal visuals
/feynman style middle — balanced
/feynman style full — all visuals (default)Implementation note: output-style is enforced via a one-line runtime
suffix in the prompt-submit hook — it does NOT modify rules/feynman-activate.md,
so the 4480-byte budget stays intact.
Lint
feynman includes a linter for ASCII diagrams. It catches structural errors before they reach readers: unclosed boxes, wrong tree characters, mixed arrow styles, inconsistent column counts, mixed-script words, and more.
npx @albinocrabs/feynman lint response.md # detect only (exit 1 on error)
npx @albinocrabs/feynman lint --fix response.md # detect + repair frames in place
npx @albinocrabs/feynman lint --explain response.md # annotate frames with token cost--fix repairs four classes of ASCII misalignment automatically. All fixes
are conservative-first (≥2 consecutive lines required, ±3 column guard) and
idempotent — a second pass on an already-fixed file is a no-op.
Autofix capabilities (--fix):
| Pattern | What it fixes | Trigger | |---------|--------------|---------| | D — Frame alignment | Right edge of frame blocks, including titled tops | Any misaligned frame | | A — Arrow column | Arrow symbols in a run of ≥2 lines | Arrows within ±3 cols of each other | | B — Junction fan | Junction connectors in ≥2 adjacent lines | Connectors within ±3 cols | | C — Separator length | Pure-dash separator lines across the document | ≥2 separators of unequal length | | L11 — Dot-leader | Status frames with ≤5 inner lines and state markers | L11-eligible frames | | L15 — Homogeneous plain | k:v, bullet, or prose frames with no structural chars | All inner lines same type, ≥2 lines |
L15 converts a k:v frame to plain key: value lines, a bullet frame to - item
lines, and a prose frame to plain paragraphs. Titled tops (┌─ Config ─┐)
become a plain heading line. Complex frames (nested trees, arrows, embedded tables)
and status frames are left unchanged.
Frame alignment: ANSI escapes, combining marks, zero-width joiners are stripped, CJK wide chars count as 2 cols. Titled tops preserve the title text when rebuilding the border. Indentation preserved on all patterns.
--explain is read-only — it emits a per-frame breakdown showing
framing: ~N chars (border: B, padding: P, content: C),
equivalent dot-leader: ~M chars, and the saving. Use it to understand
why L11 or L12 fired and how many chars a lighter visual would save.
See docs/lint-rules.md for the full L01-L15 reference.
Quick hard-disable / re-enable (testing and emergency)
For temporary global disable in Codex (for smoke tests or troubleshooting), use:
touch ~/.codex/.feynman-disable-global # hard OFF
rm ~/.codex/.feynman-disable-global # hard ONThis bypasses ~/.codex/hooks.json hook execution entirely.
Regular /feynman off and /feynman on continue to use normal profile state
files (~/.codex/.feynman-active, ~/.codex/.feynman/state.json).
Security notes
feynman hooks are local prompt-context hooks. They do not require network access, do not read repository files, and do not read credentials. The active mode is stored only in the client-local state path:
~/.claude/.feynman/state.json
~/.codex/.feynman/state.jsonThe hook runtime treats invalid state as disabled for that turn, removes the activation flag, and stays silent. That prevents a corrupted state file from silently forcing diagram rules into future prompts.
uninstall removes only feynman hook commands and preserves unrelated hooks in
the same hook group. doctor validates that registered commands point to real
hook scripts, so broken manual commands are visible before a session depends on
them.
CLI examples
Quickly discover and view repository prompt templates:
feynman examples
feynman examples --name feature-planning
feynman examples --name incident-response
feynman examples --randomExport a ready-to-distribute local package (examples, rules, plugins, and skill):
feynman bootstrap
feynman bootstrap --out ./feynman-package
feynman bootstrap --out ./feynman-package --forceThis is useful for disconnected/air-gapped installs where you want to copy one
folder with all Feynman assets instead of depending on npm.
Slash command aliases (inside Claude/Codex):
/feynman on | off
/feynman start | stop
/feynman lite | full | ultra
/feynman statusExamples
Run a concrete example in the needed style:
feynman examples --name <example-name>Tip: all examples are ready-to-run templates in
examples/*.md, can be copied into prompts or docs, and rendered as a compact ASCII layout withfeynman examples --name ....
[Flow] [Architecture] [API] [Decisions]
| | | |
v v v v
[Action] [System] [Lifecycle] [Reasoning]
↓ ↓ ↓ ↓
[Outcome] [Design] [Change] [Choice]Visual example gallery
Flow and actioning
Incident-ready action playbooks
- Activity sequence — incident action plans with rollback gates
[Incident] --> [Triage] --> [Contain] --> [Mitigate] --> [Review] | no | v | [Rollback] <----+ - Incident response — triage and containment sequence
[Detect] --> [Classify] --> [Isolate] --> [Communicate] | +--> [Recover] - Bug isolation — stateful diagnostic flow with priorities
▲ high high-likelihood ▼ low narrow scope documentation - Release readiness — staged launch gates and recovery triggers
[Build] --> [QA] --> [Dark launch] --> [General] | no | yes v v [Rollback] [Monitor]
Architecture and design
- Architecture review — auth system decomposition
Auth ├── Service │ ├── Redis rate limits │ └── Postgres users └── Observability └── Events - C4 platform design — context → container → component
[User] --> [Web] --> [API] --> [DB] - Context splitting — decomposing complex initiatives
Initiative ├── Domain A ├── Domain B └── Domain C - Database schema — entity model as structured tree
Report ├── Metadata ├── Sections └── History
API and migration
- API flow — request lifecycle with branch diagnostics
[Client] --> [Auth] --> [Service] --> [DB] | yes | +-->[Cache] ---+ - Deploy pipeline — CI/CD action chain
[Source] --> [Build] --> [Test] --> [Canary] --> [Scale] | | v +--> [Rollback] - Service migration — cutover with risk controls
[Old service] --> [Dual write] --> [Read compare] --> [Cut over] | mismatch v [Stop migration]
Decisions and methods
- Feature planning — decision matrix + phased rollout
[Need] --> [Plan] --> [Run experiment] --> [Scale] | | +--> [Kill-switch] - Algorithm walkthrough — rate-limiter logic as explainable sequence
[Need decision?] --> [Compute score] --> [Allow / Deny] - Code review — issue prioritization and evidence matrix
▲ must-fix [security] ▲ medium [performance] ▼ low [docs]
One-command pack test
feynman examples --name activity-sequence && \
feynman examples --name incident-response && \
feynman examples --name c4-platform-diagrammingVisual gallery (before → after)
If you want to quickly see how diagram-first responses evolve, this is the core pattern:
Without feynman:
We need to choose between shipping fast with a managed API, keeping control in-house, or a hybrid path while managing risk and cost.
With feynman:
[Is SLA strict?] --> [Yes] --> [Prefer managed service]
| | |
| v v
| [Contract + vendor risk] --> [Is rollback cheap?]
| |
v +--> [Yes] --> [Adopt + guardrails]
[Can we build fast?] +--> [No] --> [Hybrid path]
|
no ------ +------- yes
| |
v v
[Build in house] [Run controlled managed pilot]Same brief question, different clarity level.
criterion | build in-house | managed API | hybrid
---------------|----------------|-------------|----------------
launch speed | slow | fast | medium
vendor lock-in | low | high | medium
compliance | high control | partner SLA | custom controls
cost | low initial | medium | medium-highUse this gallery style if you want feynman examples to look “production-clean”
from day one.
How it works
The SessionStart hook injects diagram rules at the start of each session and
automatically re-injects them after /compact and /clear (matchers
startup|resume|compact|clear). The hook reads the target-local state file
(~/.claude/.feynman/state.json or ~/.codex/.feynman/state.json), extracts
the rules for the active intensity level, and injects them into model context.
[your prompt]
+
[feynman rules] injected by hook
│
▼
[Claude Code]
or
[Codex]
│
▼
[structured response with ASCII diagrams]Token budget and output size
→ deeper: docs/token-economy-planning.md
feynman always adds some input context when it is enabled, because the active diagram rules are injected into the client prompt context. It does not add visible output by itself; output changes only when the assistant uses the rules.
Current rule payload sizes are approximately:
| Mode | Bytes | Approx tokens | Use when |
| ---- | ----- | ------------- | -------- |
| lite | 1307 | 317 | minimal flows and trees |
| full | 2180 | 532 | default diagram coverage |
| ultra | 1390 | 337 | force diagrams more often |
The token count is a rough chars / 4 estimate, not a billing counter. The
actual number depends on the runtime tokenizer and surrounding hook envelope.
The plugin can reduce output size when a diagram replaces repeated prose,
especially for flows, status summaries, hierarchies, and comparisons. It can
increase output for short answers where a diagram would be unnecessary, so the
rules explicitly suppress diagrams for one- or two-sentence direct answers.
Use /feynman lite for lower overhead or /feynman off when token budget is
more important than visual structure.
Prompt caching
Anthropic's prompt caching works on a prefix-match, byte-exact basis: the leading portion of a request must be byte-for-byte identical across turns before the API will reuse a cached entry. There is also a minimum token threshold — roughly 1024 tokens for Sonnet 4/4.5, 2048 for Sonnet 4.6, and 4096 for Opus 4.x / Haiku 4.5 (per Anthropic docs, 2026). A cached prefix also expires after about 5 minutes of inactivity.
The feynman rule block is 317–532 tokens depending on intensity — below every threshold. It cannot form its own cache entry.
What feynman does control, and gets right: the injected text is fully static. No timestamps, no session IDs, no per-turn values. That means the block is a stable byte sequence, so it does not break any larger cache entry it sits inside.
What feynman does not control: whether the surrounding context — system prompt, tool definitions, and other harness-injected content — is large enough and stable enough to cross a caching threshold. That is the client harness's concern, not the plugin's.
Net: feynman's token economics come from two things it directly controls —
injecting rules once at SessionStart (not per-turn) and encouraging concise
diagram output instead of verbose prose. Prompt caching, if it fires at all, is
a harness-level bonus outside the plugin's scope.
Release process
Every push runs tests on Node 18 and 20 across Ubuntu and macOS. The release
lane also lints public docs, smoke-tests the packed npm tarball, builds a
dist/*.tgz artifact, and can publish to npm from a GitHub Release when
NPM_TOKEN is configured. If the token is absent and the package version is
already published, the workflow updates release notes and exits successfully;
for a new publish, it fails with a clear message so token-less publication
cannot silently pass.
npm run ci
npm run changelog
npm run buildGitHub release path
- Tag and release from GitHub (or run workflow_dispatch with
dry_run=false). - Ensure repository secret
NPM_TOKENis set (only needed for first publish of a new version). - Keep version/tag aligned: release tag must equal
package.jsonwithvprefix (enforced by workflow). - Create release notes generated from
CHANGELOG.mdand verify package availability after publish. - Mark PRs for auto-merge with labels
auto-mergeandstatus:readyand keep required review approvals in place.
Set or rotate NPM_TOKEN with:
gh secret set NPM_TOKEN -r apolenkov/feynmanState is stored at ~/.claude/.feynman/state.json. First run bootstraps
automatically. See docs/architecture.md for internals.
Contributing
See CONTRIBUTING.md for setup, PR checklist, and rules-authoring guidelines.
License
MIT
