Try the memory thesis without installing the workflow layer
Evaluating whether recall is any good used to mean accepting the whole library first: Serena, 15 subagents, four team commands, and the deliberation skill, behind eight prompts. metalmind init --core installs recall, scribe, the stamped CLAUDE.md block, the rules and uninstall - 10 files against 40, zero subagents against 15 - and stops asking about what it is not installing. Re-run init without the flag to add the rest; the copy is idempotent, so nothing is lost by starting small. --core narrows defaults rather than overriding you: pass --teams or --serena alongside it and you get those, and an explicit --teams brings the subagents its commands dispatch instead of leaving a surface that looks installed and fails on first use.
The Qdrant + Ollama backend is gone, and 50k proved it could be
sqlite-vec + fastembed became the default in v0.5.0 and the escape hatch went unused for ten minors while charging a qdrant-client dependency, two backend implementations, 142 lines of Docker setup, a Docker prerequisite, and three doctor probes. Removing it was gated on one unanswered question: does in-process retrieval hold at 50,000 notes? It does - 95% hit@1, 100% hit@3, zero misses at k=5, 617ms p95, no server and no daemon. Getting that answer meant fixing the bench first, which had been scoring correct answers as misses: it froze the gold set at seed time, so once the corpus grew to include unlabelled comments from the same thread, a right answer outranked a labelled one and reported 25% hit@1 while 19 of 20 top hits were on the correct story. METALMIND_BACKEND=legacy now raises instead of silently re-embedding your vault with a different model than the index was built with.
burn iron returns, and the graphify hook actually goes
0.15.0 retired burn iron along with the graphify dependency, but those were not the same decision - the dependency had to go, the capability did not. It is rebuilt on metalmind's own symbol extractor: where is this symbol declared, in one repo or across a forge, with no index and no external tool. Callers and call paths still need a parser, so the output says so and points at codegraph instead of pretending. Also: 0.15.0 delegated hook removal to graphify claude uninstall, which is project-scoped and never touches ~/.claude/settings.json - so the user-scope PreToolUse hook survived the upgrade and kept firing against a graph file whose generator was gone, while doctor reported graphify-residue none because it never inspected hooks. metalmind now strips that hook itself, the residue check reads settings.json, and the repair runs automatically on the next ordinary command rather than requiring init. Also: init stops discarding config it does not own (registered forge groups, verbose, embeddings, recall all survive a re-run) and backs up any file in ~/.claude/rules/ you had edited before replacing it. Plus: the supersede integrity check treated every frontmatter value as a note pointer, so a note that said supersedes: v1 (Gateway+Relay), v2 (bookings share_sessions) reported an unresolvable pointer with no way to declare it prose - permanently red, on every machine the vault reached. Values are now classified by shape: anything with whitespace, commas or brackets was never a stem, so it is surfaced as a notice with the fix rather than a failure. Stem-shaped pointers that do not resolve still fail, and still outrank prose in the report. scribe supersede also stops demanding --force to overwrite a prose value, since that was never a link to protect.
codegraph owns the inside of a repo; forge owns what happens between them
burn bronze, burn iron, burn pewter and the graphify dependency are gone. Within-repo code-graph work belongs to codegraph, which is local, MIT-licensed and does it better - metalmind installs alongside it rather than wrapping it. Forge, the one part that genuinely depended on graphify, now extracts symbols from your source during the walk that already produced route edges, so name-match and route-match edges both survive with no external tool and no indexing step. Querying moves to metalmind forge query. The retired commands print the codegraph equivalent instead of failing as unknown, config migrates itself, and doctor names any graphify left on your machine.
doctor surfaces the Intent skills sitting unused in your dependencies
Packages can ship SKILL.md guidance that travels with them through the registry. The new intent-skills check asks each forge-registered repo's own intent binary how many its dependencies expose, and names them. Informational by design: it never fails, never changes doctor's exit code, installs nothing, and deliberately does not copy skills into the vault - their value is that they stay versioned with the package, so a vault copy would manufacture the staleness Intent exists to prevent.
scribe --code and auto-memory naming get their rough edges filed off
scribe update --code blocked on stdin without a body, so re-stamping refs meant piping a dummy body, and --code "" could never clear refs. Auto-memory filenames joined project and topic with a single hyphen, so project a + topic b-c collided with a-b + c; the separator is now a double hyphen and notes imported under the old name are renamed rather than duplicated. Ingest conflicts now name the source file as well as the vault note.
Code refs tell a definition from a call site
The definition pattern and the loose fallback ran as one ripgrep call, so a leftover call site or a mock was indistinguishable from a real definition and the exact staleness the feature exists to catch reported a clean ok. They now run as separate stages, with reference-only matches surfaced by doctor as worth checking rather than as failures - and func, record, object, and module join the definition keywords, since Go definitions had been reaching ok through the fallback. Also: tap copper --json emits structured code_refs per hit, repeated lookups are memoised per run, notes sharing a filename stem no longer vanish from the checks, and imported auto-memory carries no username in source_path.
Frontmatter parsed with a real YAML parser
metalmind already shipped the yaml package and used it only for OpenAPI specs, while ten files hand-rolled note frontmatter parsing - the source of a cluster of bugs. Quoted values kept their quotes, Obsidian's block-sequence lists were invisible, a value on the line below its key was missed, a multi-line block scalar could leak what looked like a nested key, and a fixed 2 KB read dropped the frontmatter of notes with many tags or links. One shared reader now backs scribe, code refs, doctor, ingest, and recall. The write path is untouched, so no existing note is reformatted.
Code-aware memory validation and auto-memory ingest
Notes can carry code: ["repo#symbol"] refs; tap copper --verify-code and a new doctor check flag refs whose code no longer exists in your forge-registered repos, resolved by definition-shaped ripgrep with per-repo and per-run time caps. metalmind ingest auto-memory pulls Claude Code native auto-memory topic files into the vault as Memory/ notes with hash-based provenance - idempotent, and it reports a conflict rather than clobbering a note you edited. Also hardens vault containment against symlinks arriving via git sync, quotes control characters in frontmatter values, and stops ingest from dropping frontmatter keys it does not own.
Temporal supersedes: decisions replace each other without deleting history
scribe supersede <old> <new> marks a note as replaced by its successor via frontmatter (status: superseded, superseded_by, supersedes). Recall downweights superseded notes 0.4x in fusion - stacking with folder penalties, surviving archive, reaching the rerank path - and every hit from one carries superseded_by so agents land on current truth. Nothing is hidden: history re-ranks below its successor with a signpost. Also fixes stamp to restart the watcher after a vault-rag reinstall, so recall-layer changes actually take effect on upgrade instead of waiting for an unrelated restart.
Adaptive recall fusion, folder penalties, and in-place note edits
Recall fusion weights now adapt per query: exact-match tokens (UUIDs, numeric IDs, ticket IDs, hostnames, emails) raise the keyword-leg weight, since BM25 beats embeddings on literal identifiers. Fused scores are folder-weighted - Archive/ 0.4x, Inbox/ 0.7x - so stale notes re-rank below in-flight work without being excluded. scribe patch gains --find/--replace for targeted in-place edits (frontmatter protected, ambiguity resolved via --occurrence). tap copper gains --semantic-only/--keyword-only, previously documented but unimplemented. stamp now refreshes installed output styles from bundled assets, and release-check gates docs version claims against package.json.
Shell-alias install reports what actually happened
stamp printed "sourced in 0 shell rc file(s)" after a successful re-run because the append helper returned the same false for "already present" and "file missing", and the wizard hardcoded .zshrc in its success line even on bash-only machines. The helper now returns a three-way outcome and both commands name the actual files touched. templates/zsh/ renamed to templates/shell/ since the file has been shell-agnostic since bash support landed.
metalmind duralumin: vault sync with note-loss guards
One command pulls with rebase and autostash, stages, checks the change set, commits, pushes, and then asks git whether the remote actually advanced instead of trusting the push exit code. It refuses three shapes: a deleted note whose content survives nowhere in the commit, a commit that only removes notes, and entries left unstaged after git add -A. Matching is by blob SHA, so undetected renames pass while genuine deletions do not. Born from a real incident: the vault lost 19 notes to an archive move that staged its deletions and dropped its additions. --dry-run, --no-push, and --force available; a refusal resets the index cleanly.
stamp --no-prompt works headless
Commander parses --no-prompt as a negation (opts.prompt = false) but both call sites read the nonexistent opts.noPrompt, so the documented CI flag was a silent no-op that fell through to a TTY-requiring multi-select and crashed with uv_tty_init EINVAL. Now wired correctly, and promptHosts falls back to the previously-chosen host set when stdin is not a TTY.
Recall no longer surfaces trashed notes
scribe delete moves a note into .trash/, and the live watcher indexed that move as a fresh note, letting trashed notes outrank their replacements. Bulk indexer, watcher, and incremental reindex now share one SKIP_DIRS set, and reindex treats skip-dir paths as delete-only so polluted entries self-heal. Also bumps vault-rag to 0.3.1 so the 0.9.3 cache fix actually reaches installed machines on the next stamp.
Scribe path-resolution fixes and a durable model cache
scribe rename with a bare-slug destination silently moved notes to the vault root without .md; plan slugs that already carried a date prefix got double-dated; and macOS periodically purged the fastembed model cache from the system temp dir, breaking recall until the half-cache was cleared by hand. The cache now lives at ~/.metalmind/cache/fastembed/ where temp cleanup cannot reach it.
Bundled agents bumped to Opus 4.8
All 15 bundled agent templates pin an explicit model, and the pin had fallen a version behind. Refreshed from claude-opus-4-7[1m] to claude-opus-4-8[1m]; re-stamp propagates the new pin. No behavioural change.
--compact recall: 74% fewer output tokens, zero retrieval drift
New --compact flag on tap copper / recall renders each hit as a lean envelope (score, path, heading, snippet) instead of full per-hit JSON; the path is the recovery handle for scribe show. Measured at roughly 74% fewer recall-output tokens on a real vault with the returned file set byte-identical between modes, gated by the new bench/compact-v0/ harness. Session stamps now steer agents to compact-by-default; the CLI default stays verbose for scripts.
Cursor as the third metalmind host
metalmind init auto-detects ~/.cursor and stamps it alongside Claude Code and Codex CLI; --host gains cursor and all. Recall rides on the metalmind-recall skill because Cursor 3.1.15 drops sessionStart additional context (staff-confirmed bug); a correct hook ships latent and activates when Cursor fixes it. Also installs 15 subagents, three skills, and opt-in --with-mcp. doctor --deep reports Cursor health; uninstall strips the footprint. 440 tests pass.
Colons in note titles no longer break frontmatter
A title like "Topic: subtitle" was interpolated raw into the YAML title field, producing malformed frontmatter that Obsidian, Dataview, and scribe show all failed to parse, invisibly, because the filename slug was already sanitised. Both frontmatter writers now route scalars through a yamlScalar helper that double-quotes any value carrying a YAML indicator character.
Persona-first output styles; terse renamed telegraph
Rule-list styles drift under load because they compete with the content prior; persona prompts swap the distribution wholesale and stick. Both bundled styles now open with an identity (Marsh the Steel Inquisitor; the Telegraph operator for whom every word costs money) with the rules as supporting material. stamp migrates a legacy terse.md in place, frontmatter rewritten, body preserved.
Per-turn output-style re-anchor hook
The SessionStart anchor from 0.8.10 handles fresh sessions, but styles still faded on long sessions. A new UserPromptSubmit hook emits a ~25-token reminder every turn, keeping the active style at the top of attention. Claude Code only; independent settings entry so either hook can be disabled alone.
scribe create examples corrected in skill and cookbook
Follow-up to 0.8.11: scribe create takes a plain title plus --kind, never a kind:slug argument; that shortcut only addresses existing notes (update, patch, gold, delete, show, rename). The writing-vault-notes skill and cookbook now state the distinction explicitly.
Wikilink guidance is plain-stem only
The skill and cookbook told agents to write [[kind:slug]] wikilinks. Obsidian has no kind: resolver and : is an illegal filename character, so every such link was broken by construction. Guidance is now plain stems only ([[cache-fingerprints]]), which resolve vault-wide and survive archives.
Output styles stop drifting after /compact
Claude Code loads a style body into the system prompt once at session start; the section then loses weight against accumulating context. A new SessionStart hook re-anchors the active style body as additionalContext every session, and marsh / terse skill bundles add phrase-match self-triggering ("be brief", "marsh mode") for mid-session activation.
Shipped rules trimmed under the 12k cap; Obsidian is optional, says so
The bundled rules/ set carried ~14k chars across 7 files, over the recommended 12k combined limit that Opus 4.7 punishes more literally than 4.6 did. principles.md is cut to six load-bearing sections and tool-philosophy.md is deleted, including from existing installs on next stamp. Fourteen call sites stopped implying Obsidian is a runtime dependency: the vault is plain markdown and Obsidian is one optional viewer.
Claude and Codex managed blocks share one source of truth
The two host block templates were maintained as parallel files and had drifted: the Codex variant silently omitted classic aliases, --dry-run, and the entire Forge paragraph. Both now reduce to a shared partial include, with a regression test that fails if either ever holds inline body content again. Shipped rules also stop naming the maintainer’s private tools and scope JS/TS-only guidance under explicit subsections.
Watcher unit crash-looped on every fresh install
The launchd/systemd unit invoked uv tool run --from metalmind-vault-rag, which resolves against PyPI where the package has never been published, so the watcher exited 1 on a 10-second restart throttle and recall silently fell back to a broken stdio path while pulse reported all systems nominal. Units now invoke the entry-point shim uv tool install already creates at ~/.local/bin/. A new regression test reads the real bundled templates instead of synthetic ones.
metalmind stamp self-heals broken output-style frontmatter
v0.8.3 fixed fresh installs but the installer (output-style.ts:122 - if !existsSync) skipped the file on upgrade - so every v0.8.0-v0.8.2 user kept the broken name: Marsh stamp and silent default voice through any number of metalmind stamp re-runs. installOutputStyle now detects the case-mismatched twin pattern (on-disk name differs from choice only by case AND body is byte-equal to the bundled asset) and overwrites from the asset. User-edited bodies (case-twin name but diverged body) are left alone. Five tests cover heal-fires / skips-on-edit / skips-on-unrelated-name / skips-when-correct / terse-twin. No rm step required to recover.
Bundled output styles silently inactive on fresh install
Claude Code matches settings.outputStyle against the name: frontmatter case-sensitively. The CLI wrote settings.outputStyle = "marsh" (lowercase) but the bundled cli/assets/marsh.md shipped with name: Marsh (capitalized) - so on every fresh install the file landed, the setting pointed at it, the file looked correct, and the style never applied. Same for terse. Caught only because the user had a pre-existing hand-authored lowercase copy. Fixed by lowercasing the asset name field and the legacy-migration write path. Bonus: dropped keep-coding-instructions: true from both shipped frontmatters - not a recognized output-style field.
metalmind gold rewrites wikilinks across the vault on archive
Same shape as scribe rename: when you archive a note, [[wikilinks]] in every other note that references it get rewritten to the new Archive/ path. Closes the v0.8.1 gotcha where archiving the two Codex plans left dangling links scattered across the MOC. Basename-only wikilinks survive unchanged. Plus: README anti-personas section dropped (was the same fabricated content we removed from the site in v0.7.x); releases page caught up to v0.8.x.
Three v0.8.0 follow-ups cleared
(1) doctor codex-mcp check no longer misattributes 5s timeouts as "binary not on PATH" - disambiguated via a `which codex` probe first. (2) synod + writing-vault-notes skill bundles extracted to cli/templates/.shared/skills/ - drift impossible by construction. (3) New doctor codex-agents-mirror check warns when ~/.agents/skills/ holds stale broken copies. No template-content changes, no re-stamp required for v0.8.0 users.
Codex CLI as a first-class metalmind host
metalmind init --host codex (or via the new multi-select prompt) stamps Codex with the same recall-first behaviour Claude Code gets. Seven artifacts: AGENTS.md sentinel block, SessionStart hook (reuses CC hook script verbatim - Codex JSON shape is identical), [sandbox_workspace_write] network_access=true, ~/.codex/rules/metalmind.rules pre-approving the metalmind command surface, three skills (writing-vault-notes, synod, save), opt-in --with-mcp. /save body extracted to .shared partial; CC slash-command + Codex skill source from one body - drift impossible by construction.
Repositioned as the Claude Code standard library
The module set at this release - memory, code intelligence, daily workflow, deliberation, desktop integration, health - shares state through one vault, one CLI, one stamped CLAUDE.md rule. Vault sync joined them in 0.10.0. Memory stays the headline; the rest is the moat. New site, new comparison-matrix rows, new Architecture + Cookbook docs.
Vault CLAUDE.md aligned with global block
Closed four contradictions between the vault stamped block and the global one (folder list, write contract, raw-Write rule, MOC location).
Stamped rules no longer contradict the CLI contract
Scribe daily-date guard (Fixed + Breaking) - every mutating scribe verb refuses non-today daily writes without --date. Plus eight stamped-rule contradictions closed across CLAUDE.md.block.template, save.md, and writing-vault-notes/SKILL.md.
Synod skill + metalmind synod command
A 7-persona deliberative council debate. Each persona spawns as a parallel subagent, the main agent synthesises a structured verdict (position, confidence %, 3 risks, 5 next steps, minority report).
graphify no longer pollutes ~/CLAUDE.md
graphify claude install was running with cwd=$HOME, dropping a graphify stamp at ~/CLAUDE.md that injected unrelated instructions into every session under $HOME. Now spawns from a temp directory; legacy stale stamps are stripped on every init.