Wife
remembers everything
Local, persistent and auditable memory layer for Claude Code and Codex.
Your agent stops treating you like a stranger every morning.
Why • What it does • Install • How it works • Commands • Security • FAQ
$ wife show
Identity (5 facts)
Who
- Full-stack developer, mostly backend
- Ships side projects solo, nights and weekends
Preferences
- Prefers short, implementation-first answers
- Dislikes long explanations of things already known
Working style
- Always answer in Spanish
█░░░░░░░░░░░░░░░░░░░░░░░ 61/1200 tokens
Project · checkout-api (3 facts)
Stack
- Uses Postgres, Fastify and Vitest
Conventions
- Never commit directly to main
- Run the migrations before the test suite
░░░░░░░░░░░░░░░░░░░░░░░░ 27/800 tokens
Injected at session start
██░░░░░░░░░░░░░░░░░░░░░░ 174/2000 tokens
That block is handed to Claude Code and Codex at the start of every session. You never typed it. Wife learned it from things you already said, and it forgets anything you delete.
Why
You explain your stack. You explain that you want short answers. You explain that this repo runs migrations before tests. The session ends.
Tomorrow, you explain all of it again.
That is not a context-window problem — a model handles one session fine. The problem is that nothing survives the session boundary, and nothing ever learns. Instruction files are documents you maintain by hand. Session resume only reaches backwards into a single conversation. Compaction throws away the parts of a session it judges irrelevant to the current task, which is exactly where facts about you live.
Wife closes that gap with the only thing that actually works: a curator.
What it actually does
Storing text is trivial. The hard part — the entire product — is deciding what deserves to be remembered, what replaces what, and what has to go.
It waits before it believes you
A fact you mention once is staged, not stored. It has to come back in a different session before it reaches long-term memory. State it deliberately — remember that…, always…, never…, or wife remember — and it lands immediately, because you meant it.
This single rule is why Wife's memory stays small enough to trust.
It has a hard ceiling
1200 tokens for who you are. 800 for the current project. When a section fills up, the lowest-scoring fact is evicted, not appended.
score = confidence × recency × repetition × intent
Recency decays on a 90-day half-life for identity, 45 days for project memory. Pinned facts never decay and are never evicted. The ceiling is the design: without it, memory grows until it costs you tokens on every single turn.
It resolves contradictions instead of stacking them
Move off a framework and the old fact is replaced, with the change recorded. Restate something more precisely and the vaguer version is absorbed.
Two statements only merge when one strictly contains the other:
| Statement A | Statement B | Result |
|---|---|---|
Prefers short answers |
Prefers short direct answers |
merged — B is more specific |
Deploys to production on Friday |
Deploys to staging on Friday |
kept apart — each says something the other does not |
Uses Postgres |
Uses MySQL |
kept apart |
Uses Redis |
Never uses Redis |
superseded — you changed your mind |
It lets go of what you stopped believing
Contradict a fact and it is replaced on the spot. But most beliefs don't die that cleanly — you just quietly stop working that way, and never say so.
Go quiet about something for long enough and it goes dormant: out of the
injected context, still visible in the file under ## Dormant. Say it again and
it comes straight back. Delete the line and it's gone for good.
## Dormant
_Not mentioned in a long time, so these are no longer sent to the agent._
_Say one again and it comes back. Delete the line to forget it for good._
- Uses Redis for caching
120 days for identity, 60 for the project, doubled for anything you stated deliberately. Pinned facts never go dormant — that's what pinning is for.
It notices what follows you between repos
Say "never commit directly to main" in one codebase and it's a house rule. Say it in your last three codebases and it's how you work. At three repos, a project fact is promoted into identity automatically, where it follows you everywhere.
wife spread shows what's on its way there.
It follows you between machines
Push your memory folder to a private repo and it works — right up to the day you use two machines in the same week. Then git hands you a text conflict in a file full of facts and asks you to pick a side, and every side loses something.
wife sync setup git@github.com:you/wife-memory.git # once, per machine
wife sync # commit, merge, push
wife clone git@github.com:you/wife-memory.git # set up a new machine
Facts are content-addressed and carry their own provenance, so they merge by meaning rather than by line:
| Situation | What happens |
|---|---|
| Same fact on both machines | sessions are unioned, latest sighting wins |
| Only on one, and it was in the ancestor | the other machine deleted it — deletion wins |
| Only on one, and it is new | kept |
| Contradiction across machines | the newer statement wins, the old one is dropped |
| Candidate waiting on both | sessions merge — the two-session gate now spans machines |
That last row is the quiet win: say something once on the laptop and once on the desktop, and it is finally enough to be remembered.
None of this is limited to two machines. Seven laptops converge as cleanly as
two. And sessions/ is git-ignored, so raw prompts never leave the machine they
were typed on.
It enforces what can be enforced
Injected text is a suggestion. The agent almost always follows it. Almost is not a guarantee — and for some rules that gap matters.
wife harden
Wife ships with no rules of its own. A fresh install has an empty memory and
zero guards; everything below comes from things you said. wife harden scans
your rules for the ones an agent hook can actually enforce, shows you each one,
and turns on only what you approve.
If you happened to have written these, here is what it would offer:
| A rule of yours | What the guard would do |
|---|---|
Never commit directly to main |
block git commit while you are on main, allow it on a feature branch |
Never force push |
block --force, still allow --force-with-lease |
Don't use npm, use pnpm |
block npm install, leave pnpm alone |
Never rm -rf |
block recursive deletes, allow deleting one file |
Don't touch .env |
block edits to .env, not to environment.ts |
Those shapes — git, package managers, deletes, protected files — are the ones recognised automatically because they are what people repeat most. They are not everybody's list, so any rule can be enforced directly:
wife guards --add "Never terraform apply against prod" --blocks "terraform apply"
wife guards --add "Don't touch prod config" --blocks "config/prod" --tool Edit
wife guards --add "No commits on release" --blocks "git commit" --on-branch release
wife guards --test "terraform apply -auto-approve" # see what would happen
The rule stays in memory too, and that is deliberate: the guard stops the action, the memory stops the attempt. Without the memory the agent tries the forbidden thing and eats the block every round — deterministic, and a wasted turn each time.
Three constraints this is built under. Nothing is ever enforced without you
approving it one rule at a time, because a guard invented from a sentence you
never meant as a hard rule blocks work you asked for. A description is never a
guard: Uses pnpm states a preference and blocks nothing, only Never use npm
does. And guards fail open — a broken pattern allows the call, because a bug
that blocks every command is far worse than a rule that missed once.
Most of what Wife knows maps to no tool call at all — tone, language, what you
prefer to see first — so it stays as context by design. PreToolUse is only
registered once you have a guard, so with none there is no hook in the path of
your work.
It only reads what you wrote
Your agent's replies are never mined. When a model suggests "let's use Postgres" and you answer "ok", it has not learned a fact about you — it has heard its own idea repeated back. Wife reads your prompts and nothing else.
It separates you from your repo
Facts about you follow you everywhere. Facts about this codebase stay in this codebase.
"always answer in Spanish" → identity (follows you to every repo)
"never commit directly to main" → checkout-api (stays here)
"I never deploy on Fridays" → identity (your habit, not the repo's)
"this project uses Fastify" → checkout-api
Every single fact is traceable
$ wife why "short answers"
Prefers short, implementation-first answers
store identity · section "Preferences"
source it came up in enough separate sessions to be promoted
confidence 0.75
seen 3 times across 3 sessions
first 2026-07-14 09:22:41
last 2026-07-29 18:03:12
score 0.847 (confidence x recency x repetition x intent)
you wrote "prefiero respuestas cortas, sin tanta explicación"
If you cannot see where a memory came from, you cannot trust it. Wife shows you.
It is a markdown file you own
~/.wife/identity.md is the source of truth. Open it in any editor. Delete a line and it is forgotten — no command needed. Add a line by hand and it is kept at full confidence. git init it if you want history.
No database. No daemon. No account. No network call. Ever.
Install
Option 1 — let your agent do it
Copy this and paste it into Claude Code or Codex:
Install "Wife", a local memory layer for coding agents, from
https://github.com/ma-nucho-pro/wife
Do exactly this:
1. git clone https://github.com/ma-nucho-pro/wife.git ~/.local/share/wife
2. cd ~/.local/share/wife
3. npm link (this puts the `wife` command on my PATH)
4. wife init
5. wife attach claude (use `wife attach codex` if you are Codex)
6. wife status and show me the output
Do not modify any of my existing hooks or settings beyond what
`wife attach` does. It merges into my settings file without
removing anything. If `npm link` fails with a permission error,
tell me instead of using sudo.
Then restart your agent. That is it.
This repo ships a
CLAUDE.mdand anAGENTS.md, so if your agent is already sitting inside the cloned folder it knows how to install itself without any prompt at all.
Option 2 — one command
curl -fsSL https://raw.githubusercontent.com/ma-nucho-pro/wife/main/install.sh | bash
Option 3 — by hand
git clone https://github.com/ma-nucho-pro/wife.git
cd wife
npm link # puts the `wife` command on your PATH
wife init # creates ~/.wife and attaches whatever it finds
wife attach claude
On Windows, use Option 3 in PowerShell — the install script needs bash.
Requires Node 18.17 or newer, which you already have if you are running Claude Code. There is no build step and zero runtime dependencies: the whole tool is plain Node with nothing pulled from npm.
Already have a CLAUDE.md? Start from it.
wife import # --dry-run to see it first
Reads ~/.claude/CLAUDE.md, ~/.codex/AGENTS.md, and this repo's CLAUDE.md
or AGENTS.md, and seeds memory from them. The scope of the file decides the
scope of the fact: your user file becomes identity, the repo's file becomes
project memory.
Credentials are screened out before anything is written, code blocks and install steps are ignored, and Wife never re-reads its own managed block.
Check it worked
wife status
Then open a new session. In Claude Code, /hooks will list three entries. Nothing else about how you work changes.
Uninstall
wife detach claude
wife detach codex
rm -rf ~/.wife # only if you also want the memory gone
detach removes Wife's hooks and leaves every other hook in your settings exactly as it was.
Which agents, and how far
Not every agent exposes the same lifecycle, so this is exactly what each one does.
| Injects memory | Learns from your sessions | Enforces guards | |
|---|---|---|---|
| Claude Code | SessionStart |
UserPromptSubmit + SessionEnd |
PreToolUse |
| Codex | SessionStart |
UserPromptSubmit + Stop |
PreToolUse |
| Cursor | rules file, rewritten at stop |
beforeSubmitPrompt + stop |
beforeShellExecution |
| Gemini CLI | GEMINI.md |
no | no |
wife attach claude
wife attach codex
wife attach cursor
wife attach gemini
All four read the same memory, so a fact learned in Claude Code shows up in Codex.
Codex needs hooks, which went stable in v0.124.0. wife attach codex also
enables [features] codex_hooks for older builds and writes an AGENTS.md
block as a fallback for versions predating the hook engine entirely.
Cursor has no session-start event whose output becomes context, so memory is
injected through an always-applied rule at .cursor/rules/wife-memory.mdc,
rewritten by the stop hook at the end of every session. The loop still closes;
it is just one session behind on facts learned minutes ago.
Gemini CLI gets injection only. Its hook engine exists, but wiring to an
event name this integration cannot verify would fail silently — the worst
outcome for a memory tool — so GEMINI.md it is. Refresh with wife sync-gemini,
or let a Claude Code or Codex session on the same machine keep the store current.
Blocking works differently in each: Claude Code takes a permissionDecision,
Codex wants exit code 2, Cursor wants { permission: "deny" }. Cursor also
names things differently — conversation_id and text where the others send
session_id and prompt. All of that is handled, and tested against each
agent's documented payload.
How it works
Three hooks. No wrapper around your agent, so your workflow is untouched.
SessionStart → wife inject puts your memory into the session
UserPromptSubmit → wife capture buffers what you typed, silently
SessionEnd → wife harvest curates the session into memory
The curator runs in four steps:
what you typed
│
1. extract pattern rules, Spanish and English,
│ tuned to miss rather than to invent
▼
2. gate explicit? store now.
│ otherwise stage it and wait for a second session
▼
3. reconcile reinforce · supersede on contradiction · add
│
▼
4. prune enforce the token ceiling, lowest score first
│
▼
identity.md + projects/<repo>/project.md
Extraction is deterministic pattern matching, not an LLM call. No API key, no cost per session, no network, and behaviour you can read in one file and predict. It fires on the phrasings people actually use when stating something durable — recuerda que, siempre, nunca, prefiero, no uses, usamos, me llamo, and their English equivalents — and throws out anything that is a question, a task, code, a path, a URL, a pasted log, or a credential.
Facts are written in the language you said them in. Spanish in, Spanish out.
Crash safety. If your agent is killed, your laptop dies, or SessionEnd never fires, the buffer is picked up at the next SessionStart. Session buffers are the only place raw prompt text is written, and they are deleted the moment they are harvested.
The injected block reads as plain factual statements, never as commands, so it is used as context instead of being flagged and surfaced back to you.
Commands
Memory
| Command | What it does |
|---|---|
wife import |
seed from your existing CLAUDE.md / AGENTS.md — --dry-run |
wife review |
decide what stays: waiting candidates and dormant facts |
wife spread |
facts showing up in more than one repo |
wife harden |
turn rules a hook can enforce into real guards |
wife guards |
what is enforced — --add … --blocks …, --test …, --off … |
wife remember "<fact>" |
store it now — --project, --section X |
wife forget "<text>" |
remove it entirely |
wife pin "<text>" |
exempt from decay and eviction |
wife unpin "<text>" |
undo that |
wife why "<text>" |
where it came from and what it replaced |
wife edit |
open the memory file in $EDITOR — --project |
Inspect
| Command | What it does |
|---|---|
wife show |
exactly what your agent will be given — --raw, --verbose |
wife status |
memory size, wiring, pending buffers |
wife journal |
audit trail of every change — -n 50, --event added |
wife doctor |
duplicates, drift, broken wiring — --fix |
wife config [key] [value] |
read or change settings |
Setup
| Command | What it does |
|---|---|
wife init |
create ~/.wife and attach whatever is installed |
wife attach <agent> |
claude · codex · cursor · gemini — --project |
wife detach <agent> |
remove it cleanly |
wife sync-gemini |
refresh the Gemini block |
wife sync setup <url> |
wire ~/.wife up to a private git repo |
wife sync |
commit, merge the other machines in, push |
wife sync status |
how far this machine has drifted |
wife clone <url> |
set up a new machine from your memory repo |
wife sync-codex |
refresh Wife's block in AGENTS.md |
Lifecycle
wife inject, wife capture and wife harvest are what the hooks call. You rarely run them by hand, though wife harvest --verbose is the best way to see what the curator accepted and why it rejected the rest.
Security
Wife reads every prompt you type. That is only acceptable under strict rules, so here they are.
Credentials never reach disk. Anything matching a credential shape disqualifies the entire candidate — it is dropped, not masked, because a masked fact still leaks its context.
| Screened | Examples |
|---|---|
| Provider keys | sk-…, sk-ant-…, ghp_…, AKIA…, AIza…, xox…, sk_live_… |
| Tokens | JWTs, Bearer …, Authorization: headers |
| Secrets in assignments | password=, api_key=, secret=, token= |
| Connection strings | postgres://user:pass@…, mongodb+srv://…, redis://… |
| Key material | -----BEGIN … PRIVATE KEY----- |
| Entropy | long hex digests and high-entropy base64 blobs |
Add your own with wife config denyPatterns '["client-name","internal-codename"]'.
Nothing leaves your machine. No telemetry, no analytics, no network calls, no accounts. ~/.wife is a folder of markdown and JSON on your disk.
Raw prompts are transient. They live in a session buffer only until that session is curated, then the buffer is deleted.
Everything is reversible. wife forget removes a fact completely. Deleting a line from identity.md does the same. The journal records that a removal happened and when, never resurrecting the content.
Pause it whenever you want: wife config capture false stops learning while still injecting what it already knows.
Architecture
~/.wife/
identity.md you. hand-editable, the source of truth
identity.index.json confidence, seen counts, provenance
projects/
checkout-api-a1b2c3d4/
project.md this repo. same rules
project.index.json
meta.json
sessions/ prompt buffers, deleted once curated
cross-project.json which facts have shown up in more than one repo
journal.jsonl append-only audit log
config.json
The .md files are what you read and edit. The .json sidecars hold metadata that has no readable place in a bullet list.
Markdown always wins. On every load Wife reconciles the index against the file, so a line you delete by hand is forgotten and a line you add is adopted at full confidence. You are never fighting the tool for control of your own memory.
Configuration
wife config # show everything
wife config budget.identity 2000 # more room for who you are
wife config promotionThreshold 3 # be even more sceptical
wife config halfLife.project 30 # project facts go stale faster
wife config denyPatterns '["acme-corp"]' # never store anything matching this
wife config capture false # pause learning, keep injecting
wife config dormancy.identity 180 # be slower to let go of who you are
wife config crossProjectThreshold 2 # promote to identity sooner
FAQ
Does this send anything anywhere?
No. There is no network code in this repo outside of git clone during install. Memory is markdown on your disk.
Does it cost tokens? About 150–250 tokens per session, once, at the start. That is roughly what you spend re-explaining your stack in a single message.
Does it need an API key? No. Extraction is pattern matching, not a model call.
What if it remembers something wrong?
wife forget "<text>", or open ~/.wife/identity.md and delete the line. Both are permanent.
What if it misses something important?
wife remember "<fact>" stores it immediately at full confidence. Saying remember that… or always… in a normal prompt does the same thing.
Isn't a rule in a prompt just a suggestion?
For some rules, yes, and that is a fair criticism. wife harden finds the ones a
hook can enforce and turns them into PreToolUse guards you approve one by one.
The rest — tone, language, preferences — correspond to no tool call, so a hook
cannot express them either way.
What happens to something that stops being true? Three ways out. Contradict it and the old fact is replaced immediately, with the change recorded. Say nothing for long enough and it goes dormant — out of the context, still in the file, revived the moment you mention it again. Or delete the line yourself. Nothing silently rots.
Can I use it on several machines?
Yes, and properly. wife sync setup <private-repo-url> on each machine, then
wife sync. Memory merges by meaning rather than by line, so two machines that
both learned things in the same week end up with everything, not with one of
them winning. There is no two-machine limit.
Does it work with both Claude Code and Codex at the same time? Yes. Both read the same memory, so a fact learned in one shows up in the other.
Can I edit the memory by hand? That is the intended way to use it. The markdown file is the source of truth and your edits always win.
Which languages does it understand?
Spanish and English out of the box, and it writes each fact back in the language you said it in. Adding a language is a rule block in src/core/extract.js — pull requests welcome.
Verify it yourself
npm run check
247 unit tests, a 78-check end-to-end run, a 67-check multi-agent run, and a 55-check multi-machine convergence run using real git that spawns the real CLI and feeds it the exact JSON Claude Code puts on a hook's stdin. Among the things it proves:
- a credential pasted into a prompt never appears anywhere under
~/.wife - a task ("fix the login bug") never becomes a memory
- a preference stated once is not stored; stated again in a different session, it is
- attaching over an existing settings file preserves every other hook and setting
- attaching three times produces three handlers, not nine
- every hook command exits 0 given no stdin, garbage stdin, a null prompt, a 500 KB prompt, or a session id of
../../../etc/passwd - a corrupt index file is quarantined and recovered from instead of crashing
- a buffer from a session that never ended is picked up at the next start
- the CLI works through npm's real platform launcher (
wifeon POSIX andwife.cmdon Windows), not just as a direct file - a credential inside an imported CLAUDE.md is dropped, underscores and all
- a fact gone quiet for months stops being injected but stays in the file
- saying a dormant fact again revives it, back to its original section
- one repo repeating itself never triggers cross-project promotion; three do
- three machines diverging in parallel converge to an identical set of facts
- a fact deleted on one machine stays deleted on the others after a sync
- a candidate seen once on each of two machines is promoted, exactly as it would be within one
- a description ("Uses pnpm", "Deploys on Thursdays") never becomes a blocking guard
- a commit guard blocks on main and allows the identical command on a feature branch
- a malformed guard pattern allows the call instead of throwing
PreToolUseis not registered at all until a guard exists- Codex wires
Stop, notSessionEnd— Codex has no such event, and a hook on a name that does not exist never fires and never says so - Cursor's
conversation_id/textpayload is understood, and Cursor gets an explicitallowrather than silence - a Codex guard denies with exit code 2, not with a JSON decision object
- attaching to Codex three times leaves one
codex_hooks = true, and the rest of yourconfig.tomluntouched, blank lines included
CI runs the whole suite on Linux, macOS and Windows across Node 18, 20 and 22.
Author
Roberto Manuel Jara Peche
If Wife saves you from re-explaining yourself, a ⭐ on the repo helps other people find it.
Comments