Fux — a portable agent-aware knowledge engine: rules, memory, narrative, and graph in one frontmatter substrate.
Project description
Fux
Memory tools record what your agent did. Fux records why your code is the way it is — and checks it's still true.
The why behind your code — why this formula, why this invariant, why it was done this way — usually lives in someone's head and dies when they leave. Fux makes it a first-class, version-controlled thing your agent reads before it touches anything, and tells you the moment the code drifts away from what you wrote. $0, deterministic, zero dependencies, no mandatory LLM calls.
Pronounced "fox." · Python ≥ 3.11 · stdlib only · MIT
▶ Demo GIF coming soon.
The story
A story? In a README? I know — stop clutching your config flags. We don't do stories here. We do badges, a wall of CLI options, and a "Contributing" section nobody's opened since 2019, and we call it documentation. But here's the thing: you will not remember my feature list. You'll remember the pipe. So I wrote the pipe. Ninety seconds, it's about a basement, and — spoiler — you're the idiot in it. Read it. — Arpit
You move into an old house. Down in the basement, the previous owner painted one pipe bright red. You have no idea why — so when you renovate, you treat it like any other pipe and reroute it. A week later, the basement floods. That red pipe froze every winter, and the paint was the owner's way of saying leave this one alone. They knew. They just never wrote it down, and then they moved out.
That's how almost all important knowledge works. The reason behind a choice lives in one person's head, and the day they leave, it's gone — so the next person changes it with complete confidence, and something quietly breaks. (Swap "person" for "AI assistant" and it happens ten times faster.)
Fux is the note taped to the red pipe. You write the reason down once, it stays right next to the thing it explains, and whoever comes next — a new owner, a contractor, an AI — reads it before they touch anything. And if someone reroutes the pipe anyway, Fux flips the note over: heads up — this may no longer match what's actually here. The reason can't vanish, and it can't quietly go out of date.
In code, the red pipe is the one line some genius is always about to "clean up":
def day_pnl(holding):
# No, this cannot be one tidy line. Normalize each leg to dollars BEFORE
# summing — percentages double-count during a corporate action.
# Yes, you have 15 years of experience. So did the last principal who
# "simplified" this and took prod down on dividend day. (see: day-pnl)
return sum(to_usd(leg) for leg in holding.legs)
Six months later, a Principal Engineer With Opinions skims that comment, concludes whoever wrote it "didn't really understand the domain," deletes it, and ships the one clean line — right before the next corporate action quietly poisons the numbers. The comment was right. It usually is. (We've all been that engineer.) Fux turns it from a comment a confident person can delete into a rule they can't — checked, and bound to the exact lines it explains.
See it
$ fux why day-pnl
formula · day-pnl · governs backend/app/aggregator.py#L40-58
Rule: Day P&L = current market value − previous close value, per holding,
summed. Dollar-normalize each leg before summing.
Why: Quantity drifts intraday (corporate actions, partial fills); summing
percentages double-counts. Dollars are the only safe common unit.
Edge: New position with no previous close → previous = cost basis, not 0.
⚑ unsealed — aggregator.py changed structure since this rule was sealed.
The logic this rule describes may no longer match. Run `fux why day-pnl --history`.
One entry, authored once, answered back with the rule, the reason, the code it governs, and — the part no doc tool does — a warning that the code moved and the rule might be stale. That last line is the whole product.
Quickstart
pip install fux-engine # the CLI, zero third-party deps
cd your-project
fux init # scaffold .fux/ + agent pointers
fux new formula day-pnl # scaffold a rule; fill Rule: / Why: / Edge cases:
fux build # regenerate INDEX + graph ($0)
fux why day-pnl # explain a rule + the code it governs
Full agent integration (Claude Code / Codex / Copilot skills + hooks): clone and run
./install.shinstead — it wires~/.claude/fux, the skills, and the SessionStart/PostToolUse/Stop hooks.
Complete, example-driven guide: docs/guide.md · full command reference: docs/cli.md.
Explain it like I'm five
Your code is a giant LEGO city. The reasons things are built a certain way — why the bridge is red, why the towers go up before the walls — usually live in one builder's head. When they go home, nobody remembers why.
Fux is a notebook for those reasons. You write each important one down once, and Fux glues a tiny one-line table of contents to the cover, so your helper can flip straight to the right page instead of searching the whole city. It also draws a map of which notes belong to which buildings — and checks that the notes still match the city, telling you when a building changed but its note didn't. And it does all that for free, without phoning anyone for help.
Why it's different
It's not another wiki or memory service. The difference is a set of properties, not features:
- Deterministic. Every maintenance command is shell / AST / parse. Same inputs, same output, every time — your knowledge layer never hallucinates because it never guesses.
- Verifiable.
fux sealbinds a rule to an AST fingerprint of its code;fux checktells you when the structure drifted (not just the mtime). Rules carrycheck:invariants and workedexamples:that actually run. $0and zero-dependency. Stdlib-only Python, no third-party deps, no API key required to read, write, or serve. Portable as a tarball, auditable line by line.- Agent-native. Typed frontmatter, machine-readable output, an MCP server, and prompt hooks — built so an agent can call it and verify the result, not just read prose.
The "so what" chain: deterministic → so your context never hallucinates → so an agent can act on it safely → so you can put the result in front of an auditor. That last clause is the one a memory tool can't say.
The constitution — rules neither you nor your agent can break by accident
Ordinary rules document and warn. A constitutional rule is one a developer or an AI agent cannot break without it being caught and named.
- Debate → ratify. A principle becomes law through
/fux debate— a skill that spawns two sub-agents to argue it freely (blind first passes, anti-sycophancy gates, no assigned sides) and escalates to you as tie-breaker.fux ratifythen makes it tamper-evident: it stamps acontent_seal+ the debate'sdebate_hashand records the rule in a committed.fux/constitution.lock, so any later in-place edit, add, or delete is an always-blockingtamperedfinding. To change a constitutional rule you must supersede it — the amendment article governs its own amendment, and has already amended itself. - Critique before it lands.
fux criticchecks a change against the constitution: a deterministic pass first (money / PII / numbers — decided by acheck:or seal, never sent to an LLM, and they hard-block), then the host agent self-critiques the judgment principles (tone, completeness) with its own tokens. The judgment critic is advisory-first — a suggestion, not a blocker — so it earns trust before it interrupts. - A real wall. Every merge to
mainrequires two checks —fux gate(integrity) andai-review(a separate reviewer identity that refuses when reviewer == author). New branch → PR → both green → merge is the only path, for everyone including the owner. Branch protection lives outside the repo, so a weekly drift audit fails loudly if it ever changes. (details)
Crucially, the debates and critiques spend the host session's tokens — Fux's own code never calls an LLM (a guard test proves it) — and the whole layer is opt-in: tier defaults to standard, so adopting Fux changes nothing until you ratify your first rule.
The bet: once verifiable, governed code-context is normal, shipping an AI change against undocumented, unchecked invariants will look as reckless as deploying without tests.
How it works
You maintain only the source frontmatter. Everything else is derived, lazily, for $0:
Tier 0 agent pointers ........... CLAUDE.md, AGENTS.md, Copilot instructions
Tier 1 .fux/out/INDEX.md ........ ~1 line/rule, read FIRST ← cheap
Tier 2 .fux/rules/<id>.md ....... opened ONLY when relevant ← lazy
Tier 3 .fux/out/{rules,graph}.json machine lookup + browsing
Your agent reads the one-line index first and opens a full rule only when it's relevant, so lookups run ~5–10× cheaper and more correct on every later session — and you don't take that on faith: fux savings prices the win in real dollars from your own file sizes. Three hooks keep it live: SessionStart injects the index, PostToolUse warns when an edited file's rule drifted, Stop validates before the turn ends.
The graph merges your rules with code symbols and call edges across Python (stdlib ast) and JS/TS, Go, Rust (brace-heuristic, or real tree-sitter ASTs via the optional [ast] extra), with community clustering and PageRank centrality for architectural chokepoints. The interactive graph.html "Solar Terminal" viewer desaturates code to graphite while knowledge nodes ignite amber and governs links stream across as glowing threads — so which rule governs which code is impossible to miss.
The full command surface (authoring · verification · governance · runtime)
fux check --fix # validate; repair mechanical drift ($0)
fux why day-pnl --history # how a rule's *why* evolved, via git
fux refs src/aggregator.py # which rules govern this file
fux recall "how is day P&L computed" --hybrid # BM25F; RRF-fuse lexical+semantic+graph
fux seal --all # bind rules to an AST fingerprint of their code
fux debate "<rule>" (skill) # two-agent free debate → you ratify the result
fux ratify <id> --by Arpit # ratify a constitutional rule (tamper-evident)
fux constitution # status: what's law, what it governs, debates, violations
fux critic "<change>" # critique a change vs principles before it lands ($0)
fux coverage # % of important files with a governing rule
fux verify --fuzz # run invariant `check:`; boundary-fuzz div-by-zero
fux mine # surface candidate rules latent in the code (drafts)
fux savings "how is day P&L computed" # measured token + dollar cost win
fux lint # rule quality: missing why / code_refs / edges
fux stats # knowledge-health dashboard + score
fux gate --install # wire a git pre-commit enforcement hook
fux mcp # serve the substrate to agents over MCP (stdio)
fux serve # local dashboard over the generated views
fux import docs/ # migrate existing markdown → narrative entries
fux query / path / explain # graph traversal: "how does X relate to Y"
Layered rules — maintain once, inherit everywhere
effective ruleset = ~/.claude/fux/global/ (cross-project best practices)
⊕ ~/.claude/fux/packs/* (opt-in shareable domain packs)
⊕ ./.fux/rules/ (this project's domain rules)
project overrides pack overrides global, and fux check flags conflicts instead of silently shadowing. Packs are optional — a single project can keep everything version-controlled in its own .fux/, beside the code it governs.
The $0 guarantee
Every maintenance command is shell / AST / parse — no LLM calls, ever. The only paths that touch a model are the authoring skills (debate, plan, adr, and the judgment critic), and they ride the session you're already in — no background spend. The headless AI critic ships behind an opt-in [critic] extra; the default install stays model-free.
Honest limits. Fux doesn't write your rules for you — fux mine drafts candidates, but the why is yours. The constitution governs where trust lives (money, PII, audit), not every line — making everything constitutional would crush your velocity, and the design says so. And branch protection lives in GitHub, so Fux can watch it but can't seal it; that one link is honest about being outside its reach.
What's new
- v0.6.0 — the wall is real. Merging to
mainrequiresfux gate+ai-review(separate reviewer, refuses when reviewer == author).fux ratifyopens its own gated PR; a weekly drift audit catches protection changes. (details) - v0.5.0 — advisory-first critic + first amendment. The judgment critic suggests rather than blocks;
fux constitutiongains debates + violations by severity; the amendment article amended itself by supersession. - v0.4.0 — the constitutional-app engine.
tier,/fux debate,fux ratify,.fux/constitution.lock,fux critic, and the deterministic/judgment split. Opt-in and$0.
The name
Named after Johann Joseph Fux, author of Gradus ad Parnassum (1725) — the counterpoint treatise every composer learned the rules from. A tool that codifies and enforces rules, named after the man who wrote the rulebook. The name is deliberate (yes, I kept it). Sits beside wagner, bach, orff.
Fux unifies and replaces three things a project usually runs separately — the structural graph, cross-session memory, and the narrative docs — and adds the business-rules and governance layer none of them held. See docs/fux-plan.md.
If the red-pipe problem is real in your codebase, ★ star the repo and try Fux on one rule — pip install fux-engine.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fux_engine-0.6.1.tar.gz.
File metadata
- Download URL: fux_engine-0.6.1.tar.gz
- Upload date:
- Size: 215.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d031fbf917527298da84c9d1b8c551b66f6fe25c98b886bfb49dcb24e13d2302
|
|
| MD5 |
7c6eccc5ed6556affa490b03dc2fef29
|
|
| BLAKE2b-256 |
c2db70d1a1c7ead6213b11c87f786e497e2f3a68c10439f9659be4bdda34c2ba
|
Provenance
The following attestation bundles were made for fux_engine-0.6.1.tar.gz:
Publisher:
publish.yml on arpitarya/fux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fux_engine-0.6.1.tar.gz -
Subject digest:
d031fbf917527298da84c9d1b8c551b66f6fe25c98b886bfb49dcb24e13d2302 - Sigstore transparency entry: 1863134463
- Sigstore integration time:
-
Permalink:
arpitarya/fux@77d46bb535a1c0b99888b93371f1ab94b7100198 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/arpitarya
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@77d46bb535a1c0b99888b93371f1ab94b7100198 -
Trigger Event:
release
-
Statement type:
File details
Details for the file fux_engine-0.6.1-py3-none-any.whl.
File metadata
- Download URL: fux_engine-0.6.1-py3-none-any.whl
- Upload date:
- Size: 208.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1f6492c20def53c1e40a9510f11f0895025fa43c0704a338026e7ed83ee8bdf
|
|
| MD5 |
59c105ba92a2026d00e83f65eb0e0e65
|
|
| BLAKE2b-256 |
b286a3a0238ae34f29a31b73ab8fdb32037eefcd33d9e433f098f68846929703
|
Provenance
The following attestation bundles were made for fux_engine-0.6.1-py3-none-any.whl:
Publisher:
publish.yml on arpitarya/fux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fux_engine-0.6.1-py3-none-any.whl -
Subject digest:
d1f6492c20def53c1e40a9510f11f0895025fa43c0704a338026e7ed83ee8bdf - Sigstore transparency entry: 1863134548
- Sigstore integration time:
-
Permalink:
arpitarya/fux@77d46bb535a1c0b99888b93371f1ab94b7100198 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/arpitarya
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@77d46bb535a1c0b99888b93371f1ab94b7100198 -
Trigger Event:
release
-
Statement type: