session-notes — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited session-notes (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Create a human-readable session summary note in Obsidian after significant work.
Obsidian must be open. Config at ~/.mnemo/config.json — reads vault, taxonomy.session, links_section, handoff_note. Schema in references/config-schema.md.
Tool-routing (MCP for writes, CLI for reads/search) in references/tool-routing.md. Frontmatter template in assets/session-template.md.
/mn:sessionAnalyze the conversation: what was done, key decisions, commits/PRs created, findings.
Derive a planned filename: {session_prefix}{YYYY-MM-DD} {short descriptive topic}. Topic should be specific enough to disambiguate from other sessions the same day (include PR number, Linear ticket, branch name, or primary keyword).
Naming: the topic must NOT contain #, ., or / — they break wikilinks (#→heading anchor) or the CLI (.→truncation). Write PR 387, not PR #387. See references/tool-routing.md (naming rules).
Run Level 1 and Level 2 in parallel — single assistant message with two Bash tool uses. ~185ms total instead of ~370ms sequential.
Level 1 — exact filename:
obsidian read file="{planned-filename}" vault="{vault}" 2>/dev/null | head -5If the read returns content → a note with this EXACT filename already exists. Do NOT silently skip and do NOT auto-overwrite. Offer append / overwrite / rename, leading with append/continuation. To append, use mcp__obsidian__insert (at the file's last line) or mcp__obsidian__str_replace to add a ## part 2 / ## continuation section — NOT mcp__obsidian__create (it only creates new files and will fail or clobber an existing one). Overwrite only if the user is clearly regenerating the same session.
Level 2 — related same-day sessions (informational only):
obsidian search query="{session_prefix}{YYYY-MM-DD}" vault="{vault}"These are NOT duplicates — same day, different topics. Doing many sessions in one day is normal: each distinct topic gets its OWN note. A Level-2 same-day match is context, NOT a reason to skip creation or to assume the note already exists — that mistake silently loses sessions. Show the list to the user so they can:
## Связи / ## LinksDo not block creation on Level 2 matches — they're context, not conflicts.
Always use `mcp__obsidian__create` for creation. Never CLI with inline content=.
First, read the template (provides the exact structure to follow):
cat "${CLAUDE_PLUGIN_ROOT}/assets/session-template.md" 2>/dev/null \
|| cat "$(dirname "$0")/../../assets/session-template.md"Then create the note, filling the template placeholders ({Session Title}, {YYYY-MM-DD}, {project}, etc.) with the current session's context:
mcp__obsidian__create(
path: "{planned-filename}.md",
file_text: "<template with placeholders filled in>"
)Where {session_prefix} comes from config.taxonomy.session.prefix, {links_section} from config.links_section, and {CLAUDE_SESSION_ID} from the environment (empty string if not available).
Why MCP here: frontmatter and body may contain any markdown — code blocks with backticks, $(...) samples, shell snippets. MCP passes file_text as a JSON parameter; no shell involved.
Read MOC (CLI — safe, read-only):
obsidian read file="{MOC name}" vault="{vault}"Check if the new session note is listed.
If missing — append link (MCP preferred):
mcp__obsidian__str_replace(
path: "{MOC name}.md",
old_str: "{some stable anchor line near the session list}",
new_str: "{same anchor}\n- [[{session note name}]]"
)Alternatively, if the MOC has a predictable append point, use mcp__obsidian__insert with a line number.
CLI fallback (only if link text has no backticks/`$()`): obsidian append file="{MOC}" content="- [[{name}]]" — a plain wikilink is safe, but prefer MCP for consistency.
Read handoff (CLI — safe):
obsidian read file="{handoff_note}" vault="{vault}"Update with MCP `str_replace` — targeted, not blind append:
mcp__obsidian__str_replace(
path: "{handoff_note}.md",
old_str: "{old section content}",
new_str: "{updated section content}"
)If handoff note doesn't exist, create it via mcp__obsidian__create (same structure as initial-setup Step 6).
obsidian orphans vault="{vault}"If the newly created note appears in orphans, it means no ## Связи links or the MOC didn't get updated.
⚠️ `obsidian orphans` caches & lags writes 1-5s — a note created moments ago via MCP may show as orphan falsely. If it appears right after creation, wait 2-3s and re-run, or verify authoritatively via obsidian eval (metadataCache.resolvedLinks/unresolvedLinks). See references/gotchas.md.
Output summary:
[[wikilinks]]Common failures (IPC hung, shell injection) in references/gotchas.md. Skill-specific rules:
path (not name), file_text (not content). Path is relative to vault root, include .md extension.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.