claude-nomad 0.25.3 → 0.25.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +71 -65
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.25.4](https://github.com/funkadelic/claude-nomad/compare/v0.25.3...v0.25.4) (2026-05-27)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Documentation
|
|
7
|
+
|
|
8
|
+
* **readme:** clarify setup docs, reduce jargon, add $ command prompts ([#147](https://github.com/funkadelic/claude-nomad/issues/147)) ([d590833](https://github.com/funkadelic/claude-nomad/commit/d590833e9a2cc1503651b2a4468ca6e8269fd57c))
|
|
9
|
+
|
|
3
10
|
## [0.25.3](https://github.com/funkadelic/claude-nomad/compare/v0.25.2...v0.25.3) (2026-05-26)
|
|
4
11
|
|
|
5
12
|
|
package/README.md
CHANGED
|
@@ -50,12 +50,12 @@ For anyone running Claude Code on more than one machine: a laptop and a desktop,
|
|
|
50
50
|
If you already have a private claude-nomad mirror (see [Setup](#setup) for the one-time bootstrap), adding a new host is three steps:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
npm i -g claude-nomad
|
|
53
|
+
$ npm i -g claude-nomad
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
# Clone your private mirror so nomad has a repo to sync into.
|
|
58
|
-
git clone git@github.com:<your-username>/claude-nomad.git ~/claude-nomad
|
|
58
|
+
$ git clone git@github.com:<your-username>/claude-nomad.git ~/claude-nomad
|
|
59
59
|
|
|
60
60
|
# Add to ~/.zshrc or ~/.bashrc:
|
|
61
61
|
export NOMAD_HOST=<your-host-label>
|
|
@@ -68,9 +68,9 @@ export NOMAD_HOST=<your-host-label>
|
|
|
68
68
|
Then the everyday loop:
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
nomad doctor # confirm setup
|
|
72
|
-
nomad pull # apply config to ~/.claude/
|
|
73
|
-
nomad push # publish local changes (sessions, settings)
|
|
71
|
+
$ nomad doctor # confirm setup
|
|
72
|
+
$ nomad pull # apply config to ~/.claude/
|
|
73
|
+
$ nomad push # publish local changes (sessions, settings)
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
First-host bootstrap and the safe-migration sequence for a populated `~/.claude/` are in [Setup](#setup) and [Migrating an existing ~/.claude/](#migrating-an-existing-claude).
|
|
@@ -150,14 +150,14 @@ The hard problem: Claude Code stores sessions in `~/.claude/projects/<encoded-pa
|
|
|
150
150
|
```json
|
|
151
151
|
{
|
|
152
152
|
"projects": {
|
|
153
|
-
"
|
|
154
|
-
"<your-mac>": "/Users/you/code/
|
|
155
|
-
"<your-wsl-host>": "/home/you/code/
|
|
153
|
+
"my-example-repo": {
|
|
154
|
+
"<your-mac>": "/Users/you/code/my-example-repo",
|
|
155
|
+
"<your-wsl-host>": "/home/you/code/my-example-repo",
|
|
156
156
|
"<your-nuc>": "TBD"
|
|
157
157
|
}
|
|
158
158
|
},
|
|
159
159
|
"extras": {
|
|
160
|
-
"
|
|
160
|
+
"my-example-repo": [".planning", "CLAUDE.md"]
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
```
|
|
@@ -167,9 +167,13 @@ The hard problem: Claude Code stores sessions in `~/.claude/projects/<encoded-pa
|
|
|
167
167
|
|
|
168
168
|
Use the literal string `"TBD"` for hosts you haven't onboarded yet; `remapPull` skips TBD entries cleanly instead of creating an orphan `~/.claude/projects/TBD/`. Replace each `"TBD"` with the real path when you bring up that host.
|
|
169
169
|
|
|
170
|
-
On `push`, sessions in `~/.claude/projects/-Users-you-code-
|
|
170
|
+
On `push`, sessions in `~/.claude/projects/-Users-you-code-my-example-repo/` get copied to `shared/projects/my-example-repo/`. On `pull` on another machine, they get copied to that host's encoded path. `claude --resume` then finds them (see [What does NOT sync (deliberate trade-offs)](#what-does-not-sync-deliberate-trade-offs) for the cross-OS cwd-binding gotcha).
|
|
171
171
|
|
|
172
|
-
The `extras` block is additive and back-compatible: legacy `path-map.json` files without it
|
|
172
|
+
The `extras` block is additive and back-compatible: legacy `path-map.json` files without it keep working unchanged. Each value is an array of directory or root-file names (e.g. `.planning`, `CLAUDE.md`) checked against `SUPPORTED_EXTRAS` in `src/config.ts`; anything outside that whitelist is skipped with a log line, so an unrecognized name cannot widen the sync surface.
|
|
173
|
+
|
|
174
|
+
On `push`, opted-in content at `<localRoot>/<name>` (a directory subtree or a single file) is copied to `shared/extras/<logical>/<name>` and goes through the same staged-tree gitleaks scan as everything else. On `pull`, the reverse copy runs after `git pull --rebase`, and just before it overwrites your working tree a divergence check compares the incoming content against your local copy and prints a per-file WARN naming anything that differs.
|
|
175
|
+
|
|
176
|
+
Your existing local content is backed up under `~/.cache/claude-nomad/backup/<ts>/extras/` before the pull copy lands, so an unexpected overwrite is always recoverable.
|
|
173
177
|
|
|
174
178
|
## Per-host overrides
|
|
175
179
|
|
|
@@ -206,7 +210,7 @@ Read these before adopting so you opt in with eyes open.
|
|
|
206
210
|
- **Manual push/pull.** No file watcher. Shell hooks recommended.
|
|
207
211
|
- **OAuth doesn't sync.** You'll log in once per host. Intentional.
|
|
208
212
|
- **Only sessions in `path-map.json` are remapped.** Drive-by sessions on un-mapped paths are left alone.
|
|
209
|
-
- **Extras are opt-in and whitelisted.** Projects without an `extras` entry in `path-map.json` are unaffected. Names (a directory or a single root file) outside `SUPPORTED_EXTRAS` are skipped with a `skip ... not in SUPPORTED_EXTRAS` log line so an unrecognized name cannot widen the sync surface. Unsafe path-map values (path-traversal in `logical` keys, non-absolute or unnormalized `localRoot` values)
|
|
213
|
+
- **Extras are opt-in and whitelisted.** Projects without an `extras` entry in `path-map.json` are unaffected. Names (a directory or a single root file) outside `SUPPORTED_EXTRAS` are skipped with a `skip ... not in SUPPORTED_EXTRAS` log line so an unrecognized name cannot widen the sync surface. Unsafe path-map values (path-traversal in `logical` keys, non-absolute or unnormalized `localRoot` values) abort the run before any file is touched, so a malformed entry fails loudly instead of corrupting state.
|
|
210
214
|
- **Cross-OS `claude --resume` cwd binding.** Sessions embed the cwd where they were created, so the picker's `cd ... && claude --resume <id>` line fails on a different host. Use `nomad doctor --resume-cmd <id>` for a host-local equivalent (see [Cross-OS resume](#cross-os-resume)). The sidecar approach preserves transcript byte-equality.
|
|
211
215
|
- **Empty directories don't survive sync.** Git doesn't track empty dirs; `nomad doctor` reports them as `missing` (benign). Drop a `.gitkeep` to force materialization.
|
|
212
216
|
|
|
@@ -215,7 +219,7 @@ Read these before adopting so you opt in with eyes open.
|
|
|
215
219
|
- Node.js 22.22.1 or newer (24 LTS recommended; the npm `engines` field declares the 22.22.1 floor and surfaces a warning on older runtimes - npm only blocks the install when `engine-strict=true` is configured)
|
|
216
220
|
- `tsx` (ships as a runtime dependency of the published package; no separate global install required)
|
|
217
221
|
- Git
|
|
218
|
-
- [`gitleaks`](https://github.com/gitleaks/gitleaks) (required for `nomad push`, which
|
|
222
|
+
- [`gitleaks`](https://github.com/gitleaks/gitleaks) (required for `nomad push`, which exits with an error if it is not on PATH; `nomad doctor` also checks it against the pinned 8.30.x and warns when it is absent or mismatched)
|
|
219
223
|
- A **private** GitHub repo (or any Git remote you control)
|
|
220
224
|
|
|
221
225
|
**Optional:**
|
|
@@ -229,10 +233,10 @@ Read these before adopting so you opt in with eyes open.
|
|
|
229
233
|
|
|
230
234
|
### Privacy by default
|
|
231
235
|
|
|
232
|
-
|
|
236
|
+
When you mirror-push the tool into your repo, you copy its automation along with its code: the `.github/workflows/` directory holds the public project's own CI (running its test suite, linting, secret and code scanning, release tagging, and npm publishing). That CI is meant for the public project, not your config; if it ran on your private mirror, a job could echo transcript contents into build logs. So your mirror gets two independent layers of defense against that, both applied automatically:
|
|
233
237
|
|
|
234
|
-
1.
|
|
235
|
-
2.
|
|
238
|
+
1. **The workflows are written to skip private repos.** Each one carries the run condition `${{ !github.event.repository.private }}` (in plain terms: "run only when this repo is NOT private"), so even with Actions enabled the jobs do not run on your mirror.
|
|
239
|
+
2. **`nomad init` turns Actions off for the whole repo** on first run, via the GitHub API call `gh api -X PUT repos/<owner>/<repo>/actions/permissions -F enabled=false`. This needs the `gh` CLI installed and authed; if it is missing or unauthed, init logs a manual fallback tip and continues.
|
|
236
240
|
|
|
237
241
|
Pass `--keep-actions` to either form of init to skip step 2 (for example, when your org already enforces an Actions policy upstream).
|
|
238
242
|
|
|
@@ -241,34 +245,32 @@ Pass `--keep-actions` to either form of init to skip step 2 (for example, when y
|
|
|
241
245
|
|
|
242
246
|
### Bootstrap
|
|
243
247
|
|
|
244
|
-
Steps 1-2 are once-ever across all hosts;
|
|
248
|
+
Steps 1-2 are once-ever across all hosts; steps 3-4 repeat on every host:
|
|
245
249
|
|
|
246
250
|
```bash
|
|
247
251
|
# 1. Create the private repo (or use the GitHub UI). Once, ever.
|
|
248
|
-
gh repo create <your-username>/claude-nomad --private
|
|
252
|
+
$ gh repo create <your-username>/claude-nomad --private
|
|
249
253
|
|
|
250
|
-
# 2.
|
|
251
|
-
#
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
# 2. Copy the public tool into your private repo. A bare clone followed by a
|
|
255
|
+
# mirror push makes a complete, independent copy (every branch and tag) with
|
|
256
|
+
# no fork link back to upstream, which is what lets you keep it private. Once, ever.
|
|
257
|
+
$ git clone --bare git@github.com:funkadelic/claude-nomad.git /tmp/cn.git # download a full copy
|
|
258
|
+
$ cd /tmp/cn.git
|
|
259
|
+
$ git push --mirror git@github.com:<your-username>/claude-nomad.git # upload it to your private repo
|
|
260
|
+
$ cd .. && rm -rf /tmp/cn.git
|
|
256
261
|
|
|
257
262
|
# 3. Install the CLI globally and clone your private copy. Repeat on every host.
|
|
258
|
-
npm i -g claude-nomad
|
|
259
|
-
git clone git@github.com:<your-username>/claude-nomad.git ~/claude-nomad
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
`npm i -g claude-nomad` puts a `nomad` binary on your PATH. The bin shim is the existing `src/nomad.ts` entrypoint resolved through tsx (a runtime dependency); no compile step. The npm `engines` field declares the 22.22.1 floor and surfaces a warning on older runtimes; npm only blocks the install when `engine-strict=true` is configured.
|
|
263
|
-
|
|
264
|
-
On every additional host you only repeat step 3 (the global install is per-host; your private repo already exists on the remote from step 2).
|
|
265
|
-
|
|
266
|
-
Add to `~/.zshrc` or `~/.bashrc`:
|
|
263
|
+
$ npm i -g claude-nomad
|
|
264
|
+
$ git clone git@github.com:<your-username>/claude-nomad.git ~/claude-nomad
|
|
267
265
|
|
|
268
|
-
|
|
266
|
+
# 4. Add a stable host label to your shell rc (~/.zshrc or ~/.bashrc). Repeat on every host.
|
|
269
267
|
export NOMAD_HOST=<your-host-label> # any short, stable label; nomad reads this instead of os.hostname()
|
|
270
268
|
```
|
|
271
269
|
|
|
270
|
+
`npm i -g claude-nomad` puts a `nomad` binary on your PATH. The bin shim is the existing `src/nomad.ts` entrypoint resolved through tsx (a runtime dependency); no compile step. (The Node version floor and the `engine-strict` caveat are in [Requirements](#requirements).)
|
|
271
|
+
|
|
272
|
+
On every additional host you repeat only steps 3-4; steps 1-2 are already done, since your private repo lives on the remote from step 2.
|
|
273
|
+
|
|
272
274
|
`NOMAD_HOST` overrides `os.hostname()`, which returns noisy values like `WINDOWS-I5NT6OH` on WSL or `<name>.local` on macOS. Pick a clean label per machine (e.g., `wsl-laptop`, `macbook`, `homelab-nuc`). `nomad doctor` reports the resolved host so you can confirm.
|
|
273
275
|
|
|
274
276
|
### Initialize the repo layout
|
|
@@ -277,15 +279,15 @@ First host only; subsequent hosts just clone and `nomad pull`. Both forms below
|
|
|
277
279
|
|
|
278
280
|
```bash
|
|
279
281
|
# Fresh start: scaffold an empty shared/, hosts/, path-map.json skeleton.
|
|
280
|
-
nomad init
|
|
282
|
+
$ nomad init
|
|
281
283
|
|
|
282
284
|
# Already have ~/.claude/ populated on this host? Capture it as the
|
|
283
285
|
# starting point. Stages shared/ and writes hosts/<NOMAD_HOST>.json from
|
|
284
286
|
# your current ~/.claude/settings.json. Does NOT touch the originals.
|
|
285
|
-
nomad init --snapshot
|
|
287
|
+
$ nomad init --snapshot
|
|
286
288
|
|
|
287
289
|
# Either form accepts --keep-actions to skip the auto-disable.
|
|
288
|
-
nomad init --keep-actions
|
|
290
|
+
$ nomad init --keep-actions
|
|
289
291
|
```
|
|
290
292
|
|
|
291
293
|
`nomad init` refuses to clobber existing scaffold artifacts, so re-running on a populated repo is a safe no-op (it errors out naming the offender). `nomad pull` against an unscaffolded repo fails fast with `FATAL: repo not initialized; run 'nomad init' to scaffold` instead of silently leaving a half-state.
|
|
@@ -293,11 +295,11 @@ nomad init --keep-actions
|
|
|
293
295
|
Edit `path-map.json` to add your logical projects (see [Path remapping](#path-remapping)), then:
|
|
294
296
|
|
|
295
297
|
```bash
|
|
296
|
-
nomad doctor # read-only state check; reports host, repo state, every check as ✓ (pass) / ✗ (fail) / ⚠︎ (warn)
|
|
297
|
-
nomad doctor --check-shared # read-only gitleaks preflight over the session transcripts a push would stage
|
|
298
|
-
nomad diff # preview what nomad pull would change on this host; no lock, no network, no mutation
|
|
299
|
-
nomad push # send current state to the private remote
|
|
300
|
-
nomad pull # apply on another host (or this one after a remote update)
|
|
298
|
+
$ nomad doctor # read-only state check; reports host, repo state, every check as ✓ (pass) / ✗ (fail) / ⚠︎ (warn)
|
|
299
|
+
$ nomad doctor --check-shared # read-only gitleaks preflight over the session transcripts a push would stage
|
|
300
|
+
$ nomad diff # preview what nomad pull would change on this host; no lock, no network, no mutation
|
|
301
|
+
$ nomad push # send current state to the private remote
|
|
302
|
+
$ nomad pull # apply on another host (or this one after a remote update)
|
|
301
303
|
```
|
|
302
304
|
|
|
303
305
|
`nomad pull --dry-run` is the network-aware twin of `nomad diff`: it acquires the lock and runs `git pull` so you see what the next real pull would do given the latest remote, then exits without mutating.
|
|
@@ -310,11 +312,11 @@ If a host already has real files at `~/.claude/{CLAUDE.md, agents/, skills/, ...
|
|
|
310
312
|
|
|
311
313
|
```bash
|
|
312
314
|
# From the host that has the canonical config (the originals are not modified):
|
|
313
|
-
nomad init --snapshot # stages shared/ and writes hosts/<NOMAD_HOST>.json from ~/.claude/
|
|
314
|
-
nomad push # publish the captured state to the private remote
|
|
315
|
+
$ nomad init --snapshot # stages shared/ and writes hosts/<NOMAD_HOST>.json from ~/.claude/
|
|
316
|
+
$ nomad push # publish the captured state to the private remote
|
|
315
317
|
|
|
316
318
|
# Then, on this host or any other host that has the private remote checked out:
|
|
317
|
-
nomad pull # materializes the symlinks
|
|
319
|
+
$ nomad pull # materializes the symlinks
|
|
318
320
|
```
|
|
319
321
|
|
|
320
322
|
`nomad pull` is what actually migrates the host. `applySharedLinks` runs a two-pass scan: any pre-existing non-symlink at a `SHARED_LINKS` path whose counterpart exists under `shared/` is renamed into `~/.cache/claude-nomad/backup/<ts>/` first, then the symlink is created. Your originals are preserved under that timestamped backup directory, not deleted. Paths whose `shared/<name>` is absent from the remote are left untouched, so a partial publish does not delete data on the destination host.
|
|
@@ -325,38 +327,42 @@ Prefer an explicit tarball rollback and a confirmation prompt before any deletio
|
|
|
325
327
|
|
|
326
328
|
## Upgrading the tool
|
|
327
329
|
|
|
328
|
-
Two
|
|
330
|
+
Two different things can fall behind, and they update independently:
|
|
329
331
|
|
|
330
|
-
- **
|
|
331
|
-
- **
|
|
332
|
+
- **The `nomad` CLI binary** (what runs when you type `nomad`). If you installed it with `npm i -g claude-nomad`, upgrade it with `npm update -g claude-nomad`. This refreshes only the binary on your PATH; it does not touch anything inside your private `~/claude-nomad/` repo.
|
|
333
|
+
- **The synced tool files inside your private repo:** `src/`, `.gitleaks.toml` (the secret-scan allowlist), and the `.github/workflows/` privacy gating. These were copied from the public repo at bootstrap and then froze, so `npm update -g` does not refresh them. `nomad update`, run from `~/claude-nomad/`, is what pulls newer versions of these files in. Topology-aware: detects vanilla vs fork remotes, pulls or merges upstream, and re-runs `npm install` when `package-lock.json` shifted.
|
|
334
|
+
|
|
335
|
+
Most people who followed the Quickstart need both: `npm update -g` for the binary, and an occasional `nomad update` for the repo files (notably to receive `.gitleaks.toml` allowlist changes and any update to the privacy gating itself). The mirror-push bootstrap leaves your repo with `origin` on your private mirror and no `upstream` remote; that becomes the "fork" topology `nomad update` expects once you add the upstream remote (the one-time `git remote add upstream ...` step is below).
|
|
332
336
|
|
|
333
337
|
Your private repo is not a fork, so GitHub's "Sync fork" UI doesn't apply. The shortcut on a source-checkout host is:
|
|
334
338
|
|
|
335
339
|
```bash
|
|
336
|
-
cd ~/claude-nomad
|
|
337
|
-
nomad update
|
|
340
|
+
$ cd ~/claude-nomad
|
|
341
|
+
$ nomad update
|
|
338
342
|
```
|
|
339
343
|
|
|
340
|
-
`nomad update`
|
|
344
|
+
`nomad update` detects which layout your `~/claude-nomad/` uses and does the right thing:
|
|
341
345
|
|
|
342
346
|
- **vanilla** (`origin` points at the public repo): `git pull --ff-only origin main`.
|
|
343
347
|
- **fork** (`upstream` points at the public repo, `origin` points at your private mirror): `git fetch upstream`, then (before merging) commit any whitelisted `shared/extras/` content that is still untracked locally so an overlap with upstream becomes a normal file merge instead of an untracked-overwrite abort, `git merge upstream/main`, then prompt before pushing the merge to `origin/main`. Pass `--push-origin` to skip the prompt. When the merge is a no-op (HEAD unchanged, nothing new to push) the prompt is skipped entirely and `nomad update` logs `already in sync with origin/main`.
|
|
344
348
|
|
|
345
|
-
Pre-flight checks run before any mutation: `REPO_HOME` exists, topology resolves to `vanilla` or `fork`, current branch is `main`, working tree is clean
|
|
349
|
+
Pre-flight checks run before any mutation: `REPO_HOME` exists, the topology resolves to `vanilla` or `fork`, the current branch is `main`, the working tree is clean (override with `--force`), and `--push-origin` is rejected on vanilla topology.
|
|
350
|
+
|
|
351
|
+
After the merge or pull, `nomad update` re-runs `npm install` only when `package-lock.json` actually shifted, commits the regenerated `package-lock.json` (fork topology) if the reinstall changed it, then invokes `nomad doctor`. The trailing version-check is non-fatal: `✓` when local matches the latest release, `⚠︎` when behind, an informational `ℹ︎ ... ahead of latest release` line when ahead (e.g. a `-dev` build between releases), and silent on network failures.
|
|
346
352
|
|
|
347
353
|
Common cases:
|
|
348
354
|
|
|
349
355
|
```bash
|
|
350
|
-
nomad update # the usual path
|
|
351
|
-
nomad update --dry-run # detect topology + pre-flight, print would-be git commands only
|
|
352
|
-
nomad update --push-origin # fork topology: push merge to origin/main without prompting
|
|
353
|
-
nomad update --force # proceed past a dirty working tree
|
|
356
|
+
$ nomad update # the usual path
|
|
357
|
+
$ nomad update --dry-run # detect topology + pre-flight, print would-be git commands only
|
|
358
|
+
$ nomad update --push-origin # fork topology: push merge to origin/main without prompting
|
|
359
|
+
$ nomad update --force # proceed past a dirty working tree
|
|
354
360
|
```
|
|
355
361
|
|
|
356
362
|
One-time setup if you're running a fork layout and don't have the `upstream` remote yet:
|
|
357
363
|
|
|
358
364
|
```bash
|
|
359
|
-
git remote add upstream git@github.com:funkadelic/claude-nomad.git
|
|
365
|
+
$ git remote add upstream git@github.com:funkadelic/claude-nomad.git
|
|
360
366
|
```
|
|
361
367
|
|
|
362
368
|
To pin to a specific release (`vX.Y.Z`, tagged by release-please) instead of tracking `main`, fetch tags from the public repo and check out the tag (detached HEAD). On vanilla topology that's `origin`; on fork topology that's `upstream` (the private mirror at `origin` does not accumulate upstream release tags). Example: `git fetch upstream --tags && git switch --detach vX.Y.Z` (substitute `origin` for vanilla; use `git checkout vX.Y.Z` on older Git).
|
|
@@ -370,7 +376,7 @@ If you installed an earlier version via `./install.sh` and a shell alias (the pr
|
|
|
370
376
|
| `nomad init` | Scaffold empty `shared/`, `hosts/`, `path-map.json` on a fresh clone. Refuses to clobber existing scaffold. Auto-disables Actions on a detected private GitHub mirror (see [Privacy by default](#privacy-by-default)). |
|
|
371
377
|
| `nomad init --snapshot` | Overlay current host's `~/.claude/` into `shared/` and write `~/.claude/settings.json` verbatim into `hosts/<NOMAD_HOST>.json`. Originals not modified. Same auto-disable behavior as `nomad init`. |
|
|
372
378
|
| `nomad init --keep-actions` | Skip the auto-disable. Combinable with `--snapshot`. Use when an upstream org policy already governs Actions, or you intentionally want CI on the private mirror. |
|
|
373
|
-
| `nomad pull` | `git pull --rebase --autostash`, apply symlinks, regenerate `settings.json`, remap session paths, and pull opted-in per-project extras.
|
|
379
|
+
| `nomad pull` | `git pull --rebase --autostash`, apply symlinks, regenerate `settings.json`, remap session paths, and pull opted-in per-project extras. Errors out if scaffold missing. |
|
|
374
380
|
| `nomad pull --dry-run` | Network-aware preview: acquire lock + `git pull --rebase`, print planned changes (symlink moves, `settings.json` diff, transcript overwrites), exit without writing. |
|
|
375
381
|
| `nomad diff` | Offline, lockless twin of `pull --dry-run`. No network, no lock. Works against the current local repo state. |
|
|
376
382
|
| `nomad push` | Export local sessions and opted-in per-project extras to logical names, commit (`chore: sync from <NOMAD_HOST>`), push. |
|
|
@@ -403,7 +409,7 @@ Every `nomad pull`, `nomad push`, and `nomad diff` run ends with a single `summa
|
|
|
403
409
|
Surgically unstages every `shared/projects/*/<id>.jsonl` plus the sibling `shared/projects/*/<id>/` subagent directory (whose nested transcripts are keyed by the same session id) from the staged tree of `~/claude-nomad/`. The local `~/.claude/projects/<encoded>/<id>.jsonl` and the local `<id>/` tree are never touched.
|
|
404
410
|
|
|
405
411
|
```bash
|
|
406
|
-
nomad drop-session <id>
|
|
412
|
+
$ nomad drop-session <id>
|
|
407
413
|
```
|
|
408
414
|
|
|
409
415
|
Single positional id (the session filename minus `.jsonl`). Anything else (missing id, leading dash, extra arg) exits 1 with a `usage:` line.
|
|
@@ -419,7 +425,7 @@ What it does NOT do: touch the local `~/.claude/projects/<encoded>/<id>.jsonl` f
|
|
|
419
425
|
|
|
420
426
|
### Recovery flow: gitleaks FATAL on a session JSONL
|
|
421
427
|
|
|
422
|
-
`nomad push` runs `gitleaks protect --staged` before commit. To catch the same findings before you push (and without mutating anything), run the read-only preflight `nomad doctor --check-shared`, which stages and scans the exact transcripts a push would publish. When findings live in a session transcript, the push
|
|
428
|
+
`nomad push` runs `gitleaks protect --staged` before commit. To catch the same findings before you push (and without mutating anything), run the read-only preflight `nomad doctor --check-shared`, which stages and scans the exact transcripts a push would publish. When findings live in a session transcript, the push aborts and names every affected session id and the recovery command:
|
|
423
429
|
|
|
424
430
|
```text
|
|
425
431
|
✗ gitleaks detected secrets in 1 session transcript(s).
|
|
@@ -474,16 +480,16 @@ Claude Code embeds the original `cwd` in each session transcript. When you resum
|
|
|
474
480
|
Run this instead:
|
|
475
481
|
|
|
476
482
|
```bash
|
|
477
|
-
eval "$(nomad doctor --resume-cmd <session-id>)"
|
|
483
|
+
$ eval "$(nomad doctor --resume-cmd <session-id>)"
|
|
478
484
|
```
|
|
479
485
|
|
|
480
486
|
Or pipe through bash:
|
|
481
487
|
|
|
482
488
|
```bash
|
|
483
|
-
nomad doctor --resume-cmd <session-id> | bash
|
|
489
|
+
$ nomad doctor --resume-cmd <session-id> | bash
|
|
484
490
|
```
|
|
485
491
|
|
|
486
|
-
`nomad doctor --resume-cmd <id>` reads the `.jsonl`'s recorded `cwd`, reverse-looks up the logical project in `path-map.json`, finds your current host's abspath for that logical, and prints `cd <local-abspath> && claude --resume <id>` to stdout. The command is read-only: it never modifies any transcript byte
|
|
492
|
+
`nomad doctor --resume-cmd <id>` reads the `.jsonl`'s recorded `cwd`, reverse-looks up the logical project in `path-map.json`, finds your current host's abspath for that logical, and prints `cd <local-abspath> && claude --resume <id>` to stdout. The command is read-only: it never modifies any transcript byte.
|
|
487
493
|
|
|
488
494
|
If the session isn't mapped on this host, you'll see:
|
|
489
495
|
|
|
@@ -496,6 +502,6 @@ Other fatal surfaces: missing `~/.claude/projects/`, session id absent from ever
|
|
|
496
502
|
## Run tests
|
|
497
503
|
|
|
498
504
|
```bash
|
|
499
|
-
npm install
|
|
500
|
-
npx vitest run
|
|
505
|
+
$ npm install
|
|
506
|
+
$ npx vitest run
|
|
501
507
|
```
|
package/package.json
CHANGED