Skip to content

feat: add a headless CLI for running one task and exiting - #21

Merged
minixalpha merged 6 commits into
mainfrom
claude/cli
Aug 20, 2026
Merged

feat: add a headless CLI for running one task and exiting#21
minixalpha merged 6 commits into
mainfrom
claude/cli

Conversation

@minixalpha

@minixalpha minixalpha commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add a headless CLI that accepts one task through -p / --prompt, --prompt-file, or piped stdin, while preserving the existing interactive REPL for a terminal with no task.
  • Run headless tasks in the process's current directory with a dedicated non-interactive system prompt, a configurable --max-turns budget, and --version support.
  • Define benchmark-safe process behavior: keep the run itself on stdout, send metadata and errors to stderr, return 0 for task outcomes such as turn exhaustion, and return non-zero for invocation, credential, API, or transport failures.
  • Document the new interface in both READMEs, the 0.8.x changelog, and synchronized Chinese and English development notes.

Error handling

  • Preserve Anthropic API error text so benchmark harnesses can classify failures.
  • Catch HTTP transport errors raised after streaming has already begun, report them without an uncaught traceback, and return exit code 1.

Validation

  • .venv/bin/pytest -q — 129 passed
  • Manual piped-task smoke test — created and executed hello.py, then exited 0

Record why the next step is a headless entry point: the benchmark surveys
both conclude that nothing can be measured until the agent can be driven
programmatically end to end.
Fix two broken links, add the release-date placeholder to the version
heading, and write up the first feature the benchmark surveys point at:
a headless CLI with harness-compatible exit codes.
The only way in was an input() loop, so a container — where stdin is at EOF
— made the agent print "Bye!" and exit having done nothing. Nothing about
the harness could be measured, because nothing could drive it end to end.

A task can now arrive three ways: -p/--prompt, --prompt-file, or piped on
stdin (taken as the task whenever stdin is not a terminal). With no task and
a terminal attached, the interactive session opens as before. The run happens
in the process's working directory, and --max-turns caps how many model
replies an unattended run may spend.

Exit codes answer one question: did the harness fail, or did the task?
Everything that is merely a bad outcome — the model gave up, the turn budget
ran out, the work is half done — exits 0 and leaves the verdict to whatever
scores the result, because a benchmark reads a non-zero code as a broken
agent and may pay to retry the trial. Only a run that could not happen exits
non-zero: 1 for missing credentials or an API that kept refusing, 2 for a
misused command line. API errors are printed verbatim, since a harness
classifies a failed run by pattern-matching that text.

A headless run also gets its own system prompt. With no user at the other
end, a clarifying question or a pause for approval ends the run with the task
untouched, which scores exactly like a wrong answer.
@minixalpha
minixalpha merged commit 3fbbdcb into main Aug 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant