@hydra-acp/cli 0.1.5 → 0.1.6

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
@@ -178,7 +178,7 @@ hydra-acp daemon start
178
178
  # spawned-by-editor cases where stdio is already piped. The first
179
179
  # session/new asks the daemon which agent to spawn (defaults to
180
180
  # config.defaultAgent). If you'd rather the editor pin a specific agent,
181
- # spawn `hydra-acp launch <agent-id>` (see "Launcher mode" below).
181
+ # spawn `hydra-acp launch <agent>` (see "Launcher mode" below).
182
182
 
183
183
  # 4. From a terminal, drive a session interactively (TUI).
184
184
  hydra-acp # bare invocation in a TTY launches the TUI
@@ -198,8 +198,8 @@ hydra-acp --session-id hydra_session_abc123
198
198
  hydra-acp # auto-dispatch: TUI in a TTY, shim when stdio is piped
199
199
  hydra-acp shim # explicit shim mode (forces shim regardless of TTY)
200
200
  hydra-acp tui # explicit terminal-UI mode
201
- hydra-acp launch <agent-id> # launcher mode: shim that forces the
202
- # daemon to spawn <agent-id> on session/new
201
+ hydra-acp launch <agent> # launcher mode: shim that forces the
202
+ # daemon to spawn <agent> on session/new
203
203
  hydra-acp --session-id <id> # attach to existing session
204
204
  # (TUI in a TTY, shim otherwise)
205
205
 
@@ -234,7 +234,7 @@ A bare invocation (`hydra-acp` with no subcommand) auto-dispatches based on whet
234
234
 
235
235
  ### Launcher mode
236
236
 
237
- `hydra-acp launch <agent-id>` is a convenience for "shim me, and use *this* registry agent." It's the easiest way to wrap an existing ACP-speaking editor configuration whose agent-spawn surface is just a command and arguments:
237
+ `hydra-acp launch <agent>` is a convenience for "shim me, and use *this* registry agent." It's the easiest way to wrap an existing ACP-speaking editor configuration whose agent-spawn surface is just a command and arguments:
238
238
 
239
239
  ```text
240
240
  # Configure your editor's ACP-launch command to:
@@ -243,9 +243,9 @@ hydra-acp launch claude-code
243
243
 
244
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.
245
245
 
246
- `<agent-id>` 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 agents` to browse what's available, or fetch the registry CDN URL directly.
247
247
 
248
- If both `launch <agent-id>` and `--session-id` are given, `--session-id` wins (attach mode); the agent ID is ignored because the agent process is already running.
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
 
@@ -286,9 +286,9 @@ Each session carries a stable **`lineageId`** that survives every export/import
286
286
 
287
287
  The first attach to an imported session is slow: hydra spawns a fresh agent, runs `session/new`, and feeds the imported history back in as a synthesized takeover transcript (same machinery as `/hydra agent`). Subsequent attaches use the normal `session/load` path. This is a text-level handover — the originating agent's internal state (tool-call chains, compacted earlier turns) isn't preserved, so the resumed conversation may be cognitively shallower than the original.
288
288
 
289
- ### Forwarding agent args (`hydra-acp launch <agent-id> ...`)
289
+ ### Forwarding agent args (`hydra-acp launch <agent> ...`)
290
290
 
291
- Anything you put after `<agent-id>` in launcher mode is forwarded to the underlying agent's command. Hydra appends the extra args to the registry-provided spawn plan. Example:
291
+ Anything you put after `<agent>` in launcher mode is forwarded to the underlying agent's command. Hydra appends the extra args to the registry-provided spawn plan. Example:
292
292
 
293
293
  ```text
294
294
  hydra-acp launch codex-acp -c sandbox_mode=danger-full-access
@@ -303,14 +303,17 @@ Every config-knob flag has an `HYDRA_ACP_FOO_BAR` env-var equivalent. Flag wins
303
303
  | Flag | Env var |
304
304
  |---|---|
305
305
  | `--name` | `HYDRA_ACP_NAME` |
306
- | `--agent-id` | `HYDRA_ACP_AGENT_ID` |
306
+ | `--agent` | `HYDRA_ACP_AGENT` |
307
+ | `--model` | `HYDRA_ACP_MODEL` |
307
308
  | `--session-id` | `HYDRA_ACP_SESSION_ID` |
308
309
 
310
+ `--model` is a one-shot override for the per-agent `defaultModels` entry in `~/.hydra-acp/config.json`. It only applies at fresh session creation — resurrect and `/hydra agent` switch ignore it (resurrected sessions stay on whatever model they were last using).
311
+
309
312
  Action commands (`init`, `daemon`, `sessions`, `--help`, `--version`, `--rotate-token`) are not config knobs and are flag-only.
310
313
 
311
314
  ### Registry id resolution
312
315
 
313
- When you ask hydra to spawn an agent (via `launch <id>`, `--agent-id`, or `HYDRA_ACP_AGENT_ID`), the daemon first tries an exact match against the ACP Registry's `id` field. If nothing matches, it falls back to matching against the **npx package basename** (the segment after the last `/` and before the version `@`). That means common binary names work transparently:
316
+ When you ask hydra to spawn an agent (via `launch <agent>`, `--agent`, or `HYDRA_ACP_AGENT`), the daemon first tries an exact match against the ACP Registry's `id` field. If nothing matches, it falls back to matching against the **npx package basename** (the segment after the last `/` and before the version `@`). That means common binary names work transparently:
314
317
 
315
318
  | You spawn… | Registry `id` | Resolves via |
316
319
  |---|---|---|
package/dist/cli.js CHANGED
@@ -248,6 +248,9 @@ function extractHydraMeta(meta) {
248
248
  out.resume = parsed.data;
249
249
  }
250
250
  }
251
+ if (typeof obj.model === "string") {
252
+ out.model = obj.model;
253
+ }
251
254
  if (typeof obj.currentModel === "string") {
252
255
  out.currentModel = obj.currentModel;
253
256
  }
@@ -5420,8 +5423,17 @@ function formatPlan(event) {
5420
5423
  }
5421
5424
  ];
5422
5425
  }
5426
+ const allComplete = event.entries.every(
5427
+ (e) => (e.status ?? "pending") === "completed"
5428
+ );
5429
+ const headerStyle = allComplete ? "plan-done" : "plan";
5423
5430
  const lines = [
5424
- { prefix: "\u25A3 ", prefixStyle: "plan", body: "Plan", bodyStyle: "plan" }
5431
+ {
5432
+ prefix: "\u25A3 ",
5433
+ prefixStyle: headerStyle,
5434
+ body: "Plan",
5435
+ bodyStyle: headerStyle
5436
+ }
5425
5437
  ];
5426
5438
  for (const entry of event.entries) {
5427
5439
  const status = entry.status ?? "pending";
@@ -5718,10 +5730,17 @@ async function runSession(term, config, opts, exitHint) {
5718
5730
  let initialCommands;
5719
5731
  let initialTurnStartedAt;
5720
5732
  if (ctx.sessionId === "__new__") {
5733
+ const hydraNewMeta = {};
5734
+ if (opts.name) {
5735
+ hydraNewMeta.name = opts.name;
5736
+ }
5737
+ if (opts.model) {
5738
+ hydraNewMeta.model = opts.model;
5739
+ }
5721
5740
  const created = await conn.request("session/new", {
5722
5741
  cwd: ctx.cwd,
5723
5742
  ...opts.agentId ? { agentId: opts.agentId } : {},
5724
- ...opts.name ? { _meta: { [HYDRA_META_KEY]: { name: opts.name } } } : {}
5743
+ ...Object.keys(hydraNewMeta).length > 0 ? { _meta: { [HYDRA_META_KEY]: hydraNewMeta } } : {}
5725
5744
  });
5726
5745
  resolvedSessionId = created.sessionId;
5727
5746
  exitHint.sessionId = resolvedSessionId;
@@ -7816,7 +7835,8 @@ var SessionManager = class {
7816
7835
  agentId: params.agentId,
7817
7836
  cwd: params.cwd,
7818
7837
  agentArgs: params.agentArgs,
7819
- mcpServers: params.mcpServers
7838
+ mcpServers: params.mcpServers,
7839
+ model: params.model
7820
7840
  });
7821
7841
  const session = new Session({
7822
7842
  cwd: params.cwd,
@@ -8008,7 +8028,7 @@ var SessionManager = class {
8008
8028
  );
8009
8029
  }
8010
8030
  let initialModel = extractInitialModel(newResult);
8011
- const desired = this.defaultModels[params.agentId];
8031
+ const desired = params.model ?? this.defaultModels[params.agentId];
8012
8032
  if (desired && desired !== initialModel) {
8013
8033
  try {
8014
8034
  await agent.connection.request("session/set_model", {
@@ -9459,7 +9479,8 @@ function registerAcpWsEndpoint(app, deps) {
9459
9479
  agentId: params.agentId ?? deps.defaultAgent,
9460
9480
  mcpServers: params.mcpServers,
9461
9481
  title: hydraMeta.name,
9462
- agentArgs: hydraMeta.agentArgs
9482
+ agentArgs: hydraMeta.agentArgs,
9483
+ model: hydraMeta.model
9463
9484
  });
9464
9485
  const client = bindClientToSession(connection, session, state);
9465
9486
  await session.attach(client, "full");
@@ -10834,6 +10855,9 @@ function wireShim({
10834
10855
  outgoing = injectHydraMeta(outgoing, { name: namingState.name });
10835
10856
  namingState.used = true;
10836
10857
  }
10858
+ if (opts.model) {
10859
+ outgoing = injectHydraMeta(outgoing, { model: opts.model });
10860
+ }
10837
10861
  void upstream.send(outgoing);
10838
10862
  return;
10839
10863
  }
@@ -10976,10 +11000,10 @@ async function main() {
10976
11000
  const positionalAgentId = afterLaunch[0];
10977
11001
  const agentArgs = afterLaunch.slice(1);
10978
11002
  const { flags: flags2 } = parseArgs(beforeLaunch);
10979
- const agentId = positionalAgentId ?? resolveOption(flags2, "agent-id");
11003
+ const agentId = positionalAgentId ?? resolveOption(flags2, "agent");
10980
11004
  if (!agentId) {
10981
11005
  process.stderr.write(
10982
- "Usage: hydra-acp launch <agent-id> [agent-args...]\n"
11006
+ "Usage: hydra-acp launch <agent> [agent-args...]\n"
10983
11007
  );
10984
11008
  process.exit(2);
10985
11009
  return;
@@ -10987,7 +11011,8 @@ async function main() {
10987
11011
  const launchResume = flags2.resume;
10988
11012
  const sessionId2 = typeof launchResume === "string" ? launchResume : resolveOption(flags2, "session-id");
10989
11013
  const name2 = resolveOption(flags2, "name");
10990
- await runShim({ sessionId: sessionId2, agentId, agentArgs, name: name2 });
11014
+ const model2 = resolveOption(flags2, "model");
11015
+ await runShim({ sessionId: sessionId2, agentId, agentArgs, name: name2, model: model2 });
10991
11016
  return;
10992
11017
  }
10993
11018
  const { positional, flags } = parseArgs(argv);
@@ -11004,22 +11029,24 @@ async function main() {
11004
11029
  const resumeFlag = flags.resume;
11005
11030
  const sessionId = typeof resumeFlag === "string" ? resumeFlag : resolveOption(flags, "session-id");
11006
11031
  const name = resolveOption(flags, "name");
11007
- const agentIdFromFlag = resolveOption(flags, "agent-id");
11032
+ const agentIdFromFlag = resolveOption(flags, "agent");
11033
+ const model = resolveOption(flags, "model");
11008
11034
  if (!subcommand) {
11009
11035
  if (process.stdout.isTTY) {
11010
11036
  await dispatchTui(flags, {
11011
11037
  sessionId,
11012
11038
  agentId: agentIdFromFlag,
11013
- name
11039
+ name,
11040
+ model
11014
11041
  });
11015
11042
  return;
11016
11043
  }
11017
- await runShim({ sessionId, name, agentId: agentIdFromFlag });
11044
+ await runShim({ sessionId, name, agentId: agentIdFromFlag, model });
11018
11045
  return;
11019
11046
  }
11020
11047
  switch (subcommand) {
11021
11048
  case "shim":
11022
- await runShim({ sessionId, name, agentId: agentIdFromFlag });
11049
+ await runShim({ sessionId, name, agentId: agentIdFromFlag, model });
11023
11050
  return;
11024
11051
  case "init":
11025
11052
  await runInit(flags);
@@ -11141,7 +11168,8 @@ async function main() {
11141
11168
  await dispatchTui(flags, {
11142
11169
  sessionId,
11143
11170
  agentId: agentIdFromFlag,
11144
- name
11171
+ name,
11172
+ model
11145
11173
  });
11146
11174
  return;
11147
11175
  default:
@@ -11169,6 +11197,9 @@ async function dispatchTui(flags, base) {
11169
11197
  if (base.name !== void 0) {
11170
11198
  tuiOpts.name = base.name;
11171
11199
  }
11200
+ if (base.model !== void 0) {
11201
+ tuiOpts.model = base.model;
11202
+ }
11172
11203
  await runTui(tuiOpts);
11173
11204
  }
11174
11205
  function readVersion() {
@@ -11191,9 +11222,9 @@ function printHelp() {
11191
11222
  " hydra-acp Auto: TUI when stdout is a TTY, shim otherwise (the editor-spawned case)",
11192
11223
  " hydra-acp shim Run as ACP shim explicitly (forces shim mode regardless of TTY)",
11193
11224
  " hydra-acp tui [opts] Run the terminal UI explicitly (see below for opts)",
11194
- " hydra-acp launch <agent-id> [agent-args...]",
11195
- " Shim mode, force daemon to spawn <agent-id>",
11196
- " from the registry. Args after <agent-id>",
11225
+ " hydra-acp launch <agent> [agent-args...]",
11226
+ " Shim mode, force daemon to spawn <agent>",
11227
+ " from the registry. Args after <agent>",
11197
11228
  " are forwarded to the agent's command.",
11198
11229
  " hydra-acp --resume <id> Attach to an existing session (TUI when in a terminal, shim otherwise)",
11199
11230
  " hydra-acp init [--rotate-token] Initialize ~/.hydra-acp/config.json",
@@ -11214,14 +11245,15 @@ function printHelp() {
11214
11245
  " hydra-acp extensions logs <name> [-f] [-n N]Tail or follow an extension's log",
11215
11246
  " hydra-acp agents [list] List agents in the cached registry",
11216
11247
  " hydra-acp agents refresh Force a registry re-fetch",
11217
- " hydra-acp tui flags: [--resume [<id>]] [--new] [--agent-id <id>] [--cwd <path>] [--name <label>]",
11248
+ " hydra-acp tui flags: [--resume [<id>]] [--new] [--agent <id>] [--model <id>] [--cwd <path>] [--name <label>]",
11218
11249
  " --resume <id> attaches to a specific session; bare --resume picks the most-recent",
11219
11250
  " in cwd. Smart default (no flags): picks if any live sessions exist, else new.",
11220
11251
  " hydra-acp --version Print version",
11221
11252
  " hydra-acp --help Show this help",
11222
11253
  "",
11223
11254
  "Config knob flags accept env-var equivalents (flag wins):",
11224
- " --agent-id HYDRA_ACP_AGENT_ID",
11255
+ " --agent HYDRA_ACP_AGENT",
11256
+ " --model HYDRA_ACP_MODEL (one-shot at session/new; ignored on --resume)",
11225
11257
  " --resume / --session-id HYDRA_ACP_SESSION_ID",
11226
11258
  " --name HYDRA_ACP_NAME",
11227
11259
  ""
package/dist/index.d.ts CHANGED
@@ -1964,6 +1964,7 @@ interface CreateSessionParams {
1964
1964
  mcpServers?: unknown[];
1965
1965
  title?: string;
1966
1966
  agentArgs?: string[];
1967
+ model?: string;
1967
1968
  }
1968
1969
  interface ResurrectParams {
1969
1970
  hydraSessionId: string;
package/dist/index.js CHANGED
@@ -696,6 +696,9 @@ function extractHydraMeta(meta) {
696
696
  out.resume = parsed.data;
697
697
  }
698
698
  }
699
+ if (typeof obj.model === "string") {
700
+ out.model = obj.model;
701
+ }
699
702
  if (typeof obj.currentModel === "string") {
700
703
  out.currentModel = obj.currentModel;
701
704
  }
@@ -2598,7 +2601,8 @@ var SessionManager = class {
2598
2601
  agentId: params.agentId,
2599
2602
  cwd: params.cwd,
2600
2603
  agentArgs: params.agentArgs,
2601
- mcpServers: params.mcpServers
2604
+ mcpServers: params.mcpServers,
2605
+ model: params.model
2602
2606
  });
2603
2607
  const session = new Session({
2604
2608
  cwd: params.cwd,
@@ -2790,7 +2794,7 @@ var SessionManager = class {
2790
2794
  );
2791
2795
  }
2792
2796
  let initialModel = extractInitialModel(newResult);
2793
- const desired = this.defaultModels[params.agentId];
2797
+ const desired = params.model ?? this.defaultModels[params.agentId];
2794
2798
  if (desired && desired !== initialModel) {
2795
2799
  try {
2796
2800
  await agent.connection.request("session/set_model", {
@@ -4305,7 +4309,8 @@ function registerAcpWsEndpoint(app, deps) {
4305
4309
  agentId: params.agentId ?? deps.defaultAgent,
4306
4310
  mcpServers: params.mcpServers,
4307
4311
  title: hydraMeta.name,
4308
- agentArgs: hydraMeta.agentArgs
4312
+ agentArgs: hydraMeta.agentArgs,
4313
+ model: hydraMeta.model
4309
4314
  });
4310
4315
  const client = bindClientToSession(connection, session, state);
4311
4316
  await session.attach(client, "full");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Multi-client ACP session daemon: spawn agents, attach over WSS, multiplex sessions across editors.",
5
5
  "license": "MIT",
6
6
  "type": "module",