@solidrt/cli 0.0.48 → 0.0.50

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.
package/AGENTS.md CHANGED
@@ -24,7 +24,11 @@ bundled `flux` runtime, not on Bun. Invoke via `bunx srt <command>`.
24
24
  separately (server distributes code; clients on other devices connect to it).
25
25
  - `bunx srt run src/index.tsx --capture out.script.json` - records keydown/keyup
26
26
  from every connected client into one script file (written on client
27
- disconnect), for replaying later with `render --script`.
27
+ disconnect), for replaying later with `render --script`. The file is JSON
28
+ Lines and hand-authorable - the exact shape (`after` ms, `type`, `key`,
29
+ `device`) is in `docs/cli.md` under `--capture`. For probing app state
30
+ without a display, `-- <args...>` reaches the app as `flux:process` argv
31
+ (also `docs/cli.md`), which is often simpler than scripting input.
28
32
 
29
33
  ## Verifying without a display (headless / CI / agent box)
30
34
 
@@ -35,7 +39,8 @@ Two reliable checks that need no GUI:
35
39
  renders offscreen via EGL and writes `frame-NNNNNN.png`. This actually
36
40
  proves the app renders. Combine with `--fps`/`--duration` (defaults
37
41
  1280x720, 60fps, 1s). No display needed: rendering uses SDL's offscreen
38
- driver (falling back to a hidden window where EGL cannot go headless).
42
+ driver, or alloy's own EGL pbuffer where that driver cannot go headless
43
+ (see the ANGLE gotcha below).
39
44
 
40
45
  Also headless: the bundled flux runtime runs a plain `.js` file directly -
41
46
  `node_modules/@solidrt/<platform>/flux script.js` (e.g.
@@ -49,12 +54,38 @@ behavior in isolation.
49
54
  - `--size` is physical output pixels: layout runs at exactly that size
50
55
  (display scale is pinned to 1), so frames are identical on every machine.
51
56
  - Run from the project directory. There is no `bunx --cwd` flag.
57
+ - On ANGLE stacks (Windows, macOS) SDL's offscreen driver cannot go
58
+ headless (no EGL device enumeration), so `render` there builds its own
59
+ EGL pbuffer context behind SDL's dummy video driver instead; the log says
60
+ "using a headless EGL context". If that also fails it renders into a
61
+ hidden window, which needs an interactive desktop session (fails under a
62
+ service, in Session 0, or over SSH-only). Verified headless on Linux
63
+ (Wayland) and the pbuffer path on Windows from a desktop session; a
64
+ non-interactive Windows session and macOS are unverified.
65
+
66
+ ## Sessions (parallel dev servers on one machine)
67
+
68
+ - `-s <N>` / `--session <N>` (default 0) picks the dev server: port
69
+ `34884 + N`. Valid on `run`, `server`, `client`, `mcp`. `srt run -s1` is a
70
+ second, fully independent dev setup; `srt client -s1 -c2` attaches another
71
+ client to it.
72
+ - `-c <N>` / `--client <N>` picks the client data tree, defaulting to the
73
+ session number. (`--compile` gave its short to `--client`.)
74
+ - Dev state lives in `~/.solidrt/`: `servers/<port>/` holds each server's tunnel
75
+ key and `live.json` (the registry record MCP resolution reads, removed at
76
+ exit), `clients/client<M>/` the client trees (srt passes
77
+ `--data-root ~/.solidrt/clients` to every locally spawned client).
78
+ - A server run serves the project it was started in; `load` outside the
79
+ project root is refused. Restart the server in another project to switch.
80
+ - `srt mcp` needs no port: each tool call resolves the server serving the
81
+ project the bridge runs in (registry match + probe); `-s`/`--port` pin it.
52
82
 
53
83
  ## Dev server proxies (when clients on other devices need your machine's data)
54
84
 
55
85
  - `--proxy-http` - route `fetch` through the dev server; responses cached in
56
- `.srt-data/http-cache.db` (delete the file to clear).
86
+ `.srt-data/http-cache.db` in the project root (delete the file to clear).
57
87
 
58
88
  ## REPL (opened by `run`/`server`)
59
89
 
60
90
  `load <file>`, `reload [n]`, `stop [n]`, `list`, `!<cmd>`, `quit`/`exit`.
91
+ `load` is bound to the project root the server was started in.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/cli",
3
- "version": "0.0.48",
3
+ "version": "0.0.50",
4
4
  "license": "MIT",
5
5
  "author": "Antoine van Wel",
6
6
  "type": "module",
@@ -19,25 +19,26 @@
19
19
  "@babel/core": "^7.0.0",
20
20
  "@babel/plugin-syntax-jsx": "^7.0.0",
21
21
  "@babel/preset-typescript": "^7.0.0",
22
+ "@clack/prompts": "^1.7.0",
22
23
  "@jridgewell/remapping": "^2.3.0",
23
24
  "@jridgewell/trace-mapping": "^0.3.25",
24
25
  "@modelcontextprotocol/sdk": "^1.29.0",
25
- "babel-preset-solid": "2.0.0-beta.31",
26
+ "babel-preset-solid": "2.0.0-rc.0",
26
27
  "bonjour-service": "^1.4.0",
27
28
  "qrcode-generator": "^2.0.4",
28
29
  "zod": "^4.4.3"
29
30
  },
30
31
  "optionalDependencies": {
31
- "@solidrt/darwin-arm64": "0.0.48",
32
- "@solidrt/linux-arm64-gnu": "0.0.48",
33
- "@solidrt/linux-x64-gnu": "0.0.48",
34
- "@solidrt/win32-x64-msvc": "0.0.48"
32
+ "@solidrt/darwin-arm64": "0.0.50",
33
+ "@solidrt/linux-arm64-gnu": "0.0.50",
34
+ "@solidrt/linux-x64-gnu": "0.0.50",
35
+ "@solidrt/win32-x64-msvc": "0.0.50"
35
36
  },
36
37
  "peerDependencies": {
37
38
  "typescript": "^7"
38
39
  },
39
40
  "devDependencies": {
40
- "@solidrt/flux-types": "0.0.48",
41
+ "@solidrt/flux-types": "0.0.50",
41
42
  "@types/babel__core": "^7.20.5",
42
43
  "@types/bun": "latest"
43
44
  }
@@ -280,6 +280,46 @@ work stops being free" below is where it does not. Rules, in order of leverage:
280
280
  snapshot instead of re-rasterizing. A window shader's output is invisible
281
281
  to get_snapshot and every other MCP tool; `srt render` is the only way to
282
282
  see it (Run / verify below).
283
+ 7. `flux:wasm` is not the fast lane. It runs a pure interpreter (wasmi, no
284
+ JIT), so tight typed compute gains a small constant factor over the same
285
+ loop in JavaScript, nowhere near browser wasm speed, and every host call
286
+ costs marshalling. Use it to ship one compiled module across every target
287
+ without native binaries, not to speed up per-frame work; for that, rules
288
+ 1-2 (move it to the GPU, cut property writes) are the leverage.
289
+
290
+ ### Isolates: heavy work off the JS thread
291
+
292
+ A long synchronous computation (a big parse, a simulation step, a blocking
293
+ `flux:ffi`/`flux:wasm` call) freezes rendering and input for its duration.
294
+ Move it into an isolate module: a file whose first statement is the
295
+ `"use isolate"` directive runs in a second runtime on its own thread, and
296
+ main calls its exports as async functions.
297
+
298
+ ```ts
299
+ // src/worker.ts
300
+ "use isolate"
301
+ export function crunch(data: Uint8Array): number { /* ... */ }
302
+ ```
303
+
304
+ ```ts
305
+ // src/index.tsx
306
+ import { isolate } from "flux:isolate"
307
+ import type * as Worker from "./worker"
308
+ let worker = isolate<typeof Worker>("worker") // id = path from src/, no extension
309
+ let n = await worker.crunch(bytes) // main keeps rendering meanwhile
310
+ ```
311
+
312
+ The bundler builds each such module as its own bundle and ships it with the
313
+ app (dev pushes and `srt pack` alike). Rules: main may only `import type`
314
+ from an isolate module (a value import is a build error); arguments and
315
+ results are copies (numbers, strings, byte buffers, arrays, plain objects -
316
+ no functions, no class instances); the child has the non-gui `flux:*`
317
+ modules only, so it never touches the render tree; module state persists
318
+ between calls and each `isolate()` call is its own instance. An
319
+ `async function*` export is a stream: `for await (let p of worker.progress())`
320
+ pulls one item per step (progress, ticks, a subscription), `break` ends it in
321
+ the isolate, and streams never block plain calls. Full contract:
322
+ node_modules/@solidrt/flux-types/modules/isolate.d.ts.
283
323
 
284
324
  ### Where GPU work stops being free
285
325
 
@@ -346,7 +386,8 @@ up to the frame period, because work outside the frame call is not in them.
346
386
  (future launcher/window naming) with no storage meaning.
347
387
  - `bunx srt pack src/index.tsx` builds a single-file executable;
348
388
  `bunx srt pack --folder src/index.tsx` writes the flat app folder
349
- (runner + manifest.json + bundle + assets/) to `dist/`.
389
+ (runner + manifest.json + bundle + assets/, plus the runner's GL
390
+ libraries on Windows and macOS) to `dist/`.
350
391
 
351
392
  ## Run / verify
352
393
 
@@ -374,8 +415,11 @@ its tools over guessing at runtime state:
374
415
 
375
416
  - list_clients: connected app clients, their platform and runtime
376
417
  capabilities, plus the server's `entry` (the app source it serves) and
377
- `projectDir` - check entry matches the app you think you are driving; the
378
- dev port is fixed, so another project's server answers on the same port.
418
+ `projectDir` - check entry matches the app you think you are driving. Each
419
+ tool call finds the dev server currently serving this project (by its
420
+ project root), so a server restarted on another port/session is followed
421
+ automatically; no server serving this project is an error, not a wrong
422
+ server.
379
423
  Each client also lists `queries`, the dev-tool query kinds its runtime
380
424
  answers - check it before planning verification against a mixed-version
381
425
  fleet (no "input" = the client predates send_input)
@@ -394,7 +438,7 @@ its tools over guessing at runtime state:
394
438
  re-fetch ids and restart cursors
395
439
  - get_stats: fps, CPU/memory, frame phase timings, setProperty rate, plus
396
440
  layout-activity counters for the last rebuild (nodes, measureCalls,
397
- paraShapes, dirtiedNodes, cacheGets/cacheHits) - when layoutMs looks
441
+ paraShapes/wordHits, dirtiedNodes, cacheGets/cacheHits) - when layoutMs looks
398
442
  wrong, these say whether the cost is text shaping, invalidation breadth,
399
443
  or a defeated layout cache (healthy incremental rebuilds show a near-100%
400
444
  cacheHits rate). reusedPerSec/skippedPerSec are the demand gate's visible
@@ -10,12 +10,13 @@
10
10
  "android": "srt client --android"
11
11
  },
12
12
  "dependencies": {
13
- "@solidrt/core": "0.0.48",
14
- "@solidrt/components": "0.0.48"
13
+ "@solidrt/core": "0.0.50",
14
+ "@solidrt/components": "0.0.50",
15
+ "@solidrt/3d": "0.0.50"
15
16
  },
16
17
  "devDependencies": {
17
- "@solidrt/cli": "0.0.48",
18
- "@solidrt/flux-types": "0.0.48",
18
+ "@solidrt/cli": "0.0.50",
19
+ "@solidrt/flux-types": "0.0.50",
19
20
  "typescript": "^7"
20
21
  }
21
22
  }
package/server/main.ts CHANGED
@@ -74,16 +74,16 @@ async function handleInternal(req: FluxRequest, server: Server, path: string): P
74
74
 
75
75
  switch (path) {
76
76
  case "/__internal__/reload": {
77
- // { message, clients?, latch?, sourceDir?, projectDir?, map? }: send
78
- // `message` (a full client-protocol message, built by srt) to the listed
79
- // client ids, or to all when omitted. `latch` keeps it for late-joining
80
- // clients (code reloads latch, one-shot bytecode loads do not);
81
- // `sourceDir` moves the file-serving root and `projectDir` the /assets/
82
- // root (repl `load`); `map` is the bundle's sourcemap for log remapping,
83
- // replaced on every reload (absent means none).
77
+ // { message, clients?, latch?, sourceDir?, map? }: send `message` (a
78
+ // full client-protocol message, built by srt) to the listed client ids,
79
+ // or to all when omitted. `latch` keeps it for late-joining clients
80
+ // (code reloads latch, one-shot bytecode loads do not); `sourceDir`
81
+ // moves the file-serving root (repl `load`; the project root - and with
82
+ // it the /assets/ root - is fixed for the life of the run); `map` is
83
+ // the bundle's sourcemap for log remapping, replaced on every reload
84
+ // (absent means none).
84
85
  let body = await req.json()
85
86
  if (typeof body.sourceDir === "string") state.sourceDir = body.sourceDir
86
- if (typeof body.projectDir === "string") state.projectDir = body.projectDir
87
87
  // Keep the rebuild entry in sync when `load` moves it, so a later MCP
88
88
  // reload bundles the newly loaded file, not the launch-time one.
89
89
  if (typeof body.entry === "string") state.config.entry = body.entry
@@ -211,6 +211,12 @@ serve({
211
211
  if (path === "/assets" || path.startsWith("/assets/")) {
212
212
  return handleFiles(req, path, state.projectDir)
213
213
  }
214
+ // Isolate bundles are build outputs, not project files: srt (and the
215
+ // rebuild here) write them under .srt-data/isolates/, and the manifest
216
+ // lists them as isolates/<id>.js.
217
+ if (path.startsWith("/isolates/")) {
218
+ return handleFiles(req, path, config.cacheDir)
219
+ }
214
220
  return handleFiles(req, path, state.sourceDir)
215
221
  },
216
222
  websocket: {
package/server/rebuild.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { command } from "flux:subprocess"
2
+ import { dir, file } from "flux:fs"
2
3
  import { state } from "./state"
3
4
 
4
5
  // Server-owned "rebuild and push": the single place the running app is rebuilt
@@ -45,13 +46,20 @@ export async function rebuildAndBroadcast(): Promise<string | null> {
45
46
  return `Rebuild failed:\n${stderr.trim()}`
46
47
  }
47
48
 
48
- // bundle-cli writes one JSON object { code, map, manifest } to stdout.
49
- let bundle: { code?: string; map?: string | null; manifest?: string }
49
+ // bundle-cli writes one JSON object { code, map, manifest, isolates } to stdout.
50
+ let bundle: { code?: string; map?: string | null; manifest?: string; isolates?: { id: string; code: string }[] }
50
51
  try {
51
52
  bundle = JSON.parse(typeof result.stdout === "string" ? result.stdout : "")
52
53
  } catch {
53
54
  return "Rebuild failed: unreadable bundler output"
54
55
  }
56
+ // Isolate bundles are manifest assets clients fetch from our /isolates/
57
+ // route (served from cacheDir), so they must be on disk before the push.
58
+ for (let isolate of bundle.isolates ?? []) {
59
+ let path = `${config.cacheDir}/isolates/${isolate.id}.js`
60
+ await dir(path.slice(0, path.lastIndexOf("/"))).create()
61
+ await file(path).write(isolate.code)
62
+ }
55
63
  state.currentMap = bundle.map ?? null
56
64
  let text = JSON.stringify(buildReload(bundle.code ?? "", bundle.manifest))
57
65
  state.currentReload = text
package/server/state.ts CHANGED
@@ -29,7 +29,7 @@ export type Config = {
29
29
  cache: boolean
30
30
  /** Directory holding the proxy cache db (the project-local .srt-data). */
31
31
  cacheDir: string
32
- /** Directory holding .srt-tunnel-key (the project root). */
32
+ /** Directory holding tunnel.key (the server's ~/.solidrt/servers/<port>/ folder). */
33
33
  keyDir: string
34
34
  /** Destination for captured key events, or unset when off. */
35
35
  capture?: string
package/server/tunnel.ts CHANGED
@@ -15,15 +15,16 @@ import { printQr } from "./qr"
15
15
  // the handshake instead of desyncing.
16
16
  export const TUNNEL_PROTOCOL = "solidrt-dev/0"
17
17
 
18
- // The persisted identity file, at the project root. Delete it to rotate the
19
- // tunnel's identity (which invalidates any old ticket).
20
- const KEY_FILE = ".srt-tunnel-key"
18
+ // The persisted identity file, in the server's ~/.solidrt/servers/<port>/ folder
19
+ // (keyDir): the tunnel identity belongs to the server, not to any project it
20
+ // serves. Delete it to rotate the identity (which invalidates any old ticket).
21
+ const KEY_FILE = "tunnel.key"
21
22
 
22
23
  /**
23
24
  * Bind the tunnel endpoint and print its ticket (text + QR). The endpoint is
24
25
  * kept stable across restarts so a paired client can re-dial the old ticket
25
26
  * without re-scanning: the UDP port is pinned to the dev server's port, and the
26
- * secret key is persisted in <keyDir>/.srt-tunnel-key (generated on first
27
+ * secret key is persisted in <keyDir>/tunnel.key (generated on first
27
28
  * run). Both are needed - a moving port or a fresh key each start would change
28
29
  * the ticket. Stable across restarts on the same network only; a new machine IP
29
30
  * still stales the ticket's addresses (that is the discovery/off-LAN story).
package/src/args.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { parseArgs } from "node:util"
2
2
  import { resolve } from "node:path"
3
+ import { clientsRoot } from "./dev-dir"
3
4
 
4
5
  // Everything after a bare "--" is the app's argument vector, kept out of
5
6
  // parseArgs (which would fold it into positionals) and forwarded verbatim to
@@ -14,8 +15,9 @@ export let { values, positionals } = parseArgs({
14
15
  options: {
15
16
  dev: { type: "boolean", short: "d", default: false },
16
17
  minify: { type: "boolean", short: "m", default: false },
17
- compile: { type: "boolean", short: "c", default: false },
18
+ compile: { type: "boolean", default: false },
18
19
  flux: { type: "boolean", short: "f", default: false },
20
+ session: { type: "string", short: "s" },
19
21
  folder: { type: "boolean", default: false },
20
22
  stdout: { type: "boolean", default: false },
21
23
  output: { type: "string", short: "o" },
@@ -28,33 +30,51 @@ export let { values, positionals } = parseArgs({
28
30
  tunnel: { type: "boolean", default: false },
29
31
  stats: { type: "boolean", default: false },
30
32
  "data-root": { type: "string" },
31
- client: { type: "string" },
33
+ client: { type: "string", short: "c" },
32
34
  server: { type: "string" },
33
35
  port: { type: "string" },
34
36
  android: { type: "boolean", default: false },
35
37
  device: { type: "string" },
36
- template: { type: "string", short: "t" },
38
+ with: { type: "string" },
37
39
  },
38
40
  allowPositionals: true,
39
41
  })
40
42
 
41
- // Storage flags for a locally spawned client, forwarded only when given: with
42
- // no --data-root the client resolves its platform pref path (see
43
- // lattice/src/storage.rs); --client <N> selects the client<N>/ tree under
44
- // either root. An explicit root is passed absolute because the client chdirs
45
- // into its app sandbox at startup.
43
+ export const DEFAULT_DEV_PORT = 0x8844
44
+
45
+ // The session number: -s/--session <N> selects the dev server (port
46
+ // DEFAULT_DEV_PORT + N, see dev-server.ts resolveDevPort) and the default
47
+ // client slot. Resolved at load, like the port.
48
+ function resolveSession(): number {
49
+ let raw = values.session
50
+ if (raw === undefined) return 0
51
+ let n = Number(raw)
52
+ if (!/^\d+$/.test(raw) || DEFAULT_DEV_PORT + n > 65535) {
53
+ console.error(
54
+ `Invalid --session value "${raw}": expected a non-negative integer with ${DEFAULT_DEV_PORT} + N at most 65535`,
55
+ )
56
+ process.exit(1)
57
+ }
58
+ return n
59
+ }
60
+ export let session = resolveSession()
61
+
62
+ // Storage flags for a locally spawned client. Dev client trees live in
63
+ // ~/.solidrt/clients/client<M>/, reached through --data-root so the client
64
+ // runtime keeps its single pref-path default rule (see lattice/src/storage.rs
65
+ // and okf/backlog/parallel-dev-servers.md); an explicit --data-root wins. The
66
+ // client slot defaults to the session number, so each session gets its own
67
+ // tree with a single flag. Roots are passed absolute because the client
68
+ // chdirs into its app sandbox at startup.
46
69
  export function clientStorageArgs(): string[] {
47
- let args: string[] = []
48
70
  let root = values["data-root"]
49
- if (root) args.push("--data-root", resolve(root))
50
- let client = values.client
51
- if (client !== undefined) {
52
- if (!/^\d+$/.test(client)) {
53
- console.error(`Invalid --client value "${client}": expected a non-negative integer`)
54
- process.exit(1)
55
- }
56
- args.push("--client", client)
71
+ let args = ["--data-root", root ? resolve(root) : clientsRoot()]
72
+ let client = values.client ?? String(session)
73
+ if (!/^\d+$/.test(client)) {
74
+ console.error(`Invalid --client value "${client}": expected a non-negative integer`)
75
+ process.exit(1)
57
76
  }
77
+ args.push("--client", client)
58
78
  return args
59
79
  }
60
80
 
@@ -111,6 +131,17 @@ export function validateArgs() {
111
131
  if (values.port !== undefined && command !== "run" && command !== "server" && command !== "mcp") {
112
132
  usage("srt <run|server|mcp> --port <N> (--port is only valid with the run, server and mcp commands)")
113
133
  }
134
+ // --session selects a dev server (and the default client slot), so it is
135
+ // valid wherever a dev server is started, attached to, or resolved.
136
+ if (
137
+ values.session !== undefined &&
138
+ command !== "run" &&
139
+ command !== "server" &&
140
+ command !== "client" &&
141
+ command !== "mcp"
142
+ ) {
143
+ usage("srt <run|server|client|mcp> -s <N> (--session is only valid with the run, server, client and mcp commands)")
144
+ }
114
145
  }
115
146
 
116
147
  export function printUsage() {
@@ -128,10 +159,11 @@ Commands:
128
159
  mcp MCP server (stdio) exposing the running dev server to coding agents
129
160
 
130
161
  init options:
131
- -t, --template <name> Start from a named template (skips the interactive picker)
162
+ --with <pkg,pkg> Extensions to include, e.g. @solidrt/components,@solidrt/3d (skips the picker)
132
163
 
133
164
  run/server options:
134
- --port <N> Dev server port (default: 34884)
165
+ -s, --session <N> Session number: dev server on port 34884+N, client slot N (default: 0)
166
+ --port <N> Dev server port (default: 34884 + session)
135
167
  --proxy-http Route fetch calls through the dev server (HTTP cache enabled)
136
168
  --capture <file> Record connected clients' key events to a script file
137
169
  --tunnel Accept ticket-paired clients through the p2p tunnel
@@ -140,22 +172,25 @@ run/server options:
140
172
  run/client options:
141
173
  --size <WxH> Window size (default: 1280x720)
142
174
  --stats Show the debug stats overlay (FPS, memory, frame timings)
143
- --data-root <dir> Client data root (default: the platform pref path)
144
- --client <N> Client number: its own data tree under the data root (default: 0)
175
+ --data-root <dir> Client data root (default: ~/.solidrt/clients)
176
+ -c, --client <N> Client number: its own data tree under the data root (default: the session)
145
177
 
146
178
  client options:
147
- --server <host[:port]> Connect to a dev server at this address (default port: 34884)
179
+ -s, --session <N> Connect to this session's dev server on this machine
180
+ (127.0.0.1:34884+N); without it, start on the connect screen
181
+ --server <host[:port]> Connect to a dev server at this address (default port: 34884 + session)
148
182
  --android Install and launch the client on a connected Android device
149
183
  --device <serial> Target a specific adb device by serial or unique prefix
150
184
 
151
185
  mcp options:
152
- --port <N> Port of the dev server to attach to (default: 34884)
186
+ -s, --session <N> Attach to the dev server of this session (default: resolve by project)
187
+ --port <N> Port of the dev server to attach to (default: resolve by project)
153
188
 
154
189
  bundle options:
155
190
  -f, --flux Bundle for the bare Flux runtime, without SolidJS (entry must be .ts|.js)
156
191
  -d, --dev Use development build of SolidJS (default: production)
157
192
  -m, --minify Minify the output
158
- -c, --compile Compile to bytecode
193
+ --compile Compile to bytecode
159
194
  -o, --output <name> Output filename
160
195
  --stdout Write bundle to stdout
161
196
 
package/src/bundle-cli.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  // Standalone bundler entry, spawned by the dev server (a flux process) as a
2
2
  // Bun subprocess to rebuild the app on an MCP-triggered reload. flux cannot call
3
3
  // Bun.build, so the server shells out to this. Params arrive as one JSON
4
- // argument; one JSON object { code, map } goes to stdout and diagnostics to
5
- // stderr. On a build failure it exits non-zero with an empty stdout.
4
+ // argument; one JSON object { code, map, manifest, isolates } goes to stdout
5
+ // and diagnostics to stderr. On a build failure it exits non-zero with an
6
+ // empty stdout.
6
7
 
7
8
  import { bundleWith, type BundleOptions } from "./bundler"
8
9