@slats/claude-assets-sync 0.1.3 → 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.
Files changed (228) hide show
  1. package/README.md +111 -587
  2. package/bin/claude-sync.mjs +24 -0
  3. package/dist/@aileron/declare/index.d.ts +4 -4
  4. package/dist/claude-hashes.json +20 -0
  5. package/dist/commands/index.d.ts +1 -112
  6. package/dist/commands/runCli/index.d.ts +2 -0
  7. package/dist/commands/runCli/runCli.cjs +31 -0
  8. package/dist/commands/runCli/runCli.d.ts +10 -0
  9. package/dist/commands/runCli/runCli.mjs +29 -0
  10. package/dist/commands/runCli/type.d.ts +28 -0
  11. package/dist/commands/runCli/utils/injectOne.cjs +48 -0
  12. package/dist/commands/runCli/utils/injectOne.d.ts +3 -0
  13. package/dist/commands/runCli/utils/injectOne.mjs +46 -0
  14. package/dist/commands/runCli/utils/resolveScopeFlag.cjs +28 -0
  15. package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +2 -0
  16. package/dist/commands/runCli/utils/resolveScopeFlag.mjs +26 -0
  17. package/dist/commands/runCli/utils/runInject.cjs +36 -0
  18. package/dist/commands/runCli/utils/runInject.d.ts +2 -0
  19. package/dist/commands/runCli/utils/runInject.mjs +34 -0
  20. package/dist/core/buildPlan/buildPlan.cjs +42 -0
  21. package/dist/core/buildPlan/buildPlan.d.ts +2 -0
  22. package/dist/core/buildPlan/buildPlan.mjs +40 -0
  23. package/dist/core/buildPlan/index.d.ts +2 -0
  24. package/dist/core/buildPlan/type.d.ts +32 -0
  25. package/dist/core/buildPlan/utils/toPosix.cjs +9 -0
  26. package/dist/core/buildPlan/utils/toPosix.d.ts +1 -0
  27. package/dist/core/buildPlan/utils/toPosix.mjs +7 -0
  28. package/dist/core/buildPlan/utils/walkFiles.cjs +25 -0
  29. package/dist/core/buildPlan/utils/walkFiles.d.ts +1 -0
  30. package/dist/core/buildPlan/utils/walkFiles.mjs +23 -0
  31. package/dist/core/hash/hash.cjs +30 -0
  32. package/dist/core/hash/hash.d.ts +4 -0
  33. package/dist/core/hash/hash.mjs +26 -0
  34. package/dist/core/hash/index.d.ts +1 -0
  35. package/dist/core/hashManifest/hashManifest.cjs +27 -0
  36. package/dist/core/hashManifest/hashManifest.d.ts +17 -0
  37. package/dist/core/hashManifest/hashManifest.mjs +23 -0
  38. package/dist/core/hashManifest/index.d.ts +1 -0
  39. package/dist/core/index.d.ts +5 -0
  40. package/dist/core/injectDocs/index.d.ts +2 -0
  41. package/dist/core/injectDocs/injectDocs.cjs +43 -0
  42. package/dist/core/injectDocs/injectDocs.d.ts +2 -0
  43. package/dist/core/injectDocs/injectDocs.mjs +41 -0
  44. package/dist/core/injectDocs/type.d.ts +30 -0
  45. package/dist/core/injectDocs/utils/applyAction.cjs +21 -0
  46. package/dist/core/injectDocs/utils/applyAction.d.ts +2 -0
  47. package/dist/core/injectDocs/utils/applyAction.mjs +19 -0
  48. package/dist/core/injectDocs/utils/emitCiForceList.cjs +10 -0
  49. package/dist/core/injectDocs/utils/emitCiForceList.d.ts +2 -0
  50. package/dist/core/injectDocs/utils/emitCiForceList.mjs +8 -0
  51. package/dist/core/injectDocs/utils/printPlan.cjs +20 -0
  52. package/dist/core/injectDocs/utils/printPlan.d.ts +2 -0
  53. package/dist/core/injectDocs/utils/printPlan.mjs +18 -0
  54. package/dist/core/injectDocs/utils/summarize.cjs +27 -0
  55. package/dist/core/injectDocs/utils/summarize.d.ts +3 -0
  56. package/dist/core/injectDocs/utils/summarize.mjs +25 -0
  57. package/dist/core/scope/index.d.ts +1 -0
  58. package/dist/core/scope/scope.cjs +46 -0
  59. package/dist/core/scope/scope.d.ts +16 -0
  60. package/dist/core/scope/scope.mjs +41 -0
  61. package/dist/core/scope/utils/isDirectory.cjs +14 -0
  62. package/dist/core/scope/utils/isDirectory.d.ts +1 -0
  63. package/dist/core/scope/utils/isDirectory.mjs +12 -0
  64. package/dist/index.cjs +15 -9
  65. package/dist/index.d.ts +3 -5
  66. package/dist/index.mjs +7 -3
  67. package/dist/prompts/confirmForce.cjs +27 -0
  68. package/dist/prompts/confirmForce.d.ts +1 -0
  69. package/dist/prompts/confirmForce.mjs +25 -0
  70. package/dist/prompts/index.d.ts +2 -0
  71. package/dist/prompts/selectScope.cjs +30 -0
  72. package/dist/prompts/selectScope.d.ts +2 -0
  73. package/dist/prompts/selectScope.mjs +28 -0
  74. package/dist/utils/heartbeat.cjs +25 -0
  75. package/dist/utils/heartbeat.d.ts +16 -0
  76. package/dist/utils/heartbeat.mjs +23 -0
  77. package/dist/utils/logger.cjs +7 -0
  78. package/dist/utils/logger.d.ts +8 -0
  79. package/dist/utils/logger.mjs +7 -0
  80. package/dist/utils/types.d.ts +1 -252
  81. package/dist/utils/version.cjs +2 -14
  82. package/dist/utils/version.d.ts +3 -53
  83. package/dist/utils/version.mjs +2 -13
  84. package/docs/bundle-size-decision.md +36 -0
  85. package/docs/claude/skills/claude-sync-applier/SKILL.md +195 -0
  86. package/docs/claude/skills/claude-sync-applier/knowledge/claude-md-template.md +77 -0
  87. package/docs/claude/skills/claude-sync-applier/knowledge/dependency-cruiser.md +126 -0
  88. package/docs/claude/skills/claude-sync-applier/knowledge/gotchas.md +139 -0
  89. package/docs/claude/skills/claude-sync-applier/knowledge/package-json-patches.md +130 -0
  90. package/docs/claude/skills/claude-sync-applier/knowledge/reference-files.md +120 -0
  91. package/docs/claude/skills/claude-sync-applier/knowledge/smoke-tests.md +102 -0
  92. package/docs/consumer-integration.md +153 -0
  93. package/package.json +25 -17
  94. package/scripts/build-hashes.mjs +30 -0
  95. package/scripts/buildHashes.d.mts +15 -0
  96. package/scripts/buildHashes.mjs +82 -0
  97. package/scripts/claude-build-hashes.mjs +42 -0
  98. package/scripts/inject-version.js +112 -0
  99. package/dist/cli.cjs +0 -8
  100. package/dist/cli.d.ts +0 -1
  101. package/dist/cli.mjs +0 -7
  102. package/dist/commands/add.cjs +0 -80
  103. package/dist/commands/add.d.ts +0 -8
  104. package/dist/commands/add.mjs +0 -78
  105. package/dist/commands/list.cjs +0 -94
  106. package/dist/commands/list.d.ts +0 -15
  107. package/dist/commands/list.mjs +0 -91
  108. package/dist/commands/migrate.cjs +0 -9
  109. package/dist/commands/migrate.d.ts +0 -6
  110. package/dist/commands/migrate.mjs +0 -7
  111. package/dist/commands/remove.cjs +0 -127
  112. package/dist/commands/remove.d.ts +0 -6
  113. package/dist/commands/remove.mjs +0 -105
  114. package/dist/commands/status.cjs +0 -193
  115. package/dist/commands/status.d.ts +0 -6
  116. package/dist/commands/status.mjs +0 -171
  117. package/dist/commands/sync.cjs +0 -28
  118. package/dist/commands/sync.d.ts +0 -6
  119. package/dist/commands/sync.mjs +0 -26
  120. package/dist/commands/types.d.ts +0 -89
  121. package/dist/commands/update.cjs +0 -209
  122. package/dist/commands/update.d.ts +0 -29
  123. package/dist/commands/update.mjs +0 -206
  124. package/dist/components/add/AddCommand.cjs +0 -103
  125. package/dist/components/add/AddCommand.d.ts +0 -14
  126. package/dist/components/add/AddCommand.mjs +0 -101
  127. package/dist/components/add/BulkAddView.cjs +0 -165
  128. package/dist/components/add/BulkAddView.d.ts +0 -11
  129. package/dist/components/add/BulkAddView.mjs +0 -163
  130. package/dist/components/add/index.d.ts +0 -2
  131. package/dist/components/index.d.ts +0 -2
  132. package/dist/components/list/EditableTreeItem.d.ts +0 -13
  133. package/dist/components/list/ListCommand.cjs +0 -651
  134. package/dist/components/list/ListCommand.d.ts +0 -5
  135. package/dist/components/list/ListCommand.mjs +0 -649
  136. package/dist/components/list/SyncedPackageTree.d.ts +0 -14
  137. package/dist/components/list/index.d.ts +0 -10
  138. package/dist/components/list/types.d.ts +0 -14
  139. package/dist/components/primitives/Box.d.ts +0 -4
  140. package/dist/components/primitives/Spinner.d.ts +0 -6
  141. package/dist/components/primitives/Text.d.ts +0 -4
  142. package/dist/components/primitives/index.d.ts +0 -3
  143. package/dist/components/remove/RemoveConfirm.cjs +0 -18
  144. package/dist/components/remove/RemoveConfirm.d.ts +0 -11
  145. package/dist/components/remove/RemoveConfirm.mjs +0 -16
  146. package/dist/components/shared/Confirm.cjs +0 -30
  147. package/dist/components/shared/Confirm.d.ts +0 -8
  148. package/dist/components/shared/Confirm.mjs +0 -28
  149. package/dist/components/shared/MenuItem.cjs +0 -18
  150. package/dist/components/shared/MenuItem.d.ts +0 -7
  151. package/dist/components/shared/MenuItem.mjs +0 -16
  152. package/dist/components/shared/ProgressBar.d.ts +0 -7
  153. package/dist/components/shared/StepRunner.cjs +0 -58
  154. package/dist/components/shared/StepRunner.d.ts +0 -15
  155. package/dist/components/shared/StepRunner.mjs +0 -56
  156. package/dist/components/shared/Table.cjs +0 -19
  157. package/dist/components/shared/Table.d.ts +0 -8
  158. package/dist/components/shared/Table.mjs +0 -17
  159. package/dist/components/shared/index.d.ts +0 -6
  160. package/dist/components/status/PackageStatusCard.d.ts +0 -10
  161. package/dist/components/status/StatusDisplay.cjs +0 -26
  162. package/dist/components/status/StatusDisplay.d.ts +0 -23
  163. package/dist/components/status/StatusDisplay.mjs +0 -24
  164. package/dist/components/status/StatusTreeNode.cjs +0 -40
  165. package/dist/components/status/StatusTreeNode.d.ts +0 -15
  166. package/dist/components/status/StatusTreeNode.mjs +0 -38
  167. package/dist/components/status/index.d.ts +0 -6
  168. package/dist/components/tree/AssetTreeNode.cjs +0 -54
  169. package/dist/components/tree/AssetTreeNode.d.ts +0 -12
  170. package/dist/components/tree/AssetTreeNode.mjs +0 -52
  171. package/dist/components/tree/TreeSelect.cjs +0 -129
  172. package/dist/components/tree/TreeSelect.d.ts +0 -12
  173. package/dist/components/tree/TreeSelect.mjs +0 -127
  174. package/dist/components/tree/index.d.ts +0 -4
  175. package/dist/core/assetStructure.cjs +0 -30
  176. package/dist/core/assetStructure.d.ts +0 -36
  177. package/dist/core/assetStructure.mjs +0 -27
  178. package/dist/core/cli.cjs +0 -106
  179. package/dist/core/cli.d.ts +0 -9
  180. package/dist/core/cli.mjs +0 -103
  181. package/dist/core/constants.cjs +0 -28
  182. package/dist/core/constants.d.ts +0 -94
  183. package/dist/core/constants.mjs +0 -21
  184. package/dist/core/filesystem.cjs +0 -98
  185. package/dist/core/filesystem.d.ts +0 -94
  186. package/dist/core/filesystem.mjs +0 -88
  187. package/dist/core/github.cjs +0 -115
  188. package/dist/core/github.d.ts +0 -61
  189. package/dist/core/github.mjs +0 -107
  190. package/dist/core/io.cjs +0 -46
  191. package/dist/core/io.d.ts +0 -40
  192. package/dist/core/io.mjs +0 -39
  193. package/dist/core/listOperations.cjs +0 -228
  194. package/dist/core/listOperations.d.ts +0 -43
  195. package/dist/core/listOperations.mjs +0 -205
  196. package/dist/core/localSource.cjs +0 -126
  197. package/dist/core/localSource.d.ts +0 -33
  198. package/dist/core/localSource.mjs +0 -120
  199. package/dist/core/migration.cjs +0 -201
  200. package/dist/core/migration.d.ts +0 -57
  201. package/dist/core/migration.mjs +0 -198
  202. package/dist/core/packageScanner.cjs +0 -360
  203. package/dist/core/packageScanner.d.ts +0 -22
  204. package/dist/core/packageScanner.mjs +0 -356
  205. package/dist/core/sync.cjs +0 -400
  206. package/dist/core/sync.d.ts +0 -21
  207. package/dist/core/sync.mjs +0 -397
  208. package/dist/core/syncMeta.cjs +0 -242
  209. package/dist/core/syncMeta.d.ts +0 -75
  210. package/dist/core/syncMeta.mjs +0 -229
  211. package/dist/utils/dependencies.cjs +0 -57
  212. package/dist/utils/dependencies.d.ts +0 -10
  213. package/dist/utils/dependencies.mjs +0 -34
  214. package/dist/utils/nameTransform.cjs +0 -13
  215. package/dist/utils/nameTransform.d.ts +0 -65
  216. package/dist/utils/nameTransform.mjs +0 -11
  217. package/dist/utils/package.cjs +0 -170
  218. package/dist/utils/package.d.ts +0 -105
  219. package/dist/utils/package.mjs +0 -157
  220. package/dist/utils/packageName.cjs +0 -24
  221. package/dist/utils/packageName.d.ts +0 -32
  222. package/dist/utils/packageName.mjs +0 -21
  223. package/dist/utils/paths.cjs +0 -18
  224. package/dist/utils/paths.d.ts +0 -55
  225. package/dist/utils/paths.mjs +0 -15
  226. package/dist/version.cjs +0 -5
  227. package/dist/version.d.ts +0 -5
  228. package/dist/version.mjs +0 -3
package/dist/index.cjs CHANGED
@@ -1,14 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var sync = require('./core/sync.cjs');
4
- var cli = require('./core/cli.cjs');
5
- var migration = require('./core/migration.cjs');
3
+ var runCli = require('./commands/runCli/runCli.cjs');
4
+ require('node:crypto');
5
+ require('node:fs/promises');
6
+ var hashManifest = require('./core/hashManifest/hashManifest.cjs');
7
+ var injectDocs = require('./core/injectDocs/injectDocs.cjs');
8
+ require('node:path');
9
+ var scope = require('./core/scope/scope.cjs');
6
10
 
7
11
 
8
12
 
9
- exports.syncPackage = sync.syncPackage;
10
- exports.syncPackages = sync.syncPackages;
11
- exports.createProgram = cli.createProgram;
12
- exports.run = cli.run;
13
- exports.migrateToFlat = migration.migrateToFlat;
14
- exports.needsMigration = migration.needsMigration;
13
+ exports.runCli = runCli.runCli;
14
+ exports.HASH_MANIFEST_FILENAME = hashManifest.HASH_MANIFEST_FILENAME;
15
+ exports.computeNamespacePrefixes = hashManifest.computeNamespacePrefixes;
16
+ exports.readHashManifest = hashManifest.readHashManifest;
17
+ exports.injectDocs = injectDocs.injectDocs;
18
+ exports.isInteractive = scope.isInteractive;
19
+ exports.isValidScope = scope.isValidScope;
20
+ exports.resolveScope = scope.resolveScope;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- export { syncPackage, syncPackages } from './core/sync';
2
- export { createProgram, run } from './core/cli.js';
3
- export { migrateToFlat, needsMigration } from './core/migration';
4
- export type { MigrationResult } from './core/migration';
5
- export type { AssetType, CliOptions, ClaudeConfig, GitHubRepoInfo, PackageInfo, SyncMeta, SyncResult, UnifiedSyncMeta, PackageSyncInfo, FileMapping, } from './utils/types';
1
+ export { runCli, type RunCliOptions } from './commands/index.js';
2
+ export { HASH_MANIFEST_FILENAME, computeNamespacePrefixes, injectDocs, isInteractive, isValidScope, readHashManifest, resolveScope, type HashManifest, type InjectOptions, type InjectReport, type Scope, type ScopeResolution, } from './core/index.js';
3
+ export type { AssetType } from './utils/types.js';
package/dist/index.mjs CHANGED
@@ -1,3 +1,7 @@
1
- export { syncPackage, syncPackages } from './core/sync.mjs';
2
- export { createProgram, run } from './core/cli.mjs';
3
- export { migrateToFlat, needsMigration } from './core/migration.mjs';
1
+ export { runCli } from './commands/runCli/runCli.mjs';
2
+ import 'node:crypto';
3
+ import 'node:fs/promises';
4
+ export { HASH_MANIFEST_FILENAME, computeNamespacePrefixes, readHashManifest } from './core/hashManifest/hashManifest.mjs';
5
+ export { injectDocs } from './core/injectDocs/injectDocs.mjs';
6
+ import 'node:path';
7
+ export { isInteractive, isValidScope, resolveScope } from './core/scope/scope.mjs';
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ var prompts = require('@inquirer/prompts');
4
+ var pc = require('picocolors');
5
+
6
+ async function confirmForceAsync(divergedCount, orphanCount, relPaths) {
7
+ const extra = Math.max(0, divergedCount + orphanCount - relPaths.length);
8
+ const divergedPart = pc.red(pc.bold(`${divergedCount} diverged file(s)`));
9
+ const orphanPart = orphanCount > 0
10
+ ? ` and ${pc.red(pc.bold(`delete ${orphanCount} orphan(s)`))}`
11
+ : '';
12
+ process.stderr.write(`${pc.yellow(pc.bold('!'))} This will overwrite ${divergedPart}${orphanPart}:\n`);
13
+ for (const p of relPaths) {
14
+ process.stderr.write(` ${pc.dim('-')} ${p}\n`);
15
+ }
16
+ if (extra > 0) {
17
+ process.stderr.write(` ${pc.dim(`... and ${extra} more`)}\n`);
18
+ }
19
+ process.stderr.write('\n');
20
+ const answer = await prompts.confirm({
21
+ message: pc.bold('Do you have these in git? Proceed?'),
22
+ default: false,
23
+ });
24
+ return answer;
25
+ }
26
+
27
+ exports.confirmForceAsync = confirmForceAsync;
@@ -0,0 +1 @@
1
+ export declare function confirmForceAsync(divergedCount: number, orphanCount: number, relPaths: string[]): Promise<boolean>;
@@ -0,0 +1,25 @@
1
+ import { confirm } from '@inquirer/prompts';
2
+ import pc from 'picocolors';
3
+
4
+ async function confirmForceAsync(divergedCount, orphanCount, relPaths) {
5
+ const extra = Math.max(0, divergedCount + orphanCount - relPaths.length);
6
+ const divergedPart = pc.red(pc.bold(`${divergedCount} diverged file(s)`));
7
+ const orphanPart = orphanCount > 0
8
+ ? ` and ${pc.red(pc.bold(`delete ${orphanCount} orphan(s)`))}`
9
+ : '';
10
+ process.stderr.write(`${pc.yellow(pc.bold('!'))} This will overwrite ${divergedPart}${orphanPart}:\n`);
11
+ for (const p of relPaths) {
12
+ process.stderr.write(` ${pc.dim('-')} ${p}\n`);
13
+ }
14
+ if (extra > 0) {
15
+ process.stderr.write(` ${pc.dim(`... and ${extra} more`)}\n`);
16
+ }
17
+ process.stderr.write('\n');
18
+ const answer = await confirm({
19
+ message: pc.bold('Do you have these in git? Proceed?'),
20
+ default: false,
21
+ });
22
+ return answer;
23
+ }
24
+
25
+ export { confirmForceAsync };
@@ -0,0 +1,2 @@
1
+ export { selectScopeAsync } from './selectScope.js';
2
+ export { confirmForceAsync } from './confirmForce.js';
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var prompts = require('@inquirer/prompts');
4
+ var pc = require('picocolors');
5
+
6
+ const CHOICES = [
7
+ {
8
+ name: 'user',
9
+ value: 'user',
10
+ description: '~/.claude (applies globally to every project)',
11
+ },
12
+ {
13
+ name: 'project',
14
+ value: 'project',
15
+ description: 'nearest ancestor .claude (or <cwd>/.claude)',
16
+ },
17
+ ];
18
+ async function selectScopeAsync() {
19
+ const answer = await prompts.select({
20
+ message: pc.bold(pc.cyan('Select injection scope:')),
21
+ choices: CHOICES.map((c) => ({
22
+ name: c.name,
23
+ value: c.value,
24
+ description: pc.dim(c.description),
25
+ })),
26
+ });
27
+ return answer;
28
+ }
29
+
30
+ exports.selectScopeAsync = selectScopeAsync;
@@ -0,0 +1,2 @@
1
+ import type { Scope } from '../core/scope/index.js';
2
+ export declare function selectScopeAsync(): Promise<Scope>;
@@ -0,0 +1,28 @@
1
+ import { select } from '@inquirer/prompts';
2
+ import pc from 'picocolors';
3
+
4
+ const CHOICES = [
5
+ {
6
+ name: 'user',
7
+ value: 'user',
8
+ description: '~/.claude (applies globally to every project)',
9
+ },
10
+ {
11
+ name: 'project',
12
+ value: 'project',
13
+ description: 'nearest ancestor .claude (or <cwd>/.claude)',
14
+ },
15
+ ];
16
+ async function selectScopeAsync() {
17
+ const answer = await select({
18
+ message: pc.bold(pc.cyan('Select injection scope:')),
19
+ choices: CHOICES.map((c) => ({
20
+ name: c.name,
21
+ value: c.value,
22
+ description: pc.dim(c.description),
23
+ })),
24
+ });
25
+ return answer;
26
+ }
27
+
28
+ export { selectScopeAsync };
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ var pc = require('picocolors');
4
+
5
+ function startHeartbeat(options = {}) {
6
+ const intervalMs = options.intervalMs ?? 500;
7
+ const label = options.label ?? 'working';
8
+ const emit = options.emit ??
9
+ ((line) => {
10
+ process.stderr.write(line);
11
+ });
12
+ const startedAt = Date.now();
13
+ const timer = setInterval(() => {
14
+ const elapsedMs = Date.now() - startedAt;
15
+ const seconds = (elapsedMs / 1000).toFixed(1);
16
+ emit(`${pc.dim(`[${seconds}s]`)} ${pc.cyan(`${label}...`)}\n`);
17
+ }, intervalMs);
18
+ if (typeof timer.unref === 'function')
19
+ timer.unref();
20
+ return () => {
21
+ clearInterval(timer);
22
+ };
23
+ }
24
+
25
+ exports.startHeartbeat = startHeartbeat;
@@ -0,0 +1,16 @@
1
+ export interface HeartbeatOptions {
2
+ intervalMs?: number;
3
+ emit?: (line: string) => void;
4
+ label?: string;
5
+ }
6
+ export type StopHeartbeat = () => void;
7
+ /**
8
+ * Wall-clock heartbeat ticker for long-running async operations.
9
+ *
10
+ * Wraps operations at the command layer (NOT core) to provide in-flight
11
+ * visibility when stdout is quiet for several hundred milliseconds.
12
+ *
13
+ * The emitted line is written via the provided `emit` (default: stderr) so
14
+ * it never interferes with programmatic stdout output.
15
+ */
16
+ export declare function startHeartbeat(options?: HeartbeatOptions): StopHeartbeat;
@@ -0,0 +1,23 @@
1
+ import pc from 'picocolors';
2
+
3
+ function startHeartbeat(options = {}) {
4
+ const intervalMs = options.intervalMs ?? 500;
5
+ const label = options.label ?? 'working';
6
+ const emit = options.emit ??
7
+ ((line) => {
8
+ process.stderr.write(line);
9
+ });
10
+ const startedAt = Date.now();
11
+ const timer = setInterval(() => {
12
+ const elapsedMs = Date.now() - startedAt;
13
+ const seconds = (elapsedMs / 1000).toFixed(1);
14
+ emit(`${pc.dim(`[${seconds}s]`)} ${pc.cyan(`${label}...`)}\n`);
15
+ }, intervalMs);
16
+ if (typeof timer.unref === 'function')
17
+ timer.unref();
18
+ return () => {
19
+ clearInterval(timer);
20
+ };
21
+ }
22
+
23
+ export { startHeartbeat };
@@ -62,6 +62,13 @@ const logger = {
62
62
  console.log(pc.yellow(pc.bold('[DRY RUN] No files will be created or modified.')));
63
63
  console.log();
64
64
  },
65
+ heading(message) {
66
+ console.log();
67
+ console.log(pc.bold(pc.cyan(`▸ ${message}`)));
68
+ },
69
+ accent(message) {
70
+ return pc.cyan(pc.bold(message));
71
+ },
65
72
  };
66
73
 
67
74
  exports.logger = logger;
@@ -54,4 +54,12 @@ export declare const logger: {
54
54
  * Log dry-run notice
55
55
  */
56
56
  dryRunNotice(): void;
57
+ /**
58
+ * Top-level section heading with a distinct accent.
59
+ */
60
+ heading(message: string): void;
61
+ /**
62
+ * Inline accent — cyan bold, for short labels interleaved with content.
63
+ */
64
+ accent(message: string): string;
57
65
  };
@@ -60,6 +60,13 @@ const logger = {
60
60
  console.log(pc.yellow(pc.bold('[DRY RUN] No files will be created or modified.')));
61
61
  console.log();
62
62
  },
63
+ heading(message) {
64
+ console.log();
65
+ console.log(pc.bold(pc.cyan(`▸ ${message}`)));
66
+ },
67
+ accent(message) {
68
+ return pc.cyan(pc.bold(message));
69
+ },
63
70
  };
64
71
 
65
72
  export { logger };
@@ -1,252 +1 @@
1
- /**
2
- * Asset structure type (nested or flat)
3
- */
4
- export type AssetStructure = 'nested' | 'flat';
5
- /**
6
- * Configuration for a specific asset type
7
- */
8
- export interface AssetTypeConfig {
9
- structure: AssetStructure;
10
- }
11
- /**
12
- * Configuration mapping asset types to their structure
13
- */
14
- export interface AssetsConfig {
15
- [assetType: string]: AssetTypeConfig;
16
- }
17
- /**
18
- * Claude configuration in package.json
19
- */
20
- export interface ClaudeConfig {
21
- /** Path to Claude assets directory (e.g., "docs/claude") */
22
- assetPath: string;
23
- /** Optional configuration for asset types */
24
- assets?: AssetsConfig;
25
- }
26
- /**
27
- * Repository information from package.json
28
- */
29
- export interface RepositoryInfo {
30
- type: string;
31
- url: string;
32
- directory?: string;
33
- }
34
- /**
35
- * Parsed package information
36
- */
37
- export interface PackageInfo {
38
- name: string;
39
- version: string;
40
- repository: RepositoryInfo;
41
- claude?: ClaudeConfig;
42
- }
43
- /**
44
- * Parsed GitHub repository details
45
- */
46
- export interface GitHubRepoInfo {
47
- owner: string;
48
- repo: string;
49
- directory?: string;
50
- }
51
- /**
52
- * GitHub API file/directory entry
53
- */
54
- export interface GitHubEntry {
55
- name: string;
56
- path: string;
57
- type: 'file' | 'dir';
58
- download_url: string | null;
59
- sha: string;
60
- }
61
- /**
62
- * Sync metadata stored in .sync-meta.json
63
- */
64
- export interface SyncMeta {
65
- /** Package version at sync time */
66
- version: string;
67
- /** ISO timestamp of last sync */
68
- syncedAt: string;
69
- /** List of synced file names */
70
- files: string[];
71
- }
72
- /**
73
- * Asset type (can be any string, not limited to commands/skills/agents)
74
- */
75
- export type AssetType = string;
76
- /**
77
- * Sync result for a single package
78
- */
79
- export interface SyncResult {
80
- packageName: string;
81
- success: boolean;
82
- skipped: boolean;
83
- reason?: string;
84
- syncedFiles?: Record<string, string[]>;
85
- }
86
- /**
87
- * CLI options
88
- */
89
- export interface CliOptions {
90
- package: string[];
91
- force: boolean;
92
- dryRun: boolean;
93
- local: boolean;
94
- /** Custom git ref (branch, tag, or commit) to fetch from */
95
- ref?: string;
96
- /** Use flat structure (default: true in v2) */
97
- flat?: boolean;
98
- }
99
- /**
100
- * Workspace info from yarn workspaces
101
- */
102
- export interface WorkspaceInfo {
103
- name: string;
104
- location: string;
105
- }
106
- /**
107
- * Unified sync metadata for all packages (flat structure)
108
- */
109
- export interface UnifiedSyncMeta {
110
- /** Schema version for migration support */
111
- schemaVersion: string;
112
- /** Last sync timestamp */
113
- syncedAt: string;
114
- /** Package metadata keyed by transformed name (e.g., "canard-schemaForm") */
115
- packages: Record<string, PackageSyncInfo>;
116
- /** SkillUnit format version marker. Present when data uses SkillUnit[] format. */
117
- skillUnitFormat?: string;
118
- }
119
- /**
120
- * Individual package sync info within unified meta
121
- */
122
- export interface PackageSyncInfo {
123
- /** Original package name (e.g., "@canard/schema-form") */
124
- originalName: string;
125
- /** Package version at sync time */
126
- version: string;
127
- /** Whether this package is from local workspace (true) or remote npm (false/undefined) */
128
- local?: boolean;
129
- /** Synced skill units per asset type. Each entry is a SkillUnit (atomic unit of selection). */
130
- files: Record<string, SkillUnit[]>;
131
- /** Optional exclusions for selective syncing */
132
- exclusions?: {
133
- /** Excluded directory paths (e.g., ["skills/deprecated"]) */
134
- directories: string[];
135
- /** Excluded file paths (e.g., ["commands/old-cmd.md"]) */
136
- files: string[];
137
- };
138
- }
139
- /**
140
- * File name mapping (original to transformed)
141
- */
142
- export interface FileMapping {
143
- /** Original file name (e.g., "guide.md") */
144
- original: string;
145
- /** Transformed file name (e.g., "canard-schemaForm_guide.md") */
146
- transformed: string;
147
- }
148
- /**
149
- * Represents an atomic skill unit in sync metadata.
150
- * A skill unit is either a single .md file or a directory skill (containing SKILL.md).
151
- */
152
- export interface SkillUnit {
153
- /** Skill name (file name without extension, or directory name) */
154
- name: string;
155
- /** Whether this is a directory-based skill */
156
- isDirectory: boolean;
157
- /** For flat structure: transformed file/directory name */
158
- transformed?: string;
159
- /** Internal files within directory skill (for tree browsing, not individual selection).
160
- * Only present when isDirectory is true.
161
- * Stores relative paths within the skill directory (e.g., ["SKILL.md", "knowledge/api.md"]) */
162
- internalFiles?: string[];
163
- }
164
- /**
165
- * Add command selection result
166
- */
167
- export interface AddCommandSelection {
168
- /** Package name */
169
- packageName: string;
170
- /** Source type */
171
- source: 'local' | 'npm';
172
- /** Git ref (branch, tag, or commit) */
173
- ref?: string;
174
- /** Included skill units by asset type (skill unit names, not individual file paths) */
175
- includedAssets: Record<string, string[]>;
176
- /** Excluded skill units by asset type (skill unit names, not individual file paths) */
177
- excludedAssets: Record<string, string[]>;
178
- }
179
- /**
180
- * Tree node for asset selection
181
- */
182
- export interface TreeNode {
183
- /** Unique identifier */
184
- id: string;
185
- /** Node label */
186
- label: string;
187
- /** Full path */
188
- path: string;
189
- /** Node type */
190
- type: 'directory' | 'file' | 'skill-directory';
191
- /** Child nodes */
192
- children?: TreeNode[];
193
- /** Selection state */
194
- selected: boolean;
195
- /** Expanded state */
196
- expanded: boolean;
197
- /** Disabled state */
198
- disabled?: boolean;
199
- /** If true, this node's children are view-only (cannot be individually selected) */
200
- viewOnly?: boolean;
201
- /** Additional metadata */
202
- metadata?: {
203
- assetType: string;
204
- originalName?: string;
205
- transformedName?: string;
206
- };
207
- }
208
- /**
209
- * Re-export asset structure utilities from core module
210
- *
211
- * @deprecated These exports are kept for backward compatibility only.
212
- * Please update your imports to use the recommended paths below.
213
- *
214
- * Migration Guide:
215
- * ================
216
- *
217
- * ❌ OLD (Deprecated - will be removed in v1.0.0)
218
- * ```typescript
219
- * import {
220
- * DEFAULT_ASSET_TYPES,
221
- * DEFAULT_ASSET_STRUCTURES,
222
- * getAssetStructure,
223
- * detectStructureType,
224
- * validateAssetStructure,
225
- * normalizeAssetStructure,
226
- * } from './utils/types';
227
- * ```
228
- *
229
- * ✅ NEW (Recommended)
230
- * ```typescript
231
- * import {
232
- * DEFAULT_ASSET_TYPES,
233
- * DEFAULT_ASSET_STRUCTURES,
234
- * getAssetStructure,
235
- * detectStructureType,
236
- * validateAssetStructure,
237
- * normalizeAssetStructure,
238
- * } from './core/assetStructure';
239
- * ```
240
- *
241
- * Why the change?
242
- * - Clearer module organization (asset structure logic lives in core/)
243
- * - Direct imports are more maintainable and tree-shake friendly
244
- * - Reduces coupling between utils and core modules
245
- *
246
- * Timeline:
247
- * - v0.x: Old imports work (with deprecation warnings)
248
- * - v1.0.0: Re-exports removed
249
- *
250
- * @see ../core/assetStructure for the actual implementations
251
- */
252
- export { DEFAULT_ASSET_TYPES, DEFAULT_ASSET_STRUCTURES, getAssetStructure, detectStructureType, validateAssetStructure, normalizeAssetStructure, } from '../core/assetStructure';
1
+ export type AssetType = 'skills' | 'commands' | 'rules' | string;
@@ -1,17 +1,5 @@
1
1
  'use strict';
2
2
 
3
- function compareVersions(v1, v2) {
4
- return v1 === v2;
5
- }
6
- function needsVersionSync(currentVersion, syncedVersion) {
7
- if (syncedVersion === undefined) {
8
- return true;
9
- }
10
- if (currentVersion === '' || syncedVersion === '') {
11
- return true;
12
- }
13
- return !compareVersions(currentVersion, syncedVersion);
14
- }
3
+ const VERSION = '0.2.0';
15
4
 
16
- exports.compareVersions = compareVersions;
17
- exports.needsVersionSync = needsVersionSync;
5
+ exports.VERSION = VERSION;
@@ -1,55 +1,5 @@
1
1
  /**
2
- * Version comparison utilities
3
- *
4
- * These functions provide exact string-based version comparison
5
- * for semantic versioning with pre-release and build metadata support.
2
+ * Current package version from package.json
3
+ * Automatically synchronized during build process
6
4
  */
7
- /**
8
- * Compare two semantic versions for exact equality
9
- *
10
- * Performs case-sensitive exact string comparison of version strings.
11
- * Supports semver format including pre-release and build metadata:
12
- * - Major.Minor.Patch (e.g., "1.2.3")
13
- * - Pre-release (e.g., "1.0.0-alpha", "1.0.0-rc.1")
14
- * - Build metadata (e.g., "1.0.0+build.123")
15
- * - Combined (e.g., "1.0.0-rc.1+build.456")
16
- *
17
- * @param v1 - First version string
18
- * @param v2 - Second version string
19
- * @returns true if versions are exactly equal (case-sensitive)
20
- *
21
- * @example
22
- * compareVersions('1.0.0', '1.0.0') // true
23
- * compareVersions('1.0.0', '1.0.1') // false
24
- * compareVersions('1.0.0-alpha', '1.0.0-Alpha') // false (case-sensitive)
25
- * compareVersions('1.0.0+build.1', '1.0.0+build.1') // true
26
- */
27
- export declare function compareVersions(v1: string, v2: string): boolean;
28
- /**
29
- * Check if version synchronization is needed
30
- *
31
- * Determines whether assets need to be re-synced based on version comparison.
32
- * Sync is needed in the following cases:
33
- * - First sync (syncedVersion is undefined)
34
- * - Empty version strings (currentVersion or syncedVersion is empty)
35
- * - Version mismatch (versions are not exactly equal)
36
- *
37
- * @param currentVersion - Current package version from package.json
38
- * @param syncedVersion - Previously synced version from .sync-meta.json (undefined if never synced)
39
- * @returns true if sync is needed, false if versions match
40
- *
41
- * @example
42
- * // First sync
43
- * needsVersionSync('1.0.0', undefined) // true
44
- *
45
- * // Version mismatch
46
- * needsVersionSync('1.0.1', '1.0.0') // true
47
- *
48
- * // Versions match
49
- * needsVersionSync('1.0.0', '1.0.0') // false
50
- *
51
- * // Empty strings
52
- * needsVersionSync('', '1.0.0') // true
53
- * needsVersionSync('1.0.0', '') // true
54
- */
55
- export declare function needsVersionSync(currentVersion: string, syncedVersion?: string): boolean;
5
+ export declare const VERSION = "0.2.0";
@@ -1,14 +1,3 @@
1
- function compareVersions(v1, v2) {
2
- return v1 === v2;
3
- }
4
- function needsVersionSync(currentVersion, syncedVersion) {
5
- if (syncedVersion === undefined) {
6
- return true;
7
- }
8
- if (currentVersion === '' || syncedVersion === '') {
9
- return true;
10
- }
11
- return !compareVersions(currentVersion, syncedVersion);
12
- }
1
+ const VERSION = '0.2.0';
13
2
 
14
- export { compareVersions, needsVersionSync };
3
+ export { VERSION };
@@ -0,0 +1,36 @@
1
+ # Phase 0 — Prompt Library Bundle-Size Decision
2
+
3
+ **Gate threshold**: tree-shaken footprint for `select` + `confirm` ≤ 200 KB.
4
+
5
+ ## Measurement setup
6
+
7
+ - Entry: `import { select, confirm } from '@inquirer/prompts'; export { select, confirm };`
8
+ - Bundler: esbuild 0.28.0 via `yarn dlx esbuild`
9
+ - Flags: `--bundle --format=esm --platform=node --external:node:*`
10
+ - Measured from `packages/slats/claude-assets-sync/` with `@inquirer/prompts@^8.4.2` resolved via yarn workspaces.
11
+
12
+ ## Results
13
+
14
+ | Variant | Size |
15
+ |---|---|
16
+ | Bundled + minified | **28.5 KB** (29,215 bytes) |
17
+ | Bundled, no minify | 62.0 KB (63,522 bytes) |
18
+ | Raw `node_modules/@inquirer` footprint | 1.6 MB (includes unused prompt families) |
19
+
20
+ The minified bundle represents the realistic runtime cost after slats's Rollup build. The raw node_modules number is not representative because tree-shaking and dead-code elimination eliminate unused prompts from the published `dist/`.
21
+
22
+ ## Decision
23
+
24
+ **Pinned**: `@inquirer/prompts@^8.4.2` in `dependencies`.
25
+
26
+ **Pinned**: `@inquirer/testing@^3.3.5` in `devDependencies`.
27
+
28
+ The 28.5 KB minified footprint is **7× under the 200 KB threshold**. No fallback to `@clack/prompts` needed.
29
+
30
+ ## Fallback plan (unused)
31
+
32
+ If a future `@inquirer/prompts` major release inflates the bundle past 200 KB (e.g., new default imports that resist tree-shaking), replace with `@clack/prompts@^0.7.0` (~30 KB, zero deps) and re-run this measurement. `@clack` lacks a first-party testing kit, so `tests/prompts/*.test.ts` would need to switch to raw stdin mocking.
33
+
34
+ ## Artifacts
35
+
36
+ Scratch files removed after measurement: `scratch-entry.mjs`, `scratch-bundle.mjs`, `scratch-bundle-raw.mjs`.