FAQ
I edited ~/.claude/settings.json and my change vanished after a pull. Why?
Section titled “I edited ~/.claude/settings.json and my change vanished after a pull. Why?”Because that file is generated, not synced. Every nomad pull rebuilds it by merging
shared/settings.base.json with hosts/<NOMAD_HOST>.json from your sync repo, so anything you
hand-edit into ~/.claude/settings.json on a synced host is overwritten by the next pull.
Make the edit in the sync repo instead:
- Want it on every host? Edit
shared/settings.base.json. - Want it on this host only? Edit
hosts/<NOMAD_HOST>.json.
Then nomad push from the host you edited on (or just commit and push the repo) and nomad pull
everywhere else. Truly host-local settings that should never sync can also live in
~/.claude/settings.local.json, which claude-nomad never touches.
How do I set a per-host setting, like a different model or an env var?
Section titled “How do I set a per-host setting, like a different model or an env var?”Put it in hosts/<NOMAD_HOST>.json in your sync repo. On every pull, that file is deep-merged on
top of shared/settings.base.json, with these rules:
- Scalars override:
"model": "opus"in the host file beats the base value. - Objects merge recursively: you can override one key inside
envwithout redeclaring the rest. - Arrays replace wholesale: a host-file array swaps out the base array, it does not append.
nullis a valid override: use it to explicitly blank out a base value on one host.
Why isn’t my session showing up on the other host?
Section titled “Why isn’t my session showing up on the other host?”Almost always: the project is not in path-map.json. Only projects listed there sync; everything
else is left alone in both directions, and push/pull fold those into a single info row like
ℹ︎ 4 not in path-map. Run nomad doctor to list the unmapped projects by name, then add the
project to path-map.json with its absolute path on each host (see
How it works for the format), push, and pull on the other host.
What never leaves my machine?
Section titled “What never leaves my machine?”Credentials and ephemeral state are excluded by a hard-coded block list: OAuth tokens and MCP
state (.claude.json, .credentials.json), your prompt history (history.jsonl), per-host
overrides (settings.local.json), and runtime dirs like todos/, shell-snapshots/, caches,
and telemetry. The authoritative list is the NEVER_SYNC set in src/config.ts, and the
sensitive subset stays blocked even inside an opted-in extras directory. On top of that, only an
explicit allow-list of paths can be pushed at all, and everything that is pushed gets scanned by
gitleaks first. See Security for the full trust model.
Push says gitleaks found a secret. Now what?
Section titled “Push says gitleaks found a secret. Now what?”Three exits, depending on what the finding is:
- Real secret in a transcript you want to keep:
nomad redact <session-id>(or answerRedactin the interactive menu) rewrites the secret in place, locally, then push again. - False positive:
nomad push --allow <rule>ornomad allow <fingerprint>records it in.gitleaksignoreso it stops blocking. - Session you do not need to sync:
nomad drop-session <id>unstages it from the sync repo while leaving the local file intact forclaude --resume.
The full decision tree, including non-interactive CI paths, is in Recovery flows.
What is the difference between nomad diff and nomad pull —dry-run?
Section titled “What is the difference between nomad diff and nomad pull —dry-run?”Both preview what a pull would change, but nomad diff is offline and lockless: it does not
take the sync lock and does not contact the remote, so it shows what a pull would do against the
repo state you already have checked out. nomad pull --dry-run does the network round-trip
first, so it shows what the next real pull would actually apply. Use diff for a quick local
look, --dry-run for the authoritative preview.
Backups are piling up in ~/.cache/claude-nomad. Is that a problem?
Section titled “Backups are piling up in ~/.cache/claude-nomad. Is that a problem?”Every pull and push snapshots what it is about to overwrite into
~/.cache/claude-nomad/backup/<timestamp>/, and nothing deletes those automatically. nomad doctor warns once the pile passes 20 directories or 200 MB. Prune with:
$ nomad clean --backups # delete backups older than 14 days$ nomad clean --backups --keep 5 # or: keep only the 5 newest$ nomad clean --backups --dry-run # preview either mode firstEvery pull fails with “Pulling is not possible because you have unmerged files”
Section titled “Every pull fails with “Pulling is not possible because you have unmerged files””error: Pulling is not possible because you have unmerged files.fatal: Exiting because of an unresolved conflict.✗ git pull --rebase failedThis means a previous pull’s rebase hit a conflict and was never resolved, leaving your sync
repo (~/claude-nomad/) stuck mid-rebase. Every pull since then has died on the same wall.
Automated recovery (recommended): nomad pull --force-remote automates the sequence below.
It aborts the in-progress rebase or merge, safety-diffs stranded commits and dirty tracked
changes against origin/main, parks stranded commits on a nomad/stranded-<ts> branch, resets
hard to origin/main, and re-pulls. If any stranded or dirty tracked changes touch synced config
(shared/, hosts/, path-map.json), it refuses and lists the at-risk paths so nothing config-related
is silently discarded. The parking branch stays in the repo as a recoverable ref.
Manual fallback (use if --force-remote refuses due to synced-config changes):
$ cd ~/claude-nomad$ git rebase --abort # or: git merge --abort, if it was a merge
# Safety check before discarding local state: what would be thrown away?$ git log --oneline origin/main..HEAD # stranded local commits, if any$ git diff origin/main --stat # uncommitted divergence
# If nothing above touches config you care about (shared/, hosts/, path-map.json):$ git reset --hard origin/main$ nomad pullIf the safety check shows local-only commits that DO touch synced config, cherry-pick or copy
those changes out before the reset --hard; they exist nowhere else. When in doubt, the repo is
plain git, so anything discarded is still in git reflog until git prunes it.
A hook that worked before nomad now fails with “Cannot find module”
Section titled “A hook that worked before nomad now fails with “Cannot find module””SessionStart:startup hook errorError: Cannot find module '../some-tool/lib/helper.cjs'Require stack:- /home/you/claude-nomad/shared/hooks/check-update.jsThe giveaway is the require stack: the failing script shows up under your sync repo
(~/claude-nomad/shared/...) instead of ~/.claude/....
Here is what happens. On a synced host, directories like ~/.claude/hooks/ are symlinks into the
sync repo. When Node runs a script, it resolves symlinks first, so the script “believes” it lives
in ~/claude-nomad/shared/hooks/. If the tool that installed the hook loads another file by a
path relative to its own location (say require('../tool-runtime/helper.cjs'), expecting to find
~/.claude/tool-runtime/ next door), the lookup happens inside the sync repo, where that
directory does not exist. The hook crashes with MODULE_NOT_FOUND.
For Node hooks the fix is one flag, --preserve-symlinks-main, which tells Node to keep the
symlinked path so relative lookups resolve back under ~/.claude/:
"command": "node --preserve-symlinks-main \"$HOME/.claude/hooks/check-update.js\""Make that edit in shared/settings.base.json in your sync repo, not in ~/.claude/settings.json
(see the first question for why), then push and pull as usual.
Any tool that installs files into a synced directory (hooks/, skills/, and friends) and
references other ~/.claude/ paths relative to its own file location can hit this, often right
after the tool updates itself. You do not have to spot it yourself: nomad doctor warns about
hook commands with this shape and prints the same fix hint.
Is nomad update different from npm update -g claude-nomad?
Section titled “Is nomad update different from npm update -g claude-nomad?”No. nomad update runs the npm self-update for you; it is a convenience wrapper, nothing more.
Use whichever you prefer.
I have local changes to push and remote changes to pull. What order do I run them in?
Section titled “I have local changes to push and remote changes to pull. What order do I run them in?”Push first, then pull.
$ nomad diff # optional: preview what a pull would apply, without locking anything$ nomad push # your local changes win and land in the sync repo$ nomad pull # apply the merged repo state back to ~/.claude/Why this order works:
-
nomad pushalready does the pull’s git half for you. Before touching anything, push rebases your sync repo on the remote, so commits from other hosts are integrated first. Then your local state (sessions, extras, hooks) is copied over the repo tree and pushed. When the same file changed on both sides, your local copy wins (last-write-wins is the designed model). Conflicts that git cannot rebase cleanly stop the push at the rebase step so you can resolve them by hand. -
nomad pullthen applies the merged result locally: it regeneratessettings.jsonfrom the base and host files, refreshes the symlinks, and copies down anything other hosts pushed that you did not have yet.
The reverse order is the lossy one. Pulling first overwrites your diverging local files with the repo versions; that is exactly what the warning below is telling you:
⚠︎ local .planning for claude-nomad diverges from origin in 3 file(s); next remapExtrasPull will overwrite themIf you pull anyway, your overwritten files are recoverable from
~/.cache/claude-nomad/backup/<timestamp>/, but pushing first means you never need them. The
divergence warning prints the exact backup path it wrote; otherwise, find the newest backup and
copy the file back. Inside the backup, extras live under extras/<encoded-project-path>/ (the
project’s absolute path with slashes turned into dashes):
$ ls -t ~/.cache/claude-nomad/backup/ | head -1 # newest backup, named <timestamp>$ cp ~/.cache/claude-nomad/backup/<timestamp>/extras/-home-you-code-myproject/.planning/ROADMAP.md \ ~/code/myproject/.planning/ROADMAP.mdThen push so the repo gets your restored copy and the warning stops firing.
One nuance: because push is last-write-wins, if the same file genuinely changed on two hosts,
the host that pushes last clobbers the other’s version in the sync repo (the older copy survives
only in git history). If you suspect a real both-sides edit on something you care about, run
nomad diff first and reconcile by hand before pushing.