Files
goldbrain/.source-references/references-only/reference vault/memory/projects/obsidian-memory-plugin.md
T
2026-06-04 16:20:56 -05:00

6.4 KiB

type, status, tags, updated
type status tags updated
project active
obsidian
cowork
plugin
memory
2026-05-27

obsidian-memory Plugin

Claude Cowork plugin that uses Jason's Obsidian vault at 10.2.0.2 as persistent memory across sessions.

Current status

Plugin built and installed. Vault bootstrapped 2026-05-27. Ready for daily use — memory accumulates as sessions run.

Key decisions

  • No MCP server — direct REST calls via bash/curl (simpler, fully portable in a single .plugin file)
  • API key and server hardcoded (personal plugin, not for distribution)
  • Uses -k flag for SSL (Obsidian Local REST API uses a self-signed cert)
  • Server: https://10.2.0.2:27124
  • API key: stored in skill, not to be redistributed
  • Vault layout roots at Projects/agents/ — index → profile → memory subdirs

Architecture

obsidian-memory.plugin
├── .claude-plugin/plugin.json
├── skills/obsidian-memory/
│   ├── SKILL.md               ← load/write/log instructions + curl patterns
│   └── references/
│       ├── api-reference.md   ← all curl endpoint patterns
│       ├── vault-layout.md    ← frontmatter conventions + folder map
│       ├── bootstrap.md       ← first-run setup procedure
│       └── session-log-template.md
└── README.md

Vault layout

Projects/agents/
├── README.md
├── memory/
│   ├── profile.md
│   ├── inbox.md
│   ├── projects/<slug>.md
│   ├── sessions/YYYY-MM-DD-<slug>.md
│   ├── people/<name>.md
│   └── decisions/YYYY-MM-DD-<slug>.md

Open threads

  • Populate profile.md as facts emerge in conversations
  • Consider adding a decisions file for major project choices

Log

  • 2026-05-27: Plugin built in Cowork session. Vault bootstrapped. First session logged.

Known issues

PATCH with Target-Type: heading returns invalid-target (2026-05-28)

Symptom: Every PATCH request with Operation: append|replace, Target-Type: heading, and a Target: header (e.g. Target: Current status) returns:

HTTP 400
{ "message": "The patch you provided could not be applied to the target content.\ninvalid-target", "errorCode": 40080 }

This happens on all files tested including freshly-fetched profile.md and project files with confirmed valid heading text. The documented example from references/api-reference.md ("Replace a heading's content entirely") reproduces the failure exactly.

Reading a heading via URL path (/vault/path/file.md/heading/Heading%20Name) also returns 404 Not Found even when the heading clearly exists in the file body — so the failure is in the heading-resolution layer, not the patch-apply layer.

Workaround: Use POST (append-to-EOF) and PUT (full overwrite) instead. The skill's main flow already documents POST as the default for additive entries, so this only matters when you need targeted section editing (e.g. "replace Current status" for a project file).

Impact: Cannot do surgical section replacement. The project file for unifi-access-dashboard.md ended up with the new content appended to the bottom instead of replacing "Current status" inline — readable but less tidy.

To investigate:

  • Check installed Local REST API plugin version on the vault (Obsidian → Settings → Community plugins)
  • Compare against the coddingtonbear/obsidian-local-rest-api release notes for PATCH-heading regressions
  • If recent, try downgrading; if old, try upgrading
  • Try with explicit Target-Delimiter header (some versions need it for top-level headings)
  • Verify the file is using LF line endings — CRLF can break heading parsing in some plugin versions

Log

  • 2026-05-28: Discovered PATCH-heading bug during the unifi-access-dashboard memory update. Logged under Known issues; working around with POST/PUT.

Retest after plugin upgrade 3.6 → 4.1.1 (2026-05-28)

Still broken. Both failure modes reproduce identically after the upgrade:

Test Result
PATCH w/ Target-Type: heading, Target: Communication preferences HTTP 400, invalid-target
PATCH w/ Target-Type: heading, Target: Role (single word, no spaces) HTTP 400, invalid-target
PATCH w/ Target-Type: heading, Target: Communication%20preferences (URL-encoded) HTTP 400, invalid-target
GET /vault/.../profile.md/heading/Role (URL-path heading read) HTTP 404, Not Found
GET /vault/.../profile.md (bare file read — sanity) HTTP 200 ✓
PATCH w/ Target-Type: frontmatter, Target: updated HTTP 200 ✓

Narrowed diagnosis: The PATCH route is healthy — Target-Type: frontmatter works perfectly. Only the heading resolver is broken. The same resolver is shared between the heading-target PATCH path and the URL-path /heading/... read path (both 404 on valid headings), which is consistent with a single bug in heading lookup.

Ruled out:

  • Plugin version (3.6 was old) — 4.1.1 has the same bug
  • Spaces in heading text — single-word "Role" also fails
  • URL encoding of Target: header — both raw and %20-encoded fail
  • Broken PATCH route generally — frontmatter target works

Likely culprits (narrower now):

  • CRLF vs LF line endings in vault files — heading parser may require LF. Files written by curl from this skill use LF, but files edited in Obsidian on Windows might get CRLF.
  • Unicode BOM at file start
  • An option in the plugin settings UI that toggles heading-mode patches
  • An upstream bug — worth opening an issue at coddingtonbear/obsidian-local-rest-api with this exact reproducer (it's small and easy to verify)

Workarounds (in order of preference):

  1. For metadata: Target-Type: frontmatter works — use it for updated, status, tags.
  2. For additive section content: POST (append to EOF) — already the skill's documented default.
  3. For surgical section replacement: read the file, modify in code, PUT the whole thing back. Heavy-handed but reliable.
  • 2026-05-28: Plugin upgraded 3.6 → 4.1.1 to fix the PATCH-heading bug. Retest shows the bug persists in 4.1.1. Narrowed: Target-Type: frontmatter works, only Target-Type: heading (and the URL-path /heading/... read) is broken. Likely a heading-resolver bug. Workaround unchanged: POST/PUT/frontmatter-PATCH only.