Skip to content

v4.0.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 07:22

The kit becomes vkm-kit: one plug-and-play efficiency suite for Claude Code —
persistent vault memory + token-saver + local usage doctor + spec-builder. The
repo is now Vahlame/create-vkm-kit; the installer package is
@vkmikc/create-vkm-kit (bins create-vkm-kit and vkm), and the old
@vkmikc/create-obsidian-memory name lives on as a forwarding shim — see the
migration notes in ADR-0041/0050. Machine identifiers your installs depend on
are FROZEN: the MCP server key obsidian-memory-hybrid, the obsidian-memoryd
daemon, and BASIC_MEMORY_HOME. Managed blocks and hook files written by 3.x
are recognized and migrated in place on the next install (dual-read markers,
vkm-kit:start/end sentinels, VKM_VAULT env accepted alongside the legacy
names).

Changed

  • Rename (ADR-0041): packages/create-obsidian-memory
    packages/create-vkm-kit; ownership marker vkm-kit (legacy
    create-obsidian-memory still recognized); managed-block sentinels
    <!-- vkm-kit:start/end --> with in-place migration of legacy blocks
    (test-pinned); VKM_VAULT accepted before BASIC_MEMORY_HOME /
    OBSIDIAN_MEMORY_VAULT; release workflow publishes the renamed installer
    plus the shim.

Security

  • RAG-passthrough MCP tools no longer accept a caller-supplied vault path.
    vault_hybrid_search, vault_fts_search, vault_fts_index, vault_complete,
    vault_relations, vault_observations, vault_kg_suggest,
    memory_extract_candidates, vault_audit, and vault_memory_report exposed
    an optional vault parameter with no validation against the configured
    default — a prompt-injected note could coerce an agent into pointing one of
    these tools at an arbitrary directory on disk, indexing and searching its
    .md files (a cross-directory read oracle) and creating a
    .obsidian-memory-rag/ sidecar there. Removed the parameter from all 10
    tool schemas, matching the posture the filesystem tools (vault_read_file,
    vault_write_file, vault_edit_file, vault_list_directory) already had.
    See ADR-0040.

Added

  • vkm-spec package (ADR-0046/0047/0048) — the spec-builder pipeline: a one-line
    idea + vault context (one assembleContext call) compiles into an editable
    <orchestration_package> XML prompt, optionally enriched by a LOCAL Ollama
    draft (phi4-mini:3.8b-q4_K_M, /api/chat with format=<JSON schema>
    constrained decoding, fetch-only client, typed failures) — then reviewed by
    the human (GUI on 127.0.0.1:4923 with an SSE draft stream and a visible
    ollama/fallback source badge, or vkm-spec CLI with $EDITOR review) and
    pasted into Claude Code / Claude web / any AI. The deterministic fallback is
    structural: buildSpec always compiles a working prompt and the LLM draft
    only overwrites fields on success — pinned by a degradation-gate test (Ollama
    down → SSE error frame still carries a working XML). The installer can
    auto-provision Ollama + the model under explicit --full or --ollama
    (winget silent on Windows, ~2.3GB pull, best-effort — never curl|sh, never
    a surprise download on a bare install; --no-ollama opts out).

  • vkm skills + subagent template (ADR-0049)/vkm-discipline (execution
    contract: same functionality and quality in fewer readable lines — density,
    never reduced scope; vault-first context via one assemble_context call;
    terse output; nothing is "done" without executed evidence) and /vkm-spec
    (turn a one-line idea into a precise, context-grounded spec in-session — no
    local LLM in the synchronous path) installed into ~/.claude/skills/, plus
    the vkm-implementer subagent template in ~/.claude/agents/. All
    hash-tracked (--skills / --agents toggles; user-modified files survive
    uninstall), with a lint gate keeping every skill description ≤300 chars. The
    managed rules block gains one "Executable discipline (vkm)" bullet (ES/EN,
    within existing budgets; AGENTS.md + install docs re-synced — drift gates
    green).

  • assemble_context MCP tool (ADR-0045) — one call returns a budgeted context
    bundle for a task (typed [decision]s from the project note, non-decision
    observations + relevant cross-note passages, #stack facts, and a raw-note
    fallback excerpt when a project has no typed decisions yet), replacing the
    3-6 discrete search/read round-trips an agent would otherwise chain. Engine
    relocated from the prompt-compiler's context-search.mjs into
    obsidian-memory-mcp/src/context-assemble.mjs (parallel json-hybrid-search --graph + two json-observations passes over the same Python bridge).
    Honors the security posture of every RAG tool: no wire-level vault param
    (env-resolved only, pinned by test), untrusted-data _trust envelope with
    injection flagging, and a budget_chars cap (default 6000) that trims
    passages-first so decisions survive longest. Measured and CI-locked by the
    new bench-assemble gate (--assert-savings 0.60 --assert-answered 0.90):
    on the labelled fixture, median 68% fewer wire tokens than the naive
    multi-call pattern at 100% completeness (10,867 vs 30,816 tokens aggregate;
    cross-cutting queries save an honest 45%, project tasks 68% — and the naive
    arm pays no discovery cost, so these are floors).

  • vkm-doctor package + local telemetry (ADR-0044) — a zero-dependency local
    OTLP/HTTP JSON sink (vkm-otel-sink, 127.0.0.1:4319 → NDJSON rollups in
    ~/.vkm/telemetry/, 90-day prune, lockfile singleton, tolerant parser that
    archives unknown metric shapes instead of dropping them) plus a vkm-doctor
    CLI that reports token usage per day/model/type, the cache-hit ratio, cost,
    and a "broken cache" diagnosis (high input volume with near-zero cacheRead).
    The installer wires Claude Code's OTEL export to the sink (managed env
    block; --no-telemetry opts out) and a SessionStart hook spawns the sink
    when it isn't running — no OS service. Local only: nothing leaves the
    machine. Transcript scanning exists only as a clearly-labeled
    transcript-estimate fallback (the JSONL format is officially unstable).

  • Token-saver module (ADR-0043) in create-obsidian-memory — on by default for
    Claude Code installs (--no-token-saver / --no-terse-style opt out;
    VKM_TOKEN_SAVER=0 is a runtime kill switch). Three pieces, all reconciled
    symmetrically and fully reversed by --uninstall: (1) a PostToolUse hook
    (matcher Bash) that compacts noisy shell output before it enters context —
    ANSI stripped, \r progress repaints reduced to their final frame, runs of
    identical lines collapsed, >200-line logs windowed to head+tail — while a
    hard, test-gated guarantee keeps every error/warn/fail/exit-code line and the
    final lines verbatim (≥30% reduction on the noisy CI fixture, zero
    diagnostic loss); (2) a PostToolUse hook (matcher mcp__.*) that
    re-serializes pretty-printed JSON tool results into compact form
    (whitespace-only — parsed data, including the _trust envelope, is
    byte-identical after JSON.parse); (3) permissions.deny read rules for
    token-hungry artifacts (node_modules/**, **/dist/**, lockfiles) plus the
    vkm-terse output style (keep-coding-instructions: true), installed
    hash-tracked and activated via the outputStyle setting.

  • Shared settings-write infrastructure (settings-io.mjs, settings-writers.mjs,
    asset-install.mjs) in create-obsidian-memory
    — Phase 0 groundwork for the
    vkm-kit efficiency-suite train. The safe ~/.claude/settings.json idiom
    (read→BOM-strip→parse with invalid-JSON backup, pure managed-hook merge/remove
    deduped by filename stem, JSON sanity parse, restricted backups, atomic
    tmp+rename writes, ownership-marker checks) is extracted out of
    claude-native-memory.mjs into settings-io.mjs — behavior unchanged, existing
    suite as the refactor guard — and joined by new pure writers for the sections
    upcoming modules manage (env, permissions.deny/allow, outputStyle;
    removal only reverses values still provably ours) plus a managed-asset
    installer that tracks installed template files by SHA-256 in a
    ~/.claude/vkm-kit.assets.json sidecar so uninstall deletes only unmodified
    files.

  • Cross-process lock for the Go daemon's git-sync. Two obsidian-memoryd
    instances (or a daemon plus a manual sync once/git operation) pointed at
    the same vault could previously race add/commit/pull/push against
    the same working tree. See ADR-0040.

  • create-obsidian-memory --uninstall. Fully reverses this kit's
    Claude Code integration (hook entries, autoMemoryEnabled override, and the
    hook script files it owns) without touching a user's own unrelated hooks or
    same-named files. Turning an enforcement flag off on a re-run
    (--no-effort-gate, --no-memory-enforcement, --no-native-memory-override)
    now also removes the corresponding previously-installed hook instead of
    leaving it active. See ADR-0040.

Removed

  • obsidian-prompt-compiler package (ADR-0046) — absorbed into vkm-spec.
    Its pure modules (compile-xml, prompt-defaults, project-resolve,
    clipboard, review) moved verbatim; its retrieval was already relocated to
    obsidian-memory-mcp/src/context-assemble.mjs (ADR-0045). The GUI moved off
    port 4317 (OTLP collision) to 4923.

Fixed

  • Go daemon doctor could report healthy while actually blind. A failed
    git add/commit/pull (not just push) now feeds the same health state
    doctor alarms on; a repeated rebase --abort now feeds the alarm too
    (previously only displayed, never alarmed); a silently-failing filesystem
    watcher startup (fsnotify.NewWatcher) now sets an immediate alarm instead
    of leaving the daemon looking idle-but-fine with a heartbeat that never
    starts; a sync aborted by intentional shutdown (Ctrl-C / service stop) no
    longer counts toward the "vault not syncing" alarm; doctor's unpushed-
    commit git call now has a timeout like every other git call in the file,
    instead of being able to hang forever.
  • Go daemon push retries now re-pull first. A push rejected because the
    remote advanced was retried identically on every attempt with no chance of
    succeeding; retries now re-pull/rebase before retrying the push.
  • doctor's exit code / output ordering under the shipped -H windowsgui
    build.
    Root-caused to PowerShell not waiting for a GUI-subsystem child
    process unless its output is redirected (not fixable from inside the
    process) — documented the correct invocation pattern
    (docs/en/troubleshooting.md, docs/es/troubleshooting.md,
    docs/observability.md) and added a defensive writer flush before doctor
    returns.
  • obsidian-memoryd inspect --last -5 no longer panics on a negative
    line count.
  • vault_complete and memory_extract_candidates results now carry the
    same untrusted-data envelope as every other RAG tool
    — both previously
    returned vault-derived content (autocomplete matches, memory-dedup
    snippets) with no _trust/injection-flagging, unlike vault_hybrid_search
    and friends.
  • No subprocess timeout on the MCP↔Python RAG bridge. A hung/misbehaving
    Python backend could previously block an MCP tool call (and leak the
    process) indefinitely; configurable via OBSIDIAN_MEMORY_RAG_TIMEOUT_MS
    (default 120s).
  • Claude Code hook commands no longer corrupt on vault paths containing a
    quote or a trailing backslash.
    Switched from an interpolated shell string
    to Claude Code's exec form (command + args array), which eliminates the
    escaping bug class entirely rather than patching it.
  • Hook transcript scans are now incremental. guard-effort-gate and
    stop-vault-close-reminder used to re-read and re-parse the entire session
    transcript on every gated event (measured ~75ms on a 25MB transcript,
    compounding across a long session); they now cache the last-scanned offset
    and only read the new suffix, falling back to a full rescan on any doubt.
  • Backup files (.bak.* of settings.json/mcp.json) are now actually
    permission-restricted on Windows.
    The existing chmod 0600 protection was
    unconditionally skipped on win32 — the platform this repo is chiefly used
    on — despite the code's own stated intent of protecting files that may
    contain tokens. Now applies an equivalent icacls ACL restriction.
  • vault_complete's autocomplete no longer surfaces tags found inside
    fenced code blocks.
    A note documenting #tag syntax inside a code fence
    polluted the autocomplete trie with the example text as if it were a real
    tag.
  • Usage-boost retrieval scoring no longer lets stale-but-in-window usage
    permanently outrank a new note.
    The usage lever (ADR-0038) counted a use
    fully anywhere inside its 90-day window and not at all outside it; it now
    weights each use by recency-decay before scoring, closer to the lever's
    original "recent activity should matter more" intent.
  • A vector index built with one embedder no longer silently grows a second,
    redundant index under another.
    Every RAG CLI call that didn't pass an
    explicit --embedder resolved one independent of whatever embedder had
    actually built the existing on-disk index; it now reuses the on-disk
    identity when the caller passed no explicit override.
  • memory-report --duplicates/memory-reflect no longer report "zero
    near-duplicates" indistinguishably from "duplicate detection was skipped."

    Above the 1500-note pair-comparison cap, the scan now signals that it was
    skipped instead of returning a bare empty result.

See ADR-0040 for the design-level decisions in this pass (cross-process lock,
MCP wire-schema lockdown, hook exec-form, installer uninstall symmetry,
incremental transcript cache, Windows ACL backup protection, usage-decay
scoring, embedder-identity reuse).