@claudeflows/cli 0.1.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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/bin/claudeflows.js +2 -0
  4. package/dist/commands/doctor.d.ts +3 -0
  5. package/dist/commands/doctor.d.ts.map +1 -0
  6. package/dist/commands/doctor.js +111 -0
  7. package/dist/commands/doctor.js.map +1 -0
  8. package/dist/commands/init.d.ts +3 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +174 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/install.d.ts +3 -0
  13. package/dist/commands/install.d.ts.map +1 -0
  14. package/dist/commands/install.js +353 -0
  15. package/dist/commands/install.js.map +1 -0
  16. package/dist/commands/license.d.ts +3 -0
  17. package/dist/commands/license.d.ts.map +1 -0
  18. package/dist/commands/license.js +167 -0
  19. package/dist/commands/license.js.map +1 -0
  20. package/dist/commands/list.d.ts +3 -0
  21. package/dist/commands/list.d.ts.map +1 -0
  22. package/dist/commands/list.js +97 -0
  23. package/dist/commands/list.js.map +1 -0
  24. package/dist/commands/login.d.ts +3 -0
  25. package/dist/commands/login.d.ts.map +1 -0
  26. package/dist/commands/login.js +144 -0
  27. package/dist/commands/login.js.map +1 -0
  28. package/dist/commands/publish.d.ts +3 -0
  29. package/dist/commands/publish.d.ts.map +1 -0
  30. package/dist/commands/publish.js +121 -0
  31. package/dist/commands/publish.js.map +1 -0
  32. package/dist/commands/uninstall.d.ts +3 -0
  33. package/dist/commands/uninstall.d.ts.map +1 -0
  34. package/dist/commands/uninstall.js +66 -0
  35. package/dist/commands/uninstall.js.map +1 -0
  36. package/dist/commands/update.d.ts +3 -0
  37. package/dist/commands/update.d.ts.map +1 -0
  38. package/dist/commands/update.js +167 -0
  39. package/dist/commands/update.js.map +1 -0
  40. package/dist/commands/verify.d.ts +3 -0
  41. package/dist/commands/verify.d.ts.map +1 -0
  42. package/dist/commands/verify.js +129 -0
  43. package/dist/commands/verify.js.map +1 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +28 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/lib/config.d.ts +10 -0
  49. package/dist/lib/config.d.ts.map +1 -0
  50. package/dist/lib/config.js +37 -0
  51. package/dist/lib/config.js.map +1 -0
  52. package/dist/lib/doctor.d.ts +14 -0
  53. package/dist/lib/doctor.d.ts.map +1 -0
  54. package/dist/lib/doctor.js +344 -0
  55. package/dist/lib/doctor.js.map +1 -0
  56. package/dist/lib/env-manager.d.ts +10 -0
  57. package/dist/lib/env-manager.d.ts.map +1 -0
  58. package/dist/lib/env-manager.js +60 -0
  59. package/dist/lib/env-manager.js.map +1 -0
  60. package/dist/lib/installer.d.ts +3 -0
  61. package/dist/lib/installer.d.ts.map +1 -0
  62. package/dist/lib/installer.js +43 -0
  63. package/dist/lib/installer.js.map +1 -0
  64. package/dist/lib/integrity.d.ts +42 -0
  65. package/dist/lib/integrity.d.ts.map +1 -0
  66. package/dist/lib/integrity.js +119 -0
  67. package/dist/lib/integrity.js.map +1 -0
  68. package/dist/lib/license.d.ts +39 -0
  69. package/dist/lib/license.d.ts.map +1 -0
  70. package/dist/lib/license.js +108 -0
  71. package/dist/lib/license.js.map +1 -0
  72. package/dist/lib/manifest.d.ts +74 -0
  73. package/dist/lib/manifest.d.ts.map +1 -0
  74. package/dist/lib/manifest.js +47 -0
  75. package/dist/lib/manifest.js.map +1 -0
  76. package/dist/lib/mcp-setup.d.ts +18 -0
  77. package/dist/lib/mcp-setup.d.ts.map +1 -0
  78. package/dist/lib/mcp-setup.js +92 -0
  79. package/dist/lib/mcp-setup.js.map +1 -0
  80. package/dist/lib/registry.d.ts +28 -0
  81. package/dist/lib/registry.d.ts.map +1 -0
  82. package/dist/lib/registry.js +77 -0
  83. package/dist/lib/registry.js.map +1 -0
  84. package/dist/lib/skill-linker.d.ts +13 -0
  85. package/dist/lib/skill-linker.d.ts.map +1 -0
  86. package/dist/lib/skill-linker.js +134 -0
  87. package/dist/lib/skill-linker.js.map +1 -0
  88. package/package.json +49 -0
@@ -0,0 +1,344 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { readFile, stat, readlink } from 'node:fs/promises';
3
+ import { join, resolve } from 'node:path';
4
+ import { homedir } from 'node:os';
5
+ import semver from 'semver';
6
+ import { getInstalledDir } from './config.js';
7
+ import { verifyIntegrity } from './integrity.js';
8
+ async function fileExists(path) {
9
+ try {
10
+ await stat(path);
11
+ return true;
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
17
+ function getVersion(command) {
18
+ try {
19
+ const output = execSync(command, { stdio: 'pipe', encoding: 'utf-8' }).trim();
20
+ // Extract version number from output like "v20.11.0" or "Python 3.12.0"
21
+ const match = output.match(/(\d+\.\d+\.\d+)/);
22
+ return match ? match[1] : null;
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ export async function checkRuntime(manifest) {
29
+ const checks = [];
30
+ if (!manifest.runtime) {
31
+ return checks;
32
+ }
33
+ for (const [name, requiredRange] of Object.entries(manifest.runtime)) {
34
+ let versionCmd;
35
+ switch (name) {
36
+ case 'node':
37
+ versionCmd = 'node --version';
38
+ break;
39
+ case 'python':
40
+ versionCmd = 'python3 --version';
41
+ break;
42
+ case 'claude_code':
43
+ versionCmd = 'claude --version';
44
+ break;
45
+ default:
46
+ versionCmd = `${name} --version`;
47
+ }
48
+ const installed = getVersion(versionCmd);
49
+ if (!installed) {
50
+ checks.push({
51
+ name: `Runtime: ${name}`,
52
+ status: 'error',
53
+ message: `${name} is not installed (requires ${requiredRange})`,
54
+ });
55
+ continue;
56
+ }
57
+ if (semver.satisfies(installed, requiredRange)) {
58
+ checks.push({
59
+ name: `Runtime: ${name}`,
60
+ status: 'ok',
61
+ message: `${name} ${installed} satisfies ${requiredRange}`,
62
+ });
63
+ }
64
+ else {
65
+ checks.push({
66
+ name: `Runtime: ${name}`,
67
+ status: 'error',
68
+ message: `${name} ${installed} does not satisfy ${requiredRange}`,
69
+ });
70
+ }
71
+ }
72
+ return checks;
73
+ }
74
+ export async function checkMcp(manifest) {
75
+ const checks = [];
76
+ if (!manifest.mcp) {
77
+ return checks;
78
+ }
79
+ let mcpJson = { mcpServers: {} };
80
+ try {
81
+ const mcpPath = join(homedir(), '.claude', '.mcp.json');
82
+ const raw = await readFile(mcpPath, 'utf-8');
83
+ mcpJson = JSON.parse(raw);
84
+ }
85
+ catch {
86
+ // No MCP config found
87
+ }
88
+ for (const [name, config] of Object.entries(manifest.mcp)) {
89
+ const isConfigured = name in (mcpJson.mcpServers ?? {});
90
+ const isRequired = config.required !== false;
91
+ if (isConfigured) {
92
+ checks.push({
93
+ name: `MCP: ${name}`,
94
+ status: 'ok',
95
+ message: `${name} is configured`,
96
+ });
97
+ // Check env vars for this MCP server
98
+ if (config.env) {
99
+ for (const [envName, envConfig] of Object.entries(config.env)) {
100
+ const isSet = !!process.env[envName];
101
+ const envRequired = envConfig.required !== false;
102
+ if (isSet) {
103
+ checks.push({
104
+ name: `MCP env: ${envName}`,
105
+ status: 'ok',
106
+ message: `${envName} is set`,
107
+ });
108
+ }
109
+ else if (envRequired) {
110
+ checks.push({
111
+ name: `MCP env: ${envName}`,
112
+ status: 'error',
113
+ message: `${envName} is not set (required by ${name})`,
114
+ });
115
+ }
116
+ else {
117
+ checks.push({
118
+ name: `MCP env: ${envName}`,
119
+ status: 'warn',
120
+ message: `${envName} is not set (optional for ${name})`,
121
+ });
122
+ }
123
+ }
124
+ }
125
+ }
126
+ else if (isRequired) {
127
+ checks.push({
128
+ name: `MCP: ${name}`,
129
+ status: 'error',
130
+ message: `${name} is not configured (required)`,
131
+ });
132
+ }
133
+ else {
134
+ checks.push({
135
+ name: `MCP: ${name}`,
136
+ status: 'warn',
137
+ message: `${name} is not configured (optional)`,
138
+ });
139
+ }
140
+ }
141
+ return checks;
142
+ }
143
+ export async function checkEnv(manifest) {
144
+ const checks = [];
145
+ if (!manifest.env) {
146
+ return checks;
147
+ }
148
+ for (const [name, config] of Object.entries(manifest.env)) {
149
+ const isSet = !!process.env[name];
150
+ const isRequired = config.required !== false;
151
+ if (isSet) {
152
+ checks.push({
153
+ name: `Env: ${name}`,
154
+ status: 'ok',
155
+ message: `${name} is set`,
156
+ });
157
+ }
158
+ else if (isRequired) {
159
+ checks.push({
160
+ name: `Env: ${name}`,
161
+ status: 'error',
162
+ message: `${name} is not set${config.description ? ` (${config.description})` : ''}`,
163
+ });
164
+ }
165
+ else {
166
+ checks.push({
167
+ name: `Env: ${name}`,
168
+ status: 'warn',
169
+ message: `${name} is not set (optional)${config.description ? ` — ${config.description}` : ''}`,
170
+ });
171
+ }
172
+ }
173
+ return checks;
174
+ }
175
+ export async function checkDeps(manifest) {
176
+ const checks = [];
177
+ if (!manifest.dependencies) {
178
+ return checks;
179
+ }
180
+ const installedDir = getInstalledDir();
181
+ for (const [depName, depConfig] of Object.entries(manifest.dependencies)) {
182
+ const depDir = join(installedDir, depName);
183
+ const depExists = await fileExists(join(depDir, 'workflow.json'));
184
+ const isRequired = depConfig.required !== false;
185
+ if (depExists) {
186
+ if (depConfig.version) {
187
+ try {
188
+ const raw = await readFile(join(depDir, 'workflow.json'), 'utf-8');
189
+ const depManifest = JSON.parse(raw);
190
+ if (depManifest.version && semver.satisfies(depManifest.version, depConfig.version)) {
191
+ checks.push({
192
+ name: `Dep: ${depName}`,
193
+ status: 'ok',
194
+ message: `${depName} ${depManifest.version} satisfies ${depConfig.version}`,
195
+ });
196
+ }
197
+ else {
198
+ checks.push({
199
+ name: `Dep: ${depName}`,
200
+ status: 'warn',
201
+ message: `${depName} ${depManifest.version ?? 'unknown'} may not satisfy ${depConfig.version}`,
202
+ });
203
+ }
204
+ }
205
+ catch {
206
+ checks.push({
207
+ name: `Dep: ${depName}`,
208
+ status: 'warn',
209
+ message: `${depName} is installed but version could not be verified`,
210
+ });
211
+ }
212
+ }
213
+ else {
214
+ checks.push({
215
+ name: `Dep: ${depName}`,
216
+ status: 'ok',
217
+ message: `${depName} is installed`,
218
+ });
219
+ }
220
+ }
221
+ else if (isRequired) {
222
+ checks.push({
223
+ name: `Dep: ${depName}`,
224
+ status: 'error',
225
+ message: `${depName} is not installed (required)`,
226
+ });
227
+ }
228
+ else {
229
+ checks.push({
230
+ name: `Dep: ${depName}`,
231
+ status: 'warn',
232
+ message: `${depName} is not installed (optional)`,
233
+ });
234
+ }
235
+ }
236
+ return checks;
237
+ }
238
+ export async function checkSkills(manifest, installDir) {
239
+ const checks = [];
240
+ const skillsDir = join(homedir(), '.claude', 'skills');
241
+ for (const skill of manifest.skills) {
242
+ const linkedName = `${manifest.name}-${skill.name}`;
243
+ const linkPath = join(skillsDir, linkedName);
244
+ const targetPath = resolve(installDir, skill.path);
245
+ // Check that the source file exists
246
+ if (!(await fileExists(targetPath))) {
247
+ checks.push({
248
+ name: `Skill: ${skill.name}`,
249
+ status: 'error',
250
+ message: `Source file not found: ${skill.path}`,
251
+ });
252
+ continue;
253
+ }
254
+ // Check that the symlink exists and points to the right place
255
+ try {
256
+ const actualTarget = await readlink(linkPath);
257
+ if (resolve(actualTarget) === resolve(targetPath)) {
258
+ checks.push({
259
+ name: `Skill: ${skill.name}`,
260
+ status: 'ok',
261
+ message: `${linkedName} linked correctly`,
262
+ });
263
+ }
264
+ else {
265
+ checks.push({
266
+ name: `Skill: ${skill.name}`,
267
+ status: 'warn',
268
+ message: `${linkedName} exists but points to ${actualTarget} instead of ${targetPath}`,
269
+ });
270
+ }
271
+ }
272
+ catch {
273
+ checks.push({
274
+ name: `Skill: ${skill.name}`,
275
+ status: 'error',
276
+ message: `${linkedName} is not linked in ${skillsDir}`,
277
+ });
278
+ }
279
+ }
280
+ return checks;
281
+ }
282
+ export async function checkIntegrity(manifest, installDir) {
283
+ const checks = [];
284
+ if (!manifest.integrity) {
285
+ checks.push({
286
+ name: 'Integrity',
287
+ status: 'warn',
288
+ message: 'No integrity block in workflow.json — file verification not available',
289
+ });
290
+ return checks;
291
+ }
292
+ try {
293
+ const result = await verifyIntegrity(installDir, manifest.integrity);
294
+ if (result.valid) {
295
+ checks.push({
296
+ name: 'Integrity',
297
+ status: 'ok',
298
+ message: `All ${Object.keys(manifest.integrity.files).length} file hashes verified`,
299
+ });
300
+ }
301
+ else {
302
+ if (result.mismatches.length > 0) {
303
+ checks.push({
304
+ name: 'Integrity',
305
+ status: 'error',
306
+ message: `${result.mismatches.length} file(s) modified: ${result.mismatches.join(', ')}`,
307
+ });
308
+ }
309
+ if (result.missing.length > 0) {
310
+ checks.push({
311
+ name: 'Integrity',
312
+ status: 'error',
313
+ message: `${result.missing.length} file(s) missing: ${result.missing.join(', ')}`,
314
+ });
315
+ }
316
+ if (result.extra.length > 0) {
317
+ checks.push({
318
+ name: 'Integrity',
319
+ status: 'warn',
320
+ message: `${result.extra.length} extra file(s) not in manifest: ${result.extra.join(', ')}`,
321
+ });
322
+ }
323
+ }
324
+ }
325
+ catch (err) {
326
+ checks.push({
327
+ name: 'Integrity',
328
+ status: 'error',
329
+ message: `Integrity check failed: ${err.message}`,
330
+ });
331
+ }
332
+ return checks;
333
+ }
334
+ export async function runDoctor(manifest, installDir) {
335
+ const results = [];
336
+ results.push(...(await checkRuntime(manifest)));
337
+ results.push(...(await checkMcp(manifest)));
338
+ results.push(...(await checkEnv(manifest)));
339
+ results.push(...(await checkDeps(manifest)));
340
+ results.push(...(await checkSkills(manifest, installDir)));
341
+ results.push(...(await checkIntegrity(manifest, installDir)));
342
+ return results;
343
+ }
344
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/lib/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { EnvVar } from './manifest.js';
2
+ export declare function checkEnvVar(name: string): string | undefined;
3
+ export declare function promptEnvVar(name: string, config: EnvVar): Promise<string | null>;
4
+ export declare function suggestShellExport(name: string, value: string): string;
5
+ export declare function setupEnvVars(envConfig: Record<string, EnvVar>): Promise<{
6
+ set: string[];
7
+ missing: string[];
8
+ suggestions: string[];
9
+ }>;
10
+ //# sourceMappingURL=env-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-manager.d.ts","sourceRoot":"","sources":["../../src/lib/env-manager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5D;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4BxB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGtE;AAaD,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAgBtE"}
@@ -0,0 +1,60 @@
1
+ import { input, confirm } from '@inquirer/prompts';
2
+ import chalk from 'chalk';
3
+ export function checkEnvVar(name) {
4
+ return process.env[name];
5
+ }
6
+ export async function promptEnvVar(name, config) {
7
+ const existing = checkEnvVar(name);
8
+ if (existing) {
9
+ return existing;
10
+ }
11
+ let message = `Environment variable ${chalk.bold(name)} is not set.`;
12
+ if (config.description) {
13
+ message += `\n ${config.description}`;
14
+ }
15
+ if (config.url) {
16
+ message += `\n Get it at: ${chalk.cyan(config.url)}`;
17
+ }
18
+ const shouldSet = await confirm({
19
+ message: `${message}\n Would you like to set it now?`,
20
+ default: config.required !== false,
21
+ });
22
+ if (!shouldSet) {
23
+ return null;
24
+ }
25
+ const value = await input({
26
+ message: `Enter value for ${name}:`,
27
+ });
28
+ return value || null;
29
+ }
30
+ export function suggestShellExport(name, value) {
31
+ const shellRc = detectShellRc();
32
+ return `To persist this variable, add the following to ${chalk.bold(shellRc)}:\n\n ${chalk.green(`export ${name}="${value}"`)}\n`;
33
+ }
34
+ function detectShellRc() {
35
+ const shell = process.env.SHELL ?? '';
36
+ if (shell.includes('zsh')) {
37
+ return '~/.zshrc';
38
+ }
39
+ if (shell.includes('bash')) {
40
+ return '~/.bashrc';
41
+ }
42
+ return '~/.profile';
43
+ }
44
+ export async function setupEnvVars(envConfig) {
45
+ const set = [];
46
+ const missing = [];
47
+ const suggestions = [];
48
+ for (const [name, config] of Object.entries(envConfig)) {
49
+ const value = await promptEnvVar(name, config);
50
+ if (value) {
51
+ set.push(name);
52
+ suggestions.push(suggestShellExport(name, value));
53
+ }
54
+ else {
55
+ missing.push(name);
56
+ }
57
+ }
58
+ return { set, missing, suggestions };
59
+ }
60
+ //# sourceMappingURL=env-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-manager.js","sourceRoot":"","sources":["../../src/lib/env-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,MAAc;IAEd,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,GAAG,wBAAwB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;IACrE,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,OAAO,IAAI,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC;IACD,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,OAAO,IAAI,kBAAkB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACxD,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC;QAC9B,OAAO,EAAE,GAAG,OAAO,mCAAmC;QACtD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,KAAK;KACnC,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC;QACxB,OAAO,EAAE,mBAAmB,IAAI,GAAG;KACpC,CAAC,CAAC;IAEH,OAAO,KAAK,IAAI,IAAI,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,KAAa;IAC5D,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,OAAO,kDAAkD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,KAAK,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,KAAK,GAAG,CAAC,IAAI,CAAC;AACrI,CAAC;AAED,SAAS,aAAa;IACpB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;IACtC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAiC;IAEjC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACf,WAAW,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AACvC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function downloadFromGithub(url: string, destDir: string): Promise<void>;
2
+ export declare function extractWorkflow(source: string, dest: string): Promise<void>;
3
+ //# sourceMappingURL=installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/lib/installer.ts"],"names":[],"mappings":"AAKA,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBpF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAejF"}
@@ -0,0 +1,43 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { rm, cp, mkdtemp, stat } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ export async function downloadFromGithub(url, destDir) {
6
+ // Normalize the URL — accept both https://github.com/user/repo and full .git URLs
7
+ let repoUrl = url.trim();
8
+ if (!repoUrl.endsWith('.git')) {
9
+ repoUrl = repoUrl.replace(/\/$/, '') + '.git';
10
+ }
11
+ const tempDir = await mkdtemp(join(tmpdir(), 'cw-clone-'));
12
+ try {
13
+ execSync(`git clone --depth 1 "${repoUrl}" "${tempDir}/repo"`, {
14
+ stdio: 'pipe',
15
+ timeout: 60_000,
16
+ });
17
+ const clonedDir = join(tempDir, 'repo');
18
+ // Remove .git directory
19
+ await rm(join(clonedDir, '.git'), { recursive: true, force: true });
20
+ // Copy contents to destination
21
+ await cp(clonedDir, destDir, { recursive: true });
22
+ }
23
+ finally {
24
+ await rm(tempDir, { recursive: true, force: true });
25
+ }
26
+ }
27
+ export async function extractWorkflow(source, dest) {
28
+ // Determine if source is a local path or URL
29
+ try {
30
+ const s = await stat(source);
31
+ if (s.isDirectory()) {
32
+ await cp(source, dest, { recursive: true });
33
+ // Remove .git if present
34
+ await rm(join(dest, '.git'), { recursive: true, force: true });
35
+ return;
36
+ }
37
+ }
38
+ catch {
39
+ // Not a local path — try as URL
40
+ }
41
+ await downloadFromGithub(source, dest);
42
+ }
43
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/lib/installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAW,EAAE,OAAe;IACnE,kFAAkF;IAClF,IAAI,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC;IAChD,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;IAE3D,IAAI,CAAC;QACH,QAAQ,CAAC,wBAAwB,OAAO,MAAM,OAAO,QAAQ,EAAE;YAC7D,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAExC,wBAAwB;QACxB,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpE,+BAA+B;QAC/B,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,IAAY;IAChE,6CAA6C;IAC7C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACpB,MAAM,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,yBAAyB;YACzB,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,MAAM,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Registry Ed25519 public key for verifying workflow signatures.
3
+ * The corresponding private key is stored as a GitHub Actions secret (CW_SIGNING_KEY).
4
+ * This key can also be fetched from: https://claudeflows.dev/.well-known/signing-key.pub
5
+ */
6
+ export declare const REGISTRY_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAcynktEtcJ38faZLHJkb4cpEIRyIMcDogyzCsL9YJn3w=\n-----END PUBLIC KEY-----";
7
+ export interface IntegrityBlock {
8
+ algorithm: 'sha256';
9
+ files: Record<string, string>;
10
+ root: string;
11
+ signature?: string;
12
+ }
13
+ export interface IntegrityResult {
14
+ valid: boolean;
15
+ mismatches: string[];
16
+ missing: string[];
17
+ extra: string[];
18
+ }
19
+ /**
20
+ * Compute SHA-256 hashes for all files in a directory.
21
+ * Returns a map of relative POSIX paths to hex-encoded SHA-256 hashes.
22
+ */
23
+ export declare function computeFileHashes(dir: string, excludePatterns?: string[]): Promise<Record<string, string>>;
24
+ /**
25
+ * Compute a root hash from a file hash map.
26
+ * Sorts keys alphabetically, concatenates "path:hash" pairs, then SHA-256s the result.
27
+ */
28
+ export declare function computeRootHash(files: Record<string, string>): string;
29
+ /**
30
+ * Verify file integrity by recomputing hashes and comparing against expected values.
31
+ */
32
+ export declare function verifyIntegrity(dir: string, expected: IntegrityBlock): Promise<IntegrityResult>;
33
+ /**
34
+ * Verify an Ed25519 signature against a root hash using the registry public key.
35
+ */
36
+ export declare function verifySignature(rootHash: string, signature: string, publicKey?: string): boolean;
37
+ /**
38
+ * Build an integrity block for a workflow directory.
39
+ * Used during `claudeflows publish` to embed integrity data into workflow.json.
40
+ */
41
+ export declare function buildIntegrityBlock(dir: string): Promise<IntegrityBlock>;
42
+ //# sourceMappingURL=integrity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/lib/integrity.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,uHACsF,CAAC;AAUvH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,QAAQ,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAqCD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,eAAe,GAAE,MAAM,EAAqB,GAC3C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAcjC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAIrE;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,eAAe,CAAC,CA+B1B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,GAAE,MAA4B,GACtC,OAAO,CAQT;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAI9E"}
@@ -0,0 +1,119 @@
1
+ import { createHash, verify as cryptoVerify } from 'node:crypto';
2
+ import { readFile, readdir } from 'node:fs/promises';
3
+ import { join, relative, posix } from 'node:path';
4
+ /**
5
+ * Registry Ed25519 public key for verifying workflow signatures.
6
+ * The corresponding private key is stored as a GitHub Actions secret (CW_SIGNING_KEY).
7
+ * This key can also be fetched from: https://claudeflows.dev/.well-known/signing-key.pub
8
+ */
9
+ export const REGISTRY_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAcynktEtcJ38faZLHJkb4cpEIRyIMcDogyzCsL9YJn3w=\n-----END PUBLIC KEY-----';
10
+ /** Patterns to exclude from integrity hashing */
11
+ const EXCLUDE_PATTERNS = [
12
+ '.git',
13
+ 'node_modules',
14
+ '.deps.json',
15
+ '.skill-links.json',
16
+ ];
17
+ /**
18
+ * Recursively collect all file paths in a directory, excluding specified patterns.
19
+ */
20
+ async function collectFiles(dir, baseDir, excludePatterns) {
21
+ const entries = await readdir(dir, { withFileTypes: true });
22
+ const files = [];
23
+ for (const entry of entries) {
24
+ const fullPath = join(dir, entry.name);
25
+ const relativePath = relative(baseDir, fullPath);
26
+ // Check if any exclude pattern matches
27
+ const shouldExclude = excludePatterns.some((pattern) => entry.name === pattern ||
28
+ relativePath === pattern ||
29
+ relativePath.startsWith(pattern + '/'));
30
+ if (shouldExclude)
31
+ continue;
32
+ if (entry.isDirectory()) {
33
+ files.push(...(await collectFiles(fullPath, baseDir, excludePatterns)));
34
+ }
35
+ else if (entry.isFile()) {
36
+ files.push(relativePath);
37
+ }
38
+ }
39
+ return files;
40
+ }
41
+ /**
42
+ * Compute SHA-256 hashes for all files in a directory.
43
+ * Returns a map of relative POSIX paths to hex-encoded SHA-256 hashes.
44
+ */
45
+ export async function computeFileHashes(dir, excludePatterns = EXCLUDE_PATTERNS) {
46
+ const files = await collectFiles(dir, dir, excludePatterns);
47
+ const hashes = {};
48
+ for (const filePath of files) {
49
+ const fullPath = join(dir, filePath);
50
+ const content = await readFile(fullPath);
51
+ const hash = createHash('sha256').update(content).digest('hex');
52
+ // Normalize to POSIX paths for cross-platform consistency
53
+ const posixPath = filePath.split('/').join(posix.sep);
54
+ hashes[posixPath] = hash;
55
+ }
56
+ return hashes;
57
+ }
58
+ /**
59
+ * Compute a root hash from a file hash map.
60
+ * Sorts keys alphabetically, concatenates "path:hash" pairs, then SHA-256s the result.
61
+ */
62
+ export function computeRootHash(files) {
63
+ const sorted = Object.keys(files).sort();
64
+ const concatenated = sorted.map((key) => `${key}:${files[key]}`).join('\n');
65
+ return createHash('sha256').update(concatenated).digest('hex');
66
+ }
67
+ /**
68
+ * Verify file integrity by recomputing hashes and comparing against expected values.
69
+ */
70
+ export async function verifyIntegrity(dir, expected) {
71
+ const actual = await computeFileHashes(dir);
72
+ const actualRoot = computeRootHash(actual);
73
+ const mismatches = [];
74
+ const missing = [];
75
+ const extra = [];
76
+ // Check for files in expected but not in actual, or with different hashes
77
+ for (const [filePath, expectedHash] of Object.entries(expected.files)) {
78
+ if (!(filePath in actual)) {
79
+ missing.push(filePath);
80
+ }
81
+ else if (actual[filePath] !== expectedHash) {
82
+ mismatches.push(filePath);
83
+ }
84
+ }
85
+ // Check for files in actual but not in expected
86
+ for (const filePath of Object.keys(actual)) {
87
+ if (!(filePath in expected.files)) {
88
+ extra.push(filePath);
89
+ }
90
+ }
91
+ const valid = mismatches.length === 0 &&
92
+ missing.length === 0 &&
93
+ extra.length === 0 &&
94
+ actualRoot === expected.root;
95
+ return { valid, mismatches, missing, extra };
96
+ }
97
+ /**
98
+ * Verify an Ed25519 signature against a root hash using the registry public key.
99
+ */
100
+ export function verifySignature(rootHash, signature, publicKey = REGISTRY_PUBLIC_KEY) {
101
+ try {
102
+ const signatureBuffer = Buffer.from(signature, 'base64');
103
+ const dataBuffer = Buffer.from(rootHash, 'utf-8');
104
+ return cryptoVerify(null, dataBuffer, publicKey, signatureBuffer);
105
+ }
106
+ catch {
107
+ return false;
108
+ }
109
+ }
110
+ /**
111
+ * Build an integrity block for a workflow directory.
112
+ * Used during `claudeflows publish` to embed integrity data into workflow.json.
113
+ */
114
+ export async function buildIntegrityBlock(dir) {
115
+ const files = await computeFileHashes(dir);
116
+ const root = computeRootHash(files);
117
+ return { algorithm: 'sha256', files, root };
118
+ }
119
+ //# sourceMappingURL=integrity.js.map