@aipoch/open-science 0.0.0-stage → 1.0.1

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/CLI.md ADDED
@@ -0,0 +1,745 @@
1
+ # Open-Science CLI
2
+
3
+ The `open-science` command controls the local Open-Science service and submits research tasks without
4
+ requiring browser interaction.
5
+
6
+ The [release compatibility policy](https://github.com/aipoch/open-science/blob/main/docs/compatibility.md)
7
+ defines the 1.x contract for commands, machine-readable output and exit codes.
8
+
9
+ ## Installation
10
+
11
+ ### Standalone Node package
12
+
13
+ Install the target-specific standalone tarball built with `npm run pack:backend`, using ordinary
14
+ Node >=22.13.0. It includes the backend, Web UI, resources and native dependencies; Electron and
15
+ a graphical display are not required.
16
+
17
+ ```bash
18
+ npm install --global ./aipoch-open-science-VERSION.tgz # Replace VERSION with the downloaded version.
19
+ open-science start --no-open
20
+ open-science url
21
+ ```
22
+
23
+ Linux secure storage requires an unlocked OS vault and user D-Bus session. See the
24
+ [standalone runtime guide](https://github.com/aipoch/open-science/blob/main/docs/standalone-runtime.md)
25
+ for build dependencies, compatibility and desktop-only capabilities.
26
+
27
+ ### Desktop package launchers (including Debian/WSL)
28
+
29
+ Installing the `.deb` package registers `/usr/bin/open-science` automatically. No separate
30
+ desktop Settings interaction or `cli install` command is needed to use the launcher.
31
+ It starts or reuses the bundled ordinary Node backend without opening Electron:
32
+
33
+ ```bash
34
+ sudo apt install ./open-science.deb # Use the downloaded package's actual filename.
35
+ open-science init
36
+ open-science start --no-open
37
+ open-science url
38
+ ```
39
+
40
+ The desktop shortcut continues to launch the application directly. Debian maintains the CLI entry
41
+ through upgrades and removal. Upgrades migrate only the old package-owned system alternative;
42
+ existing user launchers and unrelated manually selected alternatives are preserved. The installer
43
+ reports a conflict instead of overwriting an unmanaged `/usr/bin/open-science` file or symlink.
44
+ The desktop Settings controls manage the optional user launcher, not the
45
+ Debian-owned system entry; remove the Debian package to remove that entry.
46
+
47
+ ### From other application packages
48
+
49
+ Open **Settings > General > Command line tool** in Open-Science and choose **Install command**. This
50
+ adds an `open-science` launcher to your PATH (`~/.local/bin` on macOS and Linux, or a per-user
51
+ directory added to PATH on Windows). The launcher uses the application's bundled runtime, so it does
52
+ not require a separate Node.js installation.
53
+
54
+ If the launcher directory is not yet on PATH, the Settings panel shows the line to add. Open a new
55
+ terminal after updating PATH. Choose **Uninstall command** in the same panel to remove the launcher.
56
+
57
+ ### From npm
58
+
59
+ The lightweight CLI/SDK package requires Node.js 22.5 or later. It controls an existing service.
60
+ To start an independent service, install the standalone artifact (Node >=22.13.0); the lightweight
61
+ package alone does not contain backend resources.
62
+ Install it globally after the package is published:
63
+
64
+ ```bash
65
+ npm install --global @aipoch/open-science
66
+ open-science --help
67
+ ```
68
+
69
+ ### From a source checkout
70
+
71
+ Replace `open-science` in the examples below with:
72
+
73
+ ```bash
74
+ node packages/open-science/cli.mjs
75
+ ```
76
+
77
+ ## Service lifecycle
78
+
79
+ Initialize the local configuration directory from a terminal. This is safe to repeat and does not
80
+ start the desktop application:
81
+
82
+ ```bash
83
+ open-science init
84
+ open-science init --config-root /absolute/path/to/profile --json
85
+ ```
86
+
87
+ `init` prepares the profile directory; the first `start` creates the authenticated service state and
88
+ token. It does not migrate or modify an existing profile beyond creating the directory when needed.
89
+ Use `--profile` as an alias for `--config-root`. Both accept an absolute configuration directory,
90
+ including in packaged distributions.
91
+
92
+ Start the service without opening a browser, check its status, or stop it:
93
+
94
+ ```bash
95
+ open-science start --no-open
96
+ open-science status --json
97
+ open-science stop
98
+ ```
99
+
100
+ To open the Web UI later, request its authenticated URL explicitly:
101
+
102
+ ```bash
103
+ open-science url
104
+ ```
105
+
106
+ `open-science url` is the only command that intentionally prints an authenticated browser URL. Normal
107
+ human-readable, JSON, and JSONL output never includes the local token.
108
+
109
+ Use `--port <port>` to override `OPEN_SCIENCE_WEB_PORT`, or the default port of `44100` when neither is set. `start` discovers the standalone
110
+ Node entry bundled beside the CLI, or `out/backend/index.cjs` in a source checkout. Build the
111
+ source entry with `npm run build:backend` and Web UI with `npm run build:web` first.
112
+ `--app-path` and `OPEN_SCIENCE_APP_PATH` no longer select a hidden Electron backend.
113
+ `--no-sandbox` does not apply to Node startup; existing Notebook/process permissions still apply.
114
+
115
+ An already running Node runtime is reused through authenticated discovery, including one started
116
+ by the desktop. Electron attaches to an existing same-version Node server without adding another
117
+ writer. Quitting a desktop stops only a server it started; a desktop attached to a CLI-started
118
+ server only detaches. Closing a Web tab or SDK connection does not stop the server. Use
119
+ `open-science stop` for an explicit global stop affecting every connected client.
120
+
121
+ `open-science stop` requests an authenticated graceful shutdown and waits for the service to exit. If
122
+ the request cannot be accepted or a dedicated daemon remains alive after the shutdown deadline, the
123
+ command fails without signalling the PID recorded in `web-service.json`; a stale PID may have been
124
+ reused by an unrelated process. The state file is retained for diagnosis and can be replaced by a
125
+ later `open-science start`.
126
+
127
+ Automatic discovery tries the development config directory before the production directory, skipping
128
+ dead or unhealthy candidates until it finds a healthy service. An explicit `--config-root`,
129
+ `OPEN_SCIENCE_CONFIG_ROOT`, or `OPEN_SCIENCE_STORAGE_ROOT` limits discovery to that directory. Live
130
+ unhealthy records are retained; failed authentication never authorizes signalling a recorded PID.
131
+
132
+ `open-science stop --json` prints exactly one result object on success:
133
+
134
+ | `result` | Meaning |
135
+ | --------------------- | ---------------------------------------------------------------------------- |
136
+ | `already-stopped` | No live service record was found. |
137
+ | `daemon-stopped` | The authenticated Node daemon exited (desktop-started or CLI-started). |
138
+ | `web-service-stopped` | Legacy desktop-host protocol only: Web stopped; old desktop remains running. |
139
+
140
+ Among lifecycle commands, `status` and `stop` support `--json`. `start` and `url` reject
141
+ it; run `start --no-open` followed by `status --json` for machine-readable startup status. Errors
142
+ with `--json` are reported on stderr as a JSON error object with a nonzero exit code.
143
+
144
+ ## Readiness checks
145
+
146
+ Inspect the running service without changing runtime, provider, credential, onboarding, or Skill
147
+ settings:
148
+
149
+ ```bash
150
+ open-science doctor --json
151
+ ```
152
+
153
+ The command prints one JSON object. `ready` requires both the selected Agent runtime and active
154
+ provider to be ready. A check is `missing` when its resource is absent and `not_ready` when it is
155
+ configured but unusable; provider failures may include a stable `reason`, such as
156
+ `credential_invalid`.
157
+
158
+ Codex credential inspection checks supported material in the app-owned `auth.json` without launching
159
+ Codex or validating expiry/revocation remotely; historical provider validation remains a separate gate.
160
+
161
+ `checks.skills.enabled` contains the sorted IDs of enabled, available Skills; Skills do not block
162
+ overall readiness. `next` contains stable action codes such as
163
+ `runtime_missing` and `provider_not_ready`, with an additive `argv` recovery command for the Codex bootstrap path. A completed inspection
164
+ exits with code `0` even when `ready` is false; connection and command failures keep the existing
165
+ nonzero CLI error codes.
166
+
167
+ ## First-run setup (Codex)
168
+
169
+ Install the standalone artifact or a desktop package containing the ordinary Node backend first.
170
+ `init` creates a configuration directory only; `--profile` selects an absolute configuration directory.
171
+
172
+ ```bash
173
+ open-science start --no-open
174
+ open-science runtime install codex --json
175
+ open-science codex login
176
+ open-science connector configure literature --openalex-key-env OPENALEX_API_KEY --json
177
+ open-science doctor --json
178
+ open-science project create "First review" --json
179
+ open-science run --project "First review" --skill literature-review \
180
+ --prompt "Review the evidence for the research question in the project context" --wait --jsonl
181
+ ```
182
+
183
+ Place credentials in the named environment variables through your existing secret-management flow.
184
+ Do not put secret values in command arguments. The CLI reads only the variable explicitly named by
185
+ `--api-key-env` or `--openalex-key-env`; it never imports external Codex credentials.
186
+
187
+ For an OpenAI API-key provider instead of subscription login, prepare the runtime and then use:
188
+
189
+ ```bash
190
+ open-science provider add --type official --vendor openai --model gpt-5.4 \
191
+ --api-key-env OPENAI_API_KEY --json
192
+ ```
193
+
194
+ Use a model supported by the installed application's OpenAI catalog. Setup probes that exact model
195
+ before saving its protected credential reference and validation record. This initial command creates
196
+ `cli-openai`; repeating it with the same key and currently selected model revalidates that target.
197
+ If Settings changed the active model, Doctor suggests the selected model; revalidation preserves the
198
+ provider default model and active selection. Different existing credentials,
199
+ providers, or framework selections produce `configuration_conflict`, without overwriting them.
200
+ Later account edits remain in Settings. Other runtime/provider bootstrap combinations are not yet
201
+ supported. Existing run-time selection commands are unchanged.
202
+
203
+ OpenAlex keys are validated before persistence and Literature Graph enablement. Rejected keys or a
204
+ configuration changed during the probe are not saved. A recognized key may still have exhausted
205
+ quota (the existing probe accepts HTTP 429); a successful probe is not a completed literature run.
206
+
207
+ All writes use existing Settings/runtime/credential owners and formats. No onboarding completion
208
+ flag or database migration is added. OS storage remains the default; Linux file storage still
209
+ requires the existing explicit `start --credential-store file` option on every start.
210
+
211
+ `doctor` keeps existing readiness/reason fields. If the daemon is absent, the CLI prints a report
212
+ with `checks.daemon.status: "missing"` and `next: [{ code: "daemon_unavailable", argv: ["start",
213
+ "--no-open"] }]`, exiting 3. This includes a stale state file whose loopback connection is refused; HTTP health
214
+ rejections (including authorization failures) remain errors rather than missing-daemon reports.
215
+ When probing both default profiles, a later refused connection does not hide an earlier HTTP or
216
+ configuration error; a healthy later profile can still be selected. A running-daemon report still exits 0 even when readiness is false.
217
+ Append the same development `--profile` argument when executing a suggested argv in an isolated
218
+ profile. Doctor reports readiness, not a live third-party authorization or research-run guarantee.
219
+
220
+ `bootstrap` SDK requests return `{ ok: true, providerId? }` or `{ ok: false, code }`. Codes are
221
+ `invalid_request` (including unknown model/input), `configuration_conflict`, `runtime_unavailable`,
222
+ `credential_invalid`, or `bootstrap_failed`. The CLI exits nonzero for failures; results never
223
+ include the submitted secret or raw upstream error. Bootstrap/launcher writes require an
224
+ authenticated local connection and are not exposed as research-agent tools.
225
+
226
+ For desktop packages without an automatically registered command, use **Settings > General >
227
+ Command line tool > Install command**. To invoke the bundled ordinary Node CLI directly on macOS:
228
+
229
+ ```bash
230
+ "/Applications/Open-Science.app/Contents/Resources/node-runtime/node" \
231
+ "/Applications/Open-Science.app/Contents/Resources/backend/cli.mjs" start --no-open
232
+ ```
233
+
234
+ The native Settings controls own launcher installation/removal. `cli install`/`cli uninstall` over
235
+ the Node service are unavailable; npm owns standalone launchers. Reinstall historical Electron-as-Node
236
+ launchers in desktop Settings. AppImage launchers retain a private immutable backend/Node cache so
237
+ an independently started server survives the invocation's temporary mount. Existing ownership
238
+ receipts and unrelated executables remain protected.
239
+
240
+ ## Agent runtimes
241
+
242
+ List the supported Agent runtimes and inspect their readiness without exposing executable paths:
243
+
244
+ ```bash
245
+ open-science runtime list
246
+ open-science runtime list --json
247
+ ```
248
+
249
+ ## Upgrading installations
250
+
251
+ Stop the backend before upgrading an installation, then restart it with the same profile.
252
+ Use the installation channel that owns the CLI: Homebrew for a Formula, the new downloaded
253
+ package for deb/rpm or a local npm tarball, or a verified new Release archive in a new directory
254
+ with PATH/the symlink updated. npm registry publication remains deferred.
255
+ The desktop update UI discovers and downloads packages. Automatic replacement remains closed for
256
+ macOS ZIP, Linux AppImage and Debian until each channel passes complete installed-package
257
+ acceptance. Windows automatic installation remains disabled; artifact checks and same-version copy tests do not certify a cross-version upgrade.
258
+ For an accepted channel, use the desktop application's native update UI. A Desktop
259
+ that adopts an orphaned Desktop-launched Runtime can stop it through the normal update gate.
260
+ For a CLI-launched service, explicitly confirm stopping the service and switching to Desktop;
261
+ all connected clients will disconnect, and future Desktop Quit stops the replacement Runtime.
262
+ Cancel keeps the service running. The switch preserves supported configuration and refuses
263
+ unsupported credential/profile settings before stopping. It does not upgrade standalone files.
264
+ Installation recovery may require the original installer when file integrity cannot be verified.
265
+
266
+ ## Codex subscription sign-in
267
+
268
+ Sign the Open-Science Codex profile in from a terminal without opening Settings:
269
+
270
+ ```bash
271
+ open-science codex login
272
+ ```
273
+
274
+ For first-run setup, start the daemon with `open-science start --no-open`. The command prepares
275
+ the managed runtime and app-owned provider, then runs native Codex OAuth device-code authentication. It prints a verification URL and one-time code in the current terminal; open the URL
276
+ on any browser-capable device, enter the code, and keep the terminal open until Codex reports
277
+ success. Credentials are written only to the app-owned
278
+ <code>codex-subscription/auth.json</code> profile.
279
+
280
+ The native login follows the profile's saved Network proxy mode. Manual uses the configured proxy,
281
+ Direct clears inherited proxy variables, and System uses the environment that launched the CLI.
282
+
283
+ When that profile already contains credentials, the command validates and registers them without
284
+ replacing them. Successful validation activates the initial provider; a different active provider is
285
+ never replaced. Start a
286
+ new device-code flow explicitly with:
287
+
288
+ ```bash
289
+ open-science codex login --force
290
+ ```
291
+
292
+ The login command is interactive and intentionally does not support <code>--json</code> or
293
+ <code>--jsonl</code>. Setup and readiness registration use the local daemon; the one-time code stays
294
+ in the terminal process. Already configured profiles can still sign in while the daemon is stopped,
295
+ but must repeat the command with an updated daemon running to register readiness. A running older daemon
296
+ without the bootstrap endpoint also permits this configured native-login path; it cannot register
297
+ provider readiness. An empty profile instead receives `bootstrap_unavailable` with an instruction to
298
+ update and restart the application. HTTP authorization failures do not trigger this fallback.
299
+
300
+ ### AppImage and Node startup
301
+
302
+ The desktop launcher starts ordinary Node. Chromium's `--no-sandbox` option is rejected by
303
+ `open-science start`; it is not a fallback for starting or updating this backend. Desktop
304
+ Chromium launch troubleshooting is separate from CLI service startup.
305
+
306
+ ## Projects
307
+
308
+ Create a project and list the projects available to task runs:
309
+
310
+ ```bash
311
+ open-science project create "Systematic review" \
312
+ --description "Evidence review workspace" \
313
+ --agent-context-file ./agent-context.md \
314
+ --json
315
+ open-science project list --json
316
+ ```
317
+
318
+ Commands that accept `--project` allow either a project ID or an exact project name. The CLI resolves
319
+ a unique display name to its ID before calling the Task API; use the ID when names are duplicated.
320
+
321
+ Project Agent Context contains persistent instructions that are added when Open-Science sets up an
322
+ agent Session. Supply it directly with `--agent-context <text>` or read multiline instructions from a
323
+ strict UTF-8 file with `--agent-context-file <path>`; the two options are mutually exclusive. The
324
+ existing 16,000-character limit applies to both forms.
325
+
326
+ Update Project metadata or replace its Agent Context later using an ID or exact name:
327
+
328
+ ```bash
329
+ open-science project update "Systematic review" \
330
+ --name "Evidence synthesis" \
331
+ --description "Updated evidence review workspace" \
332
+ --agent-context-file ./revised-agent-context.md \
333
+ --json
334
+
335
+ open-science project update <project-id> --clear-agent-context --json
336
+ ```
337
+
338
+ `--name` renames the Project and requires a non-empty value. `--clear-agent-context` is explicit so
339
+ an omitted option keeps the existing value. An update affects
340
+ newly created Sessions and provider Sessions that are set up again after the update. It does not
341
+ rebuild an already attached Session. Project list, create, and update output reports only the boolean
342
+ `hasAgentContext`; Agent Context contents are not returned through the public Task API or CLI output.
343
+
344
+ ### Project Session defaults
345
+
346
+ Inspect or update the configuration copied into each newly created Session:
347
+
348
+ ```bash
349
+ open-science project session-defaults show <project-id> --json
350
+ open-science project session-defaults update <project-id> \
351
+ --provider anthropic --model claude-sonnet-4-5 --reasoning-effort high \
352
+ --approval-profile auto --auto-review --memory --delegation allow \
353
+ --enable-compute-host ssh:cluster-a --compute-host ssh:cluster-a --json
354
+ ```
355
+
356
+ Updates use the Project's current `updatedAt` value as a compare-and-swap revision. They fail on a
357
+ concurrent Project edit instead of overwriting it. Use the corresponding `--clear-*` option to
358
+ remove an optional default, or `--clear-compute-hosts` to remove both enabled and selected Compute
359
+ Hosts. Omitted options are preserved.
360
+
361
+ The precedence for a new Session is explicit `run` options, then Project Session defaults, then
362
+ application settings, then the provider-owned default. Defaults are snapshotted into the new
363
+ Session; changing them never rewrites an existing Session.
364
+
365
+ ## Run a task
366
+
367
+ Provide a prompt directly, read it from a UTF-8 file, or pipe it through stdin:
368
+
369
+ ```bash
370
+ open-science run --project "Systematic review" --prompt "Summarize the evidence" --wait
371
+ open-science run --project <project-id> --prompt-file ./task.md --wait --json
372
+ open-science run --project <project-id> --cwd ./research --prompt-file ./task.md --wait --json
373
+ printf '%s\n' "Summarize the evidence" | open-science run --project <project-id> --wait --json
374
+ ```
375
+
376
+ Use repeatable `--compute-host <provider-id>` options to select Compute Host execution targets for
377
+ the Session:
378
+
379
+ ```bash
380
+ open-science run --project <project-id> --prompt-file ./task.md \
381
+ --compute-host ssh:cluster-a --compute-host ssh:cluster-b --wait --json
382
+ ```
383
+
384
+ On a new Session, `--enable-compute-host` adds Available hosts, `--compute-host` enables and selects
385
+ its explicit list, and `--clear-compute-hosts` overrides Project defaults with empty Enabled and
386
+ Selected lists. With `--session`, `--compute-host` replaces the selected target pool and enables any
387
+ newly named hosts without disabling other Available hosts. Existing-Session runs reject
388
+ `--enable-compute-host` and `--clear-compute-hosts`; use `session config update` for those access
389
+ changes. Omitting every Compute Host option preserves both access and selection. SDK and Task API
390
+ callers can explicitly send an empty `computeHostIds` array to clear Selected while preserving
391
+ Enabled hosts. JSON output uses the server's compatibility-named
392
+ `preferredComputeHostIds` authority result, not a copy inferred from the command line.
393
+
394
+ When the selection is non-empty, the agent is instructed to run tool-backed task work on one of
395
+ those hosts and not silently fall back to local execution or another Available Compute Host. Pure answers
396
+ and lightweight orchestration do not require remote execution. Each provider ID must refer to a
397
+ host already configured in Open-Science. This option does not create a host, configure SSH or
398
+ credentials, probe a connection, or pin scratch storage.
399
+
400
+ `--cwd <path>` selects an externally owned working directory for the Session. The CLI resolves a
401
+ relative path from the directory where the command is invoked. Open-Science then resolves the real
402
+ path, verifies that it exists, is a directory, and is readable and writable, and persists that
403
+ canonical path on a newly created Session. Open-Science does not take ownership of or remove an
404
+ external working directory. Without `--cwd`, Open-Science allocates its usual managed workspace.
405
+
406
+ The working directory is a Session boundary, not a per-Run override. When `--session` and `--cwd`
407
+ are used together, the requested path must resolve to the Session's recorded working directory. A
408
+ different, missing, or otherwise invalid recorded directory is rejected; it is not migrated,
409
+ replaced, or repaired by the Run request.
410
+
411
+ Without `--wait`, the command returns as soon as the run starts. Use the returned `id` and `sessionId`
412
+ to poll its state:
413
+
414
+ ```bash
415
+ open-science run --project <project-id> --prompt-file ./task.md --json
416
+ open-science run status <run-id> --json
417
+ open-science run cancel <run-id> --json
418
+ open-science session status <session-id> --json
419
+ ```
420
+
421
+ Use `--timeout-ms <milliseconds>` with `--wait` to bound how long the client waits. A timeout stops the
422
+ CLI wait and returns exit code `1`; it does not cancel the run, which can still be inspected with
423
+ `open-science run status <run-id>`. Add `--cancel-on-timeout` to explicitly cancel the server run after
424
+ the timeout; the command still reports the original timeout and returns exit code `1`. Explicit
425
+ cancellation waits for provider work and application finalization to drain, and preserves partial
426
+ output and successfully finalized artifacts. When the `ask` approval profile needs permission,
427
+ human-readable output directs the user to approve the request in Open-Science Desktop or the Web UI.
428
+
429
+ Pass an existing session ID to continue a conversation. Approval profiles are `ask`, `auto`, and
430
+ `full`; `--skill` is repeatable:
431
+
432
+ ```bash
433
+ open-science run \
434
+ --project <project-id> \
435
+ --session <session-id> \
436
+ --prompt-file ./follow-up.md \
437
+ --approval-profile auto \
438
+ --skill literature-review \
439
+ --skill citation-check \
440
+ --wait \
441
+ --json
442
+ ```
443
+
444
+ For a new Session, an explicit approval profile overrides Project Session defaults, then the saved global
445
+ default; only when all are absent does it fall back to `ask`. Resumed Sessions retain their saved profile unless explicitly changed. For unattended execution, explicitly add
446
+ `--permission-prompts none`. This keeps the selected approval profile and existing grants;
447
+ it denies any remaining request that would require a person. `auto` can still require approval,
448
+ and `full` does not answer questions or approve Plans on the user's behalf.
449
+
450
+ ```bash
451
+ open-science run --project <project-id> --prompt-file ./task.md \
452
+ --approval-profile auto --permission-prompts none --wait --jsonl
453
+ ```
454
+
455
+ This option applies only to this Run and its delegated work. It is not a saved Session or Project
456
+ preference. Ordinary questions are declined, and generating a Plan that requires approval is
457
+ rejected; combining it with `--plan-first` fails before starting work. The agent can use an already
458
+ authorized alternative or report that it could not finish. A completed Run means the agent finished
459
+ its turn, not that every requested operation succeeded. JSONL events include declined tool results;
460
+ inspect those and the final output when deciding whether the task achieved its goal.
461
+
462
+ The CLI checks host support before starting an unattended Run. An older daemon without the
463
+ `permission-prompts-none` capability returns `unsupported_capability`; update the host rather than
464
+ silently running a task that might wait for a person. Omitting the option retains existing behavior,
465
+ including Desktop/Web approval for unresolved ordinary permissions. There are no ordinary
466
+ `permission list/show/approve` CLI commands. `--return-on-attention` only covers Plan approval.
467
+
468
+ ### Execution controls
469
+
470
+ The run command exposes five provider-neutral controls:
471
+
472
+ ```bash
473
+ open-science run \
474
+ --project "Systematic review" \
475
+ --prompt-file ./task.md \
476
+ --plan-first \
477
+ --auto-review \
478
+ --memory \
479
+ --specialist literature-reviewer \
480
+ --delegation deny \
481
+ --wait \
482
+ --return-on-attention \
483
+ --json
484
+ ```
485
+
486
+ - `--plan-first` marks this turn as Plan First. The Run remains running while its generated Plan
487
+ waits for an explicit response.
488
+ - `--auto-review` and `--no-auto-review` update the Session automatic-review setting. When enabled, a
489
+ successful turn starts the existing reviewer workflow before the Run becomes terminal; the Run
490
+ `review` property reports whether it started and its final lifecycle/outcome.
491
+ - `--memory` and `--no-memory` set Memory for a new Session; the two flags are mutually exclusive.
492
+ With `--session`, provider/model/reasoning, Memory and enabled Compute Host changes are rejected.
493
+ Use `session config update` on the idle Session before resuming it.
494
+ - `--specialist` accepts a Specialist UUID or stable Profile name. It binds only a new Session. An
495
+ existing Session cannot be rebound, and a presentation `displayName` is not an identifier.
496
+ - `--delegation allow|deny` updates whether the Session may create new delegated children. `deny`
497
+ does not cancel, hide, or prevent collection/messaging of children admitted earlier.
498
+
499
+ Ordinary `--wait` retains its terminal-only behavior. Add `--return-on-attention` to return a
500
+ still-running Run when its Plan needs approval. Plan approval is the only structured Run attention
501
+ in this release; permission and delegated-question events do not cause an attention return.
502
+
503
+ Inspect and respond to an active Plan with its exact version and revision:
504
+
505
+ ```bash
506
+ open-science plan show <session-id> --json
507
+ open-science plan approve <session-id> --artifact-version <id> --revision <number> --json
508
+ open-science plan reject <session-id> --artifact-version <id> --revision <number> --json
509
+ open-science plan revise <session-id> --feedback "Split the validation step" --json
510
+ ```
511
+
512
+ Version/revision matching prevents a stale automation client from deciding a newer Plan. Approval
513
+ persists the exact decision and triggers a one-time Agent wakeup; feedback asks the live Plan
514
+ interaction for a revision.
515
+
516
+ ## Session configuration
517
+
518
+ Read the persisted and effective configuration, including referenced provider, model, Specialist,
519
+ and Compute Host availability:
520
+
521
+ ```bash
522
+ open-science session config show <session-id> --json
523
+ ```
524
+
525
+ Update an idle Session with the revision returned by `show`:
526
+
527
+ ```bash
528
+ open-science session config update <session-id> --revision 7 \
529
+ --provider openai --provider-default-model --reasoning-effort medium \
530
+ --approval-profile ask --no-auto-review --memory --delegation deny \
531
+ --clear-compute-hosts --json
532
+ ```
533
+
534
+ The Main provider, model, and reasoning effort are one compound configuration. A provider change
535
+ must therefore include either `--model` or `--provider-default-model`. An update affects future
536
+ turns only and is rejected while root-agent, subagent, or Notebook work is active. Reviewer work
537
+ does not block the update. Stale revisions fail with `session_revision_conflict`; invalid or
538
+ unavailable references fail with `invalid_configuration`.
539
+
540
+ ## Agent routing settings
541
+
542
+ Inspect or atomically update the global Agent framework plus Reviewer and Subagent model routing:
543
+
544
+ ```bash
545
+ open-science settings agent-routing show --json
546
+ open-science settings agent-routing update --framework codex \
547
+ --reviewer-provider openai --reviewer-model gpt-5 \
548
+ --subagent-inherit --json
549
+ ```
550
+
551
+ Use `--reviewer-inherit` or `--subagent-inherit` to follow the applicable Main model. Fixed routes
552
+ require both provider and model; reasoning effort is optional. The command validates all three
553
+ settings against the target framework before saving them together. It returns identifiers and
554
+ availability only, never provider credentials.
555
+
556
+ A framework change applies to new Sessions and future Reviewer work. Existing idle Sessions migrate
557
+ lazily on their next turn, replaying their visible transcript when a fresh provider Session is
558
+ needed. In-flight Main, Reviewer, and Subagent work remains pinned to the runtime generation and
559
+ model snapshot admitted at its start. In Reviewer inherit mode, admission freezes the model name;
560
+ the provider is resolved when the Reviewer session is created. Fixed Reviewer routing freezes its
561
+ explicit provider/framework target. Reviewer and Subagent route changes affect future work.
562
+
563
+ ### Session persistence and compatibility
564
+
565
+ Session configuration continues to use the Session JSON authority; it does not add a Session
566
+ schema migration:
567
+
568
+ - Session JSON stores `delegationPolicy` with values `allow` or `deny`. Historical Session files
569
+ that omit it, and malformed values, restore as `allow`.
570
+ - autoReviewEnabled and specialistId already existed and are reused. Historical
571
+ autoReviewEnabled omissions remain disabled; an omitted specialistId remains Main Agent.
572
+ - Plan artifacts, persisted approval, active context, and delivery receipts remain under
573
+ runtimeContext.plan. The originating Conversation Turn remains the Plan owner; related later
574
+ ordinary or application Attempts on the same durable Message Branch receive it as active context
575
+ without taking ownership. Delegated attempts, messages, and questions remain under
576
+ runtimeContext.delegatedWork.
577
+
578
+ Project Session defaults add one `sessionDefaults` JSON-text column to the Project table. Existing
579
+ rows migrate to `{}` and therefore retain prior behavior. Agent routing reuses the existing Settings
580
+ JSON fields.
581
+
582
+ No persistent Session status enum value is added. Existing waiting-plan-approval remains the
583
+ durable Session status, while a public Run remains running and carries an attention discriminant.
584
+ Plan delivery receipts may persist `accepted` after the provider boundary so restart recovery can
585
+ settle that one-shot wakeup without replaying it.
586
+
587
+ ## Machine-readable output
588
+
589
+ Use `--json` to emit one result. `--jsonl` requires `run --wait` and emits progress events followed by
590
+ the final run object, one JSON value per line:
591
+
592
+ Every Run object includes its effective `cwd`; progress events and Session summaries do not.
593
+
594
+ The event stream includes `run.progress` phase changes and ten-second liveness heartbeats before the
595
+ first visible provider output. Each progress payload includes `runId`, `sessionId`, `projectId`,
596
+ `phase`, `timestamp`, `elapsedMs`, and `heartbeat`. Its timer starts after Task has prepared the
597
+ Session and registered its Run; Session creation or resume time before registration is outside this
598
+ stream. Every emitted Run event also carries top-level `sequence`, `runId`, `sessionId`, and
599
+ `projectId` fields. The client reconnects with its last sequence after an unexpected disconnect. If
600
+ the bounded, process-local replay suffix is unavailable, JSON Lines output includes a
601
+ `stream.resync-required` control event and final Run state still comes from the Task HTTP API.
602
+
603
+ ```bash
604
+ open-science run \
605
+ --project <project-id> \
606
+ --prompt-file ./task.md \
607
+ --approval-profile auto \
608
+ --wait \
609
+ --jsonl
610
+ ```
611
+
612
+ `--json` and `--jsonl` cannot be used together. Structured errors use this shape:
613
+
614
+ ```json
615
+ { "error": { "code": "invalid_cli_usage", "message": "--project is required." }, "exitCode": 2 }
616
+ ```
617
+
618
+ Exit codes form part of the automation contract:
619
+
620
+ | Exit code | Meaning |
621
+ | --------- | ----------------------------------------------------------------------------- |
622
+ | `0` | The command succeeded, including a completed waited run. |
623
+ | `1` | A run failed, status found no service, or a general command failure occurred. |
624
+ | `2` | CLI usage was invalid. |
625
+ | `3` | The local daemon was unavailable. |
626
+ | `4` | A requested project, run, session, artifact, or Specialist was not found. |
627
+
628
+ Codex login can propagate the native login process exit code (a signal without a code becomes `1`).
629
+ A successfully cancelled Run is not itself a CLI failure; inspect its `cancelled` status.
630
+
631
+ Timeouts and `session_busy` conflicts use exit code `1` and retain their distinct `timeout` and
632
+ `session_busy` error codes in structured output.
633
+
634
+ ## Artifacts
635
+
636
+ List the artifacts produced for a session and download one by ID:
637
+
638
+ ```bash
639
+ open-science artifacts list <session-id> --json
640
+ open-science artifacts download <artifact-id> --output ./report.md --json
641
+ ```
642
+
643
+ Artifact output paths are resolved relative to the current working directory.
644
+
645
+ ## Current scope
646
+
647
+ The CLI does not expose file/directory attachments or per-run Agent framework selection.
648
+ New Sessions accept provider/model selection; resumed Sessions use `session config update`.
649
+ The help listing still includes `cli install`, but the Node host cannot perform this desktop-only
650
+ operation. Use Settings in the desktop application to install a desktop launcher.
651
+
652
+ ## Connector management
653
+
654
+ Connector commands use the running backend and the same saved Settings as the desktop and web UI.
655
+ Use `--config-root` to select the intended instance. Custom MCP and credential mutations require a
656
+ local authenticated connection; run the CLI on the server itself, including through SSH.
657
+
658
+ ```sh
659
+ open-science connector list --json
660
+ open-science connector show context7 --json
661
+ open-science connector enable context7
662
+ open-science connector disable context7
663
+ open-science connector add --json < connector.json
664
+ open-science connector update context7 --json < connector-update.json
665
+ open-science connector remove context7
666
+ open-science connector test context7 --json
667
+ ```
668
+
669
+ `add` reads an object with `name`, `displayName`, `transport`, and `command` (stdio) or `url`
670
+ (`streamable_http` or `sse`). Optional fields include `args`, `description`, `envCredentialIds`,
671
+ `headerCredentialIds`, and `oauthCredentialId`. Names and IDs remain stable on update. `update`
672
+ requires `transport`; omitted credential bindings retain their saved values. Use an empty binding
673
+ object to clear environment/header bindings. Only custom MCP Connectors can be added, edited, or removed.
674
+
675
+ ```json
676
+ {
677
+ "name": "context7",
678
+ "displayName": "Context7",
679
+ "transport": "streamable_http",
680
+ "url": "https://mcp.example.test/mcp"
681
+ }
682
+ ```
683
+
684
+ `list` and `show` expose safe Settings views, not raw credential material. `enabled` is a selection
685
+ preference, not proof of connectivity or a global revocation of Specialist access. `availability`,
686
+ `checking`, credential-presence fields, and `skillProjectionStatus` retain their Settings meanings.
687
+ Changes reuse existing agent refresh behavior. Start a new session if its tool list remains unchanged;
688
+ these commands do not force-reset active conversations.
689
+
690
+ `test` opens a separate MCP connection, discovers tools, and closes it. It does not enable a disabled
691
+ Connector or execute business tools. Its result is `{ success, toolCount?, message, stage?, code? }`; failure exits
692
+ nonzero. Discovery is bounded to ten seconds. Bundled Connector live diagnostics are unsupported.
693
+ OAuth refresh may update existing encrypted token state; testing does not perform first-time browser login.
694
+
695
+ ### Credentials
696
+
697
+ ```sh
698
+ open-science credential list --json
699
+ open-science credential add --json < credential.json
700
+ open-science credential update <credential-id> --json < credential-update.json
701
+ ```
702
+
703
+ Credential writes read JSON exclusively from stdin. Do not put secrets in command arguments or shell
704
+ history. Protect any input file and remove it when no longer needed. A token input has the shape
705
+ `{ "displayName": "Service token", "kind": "token", "secret": "..." }`; `api_key` is also supported.
706
+ The returned `createdCredential.id` can be bound in `envCredentialIds` or `headerCredentialIds`.
707
+ Updates accept `displayName` and/or `secret`. Existing OAuth registration can be created with `kind:
708
+ "oauth"`, `resourceUri`, remote `transport`, and an `oauth` registration object, then authenticated
709
+ through Settings. First-time browserless OAuth login is outside these commands.
710
+
711
+ Secrets use the OS-protected store by default. Linux headless deployments without a usable keyring
712
+ can explicitly opt into unencrypted local file storage:
713
+
714
+ ```sh
715
+ open-science start --credential-store=file --no-open
716
+ ```
717
+
718
+ Continue using the normal Settings forms and credential commands. The selected mode applies to new
719
+ and updated Settings-managed secrets: provider API keys and app-managed subscription tokens, GitHub
720
+ and literature keys, shared connector credentials, custom MCP secret environment/header values,
721
+ and Settings-managed OAuth client secrets and token state. Compute passwords and protected Compute
722
+ data keep their independent OS-storage requirement; external framework login stores keep their own
723
+ behavior. This flag does not disable any sandbox.
724
+
725
+ File mode reuses `settings.json` and `credentials.json` under the application's configuration root.
726
+ Secret refs use `file:v1:` followed by base64 **encoding, not encryption**. The existing atomic writer
727
+ creates files and temporary replacements with POSIX mode `0600`. Keep the configuration directory
728
+ private; anyone who can read these files can recover the secrets. Do not copy them into images,
729
+ repositories, logs, or support reports. A disposable container filesystem discards them when the
730
+ container is removed; a persistent volume retains them. A tmpfs mount can be used when disk
731
+ persistence is unwanted. Open-Science does not delete configuration automatically on shutdown.
732
+
733
+ Specify the option at every startup, including after updates. It is a startup choice, not a saved
734
+ preference. The default (or `--credential-store=os`) requires OS protection. An already-running
735
+ backend rejects explicit mode selection: stop it before restarting with the desired option. File
736
+ mode is supported only by the Linux headless backend, not desktop launches or macOS/Windows.
737
+
738
+ Legacy `plain:` refs remain readable in explicit file mode without rewriting them.
739
+ Existing encrypted refs are not automatically migrated or downgraded. They still require the original
740
+ OS vault to read, even in file mode; otherwise re-enter the credential. New/refreshed values saved in
741
+ file mode use the file format. File refs require explicit file mode to read and are unreadable by
742
+ older releases. To switch a file credential back to OS storage, restart in OS mode and explicitly
743
+ replace it with the key while the vault is available. Existing unreadable records remain intact.
744
+ These commands do not migrate historical configuration or store diagnostic history. Older backends that
745
+ lack the endpoints return an endpoint error; the CLI never falls back to editing Settings files directly.