Today I ran make pull on my older Mac after a round of changes on the new one. Skills, settings and the list of MCP servers all came across. Then the output ended with four lines like this:
SECRET slack.env.SLACK_TOKEN is not set on this machine, fill it in ~/.claude.json
SECRET bank-statements.env.STATEMENTS_DIR is not set on this machine, fill it in ~/.claude.json
The sync did its job. It knew a token was needed and left it blank on purpose, because secrets never go into the repo. But the values only existed on the other Mac, and the only reminder was a line in the output that I would scroll past. A week later I would open Claude Code, ask for the Slack tool, and wonder why it was broken.
I set up the two-Mac sync last week. This is the missing piece.
The rule: the repo knows the names, Bitwarden knows the values
I had just moved every password I own into Bitwarden and turned off Chrome and iCloud passwords. So the answer was already on my machine: one vault, one place for every value, on every computer and the phone.
flowchart LR
A["mcp-servers.json<br/>(git, names only)"] --> B[make pull]
C["Bitwarden<br/>folder claude-mcp"] --> B
B --> D["~/.claude.json<br/>(this Mac)"]
D -- "set only here" --> C
B --> E["state/todo.txt"]
E --> F[new terminal]
The vault has one folder, claude-mcp, with one secure note per MCP server. Each env variable is a hidden field on that note. For every blank key, the sync script now does one of four things:
| This Mac | Bitwarden | What happens |
|---|---|---|
| empty | has it | copied to ~/.claude.json |
| has it | empty | uploaded to Bitwarden |
| has it | different | flagged, I fix it by hand |
| empty | empty | added to the to-do list |
The upload row matters most. When I add a new MCP server and paste its token on one Mac, the next make push stores it in the vault. The other Mac picks it up on its next pull. I never have to remember to copy it.
Reminders where I actually look
My first idea was a GitHub issue per missing secret. It sounded tidy, but nothing would close the issue when I set the value, so it would go stale in a week. A local file always matches the real state of the machine.
So the script writes whatever is still open to ~/.claude/state/todo.txt, and one line in ~/.zshrc prints it in yellow when I open a terminal. An empty file prints nothing. That covers Claude Code and Codex, because both start from a terminal.
I first wanted a Claude Code SessionStart hook for the reminder. But my settings.json is gitignored, so the hook would never reach the other Mac. The zsh line is a tracked script plus one line per machine, and the to-do list itself reminds me to add that line.
When the vault is locked, the script can't read Bitwarden. It still checks what is empty on this Mac and prints the hint run make secrets. That target unlocks the vault, asks for the master password once, and runs the full sync.
The bug was in my CLI, not my code
Before the first real run I checked bw status. The Bitwarden CLI on this Mac was still logged in to an old account on the EU server, which I had already deleted. Every secret would have gone into a vault that no longer existed. The fix was three commands: bw logout, bw config server, bw login.
The CLI keeps its own login, separate from the app and the browser extension. After you move to a new Bitwarden account, check every tool that talks to the vault, not just the ones you can see.
What it took
About 150 lines of Python in the existing sync script, one make target and a five-line zsh file. The part that took thinking was the table above, especially what to do when both sides have a value and they differ. I don't guess there. The script flags it and I pick one. Next time I'd start with bw status on every machine before writing a line of code.

Related notes
Codemagic MCP Server: Trigger Mobile CI Builds from Claude Code
I open-sourced mcp-codemagic, an MCP server that brings Codemagic CI/CD into Claude Code. List apps, trigger builds, check status, and cancel runs without leaving your terminal.
Verified Human Cert MCP Server: Prove Your Music Is Human-Made, Right from the Terminal
I built an MCP server that queries the Verified Human Cert registry. Verify human-made music certifications by ISRC, artist, track, or cert number directly from Claude Code.



