mlx-bun 0.2.0 → 0.4.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 (433) hide show
  1. package/README.md +71 -588
  2. package/docs/README.md +94 -0
  3. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  4. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  5. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  6. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  7. package/docs/archive/investigations/openjarvis-fit.md +198 -0
  8. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  9. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  10. package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
  11. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  12. package/docs/archive/planning/release-notes-v0.3.0.md +35 -0
  13. package/docs/design/batching.md +1841 -0
  14. package/docs/design/decode-speed-program.md +2346 -169
  15. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  16. package/docs/design/generic-model-support.md +655 -334
  17. package/docs/design/kv-cache.md +824 -0
  18. package/docs/design/orpo-training.md +673 -1239
  19. package/docs/design/speculative-decoding.md +1990 -0
  20. package/docs/design/turboquant.md +2212 -0
  21. package/docs/design/unified-engine-frontier-plan.md +1833 -727
  22. package/docs/design/web-chat-redesign.md +666 -1083
  23. package/docs/planning/PRODUCT_ROADMAP.md +50 -1
  24. package/docs/planning/release-notes-v0.4.0.md +45 -0
  25. package/docs/planning/video-series.md +2 -2
  26. package/docs/reference/benchmarks.md +3613 -0
  27. package/docs/reference/cli.md +434 -160
  28. package/docs/reference/distribution.md +328 -182
  29. package/docs/reference/environment.md +398 -0
  30. package/docs/reference/glossary.md +39 -0
  31. package/docs/reference/library-api.md +566 -168
  32. package/docs/reference/memory.md +227 -64
  33. package/docs/reference/models.md +113 -6
  34. package/docs/reference/server-api.md +944 -429
  35. package/docs/reference/server-config.md +740 -338
  36. package/docs/reference/training.md +393 -254
  37. package/docs/reference/troubleshooting.md +158 -0
  38. package/package.json +9 -4
  39. package/src/audio/decode.ts +2 -2
  40. package/src/audio/features.ts +2 -2
  41. package/src/backends/mlx/assistant-target.ts +46 -0
  42. package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
  43. package/src/backends/mlx/autoregressive.ts +108 -0
  44. package/src/backends/mlx/batch-group.ts +1790 -0
  45. package/src/backends/mlx/cache-attachment.ts +67 -0
  46. package/src/backends/mlx/cache-layout.ts +31 -0
  47. package/src/backends/mlx/checkpoint-state.ts +53 -0
  48. package/src/backends/mlx/continuation-persistence.ts +106 -0
  49. package/src/backends/mlx/continuation-request.ts +43 -0
  50. package/src/backends/mlx/continuation.ts +77 -0
  51. package/src/backends/mlx/diffusion.ts +39 -0
  52. package/src/backends/mlx/draft-target.ts +32 -0
  53. package/src/backends/mlx/evaluation.ts +105 -0
  54. package/src/backends/mlx/fill-append.ts +45 -0
  55. package/src/backends/mlx/full-kv-row-append.ts +32 -0
  56. package/src/backends/mlx/full-kv-row-donor.ts +54 -0
  57. package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
  58. package/src/backends/mlx/gateway-binding.ts +130 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/kv-codec.ts +9 -0
  61. package/src/backends/mlx/kv-maintenance.ts +133 -0
  62. package/src/backends/mlx/kv-tensor-rows.ts +212 -0
  63. package/src/backends/mlx/memory-client.ts +189 -0
  64. package/src/backends/mlx/methods.ts +90 -0
  65. package/src/backends/mlx/model-prompt.ts +164 -0
  66. package/src/backends/mlx/model-serving.ts +79 -0
  67. package/src/backends/mlx/prefill-cohort.ts +89 -0
  68. package/src/backends/mlx/prefill-rows.ts +200 -0
  69. package/src/backends/mlx/prefill.ts +33 -0
  70. package/src/backends/mlx/projected-context-rows.ts +72 -0
  71. package/src/backends/mlx/request-policy.ts +20 -0
  72. package/src/backends/mlx/request-state-policy.ts +41 -0
  73. package/src/backends/mlx/rollback.ts +89 -0
  74. package/src/backends/mlx/row-sampling.ts +49 -0
  75. package/src/backends/mlx/serial-executor.ts +242 -0
  76. package/src/backends/mlx/speculative-group.ts +359 -0
  77. package/src/backends/mlx/speculative-round.ts +161 -0
  78. package/src/backends/mlx/speculative.ts +114 -0
  79. package/src/backends/mlx/state-rows.ts +104 -0
  80. package/src/backends/mlx/state-views.ts +46 -0
  81. package/src/backends/mlx/target-layout-capability.ts +35 -0
  82. package/src/backends/mlx/text-engine.ts +73 -0
  83. package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
  84. package/src/cli.ts +66 -58
  85. package/src/client.ts +66 -0
  86. package/src/config.ts +21 -4
  87. package/src/contracts/completion.ts +16 -0
  88. package/src/contracts/execution.ts +60 -0
  89. package/src/contracts/generation.ts +103 -0
  90. package/src/contracts/host.ts +7 -0
  91. package/src/contracts/jobs.ts +66 -0
  92. package/src/contracts/pi-provider.ts +30 -0
  93. package/src/contracts/pi.ts +259 -0
  94. package/src/contracts/prefix-cache.ts +23 -0
  95. package/src/contracts/resources.ts +25 -0
  96. package/src/contracts/sampling.ts +23 -0
  97. package/src/contracts/scheduling.ts +45 -0
  98. package/src/contracts/tsconfig.json +14 -0
  99. package/src/diffusion/diffusion-generate.ts +218 -153
  100. package/src/embed.ts +1 -1
  101. package/src/engine/admission.ts +59 -0
  102. package/src/engine/cancellation.ts +38 -0
  103. package/src/engine/engine.ts +56 -0
  104. package/src/engine/execution-coordinator.ts +70 -0
  105. package/src/engine/execution-plan.ts +53 -0
  106. package/src/engine/resources.ts +53 -0
  107. package/src/engine/scheduler.ts +72 -0
  108. package/src/engine/session.ts +247 -0
  109. package/src/eval/README.md +44 -1
  110. package/src/eval/kl.ts +236 -3
  111. package/src/eval/reference-logits.ts +207 -0
  112. package/src/eval/runner.ts +8 -96
  113. package/src/fill/echo-index.ts +188 -0
  114. package/src/fill/fill-session.ts +452 -0
  115. package/src/fill/proposal.ts +68 -0
  116. package/src/fill/schema-rows.ts +506 -0
  117. package/src/fill/tool-boundary.ts +103 -0
  118. package/src/fit.ts +30 -16
  119. package/src/generate.ts +709 -417
  120. package/src/grammar.ts +12 -7
  121. package/src/harness-pi.ts +14 -33
  122. package/src/hub-rest.ts +4 -4
  123. package/src/index.ts +7 -0
  124. package/src/inference/denoising.ts +17 -0
  125. package/src/inference/draft-acceptance.ts +41 -0
  126. package/src/inference/draft-output.ts +49 -0
  127. package/src/inference/graph.ts +33 -0
  128. package/src/inference/prefill.ts +39 -0
  129. package/src/inference/rollback.ts +7 -0
  130. package/src/jobs/db.ts +4 -0
  131. package/src/jobs/index.ts +2 -0
  132. package/src/jobs/job-entry.ts +12 -12
  133. package/src/jobs/runner.ts +98 -13
  134. package/src/jobs/task-client.ts +19 -0
  135. package/src/jobs/types.ts +2 -58
  136. package/src/kv-scheme.ts +70 -12
  137. package/src/kv-store.ts +177 -63
  138. package/src/lab/README.md +18 -0
  139. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  140. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  141. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +5 -5
  142. package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
  143. package/src/{model → lab/paged-kv}/paged-kv.ts +32 -15
  144. package/src/library.ts +40 -0
  145. package/src/lora.ts +18 -0
  146. package/src/media-fetch.ts +1 -1
  147. package/src/memory/article.ts +1 -1
  148. package/src/memory/chunk.ts +1 -1
  149. package/src/memory/model.ts +30 -169
  150. package/src/memory/prompts.ts +1 -1
  151. package/src/memory/rest.ts +1 -1
  152. package/src/memory/schedule.ts +1 -1
  153. package/src/memory/stages.ts +4 -1
  154. package/src/memory/vault.ts +1 -3
  155. package/src/mlx/array.ts +11 -11
  156. package/src/mlx/compile.ts +12 -2
  157. package/src/mlx/ffi.ts +58 -11
  158. package/src/mlx/materialize.ts +23 -0
  159. package/src/mlx/metal-kernel.ts +10 -11
  160. package/src/mlx/ops.ts +33 -13
  161. package/src/mlx/quantized-rows.ts +36 -0
  162. package/src/mlx/token-bitmask.ts +52 -0
  163. package/src/mlx/turboquant-kv-decode.ts +82 -0
  164. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  165. package/src/mlx/turboquant-ops.ts +33 -3
  166. package/src/mlx/turboquant-tables.ts +2 -2
  167. package/src/model/artifact-identity.ts +73 -0
  168. package/src/model/batched-kv.ts +235 -0
  169. package/src/model/batched-mask.ts +20 -6
  170. package/src/model/batched-quant.ts +9 -3
  171. package/src/model/batched-quantized-kv.ts +144 -0
  172. package/src/model/batched-rotating-quant.ts +78 -17
  173. package/src/model/batched-rotating-state.ts +76 -0
  174. package/src/model/batched-rotating.ts +65 -23
  175. package/src/model/batched-row-storage.ts +52 -0
  176. package/src/model/batched-ssm.ts +52 -0
  177. package/src/model/batched-turboquant-kv.ts +93 -0
  178. package/src/model/compiled-decode.ts +8 -2
  179. package/src/model/decoded-kv-donor.ts +12 -0
  180. package/src/model/delayed-quantized-kv.ts +72 -0
  181. package/src/model/delayed-rotating-quantized-kv.ts +93 -0
  182. package/src/model/delayed-turboquant-kv.ts +55 -0
  183. package/src/model/diffusion-gemma.ts +8 -8
  184. package/src/model/factory.ts +76 -33
  185. package/src/model/fingerprint.ts +1 -1
  186. package/src/model/flash-attention.ts +3 -3
  187. package/src/model/full-prefill-padding.ts +56 -0
  188. package/src/model/full-prefill-row.ts +105 -0
  189. package/src/model/gemma4-base.ts +179 -80
  190. package/src/model/gemma4.ts +40 -32
  191. package/src/model/generated/gemma4-12b.ts +6 -3
  192. package/src/model/generated/gemma4-26b.ts +6 -3
  193. package/src/model/generated/gemma4-e4b.ts +6 -3
  194. package/src/model/glm52-cache.ts +80 -4
  195. package/src/model/glm52-dsa.ts +13 -9
  196. package/src/model/glm52-memory.ts +1 -1
  197. package/src/model/glm52-mla.ts +12 -6
  198. package/src/model/glm52.ts +19 -40
  199. package/src/model/implementation.ts +69 -0
  200. package/src/model/kv-attention-view.ts +67 -0
  201. package/src/model/minicpm5.ts +17 -15
  202. package/src/model/profile.ts +12 -2
  203. package/src/model/qwen-append.ts +12 -0
  204. package/src/model/qwen-conv.ts +52 -0
  205. package/src/model/qwen3-delta-state.ts +74 -0
  206. package/src/model/qwen3-delta.ts +59 -36
  207. package/src/model/qwen3_5-checkpoint.ts +164 -0
  208. package/src/model/qwen3_5.ts +202 -78
  209. package/src/model/rotating-kv-donor.ts +35 -0
  210. package/src/model/rotating-kv-layout.ts +262 -0
  211. package/src/model/rotating-row-transaction.ts +35 -0
  212. package/src/model/speculative-rotating-kv.ts +101 -0
  213. package/src/model/ssm-prefill-padding.ts +39 -0
  214. package/src/model/support.ts +1 -1
  215. package/src/model/trellis-balanced-scatter.ts +51 -0
  216. package/src/model/trellis-linear.ts +672 -0
  217. package/src/model/trellis-shared-m.ts +151 -0
  218. package/src/model/trellis-shared-scatter.ts +144 -0
  219. package/src/model/trellis-splitk-prefill.ts +158 -0
  220. package/src/model/trellis-tiled-prefill.ts +136 -0
  221. package/src/model/trellis-vector-expand.ts +62 -0
  222. package/src/model/trellis-wide-prefill.ts +94 -0
  223. package/src/model/turboquant-codec.ts +83 -0
  224. package/src/model/universal/dense.ts +15 -14
  225. package/src/model/universal/modules.ts +8 -1
  226. package/src/native-pack.ts +6 -5
  227. package/src/pi-provider.ts +6 -64
  228. package/src/pi-web.ts +8 -315
  229. package/src/preflight.ts +31 -15
  230. package/src/prompt-cache.ts +110 -69
  231. package/src/quantize/allocator.ts +1 -1
  232. package/src/quantize/config-writer.ts +10 -3
  233. package/src/quantize/rotate.ts +4 -4
  234. package/src/quantize/trellis.ts +586 -0
  235. package/src/responses.ts +28 -1
  236. package/src/runtime-config.ts +18 -4
  237. package/src/sampler.ts +40 -29
  238. package/src/serve/batch-scheduler.ts +8 -1671
  239. package/src/serve/chat-request.ts +391 -0
  240. package/src/serve/chat-stage.ts +195 -0
  241. package/src/serve/checkpoint-identity.ts +64 -0
  242. package/src/serve/completion-executor.ts +15 -7
  243. package/src/serve/discovery-routes.ts +12 -13
  244. package/src/serve/generation-gateway.ts +183 -213
  245. package/src/serve/http.ts +159 -0
  246. package/src/serve/inference-request.ts +79 -0
  247. package/src/serve/isolate.ts +297 -105
  248. package/src/serve/lab-routes.ts +3 -0
  249. package/src/serve/lane-registry.ts +2 -1
  250. package/src/serve/model-admin-routes.ts +7 -5
  251. package/src/serve/model-binding.ts +43 -0
  252. package/src/serve/model-host.ts +511 -0
  253. package/src/serve/openai-wire.ts +103 -0
  254. package/src/serve/parent-application.ts +56 -0
  255. package/src/serve/pipeline.ts +33 -0
  256. package/src/serve/preparation.ts +33 -0
  257. package/src/serve/request-plan.ts +23 -18
  258. package/src/serve/request-prep.ts +344 -0
  259. package/src/serve/response-lease.ts +24 -0
  260. package/src/serve/responses-client.ts +69 -0
  261. package/src/serve/session-completion-engine.ts +110 -0
  262. package/src/serve/session-search.ts +1 -1
  263. package/src/serve/static-routes.ts +5 -5
  264. package/src/serve/text-completion-stage.ts +104 -0
  265. package/src/serve/token-streams.ts +519 -0
  266. package/src/server.ts +335 -2711
  267. package/src/spec/assistant-rows.ts +92 -0
  268. package/src/spec/assistant-source.ts +31 -55
  269. package/src/spec/cache-identity.ts +22 -0
  270. package/src/spec/deepspec-rows.ts +29 -0
  271. package/src/spec/deepspec-source.ts +16 -14
  272. package/src/spec/dflash-source.ts +36 -12
  273. package/src/spec/drafter.ts +153 -142
  274. package/src/spec/dspark/ab-stats.ts +3 -3
  275. package/src/spec/dspark/calibration.ts +2 -2
  276. package/src/spec/dspark/deepspec-module.ts +97 -122
  277. package/src/spec/dspark/generate-dflash.ts +2 -2
  278. package/src/spec/dspark/generate.ts +2 -2
  279. package/src/spec/dspark/loader.ts +1 -1
  280. package/src/spec/dspark/module-dflash.ts +129 -172
  281. package/src/spec/dspark/module.ts +3 -3
  282. package/src/spec/dspark/quantize-drafter.ts +1 -1
  283. package/src/spec/generate.ts +1 -1
  284. package/src/spec/glm52-mtp-graph.ts +29 -0
  285. package/src/spec/glm52-mtp-rows.ts +132 -0
  286. package/src/spec/glm52-mtp-source.ts +54 -137
  287. package/src/spec/glm52-mtp-state.ts +33 -0
  288. package/src/spec/ngram-source.ts +93 -21
  289. package/src/spec/projected-draft-rows.ts +73 -0
  290. package/src/spec/qwen-mtp-module.ts +171 -0
  291. package/src/spec/qwen-mtp-rows.ts +219 -0
  292. package/src/spec/qwen-mtp-source.ts +147 -195
  293. package/src/spec/qwen-mtp-state.ts +30 -0
  294. package/src/spec/serve-loop.ts +201 -201
  295. package/src/spec/source.ts +110 -13
  296. package/src/spec/two-model-rows.ts +61 -0
  297. package/src/spec/two-model.ts +44 -102
  298. package/src/ssd-cache.ts +99 -19
  299. package/src/ssd-durability.ts +36 -20
  300. package/src/tool-call.ts +51 -14
  301. package/src/train/flash-cce.ts +2 -2
  302. package/src/train/forward.ts +6 -0
  303. package/src/train/loss.ts +1 -1
  304. package/src/train/prefix-shared.ts +5 -1
  305. package/src/train/segmented.ts +5 -3
  306. package/src/train/trainer.ts +6 -6
  307. package/src/vision/prompt.ts +1 -1
  308. package/src/vision/qwen3vl-tower.ts +52 -10
  309. package/src/web/app.html +1 -1
  310. package/src/web/app.js +62 -60
  311. package/src/web/src/adapters-panel.ts +3 -3
  312. package/src/web/src/assistant.ts +2 -36
  313. package/src/web/src/chat.ts +4 -4
  314. package/src/web/src/composer.ts +4 -4
  315. package/src/web/src/hub.ts +1 -1
  316. package/src/web/src/markdown.ts +0 -0
  317. package/src/web/src/memory-panel.ts +1 -1
  318. package/src/web/src/model-picker.ts +1 -1
  319. package/src/web/src/palette.ts +1 -1
  320. package/src/web/src/protocol.ts +3 -39
  321. package/src/web/src/sessions.ts +1 -1
  322. package/src/web/src/ui-catalog.ts +4 -18
  323. package/src/web-assets.ts +47 -0
  324. package/src/weights.ts +55 -9
  325. package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
  326. package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
  327. package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
  328. package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
  329. package/docs/archive/investigations/hlg-ab.html +0 -34
  330. package/docs/archive/investigations/hlg-explorer.html +0 -238
  331. package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
  332. package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
  333. package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
  334. package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
  335. package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
  336. package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
  337. package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
  338. package/docs/archive/investigations/hlg-report.html +0 -262
  339. package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
  340. package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  341. package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
  342. package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
  343. package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
  344. package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
  345. package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
  346. package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
  347. package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
  348. package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
  349. package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  350. package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
  351. package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
  352. package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
  353. package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  354. package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  355. package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  356. package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  357. package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  358. package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  359. package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  360. package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
  361. package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
  362. package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
  363. package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
  364. package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
  365. package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  366. package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
  367. package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
  368. package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
  369. package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
  370. package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
  371. package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  372. package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
  373. package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  374. package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  375. package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  376. package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  377. package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  378. package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  379. package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
  380. package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  381. package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
  382. package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  383. package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  384. package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  385. package/docs/archive/mlx-bun-lab-report.html +0 -275
  386. package/docs/archive/wwdc-mlx-bun.html +0 -848
  387. package/docs/design/adapters-end-to-end.md +0 -205
  388. package/docs/design/batching-perf-path.md +0 -255
  389. package/docs/design/batching-v2-plan.md +0 -529
  390. package/docs/design/bucketing-stage.md +0 -197
  391. package/docs/design/compat-cli-surface-design.md +0 -230
  392. package/docs/design/docs-reorg-plan.md +0 -165
  393. package/docs/design/dspark-serving-program.md +0 -371
  394. package/docs/design/dspark-speculative-decoding.md +0 -318
  395. package/docs/design/grammar-spec-batching-integration.md +0 -301
  396. package/docs/design/memory-inference-path.md +0 -422
  397. package/docs/design/memory-synthesis.md +0 -287
  398. package/docs/design/memory-system.md +0 -237
  399. package/docs/design/mlx-lm-serving-execution-seam.md +0 -81
  400. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  401. package/docs/design/omlx-adoption-map.md +0 -98
  402. package/docs/design/orpo-dynamic-lambda.md +0 -220
  403. package/docs/design/orpo-future-enhancements.md +0 -340
  404. package/docs/design/paged-kv-cache.md +0 -214
  405. package/docs/design/parallel-slots.md +0 -567
  406. package/docs/design/parity-tier-dag.md +0 -161
  407. package/docs/design/repo-cleanup-plan.md +0 -231
  408. package/docs/design/runtime-isolation.md +0 -263
  409. package/docs/design/segmented-backward-training.md +0 -543
  410. package/docs/design/spec-decode-larger-targets.md +0 -229
  411. package/docs/design/ssd-kv-cold-tier.md +0 -415
  412. package/docs/design/structured-output.md +0 -484
  413. package/docs/design/tauri-desktop-app.md +0 -127
  414. package/docs/design/the-dreaming-master-plan.md +0 -445
  415. package/docs/design/turboquant-kv.md +0 -235
  416. package/docs/design/turboquant-weights.md +0 -467
  417. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  418. package/docs/design/web-chat-beat-matrix.md +0 -315
  419. package/docs/design/write-pipeline-entity.md +0 -468
  420. package/docs/planning/IDEAS.md +0 -69
  421. package/docs/reference/embedding.md +0 -197
  422. package/docs/reference/features-matrix.md +0 -101
  423. package/docs/reference/orpo-quickstart.md +0 -135
  424. package/src/flags.ts +0 -11
  425. /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
  426. /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
  427. /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
  428. /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
  429. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  430. /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
  431. /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
  432. /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
  433. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -1,209 +1,355 @@
1
- # Distributing mlx-bun via Homebrew (signed + notarized)
2
-
3
- The end-to-end runbook for shipping a `brew install`-able, Developer-ID
4
- signed and notarized mlx-bun. Companion to [embedding.md](./embedding.md)
5
- (which covers the Tauri/Electron *sidecar* layout); this doc is the
6
- *standalone CLI* distribution.
7
-
8
- ## What ships
9
-
10
- A single **self-contained** bundle — the whole `dist/` directory in one
11
- tarball (~73 MB compressed, ~228 MB installed):
12
-
13
- | file | what |
14
- |---|---|
15
- | `mlx-bun` | the CLI/server (`bun build --compile`), ~61 MB |
16
- | `libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib` | MLX native runtime |
17
- | `libmlx_bun_expert_io.dylib` | bounded native expert-streaming helper required by direct Colibri GLM-5.2 |
18
- | `mlx-bun-frame-extract` | AVFoundation frame-extraction sidecar for video input (darwin-native codecs, the afconvert doctrine) |
19
- | `mlx.metallib` | Metal kernels (~150 MB — the bulk) |
20
- | pi assets | `photon_rs_bg.wasm`, `theme/`, `assets/`, `export-html/`, `native/`, `package.json`, `CHANGELOG.md` |
21
-
22
- We ship everything in the bottle (rather than the npm/sidecar approach of
23
- a tiny binary that downloads the native pack on first run) so that
24
- `brew install` is the *only* network step and the entire bundle is signed
25
- and notarized as one artifact.
26
-
27
- ## One-time Apple setup
28
-
29
- 1. **Developer ID Application certificate** — Xcode → Settings → Accounts →
1
+ # Distributing mlx-bun — build, sign, notarize, publish
2
+
3
+ The canonical ship doc. Everything here is what the scripts do, not a
4
+ recipe to type by hand: [scripts/build-binary.sh](../../scripts/build-binary.sh)
5
+ builds the bundle, [scripts/release-binary.sh](../../scripts/release-binary.sh)
6
+ signs and notarizes it, [scripts/publish-release.sh](../../scripts/publish-release.sh)
7
+ pushes it to every channel. If this doc and a script disagree, the script
8
+ is right and this doc has drifted.
9
+
10
+ Three install channels ship from one release:
11
+
12
+ | channel | what the user gets | network step |
13
+ |---|---|---|
14
+ | Homebrew (`brew install joshuarossi/tap/mlx-bun`) | the signed + notarized self-contained bundle | one tarball, via brew |
15
+ | Direct download (`curl -fsSL https://mlx-bun.dev/install.sh \| sh`) | the same bundle, into `~/.mlx-bun` | one tarball, via curl |
16
+ | npm / bunx (`bunx mlx-bun`, `bun install -g mlx-bun`) | a launcher + the TypeScript source, run under the user's Bun | the package, then the native runtime pack on first run |
17
+
18
+ [docs/reference/distribution.md](./distribution.md) covers the *sidecar* use of the same bundle
19
+ inside a Tauri/Electron app; the build and signing facts it relies on are
20
+ documented here.
21
+
22
+ ## What ships in the bundle
23
+
24
+ `scripts/build-binary.sh [outdir]` (default `dist/`) produces one relocatable
25
+ directory. The release tarball is the directory's *contents* (no parent
26
+ dir), ~80 MB compressed; `mlx.metallib` is the bulk of the installed size.
27
+
28
+ | file | what | built from |
29
+ |---|---|---|
30
+ | `mlx-bun` | the CLI/server, `bun build --compile src/cli.ts` | our code + Bun |
31
+ | `libmlxc.dylib` | mlx-c; load command rewritten to `@loader_path/libmlx.dylib` | `/opt/homebrew/lib/libmlxc.dylib` (override `MLXC_DYLIB`) |
32
+ | `libmlx.dylib`, `libjaccl.dylib`, `mlx.metallib` | MLX core, its distributed-comm dependency, the Metal kernels (libmlx loads the metallib from its own directory) | `/opt/homebrew/opt/mlx/lib` (override `MLX_LIB_DIR`) |
33
+ | `libmlx_bun_expert_io.dylib` | bounded streamed-expert I/O for GLM-5.2 MoE serving | [scripts/build-expert-io.sh](../../scripts/build-expert-io.sh) |
34
+ | `mlx-bun-frame-extract` | AVFoundation frame-extraction helper for video input (a Mach-O *executable*, not a dylib) | [scripts/build-frame-extract.sh](../../scripts/build-frame-extract.sh) → `swiftc -O src/native/frame_extract.swift` |
35
+ | `photon_rs_bg.wasm` | pi's image codec, resolved next to the executable by the web chat's `read`-on-image path (best-effort; pi degrades to a text note without it) | `node_modules/@silvia-odwyer/photon-node` (override `PHOTON_WASM`) |
36
+ | `theme/*.json`, `assets/*.png`, `export-html/`, `package.json`, `CHANGELOG.md`, `native/darwin/prebuilds/<arch>/darwin-modifiers.node` | assets the embedded pi **terminal** (`mlx-bun pi`) resolves by path: themes, startup art, `/export` template, version banner + changelog, native modifier-key helper (degrades if absent) | `node_modules/@earendil-works/pi-coding-agent/dist`, `pi-tui` |
37
+
38
+ pi's JavaScript itself is bundled into the executable by `bun build
39
+ --compile`; only what pi resolves *by path* rides along. For a Bun
40
+ single-file executable pi computes its package dir as
41
+ `dirname(process.execPath)`, so every asset sits flat next to `mlx-bun`.
42
+
43
+ After copying, the script runs `install_name_tool` (`libmlxc` →
44
+ `@loader_path/libmlx.dylib`; `@loader_path` rpath on `libmlx` for `libjaccl`)
45
+ and **ad-hoc signs** every Mach-O it touched — arm64 requires a valid
46
+ signature after any load-command rewrite. Ad-hoc is only for local runs; the
47
+ release script replaces it (below).
48
+
49
+ The C and Swift helpers target macOS 14.0 by default, matching the package's
50
+ minimum macOS version. `MACOSX_DEPLOYMENT_TARGET` can override that build
51
+ target. Verify the MLX libraries' deployment targets as well when replacing
52
+ the bundled runtime; compiling our helpers for 14.0 cannot lower a dependency's
53
+ minimum OS version.
54
+
55
+ **Build-time smoke.** The script then runs `mlx-bun --version`, `--help`, and
56
+ `ls`, and compiles [scripts/verify-binary-pi.ts](../../scripts/verify-binary-pi.ts)
57
+ into a *sibling* binary inside the same directory so `process.execPath` points
58
+ at the bundle exactly as it does for the real binary. That smoke builds the
59
+ same headless pi session `src/pi-web.ts` builds (against an unreachable
60
+ provider — a provider error is the success signal), exercises the photon
61
+ image path, calls `initTheme` (load-bearing for `mlx-bun pi`; a failure here
62
+ fails the smoke), and loads the native modifier helper. No model, no server.
63
+ A live streaming turn is the one thing it cannot cover.
64
+
65
+ **Runtime resolution.** The binary finds its native runtime in this order
66
+ (`src/mlx/ffi.ts`, mirrored by `nativeRuntimeDir()` in `src/native-pack.ts`):
67
+ `MLX_BUN_LIBMLXC` env → `libmlxc.dylib` beside the executable → the
68
+ native-pack cache (`~/Library/Caches/mlx-bun/native-v<ver>-<arch>/`) →
69
+ `/opt/homebrew/lib` → `/usr/local/lib`. The expert helper resolves
70
+ `MLX_BUN_EXPERT_IO_DYLIB` → beside the executable → the cache
71
+ (`src/expert-io.ts`); the frame extractor resolves `MLX_BUN_FRAME_EXTRACT` →
72
+ beside the executable → the cache → `dist-native/` → compile-on-demand from
73
+ `src/native/` via the Xcode CLT (`src/vision/video-frames.ts`). The whole
74
+ directory can be moved or renamed; nothing references an absolute path after
75
+ the fixups. Bun realpaths `execPath`, so a symlink to `mlx-bun` (Homebrew's
76
+ `bin/`, the installer's `~/.local/bin`) resolves back to the bundle.
77
+
78
+ ## One-time machine setup
79
+
80
+ Releases are inherently local: signing and notarization need the Developer
81
+ ID certificate and Apple credentials on this Mac, so the publish step is
82
+ local too (no cross-repo CI token, nothing for the tap to drift from). The
83
+ release machine needs:
84
+
85
+ 1. **Build inputs** — Homebrew `mlx` + `mlx-c` (the bundle copies the dylibs
86
+ and metallib from the brew prefixes above), the Xcode command-line tools
87
+ (`swiftc` for the frame extractor, the C toolchain for the expert helper),
88
+ and Bun at or above the floor in `package.json` `engines.bun`.
89
+ 2. **Developer ID Application certificate** — Xcode → Settings → Accounts →
30
90
  your Apple ID → *Manage Certificates…* → **+** → **Developer ID
31
- Application**. Verify:
32
- ```sh
33
- security find-identity -v -p codesigning # shows "Developer ID Application: NAME (TEAMID)"
34
- ```
35
- 2. **Notary credentials** — an App Store Connect **API key** (not the
36
- Developer-portal "Keys" page; not your Apple ID password). Create at
37
- **App Store Connect → Users and Access → Integrations → App Store
38
- Connect API → Team Keys → +** (role: Developer). Download the
39
- `AuthKey_<KEYID>.p8` (one-time download), note the **Key ID** and the
40
- **Issuer ID** (UUID at the top of the page), then:
91
+ Application**. The release script picks the first such identity from
92
+ `security find-identity -v -p codesigning`; override with
93
+ `MLX_BUN_SIGN_IDENTITY`.
94
+ 3. **Notary credentials** — an App Store Connect **API key** (not your Apple
95
+ ID password): App Store Connect → Users and Access → Integrations → App
96
+ Store Connect API → Team Keys → **+** (role: Developer). Download the
97
+ `AuthKey_<KEYID>.p8` (one-time download), note the Key ID and Issuer ID,
98
+ then store them under the profile name the script expects:
41
99
  ```sh
42
100
  xcrun notarytool store-credentials AC_PROFILE \
43
101
  --key ~/.private_keys/AuthKey_<KEYID>.p8 \
44
102
  --key-id "<KEYID>" --issuer "<ISSUER-UUID>"
45
103
  ```
46
- `store-credentials` validates against Apple before saving — success
47
- means notarization auth works.
48
-
49
- ## Release a build
50
-
51
- ```sh
52
- ./scripts/release-binary.sh # version from package.json
53
- # or: ./scripts/release-binary.sh 0.0.4
54
- ```
55
-
56
- This runs [build-binary.sh](../../scripts/build-binary.sh), then:
57
- - signs every nested Mach-O (dylibs, any `.node`) with the hardened
58
- runtime, then the executable with the JIT
59
- [entitlements](../../packaging/entitlements.plist) (JavaScriptCore JITs —
60
- without `allow-jit` the binary is killed on launch);
61
- - notarizes the zipped bundle via `AC_PROFILE` and waits;
62
- - emits `dist-release/mlx-bun-v<ver>-arm64.tar.gz` (+ `.sha256`) and
63
- prints the `version`/`url`/`sha256` for the formula.
64
-
65
- > A flat CLI bundle **cannot be stapled** (`stapler` only handles
66
- > `.app`/`.dmg`/`.pkg`); the notarization ticket lives on Apple's servers.
67
- > Gatekeeper checks it online only when a copy is *quarantined*. brew
68
- > formula installs are **not** quarantined (brew downloads via curl), so
69
- > the binary runs prompt-free regardless — notarization is load-bearing
70
- > only for a direct browser download or a Cask.
71
-
72
- Publish the artifact as a GitHub release whose tag matches the formula url:
73
- ```sh
74
- gh release create v0.0.4 dist-release/mlx-bun-v0.0.4-arm64.tar.gz \
75
- --title "mlx-bun v0.0.4" --notes "..."
76
- ```
77
-
78
- ## The tap
79
-
80
- Homebrew taps must be a repo named `homebrew-<name>`. The canonical tap is
81
- **`joshuarossi/homebrew-tap`** (Homebrew shorthand: `joshuarossi/tap`).
82
-
83
- 1. Create a public repo **`joshuarossi/homebrew-tap`** (one-time).
84
- 2. Copy [packaging/homebrew/mlx-bun.rb](../../packaging/homebrew/mlx-bun.rb)
85
- to `Formula/mlx-bun.rb` in it, updating `version`/`url`/`sha256` from
86
- the release-script output. Commit and push.
87
- 3. Install:
88
- ```sh
89
- brew install joshuarossi/tap/mlx-bun
90
- mlx-bun --version
91
- ```
92
-
93
- `brew audit --strict --new joshuarossi/tap/mlx-bun` before pushing
94
- catches most formula issues; `brew install --build-from-source` +
95
- `brew test` runs the formula's `test do` locally.
96
-
97
- ## Updating (one command)
98
-
99
- Releases must originate on this Mac (signing + notarization need the
100
- Developer ID cert + Apple creds), so the publish step is local too — no
101
- cross-repo CI token to manage, and the tap can't drift out of sync.
102
-
103
- Per release:
104
-
105
- 1. bump `version` in `package.json` and commit;
106
- 2. one shot:
107
- ```sh
108
- PUBLISH=1 ./scripts/release-binary.sh
109
- ```
110
- This builds → signs → notarizes → creates the `v<ver>` GitHub release →
111
- rewrites `version`/`url`/`sha256` in the tap's `Formula/mlx-bun.rb` and
112
- pushes it → mirrors the same fields into
113
- [packaging/homebrew/mlx-bun.rb](../../packaging/homebrew/mlx-bun.rb)
114
- (left staged — commit it).
115
-
116
- Prefer two steps? Run `./scripts/release-binary.sh` to build, eyeball the
117
- artifact, then `./scripts/publish-release.sh` to publish + sync the tap.
118
- Both are idempotent: re-running `publish-release.sh` clobbers the release
119
- asset and no-ops the tap push if nothing changed.
120
-
121
- Users then upgrade with:
122
- ```sh
123
- brew upgrade joshuarossi/tap/mlx-bun
124
- ```
125
-
126
- ## Direct download (stable URL)
104
+ `store-credentials` validates against Apple before saving. Override the
105
+ profile name with `NOTARY_PROFILE`.
106
+ 4. **GitHub** — `gh auth login` with push access to `joshuarossi/mlx-bun`
107
+ (releases) and `joshuarossi/homebrew-tap` (the tap is cloned over https
108
+ and pushed).
109
+ 5. **npm** — a publish token for `mlx-bun` (`.npmrc`; `npm whoami` must
110
+ answer).
111
+ 6. **The tap repo** — `joshuarossi/homebrew-tap` (Homebrew shorthand
112
+ `joshuarossi/tap`) must already contain `Formula/mlx-bun.rb`; the publish
113
+ script rewrites three fields in it and refuses to run if the file is
114
+ missing.
115
+
116
+ ## Per-release flow
117
+
118
+ Exactly what `bun run release` (= `PUBLISH=1 sh scripts/release-binary.sh`)
119
+ does, in order. Steps 1–3 are yours; the rest is the scripts.
120
+
121
+ 1. **Write the notes** at `docs/planning/release-notes-v<ver>.md`. The
122
+ publish script uses it as the GitHub release body (`--notes-file`); if it
123
+ is missing the release is created with a bare title and a warning. After
124
+ the release the file is archived to `docs/archive/planning/` (the
125
+ planning directory holds living docs only).
126
+ 2. **Bump `version` in `package.json`** and commit.
127
+ 3. **Push** so `HEAD == origin/main`. The publish preflight refuses a dirty
128
+ tree or a local HEAD that differs from `origin/main`: the site deploys from
129
+ the push while the binaries are built from the local tree, and the two
130
+ must tell the same story. `RELEASE_SKIP_GIT_CHECK=1` bypasses this for an
131
+ assets-only re-run.
132
+ 4. **Build** — `scripts/build-binary.sh dist` as described above
133
+ (`BUILD_DIR` overrides `dist`). Release builds are arm64-only; the script
134
+ exits on any other host arch.
135
+ 5. **Sign nested code first** — every `*.dylib`, `*.node`, and the
136
+ `mlx-bun-frame-extract` helper, matched by name under the build dir, gets
137
+ `codesign --force --timestamp --options runtime -s "<identity>"`.
138
+ Nested-before-container is required. The metallib, wasm, JSON, and PNG
139
+ assets are data, not code, and are skipped.
140
+ 6. **Sign the executable** with the hardened runtime and
141
+ [scripts/packaging/entitlements.plist](../../scripts/packaging/entitlements.plist):
142
+ - `allow-jit` + `allow-unsigned-executable-memory` — JavaScriptCore JITs;
143
+ under the hardened runtime the binary is killed on launch without them;
144
+ - `disable-library-validation` — required for the Homebrew install.
145
+ brew ad-hoc re-signs bundled dylibs during its relocation pass,
146
+ stripping our team ID off them while leaving the executable
147
+ Developer-ID signed; library validation would then reject the team-ID
148
+ mismatch at `dlopen`. Notarization still passes with it.
149
+ 7. **Verify + smoke** — `codesign --verify --strict`, then
150
+ `dist/mlx-bun --version`. A missing entitlement kills the binary here, not
151
+ in a user's `brew install`.
152
+ 8. **Notarize** — `ditto` the bundle into a zip, `xcrun notarytool submit
153
+ --wait` under the notary profile (Apple's automated scan, typically 1–5
154
+ min), delete the zip. The script greps the output for
155
+ `status: Accepted` and **exits non-zero on anything else**, printing the
156
+ `xcrun notarytool log <submission-id>` command to inspect the rejection.
157
+ `notarytool` itself exits 0 on `Invalid`, so without this gate a rejected
158
+ bundle would reach PUBLISH.
159
+ 9. **Package** — `tar -czf dist-release/mlx-bun-v<ver>-arm64.tar.gz` of the
160
+ bundle contents (only the files that exist from the fixed manifest:
161
+ binary, four dylibs, helper, metallib, wasm, pi assets), plus a `.sha256`
162
+ sidecar. The script prints the `version` / `url` / `sha256` triple for
163
+ the formula. (`OUT_DIR` overrides `dist-release`.) Without `PUBLISH=1` it
164
+ stops here and tells you to run `scripts/publish-release.sh`.
165
+ 10. **GitHub release** (`publish-release.sh`, step 1) — copies the tarball to
166
+ a versionless `mlx-bun-arm64.tar.gz`, then `gh release create v<ver>`
167
+ with both assets and the notes file; if the release already exists the
168
+ assets are re-uploaded with `--clobber` instead.
169
+ 11. **Tap push** (step 2) — clones `joshuarossi/homebrew-tap`, rewrites
170
+ `version` / `url` / `sha256` in `Formula/mlx-bun.rb` with `sed`, commits
171
+ and pushes only if the diff is non-empty.
172
+ 12. **Mirror the formula** (step 3) — the same three fields are rewritten in
173
+ the in-repo source of truth,
174
+ [scripts/packaging/homebrew/mlx-bun.rb](../../scripts/packaging/homebrew/mlx-bun.rb),
175
+ and left **uncommitted** for you.
176
+ 13. **npm publish** (step 4) — `npm view mlx-bun@<ver>`; if that version is
177
+ already live the step is skipped, otherwise `bun publish`. On failure the
178
+ script exits with the retry hint `bun run publish:npm`.
179
+ 14. **Commit the mirrored formula** — the script's closing line:
180
+ `git commit -am "chore(dist): mlx-bun <ver>"`.
181
+
182
+ Two-step variant: run `./scripts/release-binary.sh` alone, eyeball
183
+ `dist-release/`, then `./scripts/publish-release.sh`. Both are idempotent —
184
+ re-running publish clobbers the release assets, no-ops the tap push, and skips
185
+ npm if the version is live. Env overrides: `MLX_BUN_SIGN_IDENTITY`,
186
+ `NOTARY_PROFILE`, `BUILD_DIR`, `OUT_DIR` (release); `OUT_DIR`, `REPO`,
187
+ `TAP_REPO` (publish).
188
+
189
+ For an SSH-driven release, a local keychain unlock may still leave
190
+ `notarytool` reporting `keychainLocked` in the SSH session. The v0.3.0
191
+ release succeeded by running `release-binary.sh` in the M1 Max's local
192
+ Terminal, then `publish-release.sh` over SSH. Both steps used the same clean
193
+ merged source and `OUT_DIR`. Check `npm whoami` from the actual release
194
+ checkout too: a project `.npmrc` can override the user's configuration.
195
+
196
+ ### The notarization lesson (v0.2.0, 2026-08-24)
197
+
198
+ The first v0.2.0 submission came back **Invalid**. The release added
199
+ `mlx-bun-frame-extract`, a Swift executable, to the bundle; the signing step
200
+ matched only `*.dylib` and `*.node`, so the helper reached Apple with the
201
+ build script's ad-hoc signature — no Developer ID, no hardened runtime, no
202
+ timestamp — and notarization rejects any nested Mach-O signed that way. The
203
+ old script also treated `notarytool`'s exit 0 as success, which would have
204
+ let the rejected bundle go on to publish.
205
+
206
+ Two changes, both in `scripts/release-binary.sh`: helper executables are
207
+ matched **by name** in the nested-signing pass (add every new helper there
208
+ when it lands — the manifest in the packaging step is the checklist), and
209
+ the script fails on any status other than `Accepted`. The resubmission was
210
+ accepted and the release shipped the same day.
211
+
212
+ ### Stapling, quarantine, and where notarization matters
213
+
214
+ A flat CLI bundle **cannot be stapled** (`stapler` only handles `.app` /
215
+ `.dmg` / `.pkg`); the notarization ticket lives on Apple's servers, and
216
+ Gatekeeper consults it online only when a copy carries the
217
+ `com.apple.quarantine` xattr. Homebrew's download and the installer's
218
+ `curl` do not set that xattr, so both run prompt-free regardless;
219
+ notarization is load-bearing for a browser-downloaded copy (or a future
220
+ Cask). `xattr -d com.apple.quarantine <file>` is the manual escape hatch for
221
+ a quarantined copy on an offline machine.
222
+
223
+ ## Channel: Homebrew
224
+
225
+ `brew install joshuarossi/tap/mlx-bun`; upgrades with
226
+ `brew upgrade joshuarossi/tap/mlx-bun`. The formula
227
+ ([scripts/packaging/homebrew/mlx-bun.rb](../../scripts/packaging/homebrew/mlx-bun.rb),
228
+ mirrored to the tap by the publish script):
229
+
230
+ - `depends_on arch: :arm64`, `depends_on macos: :sonoma` — bump the macOS
231
+ floor if MLX needs newer;
232
+ - `libexec.install Dir["*"]` then `bin.install_symlink libexec/"mlx-bun"` —
233
+ the whole bundle lands in `libexec`, and the dylibs and pi assets resolve
234
+ next to the executable through Bun's realpath of `execPath`;
235
+ - `test do` asserts `mlx-bun --version` prints the formula version.
236
+
237
+ The formula deliberately ships everything in one tarball rather than the
238
+ npm approach of a small package plus a first-run download, so `brew install`
239
+ is the only network step and the entire bundle is one signed, notarized
240
+ artifact. Before pushing a formula change by hand, `brew audit --strict --new
241
+ joshuarossi/tap/mlx-bun` catches most issues and `brew install
242
+ --build-from-source` + `brew test` runs the `test do` block locally.
243
+
244
+ ## Channel: direct download
127
245
 
128
246
  `publish-release.sh` uploads two assets per release: the versioned tarball
129
- (`mlx-bun-v<ver>-arm64.tar.gz`) **and** a versionless stable copy
130
- (`mlx-bun-arm64.tar.gz`) pinned to `releases/latest`. This lets the
131
- install script target a URL that never changes:
247
+ and a versionless `mlx-bun-arm64.tar.gz`, so `releases/latest` has a URL
248
+ that never changes:
132
249
 
133
250
  ```
134
251
  https://github.com/joshuarossi/mlx-bun/releases/latest/download/mlx-bun-arm64.tar.gz
135
252
  ```
136
253
 
137
- The user-facing install path is the script at
138
- [`website/public/install.sh`](../../website/public/install.sh) (served at
139
- `mlx-bun.dev/install.sh`), which resolves that URL, extracts the bundle, and
140
- links `mlx-bun` onto `PATH`:
141
- ```sh
142
- curl -fsSL https://mlx-bun.dev/install.sh | sh
143
- ```
254
+ The user-facing path is [website/public/install.sh](../../website/public/install.sh)
255
+ (served at `mlx-bun.dev/install.sh`):
144
256
 
145
- Without the script, the same stable URL streams straight to `tar`:
146
257
  ```sh
147
- curl -fsSL https://github.com/joshuarossi/mlx-bun/releases/latest/download/mlx-bun-arm64.tar.gz \
148
- | tar -xz -C /usr/local/bin mlx-bun
258
+ curl -fsSL https://mlx-bun.dev/install.sh | sh
149
259
  ```
150
260
 
151
- Note: **browser downloads and `curl`-to-file** (e.g. `curl -O ...`) are
152
- quarantined by Gatekeeper — macOS sets the `com.apple.quarantine` xattr on
153
- the saved file. The piped one-liner above streams directly to `tar` and
154
- never writes a quarantined file, so it runs without any Gatekeeper prompt.
155
- For the browser/curl-to-file path, the notarization ticket resolves the
156
- Gatekeeper check online; `xattr -d com.apple.quarantine mlx-bun` is the
157
- manual escape hatch if offline.
261
+ It checks for Darwin/arm64, downloads that URL (or a pinned tag via
262
+ `MLX_BUN_VERSION=v<ver>`), extracts the **whole** bundle into
263
+ `MLX_BUN_INSTALL_DIR` (default `~/.mlx-bun`), and symlinks `mlx-bun` into the
264
+ first writable of `~/.local/bin`, `/usr/local/bin`, `/opt/homebrew/bin` —
265
+ or prints the `PATH` line to add. Extract into a directory, never just the
266
+ `mlx-bun` file: the executable alone would fall through to the native-pack
267
+ download on first run and lose the pi terminal's assets.
158
268
 
159
- ## npm / bunx
160
-
161
- mlx-bun is published to npm as `mlx-bun`. Install or run without a
162
- permanent install:
269
+ ## Channel: npm / bunx
163
270
 
164
271
  ```sh
165
- # one-off (no install)
166
- bunx mlx-bun
167
-
168
- # permanent global install
169
- bun install -g mlx-bun
272
+ bunx mlx-bun # one-off, no install
273
+ bun install -g mlx-bun # permanent
170
274
  mlx-bun --version
171
275
  ```
172
276
 
173
- The npm package is a thin launcher (no postinstall hook): it imports
174
- `src/cli.ts` under Bun, which fetches the small (~52 MB compressed,
175
- sha256-verified) native runtime pack — `libmlxc`/`libmlx`/`libjaccl`/
176
- `mlx.metallib` plus `libmlx_bun_expert_io.dylib` — into
177
- `~/Library/Caches/mlx-bun/` on first invocation if
178
- no copy is already resolvable (env / beside the binary / cache /
179
- Homebrew). This is the same npm/sidecar mechanism described above, not
180
- the signed/notarized Homebrew bundle. `bun publish` is already run
181
- automatically and idempotently as step 4 of `PUBLISH=1
182
- ./scripts/release-binary.sh`; run it standalone only as a manual
183
- fallback/retry:
184
-
185
- ```sh
186
- bun publish # manual retry; package.json version must already be bumped
187
- ```
188
-
189
- ### Publishing the first-run native pack
190
-
191
- The npm/bunx path has an independent, versioned release asset. Whenever its
192
- file manifest changes, build and publish it before shipping code that names the
193
- new `NATIVE_PACK_VERSION`:
277
+ The npm package is **source, not a binary**. `package.json` `files[]` ships
278
+ `bin/`, `src/`, `docs/`, `README.md`, `LICENSE`, `THIRD_PARTY_LICENSES.md`;
279
+ `exports["."]` points at `src/index.ts` (the library API), `bin.mlx-bun` at
280
+ [bin/mlx-bun.mjs](../../bin/mlx-bun.mjs). There is no postinstall hook and
281
+ no build step. `scripts/packaging/` is not in `files[]`, so the pi
282
+ adapter extension
283
+ ([scripts/packaging/pi-extensions/mlx-bun-adapter.ts](../../scripts/packaging/pi-extensions/mlx-bun-adapter.ts))
284
+ is installed by copying it from the repo into `~/.pi/agent/extensions/`.
285
+
286
+ **The launcher** is plain `.mjs` so any runtime can parse it before anything
287
+ touches `bun:ffi` / `bun:sqlite`. It exits with an install hint when `Bun` is
288
+ undefined (Node), when `Bun.version` is below `MIN_BUN` (kept equal to
289
+ `engines.bun`), or when the platform is not darwin/arm64; otherwise it
290
+ imports `src/cli.ts`.
291
+
292
+ **First run: the native runtime pack.** Before importing anything that
293
+ `dlopen`s, `src/cli.ts` calls `ensureNativeRuntime()` (`src/native-pack.ts`).
294
+ If no runtime resolves through the order above, it downloads
295
+ `mlx-bun-native-v<ver>-<arch>.tar.gz` from the GitHub release tagged
296
+ `native-v<ver>` (override the URL with `MLX_BUN_NATIVE_PACK_URL`) through the
297
+ same resumable, sha256- and size-verified `downloadOne` path as model
298
+ downloads, extracts it into a staging directory, checks every file in
299
+ `NATIVE_PACK_FILES` is present, and renames it into
300
+ `~/Library/Caches/mlx-bun/native-v<ver>-<arch>/` — a crashed extract never
301
+ leaves a half-populated cache. Dev trees and embedders resolve via
302
+ Homebrew/env or the sidecar and never hit this path.
303
+
304
+ The pack contains the six native files: `libmlxc.dylib`, `libmlx.dylib`,
305
+ `libjaccl.dylib`, `mlx.metallib`, `libmlx_bun_expert_io.dylib`,
306
+ `mlx-bun-frame-extract`. It is **versioned independently** of the package
307
+ (`NATIVE_PACK_VERSION` in `src/native-pack.ts`, not `package.json`), because
308
+ it changes only when MLX or the helper set changes.
309
+
310
+ ### Publishing a new native pack
311
+
312
+ Whenever the pack's file manifest or the MLX runtime changes, publish the pack
313
+ **before** the package release that depends on it — the download 404s until
314
+ the `native-v<ver>` release exists:
194
315
 
195
316
  ```sh
196
- sh scripts/build-native-pack.sh 0.2.0 dist-native
197
- gh release create native-v0.2.0 \
198
- dist-native/mlx-bun-native-v0.2.0-arm64.tar.gz \
199
- dist-native/mlx-bun-native-v0.2.0-arm64.tar.gz.sha256 \
200
- --title "mlx-bun native runtime v0.2.0" \
201
- --notes "Adds the bounded native expert-I/O helper required by direct Colibri GLM-5.2."
317
+ sh scripts/build-native-pack.sh <ver> dist-native
318
+ gh release create native-v<ver> \
319
+ dist-native/mlx-bun-native-v<ver>-arm64.tar.gz \
320
+ dist-native/mlx-bun-native-v<ver>-arm64.tar.gz.sha256 \
321
+ --latest=false --title "mlx-bun native runtime v<ver>" --notes "<what changed>"
202
322
  ```
203
323
 
204
- For v0.2.0 the arm64 archive is 52,307,647 bytes with SHA-256
205
- `9bd3795c5ea8f52b18413501f2d68c32c264a20751302300a08dc04cd67df97c`.
206
- It contains `libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib`,
207
- `mlx.metallib`, and `libmlx_bun_expert_io.dylib`. These values must match
208
- `src/native-pack.ts`; a fresh-cache extraction plus real MLX dlopen and native
209
- expert read is the pre-publish smoke.
324
+ `build-native-pack.sh` stages the same six files with the same
325
+ `install_name_tool` fixups and ad-hoc signatures as the bundle, tars them,
326
+ and prints the three constants to bake into `src/native-pack.ts`:
327
+ `NATIVE_PACK_VERSION`, the arm64 `SHA256`, and the arm64 `SIZE`. Paste them,
328
+ add any new file to `NATIVE_PACK_FILES`, and commit before bumping the
329
+ package. Pre-publish smoke: a fresh-cache extraction plus a real MLX
330
+ `dlopen` (and, when the helpers changed, an expert read or a video decode).
331
+ The pack is ad-hoc signed only — `build-native-pack.sh` never touches a
332
+ Developer ID and nothing notarizes it; it is `dlopen`ed by the user's own Bun
333
+ process, not by our signed executable. Use `--latest=false` so a native pack
334
+ does not replace the application release behind the direct installer's URL.
335
+
336
+ Native pack 0.4.0 was published on 2026-09-08 with MLX 0.32.2 and MLX-C
337
+ `c74db5307cc8ce122f48d97ef951b30578674e7f`. Its six-file macOS 14 archive
338
+ was uploaded from the M1 Max and downloaded again; its checksum matches the
339
+ package manifest. It was published before mlx-bun v0.3.0. Runtime bindings
340
+ match this one C API, and startup checks the linked core version. The old
341
+ runtime and source controls remain separate for benchmark comparisons.
342
+
343
+ CI builds that pinned C wrapper with
344
+ `sh scripts/packaging/build-native-runtime.sh <new-output-directory>` and sets
345
+ `MLX_BUN_LIBMLXC` to its `lib/libmlxc.dylib`. The script verifies the official
346
+ macOS 14 MLX-Metal archive hash and checks out the exact MLX-C commit. It
347
+ extracts native libraries and headers without running Python or compiling
348
+ Metal sources. This also reproduces the native-pack build inputs;
349
+ Homebrew's C wrapper is not the CI runtime.
350
+
351
+ Managed jobs in the compiled binary re-exec that binary through a private job
352
+ entry, with the database/log paths passed in the environment. They do not depend
353
+ on a Bun executable or a TypeScript source tree. The build runs
354
+ `scripts/packaging/verify-jobs.ts` as a compiled smoke: subprocess completion,
355
+ progress persistence and the CLI entry must pass before the bundle is accepted.