claude-nomad 0.60.0 → 0.62.0

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/.gitleaks.toml CHANGED
@@ -6,28 +6,53 @@
6
6
  [extend]
7
7
  useDefault = true
8
8
 
9
- # Path-scoped: this tool-output noise (gitleaks fingerprints, coverage
10
- # line-keys, npm audit JSON id hashes, Sonar issue keys) accumulates in Claude
11
- # Code session transcripts when a conversation runs those tools. Two of these
12
- # regexes are structurally generic enough that, left global, they could suppress
13
- # a real credential that happened to sit in a `path:word:digit` or hex-`id`
14
- # context anywhere in the repo. Scoping to `shared/projects/<logical>/.../*.jsonl`
15
- # with `condition = "AND"` (matching every other block below) confines the
16
- # suppression to synced transcripts: a real secret in a source file still fires.
17
- # The Sonar-issue-key regex is length-bounded to the real key shape (`AY` + 17-22
18
- # base64url chars = 19-24 total, matching the sibling `key:`/`rule:` block) and
19
- # token-anchored with `\b` on both ends, so it cannot suppress a longer or
20
- # embedded `AY`-prefixed credential as a substring (an unbounded `{20,}` could).
9
+ # Path-scoped: the bare Sonar-issue-key shape (`AY` + 17-22 base64url chars) is
10
+ # a CONTEXT-FREE token pattern. Unlike the three structural noise shapes below
11
+ # it carries no surrounding structure (no `:rule:line`, no `"id":`, no `key=`
12
+ # prefix), so it cannot be distinguished from a real `AY`-prefixed high-entropy
13
+ # credential of the same length. It is therefore scoped to synced session
14
+ # transcripts ONLY (`shared/projects/<logical>/.../*.jsonl`), NOT to
15
+ # `shared/skills/**`: a skill file is executable, curated content a user pastes
16
+ # real values into, so an `AY`-shaped credential dropped into a skill MUST still
17
+ # fire. `condition = "AND"` confines the suppression to transcripts: a real
18
+ # secret in a source file still fires. The regex is length-bounded to the real
19
+ # key shape and token-anchored with `\b` on both ends, so even inside a
20
+ # transcript it cannot suppress a longer or embedded `AY`-prefixed credential as
21
+ # a substring (an unbounded `{20,}` could).
21
22
  [[allowlists]]
22
- description = "claude-nomad: structurally-distinguishable tool-output noise in synced session transcripts"
23
+ description = "claude-nomad: Sonar issue-key token shape (AY-prefixed) in synced session transcripts only, NOT skills"
23
24
  regexes = [
24
25
  '''\bAY[A-Za-z0-9_-]{17,22}\b''',
26
+ ]
27
+ paths = [
28
+ '''^shared/projects/[^/]+/.*\.jsonl$''',
29
+ ]
30
+ condition = "AND"
31
+
32
+ # Path-scoped: this tool-output noise (gitleaks fingerprints, coverage
33
+ # line-keys, npm audit JSON id hashes) accumulates in Claude Code session
34
+ # transcripts when a conversation runs those tools. Each of these three regexes
35
+ # carries structural context (`<path>.<ext>:<rule>:<line>`, `"id":"<hex>"`, or
36
+ # `key=<hex> <path>:<line>`) that a bare credential does not, so widening them
37
+ # to skill content cannot mask a context-free secret token. Scoping to
38
+ # `shared/projects/<logical>/.../*.jsonl` with `condition = "AND"` (matching
39
+ # every other block below) confines the suppression to synced transcripts: a
40
+ # real secret in a source file still fires. Also scoped (recursively) to
41
+ # `shared/skills/<name>/**`: curated, portable skill content can legitimately
42
+ # embed the same structured tool-output noise shapes (e.g. a skill doc pasting
43
+ # an example npm-audit or coverage dump), and the structural anchor keeps the
44
+ # false-negative risk low in that tree too. The bare `AY` shape is deliberately
45
+ # NOT in this block (see the transcript-only block above).
46
+ [[allowlists]]
47
+ description = "claude-nomad: structurally-anchored tool-output noise in synced session transcripts and skills"
48
+ regexes = [
25
49
  '''[\w./-]+\.[A-Za-z0-9]+:[\w-]+:\d+''',
26
50
  '''"id"\s*:\s*"[a-f0-9]{40,64}"''',
27
51
  '''key=[a-f0-9]{8,} [\w./-]+\.\w+:\d+''',
28
52
  ]
29
53
  paths = [
30
54
  '''^shared/projects/[^/]+/.*\.jsonl$''',
55
+ '''^shared/skills/[^/]+/.*$''',
31
56
  ]
32
57
  condition = "AND"
33
58
 
@@ -41,7 +66,11 @@ condition = "AND"
41
66
  # false-positive handler is a narrow allowlist scoped to synced session
42
67
  # paths. `condition = "AND"` requires BOTH a known literal AND a
43
68
  # `shared/projects/<logical>/.../*.jsonl` path; a real PAT in the same
44
- # file (different 36-char body) still fires.
69
+ # file (different 36-char body) still fires. Also scoped to
70
+ # `shared/projects/<logical>/memory/*.md`: these exact literals legitimately
71
+ # appear in curated memory prose that discusses the fixture pattern itself
72
+ # (e.g. a memory note documenting this allowlist), and the exact-literal match
73
+ # carries no false-negative risk there either.
45
74
  [[allowlists]]
46
75
  description = "claude-nomad: documented test-fixture github-pat literals + scrub placeholders in synced session transcripts"
47
76
  regexes = [
@@ -52,6 +81,7 @@ regexes = [
52
81
  ]
53
82
  paths = [
54
83
  '''^shared/projects/[^/]+/.*\.jsonl$''',
84
+ '''^shared/projects/[^/]+/memory/[^/]+\.md$''',
55
85
  ]
56
86
  condition = "AND"
57
87
 
@@ -64,7 +94,13 @@ condition = "AND"
64
94
  # regexTarget = "line") keeps this from whitelisting a bare token: a real
65
95
  # secret is never preceded by an SSH key-type label and the SHA256: scheme
66
96
  # prefix. `condition = "AND"` plus the session-jsonl path scope double-locks
67
- # it to synced transcripts.
97
+ # it to synced transcripts. Also scoped to `shared/projects/<logical>/memory/*.md`:
98
+ # this is plausible content in a curated memory note documenting a commit
99
+ # signature-verification procedure, and the structural `with <keytype> key
100
+ # SHA256:` anchor keeps the false-negative risk low there too. Also scoped
101
+ # (recursively) to `shared/skills/<name>/**`: a skill documenting a
102
+ # signature-verification procedure can plausibly quote the same fingerprint
103
+ # line shape, with the same low false-negative risk.
68
104
  [[allowlists]]
69
105
  description = "claude-nomad: SSH public-key fingerprints (with <keytype> key SHA256:<b64>) in git signature output in synced session transcripts"
70
106
  regexTarget = "line"
@@ -73,6 +109,8 @@ regexes = [
73
109
  ]
74
110
  paths = [
75
111
  '''^shared/projects/[^/]+/.*\.jsonl$''',
112
+ '''^shared/projects/[^/]+/memory/[^/]+\.md$''',
113
+ '''^shared/skills/[^/]+/.*$''',
76
114
  ]
77
115
  condition = "AND"
78
116
 
@@ -84,7 +122,10 @@ condition = "AND"
84
122
  # above keys on. Anchoring on the surrounding `key:`/`rule:` structure (via
85
123
  # regexTarget = "line") keeps this from whitelisting a bare token: a real API
86
124
  # key is never followed by `\n rule: <lang>:S####`. `condition = "AND"` plus
87
- # the session-jsonl path scope double-locks it to synced transcripts.
125
+ # the session-jsonl path scope double-locks it to synced transcripts. Also
126
+ # scoped (recursively) to `shared/skills/<name>/**`: a skill documenting a
127
+ # SonarCloud triage procedure can plausibly quote the same issue-listing
128
+ # pair shape, with the same low false-negative risk.
88
129
  [[allowlists]]
89
130
  description = "claude-nomad: SonarCloud issue-listing output (key: <id> / rule: <lang>:S<n>) in synced session transcripts"
90
131
  regexTarget = "line"
@@ -93,5 +134,6 @@ regexes = [
93
134
  ]
94
135
  paths = [
95
136
  '''^shared/projects/[^/]+/.*\.jsonl$''',
137
+ '''^shared/skills/[^/]+/.*$''',
96
138
  ]
97
139
  condition = "AND"
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.62.0](https://github.com/funkadelic/claude-nomad/compare/v0.61.0...v0.62.0) (2026-07-18)
4
+
5
+
6
+ ### Added
7
+
8
+ * **crash-handler:** redacted crash reports for unexpected errors ([#433](https://github.com/funkadelic/claude-nomad/issues/433)) ([cb2d23c](https://github.com/funkadelic/claude-nomad/commit/cb2d23c16165b0004a8769a8ab5c60af026c9577))
9
+ * **exit-codes:** documented exit-code contract for scripted callers ([#432](https://github.com/funkadelic/claude-nomad/issues/432)) ([890e6a2](https://github.com/funkadelic/claude-nomad/commit/890e6a2a28d37e6559f7167ae57c695b4d1337f5))
10
+ * **push:** handle shared/skills secrets at parity with sessions and memory ([#431](https://github.com/funkadelic/claude-nomad/issues/431)) ([759262c](https://github.com/funkadelic/claude-nomad/commit/759262c52aeaf4e2913fc1421ccd90260327c882))
11
+
12
+
13
+ ### Dependencies
14
+
15
+ * bump markdownlint-cli2 from 0.23.0 to 0.23.1 ([#434](https://github.com/funkadelic/claude-nomad/issues/434)) ([68c6402](https://github.com/funkadelic/claude-nomad/commit/68c6402cea2dbc3a8f9c1eb8fd8db0a416005a53))
16
+
17
+ ## [0.61.0](https://github.com/funkadelic/claude-nomad/compare/v0.60.0...v0.61.0) (2026-07-17)
18
+
19
+
20
+ ### Added
21
+
22
+ * **push:** handle memory/*.md secrets at parity with session transcripts ([#427](https://github.com/funkadelic/claude-nomad/issues/427)) ([d1e544c](https://github.com/funkadelic/claude-nomad/commit/d1e544c4f402dae80e319c62ed1fae903fef6e4b))
23
+
24
+
25
+ ### Changed
26
+
27
+ * **publish:** checkout in smoke-test so setup-node can read .nvmrc ([#424](https://github.com/funkadelic/claude-nomad/issues/424)) ([3d8fd2c](https://github.com/funkadelic/claude-nomad/commit/3d8fd2c66ba7947a9326c46f997c336793786efc))
28
+
29
+
30
+ ### Documentation
31
+
32
+ * correct release-bump, Stryker HOME, and offboarding details ([#429](https://github.com/funkadelic/claude-nomad/issues/429)) ([bb5f0fe](https://github.com/funkadelic/claude-nomad/commit/bb5f0fede4cafb848609134bbd1581ac62d42f2c))
33
+ * drop redundant overview file tree in how-it-works ([#428](https://github.com/funkadelic/claude-nomad/issues/428)) ([dd795c8](https://github.com/funkadelic/claude-nomad/commit/dd795c831b876be3ed6bfe1b1313c8ce8f108715))
34
+ * **site:** show claude-nomad version badge in the header ([#430](https://github.com/funkadelic/claude-nomad/issues/430)) ([18d5e86](https://github.com/funkadelic/claude-nomad/commit/18d5e864cd5579d79a79fdd8060352afedcc32fe))
35
+
36
+
37
+ ### Testing
38
+
39
+ * **integration:** cover recovery, sync, dry-run, manifest, and eject flows ([#426](https://github.com/funkadelic/claude-nomad/issues/426)) ([c9c5223](https://github.com/funkadelic/claude-nomad/commit/c9c5223117426439ad57e2442137891c379af1f7))
40
+
3
41
  ## [0.60.0](https://github.com/funkadelic/claude-nomad/compare/v0.59.0...v0.60.0) (2026-07-15)
4
42
 
5
43
 
package/README.md CHANGED
@@ -45,6 +45,9 @@ survives different file paths and your secrets never ride along.
45
45
  entirely and can leak a secret that `nomad push` would have caught. Steady-state pushes scan only
46
46
  the transcripts that changed since the last successful push (incremental); a cold start, a
47
47
  gitleaks version change, a config file change, or `--full-scan` forces a full rescan.
48
+ `nomad doctor --check-shared` also runs a read-only advisory over memory notes and skill files
49
+ already synced to the repo, flagging (but never blocking on) a secret that already made it through
50
+ in a past push; the fix is the same interactive Redact step `nomad push` offers.
48
51
  - **Preview before you trust it.** `nomad diff` shows offline what a pull would change (gsd-owned
49
52
  hook churn is filtered the same as on pull, so the preview matches what a real pull writes), and
50
53
  `--dry-run` on pull and push prints the plan without writing anything.
@@ -297,6 +300,51 @@ version-staleness check and `nomad doctor --check-schema`. The CLI works without
297
300
  curl or wget needed) and verifies that `shared/` and a valid `path-map.json` are present there; it
298
301
  skips with a `⚠︎` when the ref is unavailable, and is non-fatal in all cases.
299
302
 
303
+ ## Exit codes
304
+
305
+ Every `nomad` subcommand exits with one of a small set of codes, so a script or cron wrapper can
306
+ branch on `$?` without parsing stderr text.
307
+
308
+ | Code | Name | Meaning |
309
+ | ---- | --------------- | ------------------------------------------------------------------------------------ |
310
+ | 0 | Success | Completed successfully. |
311
+ | 1 | Generic failure | Unclassified failure; the default for any error not covered below. |
312
+ | 2 | Usage | Bad argv: an unknown subcommand, an unknown flag, or a malformed flag value. |
313
+ | 4 | Conflict | The sync repo is wedged (e.g. an unresolved rebase) and needs manual git resolution. |
314
+ | 5 | Leak blocked | gitleaks confirmed a secret in the staged tree and the push was aborted. |
315
+
316
+ A run skipped because another nomad process already holds the lock also exits 0: this is an
317
+ intentional no-op skip, not a failure, so a backgrounded shell-rc or cron invocation never raises a
318
+ false alarm from a concurrent run. Value `3` is reserved for future use.
319
+
320
+ ## Crash reports
321
+
322
+ If `nomad` ever hits an unexpected bug, it no longer dumps a raw stack trace at you. Instead it
323
+ prints a short "this looks like a bug" banner (with a link to the issue tracker) and writes a small
324
+ report you can attach to a bug report if you choose. The exit code is unchanged: an unexpected crash
325
+ exits `1`, and a documented failure still exits with its own code from the table above.
326
+
327
+ What this means for you:
328
+
329
+ - **The report stays on your machine.** It is written to `~/.cache/claude-nomad/crash/` and nothing
330
+ is ever uploaded anywhere. The file just sits there until you decide to share it or delete it.
331
+ - **The saved report is scrubbed twice.** First a structural pass rewrites your home directory to
332
+ `~` and your hostname to a placeholder (absolute paths are personal information a secret scanner
333
+ would not catch). Then a best-effort secret scan runs the same gitleaks-based redaction nomad
334
+ already uses for session transcripts. The secret scan works on a temporary, owner-only (`0o600`)
335
+ copy that already has the structural scrub applied; that scratch file is deleted immediately after
336
+ the scan, and only the fully-redacted report is kept.
337
+ - **It degrades safely without gitleaks.** If gitleaks is not installed, the structural scrub still
338
+ runs and the report is still written, with a one-line note that the secret scan did not run, so
339
+ give it a glance before posting it publicly.
340
+ - **It is small and bounded.** The report contains only the nomad version, the command you ran
341
+ (bounded, and including any flag values you typed), the error name and message, a trimmed stack,
342
+ your platform, the Node.js version, and a timestamp. It never includes an environment dump or the
343
+ contents of any file.
344
+ - **The directory manages itself.** Only the most recent reports are kept; older ones are pruned
345
+ automatically on the next crash. There is no `nomad clean` flag for the crash directory, by
346
+ design: it self-manages.
347
+
300
348
  ## Learn more
301
349
 
302
350
  - [How it works](https://funkadelic.github.io/claude-nomad/how-it-works/) -- path remapping,