@slats/claude-assets-sync 0.1.4 → 0.3.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 (239) hide show
  1. package/README.md +89 -581
  2. package/bin/inject-claude-settings.mjs +4 -0
  3. package/dist/claude-hashes.json +20 -0
  4. package/dist/commands/index.d.ts +1 -112
  5. package/dist/commands/runCli/index.d.ts +2 -0
  6. package/dist/commands/runCli/runCli.cjs +53 -0
  7. package/dist/commands/runCli/runCli.d.ts +14 -0
  8. package/dist/commands/runCli/runCli.mjs +51 -0
  9. package/dist/commands/runCli/type.d.ts +19 -0
  10. package/dist/commands/runCli/utils/classifyTarget.cjs +48 -0
  11. package/dist/commands/runCli/utils/classifyTarget.d.ts +19 -0
  12. package/dist/commands/runCli/utils/classifyTarget.mjs +46 -0
  13. package/dist/commands/runCli/utils/injectOne.cjs +47 -0
  14. package/dist/commands/runCli/utils/injectOne.d.ts +3 -0
  15. package/dist/commands/runCli/utils/injectOne.mjs +45 -0
  16. package/dist/commands/runCli/utils/resolvePackage.cjs +77 -0
  17. package/dist/commands/runCli/utils/resolvePackage.d.ts +16 -0
  18. package/dist/commands/runCli/utils/resolvePackage.mjs +74 -0
  19. package/dist/commands/runCli/utils/resolveScopeAlias.cjs +69 -0
  20. package/dist/commands/runCli/utils/resolveScopeAlias.d.ts +2 -0
  21. package/dist/commands/runCli/utils/resolveScopeAlias.mjs +67 -0
  22. package/dist/commands/runCli/utils/resolveScopeFlag.cjs +28 -0
  23. package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +2 -0
  24. package/dist/commands/runCli/utils/resolveScopeFlag.mjs +26 -0
  25. package/dist/commands/runCli/utils/resolveTargets.cjs +40 -0
  26. package/dist/commands/runCli/utils/resolveTargets.d.ts +15 -0
  27. package/dist/commands/runCli/utils/resolveTargets.mjs +38 -0
  28. package/dist/commands/runCli/utils/runInject.cjs +52 -0
  29. package/dist/commands/runCli/utils/runInject.d.ts +3 -0
  30. package/dist/commands/runCli/utils/runInject.mjs +50 -0
  31. package/dist/core/buildPlan/buildPlan.cjs +42 -0
  32. package/dist/core/buildPlan/buildPlan.d.ts +2 -0
  33. package/dist/core/buildPlan/buildPlan.mjs +40 -0
  34. package/dist/core/buildPlan/index.d.ts +2 -0
  35. package/dist/core/buildPlan/type.d.ts +32 -0
  36. package/dist/core/buildPlan/utils/toPosix.cjs +9 -0
  37. package/dist/core/buildPlan/utils/toPosix.d.ts +1 -0
  38. package/dist/core/buildPlan/utils/toPosix.mjs +7 -0
  39. package/dist/core/buildPlan/utils/walkFiles.cjs +25 -0
  40. package/dist/core/buildPlan/utils/walkFiles.d.ts +1 -0
  41. package/dist/core/buildPlan/utils/walkFiles.mjs +23 -0
  42. package/dist/core/hash/hash.cjs +30 -0
  43. package/dist/core/hash/hash.d.ts +4 -0
  44. package/dist/core/hash/hash.mjs +26 -0
  45. package/dist/core/hash/index.d.ts +1 -0
  46. package/dist/core/hashManifest/hashManifest.cjs +27 -0
  47. package/dist/core/hashManifest/hashManifest.d.ts +17 -0
  48. package/dist/core/hashManifest/hashManifest.mjs +23 -0
  49. package/dist/core/hashManifest/index.d.ts +1 -0
  50. package/dist/core/index.d.ts +5 -0
  51. package/dist/core/injectDocs/index.d.ts +2 -0
  52. package/dist/core/injectDocs/injectDocs.cjs +43 -0
  53. package/dist/core/injectDocs/injectDocs.d.ts +2 -0
  54. package/dist/core/injectDocs/injectDocs.mjs +41 -0
  55. package/dist/core/injectDocs/type.d.ts +30 -0
  56. package/dist/core/injectDocs/utils/applyAction.cjs +21 -0
  57. package/dist/core/injectDocs/utils/applyAction.d.ts +2 -0
  58. package/dist/core/injectDocs/utils/applyAction.mjs +19 -0
  59. package/dist/core/injectDocs/utils/emitCiForceList.cjs +10 -0
  60. package/dist/core/injectDocs/utils/emitCiForceList.d.ts +2 -0
  61. package/dist/core/injectDocs/utils/emitCiForceList.mjs +8 -0
  62. package/dist/core/injectDocs/utils/printPlan.cjs +20 -0
  63. package/dist/core/injectDocs/utils/printPlan.d.ts +2 -0
  64. package/dist/core/injectDocs/utils/printPlan.mjs +18 -0
  65. package/dist/core/injectDocs/utils/summarize.cjs +27 -0
  66. package/dist/core/injectDocs/utils/summarize.d.ts +3 -0
  67. package/dist/core/injectDocs/utils/summarize.mjs +25 -0
  68. package/dist/core/scope/index.d.ts +1 -0
  69. package/dist/core/scope/scope.cjs +46 -0
  70. package/dist/core/scope/scope.d.ts +16 -0
  71. package/dist/core/scope/scope.mjs +41 -0
  72. package/dist/core/scope/utils/isDirectory.cjs +14 -0
  73. package/dist/core/scope/utils/isDirectory.d.ts +1 -0
  74. package/dist/core/scope/utils/isDirectory.mjs +12 -0
  75. package/dist/index.cjs +15 -9
  76. package/dist/index.d.ts +3 -5
  77. package/dist/index.mjs +7 -3
  78. package/dist/prompts/confirmForce.cjs +27 -0
  79. package/dist/prompts/confirmForce.d.ts +1 -0
  80. package/dist/prompts/confirmForce.mjs +25 -0
  81. package/dist/prompts/index.d.ts +2 -0
  82. package/dist/prompts/selectScope.cjs +30 -0
  83. package/dist/prompts/selectScope.d.ts +2 -0
  84. package/dist/prompts/selectScope.mjs +28 -0
  85. package/dist/utils/heartbeat.cjs +25 -0
  86. package/dist/utils/heartbeat.d.ts +16 -0
  87. package/dist/utils/heartbeat.mjs +23 -0
  88. package/dist/utils/logger.cjs +7 -0
  89. package/dist/utils/logger.d.ts +8 -0
  90. package/dist/utils/logger.mjs +7 -0
  91. package/dist/utils/types.d.ts +1 -252
  92. package/dist/utils/version.cjs +2 -14
  93. package/dist/utils/version.d.ts +3 -53
  94. package/dist/utils/version.mjs +2 -13
  95. package/docs/bundle-size-decision.md +36 -0
  96. package/docs/claude/skills/claude-docs-asset-wiring/SKILL.md +159 -0
  97. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/claude-md-template.md +86 -0
  98. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/dependency-cruiser.md +54 -0
  99. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/gotchas.md +122 -0
  100. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/package-json-patches.md +145 -0
  101. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/reference-files.md +37 -0
  102. package/docs/claude/skills/claude-docs-asset-wiring/knowledge/smoke-tests.md +111 -0
  103. package/docs/consumer-integration.md +94 -0
  104. package/package.json +24 -16
  105. package/scripts/build-hashes.mjs +30 -0
  106. package/scripts/buildHashes.d.mts +15 -0
  107. package/scripts/buildHashes.mjs +82 -0
  108. package/scripts/claude-build-hashes.mjs +42 -0
  109. package/scripts/inject-version.js +112 -0
  110. package/dist/cli.cjs +0 -8
  111. package/dist/cli.d.ts +0 -1
  112. package/dist/cli.mjs +0 -7
  113. package/dist/commands/add.cjs +0 -80
  114. package/dist/commands/add.d.ts +0 -8
  115. package/dist/commands/add.mjs +0 -78
  116. package/dist/commands/list.cjs +0 -94
  117. package/dist/commands/list.d.ts +0 -15
  118. package/dist/commands/list.mjs +0 -91
  119. package/dist/commands/migrate.cjs +0 -9
  120. package/dist/commands/migrate.d.ts +0 -6
  121. package/dist/commands/migrate.mjs +0 -7
  122. package/dist/commands/remove.cjs +0 -127
  123. package/dist/commands/remove.d.ts +0 -6
  124. package/dist/commands/remove.mjs +0 -105
  125. package/dist/commands/status.cjs +0 -193
  126. package/dist/commands/status.d.ts +0 -6
  127. package/dist/commands/status.mjs +0 -171
  128. package/dist/commands/sync.cjs +0 -28
  129. package/dist/commands/sync.d.ts +0 -6
  130. package/dist/commands/sync.mjs +0 -26
  131. package/dist/commands/types.d.ts +0 -89
  132. package/dist/commands/update.cjs +0 -209
  133. package/dist/commands/update.d.ts +0 -29
  134. package/dist/commands/update.mjs +0 -206
  135. package/dist/components/add/AddCommand.cjs +0 -103
  136. package/dist/components/add/AddCommand.d.ts +0 -14
  137. package/dist/components/add/AddCommand.mjs +0 -101
  138. package/dist/components/add/BulkAddView.cjs +0 -165
  139. package/dist/components/add/BulkAddView.d.ts +0 -11
  140. package/dist/components/add/BulkAddView.mjs +0 -163
  141. package/dist/components/add/index.d.ts +0 -2
  142. package/dist/components/index.d.ts +0 -2
  143. package/dist/components/list/EditableTreeItem.d.ts +0 -13
  144. package/dist/components/list/ListCommand.cjs +0 -651
  145. package/dist/components/list/ListCommand.d.ts +0 -5
  146. package/dist/components/list/ListCommand.mjs +0 -649
  147. package/dist/components/list/SyncedPackageTree.d.ts +0 -14
  148. package/dist/components/list/index.d.ts +0 -10
  149. package/dist/components/list/types.d.ts +0 -14
  150. package/dist/components/primitives/Box.d.ts +0 -4
  151. package/dist/components/primitives/Spinner.d.ts +0 -6
  152. package/dist/components/primitives/Text.d.ts +0 -4
  153. package/dist/components/primitives/index.d.ts +0 -3
  154. package/dist/components/remove/RemoveConfirm.cjs +0 -18
  155. package/dist/components/remove/RemoveConfirm.d.ts +0 -11
  156. package/dist/components/remove/RemoveConfirm.mjs +0 -16
  157. package/dist/components/shared/Confirm.cjs +0 -30
  158. package/dist/components/shared/Confirm.d.ts +0 -8
  159. package/dist/components/shared/Confirm.mjs +0 -28
  160. package/dist/components/shared/MenuItem.cjs +0 -18
  161. package/dist/components/shared/MenuItem.d.ts +0 -7
  162. package/dist/components/shared/MenuItem.mjs +0 -16
  163. package/dist/components/shared/ProgressBar.d.ts +0 -7
  164. package/dist/components/shared/StepRunner.cjs +0 -58
  165. package/dist/components/shared/StepRunner.d.ts +0 -15
  166. package/dist/components/shared/StepRunner.mjs +0 -56
  167. package/dist/components/shared/Table.cjs +0 -19
  168. package/dist/components/shared/Table.d.ts +0 -8
  169. package/dist/components/shared/Table.mjs +0 -17
  170. package/dist/components/shared/index.d.ts +0 -6
  171. package/dist/components/status/PackageStatusCard.d.ts +0 -10
  172. package/dist/components/status/StatusDisplay.cjs +0 -26
  173. package/dist/components/status/StatusDisplay.d.ts +0 -23
  174. package/dist/components/status/StatusDisplay.mjs +0 -24
  175. package/dist/components/status/StatusTreeNode.cjs +0 -40
  176. package/dist/components/status/StatusTreeNode.d.ts +0 -15
  177. package/dist/components/status/StatusTreeNode.mjs +0 -38
  178. package/dist/components/status/index.d.ts +0 -6
  179. package/dist/components/tree/AssetTreeNode.cjs +0 -54
  180. package/dist/components/tree/AssetTreeNode.d.ts +0 -12
  181. package/dist/components/tree/AssetTreeNode.mjs +0 -52
  182. package/dist/components/tree/TreeSelect.cjs +0 -129
  183. package/dist/components/tree/TreeSelect.d.ts +0 -12
  184. package/dist/components/tree/TreeSelect.mjs +0 -127
  185. package/dist/components/tree/index.d.ts +0 -4
  186. package/dist/core/assetStructure.cjs +0 -30
  187. package/dist/core/assetStructure.d.ts +0 -36
  188. package/dist/core/assetStructure.mjs +0 -27
  189. package/dist/core/cli.cjs +0 -106
  190. package/dist/core/cli.d.ts +0 -9
  191. package/dist/core/cli.mjs +0 -103
  192. package/dist/core/constants.cjs +0 -28
  193. package/dist/core/constants.d.ts +0 -94
  194. package/dist/core/constants.mjs +0 -21
  195. package/dist/core/filesystem.cjs +0 -98
  196. package/dist/core/filesystem.d.ts +0 -94
  197. package/dist/core/filesystem.mjs +0 -88
  198. package/dist/core/github.cjs +0 -115
  199. package/dist/core/github.d.ts +0 -61
  200. package/dist/core/github.mjs +0 -107
  201. package/dist/core/io.cjs +0 -46
  202. package/dist/core/io.d.ts +0 -40
  203. package/dist/core/io.mjs +0 -39
  204. package/dist/core/listOperations.cjs +0 -228
  205. package/dist/core/listOperations.d.ts +0 -43
  206. package/dist/core/listOperations.mjs +0 -205
  207. package/dist/core/localSource.cjs +0 -126
  208. package/dist/core/localSource.d.ts +0 -33
  209. package/dist/core/localSource.mjs +0 -120
  210. package/dist/core/migration.cjs +0 -201
  211. package/dist/core/migration.d.ts +0 -57
  212. package/dist/core/migration.mjs +0 -198
  213. package/dist/core/packageScanner.cjs +0 -360
  214. package/dist/core/packageScanner.d.ts +0 -22
  215. package/dist/core/packageScanner.mjs +0 -356
  216. package/dist/core/sync.cjs +0 -400
  217. package/dist/core/sync.d.ts +0 -21
  218. package/dist/core/sync.mjs +0 -397
  219. package/dist/core/syncMeta.cjs +0 -242
  220. package/dist/core/syncMeta.d.ts +0 -75
  221. package/dist/core/syncMeta.mjs +0 -229
  222. package/dist/utils/dependencies.cjs +0 -57
  223. package/dist/utils/dependencies.d.ts +0 -10
  224. package/dist/utils/dependencies.mjs +0 -34
  225. package/dist/utils/nameTransform.cjs +0 -13
  226. package/dist/utils/nameTransform.d.ts +0 -65
  227. package/dist/utils/nameTransform.mjs +0 -11
  228. package/dist/utils/package.cjs +0 -170
  229. package/dist/utils/package.d.ts +0 -105
  230. package/dist/utils/package.mjs +0 -157
  231. package/dist/utils/packageName.cjs +0 -24
  232. package/dist/utils/packageName.d.ts +0 -32
  233. package/dist/utils/packageName.mjs +0 -21
  234. package/dist/utils/paths.cjs +0 -18
  235. package/dist/utils/paths.d.ts +0 -55
  236. package/dist/utils/paths.mjs +0 -15
  237. package/dist/version.cjs +0 -5
  238. package/dist/version.d.ts +0 -5
  239. package/dist/version.mjs +0 -3
package/README.md CHANGED
@@ -1,640 +1,148 @@
1
1
  # @slats/claude-assets-sync
2
2
 
3
- CLI tool to sync Claude commands and skills from npm packages to your project's `.claude/` directory.
3
+ Engine + dispatcher CLI that lets any npm package ship its own Claude Code docs (skills, rules, commands) and inject them into a user's `.claude/` directory. Consumers declare `claude.assetPath` in `package.json` and the engine's `inject-claude-settings` bin handles the rest.
4
4
 
5
5
  ## Overview
6
6
 
7
- This tool allows npm package authors to distribute Claude Code commands and skills alongside their packages. When users install these packages, they can sync the Claude assets to their local `.claude/` directory for immediate use with Claude Code.
7
+ A consumer package declares `claude.assetPath` in `package.json` and runs `claude-build-hashes` during build to emit `dist/claude-hashes.json`. End users run `npx -p @slats/claude-assets-sync inject-claude-settings --package=<name>` and this engine resolves that single package's metadata via `createRequire`, compares the hash manifest against the target `.claude/`, and copies only what is out of date.
8
8
 
9
- ## Features
9
+ The library operates on exactly one consumer per invocation — the one named in `--package`. It never walks `node_modules` for siblings; it never enumerates workspaces.
10
10
 
11
- - **Multi-package sync**: Sync multiple packages in a single command
12
- - **Version tracking**: Automatically skip re-syncing if versions match
13
- - **Flat structure support**: Modern flat file organization with prefixed filenames
14
- - **Legacy migration**: Migrate from nested to flat directory structure
15
- - **Package management**: List, remove, and inspect synced packages
16
- - **Status monitoring**: Check sync status and available updates
17
- - **Dry-run mode**: Preview changes before applying them
18
- - **GitHub & npm integration**: Fetch from GitHub API and monitor npm registry
11
+ No GitHub fetch, no `.sync-meta.json`, no migrations the consumer's `dist/claude-hashes.json` is the single source of truth.
19
12
 
20
- ## Installation
13
+ ## Install
21
14
 
22
15
  ```bash
23
- # Using npx (recommended for one-time use)
24
- npx @slats/claude-assets-sync -p @canard/schema-form
25
-
26
- # Or install globally
27
- npm install -g @slats/claude-assets-sync
28
- ```
29
-
30
- ## Quick Start
31
-
32
- ```bash
33
- # Sync a single package
34
- npx @slats/claude-assets-sync -p @canard/schema-form
35
-
36
- # Sync multiple packages
37
- npx @slats/claude-assets-sync -p @canard/schema-form -p @lerx/promise-modal
38
-
39
- # See what would be synced
40
- npx @slats/claude-assets-sync -p @canard/schema-form --dry-run
41
-
42
- # Check sync status and available updates
43
- npx @slats/claude-assets-sync status
44
-
45
- # List all synced packages
46
- npx @slats/claude-assets-sync list
47
-
48
- # Remove a synced package
49
- npx @slats/claude-assets-sync remove -p @canard/schema-form
50
-
51
- # Migrate from legacy nested structure to flat structure
52
- npx @slats/claude-assets-sync migrate
16
+ npm install -D @slats/claude-assets-sync
17
+ # or
18
+ yarn add -D @slats/claude-assets-sync
53
19
  ```
54
20
 
55
- ## Commands
56
-
57
- ### sync (Default Command)
58
-
59
- Synchronize Claude assets from npm packages.
60
-
61
- ```bash
62
- npx @slats/claude-assets-sync [options] -p <package>
63
- ```
64
-
65
- **Options:**
66
-
67
- | Option | Description |
68
- |--------|-------------|
69
- | `-p, --package <name>` | Package name to sync (can be specified multiple times) |
70
- | `-f, --force` | Force sync even if version matches |
71
- | `--dry-run` | Preview changes without writing files |
72
- | `-l, --local` | Read packages from local workspace instead of node_modules |
73
- | `-r, --ref <ref>` | Git ref (branch, tag, or commit) to fetch from |
74
- | `--no-flat` | Use legacy nested directory structure instead of flat |
75
- | `--help` | Show help |
76
- | `--version` | Show version |
77
-
78
- **Examples:**
79
-
80
- ```bash
81
- # Sync with version check (default behavior)
82
- npx @slats/claude-assets-sync -p @canard/schema-form
83
-
84
- # Force sync, ignoring version check
85
- npx @slats/claude-assets-sync -p @canard/schema-form --force
86
-
87
- # Preview changes before syncing
88
- npx @slats/claude-assets-sync -p @canard/schema-form --dry-run
21
+ ## CLI Surface
89
22
 
90
- # Sync from a specific git ref
91
- npx @slats/claude-assets-sync -p @canard/schema-form -r main
92
-
93
- # Sync from local workspace
94
- npx @slats/claude-assets-sync -p @canard/schema-form --local
95
-
96
- # Use legacy nested structure
97
- npx @slats/claude-assets-sync -p @canard/schema-form --no-flat
98
23
  ```
99
-
100
- ### add
101
-
102
- Add a package with interactive file selection.
103
-
104
- ```bash
105
- npx @slats/claude-assets-sync add -p <package> [options]
24
+ inject-claude-settings --package=<name> [--scope=user|project] [--dry-run] [--force] [--root=<cwd>]
25
+ claude-build-hashes
106
26
  ```
107
27
 
108
- **Options:**
109
-
110
- | Option | Description |
111
- |--------|-------------|
112
- | `-p, --package <name>` | Package name to add (required) |
113
- | `-l, --local` | Read packages from local workspace instead of node_modules |
114
- | `-r, --ref <ref>` | Git ref (branch, tag, or commit) to fetch from |
115
-
116
- **Interactive Features:**
117
-
118
- When running in a TTY environment, the add command provides an interactive tree-select UI:
119
-
120
- - **↑/↓**: Navigate items
121
- - **Space**: Toggle file/directory selection
122
- - **→/←**: Expand/collapse directories
123
- - **Enter**: Confirm selection and sync
124
- - **a**: Select all files
125
- - **n**: Deselect all files
126
- - **q**: Cancel operation
127
-
128
- **Examples:**
28
+ ### End-user invocation
129
29
 
130
30
  ```bash
131
- # Add a package with interactive selection
132
- npx @slats/claude-assets-sync add -p @lerx/promise-modal
133
-
134
- # Add from local workspace
135
- npx @slats/claude-assets-sync add -p @lerx/promise-modal --local
31
+ # universal every PM (pnpm strict / yarn-berry PnP included)
32
+ npx -p @slats/claude-assets-sync inject-claude-settings --package=@canard/schema-form --scope=user
136
33
 
137
- # Add from specific git branch
138
- npx @slats/claude-assets-sync add -p @lerx/promise-modal --ref master
34
+ # simple — npm / yarn-classic only (relies on transitive bin hoist from the consumer's dependencies)
35
+ npx inject-claude-settings --package=@canard/schema-form --scope=user
139
36
  ```
140
37
 
141
- ### list
142
-
143
- List all synced packages with interactive tree view and edit mode.
144
-
145
- ```bash
146
- npx @slats/claude-assets-sync list [options]
147
- ```
148
-
149
- **Options:**
150
-
151
- | Option | Description |
152
- |--------|-------------|
153
- | `--json` | Output results as JSON |
154
-
155
- **Interactive Features (TTY mode):**
156
-
157
- When running in a TTY environment, the list command provides an interactive UI:
158
-
159
- **View Mode:**
160
- - Tree structure showing all synced packages and their files
161
- - **e**: Enter edit mode
162
- - **r**: Refresh view
163
- - **q**: Quit
164
-
165
- **Edit Mode:**
166
- - **d**: Mark file for deletion
167
- - **a**: Add new file to package
168
- - **Esc**: Exit edit mode
169
-
170
- **Examples:**
38
+ | Flag | Meaning |
39
+ |---|---|
40
+ | `--package <name>` | **Required.** Scoped npm name of a consumer that declares `claude.assetPath`. |
41
+ | `--scope=user` | `~/.claude` (applies globally). |
42
+ | `--scope=project` | Nearest ancestor `.claude` directory, or `<cwd>/.claude` if none found. |
43
+ | `--dry-run` | Print the copy / skip / warn plan, no writes. |
44
+ | `--force` | Overwrite diverged files & delete orphans (interactive confirm on TTY). |
45
+ | `--root <path>` | Override scope-resolution cwd. |
171
46
 
172
- ```bash
173
- # Interactive tree view (TTY mode)
174
- npx @slats/claude-assets-sync list
175
-
176
- # JSON output for scripting
177
- npx @slats/claude-assets-sync list --json
178
- ```
47
+ **Exit codes**: `0` success / up-to-date / dry-run, `1` runtime error, `2` user / configuration error (missing `--package`, missing `--scope` in non-TTY, unresolvable package, missing `claude.assetPath`).
179
48
 
180
- **Output (TTY mode):**
49
+ For `--scope=project` the target `.claude` directory is resolved by walking up from `process.cwd()` to the nearest existing `.claude` ancestor; the CLI logs `(auto-located)` when this happens.
181
50
 
182
- ```
183
- ┌─ Synced Packages ─────────────────────────────┐
184
- │ │
185
- │ ▼ @canard/schema-form@1.0.0 │
186
- │ ├─ commands/ │
187
- │ │ └─ @canard-schema-form-my-command.md │
188
- │ └─ skills/ │
189
- │ └─ @canard-schema-form-my-skill.md │
190
- │ │
191
- │ ▼ @lerx/promise-modal@0.5.0 │
192
- │ └─ skills/ │
193
- │ └─ @lerx-promise-modal-my-skill.md │
194
- │ │
195
- │ [e] Edit [r] Refresh [q] Quit │
196
- └───────────────────────────────────────────────┘
197
- ```
51
+ ## Consumer Integration (2 steps)
198
52
 
199
- **Output (JSON mode):**
53
+ ### 1. `package.json`
200
54
 
201
- ```json
202
- {
203
- "packages": [
204
- {
205
- "name": "@canard/schema-form",
206
- "version": "1.0.0",
207
- "syncedAt": "2025-02-05T10:30:00.000Z",
208
- "assets": 2,
209
- "types": { "commands": 1, "skills": 1 }
210
- }
211
- ]
212
- }
213
- ```
214
-
215
- ### remove
216
-
217
- Remove a synced package and its assets.
218
-
219
- ```bash
220
- npx @slats/claude-assets-sync remove [options] -p <package>
221
- ```
222
-
223
- **Options:**
224
-
225
- | Option | Description |
226
- |--------|-------------|
227
- | `-p, --package <name>` | Package name to remove (required) |
228
- | `-y, --yes` | Skip confirmation prompt |
229
- | `--dry-run` | Preview changes without removing files |
230
-
231
- **Examples:**
232
-
233
- ```bash
234
- # Remove a package with confirmation prompt
235
- npx @slats/claude-assets-sync remove -p @canard/schema-form
236
-
237
- # Remove without asking for confirmation
238
- npx @slats/claude-assets-sync remove -p @canard/schema-form --yes
239
-
240
- # Preview what would be removed
241
- npx @slats/claude-assets-sync remove -p @canard/schema-form --dry-run
242
- ```
243
-
244
- ### status
245
-
246
- Show sync status of all packages with visual UI and update checking.
247
-
248
- ```bash
249
- npx @slats/claude-assets-sync status [options]
250
- ```
251
-
252
- **Options:**
253
-
254
- | Option | Description |
255
- |--------|-------------|
256
- | `--no-remote` | Skip checking remote npm registry for updates |
257
-
258
- **Features:**
259
-
260
- - Visual box UI with color-coded status indicators (TTY mode)
261
- - Shows local vs synced version comparison
262
- - Checks npm registry for latest versions
263
- - Caches remote version checks (5-minute TTL)
264
- - Includes sync timestamp for each package
265
- - Summary statistics at the bottom
266
-
267
- **Status Indicators:**
268
-
269
- - **✓** (green): Up-to-date
270
- - **⚠** (yellow): Update available
271
- - **✗** (red): Error or missing
272
-
273
- **Examples:**
274
-
275
- ```bash
276
- # Check status with remote version checks (visual UI)
277
- npx @slats/claude-assets-sync status
278
-
279
- # Check status without checking npm registry
280
- npx @slats/claude-assets-sync status --no-remote
281
- ```
282
-
283
- **Output (TTY mode):**
284
-
285
- ```
286
- ┌─ Package Status ──────────────────────────────┐
287
- │ │
288
- │ ✓ @canard/schema-form │
289
- │ Local: 1.0.0 │
290
- │ Synced: 1.0.0 │
291
- │ Status: Up to date │
292
- │ Updated: 2/5/2025, 10:30 AM │
293
- │ Assets: 2 files │
294
- │ │
295
- │ ⚠ @lerx/promise-modal │
296
- │ Local: 0.6.0 │
297
- │ Synced: 0.5.0 │
298
- │ Status: Outdated │
299
- │ Updated: 2/5/2025, 10:30 AM │
300
- │ Assets: 1 files │
301
- │ │
302
- ├─ Summary ────────────────────────────────────┤
303
- │ Total: 2 packages │
304
- │ ✓ Up-to-date: 1 ⚠ Outdated: 1 │
305
- └───────────────────────────────────────────────┘
306
- ```
307
-
308
- ### migrate
309
-
310
- Migrate synced packages from legacy nested structure to flat structure.
311
-
312
- ```bash
313
- npx @slats/claude-assets-sync migrate [options]
314
- ```
315
-
316
- **Options:**
317
-
318
- | Option | Description |
319
- |--------|-------------|
320
- | `--dry-run` | Preview migration without making changes |
321
-
322
- **Features:**
323
-
324
- - Converts nested directory structure to flat file naming
325
- - Preserves all package metadata
326
- - Creates backup of original structure
327
- - Can be run multiple times safely
328
- - Includes comprehensive dry-run preview
329
-
330
- **Examples:**
331
-
332
- ```bash
333
- # Preview migration changes
334
- npx @slats/claude-assets-sync migrate --dry-run
335
-
336
- # Perform migration
337
- npx @slats/claude-assets-sync migrate
338
- ```
339
-
340
- ## Directory Structures
341
-
342
- ### Flat Structure (Default, Modern)
343
-
344
- The default flat structure uses prefixed filenames in shared directories:
345
-
346
- ```
347
- your-project/
348
- └── .claude/
349
- ├── commands/
350
- │ ├── @canard-schema-form-my-command.md
351
- │ └── @lerx-promise-modal-another-command.md
352
- └── skills/
353
- ├── @canard-schema-form-my-skill.md
354
- └── @lerx-promise-modal-another-skill.md
355
- ```
356
-
357
- **Benefits:**
358
- - Cleaner directory structure
359
- - Easier to share commands across packages
360
- - Single .sync-meta.json per asset type
361
- - Better scalability with many packages
362
-
363
- ### Nested Structure (Legacy)
364
-
365
- The legacy nested structure organizes by package:
366
-
367
- ```
368
- your-project/
369
- └── .claude/
370
- ├── commands/
371
- │ └── @canard/
372
- │ └── schema-form/
373
- │ ├── my-command.md
374
- │ └── .sync-meta.json
375
- └── skills/
376
- └── @lerx/
377
- └── promise-modal/
378
- ├── my-skill.md
379
- └── .sync-meta.json
380
- ```
381
-
382
- **Use case:** Legacy projects or when per-package organization is preferred
383
-
384
- ## Version Management
385
-
386
- The tool tracks synced versions to avoid unnecessary re-syncing. A unified `.sync-meta.json` file stores metadata for all packages:
387
-
388
- ```json
389
- {
390
- "version": "0.0.1",
391
- "syncedAt": "2025-02-05T10:30:00.000Z",
392
- "packages": {
393
- "@canard-schema-form": {
394
- "originalName": "@canard/schema-form",
395
- "version": "1.0.0",
396
- "files": {
397
- "commands": [
398
- { "original": "my-command.md", "transformed": "@canard-schema-form-my-command.md" }
399
- ],
400
- "skills": [
401
- { "original": "my-skill.md", "transformed": "@canard-schema-form-my-skill.md" }
402
- ]
403
- }
404
- }
405
- }
406
- }
407
- ```
408
-
409
- **Features:**
410
-
411
- - Sync is automatically skipped if package version hasn't changed
412
- - Use `--force` to override version checking and re-sync
413
- - Each sync updates the `syncedAt` timestamp
414
- - Full file mapping for cleanup and migration
415
-
416
- ## For Package Authors
417
-
418
- To make your package compatible with `claude-assets-sync`, add a `claude` field to your `package.json`:
419
-
420
- ```json
55
+ ```jsonc
421
56
  {
422
57
  "name": "@your-scope/your-package",
423
- "version": "1.0.0",
424
- "repository": {
425
- "type": "git",
426
- "url": "https://github.com/your-org/your-repo.git",
427
- "directory": "packages/your-package"
58
+ "scripts": {
59
+ "build": "… && yarn build:hashes",
60
+ "build:hashes": "claude-build-hashes"
428
61
  },
429
- "claude": {
430
- "assetPath": "docs/claude"
431
- }
432
- }
433
- ```
434
-
435
- ### Package Structure
436
-
437
- Your package should have the following structure:
438
-
439
- ```
440
- your-package/
441
- ├── docs/
442
- │ └── claude/
443
- │ ├── commands/
444
- │ │ └── your-command.md
445
- │ └── skills/
446
- │ └── your-skill.md
447
- └── package.json
448
- ```
449
-
450
- ### Asset Guidelines
451
-
452
- - **Commands and skills**: Must be Markdown files (`.md`)
453
- - **File format**: Use standard Claude Code command/skill format
454
- - **Naming**: Use descriptive, lowercase filenames with hyphens (e.g., `my-command.md`)
455
- - **No modification**: Files are synced as-is without transformation
456
- - **Repository requirement**: Must have valid `repository.type` and `repository.url` in package.json
457
-
458
- ### Configuration
459
-
460
- The `claude.assetPath` in your package.json should point to the directory containing your `commands/` and `skills/` subdirectories:
461
-
462
- ```json
463
- {
464
- "claude": {
465
- "assetPath": "docs/claude" // Path relative to package root
466
- }
62
+ "dependencies": {
63
+ "@slats/claude-assets-sync": "workspace:^"
64
+ },
65
+ "files": ["dist", "docs", "README.md"],
66
+ "claude": { "assetPath": "docs/claude" }
467
67
  }
468
68
  ```
469
69
 
470
- ## Environment Variables
471
-
472
- | Variable | Description | Default |
473
- |----------|-------------|---------|
474
- | `GITHUB_TOKEN` | GitHub personal access token for higher API rate limits | (unauthenticated) |
475
- | `VERBOSE` | Enable debug logging (set to any value) | (disabled) |
476
-
477
- ## Rate Limits
70
+ - `@slats/claude-assets-sync` MUST be in `dependencies`, not `devDependencies` — see Rationale below.
71
+ - Do **not** add any `bin` field. The engine is the sole CLI surface; per-consumer bins would collide under `node_modules/.bin/`.
72
+ - Do **not** expose `./bin/*` or `./docs/*` in `exports`. That would let consumer bundlers pull CLI code or the asset tree into app bundles.
73
+ - Do **not** create a `bin/` or `scripts/` directory in the consumer.
478
74
 
479
- - **Without token**: 60 requests/hour (GitHub API limit)
480
- - **With token**: 5,000 requests/hour
481
-
482
- For most use cases, the unauthenticated limit is sufficient. If syncing many packages, set a GitHub token:
75
+ ### 2. Build
483
76
 
484
77
  ```bash
485
- export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
486
- npx @slats/claude-assets-sync -p @package1 -p @package2 -p @package3
78
+ yarn build
79
+ # rolls up the library, emits types, then `claude-build-hashes` hashes every
80
+ # file under `claude.assetPath` and writes dist/claude-hashes.json
487
81
  ```
488
82
 
489
- ## Workflow Examples
490
-
491
- ### Initial Setup
492
-
493
- ```bash
494
- # Sync all packages from your project
495
- npx @slats/claude-assets-sync \
496
- -p @canard/schema-form \
497
- -p @lerx/promise-modal \
498
- -p @winglet/react-utils
499
-
500
- # Verify they're synced
501
- npx @slats/claude-assets-sync list
83
+ Ship the resulting `dist/` (including `claude-hashes.json`) alongside `docs/` when you publish.
502
84
 
503
- # Check for any available updates
504
- npx @slats/claude-assets-sync status
505
- ```
85
+ ### Rationale: `dependencies`, not `devDependencies`
506
86
 
507
- ### Regular Maintenance
87
+ - The monorepo build chain needs `.bin/claude-build-hashes` resolved, which requires the engine as a direct dep.
88
+ - For end users on npm / yarn-classic, listing the engine in `dependencies` makes `inject-claude-settings` transitively hoisted into `node_modules/.bin/`, enabling the short invocation `npx inject-claude-settings --package=<THIS>`. Pnpm strict users do not get the transitive hoist and must use the universal form `npx -p @slats/claude-assets-sync inject-claude-settings --package=<THIS>`.
89
+ - Bundle isolation is enforced by the import graph (`src/**` in the consumer never references the engine), not by dependency-type.
508
90
 
509
- ```bash
510
- # Check which packages have updates available
511
- npx @slats/claude-assets-sync status
91
+ ## Authoring `docs/claude/`
512
92
 
513
- # Update a specific package to latest version
514
- npx @slats/claude-assets-sync -p @canard/schema-form --force
93
+ Any tree works, but the recommended layout matches Claude Code conventions:
515
94
 
516
- # Update all packages from a specific branch
517
- npx @slats/claude-assets-sync \
518
- -p @canard/schema-form \
519
- -p @lerx/promise-modal \
520
- --force -r develop
521
95
  ```
522
-
523
- ### Cleanup
524
-
525
- ```bash
526
- # Check what you'll remove before doing it
527
- npx @slats/claude-assets-sync remove -p @old-package --dry-run
528
-
529
- # Remove a package
530
- npx @slats/claude-assets-sync remove -p @old-package --yes
531
-
532
- # List remaining packages
533
- npx @slats/claude-assets-sync list
96
+ docs/claude/
97
+ ├── skills/
98
+ │ └── <skill-name>/
99
+ │ ├── SKILL.md
100
+ │ └── knowledge/...
101
+ ├── rules/...
102
+ └── commands/...
534
103
  ```
535
104
 
536
- ### CI/CD Integration
105
+ Every file under the asset root is hashed and tracked in `dist/claude-hashes.json`.
537
106
 
538
- ```bash
539
- #!/bin/bash
540
- # Script to sync all team packages
541
- PACKAGES=(
542
- "@canard/schema-form"
543
- "@lerx/promise-modal"
544
- "@winglet/react-utils"
545
- )
546
-
547
- for pkg in "${PACKAGES[@]}"; do
548
- npx @slats/claude-assets-sync -p "$pkg" --force
549
- done
550
-
551
- # Verify sync
552
- npx @slats/claude-assets-sync list
553
- ```
107
+ ## Hash-Based Sync Strategy (Option A)
554
108
 
555
- ## Troubleshooting
109
+ - `dist/claude-hashes.json` (schema v1) is the sole source of truth.
110
+ - Per-file SHA-256 comparison:
111
+ - **missing locally** → copy
112
+ - **hash equal** → skip
113
+ - **hash differs** → warn + require `--force` (user edit vs. source update is indistinguishable by design)
114
+ - **file is outside the manifest but under a managed prefix (`skills/<name>/`)** → orphan; requires `--force` to delete
556
115
 
557
- ### "Package is not synced"
116
+ - `--force` on TTY opens an interactive confirm via `@inquirer/prompts.confirm`, listing up to 3 diverged/orphan paths.
117
+ - `--force` on non-TTY prints the divergent list to stderr and proceeds.
558
118
 
559
- The specified package hasn't been synced yet. List available packages:
119
+ ## Architectural Invariants
560
120
 
561
- ```bash
562
- npx @slats/claude-assets-sync list
563
- ```
121
+ - `src/core/**` never reads `package.json` or walks the filesystem. Only the `bin/` layer (and `src/commands/runCli/utils/resolvePackage.ts`, invoked from that dispatcher) is allowed to resolve a single explicitly-named target via `createRequire().resolve('${name}/package.json')`. Cross-package discovery (`--all`, workspace scan) is not supported.
122
+ - Prompts go through `@inquirer/prompts` only. No ink, no React.
123
+ - The engine assumes one consumer per invocation. That is the stable contract — extensions require explicit re-architecture.
564
124
 
565
- Then sync it:
125
+ ## Programmatic API
566
126
 
567
- ```bash
568
- npx @slats/claude-assets-sync -p @your-package
127
+ ```ts
128
+ import {
129
+ runCli,
130
+ injectDocs,
131
+ readHashManifest,
132
+ resolveScope,
133
+ isInteractive,
134
+ isValidScope,
135
+ computeNamespacePrefixes,
136
+ } from '@slats/claude-assets-sync';
569
137
  ```
570
138
 
571
- ### "Rate limit exceeded"
572
-
573
- You've hit GitHub's API rate limit (60 requests/hour without authentication). Solutions:
139
+ See `src/index.ts` and `src/DETAIL.md` for the full export surface.
574
140
 
575
- 1. **Set GitHub token:** `export GITHUB_TOKEN=ghp_xxxxxxxxxxxx`
576
- 2. **Wait 1 hour** for rate limit to reset
577
- 3. **Use `--local` flag** if packages are in your local workspace
141
+ ## Additional Docs
578
142
 
579
- ```bash
580
- GITHUB_TOKEN=ghp_xxxxxxxxxxxx npx @slats/claude-assets-sync -p @package
581
- ```
582
-
583
- ### "Repository information not found"
584
-
585
- The package's `package.json` is missing required repository configuration:
586
-
587
- ```json
588
- {
589
- "repository": {
590
- "type": "git",
591
- "url": "https://github.com/your-org/your-repo.git"
592
- }
593
- }
594
- ```
595
-
596
- ### Files not appearing in `.claude/`
597
-
598
- 1. **Check sync status:** `npx @slats/claude-assets-sync list`
599
- 2. **Verify package has assets:** Check that the package has a `docs/claude/commands` or `docs/claude/skills` directory
600
- 3. **Use dry-run to debug:** `npx @slats/claude-assets-sync -p @package --dry-run`
601
-
602
- ### Migrating from older versions
603
-
604
- If you have a legacy nested structure:
605
-
606
- ```bash
607
- # Preview migration changes
608
- npx @slats/claude-assets-sync migrate --dry-run
609
-
610
- # Perform migration
611
- npx @slats/claude-assets-sync migrate
612
- ```
613
-
614
- ## Architecture
615
-
616
- ### Command Architecture
617
-
618
- The tool uses a modular command structure:
619
-
620
- - **sync**: Core synchronization logic with GitHub API integration
621
- - **list**: Query unified metadata and display package information
622
- - **remove**: Safe package removal with confirmation prompts
623
- - **status**: Version checking with npm registry integration
624
- - **migrate**: Structure migration with dry-run support
625
-
626
- ### Data Flow
627
-
628
- ```
629
- 1. Read package.json → Extract claude.assetPath
630
- 2. Parse repository URL → GitHub owner/repo
631
- 3. Check version → Skip if unchanged (unless --force)
632
- 4. Fetch files → GitHub API (commands/ and skills/)
633
- 5. Transform paths → Apply naming conventions
634
- 6. Write files → .claude/{type}/{prefixed-name}.md (flat)
635
- 7. Update metadata → Unified .sync-meta.json
636
- ```
143
+ - `docs/consumer-integration.md` — complete consumer checklist (package.json patches, verification steps, end-user install topologies)
144
+ - `docs/bundle-size-decision.md` why `@inquirer/prompts` over ink
637
145
 
638
146
  ## License
639
147
 
640
- MIT License - see [LICENSE](./LICENSE) for details.
148
+ MIT see [LICENSE](./LICENSE).