opkg 0.6.1 β†’ 0.7.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 (487) hide show
  1. package/README.md +109 -186
  2. package/assets/openpackage_ascii_dark.png +0 -0
  3. package/assets/openpackage_ascii_light.png +0 -0
  4. package/dist/commands/add.js +34 -10
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/commands/apply.js +16 -0
  7. package/dist/commands/apply.js.map +1 -0
  8. package/dist/commands/delete.js +1 -1
  9. package/dist/commands/delete.js.map +1 -1
  10. package/dist/commands/install.js +177 -8
  11. package/dist/commands/install.js.map +1 -1
  12. package/dist/commands/list.js +2 -2
  13. package/dist/commands/list.js.map +1 -1
  14. package/dist/commands/login.js +1 -1
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/logout.js +1 -1
  17. package/dist/commands/logout.js.map +1 -1
  18. package/dist/commands/new.js +125 -0
  19. package/dist/commands/new.js.map +1 -0
  20. package/dist/commands/pack.js +7 -13
  21. package/dist/commands/pack.js.map +1 -1
  22. package/dist/commands/pull.js +1 -1
  23. package/dist/commands/pull.js.map +1 -1
  24. package/dist/commands/push.js +1 -1
  25. package/dist/commands/push.js.map +1 -1
  26. package/dist/commands/remove.js +63 -0
  27. package/dist/commands/remove.js.map +1 -0
  28. package/dist/commands/save.js +11 -17
  29. package/dist/commands/save.js.map +1 -1
  30. package/dist/commands/set.js +33 -0
  31. package/dist/commands/set.js.map +1 -0
  32. package/dist/commands/show.js +16 -94
  33. package/dist/commands/show.js.map +1 -1
  34. package/dist/commands/status.js +26 -701
  35. package/dist/commands/status.js.map +1 -1
  36. package/dist/commands/uninstall.js +14 -427
  37. package/dist/commands/uninstall.js.map +1 -1
  38. package/dist/constants/index.js +72 -16
  39. package/dist/constants/index.js.map +1 -1
  40. package/dist/core/add/add-conflict-handler.js +1 -8
  41. package/dist/core/add/add-conflict-handler.js.map +1 -1
  42. package/dist/core/add/add-pipeline.js +12 -10
  43. package/dist/core/add/add-pipeline.js.map +1 -1
  44. package/dist/core/add/add-to-source-pipeline.js +123 -0
  45. package/dist/core/add/add-to-source-pipeline.js.map +1 -0
  46. package/dist/core/add/package-index-updater.js +77 -78
  47. package/dist/core/add/package-index-updater.js.map +1 -1
  48. package/dist/core/add/platform-path-transformer.js +6 -4
  49. package/dist/core/add/platform-path-transformer.js.map +1 -1
  50. package/dist/core/add/source-collector.js +2 -3
  51. package/dist/core/add/source-collector.js.map +1 -1
  52. package/dist/core/apply/apply-pipeline.js +110 -0
  53. package/dist/core/apply/apply-pipeline.js.map +1 -0
  54. package/dist/core/dependency-resolver.js +263 -21
  55. package/dist/core/dependency-resolver.js.map +1 -1
  56. package/dist/core/discovery/file-discovery.js +1 -2
  57. package/dist/core/discovery/file-discovery.js.map +1 -1
  58. package/dist/core/discovery/platform-files-discovery.js +33 -18
  59. package/dist/core/discovery/platform-files-discovery.js.map +1 -1
  60. package/dist/core/flows/flow-executor.js +974 -0
  61. package/dist/core/flows/flow-executor.js.map +1 -0
  62. package/dist/core/flows/flow-inverter.js +442 -0
  63. package/dist/core/flows/flow-inverter.js.map +1 -0
  64. package/dist/core/flows/flow-key-extractor.js +101 -0
  65. package/dist/core/flows/flow-key-extractor.js.map +1 -0
  66. package/dist/core/flows/flow-key-mapper.js +382 -0
  67. package/dist/core/flows/flow-key-mapper.js.map +1 -0
  68. package/dist/core/flows/flow-transforms.js +632 -0
  69. package/dist/core/flows/flow-transforms.js.map +1 -0
  70. package/dist/core/flows/map-pipeline/context.js +73 -0
  71. package/dist/core/flows/map-pipeline/context.js.map +1 -0
  72. package/dist/core/flows/map-pipeline/index.js +156 -0
  73. package/dist/core/flows/map-pipeline/index.js.map +1 -0
  74. package/dist/core/flows/map-pipeline/operations/copy.js +104 -0
  75. package/dist/core/flows/map-pipeline/operations/copy.js.map +1 -0
  76. package/dist/core/flows/map-pipeline/operations/pipe.js +70 -0
  77. package/dist/core/flows/map-pipeline/operations/pipe.js.map +1 -0
  78. package/dist/core/flows/map-pipeline/operations/rename.js +102 -0
  79. package/dist/core/flows/map-pipeline/operations/rename.js.map +1 -0
  80. package/dist/core/flows/map-pipeline/operations/set.js +50 -0
  81. package/dist/core/flows/map-pipeline/operations/set.js.map +1 -0
  82. package/dist/core/flows/map-pipeline/operations/switch.js +79 -0
  83. package/dist/core/flows/map-pipeline/operations/switch.js.map +1 -0
  84. package/dist/core/flows/map-pipeline/operations/transform.js +543 -0
  85. package/dist/core/flows/map-pipeline/operations/transform.js.map +1 -0
  86. package/dist/core/flows/map-pipeline/operations/unset.js +65 -0
  87. package/dist/core/flows/map-pipeline/operations/unset.js.map +1 -0
  88. package/dist/core/flows/map-pipeline/types.js +8 -0
  89. package/dist/core/flows/map-pipeline/types.js.map +1 -0
  90. package/dist/core/flows/map-pipeline/utils.js +278 -0
  91. package/dist/core/flows/map-pipeline/utils.js.map +1 -0
  92. package/dist/core/flows/platform-converter.js +328 -0
  93. package/dist/core/flows/platform-converter.js.map +1 -0
  94. package/dist/core/flows/source-resolver.js +192 -0
  95. package/dist/core/flows/source-resolver.js.map +1 -0
  96. package/dist/core/flows/toml-domain-transforms.js +23 -0
  97. package/dist/core/flows/toml-domain-transforms.js.map +1 -0
  98. package/dist/core/install/bulk-install-pipeline.js +68 -7
  99. package/dist/core/install/bulk-install-pipeline.js.map +1 -1
  100. package/dist/core/install/canonical-plan.js +3 -3
  101. package/dist/core/install/canonical-plan.js.map +1 -1
  102. package/dist/core/install/dry-run.js +3 -3
  103. package/dist/core/install/dry-run.js.map +1 -1
  104. package/dist/core/install/flow-based-installer.js +1158 -0
  105. package/dist/core/install/flow-based-installer.js.map +1 -0
  106. package/dist/core/install/flow-workspace-tracker.js +111 -0
  107. package/dist/core/install/flow-workspace-tracker.js.map +1 -0
  108. package/dist/core/install/format-detector.js +228 -0
  109. package/dist/core/install/format-detector.js.map +1 -0
  110. package/dist/core/install/git-package-loader.js +20 -0
  111. package/dist/core/install/git-package-loader.js.map +1 -0
  112. package/dist/core/install/install-errors.js +1 -1
  113. package/dist/core/install/install-errors.js.map +1 -1
  114. package/dist/core/install/install-flow.js +34 -14
  115. package/dist/core/install/install-flow.js.map +1 -1
  116. package/dist/core/install/install-pipeline.js +52 -17
  117. package/dist/core/install/install-pipeline.js.map +1 -1
  118. package/dist/core/install/install-reporting.js +26 -8
  119. package/dist/core/install/install-reporting.js.map +1 -1
  120. package/dist/core/install/local-source-resolution.js +103 -0
  121. package/dist/core/install/local-source-resolution.js.map +1 -0
  122. package/dist/core/install/marketplace-handler.js +221 -0
  123. package/dist/core/install/marketplace-handler.js.map +1 -0
  124. package/dist/core/install/path-install-pipeline.js +241 -0
  125. package/dist/core/install/path-install-pipeline.js.map +1 -0
  126. package/dist/core/install/path-package-loader.js +116 -0
  127. package/dist/core/install/path-package-loader.js.map +1 -0
  128. package/dist/core/install/plugin-detector.js +72 -0
  129. package/dist/core/install/plugin-detector.js.map +1 -0
  130. package/dist/core/install/plugin-to-universal-converter.js +218 -0
  131. package/dist/core/install/plugin-to-universal-converter.js.map +1 -0
  132. package/dist/core/install/plugin-transformer.js +191 -0
  133. package/dist/core/install/plugin-transformer.js.map +1 -0
  134. package/dist/core/install/version-selection.js +1 -1
  135. package/dist/core/install/version-selection.js.map +1 -1
  136. package/dist/core/openpackage.js +40 -22
  137. package/dist/core/openpackage.js.map +1 -1
  138. package/dist/core/pack/pack-output.js +62 -0
  139. package/dist/core/pack/pack-output.js.map +1 -0
  140. package/dist/core/pack/pack-pipeline.js +186 -0
  141. package/dist/core/pack/pack-pipeline.js.map +1 -0
  142. package/dist/core/package-context.js +45 -70
  143. package/dist/core/package-context.js.map +1 -1
  144. package/dist/core/package-creation.js +203 -0
  145. package/dist/core/package-creation.js.map +1 -0
  146. package/dist/core/package.js +20 -6
  147. package/dist/core/package.js.map +1 -1
  148. package/dist/core/platforms.js +665 -209
  149. package/dist/core/platforms.js.map +1 -1
  150. package/dist/core/push/push-context.js +1 -1
  151. package/dist/core/push/push-context.js.map +1 -1
  152. package/dist/core/push/push-upload.js +2 -2
  153. package/dist/core/push/push-upload.js.map +1 -1
  154. package/dist/core/registry.js +6 -6
  155. package/dist/core/registry.js.map +1 -1
  156. package/dist/core/remote-pull.js +2 -2
  157. package/dist/core/remote-pull.js.map +1 -1
  158. package/dist/core/remove/removal-collector.js +52 -0
  159. package/dist/core/remove/removal-collector.js.map +1 -0
  160. package/dist/core/remove/removal-confirmation.js +39 -0
  161. package/dist/core/remove/removal-confirmation.js.map +1 -0
  162. package/dist/core/remove/remove-from-source-pipeline.js +173 -0
  163. package/dist/core/remove/remove-from-source-pipeline.js.map +1 -0
  164. package/dist/core/save/constants.js +3 -3
  165. package/dist/core/save/constants.js.map +1 -1
  166. package/dist/core/save/flow-based-saver.js +270 -0
  167. package/dist/core/save/flow-based-saver.js.map +1 -0
  168. package/dist/core/save/name-resolution.js +1 -1
  169. package/dist/core/save/name-resolution.js.map +1 -1
  170. package/dist/core/save/package-yml-generator.js +4 -5
  171. package/dist/core/save/package-yml-generator.js.map +1 -1
  172. package/dist/core/save/save-candidate-builder.js +215 -0
  173. package/dist/core/save/save-candidate-builder.js.map +1 -0
  174. package/dist/core/save/save-candidate-loader.js +12 -11
  175. package/dist/core/save/save-candidate-loader.js.map +1 -1
  176. package/dist/core/save/save-conflict-analyzer.js +150 -0
  177. package/dist/core/save/save-conflict-analyzer.js.map +1 -0
  178. package/dist/core/save/save-conflict-resolution.js +28 -14
  179. package/dist/core/save/save-conflict-resolution.js.map +1 -1
  180. package/dist/core/save/save-conflict-resolver.js +31 -275
  181. package/dist/core/save/save-conflict-resolver.js.map +1 -1
  182. package/dist/core/save/save-group-builder.js +52 -0
  183. package/dist/core/save/save-group-builder.js.map +1 -0
  184. package/dist/core/save/save-interactive-resolver.js +190 -0
  185. package/dist/core/save/save-interactive-resolver.js.map +1 -0
  186. package/dist/core/save/save-pipeline.js +58 -34
  187. package/dist/core/save/save-pipeline.js.map +1 -1
  188. package/dist/core/save/save-platform-handler.js +53 -0
  189. package/dist/core/save/save-platform-handler.js.map +1 -0
  190. package/dist/core/save/save-resolution-executor.js +145 -0
  191. package/dist/core/save/save-resolution-executor.js.map +1 -0
  192. package/dist/core/save/save-result-reporter.js +167 -0
  193. package/dist/core/save/save-result-reporter.js.map +1 -0
  194. package/dist/core/save/save-to-source-pipeline.js +154 -0
  195. package/dist/core/save/save-to-source-pipeline.js.map +1 -0
  196. package/dist/core/save/save-versioning.js +4 -4
  197. package/dist/core/save/save-versioning.js.map +1 -1
  198. package/dist/core/save/save-write-coordinator.js +204 -0
  199. package/dist/core/save/save-write-coordinator.js.map +1 -0
  200. package/dist/core/save/save-yml-resolution.js +28 -216
  201. package/dist/core/save/save-yml-resolution.js.map +1 -1
  202. package/dist/core/save/workspace-rename.js +7 -8
  203. package/dist/core/save/workspace-rename.js.map +1 -1
  204. package/dist/core/set/set-output.js +72 -0
  205. package/dist/core/set/set-output.js.map +1 -0
  206. package/dist/core/set/set-pipeline.js +361 -0
  207. package/dist/core/set/set-pipeline.js.map +1 -0
  208. package/dist/core/set/set-types.js +5 -0
  209. package/dist/core/set/set-types.js.map +1 -0
  210. package/dist/core/show/package-resolver.js +257 -0
  211. package/dist/core/show/package-resolver.js.map +1 -0
  212. package/dist/core/show/scope-discovery.js +165 -0
  213. package/dist/core/show/scope-discovery.js.map +1 -0
  214. package/dist/core/show/show-output.js +168 -0
  215. package/dist/core/show/show-output.js.map +1 -0
  216. package/dist/core/show/show-pipeline.js +113 -0
  217. package/dist/core/show/show-pipeline.js.map +1 -0
  218. package/dist/core/show/show-types.js +5 -0
  219. package/dist/core/show/show-types.js.map +1 -0
  220. package/dist/core/source-resolution/dependency-graph.js +104 -0
  221. package/dist/core/source-resolution/dependency-graph.js.map +1 -0
  222. package/dist/core/source-resolution/resolve-mutable-source.js +109 -0
  223. package/dist/core/source-resolution/resolve-mutable-source.js.map +1 -0
  224. package/dist/core/source-resolution/resolve-package-source.js +29 -0
  225. package/dist/core/source-resolution/resolve-package-source.js.map +1 -0
  226. package/dist/core/source-resolution/resolve-registry-version.js +35 -0
  227. package/dist/core/source-resolution/resolve-registry-version.js.map +1 -0
  228. package/dist/core/source-resolution/types.js.map +1 -0
  229. package/dist/core/status/status-file-discovery.js +23 -12
  230. package/dist/core/status/status-file-discovery.js.map +1 -1
  231. package/dist/core/status/status-pipeline.js +134 -0
  232. package/dist/core/status/status-pipeline.js.map +1 -0
  233. package/dist/core/sync/platform-sync-summary.js +27 -0
  234. package/dist/core/sync/platform-sync-summary.js.map +1 -0
  235. package/dist/core/uninstall/flow-aware-uninstaller.js +189 -0
  236. package/dist/core/uninstall/flow-aware-uninstaller.js.map +1 -0
  237. package/dist/core/uninstall/uninstall-file-discovery.js +11 -6
  238. package/dist/core/uninstall/uninstall-file-discovery.js.map +1 -1
  239. package/dist/core/uninstall/uninstall-pipeline.js +141 -0
  240. package/dist/core/uninstall/uninstall-pipeline.js.map +1 -0
  241. package/dist/core/universal-patterns.js +64 -0
  242. package/dist/core/universal-patterns.js.map +1 -0
  243. package/dist/index.js +99 -6
  244. package/dist/index.js.map +1 -1
  245. package/dist/types/flows.js +8 -0
  246. package/dist/types/flows.js.map +1 -0
  247. package/dist/types/index.js +3 -0
  248. package/dist/types/index.js.map +1 -1
  249. package/dist/types/platform-flows.js +8 -0
  250. package/dist/types/platform-flows.js.map +1 -0
  251. package/dist/types/workspace-index.js +6 -0
  252. package/dist/types/workspace-index.js.map +1 -0
  253. package/dist/utils/custom-path-resolution.js +160 -0
  254. package/dist/utils/custom-path-resolution.js.map +1 -0
  255. package/dist/utils/dependency-coverage.js +1 -1
  256. package/dist/utils/dependency-coverage.js.map +1 -1
  257. package/dist/utils/file-processing.js +1 -1
  258. package/dist/utils/flow-index-installer.js +209 -0
  259. package/dist/utils/flow-index-installer.js.map +1 -0
  260. package/dist/utils/formatters.js +47 -1
  261. package/dist/utils/formatters.js.map +1 -1
  262. package/dist/utils/fs.js +17 -0
  263. package/dist/utils/fs.js.map +1 -1
  264. package/dist/utils/git-clone-registry.js +88 -0
  265. package/dist/utils/git-clone-registry.js.map +1 -0
  266. package/dist/utils/git-clone.js +69 -0
  267. package/dist/utils/git-clone.js.map +1 -0
  268. package/dist/utils/git-spec.js +96 -0
  269. package/dist/utils/git-spec.js.map +1 -0
  270. package/dist/utils/http-client.js +7 -0
  271. package/dist/utils/http-client.js.map +1 -1
  272. package/dist/utils/index-based-installer.js +356 -163
  273. package/dist/utils/index-based-installer.js.map +1 -1
  274. package/dist/utils/install-conflict-handler.js +2 -2
  275. package/dist/utils/install-conflict-handler.js.map +1 -1
  276. package/dist/utils/install-file-discovery.js +18 -13
  277. package/dist/utils/install-file-discovery.js.map +1 -1
  278. package/dist/utils/install-helpers.js +43 -20
  279. package/dist/utils/install-helpers.js.map +1 -1
  280. package/dist/utils/jsonc.js +23 -1
  281. package/dist/utils/jsonc.js.map +1 -1
  282. package/dist/utils/manifest-paths.js +1 -1
  283. package/dist/utils/manifest-paths.js.map +1 -1
  284. package/dist/utils/markdown-frontmatter.js +46 -0
  285. package/dist/utils/markdown-frontmatter.js.map +1 -1
  286. package/dist/utils/package-copy.js +5 -103
  287. package/dist/utils/package-copy.js.map +1 -1
  288. package/dist/utils/package-filters.js +9 -105
  289. package/dist/utils/package-filters.js.map +1 -1
  290. package/dist/utils/package-index-yml.js +27 -6
  291. package/dist/utils/package-index-yml.js.map +1 -1
  292. package/dist/utils/package-input.js +98 -0
  293. package/dist/utils/package-input.js.map +1 -0
  294. package/dist/utils/package-management.js +80 -28
  295. package/dist/utils/package-management.js.map +1 -1
  296. package/dist/utils/package-name-resolution.js +327 -0
  297. package/dist/utils/package-name-resolution.js.map +1 -0
  298. package/dist/utils/package-name.js +18 -16
  299. package/dist/utils/package-name.js.map +1 -1
  300. package/dist/utils/package-versioning.js +2 -33
  301. package/dist/utils/package-versioning.js.map +1 -1
  302. package/dist/utils/package-yml.js +19 -28
  303. package/dist/utils/package-yml.js.map +1 -1
  304. package/dist/utils/path-resolution.js +102 -0
  305. package/dist/utils/path-resolution.js.map +1 -0
  306. package/dist/utils/paths.js +6 -6
  307. package/dist/utils/paths.js.map +1 -1
  308. package/dist/utils/platform-file.js +36 -24
  309. package/dist/utils/platform-file.js.map +1 -1
  310. package/dist/utils/platform-mapper.js +222 -68
  311. package/dist/utils/platform-mapper.js.map +1 -1
  312. package/dist/utils/platform-root-files.js +44 -0
  313. package/dist/utils/platform-root-files.js.map +1 -0
  314. package/dist/utils/platform-utils.js +35 -54
  315. package/dist/utils/platform-utils.js.map +1 -1
  316. package/dist/utils/platform-yaml-merge.js +20 -140
  317. package/dist/utils/platform-yaml-merge.js.map +1 -1
  318. package/dist/utils/prompts.js +92 -7
  319. package/dist/utils/prompts.js.map +1 -1
  320. package/dist/utils/registry-entry-filter.js +50 -27
  321. package/dist/utils/registry-entry-filter.js.map +1 -1
  322. package/dist/utils/registry-paths.js +5 -4
  323. package/dist/utils/registry-paths.js.map +1 -1
  324. package/dist/utils/scope-resolution.js +156 -0
  325. package/dist/utils/scope-resolution.js.map +1 -0
  326. package/dist/utils/source-mutability.js +15 -0
  327. package/dist/utils/source-mutability.js.map +1 -0
  328. package/dist/utils/tarball.js +29 -4
  329. package/dist/utils/tarball.js.map +1 -1
  330. package/dist/utils/version-ranges.js +1 -32
  331. package/dist/utils/version-ranges.js.map +1 -1
  332. package/dist/utils/workspace-index-helpers.js +28 -0
  333. package/dist/utils/workspace-index-helpers.js.map +1 -0
  334. package/dist/utils/workspace-index-ownership.js +100 -0
  335. package/dist/utils/workspace-index-ownership.js.map +1 -0
  336. package/dist/utils/workspace-index-yml.js +173 -0
  337. package/dist/utils/workspace-index-yml.js.map +1 -0
  338. package/examples/custom-subdirs-platform.jsonc +157 -0
  339. package/package.json +7 -2
  340. package/platforms.jsonc +531 -84
  341. package/schemas/map-pipeline-v1.json +256 -0
  342. package/schemas/platforms-v1.json +400 -0
  343. package/specs/README.md +88 -0
  344. package/specs/add/README.md +166 -0
  345. package/specs/agents-claude.md +570 -0
  346. package/specs/agents-opencode.md +622 -0
  347. package/specs/apply/README.md +21 -0
  348. package/specs/apply/apply-behavior.md +58 -0
  349. package/specs/apply/apply-command.md +51 -0
  350. package/specs/apply/conflicts.md +41 -0
  351. package/specs/apply/index-effects.md +81 -0
  352. package/specs/architecture.md +107 -0
  353. package/specs/auth/README.md +17 -0
  354. package/specs/auth/auth-http-contract.md +25 -0
  355. package/specs/auth/cli/credentials.md +39 -0
  356. package/specs/auth/cli/login.md +32 -0
  357. package/specs/auth/cli/logout.md +16 -0
  358. package/specs/claude-mcp.md +1065 -0
  359. package/specs/claude-plugins-marketplace.md +363 -0
  360. package/specs/claude-plugins.md +413 -0
  361. package/specs/cli-options.md +52 -0
  362. package/specs/codex-mcp.md +114 -0
  363. package/specs/commands-overview.md +175 -0
  364. package/specs/directory-layout.md +95 -0
  365. package/specs/install/README.md +12 -4
  366. package/specs/install/git-sources.md +230 -0
  367. package/specs/install/install-behavior.md +483 -73
  368. package/specs/install/package-yml-canonical.md +67 -35
  369. package/specs/install/version-resolution.md +69 -115
  370. package/specs/new/README.md +769 -0
  371. package/specs/new/SUMMARY.md +310 -0
  372. package/specs/new/scope-behavior.md +793 -0
  373. package/specs/pack/README.md +77 -0
  374. package/specs/pack/package-name-resolution.md +330 -0
  375. package/specs/package/README.md +18 -17
  376. package/specs/package/nested-packages-and-parent-packages.md +32 -31
  377. package/specs/package/package-index-yml.md +95 -101
  378. package/specs/package/package-root-layout.md +64 -46
  379. package/specs/package/registry-payload-and-copy.md +50 -44
  380. package/specs/package/universal-content.md +33 -56
  381. package/specs/package-sources.md +248 -0
  382. package/specs/platforms/README.md +52 -0
  383. package/specs/platforms/configuration.md +571 -0
  384. package/specs/platforms/detection.md +552 -0
  385. package/specs/platforms/directory-layout.md +599 -0
  386. package/specs/platforms/examples.md +1146 -0
  387. package/specs/platforms/flow-reference.md +1240 -0
  388. package/specs/platforms/flows.md +1488 -0
  389. package/specs/platforms/map-pipeline.md +801 -0
  390. package/specs/platforms/overview.md +349 -0
  391. package/specs/platforms/specification.md +700 -0
  392. package/specs/platforms/troubleshooting.md +697 -0
  393. package/specs/platforms/universal-converter.md +520 -0
  394. package/specs/push/README.md +1 -0
  395. package/specs/push/push-behavior.md +11 -3
  396. package/specs/push/push-remote-upload.md +1 -1
  397. package/specs/push/push-scoping.md +1 -1
  398. package/specs/push/push-version-selection.md +1 -1
  399. package/specs/registry.md +111 -0
  400. package/specs/remove/README.md +257 -0
  401. package/specs/save/README.md +21 -17
  402. package/specs/save/save-conflict-resolution.md +205 -83
  403. package/specs/save/save-file-discovery.md +6 -4
  404. package/specs/save/save-frontmatter-overrides.md +11 -15
  405. package/specs/save/save-modes-inputs.md +9 -39
  406. package/specs/save/save-naming-scoping.md +4 -4
  407. package/specs/save/save-package-detection.md +13 -13
  408. package/specs/save/save-registry-sync.md +16 -106
  409. package/specs/save/save-versioning.md +80 -0
  410. package/specs/scope-management.md +92 -0
  411. package/specs/set/README.md +520 -0
  412. package/specs/set/set-behavior.md +563 -0
  413. package/specs/show/README.md +483 -0
  414. package/specs/show/show-remote.md +494 -0
  415. package/specs/status/README.md +38 -0
  416. package/specs/uninstall/README.md +231 -0
  417. package/dist/commands/duplicate.js +0 -69
  418. package/dist/commands/duplicate.js.map +0 -1
  419. package/dist/commands/init.js +0 -117
  420. package/dist/commands/init.js.map +0 -1
  421. package/dist/commands/prune.js +0 -357
  422. package/dist/commands/prune.js.map +0 -1
  423. package/dist/commands/tui.js +0 -61
  424. package/dist/commands/tui.js.map +0 -1
  425. package/dist/core/install/index.js +0 -3
  426. package/dist/core/install/index.js.map +0 -1
  427. package/dist/core/push/push-single-file.js +0 -56
  428. package/dist/core/push/push-single-file.js.map +0 -1
  429. package/dist/core/save/package-detection.js +0 -147
  430. package/dist/core/save/package-detection.js.map +0 -1
  431. package/dist/core/save/save-single-file.js +0 -124
  432. package/dist/core/save/save-single-file.js.map +0 -1
  433. package/dist/core/token-store.js +0 -73
  434. package/dist/core/token-store.js.map +0 -1
  435. package/dist/tui/app.js +0 -95
  436. package/dist/tui/app.js.map +0 -1
  437. package/dist/tui/components/package-list.js +0 -73
  438. package/dist/tui/components/package-list.js.map +0 -1
  439. package/dist/tui/controller.js +0 -365
  440. package/dist/tui/controller.js.map +0 -1
  441. package/dist/tui/index.js +0 -12
  442. package/dist/tui/index.js.map +0 -1
  443. package/dist/tui/services/file-index.js +0 -64
  444. package/dist/tui/services/file-index.js.map +0 -1
  445. package/dist/tui/services/packages.js +0 -18
  446. package/dist/tui/services/packages.js.map +0 -1
  447. package/dist/tui/services/save.js +0 -21
  448. package/dist/tui/services/save.js.map +0 -1
  449. package/dist/tui/state/app-state.js +0 -15
  450. package/dist/tui/state/app-state.js.map +0 -1
  451. package/dist/tui/state.js +0 -17
  452. package/dist/tui/state.js.map +0 -1
  453. package/dist/tui/types.js.map +0 -1
  454. package/dist/tui/views/add-file-modal.js +0 -129
  455. package/dist/tui/views/add-file-modal.js.map +0 -1
  456. package/dist/tui/views/file-preview.js +0 -44
  457. package/dist/tui/views/file-preview.js.map +0 -1
  458. package/dist/tui/views/list-packages.js +0 -73
  459. package/dist/tui/views/list-packages.js.map +0 -1
  460. package/dist/tui/views/main-menu.js +0 -29
  461. package/dist/tui/views/main-menu.js.map +0 -1
  462. package/dist/tui/views/manage-view.js +0 -81
  463. package/dist/tui/views/manage-view.js.map +0 -1
  464. package/dist/tui/views/package-hub.js +0 -120
  465. package/dist/tui/views/package-hub.js.map +0 -1
  466. package/dist/tui/views/placeholder.js +0 -24
  467. package/dist/tui/views/placeholder.js.map +0 -1
  468. package/dist/utils/bun-bootstrap.js +0 -72
  469. package/dist/utils/bun-bootstrap.js.map +0 -1
  470. package/dist/utils/entity-id.js +0 -19
  471. package/dist/utils/entity-id.js.map +0 -1
  472. package/dist/utils/package-local-files.js +0 -5
  473. package/dist/utils/package-local-files.js.map +0 -1
  474. package/dist/utils/path-matching.js +0 -74
  475. package/dist/utils/path-matching.js.map +0 -1
  476. package/dist/utils/root-file-operations.js +0 -39
  477. package/dist/utils/root-file-operations.js.map +0 -1
  478. package/dist/utils/root-file-transformer.js +0 -27
  479. package/dist/utils/root-file-transformer.js.map +0 -1
  480. package/dist/utils/yaml-frontmatter.js +0 -25
  481. package/dist/utils/yaml-frontmatter.js.map +0 -1
  482. package/specs/auth/auth-device-flow.md +0 -70
  483. package/specs/login/login-device-flow.md +0 -70
  484. package/specs/platforms.md +0 -193
  485. package/specs/save-pack-versioning.md +0 -224
  486. package/specs/save-pack.md +0 -68
  487. /package/dist/{tui β†’ core/source-resolution}/types.js +0 -0
@@ -3,42 +3,174 @@
3
3
  This document defines the **user-facing behavior** of the `install` command, assuming:
4
4
 
5
5
  - Versioning semantics from `save` / `pack` specs are already in place.
6
- - `package.yml` is the **canonical declaration of direct dependencies** (see `package-yml-canonical.md`).
6
+ - `openpackage.yml` is the **canonical declaration of direct dependencies** (see `package-yml-canonical.md`).
7
7
  - Version selection obeys **β€œlatest in range”**, with **local-first defaults for fresh installs without an explicit version** and **automatic fallback to remote when local cannot satisfy** (see `version-resolution.md`).
8
8
 
9
9
  ---
10
10
 
11
+ ## 0. Workspace Context
12
+ The `install` command operates on the **workspace root** determined by the effective current working directory (`cwd` from shell or overridden by global `--cwd <dir>` flag; see [../../cli-options.md]). This affects:
13
+ - Detection of `openpackage.yml` (must exist at effective cwd for root package ops).
14
+ - Target location for file installations:
15
+ - **Universal content**: platform-mapped from package subdirs (e.g., `commands/`, `rules/`) to platform-specific locations (e.g., `.cursor/commands/`, `.opencode/commands/`).
16
+ - **Root files**: installed at workspace root (e.g., `AGENTS.md`).
17
+ - **`root/` directory (direct copy)**: copied 1:1 to workspace root with `root/` prefix stripped.
18
+ - Dependency resolution from workspace `openpackage.yml`.
19
+ - **Package source discovery**: Searches workspace-local and global packages directories before falling back to registry.
20
+
21
+ If no package detected at effective cwd, errors with "No package project found" (unless dry-run or flags allow).
22
+
23
+ ## 0.1 Package Source Resolution for Name-Based Install
24
+
25
+ When `opkg install <name>` is invoked (no path, git, or tarball syntax), the system searches for packages in this priority order:
26
+
27
+ ### 1. Check Existing Dependency in openpackage.yml (Highest Priority)
28
+
29
+ If `<name>` exists in `openpackage.yml`:
30
+ - **With `path:`**: Always use the declared path source
31
+ - **With `git:`**: Always use the declared git source
32
+ - **With `version:`**: Resolve from registry as normal
33
+
34
+ This ensures explicit declarations in the manifest are always respected.
35
+
36
+ ### 2. Check Workspace-Local Packages (Override)
37
+
38
+ If `./.openpackage/packages/<name>/` exists and is a valid package:
39
+ - **Always use it** - no version comparison
40
+ - This is an explicit local override (you're working on this project's fork)
41
+ - Skip all other checks
42
+
43
+ **User Feedback**:
44
+ ```
45
+ βœ“ Found <name> in workspace packages
46
+ πŸ’‘ Workspace packages always override global/registry
47
+ ```
48
+
49
+ ### 3. Compare Global Packages vs Registry (Version-Aware)
50
+
51
+ If both `~/.openpackage/packages/<name>/` and `~/.openpackage/registry/<name>/<version>/` exist:
52
+
53
+ **Version Comparison**:
54
+ - Read `version` from global packages `openpackage.yml`
55
+ - Find latest version in registry
56
+ - **Select source with higher semver version**
57
+ - **Tie-breaker**: If versions equal, prefer global packages (mutable, development-friendly)
58
+
59
+ **Rationale**: Global packages are for convenience/sharing. Users expect to get the latest version automatically. Unlike workspace packages (explicit override), global packages should track the latest available version to avoid outdated dependencies.
60
+
61
+ **User Feedback** (comparison case):
62
+ ```
63
+ Resolving <name>...
64
+ β€’ Global packages: 0.2.0 (mutable)
65
+ β€’ Registry: 0.5.0 (stable)
66
+ βœ“ Using <name>@0.5.0 from registry (newer version)
67
+ ⚠️ Global packages has older version (0.2.0)
68
+ πŸ’‘ To update global: cd ~/.openpackage/packages/<name> && opkg pack
69
+ ```
70
+
71
+ **User Feedback** (tie-breaker):
72
+ ```
73
+ Resolving <name>...
74
+ β€’ Global packages: 0.5.0 (mutable)
75
+ β€’ Registry: 0.5.0 (stable)
76
+ βœ“ Using <name>@0.5.0 from global packages (same version, prefer mutable)
77
+ ```
78
+
79
+ ### 4. Single Source Fallback
80
+
81
+ If only global packages OR registry exists (not both):
82
+ - Use the available source
83
+ - No version comparison needed
84
+
85
+ **User Feedback**:
86
+ ```
87
+ βœ“ Found <name> in global packages
88
+ ```
89
+
90
+ ### 5. Remote Resolution
91
+
92
+ If no local sources exist:
93
+ - Fall back to normal registry resolution (local + remote)
94
+ - Follow version-resolution.md semantics
95
+
96
+ ### Forcing Specific Sources
97
+
98
+ To bypass version comparison and force a specific source:
99
+
100
+ **Force global packages**:
101
+ ```bash
102
+ opkg install ~/.openpackage/packages/<name>/
103
+ ```
104
+
105
+ **Force registry version**:
106
+ ```bash
107
+ opkg install <name>@0.2.0 # Explicit version
108
+ ```
109
+
110
+ **Lock in openpackage.yml**:
111
+ ```yaml
112
+ packages:
113
+ - name: <name>
114
+ path: ~/.openpackage/packages/<name>/ # Explicit path = no version check
115
+ ```
116
+
117
+ ### Summary Table
118
+
119
+ | Scenario | Behavior | Reason |
120
+ |----------|----------|--------|
121
+ | In openpackage.yml with path/git | Use declared source | Explicit declaration |
122
+ | Workspace pkg exists | Use workspace (no comparison) | Explicit override |
123
+ | Global newer than registry | Use global | Higher version |
124
+ | Registry newer than global | Use registry | Higher version |
125
+ | Same version | Use global | Prefer mutable |
126
+ | Only global exists | Use global | Single source |
127
+ | Only registry exists | Use registry | Single source |
128
+ | Neither exists locally | Remote resolution | Normal flow |
129
+
11
130
  ## 1. Command shapes
12
131
 
13
132
  - **`opkg install`**
14
- - **Meaning**: Materialize *all* dependencies declared in `.openpackage/package.yml` into the workspace, at the **latest versions that satisfy their declared ranges**, using the **default local-first with remote-fallback policy** over local and remote registries (see Β§2 and `version-resolution.md`).
133
+ - **Meaning**: Materialize *all* dependencies declared in `openpackage.yml` into the workspace, at the **latest versions that satisfy their declared ranges**, using the **default local-first with remote-fallback policy** over local and remote registries (see Β§2 and `version-resolution.md`).
15
134
 
16
135
  - **`opkg install <name>`**
17
136
  - **Meaning**:
18
- - If `<name>` is **already declared** in `package.yml`: ensure it is installed at the **latest version that satisfies the `package.yml` range**, using the same **local-first with remote-fallback** resolver behavior.
19
- - If `<name>` is **not declared**: perform a **fresh install**, resolve the target version using the **local-first with remote-fallback** policy (see Β§3 and `version-resolution.md`), then add a new entry to `package.yml` (see Β§3).
137
+ - If `<name>` is **already declared** in `openpackage.yml`: ensure it is installed at the **latest version that satisfies the `openpackage.yml` range**, using the same **local-first with remote-fallback** resolver behavior.
138
+ - If `<name>` is **not declared**: perform a **fresh install**, resolve the target version using the **local-first with remote-fallback** policy (see Β§3 and `version-resolution.md`), then add a new entry to `openpackage.yml` (see Β§3).
20
139
 
21
140
  - **`opkg install <name>@<spec>`**
22
141
  - **Meaning**:
23
- - If `<name>` is **already declared** in `package.yml`: `<spec>` is treated as a **constraint hint** that must be **compatible** with the canonical `package.yml` range (see `package-yml-canonical.md` for rules); resolution still uses the same **local-first with remote-fallback** semantics unless `--local` or `--remote` are set.
24
- - If `<name>` is **not declared**: `<spec>` is treated as the **initial version range** to store in `package.yml`, and resolution uses the **local-first with remote-fallback** policy under that range (or strictly local / remote when the corresponding flags are set).
142
+ - If `<name>` is **already declared** in `openpackage.yml`: `<spec>` is treated as a **constraint hint** that must be **compatible** with the canonical `openpackage.yml` range (see `package-yml-canonical.md` for rules); resolution still uses the same **local-first with remote-fallback** semantics unless `--local` or `--remote` are set.
143
+ - If `<name>` is **not declared**: `<spec>` is treated as the **initial version range** to store in `openpackage.yml`, and resolution uses the **local-first with remote-fallback** policy under that range (or strictly local / remote when the corresponding flags are set).
25
144
 
26
145
  - **`opkg install <name>/<registry-path>`** and **`opkg install <name>@<spec>/<registry-path>`**
27
- - **Meaning**: Install only the specified registry-relative path(s) for `<name>` (e.g. `.openpackage/universal/prompts/foo.md`, `workspace/agents.md`). The path must be an **exact registry path** (no globs) and applies only to the **root dependency** being installed.
146
+ - **Meaning**: Install only the specified registry-relative path(s) for `<name>` (e.g. `commands/foo.md`, `agents/helper.md`). The path must be an **exact registry path** (no globs) and applies only to the **root dependency** being installed.
28
147
 
29
- Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, conflicts) keep their existing semantics unless overridden below.
148
+ - **`opkg install git:<url>[#ref]`**
149
+ - **Meaning**: Install a package directly from a git repository by cloning it and installing from the checked-out working tree.
150
+ - Requirements:
151
+ - The repository root MUST contain `openpackage.yml`.
152
+ - `git` must be available on PATH.
153
+ - Notes:
154
+ - The installed package version is taken from the repo’s `openpackage.yml`.
155
+ - `install` persists this dependency to `openpackage.yml` using `git` + optional `ref` (not a registry `version` range).
156
+
157
+ - **`opkg install github:<owner>/<repo>[#ref]`**
158
+ - **Meaning**: Shorthand for GitHub git installs. Equivalent to:
159
+ - `opkg install git:https://github.com/<owner>/<repo>.git[#ref]`
160
+
161
+ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, conflicts) keep their existing semantics unless overridden below.
30
162
 
31
163
  ---
32
164
 
33
165
  ## 2. High-level goals
34
166
 
35
167
  - **G1 – Single mental model**:
36
- - **β€œ`package.yml` declares intent, `install` materializes the newest versions that satisfy that intent.”**
168
+ - **β€œ`openpackage.yml` declares intent, `install` materializes the newest versions that satisfy that intent.”**
37
169
 
38
170
  - **G2 – Latest in range with local-first defaults**:
39
171
  - Whenever a version needs to be chosen for install, the system:
40
- - For **fresh dependencies** (e.g. `opkg install <name>` or `opkg install <name>@<spec>` where `<name>` is not yet in `package.yml`), first tries to satisfy the effective range from the **local registry only**, then falls back to include **remote versions** when local cannot satisfy.
41
- - For **existing dependencies** (already declared in `package.yml`, with or without CLI hints), follow the **same local-first with remote fallback policy** described in `version-resolution.md`, choosing the highest satisfying semver version (including pre-releases where allowed by policy).
172
+ - For **fresh dependencies** (e.g. `opkg install <name>` or `opkg install <name>@<spec>` where `<name>` is not yet in `openpackage.yml`), first tries to satisfy the effective range from the **local registry only**, then falls back to include **remote versions** when local cannot satisfy.
173
+ - For **existing dependencies** (already declared in `openpackage.yml`, with or without CLI hints), follow the **same local-first with remote fallback policy** described in `version-resolution.md`, choosing the highest satisfying semver version (including pre-releases where allowed by policy).
42
174
  - This same resolver policy (or its `--local` / `--remote` variants) is used **uniformly** for:
43
175
  - The root install target.
44
176
  - All **transitive dependencies** discovered during resolution.
@@ -54,7 +186,7 @@ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, confli
54
186
 
55
187
  ## 3. Fresh vs existing dependencies
56
188
 
57
- ### 3.1 Fresh dependency (`<name>` not in package.yml)
189
+ ### 3.1 Fresh dependency (`<name>` not in openpackage.yml)
58
190
 
59
191
  - **Inputs**:
60
192
  - CLI: `opkg install <name>` or `opkg install <name>@<spec>`.
@@ -63,15 +195,14 @@ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, confli
63
195
  - **Behavior**:
64
196
  - **Case A – `opkg install <name>` (no version spec)**:
65
197
  - Compute **available versions** from the **local registry only** for the first resolution attempt (no remote metadata is consulted initially).
66
- - **Default behavior**: Select the **latest semver version** from this local set that satisfies the internal wildcard range (`*`), **including pre-releases/WIPs**. If the selected version is a pre-release/WIP, the CLI should state that explicitly.
67
- - **With `--stable` flag**: From the local set, select the **latest stable** version `S` if any exist. If only WIP or pre-releases exist locally, select the latest WIP/pre-release.
198
+ - Select the **latest semver version** from this local set that satisfies the internal wildcard range (`*`), including pre-releases when applicable. If the selected version is a pre-release, the CLI should state that explicitly.
68
199
  - If **no local versions exist** or **no local version satisfies the implicit range**:
69
200
  - In **default mode** (no `--local`), `install` MUST:
70
- - Attempt resolution again including **remote versions**, following the rules in `version-resolution.md` (local+remote union and WIP/stable policies).
201
+ - Attempt resolution again including **remote versions**, following the rules in `version-resolution.md` (local+remote union).
71
202
  - Only fail if **neither local nor remote** provide a satisfying version, or remote metadata is unavailable.
72
203
  - In **`--local` mode**, this remote fallback is **disabled** and the command fails with a clear β€œnot available locally” style error that may suggest re-running without `--local` or using `save` / `pack`.
73
204
  - **Install `<name>@<selectedVersion>`**.
74
- - **Add to `package.yml`**:
205
+ - **Add to `openpackage.yml`**:
75
206
  - Default range is **caret based on the stable base** of the selected version (e.g. `^1.0.1` for `1.0.1-000fz8.a3k`), unless later overridden by a global policy.
76
207
  - When the selected version is **unversioned** (manifest omits `version`, represented internally as `0.0.0`), persist the entry **without a `version` field** in `packages` / `dev-packages` (do **not** write `0.0.0`).
77
208
 
@@ -84,25 +215,34 @@ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, confli
84
215
  - In **default mode** (no `--local`), include **remote versions** and retry selection over the combined set, allowing a remote version to be selected when it is the only match.
85
216
  - In **`--local` mode**, do **not** fall back to remote; fail with a clear error indicating no local version satisfies `<spec>`.
86
217
  - **Install the selected version**.
87
- - **Persist `<spec>` in `package.yml`** (do not auto-normalize beyond what the version-range parser requires).
218
+ - **Persist `<spec>` in `openpackage.yml`** (do not auto-normalize beyond what the version-range parser requires).
88
219
 
89
- ### 3.2 Existing dependency (`<name>` already in package.yml)
220
+ ### 3.2 Existing dependency (`<name>` already in openpackage.yml)
90
221
 
91
222
  - **Inputs**:
92
- - Canonical range from `package.yml` (see `package-yml-canonical.md`).
223
+ - Canonical range from `openpackage.yml` (see `package-yml-canonical.md`).
93
224
  - Optional CLI `<spec>` from `install <name>@<spec>`.
94
225
 
95
226
  - **Behavior**:
96
- - `opkg install <name>`:
97
- - Use the **canonical range from `package.yml`**.
98
- - Resolve versions using the same **local-first with remote-fallback** policy (per `version-resolution.md`):
99
- - First attempt to satisfy the canonical range using **only local registry versions**.
100
- - Only when no satisfying local version exists, and remote is enabled and reachable, **include remote versions** and retry selection over the combined set.
101
- - **Install / upgrade to the latest satisfying version** (if newer than current).
102
- - `opkg install <name>@<spec>`:
103
- - Treat `<spec>` as a **sanity check** against the canonical range:
104
- - If compatible (according to rules in `package-yml-canonical.md`), proceed as above.
105
- - If incompatible, **fail with a clear error** instructing the user to edit `package.yml` instead of using CLI-only overrides.
227
+ - **Path/Git Source Persistence**:
228
+ - If the dependency entry in `openpackage.yml` has a `path:` or `git:` field, `opkg install <name>` **always uses that declared source**, regardless of whether a registry version exists.
229
+ - This ensures that path-based and git-based dependencies remain consistent with their declared intent, supporting local development workflows and monorepo scenarios.
230
+ - User feedback: `βœ“ Using path source from openpackage.yml: <path>` or `βœ“ Using git source from openpackage.yml: <url>#<ref>`
231
+ - To switch from path/git to registry:
232
+ - Edit `openpackage.yml`: remove `path:` or `git:` field, add `version:` field
233
+ - Or: `opkg uninstall <name>` then `opkg install <name>@<version>`
234
+
235
+ - **Registry-based dependencies** (have `version:` field, no `path:` or `git:`):
236
+ - `opkg install <name>`:
237
+ - Use the **canonical range from `openpackage.yml`**.
238
+ - Resolve versions using the same **local-first with remote-fallback** policy (per `version-resolution.md`):
239
+ - First attempt to satisfy the canonical range using **only local registry versions**.
240
+ - Only when no satisfying local version exists, and remote is enabled and reachable, **include remote versions** and retry selection over the combined set.
241
+ - **Install / upgrade to the latest satisfying version** (if newer than current).
242
+ - `opkg install <name>@<spec>`:
243
+ - Treat `<spec>` as a **sanity check** against the canonical range:
244
+ - If compatible (according to rules in `package-yml-canonical.md`), proceed as above.
245
+ - If incompatible, **fail with a clear error** instructing the user to edit `openpackage.yml` instead of using CLI-only overrides.
106
246
 
107
247
  ### 3.4 Registry-path / single-file installs
108
248
 
@@ -113,10 +253,10 @@ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, confli
113
253
  - **Behavior – fresh dependency**:
114
254
  - Resolve the version using the same policies as Β§3.1 (respecting `<spec>` if provided).
115
255
  - Install only the specified registry path(s), including root files only when they are explicitly listed.
116
- - Persist a new `files: [<registry-path>, ...]` list for the dependency in `package.yml` alongside the chosen range.
117
- - If the requested path does not exist in the selected version, the install **warns and skips the package** (no files written, counts as `skipped`).
256
+ - Persist a new `files: [<registry-path>, ...]` list for the dependency in `openpackage.yml` alongside the chosen range.
257
+ - If the requested path does not exist in the selected version, the install **warns and skips the package** (no files written, counts as `skipped`).
118
258
 
119
- - **Behavior – existing dependency with `files` already in `package.yml`**:
259
+ - **Behavior – existing dependency with `files` already in `openpackage.yml`**:
120
260
  - `opkg install <name>` (no new path):
121
261
  - Re-installs the stored subset.
122
262
  - In an interactive TTY and non-`--dry-run`, prompt: **switch to full install?** If accepted, clears the `files` list and performs a full install; otherwise keeps the subset.
@@ -125,10 +265,10 @@ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, confli
125
265
  - Adds the new path to the stored `files` list (deduped), then installs that combined subset.
126
266
 
127
267
  - **Behavior – existing dependency without `files` (full install)**:
128
- - Path-based install attempts are **rejected** with a clear error. To install a subset, uninstall first (or remove the dependency) and re-install with a path, or edit `package.yml` manually to add `files`.
268
+ - Path-based install attempts are **rejected** with a clear error. To install a subset, uninstall first (or remove the dependency) and re-install with a path, or edit `openpackage.yml` manually to add `files`.
129
269
 
130
270
  - **Switching back to full**:
131
- - Accept the prompt described above, or delete the `files` field for the dependency in `package.yml` (or uninstall/reinstall without a path).
271
+ - Accept the prompt described above, or delete the `files` field for the dependency in `openpackage.yml` (or uninstall/reinstall without a path).
132
272
 
133
273
  ---
134
274
 
@@ -149,17 +289,23 @@ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, confli
149
289
  ## 4. `opkg install` (no args) – β€œrefresh workspace to intent”
150
290
 
151
291
  - **Inputs**:
152
- - `.openpackage/package.yml`:
153
- - `packages[]` and `dev-packages[]`, each with `name` and `version` (range or exact).
292
+ - `openpackage.yml`:
293
+ - `packages[]` and `dev-packages[]`, each with `name` and exactly one source:
294
+ - `version` (registry range or exact)
295
+ - `path` (directory or tarball)
296
+ - `git` (git URL) with optional `ref`
154
297
 
155
298
  - **Behavior**:
156
299
  - For each declared dependency:
157
- - Determine its **effective range** (canonical, possibly reconciled with any global overrides).
158
- - Resolve **latest satisfying version from local+remote**.
300
+ - If it is a registry dependency (`version`):
301
+ - Determine its **effective range** (canonical, possibly reconciled with any global overrides).
302
+ - Resolve **latest satisfying version from local+remote**.
303
+ - If it is a path dependency (`path`) or git dependency (`git` + optional `ref`):
304
+ - Load directly from that source (no registry version resolution).
159
305
  - If that version is **already installed**, **do nothing** (idempotent).
160
306
  - If a **newer satisfying version exists**, **upgrade** the installed version to that one.
161
307
  - This makes `opkg install` act as:
162
- - **β€œHydrate my workspace to match `package.yml`”** on first run.
308
+ - **β€œHydrate my workspace to match `openpackage.yml`”** on first run.
163
309
  - **β€œUpgrade within my declared ranges”** on subsequent runs.
164
310
 
165
311
  ---
@@ -186,67 +332,331 @@ Other flags (`--dev`, `--remote`, `--platforms`, `--dry-run`, `--stable`, confli
186
332
  - Selected versions are **guaranteed to exist remotely**; local-only versions are ignored for selection.
187
333
  - Intended for:
188
334
  - Ensuring compatibility with what is actually **published** remotely.
189
- - CI / reproducibility scenarios where local cache should not affect choices.
335
+ - CI / reproducibility scenarios where local registry state should not affect choices.
190
336
 
191
337
  ---
192
338
 
193
- ## 6. WIP vs stable on install
339
+ ## 6. Workspace Index and Key Tracking
340
+
341
+ ### 6.1 Workspace Index Updates
342
+
343
+ `opkg install` updates the workspace index (`openpackage.index.yml`) to reflect installed files:
344
+
345
+ - **Simple file mappings**: Direct string paths for files owned by one package
346
+ ```yaml
347
+ files:
348
+ commands/test.md:
349
+ - .cursor/commands/test.md
350
+ ```
351
+
352
+ - **Complex mappings with key tracking**: Object format for merged files
353
+ ```yaml
354
+ files:
355
+ mcp.jsonc:
356
+ - target: .opencode/opencode.json
357
+ merge: deep
358
+ keys:
359
+ - mcp.server1
360
+ - mcp.server2
361
+ ```
362
+
363
+ ### 6.2 Key Tracking for Flow-Based Merges
364
+
365
+ When packages use platform flows with merge strategies (`deep` or `shallow`), the install system automatically tracks which keys each package contributes to merged files.
366
+
367
+ **Purpose:** Enables precise removal during uninstall without affecting other packages' content.
368
+
369
+ **When keys are tracked:**
370
+ - βœ… Flow uses `merge: 'deep'` or `merge: 'shallow'`
371
+ - βœ… Target file will be shared by multiple packages
372
+
373
+ **When keys are NOT tracked:**
374
+ - ❌ `merge: 'replace'` - entire file owned by one package
375
+ - ❌ `merge: 'composite'` - delimiter-based tracking used
376
+ - ❌ Simple file copy - no merge involved
377
+
378
+ **Package source:**
379
+ ```json
380
+ {
381
+ "mcpServers": {
382
+ "server1": { "url": "http://localhost:3000" }
383
+ }
384
+ }
385
+ ```
386
+
387
+ **Workspace index after install:**
388
+ ```yaml
389
+ packages:
390
+ my-mcp-package:
391
+ files:
392
+ mcp.jsonc:
393
+ - target: .opencode/opencode.json
394
+ merge: deep
395
+ keys:
396
+ - mcp.server1 # Transformed key tracked
397
+ ```
398
+
399
+ **Key features:**
400
+ - Tracks **output** keys (after transformations), not input keys
401
+ - Uses dot notation for nested paths: `mcp.server1` β†’ `{ mcp: { server1: {...} } }`
402
+ - Enables clean uninstall without reverse-applying transformations
403
+
404
+ See [Platforms β†’ Flows](../platforms/flows.md#key-tracking-for-uninstall) for complete details on key tracking behavior.
405
+
406
+ ## 7. Pre-release vs stable on install
194
407
 
195
408
  High-level rules (details in `version-resolution.md`):
196
409
 
197
- - **Default behavior: Latest-in-range, including WIP**:
198
- - For any non-exact constraint (wildcard or range), the resolver chooses the **highest semver version** that satisfies the range, regardless of whether it is stable or WIP/pre-release.
199
- - This ensures that `opkg install <name>` naturally selects the newest available version, including WIPs, which is useful for development workflows.
200
- - When a WIP/pre-release is selected, `opkg install` output should clearly indicate that the installed version is a pre-release/WIP.
201
-
202
- - **With `--stable` flag: Stable-preferred policy**:
203
- - For a given base stable `S`, if both:
204
- - Stable `S`, and
205
- - WIPs `S-<t>.<w>`
206
- exist and satisfy the range, **prefer `S`**.
207
- - WIP/pre-release versions are only selected when **no stable versions** exist that satisfy the range.
208
- - This is useful for CI/production scenarios where stability is preferred over the absolute latest version.
410
+ - **Latest-in-range, including pre-releases**:
411
+ - For any non-exact constraint (wildcard or range), the resolver chooses the **highest semver version** that satisfies the range, including pre-releases when allowed by semver range rules.
412
+ - When a pre-release is selected, `opkg install` output should clearly indicate that the installed version is a pre-release.
209
413
 
210
414
  ---
211
415
 
212
- ## 7. WIP content resolution (unified with stable)
416
+ ## 8. Pre-release content resolution (unified with stable)
213
417
 
214
- This section ties WIP version selection to **how content is loaded** when the selected version is a WIP prerelease, assuming both WIP and stable versions are stored as full copies in the local registry.
418
+ This section ties pre-release version selection to **how content is loaded** when the selected version is a pre-release, assuming both stable and pre-release versions are stored as full copies in the local registry.
215
419
 
216
- - **Registry layout for WIP versions**:
217
- - For WIP saves, the local registry contains a **full copy** of the package:
218
- - Path: `~/.openpackage/registry/<pkg>/<wipVersion>/...`.
219
- - Contents mirror the workspace package at the time of `save`, just like stable copies.
420
+ - **Registry layout for pre-releases**:
421
+ - The local registry contains a **full copy** of the package for any version (stable or pre-release):
422
+ - Path: `~/.openpackage/registry/<pkg>/<version>/...`.
220
423
 
221
- - **Install behavior when a WIP version is selected**:
222
- - When the version resolution layer selects a **WIP version** that exists locally:
424
+ - **Install behavior when a pre-release is selected**:
425
+ - When the version resolution layer selects a **pre-release version** that exists locally:
223
426
  - The package loader (e.g. `packageManager.loadPackage`) MUST:
224
- - Load files directly from the WIP registry directory (`~/.openpackage/registry/<pkg>/<wipVersion>/...`).
225
- - Read the `package.yml` from that directory for metadata.
427
+ - Load files directly from the selected registry directory (`~/.openpackage/registry/<pkg>/<version>/...`).
428
+ - Read the `openpackage.yml` from that directory for metadata.
226
429
  - Treat this data exactly as it would for a stable registry copy for the purposes of installation and dependency resolution.
227
- - If the WIP registry directory is missing or malformed for a selected WIP version:
228
- - Install MUST **fail clearly**, indicating the broken WIP copy and suggesting:
229
- - Re-running `save`/`pack` to regenerate the version, or
430
+ - If the registry directory is missing or malformed for a selected version:
431
+ - Install MUST **fail clearly**, indicating the broken registry copy and suggesting:
432
+ - Re-running `opkg pack` (or re-pulling from remote) to regenerate the version, or
230
433
  - Using a different available version instead.
231
434
 
232
435
  - **Remote considerations**:
233
- - Both WIP and stable versions exposed by remote registries are treated as **normal copied packages**.
234
- - There is no link-based indirection layer in the registry layout for WIP versions.
436
+ - Both pre-release and stable versions exposed by remote registries are treated as **normal copied packages**.
437
+
438
+ ---
439
+
440
+ ## 9. Claude Code plugin support
441
+
442
+ OpenPackage supports installing **Claude Code plugins** and other **platform-specific packages** directly from git repositories and local paths. The **Universal Platform Converter** automatically detects package format and converts between platforms as needed during the install flow.
443
+
444
+ **Key features:**
445
+ - **Automatic format detection** - Identifies universal vs platform-specific packages
446
+ - **Direct installation** - Claude plugins install AS-IS to Claude platform (no conversion)
447
+ - **Cross-platform conversion** - Claude plugins can be installed to Cursor, OpenCode, etc. by automatically converting through universal format
448
+ - **Bidirectional flows** - Platform transformations are automatically inverted for reverse conversion
449
+
450
+ See [Platform Universal Converter](../platforms/universal-converter.md) for complete technical details.
451
+
452
+ ### 9.1 Plugin detection
453
+
454
+ After cloning a git repository or resolving a local path, the install pipeline checks for:
455
+
456
+ 1. **Claude Code plugin manifests:**
457
+ - **Individual plugin**: `.claude-plugin/plugin.json` at the package root
458
+ - **Plugin marketplace**: `.claude-plugin/marketplace.json` at the package root
459
+
460
+ 2. **Package format detection:**
461
+ - **Platform-specific**: Files in platform directories (`.claude/`, `.cursor/`, etc.)
462
+ - **Universal**: Files in universal subdirectories (`commands/`, `agents/`, `rules/`, etc.)
463
+
464
+ If a Claude plugin manifest is found, special plugin handling is triggered. Otherwise, format detection determines installation strategy.
465
+
466
+ ### 9.2 Individual plugin install flow
467
+
468
+ When an individual plugin is detected:
469
+
470
+ 1. **Read and validate** `.claude-plugin/plugin.json`
471
+ - Required fields: `name`, `version`
472
+ - Optional fields: `description`, `author`, `repository`, `license`, `keywords`
473
+
474
+ 2. **Transform to OpenPackage format (in-memory only)**
475
+ - Plugin metadata is converted to OpenPackage `PackageYml` structure
476
+ - No registry copy is created (git/path remains source of truth)
477
+
478
+ 3. **Collect plugin files**
479
+ - All files except `.claude-plugin/` directory are collected
480
+ - Original directory structure is preserved (commands/, agents/, skills/, hooks/, etc.)
481
+ - Junk files (`.DS_Store`, `.git/`, etc.) are filtered out
482
+
483
+ 4. **Detect package format**
484
+ - **Universal format**: Standard OpenPackage with `commands/`, `agents/`, etc.
485
+ - **Platform-specific format**: Claude-specific structure with `.claude/` directories
486
+ - Detection confidence score calculated based on file distribution
487
+
488
+ 5. **Install with Universal Converter**
489
+ - **Strategy selection:**
490
+ - **Direct installation (AS-IS)**: Source platform = target platform (e.g., Claude β†’ Claude)
491
+ - Files copied without transformation for fastest install
492
+ - **Cross-platform conversion**: Source β‰  target (e.g., Claude β†’ Cursor)
493
+ - Stage 1: Invert source platform flows (Claude β†’ Universal)
494
+ - Stage 2: Apply target platform flows (Universal β†’ Cursor)
495
+ - **Standard installation**: Universal packages use existing flow system
496
+
497
+ - **Platform mappings** (for universal or converted packages):
498
+ - `commands/` β†’ `.claude/commands/`, `.cursor/commands/`, etc.
499
+ - `agents/` β†’ `.claude/agents/`, `.cursor/agents/`, etc.
500
+ - `skills/` β†’ `.claude/skills/`, `.cursor/skills/`, etc.
501
+ - `hooks/` β†’ `.claude/hooks/`, `.cursor/hooks/`, etc.
502
+ - Root files (`.mcp.json`, `.lsp.json`) install to platform roots
503
+
504
+ 6. **Track as git dependency**
505
+ - Persisted in `openpackage.yml` with git source:
506
+ ```yaml
507
+ packages:
508
+ - name: commit-commands
509
+ git: https://github.com/anthropics/claude-code.git
510
+ subdirectory: plugins/commit-commands # If from subdirectory
511
+ ```
512
+
513
+ **Examples:**
514
+
515
+ ```bash
516
+ # Install Claude plugin to Claude platform (direct AS-IS installation)
517
+ opkg install github:user/my-claude-plugin --platforms claude
518
+ ```
519
+ Console output:
520
+ ```
521
+ πŸ”Œ Detected Claude Code plugin
522
+ πŸ“¦ Installing plugin: my-plugin@1.0.0
523
+ βœ“ Installing my-plugin AS-IS for claude platform (matching format)
524
+ βœ“ Added files: 5
525
+ β”œβ”€β”€ .claude/commands/review.md
526
+ β”œβ”€β”€ .claude/commands/test.md
527
+ └── ...
528
+ ```
529
+
530
+ ```bash
531
+ # Install Claude plugin to Cursor platform (cross-platform conversion)
532
+ opkg install github:user/my-claude-plugin --platforms cursor
533
+ ```
534
+ Console output:
535
+ ```
536
+ πŸ”Œ Detected Claude Code plugin
537
+ πŸ“¦ Installing plugin: my-plugin@1.0.0
538
+ πŸ”„ Converting my-plugin from claude to cursor format
539
+ βœ“ Conversion stage: platform-to-universal (5 files)
540
+ βœ“ Applying cursor platform flows
541
+ βœ“ Added files: 5
542
+ β”œβ”€β”€ .cursor/commands/review.md
543
+ β”œβ”€β”€ .cursor/commands/test.md
544
+ └── ...
545
+ ```
546
+
547
+ ```bash
548
+ # Install to multiple platforms (mixed strategies)
549
+ opkg install github:user/my-claude-plugin --platforms claude,cursor,opencode
550
+ ```
551
+ Console output:
552
+ ```
553
+ πŸ”Œ Detected Claude Code plugin
554
+ πŸ“¦ Installing plugin: my-plugin@1.0.0
555
+ βœ“ Installing AS-IS for claude platform (matching format)
556
+ πŸ”„ Converting to cursor format
557
+ πŸ”„ Converting to opencode format
558
+ βœ“ Added 15 files across 3 platforms
559
+ ```
560
+
561
+ ```bash
562
+ # Legacy: Install individual plugin from subdirectory
563
+ opkg install github:anthropics/claude-code#subdirectory=plugins/commit-commands
564
+
565
+ # Legacy: Install plugin from dedicated repo
566
+ opkg install github:user/my-claude-plugin
567
+ ```
568
+
569
+ ### 9.3 Marketplace install flow
570
+
571
+ When a plugin marketplace is detected:
572
+
573
+ 1. **Parse marketplace manifest** (`.claude-plugin/marketplace.json`)
574
+ - Required fields: `name`, `plugins[]`
575
+ - Each plugin entry must have: `name`, `subdirectory` (or `source`)
576
+
577
+ 2. **Display interactive selection prompt**
578
+ - Lists all available plugins with descriptions
579
+ - User selects plugin(s) via multiselect (space to toggle, enter to confirm)
580
+ - Canceling (no selection) exits without installing
581
+
582
+ 3. **Install each selected plugin**
583
+ - For each selected plugin:
584
+ - Resolve plugin subdirectory within the cloned/resolved marketplace directory
585
+ - Validate subdirectory contains `.claude-plugin/plugin.json`
586
+ - Install following individual plugin flow (Β§8.2)
587
+ - Each plugin gets its own entry in `openpackage.yml`
588
+
589
+ 4. **Display installation summary**
590
+ - Shows which plugins succeeded/failed
591
+ - Reports errors for any plugins that failed validation or install
592
+
593
+ **Example:**
594
+ ```bash
595
+ # Install from marketplace (prompts for selection)
596
+ opkg install github:anthropics/claude-code
597
+
598
+ πŸ“¦ Marketplace: claude-code-plugins
599
+ Example plugins demonstrating Claude Code plugin capabilities
600
+
601
+ 3 plugins available:
602
+
603
+ ❯ β—― commit-commands
604
+ β—― pr-review-toolkit
605
+ β—― explanatory-output-style
606
+
607
+ Select plugins to install (space to select, enter to confirm):
608
+ ```
609
+
610
+ Result in `openpackage.yml`:
611
+ ```yaml
612
+ packages:
613
+ - name: commit-commands
614
+ git: https://github.com/anthropics/claude-code.git
615
+ subdirectory: plugins/commit-commands
616
+ - name: pr-review-toolkit
617
+ git: https://github.com/anthropics/claude-code.git
618
+ subdirectory: plugins/pr-review-toolkit
619
+ ```
620
+
621
+ ### 9.4 Path-based plugin install
622
+
623
+ Plugins can also be installed from local paths (useful for development/testing):
624
+
625
+ ```bash
626
+ # Install from local plugin directory
627
+ opkg install ./my-plugin
628
+
629
+ # Install from local marketplace (prompts for selection)
630
+ opkg install ./my-marketplace
631
+ ```
632
+
633
+ Path-based plugin dependencies are tracked in `openpackage.yml` with `path:` source:
634
+ ```yaml
635
+ packages:
636
+ - name: my-plugin
637
+ path: ./my-plugin
638
+ ```
639
+
640
+ **Notes:**
641
+ - Plugins are **not converted to registry packages** - git/path source remains authoritative
642
+ - Plugin manifest is validated but transformation is **in-memory only**
643
+ - Standard OpenPackage operations (`save`, `add`, `apply`) work on path-sourced plugins if the source is mutable
644
+ - See [Git Sources](git-sources.md) for complete git install behavior including subdirectory syntax
235
645
 
236
646
  ---
237
647
 
238
- ## 8. Compatibility and non-goals
648
+ ## 10. Compatibility and non-goals
239
649
 
240
650
  - **Non-goal**: Emulate every nuance of npm’s `install` / `update` / `dedupe` behavior.
241
651
  - Instead, aim for a **small, orthogonal core**:
242
- - `package.yml` declares intent.
243
- - `save`/`pack` manage versions & WIPs.
652
+ - `openpackage.yml` declares intent.
653
+ - `pack` publishes versioned snapshots; `install` materializes versions into the workspace.
244
654
  - `install` materializes **latest-in-range** from local+remote.
245
655
 
246
656
  - **Compatibility goal**:
247
657
  - A user coming from npm should be able to reason as:
248
- - β€œ`package.yml` is like `package.json` dependencies.”
658
+ - β€œ`openpackage.yml` is like `package.json` dependencies.”
249
659
  - β€œ`opkg install` is like `npm install`: it installs & upgrades within ranges.”
250
- - β€œTo change which major I target, I edit the version in `package.yml`, not the CLI.”
660
+ - β€œTo change which major I target, I edit the version in `openpackage.yml`, not the CLI.”
251
661
 
252
662