@memberjunction/cli 5.41.0 → 5.42.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/dist/commands/bundle/index.d.ts +1 -0
- package/dist/commands/bundle/index.d.ts.map +1 -1
- package/dist/commands/bundle/index.js +7 -1
- package/dist/commands/bundle/index.js.map +1 -1
- package/dist/commands/codegen/index.d.ts +6 -16
- package/dist/commands/codegen/index.d.ts.map +1 -1
- package/dist/commands/codegen/index.js +6 -90
- package/dist/commands/codegen/index.js.map +1 -1
- package/dist/commands/codegen/usage.d.ts +7 -0
- package/dist/commands/codegen/usage.d.ts.map +1 -0
- package/dist/commands/codegen/usage.js +10 -0
- package/dist/commands/codegen/usage.js.map +1 -0
- package/dist/commands/install/claude.d.ts +35 -0
- package/dist/commands/install/claude.d.ts.map +1 -0
- package/dist/commands/install/claude.js +108 -0
- package/dist/commands/install/claude.js.map +1 -0
- package/dist/commands/install/index.d.ts +1 -0
- package/dist/commands/install/index.d.ts.map +1 -1
- package/dist/commands/install/index.js +4 -0
- package/dist/commands/install/index.js.map +1 -1
- package/dist/commands/migrate/convert.d.ts +59 -12
- package/dist/commands/migrate/convert.d.ts.map +1 -1
- package/dist/commands/migrate/convert.js +294 -21
- package/dist/commands/migrate/convert.js.map +1 -1
- package/dist/commands/migrate/rebake.d.ts +41 -0
- package/dist/commands/migrate/rebake.d.ts.map +1 -0
- package/dist/commands/migrate/rebake.js +193 -0
- package/dist/commands/migrate/rebake.js.map +1 -0
- package/dist/commands/plugin/add.d.ts +18 -0
- package/dist/commands/plugin/add.d.ts.map +1 -0
- package/dist/commands/plugin/add.js +53 -0
- package/dist/commands/plugin/add.js.map +1 -0
- package/dist/commands/sync/pull.d.ts +6 -26
- package/dist/commands/sync/pull.d.ts.map +1 -1
- package/dist/commands/sync/pull.js +6 -281
- package/dist/commands/sync/pull.js.map +1 -1
- package/dist/commands/sync/push.d.ts +8 -19
- package/dist/commands/sync/push.d.ts.map +1 -1
- package/dist/commands/sync/push.js +8 -328
- package/dist/commands/sync/push.js.map +1 -1
- package/dist/commands/sync/usage.d.ts +7 -0
- package/dist/commands/sync/usage.d.ts.map +1 -0
- package/dist/commands/sync/usage.js +10 -0
- package/dist/commands/sync/usage.js.map +1 -0
- package/dist/commands/update/claude.d.ts +37 -0
- package/dist/commands/update/claude.d.ts.map +1 -0
- package/dist/commands/update/claude.js +90 -0
- package/dist/commands/update/claude.js.map +1 -0
- package/dist/commands/usage.d.ts +17 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +29 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/hooks/prerun.d.ts.map +1 -1
- package/dist/hooks/prerun.js +49 -8
- package/dist/hooks/prerun.js.map +1 -1
- package/dist/lib/claude-pack/ManagedBlockEditor.d.ts +40 -0
- package/dist/lib/claude-pack/ManagedBlockEditor.d.ts.map +1 -0
- package/dist/lib/claude-pack/ManagedBlockEditor.js +127 -0
- package/dist/lib/claude-pack/ManagedBlockEditor.js.map +1 -0
- package/dist/lib/claude-pack/PackFetcher.d.ts +86 -0
- package/dist/lib/claude-pack/PackFetcher.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackFetcher.js +163 -0
- package/dist/lib/claude-pack/PackFetcher.js.map +1 -0
- package/dist/lib/claude-pack/PackInstaller.d.ts +62 -0
- package/dist/lib/claude-pack/PackInstaller.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackInstaller.js +197 -0
- package/dist/lib/claude-pack/PackInstaller.js.map +1 -0
- package/dist/lib/claude-pack/PackMerger.d.ts +61 -0
- package/dist/lib/claude-pack/PackMerger.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackMerger.js +315 -0
- package/dist/lib/claude-pack/PackMerger.js.map +1 -0
- package/dist/lib/claude-pack/PackOutputFormatter.d.ts +29 -0
- package/dist/lib/claude-pack/PackOutputFormatter.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackOutputFormatter.js +82 -0
- package/dist/lib/claude-pack/PackOutputFormatter.js.map +1 -0
- package/dist/lib/claude-pack/PackPaths.d.ts +80 -0
- package/dist/lib/claude-pack/PackPaths.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackPaths.js +182 -0
- package/dist/lib/claude-pack/PackPaths.js.map +1 -0
- package/dist/lib/claude-pack/PackTypes.d.ts +124 -0
- package/dist/lib/claude-pack/PackTypes.d.ts.map +1 -0
- package/dist/lib/claude-pack/PackTypes.js +32 -0
- package/dist/lib/claude-pack/PackTypes.js.map +1 -0
- package/dist/lib/claude-pack/SettingsMerger.d.ts +47 -0
- package/dist/lib/claude-pack/SettingsMerger.d.ts.map +1 -0
- package/dist/lib/claude-pack/SettingsMerger.js +163 -0
- package/dist/lib/claude-pack/SettingsMerger.js.map +1 -0
- package/dist/lib/cli-plugins.d.ts +16 -0
- package/dist/lib/cli-plugins.d.ts.map +1 -0
- package/dist/lib/cli-plugins.js +26 -0
- package/dist/lib/cli-plugins.js.map +1 -0
- package/dist/lib/domain-usage-command.d.ts +16 -0
- package/dist/lib/domain-usage-command.d.ts.map +1 -0
- package/dist/lib/domain-usage-command.js +23 -0
- package/dist/lib/domain-usage-command.js.map +1 -0
- package/dist/lib/usage-render.d.ts +14 -0
- package/dist/lib/usage-render.d.ts.map +1 -0
- package/dist/lib/usage-render.js +64 -0
- package/dist/lib/usage-render.js.map +1 -0
- package/dist/light-commands.d.ts.map +1 -1
- package/dist/light-commands.js +11 -0
- package/dist/light-commands.js.map +1 -1
- package/oclif.manifest.json +815 -135
- package/package.json +17 -15
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level orchestrator for `mj install:claude` and `mj update:claude`.
|
|
3
|
+
*
|
|
4
|
+
* Composes:
|
|
5
|
+
* - source resolution (remote via PackFetcher, or local via PackPaths)
|
|
6
|
+
* - MJ-major detection and the cross-major guard
|
|
7
|
+
* - the --check fast path (compare versions without touching the FS)
|
|
8
|
+
* - the merge (PackMerger) and InstallResult assembly
|
|
9
|
+
*
|
|
10
|
+
* The CLI command files thinly wrap this with flag parsing + output rendering.
|
|
11
|
+
*
|
|
12
|
+
* @see plans/claude-install-pack.md §6.3, §6.5, §7.4, §7.5
|
|
13
|
+
*/
|
|
14
|
+
import { createHash } from 'node:crypto';
|
|
15
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { fetchPack, PackFetchError } from './PackFetcher.js';
|
|
18
|
+
import { mergePack } from './PackMerger.js';
|
|
19
|
+
import { buildRemoteUrlPrefix, detectMJMajor, detectMJVersionString, resolveLocalPackRoot, } from './PackPaths.js';
|
|
20
|
+
import { emptyActionLog, } from './PackTypes.js';
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Main entry point
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
export async function installPack(opts) {
|
|
25
|
+
const targetDir = path.resolve(opts.TargetDir);
|
|
26
|
+
const onProgress = opts.OnProgress ?? (() => { });
|
|
27
|
+
const major = opts.Major ?? detectMJMajor(targetDir);
|
|
28
|
+
if (!major) {
|
|
29
|
+
return errorResult(null, 'Could not detect MJ major version (no @memberjunction/* in package.json). ' +
|
|
30
|
+
'Pass --major <N> to override.');
|
|
31
|
+
}
|
|
32
|
+
if (opts.Offline && !opts.FromPath) {
|
|
33
|
+
return errorResult(detectMJVersion(targetDir), '--offline requires --from <path>.');
|
|
34
|
+
}
|
|
35
|
+
onProgress(`resolving pack (major=v${major}${opts.FromPath ? `, from=${opts.FromPath}` : ''})`);
|
|
36
|
+
let manifest;
|
|
37
|
+
let files;
|
|
38
|
+
try {
|
|
39
|
+
({ manifest, files } = await resolvePack(major, opts, onProgress));
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const installedMJ = detectMJVersion(targetDir);
|
|
43
|
+
if (err instanceof PackFetchError) {
|
|
44
|
+
return errorResult(installedMJ, `Failed to fetch pack: ${err.message}`);
|
|
45
|
+
}
|
|
46
|
+
return errorResult(installedMJ, `Failed to resolve pack: ${err.message}`);
|
|
47
|
+
}
|
|
48
|
+
const installedMJVersion = detectMJVersion(targetDir);
|
|
49
|
+
// --check: compare versions and return without writing.
|
|
50
|
+
if (opts.CheckOnly) {
|
|
51
|
+
return buildCheckResult(targetDir, manifest, installedMJVersion);
|
|
52
|
+
}
|
|
53
|
+
// Cross-major guardrail — pack's major must match local MJ unless explicitly allowed.
|
|
54
|
+
if (manifest.mjMajor !== major && !opts.AllowMajor) {
|
|
55
|
+
return errorResult(installedMJVersion, `Pack major v${manifest.mjMajor} doesn't match local MJ major v${major}. ` +
|
|
56
|
+
`Pass --allow-major to apply anyway.`);
|
|
57
|
+
}
|
|
58
|
+
// Inject MANIFEST.json into the files map so the merger writes it to disk.
|
|
59
|
+
// (The fetched MANIFEST.json itself is not in `files` because the manifest
|
|
60
|
+
// omits its own entry to avoid the self-reference.)
|
|
61
|
+
const manifestBytes = new TextEncoder().encode(JSON.stringify(manifest, null, 2) + '\n');
|
|
62
|
+
files.set('.claude/mj/MANIFEST.json', manifestBytes);
|
|
63
|
+
onProgress('merging pack into target');
|
|
64
|
+
const { Actions, Warnings } = mergePack({
|
|
65
|
+
TargetDir: targetDir,
|
|
66
|
+
PackFiles: files,
|
|
67
|
+
Manifest: manifest,
|
|
68
|
+
DryRun: opts.DryRun,
|
|
69
|
+
Force: opts.Force,
|
|
70
|
+
SkipCommands: opts.SkipCommands,
|
|
71
|
+
SkipSkills: opts.SkipSkills,
|
|
72
|
+
SkipSettings: opts.SkipSettings,
|
|
73
|
+
RefreshCommands: opts.RefreshCommands,
|
|
74
|
+
RefreshSkills: opts.RefreshSkills,
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
ok: Actions.errors.length === 0,
|
|
78
|
+
packVersion: manifest.packVersion,
|
|
79
|
+
installedMJVersion,
|
|
80
|
+
actions: Actions,
|
|
81
|
+
warnings: Warnings,
|
|
82
|
+
notes: [],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Source resolution
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
async function resolvePack(major, opts, onProgress) {
|
|
89
|
+
if (opts.FromPath) {
|
|
90
|
+
const localRoot = resolveLocalPackRoot(opts.FromPath, major);
|
|
91
|
+
if (!localRoot) {
|
|
92
|
+
throw new Error(`Could not find a Claude pack at --from path: ${opts.FromPath}. ` +
|
|
93
|
+
`Expected either an MJ repo root (with templates/claude-pack/dist/v${major}/) or an unpacked dist directory.`);
|
|
94
|
+
}
|
|
95
|
+
return loadLocalPack(localRoot, opts.CheckOnly ?? false);
|
|
96
|
+
}
|
|
97
|
+
const fetched = await fetchPack({
|
|
98
|
+
Major: major,
|
|
99
|
+
Ref: opts.Ref,
|
|
100
|
+
HttpGet: opts.HttpGet,
|
|
101
|
+
OnProgress: onProgress,
|
|
102
|
+
ManifestOnly: opts.CheckOnly,
|
|
103
|
+
});
|
|
104
|
+
return { manifest: fetched.Manifest, files: fetched.Files };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Read a pack from a local directory, verifying every file's sha256 against
|
|
108
|
+
* the manifest (sanity check — guards against partial/corrupt local copies).
|
|
109
|
+
*/
|
|
110
|
+
function loadLocalPack(rootDir, manifestOnly) {
|
|
111
|
+
const manifestPath = path.join(rootDir, '.claude', 'mj', 'MANIFEST.json');
|
|
112
|
+
if (!existsSync(manifestPath)) {
|
|
113
|
+
throw new Error(`Local pack at ${rootDir} has no .claude/mj/MANIFEST.json`);
|
|
114
|
+
}
|
|
115
|
+
let manifest;
|
|
116
|
+
try {
|
|
117
|
+
manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
throw new Error(`Local pack manifest at ${manifestPath} is not valid JSON: ${err.message}`);
|
|
121
|
+
}
|
|
122
|
+
const files = new Map();
|
|
123
|
+
if (manifestOnly) {
|
|
124
|
+
return { manifest, files };
|
|
125
|
+
}
|
|
126
|
+
for (const entry of manifest.files) {
|
|
127
|
+
const abs = path.join(rootDir, ...entry.path.split('/'));
|
|
128
|
+
if (!existsSync(abs)) {
|
|
129
|
+
throw new Error(`Local pack missing file: ${entry.path}`);
|
|
130
|
+
}
|
|
131
|
+
// `new Uint8Array(readFileSync(...))` normalizes Buffer → Uint8Array
|
|
132
|
+
// for the strict @types/node generics (see PackFetcher.ts for context).
|
|
133
|
+
const bytes = new Uint8Array(readFileSync(abs));
|
|
134
|
+
const hash = createHash('sha256').update(bytes).digest('hex');
|
|
135
|
+
if (hash !== entry.sha256) {
|
|
136
|
+
throw new Error(`Local pack checksum mismatch for ${entry.path}: expected ${entry.sha256}, got ${hash}`);
|
|
137
|
+
}
|
|
138
|
+
files.set(entry.path, bytes);
|
|
139
|
+
}
|
|
140
|
+
return { manifest, files };
|
|
141
|
+
}
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// --check fast path
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
function buildCheckResult(targetDir, manifest, installedMJVersion) {
|
|
146
|
+
const localVersionFile = path.join(targetDir, '.claude', 'mj', 'VERSION');
|
|
147
|
+
const localVersion = existsSync(localVersionFile)
|
|
148
|
+
? readFileSync(localVersionFile, 'utf8').trim()
|
|
149
|
+
: null;
|
|
150
|
+
const actions = emptyActionLog();
|
|
151
|
+
const warnings = [];
|
|
152
|
+
const notes = [];
|
|
153
|
+
if (!localVersion) {
|
|
154
|
+
// "No local pack" is a state worth flagging — the user ran --check
|
|
155
|
+
// expecting an installed pack and there isn't one.
|
|
156
|
+
warnings.push('No local pack found (.claude/mj/VERSION missing).');
|
|
157
|
+
}
|
|
158
|
+
else if (localVersion === manifest.packVersion) {
|
|
159
|
+
// "Up to date" is the success case for --check, not a warning.
|
|
160
|
+
notes.push(`Pack is up to date (v${localVersion}).`);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// "Update available" is informational — there's an action the user
|
|
164
|
+
// *can* take, but nothing is wrong.
|
|
165
|
+
notes.push(`Update available: v${localVersion} → v${manifest.packVersion}. Run \`mj update:claude\` to apply.`);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
ok: true,
|
|
169
|
+
packVersion: manifest.packVersion,
|
|
170
|
+
installedMJVersion,
|
|
171
|
+
actions,
|
|
172
|
+
warnings,
|
|
173
|
+
notes,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
// Helpers
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
function errorResult(installedMJVersion, message) {
|
|
180
|
+
return {
|
|
181
|
+
ok: false,
|
|
182
|
+
packVersion: '',
|
|
183
|
+
installedMJVersion,
|
|
184
|
+
actions: { ...emptyActionLog(), errors: [message] },
|
|
185
|
+
warnings: [],
|
|
186
|
+
notes: [],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Detect the full MJ semver in the target dir (e.g. `5.33.0`). Delegates
|
|
191
|
+
* to {@link detectMJVersionString} in PackPaths so the workspace-walk
|
|
192
|
+
* behavior stays in sync with {@link detectMJMajor}.
|
|
193
|
+
*/
|
|
194
|
+
const detectMJVersion = detectMJVersionString;
|
|
195
|
+
/** Re-export the default raw URL prefix for tests / verbose logging. */
|
|
196
|
+
export { buildRemoteUrlPrefix };
|
|
197
|
+
//# sourceMappingURL=PackInstaller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PackInstaller.js","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackInstaller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-file merge for the Claude Code pack.
|
|
3
|
+
*
|
|
4
|
+
* Implements the table in plans/claude-install-pack.md §6.4:
|
|
5
|
+
*
|
|
6
|
+
* CLAUDE.md — managed-block rewrite (preserves user content)
|
|
7
|
+
* .claude/mj/** — overwritten as a unit (incl. sweep of stale files)
|
|
8
|
+
* .claude/settings.json — deep-merge per §10.2
|
|
9
|
+
* .claude/commands/* — seed-once; overwrite needs --force / --refresh-commands
|
|
10
|
+
* .claude/skills/** — same rule as commands
|
|
11
|
+
*
|
|
12
|
+
* The merger never destroys user content by default. `Force` and the
|
|
13
|
+
* `Refresh*` flags are explicit opt-ins.
|
|
14
|
+
*/
|
|
15
|
+
import { ManagedBlockError } from './ManagedBlockEditor.js';
|
|
16
|
+
import { type ActionLog, type Manifest } from './PackTypes.js';
|
|
17
|
+
export interface PackMergeOptions {
|
|
18
|
+
/** Absolute path to the user's project. */
|
|
19
|
+
TargetDir: string;
|
|
20
|
+
/**
|
|
21
|
+
* Pack contents keyed by pack-relative POSIX path. Must include the
|
|
22
|
+
* MANIFEST.json under `.claude/mj/MANIFEST.json` (PackInstaller injects it).
|
|
23
|
+
*/
|
|
24
|
+
PackFiles: Map<string, Uint8Array>;
|
|
25
|
+
Manifest: Manifest;
|
|
26
|
+
/** Don't write anything — just compute the action plan. */
|
|
27
|
+
DryRun?: boolean;
|
|
28
|
+
/** Overwrite user-modified commands/skills without prompting. */
|
|
29
|
+
Force?: boolean;
|
|
30
|
+
/** Skip the seed of `.claude/commands/`. */
|
|
31
|
+
SkipCommands?: boolean;
|
|
32
|
+
/** Skip the seed of `.claude/skills/`. */
|
|
33
|
+
SkipSkills?: boolean;
|
|
34
|
+
/** Skip the settings.json deep-merge. */
|
|
35
|
+
SkipSettings?: boolean;
|
|
36
|
+
/** Resync commands from pack (update:claude). Equivalent to per-file --force on commands. */
|
|
37
|
+
RefreshCommands?: boolean;
|
|
38
|
+
/** Resync skills from pack (update:claude). */
|
|
39
|
+
RefreshSkills?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface PackMergeResult {
|
|
42
|
+
Actions: ActionLog;
|
|
43
|
+
Warnings: string[];
|
|
44
|
+
}
|
|
45
|
+
export declare function mergePack(opts: PackMergeOptions): PackMergeResult;
|
|
46
|
+
declare function bytesEqual(a: Uint8Array, b: Uint8Array): boolean;
|
|
47
|
+
declare function collectPackPathsByPrefix(files: Map<string, Uint8Array>, prefix: string): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Walk a directory and return file paths relative to `relativeTo`, using
|
|
50
|
+
* POSIX separators (`/`) regardless of host OS — these are pack-relative
|
|
51
|
+
* paths the rest of the merger compares with.
|
|
52
|
+
*/
|
|
53
|
+
declare function walkRelativeFiles(dir: string, relativeTo: string): string[];
|
|
54
|
+
/** Re-export for tests that want to exercise the walker in isolation. */
|
|
55
|
+
export declare const _internals: {
|
|
56
|
+
walkRelativeFiles: typeof walkRelativeFiles;
|
|
57
|
+
bytesEqual: typeof bytesEqual;
|
|
58
|
+
collectPackPathsByPrefix: typeof collectPackPathsByPrefix;
|
|
59
|
+
};
|
|
60
|
+
export { ManagedBlockError };
|
|
61
|
+
//# sourceMappingURL=PackMerger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PackMerger.d.ts","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackMerger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,OAAO,EAIH,iBAAiB,EACpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAGH,KAAK,SAAS,EAEd,KAAK,QAAQ,EAChB,MAAM,gBAAgB,CAAC;AAMxB,MAAM,WAAW,gBAAgB;IAC7B,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6FAA6F;IAC7F,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+CAA+C;IAC/C,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAMD,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAejE;AAoQD,iBAAS,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAMzD;AAED,iBAAS,wBAAwB,CAC7B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAC9B,MAAM,EAAE,MAAM,GACf,MAAM,EAAE,CAEV;AA8BD;;;;GAIG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBpE;AAED,yEAAyE;AACzE,eAAO,MAAM,UAAU;;;;CAA8D,CAAC;AAGtF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-file merge for the Claude Code pack.
|
|
3
|
+
*
|
|
4
|
+
* Implements the table in plans/claude-install-pack.md §6.4:
|
|
5
|
+
*
|
|
6
|
+
* CLAUDE.md — managed-block rewrite (preserves user content)
|
|
7
|
+
* .claude/mj/** — overwritten as a unit (incl. sweep of stale files)
|
|
8
|
+
* .claude/settings.json — deep-merge per §10.2
|
|
9
|
+
* .claude/commands/* — seed-once; overwrite needs --force / --refresh-commands
|
|
10
|
+
* .claude/skills/** — same rule as commands
|
|
11
|
+
*
|
|
12
|
+
* The merger never destroys user content by default. `Force` and the
|
|
13
|
+
* `Refresh*` flags are explicit opt-ins.
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { parseManagedBlock, rewriteManagedBlock, wrapWithManagedBlock, ManagedBlockError, } from './ManagedBlockEditor.js';
|
|
18
|
+
import { mergeSettings } from './SettingsMerger.js';
|
|
19
|
+
import { emptyActionLog, recordOutcome, } from './PackTypes.js';
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Main entry point
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
export function mergePack(opts) {
|
|
24
|
+
const actions = emptyActionLog();
|
|
25
|
+
const warnings = [];
|
|
26
|
+
mergeRootClaudeMd(opts, actions, warnings);
|
|
27
|
+
mergeMjBundle(opts, actions, warnings);
|
|
28
|
+
if (!opts.SkipSettings)
|
|
29
|
+
mergeSettingsFile(opts, actions, warnings);
|
|
30
|
+
if (!opts.SkipCommands) {
|
|
31
|
+
mergeSeededTree(opts, actions, warnings, '.claude/commands/', !!opts.RefreshCommands);
|
|
32
|
+
}
|
|
33
|
+
if (!opts.SkipSkills) {
|
|
34
|
+
mergeSeededTree(opts, actions, warnings, '.claude/skills/', !!opts.RefreshSkills);
|
|
35
|
+
}
|
|
36
|
+
return { Actions: actions, Warnings: warnings };
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// CLAUDE.md — managed-block rewrite
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
function mergeRootClaudeMd(opts, actions, warnings) {
|
|
42
|
+
const packBytes = opts.PackFiles.get('CLAUDE.md');
|
|
43
|
+
if (!packBytes) {
|
|
44
|
+
recordOutcome(actions, { path: 'CLAUDE.md', outcome: 'error', reason: 'absent from pack' });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const packText = decodeText(packBytes);
|
|
48
|
+
let packBlock;
|
|
49
|
+
try {
|
|
50
|
+
packBlock = parseManagedBlock(packText);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
recordOutcome(actions, {
|
|
54
|
+
path: 'CLAUDE.md',
|
|
55
|
+
outcome: 'error',
|
|
56
|
+
reason: `pack CLAUDE.md malformed: ${err.message}`,
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!packBlock) {
|
|
61
|
+
recordOutcome(actions, {
|
|
62
|
+
path: 'CLAUDE.md',
|
|
63
|
+
outcome: 'error',
|
|
64
|
+
reason: 'pack CLAUDE.md has no managed block',
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const targetPath = path.join(opts.TargetDir, 'CLAUDE.md');
|
|
69
|
+
if (!existsSync(targetPath)) {
|
|
70
|
+
writeFile(opts, targetPath, packText);
|
|
71
|
+
recordOutcome(actions, { path: 'CLAUDE.md', outcome: 'added' });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const existing = readFileSync(targetPath, 'utf8');
|
|
75
|
+
let existingBlock;
|
|
76
|
+
try {
|
|
77
|
+
existingBlock = parseManagedBlock(existing);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
warnings.push(`CLAUDE.md has malformed MJ-MANAGED markers — leaving the file alone. ` +
|
|
81
|
+
`Fix it and re-run, or pass --force to wrap the existing content. (${err.message})`);
|
|
82
|
+
recordOutcome(actions, {
|
|
83
|
+
path: 'CLAUDE.md',
|
|
84
|
+
outcome: 'skipped',
|
|
85
|
+
reason: 'malformed managed markers',
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
let newContent;
|
|
90
|
+
if (existingBlock === null) {
|
|
91
|
+
newContent = wrapWithManagedBlock(existing, packBlock.body, packBlock.attrs);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
newContent = rewriteManagedBlock(existing, packBlock.body, packBlock.attrs);
|
|
95
|
+
}
|
|
96
|
+
if (newContent === existing) {
|
|
97
|
+
recordOutcome(actions, { path: 'CLAUDE.md', outcome: 'skipped', reason: 'identical' });
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
writeFile(opts, targetPath, newContent);
|
|
101
|
+
recordOutcome(actions, { path: 'CLAUDE.md', outcome: 'updated' });
|
|
102
|
+
}
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// .claude/mj/** — overwritten as a unit + sweep of stale files
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
function mergeMjBundle(opts, actions, _warnings) {
|
|
107
|
+
const mjPaths = collectPackPathsByPrefix(opts.PackFiles, '.claude/mj/');
|
|
108
|
+
const targetMjDir = path.join(opts.TargetDir, '.claude', 'mj');
|
|
109
|
+
// Sweep: delete any existing .claude/mj/ files that aren't in the new pack.
|
|
110
|
+
// The folder is "managed as a unit" — stale files from previous versions
|
|
111
|
+
// would otherwise linger.
|
|
112
|
+
if (existsSync(targetMjDir)) {
|
|
113
|
+
const expected = new Set(mjPaths);
|
|
114
|
+
for (const stale of walkRelativeFiles(targetMjDir, opts.TargetDir)) {
|
|
115
|
+
if (!stale.startsWith('.claude/mj/'))
|
|
116
|
+
continue;
|
|
117
|
+
if (!expected.has(stale)) {
|
|
118
|
+
const absPath = path.join(opts.TargetDir, stale);
|
|
119
|
+
if (!opts.DryRun)
|
|
120
|
+
unlinkSync(absPath);
|
|
121
|
+
recordOutcome(actions, {
|
|
122
|
+
path: stale,
|
|
123
|
+
outcome: 'updated',
|
|
124
|
+
reason: 'removed (no longer shipped)',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Write or overwrite every file the pack ships under .claude/mj/.
|
|
130
|
+
for (const relPath of mjPaths) {
|
|
131
|
+
const bytes = opts.PackFiles.get(relPath);
|
|
132
|
+
const absPath = path.join(opts.TargetDir, relPath);
|
|
133
|
+
const existed = existsSync(absPath);
|
|
134
|
+
const identical = existed && bytesEqual(readFileBytes(absPath), bytes);
|
|
135
|
+
if (identical) {
|
|
136
|
+
recordOutcome(actions, { path: relPath, outcome: 'skipped', reason: 'identical' });
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
writeFile(opts, absPath, bytes);
|
|
140
|
+
recordOutcome(actions, { path: relPath, outcome: existed ? 'updated' : 'added' });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// .claude/settings.json — deep-merge per §10.2
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
function mergeSettingsFile(opts, actions, warnings) {
|
|
147
|
+
const packBytes = opts.PackFiles.get('.claude/settings.json');
|
|
148
|
+
if (!packBytes) {
|
|
149
|
+
recordOutcome(actions, {
|
|
150
|
+
path: '.claude/settings.json',
|
|
151
|
+
outcome: 'error',
|
|
152
|
+
reason: 'absent from pack',
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
let packJson;
|
|
157
|
+
try {
|
|
158
|
+
packJson = JSON.parse(decodeText(packBytes));
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
recordOutcome(actions, {
|
|
162
|
+
path: '.claude/settings.json',
|
|
163
|
+
outcome: 'error',
|
|
164
|
+
reason: `pack settings.json invalid JSON: ${err.message}`,
|
|
165
|
+
});
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const targetPath = path.join(opts.TargetDir, '.claude', 'settings.json');
|
|
169
|
+
let existing = {};
|
|
170
|
+
const existed = existsSync(targetPath);
|
|
171
|
+
if (existed) {
|
|
172
|
+
try {
|
|
173
|
+
existing = JSON.parse(readFileSync(targetPath, 'utf8'));
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
warnings.push(`Existing .claude/settings.json is malformed JSON; leaving it alone. (${err.message})`);
|
|
177
|
+
recordOutcome(actions, {
|
|
178
|
+
path: '.claude/settings.json',
|
|
179
|
+
outcome: 'skipped',
|
|
180
|
+
reason: 'malformed JSON',
|
|
181
|
+
});
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const { Result, Changed } = mergeSettings({ Existing: existing, Pack: packJson });
|
|
186
|
+
if (!Changed && existed) {
|
|
187
|
+
recordOutcome(actions, {
|
|
188
|
+
path: '.claude/settings.json',
|
|
189
|
+
outcome: 'skipped',
|
|
190
|
+
reason: 'identical',
|
|
191
|
+
});
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
writeFile(opts, targetPath, JSON.stringify(Result, null, 2) + '\n');
|
|
195
|
+
recordOutcome(actions, {
|
|
196
|
+
path: '.claude/settings.json',
|
|
197
|
+
outcome: existed ? 'updated' : 'added',
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// .claude/commands/* and .claude/skills/** — seed-once with --force override
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
function mergeSeededTree(opts, actions, warnings, prefix, refresh) {
|
|
204
|
+
const paths = collectPackPathsByPrefix(opts.PackFiles, prefix);
|
|
205
|
+
for (const relPath of paths) {
|
|
206
|
+
const result = seedOneFile(opts, relPath, refresh, warnings);
|
|
207
|
+
recordOutcome(actions, result);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function seedOneFile(opts, relPath, refresh, warnings) {
|
|
211
|
+
const bytes = opts.PackFiles.get(relPath);
|
|
212
|
+
const absPath = path.join(opts.TargetDir, relPath);
|
|
213
|
+
if (!existsSync(absPath)) {
|
|
214
|
+
writeFile(opts, absPath, bytes);
|
|
215
|
+
return { path: relPath, outcome: 'added' };
|
|
216
|
+
}
|
|
217
|
+
const existing = readFileBytes(absPath);
|
|
218
|
+
if (bytesEqual(existing, bytes)) {
|
|
219
|
+
return { path: relPath, outcome: 'skipped', reason: 'identical' };
|
|
220
|
+
}
|
|
221
|
+
// Different — user has customized this file. Default behavior is to
|
|
222
|
+
// preserve theirs; --force or --refresh-commands/--refresh-skills
|
|
223
|
+
// overrides with a .bak backup.
|
|
224
|
+
if (opts.Force || refresh) {
|
|
225
|
+
if (!opts.DryRun) {
|
|
226
|
+
writeFileSync(absPath + '.bak', existing);
|
|
227
|
+
}
|
|
228
|
+
writeFile(opts, absPath, bytes);
|
|
229
|
+
return { path: relPath, outcome: 'updated', reason: 'overwritten (.bak saved)' };
|
|
230
|
+
}
|
|
231
|
+
warnings.push(`${relPath} differs from pack — kept user version. Pass --force to overwrite.`);
|
|
232
|
+
return { path: relPath, outcome: 'skipped', reason: 'user-modified' };
|
|
233
|
+
}
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Helpers
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
function decodeText(bytes) {
|
|
238
|
+
return new TextDecoder('utf-8').decode(bytes);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Read a file's raw bytes as a fresh `Uint8Array`. `readFileSync(path)` returns
|
|
242
|
+
* `Buffer`, which Node's strict @types/node 20+ won't always assign to
|
|
243
|
+
* `Uint8Array<ArrayBufferLike>` due to generic-param invariance — wrapping in
|
|
244
|
+
* `new Uint8Array(...)` produces a portable, type-clean value.
|
|
245
|
+
*/
|
|
246
|
+
function readFileBytes(absPath) {
|
|
247
|
+
return new Uint8Array(readFileSync(absPath));
|
|
248
|
+
}
|
|
249
|
+
function bytesEqual(a, b) {
|
|
250
|
+
if (a.length !== b.length)
|
|
251
|
+
return false;
|
|
252
|
+
for (let i = 0; i < a.length; i++) {
|
|
253
|
+
if (a[i] !== b[i])
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
function collectPackPathsByPrefix(files, prefix) {
|
|
259
|
+
return [...files.keys()].filter((p) => p.startsWith(prefix)).sort();
|
|
260
|
+
}
|
|
261
|
+
function writeFile(opts, absPath, body) {
|
|
262
|
+
assertWithinTarget(opts.TargetDir, absPath);
|
|
263
|
+
if (opts.DryRun)
|
|
264
|
+
return;
|
|
265
|
+
mkdirSync(path.dirname(absPath), { recursive: true });
|
|
266
|
+
if (typeof body === 'string') {
|
|
267
|
+
writeFileSync(absPath, body, 'utf8');
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
writeFileSync(absPath, body);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Defense-in-depth against malicious pack manifests: every write must
|
|
275
|
+
* resolve to a path inside `targetDir`. A hostile `--from` pack whose
|
|
276
|
+
* manifest declares `relPath: "../../etc/whatever"` would otherwise
|
|
277
|
+
* escape the install directory.
|
|
278
|
+
*/
|
|
279
|
+
function assertWithinTarget(targetDir, absPath) {
|
|
280
|
+
const resolvedTarget = path.resolve(targetDir);
|
|
281
|
+
const resolvedAbs = path.resolve(absPath);
|
|
282
|
+
const targetWithSep = resolvedTarget.endsWith(path.sep) ? resolvedTarget : resolvedTarget + path.sep;
|
|
283
|
+
if (resolvedAbs !== resolvedTarget && !resolvedAbs.startsWith(targetWithSep)) {
|
|
284
|
+
throw new Error(`Pack manifest tried to write outside the target directory: ${absPath} (target: ${targetDir})`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Walk a directory and return file paths relative to `relativeTo`, using
|
|
289
|
+
* POSIX separators (`/`) regardless of host OS — these are pack-relative
|
|
290
|
+
* paths the rest of the merger compares with.
|
|
291
|
+
*/
|
|
292
|
+
function walkRelativeFiles(dir, relativeTo) {
|
|
293
|
+
const out = [];
|
|
294
|
+
function recurse(current) {
|
|
295
|
+
for (const entry of readdirSync(current)) {
|
|
296
|
+
const abs = path.join(current, entry);
|
|
297
|
+
const stat = statSync(abs);
|
|
298
|
+
if (stat.isDirectory()) {
|
|
299
|
+
recurse(abs);
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
const rel = path.relative(relativeTo, abs).split(path.sep).join('/');
|
|
303
|
+
out.push(rel);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (existsSync(dir))
|
|
308
|
+
recurse(dir);
|
|
309
|
+
return out;
|
|
310
|
+
}
|
|
311
|
+
/** Re-export for tests that want to exercise the walker in isolation. */
|
|
312
|
+
export const _internals = { walkRelativeFiles, bytesEqual, collectPackPathsByPrefix };
|
|
313
|
+
// ManagedBlockError re-export — callers may catch it specifically.
|
|
314
|
+
export { ManagedBlockError };
|
|
315
|
+
//# sourceMappingURL=PackMerger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PackMerger.js","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackMerger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatters for `mj install:claude` and `mj update:claude`.
|
|
3
|
+
*
|
|
4
|
+
* Two shapes:
|
|
5
|
+
* - `formatPretty(result)` — human-readable colored summary for terminals
|
|
6
|
+
* - `formatJson(result)` — machine-readable schema from plan §7.5
|
|
7
|
+
*
|
|
8
|
+
* Lives in `lib/claude-pack/` (not in the command files) because both commands
|
|
9
|
+
* use the same renderer.
|
|
10
|
+
*/
|
|
11
|
+
import type { InstallResult } from './PackTypes.js';
|
|
12
|
+
/** Plain `--json` output. */
|
|
13
|
+
export declare function formatJson(result: InstallResult): string;
|
|
14
|
+
/**
|
|
15
|
+
* Multi-line colored summary for terminals. Sections:
|
|
16
|
+
*
|
|
17
|
+
* ✓ Claude Code pack v5.1.0 installed (MJ v5.33.0)
|
|
18
|
+
* added: N
|
|
19
|
+
* <list>
|
|
20
|
+
* updated: N
|
|
21
|
+
* <list>
|
|
22
|
+
* skipped: N (truncated to first few)
|
|
23
|
+
* warnings: N
|
|
24
|
+
* <list>
|
|
25
|
+
*
|
|
26
|
+
* Failure mode: a red banner + the errors[] list.
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatPretty(result: InstallResult): string;
|
|
29
|
+
//# sourceMappingURL=PackOutputFormatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PackOutputFormatter.d.ts","sourceRoot":"","sources":["../../../src/lib/claude-pack/PackOutputFormatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,6BAA6B;AAC7B,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAExD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CA6C1D"}
|