claude-nomad 0.62.0 → 0.62.2
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 +26 -0
- package/dist/nomad.mjs +33 -26
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.62.2](https://github.com/funkadelic/claude-nomad/compare/v0.62.1...v0.62.2) (2026-07-21)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
* **push:** close the interactive-push secret-gate fail-open ([#446](https://github.com/funkadelic/claude-nomad/issues/446)) ([5de8975](https://github.com/funkadelic/claude-nomad/commit/5de8975f83f5e99711041ef6025fe69933b1ab15))
|
|
9
|
+
|
|
10
|
+
## [0.62.1](https://github.com/funkadelic/claude-nomad/compare/v0.62.0...v0.62.1) (2026-07-20)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
* **coderabbit:** skip Snyk security-bump PRs ([#436](https://github.com/funkadelic/claude-nomad/issues/436)) ([10ded7c](https://github.com/funkadelic/claude-nomad/commit/10ded7cb5657b1180f8d33b1fbf73c3000fea6c3))
|
|
16
|
+
* **deps:** refresh lockfile for brace-expansion and fast-uri patches ([#445](https://github.com/funkadelic/claude-nomad/issues/445)) ([d4ea973](https://github.com/funkadelic/claude-nomad/commit/d4ea9739a450c71763a98769f48a7deefb38eca5))
|
|
17
|
+
* drop 3 dead exports flagged by knip ([#437](https://github.com/funkadelic/claude-nomad/issues/437)) ([51750d8](https://github.com/funkadelic/claude-nomad/commit/51750d8801f96b4bca8137ac863c851d63f7c074))
|
|
18
|
+
* **redact:** extract shared live-session guard ([#438](https://github.com/funkadelic/claude-nomad/issues/438)) ([59d8208](https://github.com/funkadelic/claude-nomad/commit/59d82085aaf59a53d8341de6850240fdce4aa7ea))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Dependencies
|
|
22
|
+
|
|
23
|
+
* bump actions/setup-node from 6.4.0 to 7.0.0 ([#441](https://github.com/funkadelic/claude-nomad/issues/441)) ([f24a847](https://github.com/funkadelic/claude-nomad/commit/f24a847476e6ec63c4e85715c2ebfc42cce138c3))
|
|
24
|
+
* bump astro from 7.0.7 to 7.1.3 in /docs-site ([#444](https://github.com/funkadelic/claude-nomad/issues/444)) ([01d56b7](https://github.com/funkadelic/claude-nomad/commit/01d56b7f20e1ea71f1dd64b7076411abc4fe9c02))
|
|
25
|
+
* bump SonarSource/sonarqube-scan-action from 8.2.0 to 8.2.1 ([#443](https://github.com/funkadelic/claude-nomad/issues/443)) ([2928f0f](https://github.com/funkadelic/claude-nomad/commit/2928f0f87e40147a17b068b0053486fee6cbd6e6))
|
|
26
|
+
* bump the codeql-action group with 2 updates ([#440](https://github.com/funkadelic/claude-nomad/issues/440)) ([8d30319](https://github.com/funkadelic/claude-nomad/commit/8d303191e692128c5fdc9dfaab7ff1f16eb0780d))
|
|
27
|
+
* bump the dev-dependencies group with 2 updates ([#442](https://github.com/funkadelic/claude-nomad/issues/442)) ([22427db](https://github.com/funkadelic/claude-nomad/commit/22427dbbe4fb3f455a6ec24f0d4105dee904ee17))
|
|
28
|
+
|
|
3
29
|
## [0.62.0](https://github.com/funkadelic/claude-nomad/compare/v0.61.0...v0.62.0) (2026-07-18)
|
|
4
30
|
|
|
5
31
|
|
package/dist/nomad.mjs
CHANGED
|
@@ -4895,12 +4895,12 @@ import { isAbsolute as isAbsolute2, resolve as resolve3, sep as sep7 } from "nod
|
|
|
4895
4895
|
// src/commands.push.recovery.redact.ts
|
|
4896
4896
|
init_config();
|
|
4897
4897
|
init_config_sharedDirs_guard();
|
|
4898
|
-
import { cpSync as cpSync8, existsSync as existsSync32, mkdirSync as mkdirSync10
|
|
4898
|
+
import { cpSync as cpSync8, existsSync as existsSync32, mkdirSync as mkdirSync10 } from "node:fs";
|
|
4899
4899
|
import { dirname as dirname10, join as join39, sep as sep5 } from "node:path";
|
|
4900
4900
|
|
|
4901
4901
|
// src/commands.redact.ts
|
|
4902
4902
|
init_config();
|
|
4903
|
-
import { existsSync as existsSync30
|
|
4903
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
4904
4904
|
import { dirname as dirname9, join as join37 } from "node:path";
|
|
4905
4905
|
|
|
4906
4906
|
// src/commands.redact.subtree.ts
|
|
@@ -4936,6 +4936,10 @@ function newestSubtreeMtimeMs(mainPath, subtreeFiles, statMtime = (p) => statSyn
|
|
|
4936
4936
|
}
|
|
4937
4937
|
return newest;
|
|
4938
4938
|
}
|
|
4939
|
+
function isSubtreeActive(mainPath, subtreeFiles, now) {
|
|
4940
|
+
const subtreeMtime = newestSubtreeMtimeMs(mainPath, subtreeFiles, (p) => statSync6(p).mtimeMs);
|
|
4941
|
+
return isRecentlyModified(subtreeMtime, now);
|
|
4942
|
+
}
|
|
4939
4943
|
function applySubtreeRedactions(mainPath, mainFindings, subtreeFiles, rule, ts, scan, dryRun) {
|
|
4940
4944
|
const dirty = [];
|
|
4941
4945
|
if (mainFindings.length > 0) dirty.push({ path: mainPath, findings: mainFindings });
|
|
@@ -5059,8 +5063,7 @@ function cmdRedact(opts, nowMs = Date.now, scan = scanFile) {
|
|
|
5059
5063
|
}
|
|
5060
5064
|
const sessionDir = join37(dirname9(localPath), id);
|
|
5061
5065
|
const subtreeFiles = listSubtreeFiles(sessionDir);
|
|
5062
|
-
|
|
5063
|
-
if (isRecentlyModified(subtreeMtime, nowMs())) {
|
|
5066
|
+
if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
|
|
5064
5067
|
log(
|
|
5065
5068
|
`session ${id} was modified recently and may be active.
|
|
5066
5069
|
Refusing to rewrite a potentially live transcript.
|
|
@@ -5260,8 +5263,7 @@ function preflightRedactable(f, map, nowMs) {
|
|
|
5260
5263
|
if (localPath === null) return `session ${sid}: local transcript not found`;
|
|
5261
5264
|
const sessionDir = join39(dirname10(localPath), sid);
|
|
5262
5265
|
const subtreeFiles = listSubtreeFiles(sessionDir);
|
|
5263
|
-
|
|
5264
|
-
if (isRecentlyModified(subtreeMtime, nowMs())) {
|
|
5266
|
+
if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
|
|
5265
5267
|
return `session ${sid}: looks active (modified within the last 5 minutes)`;
|
|
5266
5268
|
}
|
|
5267
5269
|
if (resolveStagedDir(localPath, map, claudeHome(), repoHome()) === null) {
|
|
@@ -5290,8 +5292,7 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
|
|
|
5290
5292
|
}
|
|
5291
5293
|
const sessionDir = join39(dirname10(localPath), sid);
|
|
5292
5294
|
const subtreeFiles = listSubtreeFiles(sessionDir);
|
|
5293
|
-
|
|
5294
|
-
if (isRecentlyModified(subtreeMtime, nowMs())) {
|
|
5295
|
+
if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
|
|
5295
5296
|
return refuse(
|
|
5296
5297
|
`session ${sid} looks active (modified within the last 5 minutes); refusing to redact, no changes made.
|
|
5297
5298
|
End the session and choose Redact again, or choose Drop session (holds this session back from the push, local copy kept) or Skip.`
|
|
@@ -5354,7 +5355,7 @@ import {
|
|
|
5354
5355
|
mkdirSync as mkdirSync12,
|
|
5355
5356
|
readFileSync as readFileSync16,
|
|
5356
5357
|
realpathSync as realpathSync4,
|
|
5357
|
-
statSync as
|
|
5358
|
+
statSync as statSync7,
|
|
5358
5359
|
writeFileSync as writeFileSync8
|
|
5359
5360
|
} from "node:fs";
|
|
5360
5361
|
import { dirname as dirname11, join as join42, sep as sep6 } from "node:path";
|
|
@@ -5435,7 +5436,7 @@ function resolveSkillLocalPath(name, relPath) {
|
|
|
5435
5436
|
const realLocal = realpathSync4(localPath);
|
|
5436
5437
|
const realRoot = realpathSync4(skillsRoot);
|
|
5437
5438
|
if (!realLocal.startsWith(realRoot + sep6)) return null;
|
|
5438
|
-
if (!
|
|
5439
|
+
if (!statSync7(realLocal).isFile()) return null;
|
|
5439
5440
|
} catch {
|
|
5440
5441
|
return null;
|
|
5441
5442
|
}
|
|
@@ -5725,6 +5726,9 @@ function allowThenRescan(append, scanVerdict, repoHome2) {
|
|
|
5725
5726
|
throw err;
|
|
5726
5727
|
}
|
|
5727
5728
|
}
|
|
5729
|
+
function leakBlockedFatal(recovery) {
|
|
5730
|
+
return new NomadFatal(recovery ?? "gitleaks detected secrets", { code: EXIT.LEAK_BLOCKED });
|
|
5731
|
+
}
|
|
5728
5732
|
function makeRealPrompt() {
|
|
5729
5733
|
return async (prompt) => {
|
|
5730
5734
|
const rl = createInterface2({
|
|
@@ -5771,9 +5775,10 @@ async function resolveLeakFindings(verdict, ts, map, deps = {}) {
|
|
|
5771
5775
|
);
|
|
5772
5776
|
}
|
|
5773
5777
|
if (!isTTYCheck()) {
|
|
5774
|
-
throw
|
|
5775
|
-
|
|
5776
|
-
|
|
5778
|
+
throw leakBlockedFatal(current.recovery);
|
|
5779
|
+
}
|
|
5780
|
+
if (current.leak && current.findings.length === 0) {
|
|
5781
|
+
throw leakBlockedFatal(current.recovery);
|
|
5777
5782
|
}
|
|
5778
5783
|
const prompt = makePromptFn();
|
|
5779
5784
|
printLegend();
|
|
@@ -5788,6 +5793,7 @@ async function resolveLeakFindings(verdict, ts, map, deps = {}) {
|
|
|
5788
5793
|
gitOrFatal(["add", "-A"], "git add", repo);
|
|
5789
5794
|
current = scanVerdict(repo);
|
|
5790
5795
|
}
|
|
5796
|
+
if (current.leak) throw leakBlockedFatal(current.recovery);
|
|
5791
5797
|
return current;
|
|
5792
5798
|
}
|
|
5793
5799
|
|
|
@@ -6223,7 +6229,7 @@ function parseDoctorArgs(args) {
|
|
|
6223
6229
|
// src/commands.drop-session.ts
|
|
6224
6230
|
init_config();
|
|
6225
6231
|
import { execFileSync as execFileSync20 } from "node:child_process";
|
|
6226
|
-
import { existsSync as existsSync38, readdirSync as readdirSync15, statSync as
|
|
6232
|
+
import { existsSync as existsSync38, readdirSync as readdirSync15, statSync as statSync8 } from "node:fs";
|
|
6227
6233
|
import { join as join47, relative as relative6 } from "node:path";
|
|
6228
6234
|
|
|
6229
6235
|
// src/commands.drop-session.git.ts
|
|
@@ -6343,7 +6349,7 @@ function collectMatches(repoProjects, id, repo) {
|
|
|
6343
6349
|
matches.push(relative6(repo, candidate));
|
|
6344
6350
|
}
|
|
6345
6351
|
const dir = join47(repoProjects, logical, id);
|
|
6346
|
-
if (existsSync38(dir) &&
|
|
6352
|
+
if (existsSync38(dir) && statSync8(dir).isDirectory()) {
|
|
6347
6353
|
const dirRel = relative6(repo, dir);
|
|
6348
6354
|
const staged = expandStagedDir(dirRel, repo);
|
|
6349
6355
|
if (staged.length > 0) matches.push(...staged);
|
|
@@ -6487,7 +6493,7 @@ init_config();
|
|
|
6487
6493
|
|
|
6488
6494
|
// src/extras-sync.ts
|
|
6489
6495
|
init_config();
|
|
6490
|
-
import { existsSync as existsSync40, statSync as
|
|
6496
|
+
import { existsSync as existsSync40, statSync as statSync9 } from "node:fs";
|
|
6491
6497
|
import { join as join50 } from "node:path";
|
|
6492
6498
|
init_utils();
|
|
6493
6499
|
init_utils_json();
|
|
@@ -6799,7 +6805,7 @@ function divergenceCheckExtras(ts, prePostHeads) {
|
|
|
6799
6805
|
divergenceWarnLine({
|
|
6800
6806
|
dirname: dirname13,
|
|
6801
6807
|
logical,
|
|
6802
|
-
isDir:
|
|
6808
|
+
isDir: statSync9(local).isDirectory(),
|
|
6803
6809
|
count: modified.length,
|
|
6804
6810
|
projectBackupRoot
|
|
6805
6811
|
})
|
|
@@ -7466,7 +7472,7 @@ import { join as join57 } from "node:path";
|
|
|
7466
7472
|
|
|
7467
7473
|
// src/commands.push.selection.ts
|
|
7468
7474
|
init_config();
|
|
7469
|
-
import { existsSync as existsSync43, statSync as
|
|
7475
|
+
import { existsSync as existsSync43, statSync as statSync10 } from "node:fs";
|
|
7470
7476
|
import { join as join53 } from "node:path";
|
|
7471
7477
|
init_utils_json();
|
|
7472
7478
|
function buildCurrentMap(map) {
|
|
@@ -7479,7 +7485,7 @@ function buildCurrentMap(map) {
|
|
|
7479
7485
|
const localDir = join53(claude, "projects", encodePath(localPath));
|
|
7480
7486
|
if (!existsSync43(localDir)) continue;
|
|
7481
7487
|
for (const f of enumerateSourceFiles(localDir)) {
|
|
7482
|
-
const st =
|
|
7488
|
+
const st = statSync10(f);
|
|
7483
7489
|
current[f] = { size: st.size, mtime: st.mtimeMs };
|
|
7484
7490
|
}
|
|
7485
7491
|
}
|
|
@@ -7883,6 +7889,7 @@ async function commitAndPush(st, ts, map, resolution, repo, newManifest, render)
|
|
|
7883
7889
|
if (!render) log("push (leak recovery)");
|
|
7884
7890
|
renderPushTree(st, verdict);
|
|
7885
7891
|
verdict = await resolveLeakFindings(verdict, ts, map, resolution);
|
|
7892
|
+
if (verdict.leak) throw leakBlockedFatal(verdict.recovery);
|
|
7886
7893
|
}
|
|
7887
7894
|
gitOrFatal(["commit", "-m", `chore: sync from ${HOST}`], "git commit", repo);
|
|
7888
7895
|
withSpinner("Pushing", () => gitOrFatal(["push"], "git push", repo));
|
|
@@ -8251,7 +8258,7 @@ init_config();
|
|
|
8251
8258
|
|
|
8252
8259
|
// src/crash-report.write.ts
|
|
8253
8260
|
init_config();
|
|
8254
|
-
import { mkdirSync as mkdirSync16, readdirSync as readdirSync18, statSync as
|
|
8261
|
+
import { mkdirSync as mkdirSync16, readdirSync as readdirSync18, statSync as statSync11, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "node:fs";
|
|
8255
8262
|
import { join as join60 } from "node:path";
|
|
8256
8263
|
|
|
8257
8264
|
// src/crash-report.ts
|
|
@@ -8364,7 +8371,7 @@ function listCrashFiles(dir = crashDir()) {
|
|
|
8364
8371
|
try {
|
|
8365
8372
|
return readdirSync18(dir).flatMap((name) => {
|
|
8366
8373
|
try {
|
|
8367
|
-
return [{ name, mtimeMs:
|
|
8374
|
+
return [{ name, mtimeMs: statSync11(join60(dir, name)).mtimeMs }];
|
|
8368
8375
|
} catch {
|
|
8369
8376
|
return [];
|
|
8370
8377
|
}
|
|
@@ -8525,7 +8532,7 @@ init_config();
|
|
|
8525
8532
|
init_utils();
|
|
8526
8533
|
init_utils_fs();
|
|
8527
8534
|
init_utils_json();
|
|
8528
|
-
import { copyFileSync as copyFileSync2, cpSync as cpSync10, existsSync as existsSync49, rmSync as rmSync19, statSync as
|
|
8535
|
+
import { copyFileSync as copyFileSync2, cpSync as cpSync10, existsSync as existsSync49, rmSync as rmSync19, statSync as statSync12 } from "node:fs";
|
|
8529
8536
|
import { join as join62 } from "node:path";
|
|
8530
8537
|
function snapshotIntoShared(map) {
|
|
8531
8538
|
const repo = repoHome();
|
|
@@ -8534,7 +8541,7 @@ function snapshotIntoShared(map) {
|
|
|
8534
8541
|
const src = join62(claude, name);
|
|
8535
8542
|
if (!existsSync49(src)) continue;
|
|
8536
8543
|
const dst = join62(repo, "shared", name);
|
|
8537
|
-
if (
|
|
8544
|
+
if (statSync12(src).isDirectory()) {
|
|
8538
8545
|
const gk = join62(dst, ".gitkeep");
|
|
8539
8546
|
if (existsSync49(gk)) rmSync19(gk);
|
|
8540
8547
|
cpSync10(src, dst, { recursive: true, force: false, errorOnExist: true });
|
|
@@ -8676,13 +8683,13 @@ function maybeDisableRepoActions(repoHome2, run) {
|
|
|
8676
8683
|
// src/init.prompt.ts
|
|
8677
8684
|
init_config();
|
|
8678
8685
|
init_utils();
|
|
8679
|
-
import { existsSync as existsSync51, readdirSync as readdirSync19, statSync as
|
|
8686
|
+
import { existsSync as existsSync51, readdirSync as readdirSync19, statSync as statSync13 } from "node:fs";
|
|
8680
8687
|
import { join as join64 } from "node:path";
|
|
8681
8688
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
8682
8689
|
function nonEmptyExists(path) {
|
|
8683
8690
|
if (!existsSync51(path)) return false;
|
|
8684
8691
|
try {
|
|
8685
|
-
if (
|
|
8692
|
+
if (statSync13(path).isDirectory()) return readdirSync19(path).length > 0;
|
|
8686
8693
|
return true;
|
|
8687
8694
|
} catch {
|
|
8688
8695
|
return false;
|
|
@@ -8997,7 +9004,7 @@ function parseSyncArgs(argv) {
|
|
|
8997
9004
|
// package.json
|
|
8998
9005
|
var package_default = {
|
|
8999
9006
|
name: "claude-nomad",
|
|
9000
|
-
version: "0.62.
|
|
9007
|
+
version: "0.62.2",
|
|
9001
9008
|
type: "module",
|
|
9002
9009
|
description: "Sync Claude Code config (~/.claude/) across machines via a private Git repo, with path remapping and per-host settings overrides.",
|
|
9003
9010
|
keywords: [
|
package/package.json
CHANGED