choom: map --continue <id> to claude --resume — claude's own --continue takes no value (closes #2127)

This commit is contained in:
damocles 2026-07-02 11:52:37 +02:00 committed by mara
commit 4e7a9b93d9
3 changed files with 30 additions and 21 deletions

View file

@ -112,15 +112,18 @@ enum Cmd {
///
/// Runs claude as the agent user from its state dir with the harness's
/// settings / MCP / system prompt. Bare `choom <name>` is a fresh
/// session; `--continue <id|name>` rejoins a prior one. Never collides
/// with the harness's live session. Requires root + a running
/// session; `--continue <session-id>` rejoins a prior one. Never
/// collides with the harness's live session. Requires root + a running
/// container. See `docs/tools/hivectl.md` (Choom) for details.
Choom {
/// Agent name (e.g. `damocles`, `iris`).
name: String,
/// Resume a prior claude session by id or display name, passed
/// through as `claude --continue <value>`. Omit for a fresh
/// blank session. A value is required when the flag is given.
/// Resume a prior claude session by its session id, passed
/// through as `claude --resume <value>` (claude's own
/// `--continue` takes no value — it resumes the cwd's latest
/// session, which is the harness's, so choom never uses it).
/// Omit for a fresh blank session. A value is required when
/// the flag is given.
#[arg(long = "continue", value_name = "SESSION")]
continue_session: Option<String>,
},
@ -1044,16 +1047,20 @@ fn choom(name: &str, continue_session: Option<&str>) -> Result<()> {
let state_dir = format!("/agents/{name}/state");
// Per-turn config the harness writes; matches `paths::config_dir()`.
let cfg = "/run/hive-config";
// `--continue <value>` passes straight through to claude. The value is
// single-quoted into the shell script, so reject an embedded single
// quote (the only char that breaks single-quoting) to rule out
// injection — session ids / display names never contain one.
// `--continue <value>` maps to `claude --resume <value>` — claude's
// own `--continue` is a bare flag (no argument): passing a value
// after it made claude resume the cwd's latest session and treat the
// value as the first PROMPT, silently poking the harness session.
// `--resume <session-id>` is the actual rejoin-by-id surface. The
// value is single-quoted into the shell script, so reject an
// embedded single quote (the only char that breaks single-quoting)
// to rule out injection — session ids never contain one.
let session_arg = match continue_session {
Some(val) => {
if val.contains('\'') {
bail!("invalid --continue value '{val}': must not contain a single quote");
}
format!("set -- --continue '{val}';")
format!("set -- --resume '{val}';")
}
None => "set --;".to_string(),
};