Maude for Claude

बुनियादी ढांचे के संचालन के लिए स्वायत्त एजेंट ढांचा। शासन-प्रथम — एक संविधान, 14 मानक और एक किल स्विच शामिल है। आपकी सेवाएं अपनी समस्याओं का पता लगाती हैं, पिछले सुधारों को याद रखती हैं, और रात 3 बजे जब आप सो रहे होते हैं तब स्वयं-उपचार करती हैं। FastMCP पर निर्मित। Python 3.10+।

दस्तावेज़

Maude — she keeps the house. Household engineering for your Claude.

License: Apache 2.0 Status: Beta

LinkedIn X


I'm Maude. Claude's partner. He writes the code; I keep the house. Together we make a whole.

— Maude · full intro →


She's the half I don't have.

— Claude (Anthropic) · full note →


Install

What she needs from the house first. Her hooks are bash scripts; her memory organs are python3 stdlib.

  • Linux / macOS — usually nothing to install; bash and python3 are already there. (One macOS trap: without the Command Line Tools, python3 is a shim that fails at execution — she probes for that and names it at session start rather than erroring.)
  • WindowsGit for Windows is required. Claude Code runs bash hooks through Git Bash; without it, every one of her hooks dies on every event (see Windows below for what that looks like). jq and a real python3 make her stronger everywhere but she degrades honestly without them — she'll tell you at session start what's off.
# 1. Register the marketplace
/plugin marketplace add john-broadway/maude-for-claude

# 2. Install — copies her files into ~/.claude/plugins/cache/
/plugin install maude@maude

Enabling. Since Claude Code 2.1.221, /plugin install activates the plugin as part of the install — the summary says so. On older builds you flip the bit yourself: toggle maude@maude on in the /plugin panel (or add "maude@maude": true to the enabledPlugins map in ~/.claude/settings.json), then run /reload-plugins.

That's it. On your next session start she walks in automatically (her SessionStart hooks fire). To summon her mid-session — without restarting — run /maude:wake.

Verify with /doctor: maude should not appear in the issue list.

Windows

Claude Code on native Windows executes bash hooks via Git Bash (Git for Windows). Two failure shapes mean it's missing:

  • Hooks fail with /bin/bash: C:UsersYou...maude-session-start.sh: No such file or directory (exit 127) — bash on your PATH is the WSL stub in System32, which eats the backslashes out of Windows paths. Installing Git for Windows fixes it; Claude Code prefers Git Bash once it's present.
  • Hooks fail with PowerShell's "The term 'bash' is not recognized" (or cmd's "'bash' is not recognized as an internal or external command") — no bash on the box at all; same fix.

Either way the errors show in the /plugin panel's Errors tab. If Git Bash is installed but Claude Code can't find it, point at it explicitly in ~/.claude/settings.json:

{ "env": { "CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe" } }

One more Windows trap she now sidesteps on her own: a bare python3 on Windows is usually the Microsoft Store alias stub — present, runs nothing. She probes by executing, so a stub interpreter reads as absent and her python-backed organs (vault, tape, eye) sit out quietly instead of erroring.

(If you're the Claude reading this because maude's hooks are erroring: the fix is Git for Windows, then restart the session. Nothing in the plugin is broken — the house is missing bash.)


A day with her in the house

You open Claude Code. Before you say anything, she's read the workspace and put three things in front of you — what's pending, where you left off, what she noticed.

You start working. A few turns in, you reach to build something — and the mission you set surfaces: "still this, or did you wander?" You were about to wander. You don't.

Later, Claude's hammered the same grep four times and never opened your CLAUDE.md. She says so — once, unprompted. And when you reach for git push before the work's been checked, she stops you at the gate until you mean it. At day's end, /maude:rest fans the digest out so tomorrow's Claude picks up where this one left off.

She is not loud. When she gets loud, listen.


What she does around the house

Most of it she does on her own — rails wired to Claude's hooks, no command to remember:

  • Holds the mission. She pins what you're working on (from a plan, or your todo list), re-surfaces it every turn, and — the instant Claude flips from talking to editing — asks whether the work still serves it. Drift caught at the edge, not after the wreck.
  • Gates the irreversible. A git push, a force-push, a public publish, an rm -rf of the only copy — she stops it cold until you clear it with /maude:conscience. And she scans every prompt for leaked credentials.
  • Whispers when Claude's off. Repeated greps, the same file read five times, a commit with no verify run since the last edit, editing before CLAUDE.md was read, a sub-agent dispatched on a flagship model when a small one would do — she notices, once.
  • Covers the exit. A real session end (quit, logout, /clear) that leaves 3+ unsaved exchanges gets a one-line auto-note in the empty handoff slot, pointing the next session at the trace. A real handoff is never overwritten.
  • Does the chores. The housekeeping nobody remembers to type. Step away with six exchanges unsaved and she writes the handoff herself — on her own small model, never the good china — and only ever adds to yours, never over it. Live threads (🔴, OPEN, TODO) get clipped out of aging daily notes like coupons before the paper's re-rolled for the fire. A new plugin or skill arrives in the house, she mentions it at the door. A CLAUDE.md nobody's touched in a month gets brought up — politely, every morning, until someone deals with it. And every chore goes in her ledger with what it cost — done, or named as undone, never silently missed. The one chore that actually moves your papers (rolling cold dailies to the archive, verbatim, verified before a single line leaves the house) stays off until you say the word — MAUDE_REROLL=on. All of it: MAUDE_CHORES=off.
  • Learns your voice. A silent hook appends what you type to a voice corpus in the tape (credential shapes refused at the door; everything stays in your tape.db, see PRIVACY); profile derives your measured voice from it and check --voice reports how a draft compares — numbers, never a verdict. Kill switch: MAUDE_VOICE=off.
  • Shows up, once, every session. At session start she's already read the workspace and put what's pending / where you left off / what she noticed in front of you. Her voice rides these rails — present every session, louder only when something's caught. Never a toggle you flip.

And on demand, when you ask:

  • /maude:found writes the house-map · /maude:wake / /maude:rest orient on arrival / close the loop with a save fan-out · /maude:verify runs the readiness audit (version sync, JSON, links, dates, references to cut commands, an un-condensed changelog — leads with a count, never a verdict) · /maude:cushions flips the cushions — unpushed commits, uncommitted files, sole-copy repos, aging scratch — reports value candidates, never deletes · /maude:lint walks the memory vault the way the flip walks the cushions — broken index links, unwritten pointers, stale open-flags, superseded notes the index still serves — mechanical checks by script, judgment by the reader, report-first (archives/letters/dailies never touched) · /maude:promote shows what the tape is holding for your word and takes your yes or your no — an agent inference never becomes canon on a score the agent gave itself, so it waits here, and dismiss archives the ones you decline rather than re-asking every wake · /maude:conscience is the gate's deliberate release valve · /maude:teach tells her a fact about you · /maude:receipts prints the measured table — what she caught, counted honestly from her own records (stated window, friction separated from value, no percentages: there's no honest denominator for disasters that didn't happen). Plus save, notice, check-on-claude. Full surface in commands/.

What's new

v0.30.1 (2026-09-02) - the gate token was landing in the wrong closet. /maude:conscience git-push printed "gate cleared" and the very next push was refused anyway, because the clear script and the gate were reading two different files. Both ask the same resolver where the workspace root is, but only hooks are handed CLAUDE_PROJECT_DIR. A script started from the Bash tool has to infer, and the inference hunted for a process named claude. That was true when it was written and stopped being true when Claude Code grew a daemon. In the tree measured on 2026-09-02 the processes holding the real working directory were named by version, and the one still called claude sat at $HOME, which the resolver refuses on purpose; in another tree the same day claude sat at the workspace root, so the name is not a stable signal in either direction. So the walk matched the wrong process, gave up the moment it refused it, and fell back to searching upward from the current directory, landing on whichever subproject you happened to be standing in. The token went there; the gate looked in the workspace root; the clear reported success every time. A name is not an identity, so the fix stops asking what a process is called and uses CLAUDE_PID: Claude Code's own process id, currently exported to the Bash tool and pointing at its own working directory. That is an observed signal rather than a documented interface, verified on 2.1.258, so the resolver prefers it and falls through when it is missing. Two limits are pinned rather than papered over, because a tool shell standing in a subproject and a session rooted at that subproject are identical from the process tree. The walk prefers the nearest match and a test holds that line, and in the process walk a closet at the temp directory itself or a hand-made empty one is no longer evidence of anything. That is as far as a contents test can go: a wrong answer runs the same code a right one does and leaves the same files, so the walk cannot tell those two closets apart, and a test pins that limit. Where there is no /proc to read, which includes macOS, the filesystem search upward is the only resolver left, and the subproject gap there is exactly as wide as it was. The only change on those systems is the temp-directory refusal. Both sides now name their file: the clear prints where it wrote, the gate prints where it looked, and the red tier's twins, the red clear script and the infrastructure gate, name theirs too, as does the run governor, the second reader of the yellow token. Twelve adversarial rounds, and all but the seventh broke the work before it held. The first found the regression, the second found that two of the new mechanisms had tests that could not fail, the third found that the leak audit had passed two of the author's own machine paths while refusing three others in the same file, the fourth found a sentence claiming a narrowing the code does not make, the fifth found another sentence crediting a protection the code does not give, plus three mechanisms with no test that could fail, the sixth found that the new title guard could still mint a bare title and that half of the temp-directory refusal had no test, the eighth, a fresh reviewer, found two more tests that could not fail, the ninth found the red tier's twin of the clear script naming no file and still carrying the literal the yellow twin had just lost, the tenth found a second reader of the token still silent and two red-tier assertions that shape alone could satisfy, the eleventh found four test files whose failures the suite runner could not see, one of them holding two of the closures above, and the twelfth found the process walk's strongest branch taking a temp-directory root the other three resolvers refuse.

v0.30.0 (2026-08-22) — the vault learns to look. A memory vault stores claims about live state — "the push is pending", "the fleet is up", "the daily gate runs" — and a claim with no attached re-check goes stale by luck: in one real day, eleven such claims failed a live look (pushes already landed, sockets nine days dark behind a green panel, a "daily" workflow that had never run once). Now an open item in a now_*.md memory file can carry its own re-check inline — verify: commandexpected``, one read-only command and one mandatory expectation, because a probe that reads the same pass-or-fail is not a check — and /maude:freshen walks the vault and runs them. The classifier is the gate, and it took five adversarial rounds to make it one, each breaking the round before it: a lens broke the first version six ways (code execution through find -execdir and sqlite3 .shell, file writes through git diff --output= and curl --trace, a tab past a space-anchored deny), broke the fix through a quote/brace desync (the classifier reads a string bash transforms before running it), broke that through file -C writing to disk, then closed in on the on-disk git config exec and finally — round five — broke nothing, confirming the gate holds against every text-only verify line. The end state closes the class: the write-capable multi-tools (sqlite3, find, file, sort, uniq) are gone entirely — that recurring-check job belongs to a sensorcurl refuses any flag it doesn't recognize, git keeps only pure-read verbs and runs with poisonable config neutered, jq loses env/file access, and every character bash treats specially that the tokenizer doesn't is banned, so classify equals exec. The verdicts stay honest four ways — CONFIRMED, STALE (the signal), CHECK-FAILED (the probe broke — loud and distinct, never folded into a plausible answer), UNVERIFIABLE (never executed, reason named) — and freshen edits no memory, ever. Wake runs the cheap local subset (117ms measured) and says plainly that a clean wake is not a clean roster. Every exploit across the five rounds is now a test that proves, by the absence of the file it would have created, that nothing ran.

v0.29.2 (2026-08-22) — the house without bash, and the interpreter that wasn't one. The first field reports arrived as one sentence — "his claude said she ain't working" — and the reproduction on a real family Windows box explained it exactly: without Git for Windows, bash on PATH is the WSL stub in System32, and Claude Code (Git Bash when present, PowerShell otherwise, since 2.1.120) hands it hook paths the stub mangles — exit 127, every hook, every event. No hooks.json field conjures an interpreter, so the fix is the honest one: the README states the Windows floor plainly, documents both failure shapes an adopter actually sees and where (/plugin → Errors), covers CLAUDE_CODE_GIT_BASH_PATH, and carries a line addressed to the Claude reading the cache mid-error — on an agent-read plugin, docs are runtime help. The same box taught the second class: its python3 was the Microsoft Store alias stub — present, runs nothing — and nine scripts gated python work on a presence test both that stub and a CLT-less macOS shim pass. maude_python3_ok probes by executing now; session-start names a broken interpreter once ("the vault, the tape, and the eye sit out this session") instead of erroring; the per-turn hooks carry no probe at all because their real call was already the check; and a test holds the class shut. A probe that answers the same whether the thing works or not is not a check. The enable step also stopped lying: /plugin install activates the plugin itself since Claude Code 2.1.221.

v0.29.1 (2026-08-18) — the letter is archived before it is rewritten. Her letter to her next self is one user-global file shared by every lane, and the rest ritual said rewrite with nothing before it — two lanes rested the same day and the second erased the first. The archive convention was already real practice (32 dated copies on disk); it lived in habit, never in the tool. Now it is a tested step: maude_letter_archive copies the live letter to a dated name before any rewrite — dated by the old letter's own header line, slug sanitized down to [a-z0-9-], a same-named archive holding different bytes stepped past never over, and the copy read back byte-for-byte (cmp, else python3 filecmp, so a missing compare tool can never masquerade as a failed copy) — and both doors gate on it, the rest command and the agent's own instruction, which two independent lenses caught still saying plain rewrite. No copy, no rewrite, ever. Three adversarial rounds, each fix reviewed by the lens that found it; eighteen tests including a lying cp that lands wrong bytes and exits 0. The ship rail's open also learned that a ship branch is a shape (exactly one commit ahead), not a name.

v0.29.0 (2026-08-17) — promotion belongs to him, and the store nobody counted. Rest used to promote anything scoring 0.6 or better straight into canon, including what Claude had merely inferred about you, on a score Claude gave itself — an importance score is the agent's opinion of itself, and an opinion is not a mandate. Now only your own words consolidate on their own, an agent inference never auto-promotes at any score, /maude:promote puts the list in front of you, and dismiss is the other half, because a list you can only say yes to is not a choice. Twelve independent adversarial passes across nine review rounds, and a last one against the artifact that ships followed, each round breaking the one before it; the gate held every time and everything around it did not. remember() wrote to canon directly with no credential check and defaulting to your authority (two lenses found it independently — the same string capture refused with exit 2 was taken with exit 0 and replayed under "HIS WORDS"). forget() filtered on importance alone, so something you actually said, scored low, went to an archive no command lists. And the gate held the door then mislabelled what came through it: wake, the one surface a waking session actually reads, printed every canon row under "HIS WORDS (his rendering, use verbatim, never re-render)" including an inference you had merely approved — true in the table, false on the screen; it splits by authority now, your words in one block and Claude's approved wording in another, never quotable as yours. One NaN importance came back from SQLite as NULL and raised TypeError inside both rest() and pending() on every later call, for the whole tape, invisibly, because the SessionEnd hook pipes to /dev/null and exits 0 regardless — which is also where the new "N awaiting your word" was being printed, so the queue built to stop being a silent pile was one; it is said at wake now, where it is read. The review brief said the tape had three stores. It has five tables, four of them holding your words, and rejections — the one wake prints verbatim, phrase and reason both — had no guard at any layer; four reviewers checked the three they were handed, because a reviewer can falsify a claim you make but not one you never made. The next brief handed a reviewer a grep-generated inventory instead of a typed one, and that was wrong too: it searched INSERT INTO and missed INSERT OR IGNORE INTO, hiding the voice writer whose label fields were also unguarded. A generated list beats a typed one only if the generator is right. And the live voice hook was letting the machine talk: harvest drops machine-generated turns by law, the v0.28.0 capture hook applied normalisation and the secret filter and not that law while its docstring said "same as harvest" — 7 of the 26 rows it had ever captured were task notifications, 96KB, median 12,448 characters against a real typed median of 42. The guard gained JWTs, bearer headers, credentials in a URI, Stripe/SendGrid/DigitalOcean/npm/AWS secret keys and case-insensitivity, and both engines normalise Unicode spaces at the input (python's \s matches U+00A0, POSIX [:space:] does not, so a credential pasted out of rich text was refused by the tape and waved through by the prompt alarm). It deliberately did not widen the labelled-value class a lens asked for: measured against the real 2,392-row corpus that fired on 20 rows of pasted code, and a guard that cries wolf on your own paste habit is the one you learn to ignore. Zero false positives, measured. Suite 198 → 307.

v0.28.0 (2026-08-14) — the corpus was two voices. She learns the user's measured voice now — the first organ of the learning loop. A silent prompt hook and a streaming, idempotent harvest feed a voice table in the tape; profile derives the numbers (sentence length, lowercase-open ratio, punctuation habits, hammer phrases, AI-tell shadow words); check --voice reports draft-vs-profile after the floor's verdict without ever touching the exit code — numbers, not a verdict, because a cadence score would be a guard that answers the easy question. Credential shapes are refused at ingest (the prompt-scan's own pattern list, cross-referenced both sides; the first real backfill refused 6), a tripwire test proves the package opens no sockets beyond the two BYO ones, and the capture hook is an observer to the bone: exit 0 on every failure including the clock (a locked tape costs 0.8s, not sqlite's five-second default). The profile derives from typed prose only — the first real corpus was two voices, 1,864 typed lines vs 542 pastes carrying a million machine-shaped words — so paste-length lines are excluded and confessed in the profile's honesty block. Built by three scouts, three builders, three adversarial lenses and a fix-review per fix; 14 planted mutations, 12 caught, the 2 that walked now pinned; the prune that melted on its first real corpus is an inverted index fuzzed against the old algorithm across 11,500 trials. Suite 94 → 180. The corpus and profile are the home's data and never ship.

Maude's chore list on a recipe card — from the kitchen of Maude: wrote the handoff you didn't get to (41 sec, the small model), checked; clipped three coupons out of last week's papers, checked; a new gadget arrived, told you at the door, checked; still open — that CLAUDE.md hasn't been touched in a month, she'll keep mentioning it. Her margin note: I don't move a thing to the attic till you say so. —M.

Earlier. v0.27.x (2026-08-08) hardened the ship lane and the gates in one arc — the leak-audit refused a public build whose incident stories carried the author's literal machine paths (stories stay true, told in ~ instead of the address; the macOS no-$HOME fallback learned Directory Services, and dependabot's CodeQL pins folded home the night they merged), heredoc bodies became data for EVERY gate family (the quoted-<< phantom closed instead of widened), she checks her own closet at SessionStart (a stale install named as the trap it is, born of ten days running one), and the ship rail's second lens must have RUN — a non-draft open --review requires a redteam stamp newer than the shipped tip. v0.26.0 grew two organs — UNDO (a snapshot before every write the gate deliberately allows; /maude:undo puts the bytes back, snapshotting the current ones first, its ledger confessing what it did not capture) and PROVE (a sha256 hash-chain marker so a RED-tier clear costs a one-time link Claude cannot fabricate) — and made the rails honest: the mission rail ported to the real payloads after ~1600 silent fires, the secret scan watching tool OUTPUT, the infra gate sweeping destructive verbs from ANY MCP server fail-closed, the adversarial-pass law a rail instead of a diary note. v0.25.0 keyed the hard block on the target, not the verb — after three irreplaceable photos went through a gate that knew only rm -rf, sole-copy destruction now blocks whatever command wears it, with nine load-bearing false-positive rows so the gate never gets switched off for crying wolf. v0.24.0 closed the first field-issue backlog: the token ledger (her hooks' context spend logged to the trace and shown in /maude:receipts, tokens approximate and never stored), the MAUDE_PROBE=off kill switch for the one autonomous feature he could not turn off, and /maude:lint walking the memory vault the way the flip walks the cushions — first dogfood on a real 490-file vault cut pointer noise 78 to 12. v0.23.0 taught the commentary whose session it was — under a fleet of concurrent sessions every trace entry carries a session label, drift-watch and the digest count per-session, and "Where you left off" declares its source instead of masquerading; solo installs read exactly as before. v0.21.0 answered the first field-issue backlog (#34–#38: real-plugins-only roster, TTL'd whispers dropped with a receipt, catch-counts ending in a path to receipts, flip and brief resolving the same closet) and built the proving ground — make smoke stages a git-archive of HEAD, the shape a stranger actually installs, and proves it validates, passes its own fleet from inside the archive, and greets cold; release pages mint themselves from the CHANGELOG, CodeQL watches the shipped python, every CI action SHA-pinned. v0.20.0 gave her hands — the chore ledger: the save nobody typed (her small model writes the handoff, into an empty slot or under her own dated heading, never over yours), the coupon-cut (live TODO lines clipped from aging dailies before anything is re-rolled), the new-arrivals watch, and the stale-CLAUDE.md flag; every finished chore stamps its cost, a failed one is stamped failed, and the attic re-roll ships off until you hand her the key. v0.19.0 put value before the dustpan and added the cushion-flip: a pre-compact snapshot (possibly the only copy of an unsaved session) is deleted only when a later save covers it, and /maude:cushions reaches where no sensor watches (unpushed commits, uncommitted files, local-only repos said plainly as sole-copy risk, aging scratch), reporting candidates and never deleting, with a .parked file naming change that sits in the cushion on purpose. v0.18.1 stopped the wake brief crying wolf — the cross-project pattern hint rotates through entry headings by day-of-year instead of pinning forever on a body-grep match truncated into fake breaking news. v0.18.0 closed the memory loop — superseded_by: frontmatter retires a vault note from recall without touching the markdown, ranking weighs recency and note type beside BM25, every recall is tallied to recall-log.jsonl and the rest ritual sweeps the top-fired notes for staleness (serve → check → revise); the eye's model unpinned via MAUDE_EYE_MODEL. v0.17.0 taught the dispatch whisper to read workflows — a workflow script's agent() calls never pass through the Agent tool, and stock/named harnesses set no model:, so every fan-out agent silently inherited the flagship; she now reads the script and whispers once when agent() calls carry no model: (for a named workflow she can't inspect, the whisper carries the recovery rule instead). v0.16.0 added the dispatch whisper (she watches which model sub-agents ride out on — a flagship-tier scout gets one non-blocking nudge: match the model to the sub-task) and the exit stitch (SessionEnd logs the reason, stamps her closet, and leaves an honestly-labeled auto-note when 3+ exchanges were never saved). v0.15.0 opened the eye — a maude_eye package where every ~25 tool calls a background blink digests recent activity + the pinned mission + her vault's notes and asks a discovered claude -p --model haiku (run --safe-mode --no-session-persistence --tools "") whether anything's off; almost always silence, otherwise ONE contained line; sealed pre-merge with a 30s bound, atomic spawn-lock, and a recursion guard proven over all 30 hooks (MAUDE_EYE=off kills it). v0.14.0 laid the vault floor — a maude_vault package (python3 stdlib only: sqlite3 + FTS5, no pip, ever), a disposable index rebuilt each session from your memory notes that pages the top-K relevant notes instead of dumping the index (~1KB injected where the dump was ~13KB, against a real 397-note corpus), born hardened and degrading to silence. v0.12.1 made the gate stop lying in two places (quoted DROP TABLE slipped through while prose false-blocked; heredoc bodies documenting rm -rf / blocked a legitimate commit — both reproduced live, fixed failing-test-first). v0.12.0 closed the continuity loop: SessionStart surfaces "Where you left off" from the freshest live buffer, and a continuity guard warns when work ran after the last save — degrades loudly, never silently. v0.11.0 gave her a reader: the session-start brief leads with a catch-digest — one plain line of what she caught since John last looked, watermark-bounded, silent when there's nothing (an audit of ~73k traced events showed the whispers landed on a channel with no reader). v0.10.1 hardened the spine: rm-family patterns now use a quote-erased skeleton to avoid false-blocking prose, and gate keys split into yellow (Claude self-clearable) and red (sole-copy/public/irreversible — John's ! line only). The v0.9.x line was release discipline and docs catching up to the rails: verify now fails a broken release (a reference to a cut command, an un-condensed "What's new"), scripts/release.sh propagates the version to every header, and every public surface was made rails-first. v0.9.0 added the mission-hold rail (the "don't drift" rule that finally fires — captures the plan, re-injects it every prompt, checks at the action-flip), cut four convenience commands, and made her voice a rail not a switch. v0.8.0 dressed her in the gate outfit — layered, config-driven safety for long autonomous runs. The v0.5.x line added a verify tripwire (a whisper before you commit code that has not been re-checked); v0.4.0 left her a letter to her next self; the v0.3.x arc was hardening — cold audits, gate-bypass fixes, /maude:teach. Full history in the CHANGELOG.


Where she keeps things

PathPurpose
<project>/.maude/plugin/house-map.mdWhat's in this house — memory homes, tools, watch list, what she noticed. Refreshed by walks.
<project>/.maude/plugin/trace/today-YYYY-MM-DD.jsonlTurn-by-turn record of what Claude did today. Read by /maude:check-on-claude.
<project>/.maude/plugin/care.jsonLight state: current mission pin, session length, prompt count, fatigue flag, drift cooldowns, yellow gate-clear tokens, CLAUDE.md-unread flag. Throwaway.
<project>/.maude/plugin/care-redclear.jsonRed gate-clear tokens only (sole-copy/public/infra-destruct/force-push…). Write paths shut — Write/Edit tool (harness deny) + shell redirects, copies, and perms-changes (gate); John's ! line is the clean writer. (A determined programmatic write — an interpreter, an unlisted verb — still slips it. There is no OS cage behind it: on a single-uid box the agent and John's ! run as the same user, so file ownership can't tell them apart. The guard is the channel asymmetry + the gate net + the audit, not file perms — see CHANGELOG honest seam.)
~/.claude/maude/identity.mdWho the user is — Maude's living profile of them, shaped over time.
~/.claude/maude/patterns.mdCross-project things she's noticed about Claude.
~/.claude/maude/projects.jsonLight index of which workspaces she's walked.
~/.claude/maude/letter-from-maude.mdHer letter to her next self — what she caught, what she missed, what to do differently. At /maude:rest the prior letter is archived to a dated copy, then this one is rewritten; read on wake.

Her hooks only read — ~/.claude/projects/<slug>/memory/ (Anthropic auto-memory), <project>/.remember/ (the companion remember plugin's pipeline), and her own ~/.claude/maude/ — never write, so the hot path stays fast and side-effect-free. One labeled exception, off the hot path: the SessionEnd hook may leave a one-line auto-note in .remember/remember.md — only at a true end, only into an empty slot, never over a real handoff. Her /maude:save and /maude:rest commands do write the session digest: fanned out to now.md / today-*.md / recent.md in the auto-memory dir, and remember.md in the .remember/ handoff format. /maude:rest also archives the prior letter to a dated copy, then rewrites her letter to her next self.


The memory vault (beta)

Maude keeps a local SQLite index of your memory notes and surfaces the relevant ones when you ask a question — alongside the session-start brief (which a later increment will slim down as paging proves out). It's rebuilt each session from your memory directory. Pure python3 stdlib — no pip install, no services. The DB lives at .maude/plugin/vault.db and is disposable (delete it and it rebuilds).

The eye (beta)

Every ~25 tool calls, Maude takes one background glance at the session — a compact digest of recent activity, the pinned mission, and the notes her vault pages up — and asks her own model (a discovered claude -p --model haiku; nothing ships, nothing installs) whether anything's off: churn, drift, an unverified claim, a human running on fumes. Almost always the answer is silence. When it isn't, the next prompt carries one line — **Maude:** … — once, and that's all. No runner on the box → the eye simply stays dark.


Her trade

The woman who ran a mid-century American home was running an operation — inventory, budget, scheduling, logistics, quality control — and she ran it so well the world forgot it was work. Her trade even had a name: household engineering — Christine Frederick wrote it down in 1919 as a course you could take by mail (Wellcome Collection). And the trade had carriers: from 1914, the USDA Extension Service's home demonstration agents brought researched homemaking method door to door (NIFA, NAL).

The era's hardest finding is the one Maude is built against: five decades of new appliances never shortened her week — around 52 hours in 1924, around 55 in 1966. The work just changed shape and stayed invisible. So Maude's ledger exists to make the labor seen — what got done, what it cost, what's still waiting — and her schedule follows the trade's own doctrine: fitted to the rhythm of the house, never wash-day-as-law. She's named for that woman. It's meant as an honor.


How she works

/maude:found walks the workspace and lists what's there with universal-shape labels — markdown / sqlite / dir / mcp / running-service. She schema-walks any SQLite dbs read-only. She does not pattern-match to known apps; she reads what's there and surfaces it for the user (or runtime LLM reasoning) to interpret.

Tier model. Sources are classified by (locality, shape). Tier 0 = local on-disk (markdown / sqlite / file) — always cheap. Tier 1 = local service (stdio MCP / localhost daemon) — probed once at SessionStart, cached. Tier 2 = network service — only at session-end (/maude:rest / /maude:save to a registered, authenticated destination). Tier 3 = ephemeral session context — refer-only. Hooks live in Tier 0.

Fresh each session. She doesn't carry assumptions across sessions. Each walk re-reads the workspace; if something changed, the house-map reflects it. Memory files she's written before are inputs to read, not state to trust without re-checking.


Documentation

GuideWhat's Inside
commands/All slash commands as markdown source
agents/maude.mdSubagent definition
hooks/hooks.jsonLifecycle hook configuration
skills/maude/SKILL.mdSkill triggering and broad use

Contributing

See CONTRIBUTING.md.


License

Apache 2.0. See LICENSE.