@slats/claude-assets-sync 0.1.4 → 0.2.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/README.md +111 -587
- package/bin/claude-sync.mjs +24 -0
- package/dist/claude-hashes.json +20 -0
- package/dist/commands/index.d.ts +1 -112
- package/dist/commands/runCli/index.d.ts +2 -0
- package/dist/commands/runCli/runCli.cjs +31 -0
- package/dist/commands/runCli/runCli.d.ts +10 -0
- package/dist/commands/runCli/runCli.mjs +29 -0
- package/dist/commands/runCli/type.d.ts +28 -0
- package/dist/commands/runCli/utils/injectOne.cjs +48 -0
- package/dist/commands/runCli/utils/injectOne.d.ts +3 -0
- package/dist/commands/runCli/utils/injectOne.mjs +46 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.cjs +28 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +2 -0
- package/dist/commands/runCli/utils/resolveScopeFlag.mjs +26 -0
- package/dist/commands/runCli/utils/runInject.cjs +36 -0
- package/dist/commands/runCli/utils/runInject.d.ts +2 -0
- package/dist/commands/runCli/utils/runInject.mjs +34 -0
- package/dist/core/buildPlan/buildPlan.cjs +42 -0
- package/dist/core/buildPlan/buildPlan.d.ts +2 -0
- package/dist/core/buildPlan/buildPlan.mjs +40 -0
- package/dist/core/buildPlan/index.d.ts +2 -0
- package/dist/core/buildPlan/type.d.ts +32 -0
- package/dist/core/buildPlan/utils/toPosix.cjs +9 -0
- package/dist/core/buildPlan/utils/toPosix.d.ts +1 -0
- package/dist/core/buildPlan/utils/toPosix.mjs +7 -0
- package/dist/core/buildPlan/utils/walkFiles.cjs +25 -0
- package/dist/core/buildPlan/utils/walkFiles.d.ts +1 -0
- package/dist/core/buildPlan/utils/walkFiles.mjs +23 -0
- package/dist/core/hash/hash.cjs +30 -0
- package/dist/core/hash/hash.d.ts +4 -0
- package/dist/core/hash/hash.mjs +26 -0
- package/dist/core/hash/index.d.ts +1 -0
- package/dist/core/hashManifest/hashManifest.cjs +27 -0
- package/dist/core/hashManifest/hashManifest.d.ts +17 -0
- package/dist/core/hashManifest/hashManifest.mjs +23 -0
- package/dist/core/hashManifest/index.d.ts +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/injectDocs/index.d.ts +2 -0
- package/dist/core/injectDocs/injectDocs.cjs +43 -0
- package/dist/core/injectDocs/injectDocs.d.ts +2 -0
- package/dist/core/injectDocs/injectDocs.mjs +41 -0
- package/dist/core/injectDocs/type.d.ts +30 -0
- package/dist/core/injectDocs/utils/applyAction.cjs +21 -0
- package/dist/core/injectDocs/utils/applyAction.d.ts +2 -0
- package/dist/core/injectDocs/utils/applyAction.mjs +19 -0
- package/dist/core/injectDocs/utils/emitCiForceList.cjs +10 -0
- package/dist/core/injectDocs/utils/emitCiForceList.d.ts +2 -0
- package/dist/core/injectDocs/utils/emitCiForceList.mjs +8 -0
- package/dist/core/injectDocs/utils/printPlan.cjs +20 -0
- package/dist/core/injectDocs/utils/printPlan.d.ts +2 -0
- package/dist/core/injectDocs/utils/printPlan.mjs +18 -0
- package/dist/core/injectDocs/utils/summarize.cjs +27 -0
- package/dist/core/injectDocs/utils/summarize.d.ts +3 -0
- package/dist/core/injectDocs/utils/summarize.mjs +25 -0
- package/dist/core/scope/index.d.ts +1 -0
- package/dist/core/scope/scope.cjs +46 -0
- package/dist/core/scope/scope.d.ts +16 -0
- package/dist/core/scope/scope.mjs +41 -0
- package/dist/core/scope/utils/isDirectory.cjs +14 -0
- package/dist/core/scope/utils/isDirectory.d.ts +1 -0
- package/dist/core/scope/utils/isDirectory.mjs +12 -0
- package/dist/index.cjs +15 -9
- package/dist/index.d.ts +3 -5
- package/dist/index.mjs +7 -3
- package/dist/prompts/confirmForce.cjs +27 -0
- package/dist/prompts/confirmForce.d.ts +1 -0
- package/dist/prompts/confirmForce.mjs +25 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/selectScope.cjs +30 -0
- package/dist/prompts/selectScope.d.ts +2 -0
- package/dist/prompts/selectScope.mjs +28 -0
- package/dist/utils/heartbeat.cjs +25 -0
- package/dist/utils/heartbeat.d.ts +16 -0
- package/dist/utils/heartbeat.mjs +23 -0
- package/dist/utils/logger.cjs +7 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.mjs +7 -0
- package/dist/utils/types.d.ts +1 -252
- package/dist/utils/version.cjs +2 -14
- package/dist/utils/version.d.ts +3 -53
- package/dist/utils/version.mjs +2 -13
- package/docs/bundle-size-decision.md +36 -0
- package/docs/claude/skills/claude-sync-applier/SKILL.md +195 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/claude-md-template.md +77 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/dependency-cruiser.md +126 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/gotchas.md +139 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/package-json-patches.md +130 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/reference-files.md +120 -0
- package/docs/claude/skills/claude-sync-applier/knowledge/smoke-tests.md +102 -0
- package/docs/consumer-integration.md +153 -0
- package/package.json +24 -16
- package/scripts/build-hashes.mjs +30 -0
- package/scripts/buildHashes.d.mts +15 -0
- package/scripts/buildHashes.mjs +82 -0
- package/scripts/claude-build-hashes.mjs +42 -0
- package/scripts/inject-version.js +112 -0
- package/dist/cli.cjs +0 -8
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +0 -7
- package/dist/commands/add.cjs +0 -80
- package/dist/commands/add.d.ts +0 -8
- package/dist/commands/add.mjs +0 -78
- package/dist/commands/list.cjs +0 -94
- package/dist/commands/list.d.ts +0 -15
- package/dist/commands/list.mjs +0 -91
- package/dist/commands/migrate.cjs +0 -9
- package/dist/commands/migrate.d.ts +0 -6
- package/dist/commands/migrate.mjs +0 -7
- package/dist/commands/remove.cjs +0 -127
- package/dist/commands/remove.d.ts +0 -6
- package/dist/commands/remove.mjs +0 -105
- package/dist/commands/status.cjs +0 -193
- package/dist/commands/status.d.ts +0 -6
- package/dist/commands/status.mjs +0 -171
- package/dist/commands/sync.cjs +0 -28
- package/dist/commands/sync.d.ts +0 -6
- package/dist/commands/sync.mjs +0 -26
- package/dist/commands/types.d.ts +0 -89
- package/dist/commands/update.cjs +0 -209
- package/dist/commands/update.d.ts +0 -29
- package/dist/commands/update.mjs +0 -206
- package/dist/components/add/AddCommand.cjs +0 -103
- package/dist/components/add/AddCommand.d.ts +0 -14
- package/dist/components/add/AddCommand.mjs +0 -101
- package/dist/components/add/BulkAddView.cjs +0 -165
- package/dist/components/add/BulkAddView.d.ts +0 -11
- package/dist/components/add/BulkAddView.mjs +0 -163
- package/dist/components/add/index.d.ts +0 -2
- package/dist/components/index.d.ts +0 -2
- package/dist/components/list/EditableTreeItem.d.ts +0 -13
- package/dist/components/list/ListCommand.cjs +0 -651
- package/dist/components/list/ListCommand.d.ts +0 -5
- package/dist/components/list/ListCommand.mjs +0 -649
- package/dist/components/list/SyncedPackageTree.d.ts +0 -14
- package/dist/components/list/index.d.ts +0 -10
- package/dist/components/list/types.d.ts +0 -14
- package/dist/components/primitives/Box.d.ts +0 -4
- package/dist/components/primitives/Spinner.d.ts +0 -6
- package/dist/components/primitives/Text.d.ts +0 -4
- package/dist/components/primitives/index.d.ts +0 -3
- package/dist/components/remove/RemoveConfirm.cjs +0 -18
- package/dist/components/remove/RemoveConfirm.d.ts +0 -11
- package/dist/components/remove/RemoveConfirm.mjs +0 -16
- package/dist/components/shared/Confirm.cjs +0 -30
- package/dist/components/shared/Confirm.d.ts +0 -8
- package/dist/components/shared/Confirm.mjs +0 -28
- package/dist/components/shared/MenuItem.cjs +0 -18
- package/dist/components/shared/MenuItem.d.ts +0 -7
- package/dist/components/shared/MenuItem.mjs +0 -16
- package/dist/components/shared/ProgressBar.d.ts +0 -7
- package/dist/components/shared/StepRunner.cjs +0 -58
- package/dist/components/shared/StepRunner.d.ts +0 -15
- package/dist/components/shared/StepRunner.mjs +0 -56
- package/dist/components/shared/Table.cjs +0 -19
- package/dist/components/shared/Table.d.ts +0 -8
- package/dist/components/shared/Table.mjs +0 -17
- package/dist/components/shared/index.d.ts +0 -6
- package/dist/components/status/PackageStatusCard.d.ts +0 -10
- package/dist/components/status/StatusDisplay.cjs +0 -26
- package/dist/components/status/StatusDisplay.d.ts +0 -23
- package/dist/components/status/StatusDisplay.mjs +0 -24
- package/dist/components/status/StatusTreeNode.cjs +0 -40
- package/dist/components/status/StatusTreeNode.d.ts +0 -15
- package/dist/components/status/StatusTreeNode.mjs +0 -38
- package/dist/components/status/index.d.ts +0 -6
- package/dist/components/tree/AssetTreeNode.cjs +0 -54
- package/dist/components/tree/AssetTreeNode.d.ts +0 -12
- package/dist/components/tree/AssetTreeNode.mjs +0 -52
- package/dist/components/tree/TreeSelect.cjs +0 -129
- package/dist/components/tree/TreeSelect.d.ts +0 -12
- package/dist/components/tree/TreeSelect.mjs +0 -127
- package/dist/components/tree/index.d.ts +0 -4
- package/dist/core/assetStructure.cjs +0 -30
- package/dist/core/assetStructure.d.ts +0 -36
- package/dist/core/assetStructure.mjs +0 -27
- package/dist/core/cli.cjs +0 -106
- package/dist/core/cli.d.ts +0 -9
- package/dist/core/cli.mjs +0 -103
- package/dist/core/constants.cjs +0 -28
- package/dist/core/constants.d.ts +0 -94
- package/dist/core/constants.mjs +0 -21
- package/dist/core/filesystem.cjs +0 -98
- package/dist/core/filesystem.d.ts +0 -94
- package/dist/core/filesystem.mjs +0 -88
- package/dist/core/github.cjs +0 -115
- package/dist/core/github.d.ts +0 -61
- package/dist/core/github.mjs +0 -107
- package/dist/core/io.cjs +0 -46
- package/dist/core/io.d.ts +0 -40
- package/dist/core/io.mjs +0 -39
- package/dist/core/listOperations.cjs +0 -228
- package/dist/core/listOperations.d.ts +0 -43
- package/dist/core/listOperations.mjs +0 -205
- package/dist/core/localSource.cjs +0 -126
- package/dist/core/localSource.d.ts +0 -33
- package/dist/core/localSource.mjs +0 -120
- package/dist/core/migration.cjs +0 -201
- package/dist/core/migration.d.ts +0 -57
- package/dist/core/migration.mjs +0 -198
- package/dist/core/packageScanner.cjs +0 -360
- package/dist/core/packageScanner.d.ts +0 -22
- package/dist/core/packageScanner.mjs +0 -356
- package/dist/core/sync.cjs +0 -400
- package/dist/core/sync.d.ts +0 -21
- package/dist/core/sync.mjs +0 -397
- package/dist/core/syncMeta.cjs +0 -242
- package/dist/core/syncMeta.d.ts +0 -75
- package/dist/core/syncMeta.mjs +0 -229
- package/dist/utils/dependencies.cjs +0 -57
- package/dist/utils/dependencies.d.ts +0 -10
- package/dist/utils/dependencies.mjs +0 -34
- package/dist/utils/nameTransform.cjs +0 -13
- package/dist/utils/nameTransform.d.ts +0 -65
- package/dist/utils/nameTransform.mjs +0 -11
- package/dist/utils/package.cjs +0 -170
- package/dist/utils/package.d.ts +0 -105
- package/dist/utils/package.mjs +0 -157
- package/dist/utils/packageName.cjs +0 -24
- package/dist/utils/packageName.d.ts +0 -32
- package/dist/utils/packageName.mjs +0 -21
- package/dist/utils/paths.cjs +0 -18
- package/dist/utils/paths.d.ts +0 -55
- package/dist/utils/paths.mjs +0 -15
- package/dist/version.cjs +0 -5
- package/dist/version.d.ts +0 -5
- package/dist/version.mjs +0 -3
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runCli } from '@slats/claude-assets-sync';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
|
+
const pkg = JSON.parse(
|
|
9
|
+
await readFile(resolve(packageRoot, 'package.json'), 'utf-8'),
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
if (typeof pkg.claude?.assetPath === 'string') {
|
|
13
|
+
runCli(process.argv, {
|
|
14
|
+
packageRoot,
|
|
15
|
+
packageName: pkg.name,
|
|
16
|
+
packageVersion: pkg.version,
|
|
17
|
+
assetPath: pkg.claude.assetPath,
|
|
18
|
+
}).catch((err) => {
|
|
19
|
+
process.stderr.write(
|
|
20
|
+
`[${pkg.name}] claude-sync failed: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
21
|
+
);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"package": {
|
|
4
|
+
"name": "@slats/claude-assets-sync",
|
|
5
|
+
"version": "0.2.0"
|
|
6
|
+
},
|
|
7
|
+
"generatedAt": "2026-04-24T04:25:43.386Z",
|
|
8
|
+
"algorithm": "sha256",
|
|
9
|
+
"assetRoot": "docs/claude",
|
|
10
|
+
"files": {
|
|
11
|
+
"skills/claude-sync-applier/SKILL.md": "1c846b7ff7b127217a3201028ec4e1476857e5a5bb38b92d863b92a16ac4c7d0",
|
|
12
|
+
"skills/claude-sync-applier/knowledge/claude-md-template.md": "966fcc668b0e8f43ae83a6111ba1887d5504182e0b138e19937abb1fb43b3318",
|
|
13
|
+
"skills/claude-sync-applier/knowledge/dependency-cruiser.md": "058de112be3c03999846a66d066be540f72f2b1c40f5a1d04a82d36236a3c562",
|
|
14
|
+
"skills/claude-sync-applier/knowledge/gotchas.md": "310ffb416cbcaaf4b9162d0e6004dead6a8d658ff693ffe9e8580a8b83f7b6ea",
|
|
15
|
+
"skills/claude-sync-applier/knowledge/package-json-patches.md": "3ef1c39800e541e6390575a5296a8a247772b58c126c30149cd1efa61ead5dcc",
|
|
16
|
+
"skills/claude-sync-applier/knowledge/reference-files.md": "d0d42df1f90b17d8a35e914bfd16fe381890d71e0ea6a767d1e5e14874f2b95f",
|
|
17
|
+
"skills/claude-sync-applier/knowledge/smoke-tests.md": "76c396e2c7d410920139c894fc52d74e9914ea59d0e41dc30ebfe106e99c4be3"
|
|
18
|
+
},
|
|
19
|
+
"previousVersions": {}
|
|
20
|
+
}
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -1,112 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Command registry and exports
|
|
3
|
-
*/
|
|
4
|
-
export * from './types.js';
|
|
5
|
-
export { runSyncCommand } from './sync.js';
|
|
6
|
-
export { runListCommand, registerListCommand } from './list.js';
|
|
7
|
-
export { runRemoveCommand } from './remove.js';
|
|
8
|
-
export { runStatusCommand } from './status.js';
|
|
9
|
-
export { runMigrateCommand } from './migrate.js';
|
|
10
|
-
export { runAddCommand } from './add.js';
|
|
11
|
-
export { runUpdateCommand } from './update.js';
|
|
12
|
-
export type { UpdateCommandOptions } from './update.js';
|
|
13
|
-
/**
|
|
14
|
-
* Command metadata for CLI help and documentation
|
|
15
|
-
*/
|
|
16
|
-
export declare const COMMANDS: {
|
|
17
|
-
readonly sync: {
|
|
18
|
-
readonly name: "sync";
|
|
19
|
-
readonly description: "Sync Claude assets from npm packages";
|
|
20
|
-
readonly options: readonly [{
|
|
21
|
-
readonly flag: "-p, --package <name>";
|
|
22
|
-
readonly description: "Package name to sync";
|
|
23
|
-
}, {
|
|
24
|
-
readonly flag: "-f, --force";
|
|
25
|
-
readonly description: "Force sync even if version matches";
|
|
26
|
-
}, {
|
|
27
|
-
readonly flag: "--dry-run";
|
|
28
|
-
readonly description: "Preview changes without writing files";
|
|
29
|
-
}, {
|
|
30
|
-
readonly flag: "-l, --local";
|
|
31
|
-
readonly description: "Read from local workspace";
|
|
32
|
-
}, {
|
|
33
|
-
readonly flag: "-r, --ref <ref>";
|
|
34
|
-
readonly description: "Git ref to fetch from";
|
|
35
|
-
}, {
|
|
36
|
-
readonly flag: "--no-flat";
|
|
37
|
-
readonly description: "Use legacy nested structure";
|
|
38
|
-
}];
|
|
39
|
-
};
|
|
40
|
-
readonly add: {
|
|
41
|
-
readonly name: "add";
|
|
42
|
-
readonly description: "Add a package with interactive asset selection";
|
|
43
|
-
readonly options: readonly [{
|
|
44
|
-
readonly flag: "-p, --package <name>";
|
|
45
|
-
readonly description: "Package name to add";
|
|
46
|
-
}, {
|
|
47
|
-
readonly flag: "-l, --local";
|
|
48
|
-
readonly description: "Read from local workspace";
|
|
49
|
-
}, {
|
|
50
|
-
readonly flag: "-r, --ref <ref>";
|
|
51
|
-
readonly description: "Git ref to fetch from";
|
|
52
|
-
}];
|
|
53
|
-
};
|
|
54
|
-
readonly list: {
|
|
55
|
-
readonly name: "list";
|
|
56
|
-
readonly description: "List all synced packages";
|
|
57
|
-
readonly options: readonly [{
|
|
58
|
-
readonly flag: "--json";
|
|
59
|
-
readonly description: "Output as JSON";
|
|
60
|
-
}];
|
|
61
|
-
};
|
|
62
|
-
readonly remove: {
|
|
63
|
-
readonly name: "remove";
|
|
64
|
-
readonly description: "Remove a synced package";
|
|
65
|
-
readonly options: readonly [{
|
|
66
|
-
readonly flag: "-p, --package <name>";
|
|
67
|
-
readonly description: "Package name to remove";
|
|
68
|
-
}, {
|
|
69
|
-
readonly flag: "-y, --yes";
|
|
70
|
-
readonly description: "Skip confirmation prompt";
|
|
71
|
-
}, {
|
|
72
|
-
readonly flag: "--dry-run";
|
|
73
|
-
readonly description: "Preview changes without removing files";
|
|
74
|
-
}];
|
|
75
|
-
};
|
|
76
|
-
readonly status: {
|
|
77
|
-
readonly name: "status";
|
|
78
|
-
readonly description: "Show sync status of all packages";
|
|
79
|
-
readonly options: readonly [{
|
|
80
|
-
readonly flag: "--no-remote";
|
|
81
|
-
readonly description: "Skip remote version check";
|
|
82
|
-
}];
|
|
83
|
-
};
|
|
84
|
-
readonly migrate: {
|
|
85
|
-
readonly name: "migrate";
|
|
86
|
-
readonly description: "Migrate from legacy to flat structure";
|
|
87
|
-
readonly options: readonly [{
|
|
88
|
-
readonly flag: "--dry-run";
|
|
89
|
-
readonly description: "Preview migration without making changes";
|
|
90
|
-
}];
|
|
91
|
-
};
|
|
92
|
-
readonly update: {
|
|
93
|
-
readonly name: "update";
|
|
94
|
-
readonly description: "Update package metadata in .sync-meta.json";
|
|
95
|
-
readonly options: readonly [{
|
|
96
|
-
readonly flag: "-p, --package <name>";
|
|
97
|
-
readonly description: "Package name to update (default: all)";
|
|
98
|
-
}, {
|
|
99
|
-
readonly flag: "-l, --local";
|
|
100
|
-
readonly description: "Read from local workspace";
|
|
101
|
-
}, {
|
|
102
|
-
readonly flag: "-r, --ref <ref>";
|
|
103
|
-
readonly description: "Git ref to fetch from";
|
|
104
|
-
}, {
|
|
105
|
-
readonly flag: "--dry-run";
|
|
106
|
-
readonly description: "Preview changes without writing";
|
|
107
|
-
}, {
|
|
108
|
-
readonly flag: "--sync";
|
|
109
|
-
readonly description: "Re-sync files after updating metadata";
|
|
110
|
-
}];
|
|
111
|
-
};
|
|
112
|
-
};
|
|
1
|
+
export { runCli, type DefaultFlags, type RunCliOptions, } from './runCli/index.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var commander = require('commander');
|
|
4
|
+
var logger = require('../../utils/logger.cjs');
|
|
5
|
+
var version = require('../../utils/version.cjs');
|
|
6
|
+
var runInject = require('./utils/runInject.cjs');
|
|
7
|
+
|
|
8
|
+
async function runCli(argv = process.argv, options) {
|
|
9
|
+
const cmd = new commander.Command();
|
|
10
|
+
cmd
|
|
11
|
+
.name('claude-sync')
|
|
12
|
+
.description("Inject this package's assets into the target .claude directory")
|
|
13
|
+
.version(options.version ?? version.VERSION)
|
|
14
|
+
.option('--scope <scope>', 'Target scope: user (~/.claude) | project (nearest ancestor .claude or <cwd>/.claude)')
|
|
15
|
+
.option('--dry-run', 'Preview without writing', false)
|
|
16
|
+
.option('--force', 'Overwrite user modifications', false)
|
|
17
|
+
.option('--root <path>', 'Override scope resolution cwd (default: cwd)')
|
|
18
|
+
.action(async (flags) => {
|
|
19
|
+
await runInject.runInject(flags, options);
|
|
20
|
+
});
|
|
21
|
+
try {
|
|
22
|
+
await cmd.parseAsync([...argv]);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
26
|
+
logger.logger.error(msg);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
exports.runCli = runCli;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RunCliOptions } from './type.js';
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry for `@slats/claude-assets-sync`.
|
|
4
|
+
*
|
|
5
|
+
* The caller passes its own package metadata (`packageRoot`, `packageName`,
|
|
6
|
+
* `packageVersion`, `assetPath`) so the library never walks the filesystem
|
|
7
|
+
* looking for consumers. Consumer bin stubs read their own `package.json`
|
|
8
|
+
* and forward the resolved values here.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runCli(argv: readonly string[] | undefined, options: RunCliOptions): Promise<void>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { logger } from '../../utils/logger.mjs';
|
|
3
|
+
import { VERSION } from '../../utils/version.mjs';
|
|
4
|
+
import { runInject } from './utils/runInject.mjs';
|
|
5
|
+
|
|
6
|
+
async function runCli(argv = process.argv, options) {
|
|
7
|
+
const cmd = new Command();
|
|
8
|
+
cmd
|
|
9
|
+
.name('claude-sync')
|
|
10
|
+
.description("Inject this package's assets into the target .claude directory")
|
|
11
|
+
.version(options.version ?? VERSION)
|
|
12
|
+
.option('--scope <scope>', 'Target scope: user (~/.claude) | project (nearest ancestor .claude or <cwd>/.claude)')
|
|
13
|
+
.option('--dry-run', 'Preview without writing', false)
|
|
14
|
+
.option('--force', 'Overwrite user modifications', false)
|
|
15
|
+
.option('--root <path>', 'Override scope resolution cwd (default: cwd)')
|
|
16
|
+
.action(async (flags) => {
|
|
17
|
+
await runInject(flags, options);
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
await cmd.parseAsync([...argv]);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
24
|
+
logger.error(msg);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { runCli };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface RunCliOptions {
|
|
2
|
+
version?: string;
|
|
3
|
+
/** Absolute filesystem path to the consumer package root. */
|
|
4
|
+
packageRoot: string;
|
|
5
|
+
/** Consumer package name used in logs and error messages. */
|
|
6
|
+
packageName: string;
|
|
7
|
+
/** Consumer package version used in logs. */
|
|
8
|
+
packageVersion: string;
|
|
9
|
+
/** Asset directory path relative to `packageRoot`. */
|
|
10
|
+
assetPath: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DefaultFlags {
|
|
13
|
+
scope?: string;
|
|
14
|
+
dryRun?: boolean;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
root?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolved consumer metadata passed to the injection pipeline.
|
|
20
|
+
* The caller owns the definition; the library does not read `package.json`.
|
|
21
|
+
*/
|
|
22
|
+
export interface ConsumerPackage {
|
|
23
|
+
name: string;
|
|
24
|
+
version: string;
|
|
25
|
+
packageRoot: string;
|
|
26
|
+
assetRoot: string;
|
|
27
|
+
hashesPresent: boolean;
|
|
28
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('node:crypto');
|
|
4
|
+
require('node:fs/promises');
|
|
5
|
+
require('node:path');
|
|
6
|
+
var injectDocs = require('../../../core/injectDocs/injectDocs.cjs');
|
|
7
|
+
require('node:os');
|
|
8
|
+
require('node:fs');
|
|
9
|
+
require('@inquirer/prompts');
|
|
10
|
+
require('picocolors');
|
|
11
|
+
var confirmForce = require('../../../prompts/confirmForce.cjs');
|
|
12
|
+
var heartbeat = require('../../../utils/heartbeat.cjs');
|
|
13
|
+
var logger = require('../../../utils/logger.cjs');
|
|
14
|
+
|
|
15
|
+
async function injectOne(target, scope, flags, originCwd) {
|
|
16
|
+
if (!target.hashesPresent) {
|
|
17
|
+
logger.logger.warn(`${target.name}: dist/claude-hashes.json missing — build the package (e.g. yarn build) to regenerate the hash manifest first.`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
logger.logger.heading(`${target.name}@${target.version}`);
|
|
21
|
+
const stopHeartbeat = heartbeat.startHeartbeat({
|
|
22
|
+
label: `injecting ${target.name}`,
|
|
23
|
+
});
|
|
24
|
+
try {
|
|
25
|
+
const report = await injectDocs.injectDocs({
|
|
26
|
+
packageName: target.name,
|
|
27
|
+
packageVersion: target.version,
|
|
28
|
+
packageRoot: target.packageRoot,
|
|
29
|
+
assetRoot: target.assetRoot,
|
|
30
|
+
scope,
|
|
31
|
+
originCwd,
|
|
32
|
+
dryRun: flags.dryRun ?? false,
|
|
33
|
+
force: flags.force ?? false,
|
|
34
|
+
confirmForce: async (plan) => {
|
|
35
|
+
const diverged = plan.actions.filter((a) => a.kind === 'warn-diverged');
|
|
36
|
+
const orphans = plan.actions.filter((a) => a.kind === 'warn-orphan');
|
|
37
|
+
return confirmForce.confirmForceAsync(diverged.length, orphans.length, [...diverged, ...orphans].map((a) => a.relPath).slice(0, 3));
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
if (report.exitCode !== 0)
|
|
41
|
+
process.exit(report.exitCode);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
stopHeartbeat();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
exports.injectOne = injectOne;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import 'node:crypto';
|
|
2
|
+
import 'node:fs/promises';
|
|
3
|
+
import 'node:path';
|
|
4
|
+
import { injectDocs } from '../../../core/injectDocs/injectDocs.mjs';
|
|
5
|
+
import 'node:os';
|
|
6
|
+
import 'node:fs';
|
|
7
|
+
import '@inquirer/prompts';
|
|
8
|
+
import 'picocolors';
|
|
9
|
+
import { confirmForceAsync } from '../../../prompts/confirmForce.mjs';
|
|
10
|
+
import { startHeartbeat } from '../../../utils/heartbeat.mjs';
|
|
11
|
+
import { logger } from '../../../utils/logger.mjs';
|
|
12
|
+
|
|
13
|
+
async function injectOne(target, scope, flags, originCwd) {
|
|
14
|
+
if (!target.hashesPresent) {
|
|
15
|
+
logger.warn(`${target.name}: dist/claude-hashes.json missing — build the package (e.g. yarn build) to regenerate the hash manifest first.`);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
logger.heading(`${target.name}@${target.version}`);
|
|
19
|
+
const stopHeartbeat = startHeartbeat({
|
|
20
|
+
label: `injecting ${target.name}`,
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
const report = await injectDocs({
|
|
24
|
+
packageName: target.name,
|
|
25
|
+
packageVersion: target.version,
|
|
26
|
+
packageRoot: target.packageRoot,
|
|
27
|
+
assetRoot: target.assetRoot,
|
|
28
|
+
scope,
|
|
29
|
+
originCwd,
|
|
30
|
+
dryRun: flags.dryRun ?? false,
|
|
31
|
+
force: flags.force ?? false,
|
|
32
|
+
confirmForce: async (plan) => {
|
|
33
|
+
const diverged = plan.actions.filter((a) => a.kind === 'warn-diverged');
|
|
34
|
+
const orphans = plan.actions.filter((a) => a.kind === 'warn-orphan');
|
|
35
|
+
return confirmForceAsync(diverged.length, orphans.length, [...diverged, ...orphans].map((a) => a.relPath).slice(0, 3));
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
if (report.exitCode !== 0)
|
|
39
|
+
process.exit(report.exitCode);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
stopHeartbeat();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { injectOne };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('node:crypto');
|
|
4
|
+
require('node:fs/promises');
|
|
5
|
+
require('node:path');
|
|
6
|
+
var logger = require('../../../utils/logger.cjs');
|
|
7
|
+
var scope = require('../../../core/scope/scope.cjs');
|
|
8
|
+
var selectScope = require('../../../prompts/selectScope.cjs');
|
|
9
|
+
require('@inquirer/prompts');
|
|
10
|
+
require('picocolors');
|
|
11
|
+
|
|
12
|
+
async function resolveScopeFlag(flag) {
|
|
13
|
+
if (flag) {
|
|
14
|
+
if (!scope.isValidScope(flag)) {
|
|
15
|
+
logger.logger.error(`Invalid --scope: ${flag}. Expected user | project.`);
|
|
16
|
+
process.exit(2);
|
|
17
|
+
}
|
|
18
|
+
return flag;
|
|
19
|
+
}
|
|
20
|
+
if (!scope.isInteractive()) {
|
|
21
|
+
logger.logger.error('--scope is required in non-interactive environments.');
|
|
22
|
+
logger.logger.error(' Pass --scope=user | --scope=project.');
|
|
23
|
+
process.exit(2);
|
|
24
|
+
}
|
|
25
|
+
return selectScope.selectScopeAsync();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
exports.resolveScopeFlag = resolveScopeFlag;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import 'node:crypto';
|
|
2
|
+
import 'node:fs/promises';
|
|
3
|
+
import 'node:path';
|
|
4
|
+
import { logger } from '../../../utils/logger.mjs';
|
|
5
|
+
import { isValidScope, isInteractive } from '../../../core/scope/scope.mjs';
|
|
6
|
+
import { selectScopeAsync } from '../../../prompts/selectScope.mjs';
|
|
7
|
+
import '@inquirer/prompts';
|
|
8
|
+
import 'picocolors';
|
|
9
|
+
|
|
10
|
+
async function resolveScopeFlag(flag) {
|
|
11
|
+
if (flag) {
|
|
12
|
+
if (!isValidScope(flag)) {
|
|
13
|
+
logger.error(`Invalid --scope: ${flag}. Expected user | project.`);
|
|
14
|
+
process.exit(2);
|
|
15
|
+
}
|
|
16
|
+
return flag;
|
|
17
|
+
}
|
|
18
|
+
if (!isInteractive()) {
|
|
19
|
+
logger.error('--scope is required in non-interactive environments.');
|
|
20
|
+
logger.error(' Pass --scope=user | --scope=project.');
|
|
21
|
+
process.exit(2);
|
|
22
|
+
}
|
|
23
|
+
return selectScopeAsync();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { resolveScopeFlag };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var promises = require('node:fs/promises');
|
|
4
|
+
var node_path = require('node:path');
|
|
5
|
+
var logger = require('../../../utils/logger.cjs');
|
|
6
|
+
var injectOne = require('./injectOne.cjs');
|
|
7
|
+
var resolveScopeFlag = require('./resolveScopeFlag.cjs');
|
|
8
|
+
|
|
9
|
+
async function runInject(flags, options) {
|
|
10
|
+
if (!options.packageRoot ||
|
|
11
|
+
!options.packageName ||
|
|
12
|
+
!options.packageVersion ||
|
|
13
|
+
!options.assetPath) {
|
|
14
|
+
logger.logger.error('runCli requires { packageRoot, packageName, packageVersion, assetPath }.');
|
|
15
|
+
process.exit(2);
|
|
16
|
+
}
|
|
17
|
+
if (!node_path.isAbsolute(options.packageRoot)) {
|
|
18
|
+
logger.logger.error(`packageRoot must be an absolute path; received: ${options.packageRoot}`);
|
|
19
|
+
process.exit(2);
|
|
20
|
+
}
|
|
21
|
+
const assetRoot = node_path.resolve(options.packageRoot, options.assetPath);
|
|
22
|
+
const hashesPath = node_path.join(options.packageRoot, 'dist', 'claude-hashes.json');
|
|
23
|
+
const hashesPresent = await promises.stat(hashesPath).then(() => true, () => false);
|
|
24
|
+
const target = {
|
|
25
|
+
name: options.packageName,
|
|
26
|
+
version: options.packageVersion,
|
|
27
|
+
packageRoot: options.packageRoot,
|
|
28
|
+
assetRoot,
|
|
29
|
+
hashesPresent,
|
|
30
|
+
};
|
|
31
|
+
const originCwd = flags.root ?? process.cwd();
|
|
32
|
+
const scope = await resolveScopeFlag.resolveScopeFlag(flags.scope);
|
|
33
|
+
await injectOne.injectOne(target, scope, flags, originCwd);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.runInject = runInject;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, resolve, join } from 'node:path';
|
|
3
|
+
import { logger } from '../../../utils/logger.mjs';
|
|
4
|
+
import { injectOne } from './injectOne.mjs';
|
|
5
|
+
import { resolveScopeFlag } from './resolveScopeFlag.mjs';
|
|
6
|
+
|
|
7
|
+
async function runInject(flags, options) {
|
|
8
|
+
if (!options.packageRoot ||
|
|
9
|
+
!options.packageName ||
|
|
10
|
+
!options.packageVersion ||
|
|
11
|
+
!options.assetPath) {
|
|
12
|
+
logger.error('runCli requires { packageRoot, packageName, packageVersion, assetPath }.');
|
|
13
|
+
process.exit(2);
|
|
14
|
+
}
|
|
15
|
+
if (!isAbsolute(options.packageRoot)) {
|
|
16
|
+
logger.error(`packageRoot must be an absolute path; received: ${options.packageRoot}`);
|
|
17
|
+
process.exit(2);
|
|
18
|
+
}
|
|
19
|
+
const assetRoot = resolve(options.packageRoot, options.assetPath);
|
|
20
|
+
const hashesPath = join(options.packageRoot, 'dist', 'claude-hashes.json');
|
|
21
|
+
const hashesPresent = await stat(hashesPath).then(() => true, () => false);
|
|
22
|
+
const target = {
|
|
23
|
+
name: options.packageName,
|
|
24
|
+
version: options.packageVersion,
|
|
25
|
+
packageRoot: options.packageRoot,
|
|
26
|
+
assetRoot,
|
|
27
|
+
hashesPresent,
|
|
28
|
+
};
|
|
29
|
+
const originCwd = flags.root ?? process.cwd();
|
|
30
|
+
const scope = await resolveScopeFlag(flags.scope);
|
|
31
|
+
await injectOne(target, scope, flags, originCwd);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { runInject };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_path = require('node:path');
|
|
4
|
+
var hash = require('../hash/hash.cjs');
|
|
5
|
+
var toPosix = require('./utils/toPosix.cjs');
|
|
6
|
+
var walkFiles = require('./utils/walkFiles.cjs');
|
|
7
|
+
|
|
8
|
+
async function buildPlan(input) {
|
|
9
|
+
const { sourceHashes, targetRoot, namespacePrefixes, force } = input;
|
|
10
|
+
const actions = [];
|
|
11
|
+
let requiresForce = false;
|
|
12
|
+
for (const [relPath, srcHash] of Object.entries(sourceHashes)) {
|
|
13
|
+
const dstAbs = node_path.join(targetRoot, relPath);
|
|
14
|
+
const dstHash = await hash.hashFile(dstAbs);
|
|
15
|
+
if (dstHash === null)
|
|
16
|
+
actions.push({ kind: 'copy', relPath, dstAbs });
|
|
17
|
+
else if (hash.hashEquals(dstHash, srcHash))
|
|
18
|
+
actions.push({ kind: 'skip-uptodate', relPath, dstAbs });
|
|
19
|
+
else {
|
|
20
|
+
actions.push({ kind: 'warn-diverged', relPath, dstAbs });
|
|
21
|
+
requiresForce = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const known = new Set(Object.keys(sourceHashes));
|
|
25
|
+
for (const prefix of namespacePrefixes) {
|
|
26
|
+
const prefixRoot = node_path.join(targetRoot, prefix);
|
|
27
|
+
for await (const abs of walkFiles.walkFiles(prefixRoot)) {
|
|
28
|
+
const relPath = toPosix.toPosix(node_path.relative(targetRoot, abs));
|
|
29
|
+
if (known.has(relPath))
|
|
30
|
+
continue;
|
|
31
|
+
if (force)
|
|
32
|
+
actions.push({ kind: 'delete', relPath, dstAbs: abs });
|
|
33
|
+
else {
|
|
34
|
+
actions.push({ kind: 'warn-orphan', relPath, dstAbs: abs });
|
|
35
|
+
requiresForce = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { actions, requiresForce };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.buildPlan = buildPlan;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { join, relative } from 'node:path';
|
|
2
|
+
import { hashFile, hashEquals } from '../hash/hash.mjs';
|
|
3
|
+
import { toPosix } from './utils/toPosix.mjs';
|
|
4
|
+
import { walkFiles } from './utils/walkFiles.mjs';
|
|
5
|
+
|
|
6
|
+
async function buildPlan(input) {
|
|
7
|
+
const { sourceHashes, targetRoot, namespacePrefixes, force } = input;
|
|
8
|
+
const actions = [];
|
|
9
|
+
let requiresForce = false;
|
|
10
|
+
for (const [relPath, srcHash] of Object.entries(sourceHashes)) {
|
|
11
|
+
const dstAbs = join(targetRoot, relPath);
|
|
12
|
+
const dstHash = await hashFile(dstAbs);
|
|
13
|
+
if (dstHash === null)
|
|
14
|
+
actions.push({ kind: 'copy', relPath, dstAbs });
|
|
15
|
+
else if (hashEquals(dstHash, srcHash))
|
|
16
|
+
actions.push({ kind: 'skip-uptodate', relPath, dstAbs });
|
|
17
|
+
else {
|
|
18
|
+
actions.push({ kind: 'warn-diverged', relPath, dstAbs });
|
|
19
|
+
requiresForce = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const known = new Set(Object.keys(sourceHashes));
|
|
23
|
+
for (const prefix of namespacePrefixes) {
|
|
24
|
+
const prefixRoot = join(targetRoot, prefix);
|
|
25
|
+
for await (const abs of walkFiles(prefixRoot)) {
|
|
26
|
+
const relPath = toPosix(relative(targetRoot, abs));
|
|
27
|
+
if (known.has(relPath))
|
|
28
|
+
continue;
|
|
29
|
+
if (force)
|
|
30
|
+
actions.push({ kind: 'delete', relPath, dstAbs: abs });
|
|
31
|
+
else {
|
|
32
|
+
actions.push({ kind: 'warn-orphan', relPath, dstAbs: abs });
|
|
33
|
+
requiresForce = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { actions, requiresForce };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { buildPlan };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Sha256Hex } from '../hash/index.js';
|
|
2
|
+
export type Action = {
|
|
3
|
+
kind: 'copy';
|
|
4
|
+
relPath: string;
|
|
5
|
+
dstAbs: string;
|
|
6
|
+
} | {
|
|
7
|
+
kind: 'skip-uptodate';
|
|
8
|
+
relPath: string;
|
|
9
|
+
dstAbs: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'warn-diverged';
|
|
12
|
+
relPath: string;
|
|
13
|
+
dstAbs: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'warn-orphan';
|
|
16
|
+
relPath: string;
|
|
17
|
+
dstAbs: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'delete';
|
|
20
|
+
relPath: string;
|
|
21
|
+
dstAbs: string;
|
|
22
|
+
};
|
|
23
|
+
export interface InjectPlan {
|
|
24
|
+
actions: Action[];
|
|
25
|
+
requiresForce: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface PlanInput {
|
|
28
|
+
sourceHashes: Record<string, Sha256Hex>;
|
|
29
|
+
targetRoot: string;
|
|
30
|
+
namespacePrefixes: string[];
|
|
31
|
+
force: boolean;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function toPosix(p: string): string;
|