claude-nomad 0.47.0 → 0.47.1
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/dist/nomad.mjs +49 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.47.1](https://github.com/funkadelic/claude-nomad/compare/v0.47.0...v0.47.1) (2026-06-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
* **extras:** preserve host-local deny-set files on .claude pull ([#276](https://github.com/funkadelic/claude-nomad/issues/276)) ([3742c3e](https://github.com/funkadelic/claude-nomad/commit/3742c3e4067c1c986e7f182011581d4c867847b0))
|
|
9
|
+
|
|
3
10
|
## [0.47.0](https://github.com/funkadelic/claude-nomad/compare/v0.46.0...v0.47.0) (2026-06-09)
|
|
4
11
|
|
|
5
12
|
|
package/dist/nomad.mjs
CHANGED
|
@@ -4240,7 +4240,7 @@ function listDivergingFiles(a, b) {
|
|
|
4240
4240
|
|
|
4241
4241
|
// src/extras-sync.core.ts
|
|
4242
4242
|
init_config();
|
|
4243
|
-
import { cpSync as cpSync6, existsSync as existsSync30, rmSync as rmSync10 } from "node:fs";
|
|
4243
|
+
import { cpSync as cpSync6, existsSync as existsSync30, lstatSync as lstatSync8, readdirSync as readdirSync11, rmSync as rmSync10 } from "node:fs";
|
|
4244
4244
|
import { basename, join as join36 } from "node:path";
|
|
4245
4245
|
|
|
4246
4246
|
// src/extras-sync.guards.ts
|
|
@@ -4314,6 +4314,36 @@ function copyExtrasFiltered(src, dst, blockSet) {
|
|
|
4314
4314
|
filter: (srcEntry) => srcEntry === src || !blockSet.has(basename(srcEntry))
|
|
4315
4315
|
});
|
|
4316
4316
|
}
|
|
4317
|
+
function prunePreservingDenied(src, dst, blockSet) {
|
|
4318
|
+
for (const name of readdirSync11(dst)) {
|
|
4319
|
+
if (blockSet.has(name)) continue;
|
|
4320
|
+
const dstPath = join36(dst, name);
|
|
4321
|
+
const srcStat = lstatSync8(join36(src, name), { throwIfNoEntry: false });
|
|
4322
|
+
if (srcStat === void 0) {
|
|
4323
|
+
rmSync10(dstPath, { recursive: true, force: true });
|
|
4324
|
+
continue;
|
|
4325
|
+
}
|
|
4326
|
+
const dstStat = lstatSync8(dstPath);
|
|
4327
|
+
if (srcStat.isDirectory() && dstStat.isDirectory()) {
|
|
4328
|
+
prunePreservingDenied(join36(src, name), dstPath, blockSet);
|
|
4329
|
+
} else if (srcStat.isDirectory() !== dstStat.isDirectory()) {
|
|
4330
|
+
rmSync10(dstPath, { recursive: true, force: true });
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
function copyExtrasFilteredPreserving(src, dst, blockSet) {
|
|
4335
|
+
const dstStat = lstatSync8(dst, { throwIfNoEntry: false });
|
|
4336
|
+
if (dstStat !== void 0) {
|
|
4337
|
+
if (dstStat.isDirectory()) prunePreservingDenied(src, dst, blockSet);
|
|
4338
|
+
else rmSync10(dst, { recursive: true, force: true });
|
|
4339
|
+
}
|
|
4340
|
+
cpSync6(src, dst, {
|
|
4341
|
+
recursive: true,
|
|
4342
|
+
force: true,
|
|
4343
|
+
verbatimSymlinks: true,
|
|
4344
|
+
filter: (srcEntry) => srcEntry === src || !blockSet.has(basename(srcEntry))
|
|
4345
|
+
});
|
|
4346
|
+
}
|
|
4317
4347
|
|
|
4318
4348
|
// src/extras-sync.ts
|
|
4319
4349
|
init_utils();
|
|
@@ -4381,12 +4411,16 @@ function remapExtrasPull(ts, opts = {}) {
|
|
|
4381
4411
|
// Snapshot the host-side dst BEFORE copyExtras clobbers it. Anchor on
|
|
4382
4412
|
// localRoot so the backup tree mirrors the project layout.
|
|
4383
4413
|
(dst, localRoot) => backupExtrasWrite(dst, ts, localRoot),
|
|
4384
|
-
// Pull
|
|
4385
|
-
//
|
|
4386
|
-
//
|
|
4387
|
-
//
|
|
4388
|
-
//
|
|
4389
|
-
|
|
4414
|
+
// Pull routes `.claude` through copyExtrasFilteredPreserving so host-local
|
|
4415
|
+
// deny-set files already on disk (e.g. settings.local.json) are preserved
|
|
4416
|
+
// instead of being wiped by a blanket rmSync. The same deny-set filter still
|
|
4417
|
+
// strips blocked basenames from the src copy (defense-in-depth: a repo
|
|
4418
|
+
// poisoned out-of-band cannot restore a blocked per-host file). Synced
|
|
4419
|
+
// non-deny files that are absent from src are still mirror-pruned. This
|
|
4420
|
+
// preservation is `.claude`-only; `.planning` and `CLAUDE.md` use the
|
|
4421
|
+
// exact-mirror copyExtras (documented restore semantics; they rarely carry
|
|
4422
|
+
// host-local files, so the exact mirror is the correct default).
|
|
4423
|
+
(src, dst, dirname7) => dirname7 === ".claude" ? copyExtrasFilteredPreserving(src, dst, extrasDenySet(dirname7)) : copyExtras(src, dst)
|
|
4390
4424
|
);
|
|
4391
4425
|
return { unmapped, skipped, pulled: done, wouldPull: would };
|
|
4392
4426
|
}
|
|
@@ -4417,7 +4451,7 @@ init_config();
|
|
|
4417
4451
|
init_utils();
|
|
4418
4452
|
init_utils_fs();
|
|
4419
4453
|
init_utils_json();
|
|
4420
|
-
import { existsSync as existsSync33, lstatSync as
|
|
4454
|
+
import { existsSync as existsSync33, lstatSync as lstatSync9, rmSync as rmSync11 } from "node:fs";
|
|
4421
4455
|
import { join as join39 } from "node:path";
|
|
4422
4456
|
function emitAutoMove(onPreview, linkPath, ts, name) {
|
|
4423
4457
|
if (onPreview) {
|
|
@@ -4434,14 +4468,14 @@ function emitCreate(onPreview, from, to) {
|
|
|
4434
4468
|
}
|
|
4435
4469
|
}
|
|
4436
4470
|
function isAlreadySymlink(linkPath) {
|
|
4437
|
-
return existsSync33(linkPath) &&
|
|
4471
|
+
return existsSync33(linkPath) && lstatSync9(linkPath).isSymbolicLink();
|
|
4438
4472
|
}
|
|
4439
4473
|
function runAutoMovePasses(linkNames, claude, repo, ts, dryRun, onPreview) {
|
|
4440
4474
|
for (const name of linkNames) {
|
|
4441
4475
|
const linkPath = join39(claude, name);
|
|
4442
4476
|
const target = join39(repo, "shared", name);
|
|
4443
4477
|
if (!existsSync33(linkPath)) continue;
|
|
4444
|
-
if (
|
|
4478
|
+
if (lstatSync9(linkPath).isSymbolicLink()) continue;
|
|
4445
4479
|
if (!existsSync33(target)) continue;
|
|
4446
4480
|
if (dryRun) {
|
|
4447
4481
|
emitAutoMove(onPreview, linkPath, ts, name);
|
|
@@ -5146,7 +5180,7 @@ init_color();
|
|
|
5146
5180
|
init_config();
|
|
5147
5181
|
init_config_sharedDirs_guard();
|
|
5148
5182
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
5149
|
-
import { copyFileSync, existsSync as existsSync36, mkdirSync as mkdirSync9, readdirSync as
|
|
5183
|
+
import { copyFileSync, existsSync as existsSync36, mkdirSync as mkdirSync9, readdirSync as readdirSync12, rmSync as rmSync12 } from "node:fs";
|
|
5150
5184
|
import { homedir as homedir5 } from "node:os";
|
|
5151
5185
|
import { join as join42 } from "node:path";
|
|
5152
5186
|
init_push_leak_verdict();
|
|
@@ -5166,7 +5200,7 @@ function stageSessions(tmpRoot, map) {
|
|
|
5166
5200
|
const localProjects = join42(claudeHome(), "projects");
|
|
5167
5201
|
if (!existsSync36(localProjects)) return 0;
|
|
5168
5202
|
let staged = 0;
|
|
5169
|
-
for (const dir of
|
|
5203
|
+
for (const dir of readdirSync12(localProjects)) {
|
|
5170
5204
|
const logical = reverse.get(dir);
|
|
5171
5205
|
if (!logical) continue;
|
|
5172
5206
|
copyDirJsonlOnly(join42(localProjects, dir), join42(tmpRoot, "shared", "projects", logical));
|
|
@@ -5830,7 +5864,7 @@ function parsePushArgs(argv) {
|
|
|
5830
5864
|
// package.json
|
|
5831
5865
|
var package_default = {
|
|
5832
5866
|
name: "claude-nomad",
|
|
5833
|
-
version: "0.47.
|
|
5867
|
+
version: "0.47.1",
|
|
5834
5868
|
type: "module",
|
|
5835
5869
|
description: "Sync Claude Code config (~/.claude/) across machines via a private Git repo, with path remapping and per-host settings overrides.",
|
|
5836
5870
|
keywords: [
|
|
@@ -6031,7 +6065,7 @@ var DEFAULT_HELP = [
|
|
|
6031
6065
|
init_config();
|
|
6032
6066
|
init_utils();
|
|
6033
6067
|
init_utils_json();
|
|
6034
|
-
import { existsSync as existsSync41, readFileSync as readFileSync14, readdirSync as
|
|
6068
|
+
import { existsSync as existsSync41, readFileSync as readFileSync14, readdirSync as readdirSync13 } from "node:fs";
|
|
6035
6069
|
import { join as join47 } from "node:path";
|
|
6036
6070
|
function resumeCmd(sessionId) {
|
|
6037
6071
|
if (!/^[A-Za-z0-9_-]+$/.test(sessionId) || sessionId.length > 128) {
|
|
@@ -6076,7 +6110,7 @@ function resumeCmd(sessionId) {
|
|
|
6076
6110
|
console.log(`cd ${shQuote(hit.localPath)} && claude --resume ${shQuote(sessionId)}`);
|
|
6077
6111
|
}
|
|
6078
6112
|
function findTranscriptPath(projectsRoot, sessionId) {
|
|
6079
|
-
for (const dir of
|
|
6113
|
+
for (const dir of readdirSync13(projectsRoot)) {
|
|
6080
6114
|
const candidate = join47(projectsRoot, dir, `${sessionId}.jsonl`);
|
|
6081
6115
|
if (existsSync41(candidate)) return candidate;
|
|
6082
6116
|
}
|
package/package.json
CHANGED