agentsclimarketplace

Save

Skill jojoprison/mnemo/plugins/mnemo/skills/save

Persistent memory layer for Claude Code — Obsidian vault health, connection discovery, brain dump, session notes, email bridge. Five lightweight skills, CLI-first, any taxonomy.

Install
npx -y skills add jojoprison/mnemo --skill save

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use right after something worth keeping appears — you solved a tricky bug, made a non-obvious decision, hit a gotcha, or the user voiced a business rule, a pain, or how they think/decide — proactively, without being asked, so a future session doesn't relearn it. Also when the user says 'remember this', 'save this', 'запомни', 'запоминай', 'сохрани', 'сохрани в память', 'сохрани в обсидиан', 'сохрани в базу знаний', 'помни', 'отложи в память', 'в мнемо', 'сохрани принцип', 'это моя боль', 'запомни как я думаю', 'запиши мой подход', 'моё правило', or similar. Splits deep material into atomic, claim-titled notes with typed slots (decision / gotcha / principle·pain·stance) — never one blob — and routes recall to the configured Obsidian taxonomy, optional claude-mem, and Claude auto memory when appropriate; Codex memories remain generated read-only state. Actionable never-X / always-Y rules keep the existing project-instruction routing.

SKILL.md

29.6 KB, as published. Nobody here has run it

mn:save — Memory Routing Cascade

Invocation marker (both runtimes): begin your reply with the exact line 🧠 mn:save (mnemo) → running — the user-visible confirmation that this skill actually loaded. Emit it once per invocation, before any other output.

Portable paths

Resolve <mnemo-root> once to the absolute plugin root before reading bundled files or running bundled scripts. In Claude Code, use ${CLAUDE_PLUGIN_ROOT}; in Codex, derive it from this loaded SKILL.md path (skill directory → skills/ → plugin root). Replace <mnemo-root> with that quoted absolute path in every command — never execute the placeholder literally and never hunt versioned cache directories.

When another mnemo skill must run, use the runtime-native path: Claude Code invokes mn:<skill> through its Skill tool; Codex reads <mnemo-root>/skills/<skill>/SKILL.md completely and follows it with the prepared input. For user-facing explicit syntax, render /mn:<skill> in Claude Code and $mnemo:<skill> in Codex.

Save information to multiple memory backends with graceful degradation. Each backend is tried independently — if one fails, others still work.

Prerequisites & config

Obsidian is preferred but not required (skill degrades gracefully). Config at ~/.mnemo/config.json — full schema including cascade.* toggles in <mnemo-root>/references/config-schema.md.

Workflow

Step 0: Classify the Input

First — is this worth saving at all? (Especially when saving proactively, unprompted.) Save only if a future session would act differently for knowing it: a solved bug + root cause, a non-obvious decision + why, a gotcha that bit you, a durable fact, an actionable rule. Skip as a NOOP — say "nothing worth persisting here" and stop — for routine steps, anything the repo/git already records, one-off chatter, or what a future agent would re-derive trivially. Saving noise pollutes recall; a lean vault is the asset.

Never persist secrets — mask tokens / keys / passwords as <REDACTED> before writing (a note is durable and may sync).

Then determine what type of information is being saved:

TypeGoes toExample
factObsidian taxonomy_roles.fact + optional claude-mem"Heroku standard-0 has 25 auto-backups"
insightObsidian taxonomy_roles.insight + optional claude-mem"CLI-first is 70,000x cheaper because of token savings"
decisionObsidian taxonomy_roles.fact + optional claude-mem + Claude auto memory when error-preventing"We chose SCOPE over TextGrad for self-correction"
gotchaObsidian taxonomy_roles.fact + Claude auto memory + possibly CLAUDE.md"execSync with shell=true is banned in antomate"
principle / pain / stance (how the user thinks / what pains them / their quality bar — the business-logic & mental-model layer)Obsidian taxonomy_roles.insight (narrower semantic type in kind:) + optional claude-mem"the user prefers ambitious-first with honest trade-offs" · "pain: pasting a wall of prompt every session"
sourceObsidian taxonomy_roles.source + optional claude-memExternal article, tool, research finding
actionable rule.claude/rules/<domain>.md (auto-inject, path-scoped) — Step 3.5 only"After touching sign_epl.py, always gate the Kontur call on the flag"

Recall vs actionable rule — the fork this cascade turns on. A recall item (fact / insight / decision / source) answers "what / why" and is fetched on demand. An actionable rule — "never do X / always do Y" tied to specific code — must auto-surface when a future agent opens the relevant file, before it repeats the mistake. Its home is .claude/rules/ (native path-scoped auto-load, Step 3.5), not recall memory. Most saves are recall; route to .claude/rules/ only when the rule would have prevented an error by appearing at the right moment.

Routing consequence — apply this to every step below. A recall item flows through Steps 1-4 normally. An actionable rule goes to Step 3.5 only: skip Steps 1-3 (Obsidian / claude-mem / memory/ are superseded by the auto-injecting rule file — don't double-write), and Step 4 (CLAUDE.md) fires only as the fallback if Step 3.5 declined (e.g. project_rules disabled). One kind → one home.

Step 0b: Shape the note — typed slots, atomicity, one rationale

Depth comes from structure, not volume. The unit you retrieve must equal the unit you address — a well-titled atom, never a 5000-word blob. A blob is unretrievable point-precisely (you can't grab the right slice from it) and drifts straight into the auto-ingest fork mnemo's founding principle rejects (docs/design-decisions.md).

Split, don't dump. If the material carries ≥2 separable claims, create ≥2 atomic notes — plus, only if a genuine cross-note insight emerges, one insight-role synthesis linking them. Never truncate; never fuse unrelated claims into one note. "Maximally detailed" is a property of the corpus (many atoms + one narrative session note + connect links), never of a single note.

Two non-negotiables per typed note:

  • Claim-shaped title (title-as-API): a statement, not a topic — {fact_prefix}Redis fail-open keeps reads alive when cache is down, not {fact_prefix}Redis. If no single claim fits the whole note, it isn't atomic → split.
  • because / rationale in the body: the premise the claim rests on, so a future agent sees why and never silently revokes a decision whose condition it can't see.
  • Gate strength: hard for decision / actionable rule / principle·pain·stance — reject the write until both exist. Soft nudge for a plain fact (a bare fact may legitimately have no deeper because).

Route the body into the slot template for its semantic type (these are body shapes written into the same Markdown string — not new backends, scripts, or frontmatter machinery):

  • decision → one Y-statement: In the context of <X>, facing <concern>, we chose <option> over <alt>, to achieve <quality>, accepting <downside>, because <rationale>. (Carries context + choice + rejected + goal + trade-off + reason in a single atom.)
  • gotcha / business ruleGIVEN <precondition> / WHEN <action> / THEN <observable> + Because: + Fails-when: (the provoking input → wrong outcome, so the rule is grep-able by its symptom).
  • principle / pain / stance (the how-the-user-thinks / business-logic / pain layer — W4) → JTBD slots: Job: (what they're trying to get done) / Pain: (functional · emotional · social) / Done-well: (the quality bar that makes output acceptable) / Anti-goal: (what they explicitly reject). Turns taste into a checkable bar a future agent can self-audit against.
  • fact / insight → claim-title + a BLUF first line (the load-bearing statement on top — it survives context down-weighting) + evidence/links.
  • source → external material + your annotations (unchanged).

W4 notes are human-authored, not psychoanalysis. A principle/pain/stance note pins one atomic claim about how the user thinks, decides, or hurts — authored or confirmed by the user in the conversation, never the agent inventing a dossier (that would be auto-ingest by the back door, violating the human-authored principle). On a proactive (unprompted) W4 save, draft the atom and confirm the claim with the user before writing.

Record the semantic sub-type. Write kind: <decision|gotcha|principle|pain|stance> into frontmatter whenever the semantic type is narrower than its taxonomy role — this makes [kind:pain] property-searchable in /mn:ask. Plain fact/insight/source omit kind: (it would only echo the role).

Step 1: Obsidian (Primary — for the user)

Skip if: cascade.obsidian.enabled is false, or Obsidian CLI returns "Unable to connect"

Validate the role map before naming the note: its key set must be exactly fact, insight, source, session, and moc; every target must name an entry in config.taxonomy; and the functional roles must self-map as session → session and moc → moc. Then resolve fact/decision/gotcha through taxonomy_roles.fact, insight/principle/pain/stance through taxonomy_roles.insight, and source through taxonomy_roles.source, using the mapped entry's prefix and tag for the filename/frontmatter (record the narrower semantic type in kind: — Step 0b). The W4 types piggyback on the insight role exactly as decision/gotcha piggyback on factno taxonomy_roles schema change, so it works on every existing vault without re-setup. If the role map is absent and all five legacy Zettelkasten taxonomy keys exist, use the documented deterministic fallback. Otherwise stop this backend and offer setup — never infer routing from a human-facing prefix.

python3 "<mnemo-root>/scripts/safe-read.py" search <<'JSON'
{"query":"{key words}","vault":"{vault}"}
JSON

If duplicate found → ask: update existing or create new?

Create through the bundled JSON-stdin writer (both runtimes):

python3 "<mnemo-root>/scripts/vault-write.py" <<'JSON'
{"action":"create","vault":"{vault}","note":"{mapped_prefix}{descriptive title}","content":"{one JSON-escaped Markdown string containing frontmatter, body, and links}"}
JSON

The Markdown string contains type: {mapped taxonomy key}, the mapped configured tag, date/source, an optional kind: semantic sub-type and optional aliases: (Step 0b + note-quality rules), the body shaped by its typed slot, {links_section}, a mapped moc link, and useful ghost links. Serialize it as JSON data; do not interpolate it into obsidian create/append. The helper discovers the vault via argv-only CLI, then performs a contained atomic create. Backticks, quotes, and $(...) remain inert data. A conflict means another writer created the note — re-read instead of overwriting.

Note quality rules (details + tables in <mnemo-root>/references/tool-routing.md):

  • Naming: never # / . / / / .md in the title — they break wikilinks (#→heading anchor) or the CLI (.→truncation). Sanitize before create. Use or space.
  • Fact-role title = a statement, not a topic (Matuschak «title as API» / Умэсао): {fact_prefix}Redis fail-open keeps reads alive when cache is down, NOT {fact_prefix}Redis.
  • Insight-role note = non-trivial synthesis of ≥2 facts (new insight not present in either alone), not "linked two notes."
  • Insight handed off with cites: (e.g. from /mn:ask compounding): when the caller passes an insight plus a cites: source list and a pre-built {links_section}, write cites: [{sources}] into frontmatter (right after date:) and use the caller's links block verbatim instead of generating a bare hub link.
  • Body follows the typed slot for its semantic type (Step 0b) — decision→Y-statement, gotcha→GIVEN/WHEN/THEN, principle·pain·stance→JTBD, fact·insight→claim+BLUF+evidence. Depth is distributed across atoms, never concentrated in one blob.
  • aliases: are retrieval keys, not content — add EN/RU synonyms or a short name to frontmatter when a future search would plausibly reach for a different term than the title (aliases: [save redesign, редизайн save]). A polyglot vault: an English-titled note should still answer a Russian query. Add when obvious; never fabricate — a key, not authored prose.
  • Two link layers: inline with context in the body («contradicts [[X]]», «builds on [[Y]]») + {links_section} for MOC/nav. A bare link without context is noise.
  • Short project names ([[Diadoc]], [[BTS Holding]]) need a hub note — Obsidian doesn't resolve bare links via alias (by design). If [[ShortName]] is referenced and no ShortName.md exists, create it: a one-liner redirecting to the note type mapped by taxonomy_roles.moc.
  • Staleness is type-driven, not stamped here. The date you write is the review anchor — health derives review cadence from the note's type (config review.staleDays), so you don't add a review date. Exception: for a fast-rotting fact (a volatile API quirk, a "current as of" price) add an optional ttl: <days> to the frontmatter to age it faster than its type default. Don't add reviewed: — that's the snooze health/the user stamps later. See <mnemo-root>/references/config-schema.md → "Optional per-note frontmatter".
  • Load-bearing [[links]] go OUTSIDE code fences — a wikilink inside a ``` block is NOT parsed into the graph (by design), so it's silently lost to backlinks. Agents emit code blocks constantly — keep navigable links in prose. Full vault conventions (Bases-first computed indexes, schema self-policing, concurrent-edit safety): <mnemo-root>/references/vault-conventions.md.

Add to the mapped hub with an optimistic targeted insert:

python3 "<mnemo-root>/scripts/vault-write.py" <<'JSON'
{"action":"insert","vault":"{vault}","note":"{mapped hub note}","anchor":"{unique stable anchor copied from safe-read}","position":"after","content":"\n- [[{note name}]] — {why it belongs here}"}
JSON

If the anchor is missing/non-unique or the note changes during publication, the helper fails closed; re-read and retry. Never fall back to inline CLI content.

On error: Log ⚠️ Obsidian: skipped (not connected), continue to next backend.

Step 2: claude-mem (Optional Semantic Search — cross-session recall)

Skip if: cascade.claude_mem.enabled is false. This is the default in new installs because many users intentionally disable claude-mem for CPU/RAM reasons.

Use the bundled helper — it auto-detects the claude-mem version for provenance, reads dynamic values as JSON from a quoted heredoc, and sends the HTTP request without a shell. A summary containing quotes, backticks, or $(...) remains data. It also bakes in the v12.3.9 gotchas documented below:

python3 "<mnemo-root>/scripts/claude-mem-save.py" <<'JSON'
{"url":"{claude_mem_url}","type":"{type}","project":"{current project or general}","summary":"{one-line summary of what was saved}","note":"{note name if created}","vault":"{vault}"}
JSON

API field name (v12.3.9): the request body key is text, not content. Earlier versions accepted content; as of v12.3.9 the API returns {"error": "text is required and must be non-empty"} if you send content. Confirmed during v0.7.3 smoke test — verified in claude-mem source.

v12.3.9 metadata gotcha — custom fields are dropped silently. POST returns {"success": true, "id": ...} but the stored observation only persists text + API-generated fields (type, title, narrative, facts, concepts, content_hash, created_at, ...). Custom metadata.* entries (including project, obsidian_note, obsidian_vault, claude_mem_version) are not retrievable from the observation record. The project field on the stored record is forced to the calling plugin's project (claude-mem), not metadata.project.

Workaround (used above): embed the key provenance fields (note name, vault, CM version) directly into text as a bracketed tail. Losing structured filtering hurts less than losing the data entirely — full-text search still finds the provenance. Keep the metadata: {...} block in the POST anyway so recovery is automatic once upstream fixes drop-silent behavior. Track upstream: thedotmack/claude-mem — search for metadata / project override.

Why obsidian_note + obsidian_vault: once upstream restores metadata persistence, claude-mem search results can link back to the full Obsidian note. Future /mn:ask --deep will show a direct wikilink alongside the observation.

Why claude_mem_version: v11.0.1 disabled semantic-inject by default, v12.0.0 introduced the file-read gate. Tagging observations by version lets retrieval logic filter legacy entries when needed.

On error: Log ⚠️ claude-mem: skipped (port {port} not responding), continue. Do not start ChromaDB or the claude-mem worker automatically.

Step 3: Runtime-owned memory (Claude write; Codex read-only)

Skip if: cascade.memory_dir.enabled is false — or this is an actionable rule (it goes to Step 3.5; .claude/rules/ supersedes a memory/ copy, never write both).

Only consider this layer if the information prevents the coding agent from making errors in future sessions and is not an actionable rule:

  • Gotchas, commands, conventions
  • NOT business context (that's Obsidian's job)

Claude Code: write only to the active auto-memory directory already exposed by Claude. Honor ${CLAUDE_CONFIG_DIR:-~/.claude}/settings.jsonautoMemoryDirectory; otherwise use the repository-derived projects/<project>/memory/ location. If autoMemoryEnabled or CLAUDE_CODE_DISABLE_AUTO_MEMORY disables it, skip. Never write ./memory/ in the repo.

Codex: skip this write. ${CODEX_HOME:-~/.codex}/memories/ is generated state owned by Codex; it may be inspected/read for recall, but mnemo must not create, edit, append, or maintain its index manually. Obsidian is the durable user-authored save surface in Codex.

How to write — keep the index lean (autodream discipline):

Claude auto memory is two layers: topic files (the detail) + MEMORY.md (a lean index — a table | File | Read when… |, one short "Read when…" row of recall triggers per topic, ≤~200 chars). Never dump prose into MEMORY.md — a bloated index gets truncated on load and old entries become invisible.

  1. Write the detail to a topic file ({topic}.md) — create or update it.
  2. Add/refresh one thin index row in MEMORY.md pointing to it (link + "Read when…" triggers: names / IDs / PR# / domain terms). Never a paragraph.
  3. If MEMORY.md links a MEMORY-archive-index.md at the top, aged/older rows live there — add aged rows there (not the lean index) and read it when recalling old context.

The index is periodically re-slimmed by autodream (memory consolidation). Resolve that cross-project guide under ${CLAUDE_CONFIG_DIR:-~/.claude}/memory/autodream-principles.md.

On error: Log ⚠️ memory/: skipped (directory not found), continue.

Step 3.5: .claude/rules/ — actionable path-scoped rules (auto-inject)

Skip if: cascade.project_rules.enabled is false (default true).

Fires only for an actionable rule (Step 0) — never for recall items. The test: would this rule have prevented an error if it had auto-surfaced the moment the agent opened the relevant file? Yes → here. "What we did / why" → recall memory (Steps 1-3), not here.

Why .claude/rules/ and not CLAUDE.md: Claude Code natively auto-loads .claude/rules/*.md. A file with paths: frontmatter loads only when the agent touches a matching file (path-scoped, zero idle-context cost); a file without paths: loads every session (always-on). It is the granular evolution of the old "dump a rule into CLAUDE.md" branch (Step 4). Docs: https://code.claude.com/docs/en/memory.md (§ "Path-specific rules", "User-level rules"). The load trigger is paths: — not description: (that field is for humans skimming the dir; it does not affect loading).

1 — Pick the level:

  • Rule is specific to this repo (names its files, domains, deploy quirks) → project .claude/rules/ (committed in the repo).
  • Rule is generic / cross-project (a language convention, a git habit, a universal gotcha that applies in every repo) → user-global ~/.claude/rules/ (auto-applies on every project on this machine).

2 — Find or create the target file (project shown; use ~/.claude/rules/ for global):

ls .claude/rules/*.md 2>/dev/null
  • Read each file's paths: / domain. Append the rule to the file whose scope covers the code it governs (under the matching section, surgical insert).
  • No file matches by meaning → create a new <domain>.md. Don't wedge an unrelated rule into the nearest file (that's the wrong-abstraction smell at the doc level).
  • .claude/rules/ doesn't exist → create the dir and the file. A first rule bootstraps the convention; do not silently fall back to CLAUDE.md just because the folder is missing.

3 — Frontmatter for a new file:

---
paths:
  - "src/<area>/**"          # globs for the files this rule governs → path-scoped auto-load
  - "tests/<area>/**"
description: "<one line, for humans skimming .claude/rules/ — NOT a load trigger>"
---

Omit paths: only for an always-on rule (rare in a project — it costs context every session). A generic global rule usually omits paths: (it should always apply).

4 — Write it. These are plain repo / dotfiles outside the Obsidian vault → use Write/Edit, never the Obsidian CLI/MCP (no vault graph to join, and obsidian create content= would shell-expand backticks). Match the file's existing section style; append surgically, don't reformat neighbors. Verify the YAML after writing — a broken-indent paths: entry silently drops the whole file from auto-load (real incident: a 0-indent list item under paths: made the rule never load).

Codex / AGENTS.md gotcha: Codex does not read .claude/rules/ — only AGENTS.md (nested, 32 KiB hard limit, silent truncate past it). If the project has an assemble-AGENTS build-step (rules → AGENTS.md), the rule reaches Codex on rebuild — run it and confirm wc -c AGENTS.md stays < 32768. No build-step + Codex devs on the repo → also surface the critical rule into AGENTS.md by hand.

On error / not applicable: Log ⚠️ .claude/rules: skipped (recall item / cascade.project_rules disabled), continue.

Step 4: CLAUDE.md (Only critical error-preventing rules)

Skip if: cascade.claude_md.enabled is false (default) — or the item is an actionable rule already handled by Step 3.5 (cascade.project_rules.enabled true). This branch is the fallback, reached only when Step 3.5 declined (e.g. project_rules disabled).

Only write here if the rule is:

  • 1-2 lines max
  • Violation would cause a real error or bad behavior
  • Not already covered by Obsidian or memory/

This is almost never needed. Most things go to Obsidian + claude-mem. For any rule tied to code, prefer Step 3.5 (.claude/rules/) — CLAUDE.md is the fallback only when you genuinely can't use a rules file (and Step 3.5 already creates the dir/file when missing, so that's rare).

Step 5: Report

💾 Memory saved:

Content: "{short summary}"
Type: {semantic type} → taxonomy `{mapped type key}`

Backends:
  1. Obsidian   ✅ → "{mapped prefix}{title}" in {mapped hub name}
  2. claude-mem ⏭  skipped (disabled)
  3. runtime memory ⏭  {Claude: skipped/not error-preventing | Codex: read-only generated state}
  3.5 .claude/rules ⏭  skipped (recall item, not an actionable rule)
  4. CLAUDE.md  ⏭  skipped (not critical rule)

For an actionable rule, the rule branch is the only write (one kind → one home):

💾 Memory saved:

Content: "after touching sign_epl.py, gate the Kontur call on the flag"
Type: actionable rule

Backends:
  1. Obsidian   ⏭  skipped (rule, not recall)
  2. claude-mem ⏭  skipped (rule, not recall)
  3. runtime memory ⏭  skipped (rule → .claude/rules supersedes a memory copy)
  3.5 .claude/rules ✅ → .claude/rules/te5-frontend.md (path-scoped) — appended
  4. CLAUDE.md  ⏭  skipped (Step 3.5 handled it)

Or with failures:

💾 Memory saved (partial):

  1. Obsidian  ⚠️ skipped (not connected — restart Obsidian)
  2. claude-mem ⏭  skipped (disabled)
  3. Claude auto memory ✅ → {active auto-memory directory}/topic.md updated

⚠️ Restart Obsidian, then run this `save` skill again (`/mn:save` in Claude Code, `$mnemo:save` in Codex) to complete sync.

After a new note is created (not a plain append/update, not an actionable-rule write), offer to run the canonical connect skill using the current runtime's explicit syntax: "New note created — run /mn:connect (Claude Code) or $mnemo:connect (Codex) to surface related notes and cross-link it?" After an explicit user save, wait for their choice. If this was a proactive save mid-task, delegate to connect immediately to surface suggestions; connect still never applies links without confirmation. A fresh note that never gets connected becomes an orphan; this closes the save→connect loop without changing the original workflow.

Decision Matrix

Information typeObsidianclaude-memClaude auto memoryCodex generated memory.claude/rules/CLAUDE.md
Fact (atomic)✅ mapped fact roleOptionalread-only
Insight (synthesized)✅ mapped insight roleOptionalread-only
External source✅ mapped source roleOptionalread-only
Decision✅ mapped fact roleOptional✅ if prevents errorsread-only
Principle / pain / stance (how-the-user-thinks, W4)✅ mapped insight role (kind: set)Optionalread-only
Gotcha✅ mapped fact roleread-only❌ (path-scoped + code-tied → classify as rule, row below)rare
Command/convention✅ mapped fact roleread-only
Actionable path-scoped ruleread-onlyprimary⚠️ fallback only

Gotchas

Common failures in <mnemo-root>/references/gotchas.md. Tool-routing rationale in <mnemo-root>/references/tool-routing.md. Skill-specific rules:

  • Graceful degradation is the point — never fail completely. If Obsidian IPC is hung, skip it and save to enabled fallback backends. The user can retry when Obsidian recovers.
  • Don't duplicate Obsidian content in Claude auto memory — different audiences. Obsidian is for the user (cite-able, searchable in vault); Claude auto memory is only for error prevention. Codex memory is never a manual write target.
  • claude-mem is optional — many users won't have it running on :37777. Skip silently, don't warn.
  • CLAUDE.md is almost never written to — only 1-2 line rules that prevent actual errors. Target: <120 lines total to preserve prompt budget.
  • Recall vs actionable rule is the routing fork (Step 3.5) — recall ("what / why") is fetched on demand; an actionable rule ("never X / always Y" tied to code) must auto-surface when the agent opens the file. Misrouting a rule into recall = it never fires when it matters. Misrouting recall into .claude/rules/ = idle context bloat. When unsure, ask "would this have prevented an error by appearing at the right file?"
  • .claude/rules/ ≠ CLAUDE.md — native path-scoped auto-load. paths: is the load trigger (not description:); no paths: = always-on. A new rule creates the <domain>.md (and the dir) when none matches — don't wedge it into an unrelated file. Verify the YAML: a broken-indent paths: entry silently drops the whole file from loading.
  • .claude/rules/ files live outside the vault — like runtime memory files, never [[wikilink]] them and never write them via the Obsidian CLI/writer. Plain Write/Edit.
  • Codex is blind to .claude/rules/ — it reads only AGENTS.md (nested, 32 KiB silent-truncate). For a repo with Codex devs, route the critical rule into the AGENTS.md build-step (or by hand) too, and keep wc -c AGENTS.md < 32768.
  • Depth = structure, not volume (Step 0b) — split deep material into atomic, claim-titled notes with typed slots; never one exhaustive blob (unretrievable point-precisely + drifts into the rejected auto-ingest fork). Every typed note needs a claim title + because (hard-gated for decision / actionable rule / principle·pain·stance). principle/pain/stance capture the user's mental model only as user-authored/confirmed atoms — never an agent-invented dossier.
  • Always check duplicates before creating Obsidian notes — clobbering a note silently is worse than any write latency.
  • Ghost notes generously — wrap entities in [[wikilinks]] even when the target doesn't exist yet. Enables future entity discovery.
  • Never [[wikilink]] a runtime-memory file — use inline code — runtime memory and project files (CLAUDE.md, AGENTS.md) live outside the Obsidian vault graph. A wikilink to them becomes a permanent unresolved ghost. If a real vault counterpart exists, link that mapped taxonomy note instead.
  • Mapped hub link mandatory for every typed Obsidian note.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.