From 4399fdef030f172b0043f0ef4a3db9c3cd6e2f0b Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Thu, 19 Feb 2026 11:15:15 -0800 Subject: [PATCH] capture and return claude print output instead of writing directly to stdout --- src/cli.ts | 20 ++++++++++++++------ src/spinner.ts | 4 ++++ src/vm.ts | 10 +++++++++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 2ebc82a..3bc227e 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -132,9 +132,13 @@ program if (opts.print) { spin.text = "Running prompt…" - await vm.claude(worktreeAbs, { prompt, print: opts.print }) - process.stdout.write("\n") - spin.succeed("Prompt complete") + const output = await vm.claude(worktreeAbs, { prompt, print: opts.print }) + if (output) { + spin.stop() + process.stdout.write(output + "\n") + } else { + spin.succeed("Done") + } } else { await vm.claude(worktreeAbs, { prompt, print: opts.print }) } @@ -192,9 +196,13 @@ program if (opts.print) { spin.text = "Running prompt…" - await vm.claude(session.worktree, { prompt, print: opts.print }) - process.stdout.write("\n") - spin.succeed("Prompt complete") + const output = await vm.claude(session.worktree, { prompt, print: opts.print }) + if (output) { + spin.stop() + process.stdout.write(output + "\n") + } else { + spin.succeed("Done") + } } else { spin.succeed("Session ready") await vm.claude(session.worktree, { prompt, print: opts.print }) diff --git a/src/spinner.ts b/src/spinner.ts index 7ef14d0..34d7e36 100644 --- a/src/spinner.ts +++ b/src/spinner.ts @@ -18,5 +18,9 @@ export function spinner(text: string) { clearInterval(id) process.stderr.write(`\r\x1b[2K✖ ${msg}\n`) }, + stop() { + clearInterval(id) + process.stderr.write(`\r\x1b[2K`) + }, } } diff --git a/src/vm.ts b/src/vm.ts index e409a5d..1a62ca0 100644 --- a/src/vm.ts +++ b/src/vm.ts @@ -107,7 +107,7 @@ export async function status(): Promise<"running" | "stopped" | "missing"> { } /** Launch claude in the container at the given workdir. */ -export async function claude(workdir: string, opts?: { prompt?: string; print?: string }): Promise { +export async function claude(workdir: string, opts?: { prompt?: string; print?: string }): Promise { const cwd = containerPath(workdir) const systemPrompt = [ "You are running inside a sandlot container (Apple Container, ubuntu:24.04).", @@ -119,6 +119,14 @@ export async function claude(workdir: string, opts?: { prompt?: string; print?: const args = ["container", "exec", "-it", "--user", USER, "--workdir", cwd, CONTAINER_NAME, CLAUDE_BIN, "--dangerously-skip-permissions", "--model", "claude-opus-4-6", "--append-system-prompt", systemPrompt] if (opts?.print) args.push("-p", opts.print) else if (opts?.prompt) args.push(opts.prompt) + + if (opts?.print) { + const proc = Bun.spawn(args, { stdin: "inherit", stdout: "pipe", stderr: "inherit" }) + const output = await new Response(proc.stdout).text() + await proc.exited + return output + } + const proc = Bun.spawn(args, { stdin: "inherit", stdout: "inherit", stderr: "inherit" }) await proc.exited }