Gap
Setting up the vault to work more with Claude Code. The vault is my local Obsidian notes directory; Claude Code writes session transcripts into it automatically. Migration phase exposes the asymmetry:
- Code sessions → vault, automatic.
- Web sessions (claude.ai) → no API to call. Didn’t anticipate that.
The only thing claude.ai offers is a bulk export — zip file, on demand, stale by design. That’s not a sync, that’s a filing cabinet. Without a real sync, ~90% of my Claude thinking stays locked on the one surface that won’t let it leave. Vault premise breaks.
Discovery chain
1. Didn’t accept export-or-nothing. Started looking for a real sync. While setting up a local integration that lets Claude Desktop read my vault, noticed Desktop, mobile, and web all showed identical session lists — same titles, same timestamps. Three surfaces, one backend. Which meant: there is an API door. Just not for me.
2. First solve — rejected deliberately. Honest first instinct was a surface-level workaround: script a cloud agent to open the desktop app, wait for Desktop to sync the web session down, then let my local integration pick up the new files:
remote agent → opens Desktop → Desktop syncs web → local integration harvests
Four links, any one breaks. Remote agent failure, Desktop failure, sync lag, harvest miss. Not a sync — a hostage situation stacked on top of a GUI I don’t control. The brainstorm clarified what reliability would require: cut dependencies, don’t add them.
3. Pivot. Don’t go through the app. Go to the service. Every surface sends an auth credential — find it.
4. Hunt. Two quotes from the session carry the texture better than paraphrase:
“I can’t interact with Windows GUI apps, only the WSL terminal.”
“The Cookies DB is locked (Claude Desktop has it open). Can’t read it while the app is running.”
Windows app-storage angle: dead end. Detour to web DevTools network tab. Two endpoints surfaced immediately:
GET /api/organizations/{org_id}/chat_conversations_v2→ metadata listGET /api/organizations/{org_id}/chat_conversations/{uuid}→ full content- Auth: session cookie, pulled from DevTools in under a minute.
Solution
Two endpoints, one cookie, incremental by default.
GET /chat_conversations_v2 → list
GET /chat_conversations/{uuid} → content
Cookie: sessionKey=<from DevTools>
- List returns newest first; diff
updated_atagainst vault frontmatter; fetch deltas only. - Key at
~/.claude_session_key(chmod 600). Cron reads it. - Cron every 8h, skip if <6h.
- Key expires → logs
AUTH_EXPIRED→ hook warns next Code session → 30 seconds to rotate.
The key-rotation step is the human-in-the-loop piece. Not hidden automation masking a manual dependency — the system surfaces the expiry cleanly and hands control back at the only moment it needs a human. Deliberate.
Attribution
- Daniel — gap identification, discovery chain, rejecting the surface solve.
- Claude — endpoint trace, sync engine, incremental pattern.
Why this matters
Started with data portability. Built the sync.
Side effect I didn’t plan for: isolating the transport layer meant nothing downstream had to know where the data came from. Parser, link graph, MCP search — all blind to source. Separation of concerns showed up on its own. Bonus, not goal.
The bigger lesson is still in motion for me —
In the cloud era we’ve become so accustomed to having our applications available on any surface at any time anywhere — we’ve designed UIs and security systems accordingly. But as agents become embedded and go deeper into our local environments, down the abstraction layer, it’s more important that we are very intentional about the way our agents can live: where we quarantine or isolate them, how we think about security, UIs, human-in-the-loop. All designed intentionally. Not one-size-fits-all.
Three live questions, same question asked three ways:
- Vault — Obsidian-local vs. cloud repo? Does my notes directory live on my laptop or in a cloud-hosted repo I sync down?
- Harness — local vs. cloud? Does the background automation that runs my agents live on my machine or on a server I reach remotely?
- Cron jobs — local cron vs. remote-triggered? Do scheduled jobs fire from my laptop’s scheduler, or from a remote trigger that calls into my environment?
Surface assignment isn’t a one-time call. Running decision, re-evaluated every time the agent layer pushes deeper.