DEV Community

Pavel Polívka
Pavel Polívka

Posted on

My Obsidian vault, written by Claude Code, in my pocket

These days I do most of my side-project work with Claude Code in a terminal. A few days ago I gave it access to my Obsidian vault and told it to write things down: every fix, every setup decision, every project. It turned out to be the best habit we built. The vault fills itself while I work.

There was one problem. All of it lived on my laptop, and my best questions come when I'm away from it. In the car, on the couch, in a queue. So I put Claude Code on my home server next to a synced copy of the vault and now I talk to it from the Claude app on my phone.

In this article, I'll walk you through:

  • how the vault is organised so an AI agent can find things
  • the setup on the server: Obsidian headless Sync and Claude Code Remote Control
  • how I locked it down
  • what broke on the way

A vault that agents can read

If you let an agent write into your notes without rules, you get a mess in a week. So the first note in my vault is Vault Rules.md. It says where things go and what Claude may and may not do:

  • Folders: Inbox/, Daily/, Projects/, Knowledge/, Archive/, Templates/, Attachments/.
  • Frontmatter on every note: created, updated, type, tags, author. The author field says if I wrote it, Claude did, or both.
  • Never delete or rewrite my text. Claude adds below it or in a callout. To get rid of something, move it to Archive/.
  • Log work in the daily note under a ## Claude heading, one line per item, with links.
  • No secrets. Passwords live in Bitwarden.

My global CLAUDE.md points to this note, so every Claude Code session reads it before writing anything.

Two more notes help agents find their way around without reading the whole vault:

  • Me.md is a profile: what I work on, my devices, how I like answers. Claude wrote it from my notes and a short interview, and anything it guessed is marked (inferred). I correct it when it is wrong.
  • Vault Map.md lists every note in one line, explains my own terms and says how to search. When a note is added or moved, Claude updates the map in the same change.

This sounds like a lot of overhead. It isn't, because I don't do it. I just read it.

The plan

I had three options for the phone part:

  1. Build my own small chat web app on top of the Claude Agent SDK.
  2. Write a Telegram bot.
  3. Use Claude Code's Remote Control.

Remote Control won. You run claude remote-control in a folder on any machine, and the session shows up in the Claude app under Code. The server only makes outgoing connections, so there's nothing to expose to the internet, no reverse proxy and no login page to maintain. It runs on my normal Claude subscription.

The vault also has to be on the server. I use Obsidian Sync between my devices, and Obsidian now has an official headless client for it. The server becomes just another synced device. When Claude edits a note there, I see it on my phone a few seconds later.

Obsidian headless Sync

The client is the obsidian-headless package on npm, and the command is ob:

npm install -g --prefix ~/.local obsidian-headless
ob login
ob sync-setup --vault Pavel --path ~/vault/Pavel --device-name home
Enter fullscreen mode Exit fullscreen mode

One thing to be careful about. Obsidian Sync syncs deletions too. An empty folder that pushes its "state" to your other devices is the nightmare scenario. So the first sync only downloads, and I switched it to two-way after I checked the file count:

ob sync-config --path ~/vault/Pavel --mode pull-only
ob sync --path ~/vault/Pavel
find ~/vault/Pavel -type f -not -path '*/.obsidian/*' | wc -l   # same as on the laptop?
ob sync-config --path ~/vault/Pavel --mode bidirectional
Enter fullscreen mode Exit fullscreen mode

After that, a systemd user service keeps it running:

# ~/.config/systemd/user/obsidian-sync.service
[Service]
ExecStart=/home/pavel/.local/bin/ob sync --continuous --path /home/pavel/vault/Pavel
Restart=always
RestartSec=30

[Install]
WantedBy=default.target
Enter fullscreen mode Exit fullscreen mode

Don't forget loginctl enable-linger for your user, or user services stop when you log out.

Claude Code next to the vault

I did not want Claude's config inside the vault, because everything in there syncs to all my devices. So Claude gets its own folder, ~/obsidian-agent, with two files:

  • CLAUDE.md: read Vault Rules.md first, then a few rules for this server. There's no Obsidian app here, so no Obsidian CLI; it edits the Markdown files directly. And keep answers short, because I read them on a phone.
  • .claude/settings.json: what it is allowed to do.

The vault itself is added as an extra directory. Then another user service runs Remote Control:

# ~/.config/systemd/user/claude-vault.service
[Service]
WorkingDirectory=/home/pavel/obsidian-agent
ExecStart=/usr/bin/claude remote-control --name Vault --permission-mode acceptEdits --spawn same-dir
Restart=always
RestartSec=30
Enter fullscreen mode Exit fullscreen mode

acceptEdits means it can edit files in the vault without asking me each time. On a phone, approving every edit gets old fast.

Locking it down

Remote Control is reachable from anywhere I'm logged in to my Claude account. That's the point, but it also means the session should not be able to do much more than I need. My rule: read and write the vault, search the web, nothing else. No shell.

{
  "permissions": {
    "defaultMode": "acceptEdits",
    "additionalDirectories": ["/home/pavel/vault/Pavel"],
    "allow": [
      "Read(//home/pavel/vault/Pavel/**)",
      "Edit(//home/pavel/vault/Pavel/**)",
      "Glob", "Grep", "WebSearch", "WebFetch"
    ],
    "deny": [
      "Bash",
      "Read(//home/pavel/.ssh/**)",
      "Read(//home/pavel/.config/**)",
      "Read(//home/pavel/.claude/**)",
      "Read(//etc/**)",
      "Edit(//home/pavel/obsidian-agent/**)",
      "Edit(//home/pavel/vault/Pavel/.obsidian/**)"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Notice the double slash. That one bit us. In Claude Code permission rules, /home/pavel/.ssh/** does not mean an absolute path. A single leading slash is relative to the settings file. For an absolute path you need //, or ~/ for your home. With one slash, my deny rules matched nothing, and nothing warned me. We only caught it because we tested: we asked the agent to read ~/.ssh/config and the error said "you haven't granted it yet" instead of "denied". With the fix, it says denied.

So test your sandbox. Ask the agent to run a command, read a secret file and edit its own rules. All three should fail.

The last line of defense is a backup that doesn't depend on Sync. Every night at 03:30 a timer tars the vault and copies it to my NAS, and the last 14 copies are kept. The vault is under a megabyte, so it costs nothing.

What broke

It was not all smooth.

  • ob: command not found. I installed it into ~/.local/bin, and on the server that wasn't on my zsh PATH. The services use the full path, so only my shell was affected.
  • Login failed. ob login said "please double check your email and password". Check that you can log in on the Obsidian website with the same details, and try typing the password instead of pasting it into the hidden prompt over SSH.
  • "Remote Control is not yet enabled for your account." The server had a Claude Code from half a year ago. I updated it with sudo npm install -g, and claude --version still said the old version. Turns out there were two installs: an old one in /usr/local that came first on the PATH, and the new one in /usr. The service was running the old one.
  • "Enable Remote Control? (y/n)". The new version asks this once, and a systemd service has no keyboard. Run claude remote-control once by hand, answer y, then start the service.

What I use it for

Mostly small things:

  • "What did I decide about X?" It searches the project notes and the daily log and answers with links.
  • "Put this in my inbox." An idea, a link, a bug I just noticed while playing my own game.
  • "How did I fix Y on my laptop?" The answer is usually in a Knowledge/ note that Claude wrote while fixing it.

It is the same agent and the same rules as on my laptop, so the notes look the same no matter where they were written. That's the part I like the most.

What it can't do

  • No Obsidian CLI on the server. The CLI talks to a running Obsidian app, and there is none. The agent uses grep and file search instead. For a vault my size that finds everything; it does miss backlinks through aliases.
  • No shell. On purpose. If I want it to do something on the server, I do that from my laptop.

Working with Claude Code

Same as last time, I want to be honest about who did the work. Claude Code planned this, checked what was already on the server, wrote all the config and found most of the problems above. It also made the permission-path mistake, and it was Claude that caught it, by testing instead of trusting its own config.

There were things it was not allowed to do. The auto mode stopped it from installing the services that keep running on my server, so I did that myself. The logins, with passwords and 2FA, were also mine. I think that is the right split.

Was it worth it?

It's new, so ask me again in a month. But one evening of setup, no custom code and nothing open to the internet, and my notes now answer me from my pocket. If you already let an agent write your notes, this is a small step.

If you have your own setup for talking to your notes from your phone, I'd love to see it. Drop a comment.


You can follow me here on dev.to for more.

Top comments (0)