claude-nomad 0.67.2 → 0.67.3

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 CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.67.3](https://github.com/funkadelic/claude-nomad/compare/v0.67.2...v0.67.3) (2026-08-29)
4
+
5
+ ### What's new
6
+
7
+ **On native Windows (PowerShell or cmd).** Note: WSL2 behaves like Linux and this does not apply to it.
8
+
9
+ - **`nomad pull` now warns about a file that should never be synced, even when your gitignore hides it.** Before a pull, nomad checks your sync repo for files that have no business travelling between machines, such as credentials or per-host settings, and warns when one turns up under `shared/`. A file covered by a gitignore rule was invisible to that check, so it could sit there unmentioned. Nomad now names the file, along with the `git check-ignore` command that tells you which rule hid it, which is often a rule in your global git config rather than anything you wrote for this repo. It only warns. Nothing is deleted, because nomad cannot publish a file git ignores, so there is nothing to undo.
10
+
11
+ The rest of this release is internal: a regression test for the Windows `nomad sync` path, a stricter check on the test suite's own mock handling, and test-result reporting in CI. Nothing else changes what nomad does.
12
+
13
+
14
+
15
+ ### Fixed
16
+
17
+ * **pull:** report gitignored denylisted paths under shared/ ([#553](https://github.com/funkadelic/claude-nomad/issues/553)) ([b226902](https://github.com/funkadelic/claude-nomad/commit/b226902e4361a3325a2fd0495e5abbd532f7d806))
18
+
19
+
20
+ ### Changed
21
+
22
+ * report test results to Codecov Test Analytics ([#551](https://github.com/funkadelic/claude-nomad/issues/551)) ([a1fb555](https://github.com/funkadelic/claude-nomad/commit/a1fb5558185e6a97a8a026eeb05d3ef6a9834f28))
23
+
24
+
25
+ ### Documentation
26
+
27
+ * clean up the documentation prose ([#549](https://github.com/funkadelic/claude-nomad/issues/549)) ([cd8c40d](https://github.com/funkadelic/claude-nomad/commit/cd8c40d2f2877a868876e9ab338f4884060e90d9))
28
+
29
+
30
+ ### Testing
31
+
32
+ * scope the doMock/doUnmock symmetry guard to every describe ([#552](https://github.com/funkadelic/claude-nomad/issues/552)) ([ebe4af9](https://github.com/funkadelic/claude-nomad/commit/ebe4af988fed37b9ced1a3a42dd736fb1901c888))
33
+ * **sync:** add a cross-platform parity journey for nomad sync ([f87464d](https://github.com/funkadelic/claude-nomad/commit/f87464dcf7bf23341f1b8b8d4ae2eaefe0cc4e08))
34
+
3
35
  ## [0.67.2](https://github.com/funkadelic/claude-nomad/compare/v0.67.1...v0.67.2) (2026-08-24)
4
36
 
5
37
  ### What's new
package/README.md CHANGED
@@ -17,8 +17,8 @@ private Git repo you control. Run `nomad sync` on any machine and everything is
17
17
  included; it pulls in your latest config first, then publishes your local changes, so you never have
18
18
  to remember which one to run first.
19
19
 
20
- Not dotfiles, not rsync. **claude-nomad** understands Claude Code's state, so your session history
21
- survives different file paths and your secrets never ride along.
20
+ Dotfiles managers and rsync copy files. **claude-nomad** understands Claude Code's state, so your
21
+ session history survives different file paths and your secrets never ride along.
22
22
 
23
23
  **Full documentation: <https://funkadelic.github.io/claude-nomad/>**
24
24
 
@@ -81,7 +81,7 @@ opt-in per-project sync, transcript redaction, backup pruning, and more.
81
81
 
82
82
  ## Quickstart
83
83
 
84
- nomad works with two directories, and the difference is the one thing worth learning up front:
84
+ nomad works with two directories:
85
85
 
86
86
  - **`~/claude-nomad/`** is your private sync repo. This is the one you edit.
87
87
  - **`~/.claude/`** is Claude Code's live config. nomad regenerates it on every `pull`.
@@ -222,18 +222,17 @@ log output remains grep-stable.
222
222
  When `nomad push` detects a potential secret, it drops into an interactive menu (TTY) or aborts with
223
223
  a recovery hint (non-TTY/CI). Three non-interactive recovery paths are available without the menu:
224
224
 
225
- - `nomad push --full-scan` -- ignore the per-host push manifest and rescan all transcripts, then
225
+ - `nomad push --full-scan`: ignore the per-host push manifest and rescan all transcripts, then
226
226
  rewrite the manifest on success. Use this after upgrading gitleaks, after editing a gitleaks
227
227
  config file, or whenever you want to be certain nothing slipped through an incremental scan.
228
228
  Composes freely with `--dry-run` and all resolution modes.
229
- - `nomad push --redact-all` -- scrub every finding from the local transcript in place, then push.
229
+ - `nomad push --redact-all`: scrub every finding from the local transcript in place, then push.
230
230
  All-or-nothing: if any finding cannot be redacted (an active session, or one that does not map to
231
231
  a synced transcript), nothing is changed and the push stops so you can handle those sessions.
232
- - `nomad push --allow <rule>` -- record findings matching one gitleaks rule id as false positives
232
+ - `nomad push --allow <rule>`: record findings matching one gitleaks rule id as false positives
233
233
  (appends their fingerprints to `.gitleaksignore`), then re-scan and push.
234
- - `nomad push --allow-all` -- record every current finding as a false positive, then re-scan and
235
- push.
236
- - `nomad allow <fingerprint>...` -- pre-record specific fingerprints in `.gitleaksignore` without
234
+ - `nomad push --allow-all`: record every current finding as a false positive, then re-scan and push.
235
+ - `nomad allow <fingerprint>...`: pre-record specific fingerprints in `.gitleaksignore` without
237
236
  going through a push cycle.
238
237
 
239
238
  All allow paths always re-scan after writing the allowlist; a surviving finding still aborts the
@@ -314,16 +313,16 @@ false alarm from a concurrent run. Value `3` is reserved for future use.
314
313
 
315
314
  ## Crash reports
316
315
 
317
- If `nomad` ever hits an unexpected bug, it no longer dumps a raw stack trace at you. Instead it
318
- prints a short "this looks like a bug" banner (with a link to the issue tracker) and writes a small
319
- report you can attach to a bug report if you choose. The exit code is unchanged: an unexpected crash
320
- exits `1`, and a documented failure still exits with its own code from the table above. A prompt you
321
- cancel yourself is not a crash: it exits `130` and writes no report.
316
+ If `nomad` ever hits an unexpected bug, it does not dump a raw stack trace. It prints a short "this
317
+ looks like a bug" banner (with a link to the issue tracker) and writes a small report you can attach
318
+ to a bug report if you choose. The exit code is unchanged: an unexpected crash exits `1`, and a
319
+ documented failure still exits with its own code from the table above. A prompt you cancel yourself
320
+ is not a crash: it exits `130` and writes no report.
322
321
 
323
322
  What this means for you:
324
323
 
325
324
  - **The report stays on your machine.** It is written to `~/.cache/claude-nomad/crash/` and nothing
326
- is ever uploaded anywhere. The file just sits there until you decide to share it or delete it.
325
+ is ever uploaded anywhere. The file sits there until you decide to share it or delete it.
327
326
  - **The saved report is scrubbed twice.** First a structural pass rewrites your home directory to
328
327
  `~` and your hostname to a placeholder (absolute paths are personal information a secret scanner
329
328
  would not catch), and redacts credential-shaped tokens it recognizes (GitHub, GitLab, Slack, and
@@ -342,24 +341,24 @@ What this means for you:
342
341
  contents of any file.
343
342
  - **The directory manages itself.** Only the most recent reports are kept; older ones are pruned
344
343
  automatically on the next crash. There is no `nomad clean` flag for the crash directory, by
345
- design: it self-manages.
344
+ design.
346
345
 
347
346
  ## Learn more
348
347
 
349
- - [How it works](https://funkadelic.github.io/claude-nomad/how-it-works/) -- path remapping,
350
- settings merge, what syncs and what doesn't
351
- - [GSD-aware sync](https://funkadelic.github.io/claude-nomad/gsd-aware-sync/) -- what nomad does for
348
+ - [How it works](https://funkadelic.github.io/claude-nomad/how-it-works/): path remapping, settings
349
+ merge, what syncs and what doesn't
350
+ - [GSD-aware sync](https://funkadelic.github.io/claude-nomad/gsd-aware-sync/): what nomad does for
352
351
  GSD users out of the box
353
- - [Setup and migration](https://funkadelic.github.io/claude-nomad/quickstart/) -- full setup
352
+ - [Setup and migration](https://funkadelic.github.io/claude-nomad/quickstart/): full setup
354
353
  walkthrough, migrating an existing `~/.claude/`
355
- - [Recipes](https://funkadelic.github.io/claude-nomad/recipes/) -- copy-pasteable example configs
356
- for common setups, from scratch to cross-OS remapping and GSD integration
357
- - [Commands reference](https://funkadelic.github.io/claude-nomad/commands/) -- all CLI flags
358
- - [Claude Code plugin](https://funkadelic.github.io/claude-nomad/plugin/) -- /nomad slash commands
359
- and the session-start drift check
360
- - [Recovery flows](https://funkadelic.github.io/claude-nomad/recovery/) -- backups, drop-session,
354
+ - [Recipes](https://funkadelic.github.io/claude-nomad/recipes/): copy-pasteable example configs for
355
+ common setups, from scratch to cross-OS remapping and GSD integration
356
+ - [Commands reference](https://funkadelic.github.io/claude-nomad/commands/): all CLI flags
357
+ - [Claude Code plugin](https://funkadelic.github.io/claude-nomad/plugin/): /nomad slash commands and
358
+ the session-start drift check
359
+ - [Recovery flows](https://funkadelic.github.io/claude-nomad/recovery/): backups, drop-session,
361
360
  redact, gitleaks allowlist, non-interactive allow
362
- - [FAQ](https://funkadelic.github.io/claude-nomad/faq/) -- common questions, like the right
363
- push/pull order when both sides have changes
361
+ - [FAQ](https://funkadelic.github.io/claude-nomad/faq/): common questions, like the right push/pull
362
+ order when both sides have changes
364
363
  - [Contributing](https://funkadelic.github.io/claude-nomad/contributing/)
365
364
  - [Security policy](https://funkadelic.github.io/claude-nomad/security/)
package/dist/nomad.mjs CHANGED
@@ -8891,13 +8891,30 @@ function newlyUntracked(before, after) {
8891
8891
  if (before === null || after === null) return [];
8892
8892
  return [...after].filter((p) => !before.has(p));
8893
8893
  }
8894
+ function ignoredPathsUnderShared(repo) {
8895
+ const out = gitProbe(
8896
+ ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--ignored", "--", "shared/"],
8897
+ repo
8898
+ );
8899
+ if (out === null) return [];
8900
+ return out.split("\0").filter((record) => record.startsWith("!! ")).map((record) => record.slice(3));
8901
+ }
8902
+ function reportIgnoredDenied(repo) {
8903
+ for (const path of new Set(ignoredPathsUnderShared(repo))) {
8904
+ const segment = deniedSegmentFor(path);
8905
+ if (segment === null) continue;
8906
+ warn(
8907
+ `${path} is inside shared/ but git ignores it: the path segment "${segment}" is on the never-sync list. Nothing was changed, and nothing published it: nomad only ever stages with "git add -A", which skips an ignored path, so it has not reached the index or the remote. It stays invisible to the rest of this gate for the same reason, so move it outside shared/ if you want it kept, or delete it. Note the ignore rule may come from your global core.excludesFile rather than from this repo; run git check-ignore -v -- "${path}" to see which file and line the rule came from`
8908
+ );
8909
+ }
8910
+ }
8894
8911
  function revertDeniedUnderShared(repo, ts) {
8895
8912
  const out = gitProbe(
8896
8913
  ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", "shared/"],
8897
8914
  repo
8898
8915
  );
8899
- if (out === null) return;
8900
- revertDeniedMirrorPaths(repo, parsePorcelainZ(out), ts);
8916
+ if (out !== null) revertDeniedMirrorPaths(repo, parsePorcelainZ(out), ts);
8917
+ reportIgnoredDenied(repo);
8901
8918
  }
8902
8919
  function reconcileSharedLinksBeforePull(repo, ts) {
8903
8920
  if (process.platform !== "win32") {
@@ -10899,7 +10916,7 @@ function parseSyncArgs(argv) {
10899
10916
  // package.json
10900
10917
  var package_default = {
10901
10918
  name: "claude-nomad",
10902
- version: "0.67.2",
10919
+ version: "0.67.3",
10903
10920
  type: "module",
10904
10921
  description: "Sync Claude Code config (~/.claude/) across machines via a private Git repo, with path remapping and per-host settings overrides.",
10905
10922
  keywords: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-nomad",
3
- "version": "0.67.2",
3
+ "version": "0.67.3",
4
4
  "type": "module",
5
5
  "description": "Sync Claude Code config (~/.claude/) across machines via a private Git repo, with path remapping and per-host settings overrides.",
6
6
  "keywords": [