@hydra-acp/cli 0.1.22 → 0.1.23

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/README.md CHANGED
@@ -185,7 +185,7 @@ hydra-acp # bare invocation in a TTY launches
185
185
  hydra-acp tui # explicit form
186
186
 
187
187
  # 5. List live sessions.
188
- hydra-acp sessions
188
+ hydra-acp session
189
189
 
190
190
  # 6. Attach a second client to an existing session.
191
191
  # Bare invocation auto-detects: TUI in a terminal, ACP shim when piped.
@@ -203,29 +203,29 @@ hydra-acp launch <agent> # launcher mode: shim that forces th
203
203
  hydra-acp --session-id <id> # attach to existing session
204
204
  # (TUI in a TTY, shim otherwise)
205
205
 
206
- hydra-acp init # generate config + auth token
206
+ hydra-acp init # generate the service token
207
207
  hydra-acp daemon start [--foreground] # detached by default; --foreground to attach
208
208
  hydra-acp daemon stop
209
209
  hydra-acp daemon status
210
210
 
211
- hydra-acp sessions # list sessions
212
- hydra-acp sessions kill <id> # close a live session (keeps the on-disk record so it can be resurrected)
213
- hydra-acp sessions remove <id> # remove a session entirely (live or cold)
214
- hydra-acp sessions export <id> [--out <file>|.]
211
+ hydra-acp session # list sessions
212
+ hydra-acp session kill <id> # close a live session (keeps the on-disk record so it can be resurrected)
213
+ hydra-acp session remove <id> # remove a session entirely (live or cold)
214
+ hydra-acp session export <id> [--out <file>|.]
215
215
  # write a session bundle (meta + history) to <file>,
216
216
  # to a default-named file when --out=., or to stdout
217
- hydra-acp sessions import <file>|- [--replace]
217
+ hydra-acp session import <file>|- [--replace]
218
218
  # import a bundle from <file> or stdin (-);
219
219
  # --replace overwrites an existing lineage match
220
220
 
221
- hydra-acp extensions # list configured extensions and live state
222
- hydra-acp extensions add <name> # add to config (--command, --args, --env, --disabled)
223
- hydra-acp extensions remove <name> # remove from config
224
- hydra-acp extensions start|stop|restart <n> # lifecycle on a running extension
225
- hydra-acp extensions logs <name> [-f] [-n] # tail (default 50) or follow an extension's log
221
+ hydra-acp extension # list configured extensions and live state
222
+ hydra-acp extension add <name> # add to config (--command, --args, --env, --disabled)
223
+ hydra-acp extension remove <name> # remove from config
224
+ hydra-acp extension start|stop|restart <n> # lifecycle on a running extension
225
+ hydra-acp extension logs <name> [-f] [-n] # tail (default 50) or follow an extension's log
226
226
 
227
- hydra-acp agents # list agents in the registry
228
- hydra-acp agents install <id> # pre-install an agent (else lazy on first use)
227
+ hydra-acp agent # list agents in the registry
228
+ hydra-acp agent install <id> # pre-install an agent (else lazy on first use)
229
229
 
230
230
  hydra-acp config # print resolved config path/values
231
231
  ```
@@ -241,15 +241,15 @@ A bare invocation (`hydra-acp` with no subcommand) auto-dispatches based on whet
241
241
  hydra-acp launch claude-code
242
242
  ```
243
243
 
244
- When the editor sends `session/new`, the shim rewrites the params to `{ ..., agentId: "claude-code" }` before forwarding to the daemon. The daemon resolves `claude-code` against the cached ACP Registry, downloads/installs the agent on first use under `~/.hydra-acp/agents/`, and spawns the subprocess. The editor sees a normal ACP agent. From then on, `hydra-acp sessions` lists the live session and any other client can `session/attach` to it.
244
+ When the editor sends `session/new`, the shim rewrites the params to `{ ..., agentId: "claude-code" }` before forwarding to the daemon. The daemon resolves `claude-code` against the cached ACP Registry, downloads/installs the agent on first use under `~/.hydra-acp/agents/`, and spawns the subprocess. The editor sees a normal ACP agent. From then on, `hydra-acp session` lists the live session and any other client can `session/attach` to it.
245
245
 
246
- `<agent>` is the registry ID — e.g. `claude-code`, `gemini-cli`, `codex`. Run `hydra-acp agents` to browse what's available, or fetch the registry CDN URL directly.
246
+ `<agent>` is the registry ID — e.g. `claude-code`, `gemini-cli`, `codex`. Run `hydra-acp agent` to browse what's available, or fetch the registry CDN URL directly.
247
247
 
248
248
  If both `launch <agent>` and `--session-id` are given, `--session-id` wins (attach mode); the agent is ignored because the agent process is already running.
249
249
 
250
250
  ### Naming sessions from the editor
251
251
 
252
- Pass `--name <label>` or set `HYDRA_ACP_NAME` and the first `session/new` from that shim is labeled accordingly. The label flows through `_meta["hydra-acp"].name` on the wire, lands in `Session.title`, and shows up in `session/list` and `hydra-acp sessions`. Subsequent `session/new` calls from the same shim are not labeled — first one wins. The label survives daemon restart (it's carried in the resume hints).
252
+ Pass `--name <label>` or set `HYDRA_ACP_NAME` and the first `session/new` from that shim is labeled accordingly. The label flows through `_meta["hydra-acp"].name` on the wire, lands in `Session.title`, and shows up in `session/list` and `hydra-acp session`. Subsequent `session/new` calls from the same shim are not labeled — first one wins. The label survives daemon restart (it's carried in the resume hints).
253
253
 
254
254
  ```text
255
255
  HYDRA_ACP_NAME="$BUFFER_NAME" hydra-acp launch claude-acp
@@ -267,19 +267,19 @@ Slash commands of the form `/hydra <verb> [args]` are intercepted by hydra befor
267
267
  |---|---|
268
268
  | `/hydra title` | Asks the agent for a one-line summary, applies it as the new title via `session_info_update`. The sub-prompt and reply are suppressed from clients. |
269
269
  | `/hydra title <text>` | Sets the title to `<text>` directly. No agent call. |
270
- | `/hydra agent <agent>` | Swaps the agent process backing this session. Spawns the new agent (must be in the registry — see `hydra-acp agents list`), kills the old one, and feeds the conversation transcript so far back in as the first prompt to the new agent. `session_info_update` carries the new `agentId`; a synthetic `agent_message_chunk` banner marks the switch in the transcript. The on-disk session record is updated so resurrection brings the session back on the new agent. |
270
+ | `/hydra agent <agent>` | Swaps the agent process backing this session. Spawns the new agent (must be in the registry — see `hydra-acp agent list`), kills the old one, and feeds the conversation transcript so far back in as the first prompt to the new agent. `session_info_update` carries the new `agentId`; a synthetic `agent_message_chunk` banner marks the switch in the transcript. The on-disk session record is updated so resurrection brings the session back on the new agent. |
271
271
 
272
272
  These work from anywhere a session prompt can be typed — the TUI's input box, agent-shell, the slack thread composer, the browser chat composer. Hydra detects them server-side; clients send them as ordinary `session/prompt` requests.
273
273
 
274
274
  ### Exporting and importing sessions
275
275
 
276
- `hydra-acp sessions export` writes a session to a `*.hydra` JSON bundle (meta + history + optional prompt history). `hydra-acp sessions import` brings it back into the local daemon as a new cold session. Use this to archive a session before clearing it, share one with a teammate, restore from backup, or move work between machines without running both daemons live.
276
+ `hydra-acp session export` writes a session to a `*.hydra` JSON bundle (meta + history + optional prompt history). `hydra-acp session import` brings it back into the local daemon as a new cold session. Use this to archive a session before clearing it, share one with a teammate, restore from backup, or move work between machines without running both daemons live.
277
277
 
278
278
  ```text
279
- hydra-acp sessions export hydra_session_abc --out backup.hydra
280
- hydra-acp sessions import backup.hydra # → new local id
281
- hydra-acp sessions import backup.hydra # error: already imported
282
- hydra-acp sessions import backup.hydra --replace # overwrites in place
279
+ hydra-acp session export hydra_session_abc --out backup.hydra
280
+ hydra-acp session import backup.hydra # → new local id
281
+ hydra-acp session import backup.hydra # error: already imported
282
+ hydra-acp session import backup.hydra --replace # overwrites in place
283
283
  ```
284
284
 
285
285
  Each session carries a stable **`lineageId`** that survives every export/import hop, so the same bundle imported twice is detected as a duplicate — the second import errors with the existing local id. `--replace` overrides that and overwrites the existing local copy, killing any live session first and preserving the local `sessionId` so bookmarks (Slack threads, editor session links) keep resolving.
@@ -331,8 +331,7 @@ When you ask hydra to spawn an agent (via `launch <agent>`, `--agent`, or `HYDRA
331
331
  {
332
332
  "daemon": {
333
333
  "host": "127.0.0.1",
334
- "port": 8765,
335
- "authToken": "hydra_token_<random>",
334
+ "port": 55514,
336
335
  "logLevel": "info"
337
336
  },
338
337
  "registry": {
@@ -343,9 +342,11 @@ When you ask hydra to spawn an agent (via `launch <agent>`, `--agent`, or `HYDRA
343
342
  }
344
343
  ```
345
344
 
345
+ The service token lives in its own file (`~/.hydra-acp/auth-token`, mode 0600) and is never written to `config.json` — so the config file stays safe to version-control.
346
+
346
347
  `daemon.sessionIdleTimeoutSeconds` (default 3600 — one hour) controls how long a session with no recorded agent or user activity stays alive before the daemon closes it. Snapshot-shaped state pings (model/mode/title/commands) and bare attach/detach don't count as activity — only recordable broadcasts (prompts, agent chunks, tool calls, permission prompts) do, so persistent observer clients like the slack/notifier/approver/browser extensions can't pin a quiet session open. In-flight turns and unresolved permission requests defer the close until they settle. The disk record stays so the session can be resurrected later via `session/load`, at which point extensions re-attach automatically through their poll loops. Set to `0` to disable.
347
348
 
348
- `daemon.sessionRecentMinutes` (default 30) controls how far back `hydra-acp sessions` (and the `/v1/sessions` REST endpoint without `?all=true`) looks for cold (disk-only) sessions. Set to `0` to never list cold sessions.
349
+ `daemon.sessionRecentMinutes` (default 30) controls how far back `hydra-acp session` (and the `/v1/sessions` REST endpoint without `?all=true`) looks for cold (disk-only) sessions. Set to `0` to never list cold sessions.
349
350
 
350
351
  `tui.mouse` (default `true`) controls whether the TUI captures mouse events. With capture on, the scroll wheel drives scrollback but selecting text requires `shift+drag` to bypass mouse reporting in your terminal. Set to `false` to disable capture — plain click-drag selects text, but wheel-driven scrollback stops working (use `PgUp` / `PgDn` instead).
351
352
 
@@ -374,11 +375,11 @@ Each extension is launched with these env vars set:
374
375
 
375
376
  | Env var | Example |
376
377
  |---|---|
377
- | `HYDRA_ACP_DAEMON_URL` | `http://127.0.0.1:8765` |
378
+ | `HYDRA_ACP_DAEMON_URL` | `http://127.0.0.1:55514` |
378
379
  | `HYDRA_ACP_DAEMON_HOST` | `127.0.0.1` |
379
- | `HYDRA_ACP_DAEMON_PORT` | `8765` |
380
+ | `HYDRA_ACP_DAEMON_PORT` | `55514` |
380
381
  | `HYDRA_ACP_TOKEN` | `hydra_token_<hex>` |
381
- | `HYDRA_ACP_WS_URL` | `ws://127.0.0.1:8765/acp` |
382
+ | `HYDRA_ACP_WS_URL` | `ws://127.0.0.1:55514/acp` |
382
383
  | `HYDRA_ACP_HOME` | `~/.hydra-acp` |
383
384
  | `HYDRA_ACP_EXTENSION_NAME` | the `name` from config |
384
385
 
@@ -387,14 +388,14 @@ Extension stdout/stderr are appended to `~/.hydra-acp/extensions/<name>.log`.
387
388
  While the daemon is running you can manage extensions without bouncing it:
388
389
 
389
390
  ```text
390
- hydra-acp extensions # table of name/status/pid/restarts/started/log
391
- hydra-acp extensions restart hydra-acp-slack
392
- hydra-acp extensions logs hydra-acp-slack --follow
391
+ hydra-acp extension # table of name/status/pid/restarts/started/log
392
+ hydra-acp extension restart hydra-acp-slack
393
+ hydra-acp extension logs hydra-acp-slack --follow
393
394
  ```
394
395
 
395
396
  `stop` suppresses the auto-restart backoff; the extension stays down until the next `start`, `restart`, or daemon bounce. `add`/`remove` are config-only — restart the daemon to apply.
396
397
 
397
- **Trust model**: extensions run with the same privileges as the daemon and receive its full auth token. Treat extensions as part of your trusted compute base — review extensions before installing and don't run untrusted code through this mechanism.
398
+ **Trust model**: extensions run with the same privileges as the daemon and receive its full service token. Treat extensions as part of your trusted compute base — review extensions before installing and don't run untrusted code through this mechanism.
398
399
 
399
400
  #### Optional extensions
400
401
 
@@ -404,8 +405,8 @@ Various ready-made extensions ship under the same `@hydra-acp` npm scope. All ar
404
405
 
405
406
  ```sh
406
407
  npm install -g @hydra-acp/slack
407
- hydra-acp extensions add hydra-acp-slack --command hydra-acp-slack
408
- hydra-acp extensions start hydra-acp-slack # if the daemon is already running
408
+ hydra-acp extension add hydra-acp-slack --command hydra-acp-slack
409
+ hydra-acp extension start hydra-acp-slack # if the daemon is already running
409
410
  ```
410
411
 
411
412
  You'll also need a Slack app and a config at `~/.hydra-acp-slack.conf` — see the [package's setup section](https://github.com/smagnuso/hydra-acp-slack#setup) for scopes, tokens, and authorized users.
@@ -414,8 +415,8 @@ You'll also need a Slack app and a config at `~/.hydra-acp-slack.conf` — see t
414
415
 
415
416
  ```sh
416
417
  npm install -g @hydra-acp/browser
417
- hydra-acp extensions add hydra-acp-browser --command hydra-acp-browser
418
- hydra-acp extensions start hydra-acp-browser
418
+ hydra-acp extension add hydra-acp-browser --command hydra-acp-browser
419
+ hydra-acp extension start hydra-acp-browser
419
420
  ```
420
421
 
421
422
  The first launch generates `~/.hydra-acp-browser/authkey` and writes the open URL (with `?authkey=…`) to `~/.hydra-acp-browser/link`. Defaults to localhost-only; see the [package's HTTPS section](https://github.com/smagnuso/hydra-acp-browser#https) for binding to a LAN address with TLS.
@@ -424,23 +425,23 @@ The first launch generates `~/.hydra-acp-browser/authkey` and writes the open UR
424
425
 
425
426
  ```sh
426
427
  npm install -g @hydra-acp/notifier
427
- hydra-acp extensions add hydra-acp-notifier --command hydra-acp-notifier
428
- hydra-acp extensions start hydra-acp-notifier
428
+ hydra-acp extension add hydra-acp-notifier --command hydra-acp-notifier
429
+ hydra-acp extension start hydra-acp-notifier
429
430
  ```
430
431
 
431
432
  **[`@hydra-acp/approver`](https://github.com/smagnuso/hydra-acp-approver) — headless permission auto-responder.** Attaches to every live session and answers `session/request_permission` based on a JS rule at `~/.hydra-acp/approver.config.js`. When the rule returns an `optionId` it wins the race and dismisses the prompt before any human client sees it; when it abstains (returns `null`), the prompt stays open for your interactive clients. Useful for centralizing approval policy in one place so per-client approve lambdas can go away.
432
433
 
433
434
  ```sh
434
435
  npm install -g @hydra-acp/approver
435
- hydra-acp extensions add hydra-acp-approver --command hydra-acp-approver
436
- hydra-acp extensions start hydra-acp-approver
436
+ hydra-acp extension add hydra-acp-approver --command hydra-acp-approver
437
+ hydra-acp extension start hydra-acp-approver
437
438
  ```
438
439
 
439
440
  Without a config file the approver abstains on everything — installing it has no behavioral effect until you write a rule.
440
441
 
441
- Per-extension config (env vars, args, custom command paths) goes in the same `extensions` block in `~/.hydra-acp/config.json` — see the snippet above. `hydra-acp extensions logs <name> -f` tails an extension's stdout/stderr if you need to debug.
442
+ Per-extension config (env vars, args, custom command paths) goes in the same `extensions` block in `~/.hydra-acp/config.json` — see the snippet above. `hydra-acp extension logs <name> -f` tails an extension's stdout/stderr if you need to debug.
442
443
 
443
- The `authToken` is generated on `hydra-acp init` and required as `Authorization: Bearer <token>` for every REST call and as a WebSocket subprotocol or query parameter for `wss://.../acp`. Tokens never leave `~/.hydra-acp/`.
444
+ The service token (stored at `~/.hydra-acp/auth-token`, mode 0600) is generated on `hydra-acp init` and required as `Authorization: Bearer <token>` for every REST call and as a WebSocket subprotocol or query parameter for `wss://.../acp`. The token never leaves `~/.hydra-acp/`.
444
445
 
445
446
  For remote access (binding to a non-loopback address), enable TLS via:
446
447
 
@@ -461,7 +462,8 @@ The daemon refuses to bind to non-loopback hosts without TLS configured.
461
462
 
462
463
  ```
463
464
  ~/.hydra-acp/
464
- ├── config.json # daemon config + auth token
465
+ ├── config.json # daemon config (safe to version-control)
466
+ ├── auth-token # service token (mode 0600, never in config.json)
465
467
  ├── daemon.pid # PID + port lockfile (when running)
466
468
  ├── daemon.<N>.log # rotated daemon logs (10 MB or daily, whichever first)
467
469
  ├── current.log # symlink to the active daemon.<N>.log
@@ -480,7 +482,7 @@ The daemon's WSS endpoint follows the [Streamable HTTP & WebSocket Transport RFD
480
482
 
481
483
  ```
482
484
  GET /acp HTTP/1.1
483
- Host: localhost:8765
485
+ Host: localhost:55514
484
486
  Upgrade: websocket
485
487
  Sec-WebSocket-Protocol: acp.v1, hydra-acp-token.<token>
486
488
  ```
@@ -553,13 +555,13 @@ Sessions are also reachable via `session/list` over ACP itself, for clients that
553
555
 
554
556
  ## Security
555
557
 
556
- The daemon exposes a process-management surface. Treat the auth token like an SSH key.
558
+ The daemon exposes a process-management surface. Treat the service token like an SSH key.
557
559
 
558
560
  - **Default bind is `127.0.0.1`.** Cross-host access requires TLS + a strong token.
559
561
  - **No anonymous access.** Every request — REST and WSS — must present the bearer token.
560
562
  - **Token rotation:** `hydra-acp init --rotate-token` invalidates the old token; running clients are kicked.
561
563
  - **Sandboxing is the user's responsibility.** Spawned agents inherit the daemon's filesystem and shell. Run the daemon under a restricted user or inside a container if you don't trust agents fully.
562
- - **Subprocess scope:** agent processes inherit `cwd` and a sanitized environment. The daemon does not pass its auth token through to spawned agents.
564
+ - **Subprocess scope:** agent processes inherit `cwd` and a sanitized environment. The daemon does not pass its service token through to spawned agents.
563
565
 
564
566
  ## Registry entry mockup
565
567