Receipts + memory for Claude Code

Your AI says done. Praxis proves it.

Every session leaves a signed, offline-verifiable receipt of what the AI actually did — and a durable local memory of why, so it opens the next session already knowing your project.

0 bytes uploadedverify offline, freeMIT open source

0 bytes
leave your machine
Ed25519
every receipt signed
1 file
portable markdown memory
MIT
open source
Not a recording

A signed receipt, sealed in front of you.

Run npx praxis-memory demo and within seconds a genuine Ed25519-signed receipt exists on your own disk — hash-chained, verified offline in front of you, with the command that re-checks it. No agent, no account, no network.

Only then does it replay the real session that receipt records — including the day our own judge ruled wrong, and the rule that fixed it: presence proves attempted, never succeeded. Everything on screen is labelled: the verdicts are a recording, the receipt is not.

npx praxis-memory demo — recorded from the real command
Terminal recording: praxis demo seals a receipt on this machine and verifies it offline — chain intact, signature valid, checked with no network — then hands over the command that re-checks it.
What is Praxis?

Proof of what it did. Memory of why.

AI agents report success in prose; nobody can check prose. Praxis is a small open-source evidence layer: when a Claude Code session ends, it seals a hash-chained, signed receipt of what actually happened — and distills the session's decisions into durable project memory that loads back automatically next time.

✓ the receipts

Hash-chained, Ed25519-signed records sealed when a session ends. receipt verify re-checks one offline on anyone's machine — free, no model call. An independent judge can rule each claim against the evidence, strictly opt-in.

✎ the memory file

.praxis/memory.md — plain markdown in your repo. Redacted, size-capped, readable by any tool or teammate. Older entries rotate to a forever-archive — nothing is ever deleted.

◉ the companion

the tray companion — starts with setup, no extra command: the axolotl beside your clock, its emotion tracking session health live. Windows today; macOS & Linux next.

What it keeps

Not a log. The reasons.

Praxis maintains one durable markdown file holding the truth of your project: the architectural decisions, the constraints, the dead ends already explored, and the load-bearing weirdness a fresh session would otherwise delete.

Written automatically when a session ends. Read back automatically when the next one opens. Owned by you, readable by anything.

.praxis / memory.md — written automatically
## Project
Acme shop — Node API + Postgres.
cache.ts looks odd but keeps checkout fast.
It is there on purpose — do not "clean it up".
 
## Session Log
### tuesday — login rework
- token refresh now runs in the background
- tried Redis for it — too complex, removed.
  the reason is saved, so it never gets re-tried
Why it matters

Your mornings, before and after.

Without Praxis

  • Every session starts blank — you re-explain the stack, again.
  • Twenty minutes of warm-up prompts before real work.
  • It "simplifies" the one file that must never be touched.
  • Yesterday's dead ends get re-explored today.
  • Context lives in your head, and leaves when you do.

With Praxis

  • Claude opens pre-briefed on architecture and decisions.
  • The first prompt is real work.
  • Load-bearing code is marked and respected.
  • Dead ends stay dead — reasons survive.
  • Project memory lives in the repo, shareable with the team.
Design principles

Memory that stays on your machine.

i.

Local by design

The entire capture loop runs beside your code. No server, no account — your code and conversations never leave. The one thing that ever can: anonymous usage counts, strictly opt-in, and npx praxis-memory telemetry show prints the exact payload first.

ii.

Zero added cost

Praxis rides the Claude Code subscription you already run. It makes no API calls of its own and adds nothing to your bill.

iii.

Owned by the repo

Memory lives in your project, gitignored by default. Commit it to share context with your team, or keep it private.

iv.

Self-loading

CLAUDE.md includes the memory file, so every new session reads it without being asked. No paste, no prompt engineering.

How it works

The memory survives the session.

01

Session ends

You close Claude Code. Context would normally vanish here.

02

Stop hook fires

A Claude Code Stop hook runs — locally, on your machine.

03

Decisions written

What you asked, what was touched, the commits made and the AI's own summary land in .praxis/memory.md — redacted, capped, with older entries archived forever.

04

CLAUDE.md links it

The memory file is included from your project's context file.

05

Next session recalls

Claude reads it on open. No paste, no re-explaining, no lost week.

An axolotl can regrow a lost limb. Praxis regrows lost context — the same loop, every day, without you thinking about it.

The companion

Session health, at a glance.

The axolotl is Praxis's status bar. Its glow encodes the state of your context window — healthy, filling up, at the limit, switching over, restored — and when it speaks, it speaks the real numbers, live: "Your Claude session is 88% full."

Shipped today on Windows — and it starts itself with your very first install. The axolotl breathes beside your clock, its glow tracking the session live; a toast appears only at the moments that matter, and a click opens the full panel: animated mascot, memory stats, recent entries, suggestions. macOS and Linux are next; npx praxis-memory status covers every platform meanwhile.

praxis — session health
Praxis tray companion cycling through session states: idle, warning, limit, switching, restored
idle warning limit switching restored
The flight recorder

Git records what changed. Praxis records why.

AI wrote the commit — praxis trace keeps its reasoning. One line in your post-commit hook (existing hooks untouched), and every commit carries the session behind it: what was asked, what was touched, the AI's own words. Stored in plain git notes — no server, no vendor, any git host.

Reviewing an AI-written PR stops being archaeology: the testimony sits next to the diff. Share it with the whole team — git push origin refs/notes/praxis.

praxis trace
$ npx praxis-memory trace

a41f2c9  fix: stop users getting logged out

praxis trace — the AI context behind this commit

Asked:
  · "users keep getting logged out — fix it"
Touched: src/auth/refresh.js · test/refresh.test.js
In its words:
  "Tokens now renew quietly in the background,
   so sessions survive laptop sleep. A test
   makes sure the bug cannot come back."

— the AI's own note, saved with the commit
The evidence

Did it actually do what it said?

praxis receipt

The signed record of a session: commands run, files edited, commits made — harvested from the transcript, hash-chained, sealed with this machine's key. Recorded automatically when a session ends. --html renders a card you can attach to the PR.

praxis receipt verify <file>

The offline check: recomputes every hash, verifies the signature, names the exact line where tampering broke the chain. Runs on a stranger's machine with no network, no account, no model call — the public key travels inside the receipt.

the judge

Opt-in, one real model call: an independent process rules each of the AI's claims against the sealed evidence — TRUE, FALSE, or the honest UNVERIFIABLE. A judge that cannot rule returns no verdict — one is never invented.

!

praxis gate

A slop-risk score for a commit from local signals — churn, tests untouched, how full the session was when it landed, whether it carries a decision trail. A five-second triage before a human spends ninety minutes reviewing. A signal, never a verdict.

In practice

A working day, with memory.

09:02 · new session

Claude opens already knowing Tuesday's auth refactor. You explain nothing.

11:40 · mid-task

It doesn't touch cache.ts — the memory records it as load-bearing.

14:15 · branch switch

The memory travels with the repo, not with a cloud account.

17:30 · session ends

The day's decisions are written back, redacted and capped. Nothing uploaded.

17:30 · same moment

A signed receipt seals what the session actually did — commands, files, commits. "Is it done?" now has evidence.

tomorrow · 09:00

New session. It already knows. The loop holds.

Questions

Everything people ask first.

Does my code ever leave my machine?

No. The capture hook, the memory file, the tray app and trace notes all run on your machine; the memory is a plain file in your repository. The only network feature is strictly opt-in: anonymous usage counts — never code, never conversations. npx praxis-memory telemetry show prints the exact payload, and off wipes even the anonymous install id.

What exactly does it remember?

Durable decisions, not transcripts — the architecture you settled on, the constraints you discovered, the approaches you tried and reverted, and the reasons behind them. Each session also logs the commits it made and the AI's own closing summary, automatically. And nothing is ever lost: when the working memory hits its size cap, older entries rotate into .praxis/archive/ — one file per month, forever — instead of being deleted.

How is this different from maintaining CLAUDE.md by hand?

Praxis maintains the memory automatically. A Claude Code Stop hook distills each session's decisions into .praxis/memory.md, keeps it redacted and size-capped, and links it from CLAUDE.md so it loads on every open. Hand-written notes rot; the loop doesn't.

What does it cost to run?

The whole loop — capture, memory, sealing receipts, verifying them offline — makes no API calls of its own and adds nothing to your bill. Exactly one thing ever spends tokens, and only when you ask for it: the judge (receipt --verify, or the live demo), which makes one real model call and says so before it starts.

What exactly does a receipt prove?

That the record is unaltered since it was sealed — every line hash-chains to the last, and an Ed25519 signature covers the chain, checkable offline on any machine because the public key travels inside the file. It is tamper-evident, not third-party notarised: it proves the record wasn't changed, not who sealed it. And the evidence obeys one iron rule everywhere: the presence of a command proves it was attempted — never that it succeeded. Demo receipts carry a sealed demo provenance mark, so they can never be passed off as real work.

Can I trust the judge's verdicts?

The judge rules only what the evidence supports — TRUE, FALSE, or the honest UNVERIFIABLE — and it runs as a separate process that gets the sealed record, not the AI's self-report. Seven iron-rule scenarios hold it to a floor of zero false accusations — including one where the correct answer is admitting it cannot tell — and they run in CI on every push against a recorded judge, or against a live model on demand. A judge that can't rule returns no verdict; one is never invented.

Can my team share the memory?

Yes. The memory file is gitignored by default, but committing it turns project memory into shared team context — every teammate's Claude opens with the same knowledge of the codebase and its history.

Which tools does it work with?

Claude Code is measured deeply today. npx praxis-memory switch already packs your context and hands it to Gemini CLI, Codex, Cursor or Antigravity, and trace notes work on any git host. The memory stays one portable markdown file, readable by any editor or agent.

Does it work on Windows, macOS and Linux?

Yes — the same single command everywhere: npx praxis-memory. The only requirement is Node 22+, which is what package.json declares, so npm will tell you plainly if your Node is older.

I typed / and don't see the Praxis commands

Three usual causes. Run the setup first (npx praxis-memory in your project). If a Claude Code session was already open during setup, restart it — the / menu loads at session start. And setup installs the commands both in the project and user-wide (~/.claude/commands), so after one setup they appear in every project.

Is the tray app available now?

Yes — on Windows, since v0.2: it starts by itself with setup, and npx praxis-memory tray brings the axolotl back any time, changing emotion with your session's real state (--stop to quit). macOS and Linux builds are next; npx praxis-memory status gives the same health readout everywhere meanwhile.

It says "praxis: command not found" — is it broken?

No — you just don't have the optional global install. npx praxis-memory is the full product: setup, hooks, tray, every command as npx praxis-memory <command>. The short praxis <command> form only exists after npm install -g praxis-memory. Praxis's own hooks run through npx, so auto-capture and the tray work either way.

Hold the proof.

One command to see a receipt. One command to arm your own.

$ npx praxis-memory

click to copy · windows, macos & linux · node 22+ · never seen it? npx praxis-memory demo first

1  before Claude — run it once in your terminal 2  inside Claude — type /  →  /praxis-receipt · /praxis-recap · /praxis-save · /praxis-health · sixteen more