From 19e137da1dc517e0d8fffbbf333df9418a3a7e8f Mon Sep 17 00:00:00 2001 From: hbrooks Date: Fri, 17 Jul 2026 18:14:07 -0400 Subject: [PATCH] bare agent: start the session idle and wait for the first message A promptless connect start (what a bare `agent` expands to) now sends idle_start on POST /v1/sessions: the sandbox spins up, Claude Code sits idle at the prompt, and the first thing typed into the composer opens turn 0, like a local `claude`. Previously the server fabricated a workflow kickoff whenever the resolved config carried a claude.system, so a bare `agent` on a dev-box config opened with "Carry out the workflow instructions in your system prompt." and no instructions to carry out. A promptless --watch/--detach start still runs the config's workflow; only the interactive open changes. Servers without the field ignore it and keep today's behavior. --- src/cli.tsx | 7 +++++-- src/commands/session.tsx | 6 ++++++ src/lib/types.ts | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/cli.tsx b/src/cli.tsx index 99c460b..6b90b7d 100644 --- a/src/cli.tsx +++ b/src/cli.tsx @@ -46,8 +46,11 @@ registerPing(program) // Any invocation that isn't a known subcommand or a top-level help/version // request is shorthand for `agent session start --connect ...`. So a bare // `agent`, and `agent "fix the tests" --model ...`, both forward the prompt -// and every trailing flag through to a fresh connected session. `agent --help`, -// `agent --version`, `agent help`, and every subcommand dispatch unchanged. +// and every trailing flag through to a fresh connected session. A bare +// `agent` starts the session idle (idle_start): the sandbox spins up and +// Claude Code waits for the first thing typed into the composer, like a +// local `claude`. `agent --help`, `agent --version`, `agent help`, and every +// subcommand dispatch unchanged. const topLevelCommands = new Set([ 'help', ...program.commands.flatMap((c) => [c.name(), ...c.aliases()]), diff --git a/src/commands/session.tsx b/src/commands/session.tsx index 7ab9b7c..efd79ad 100644 --- a/src/commands/session.tsx +++ b/src/commands/session.tsx @@ -220,6 +220,12 @@ export function registerSession(program: Command): void { // Appended to the initial user query at build time; gives this // session instructions on top of the config's shared system prompt. if (promptText) req.prompt = promptText + // A promptless connect (a bare `agent`) starts the session idle: + // no fabricated kickoff message, Claude Code waits at the prompt + // for whatever is typed into the composer, like a local `claude`. + // A promptless --watch/--detach start still runs the config's + // workflow, so this only applies to the interactive open. + if (opts.connect && !promptText) req.idle_start = true const api = new ApiClient() const session = await api.startAgentSession(req) diff --git a/src/lib/types.ts b/src/lib/types.ts index 5bb0c39..26e07bf 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -197,6 +197,12 @@ export interface StartAgentSessionRequest { // after the config's shared `claude.system` system prompt. Distinct from the // system prompt, which is identical for every session of a config. prompt?: string + // Start with no initial message: the sandbox spins up, Claude Code sits idle + // at the prompt, and the first message sent to the session opens turn 0, + // exactly like a local `claude`. Sent for a promptless --connect start (a + // bare `agent`). Mutually exclusive with prompt; the server ignores it when + // the resolved config is not interactive (that session runs its workflow). + idle_start?: boolean } // Replay payload for POST /v1/sessions/{id}/replay. Re-runs an existing