roba
A single-prompt CLI runner built on top of claude -p. One invocation,
one answer, done -- but with composable input, pipe-clean output,
sessions you can re-enter without living in them, and a stable scripting
ABI for agents and scripts.
- For humans -- what
claude -pcould be: build the prompt from files / stdin / git context, get rendered markdown on a TTY, save flag bundles as profiles, browse history, track cost. - For agents in Claude Code
-- a stable contract: stdout is the answer, stderr is metadata, a
versioned
--jsonenvelope, typed exit codes, and--tracefor observing a run in flight.
Built on claude-wrapper.
$ roba "summarize the rust ownership model in 3 bullets"
Rust's ownership model rests on three rules:
• Each value has a single owner.
• When the owner goes out of scope, the value is dropped.
• Borrows are either many immutable or one mutable.
tokens 1.2k/450 · 2.0s · session abc12345
Install
# or: brew install joshrotenberg/brew/roba
roba shells out to the claude binary, so you need
claude-code installed and
authenticated (or ANTHROPIC_API_KEY set) on your PATH.
The full flag, env-var, and config reference lives in the binary:
roba --help. This README is the conceptual tour.
Why not just claude -p?
claude -p is the one-shot primitive: one prompt in, the response to
stdout, exit. It's perfect for a quick "just answer this string" with no
piping, no file context, no continuity. roba doesn't replace it -- it
gives that same one-invocation-one-answer model a richer surface, for
when you want any of:
- Composable input. Build the prompt from more than a string: a
file (
-f), piped stdin, an editor buffer (-e),--prepend/--appendfiles, glob-embedded files (--attach), git context (--git-diff/--git-log/--git-status), and{{KEY}}template vars (--var). - Pipe-clean output. stdout is the answer and only the answer;
every bit of metadata (cost footer, spinner, tool-call lines, refusal
warnings) goes to stderr.
roba "..." | jqalways sees a clean pipe. - Rich on a TTY. Rendered markdown, a spinner, dim metadata, colored
markers -- a transient UI that exists while roba works and evaporates
when the answer lands.
--plain(orNO_COLOR) turns it all off. - Session re-entry without living in a session.
-ccontinues the most recent session in the directory,-c IDresumes a specific one,--forkbranches it,--pickis a fuzzy chooser;roba history/roba lastbrowse past runs. You dip back into a thread without opening the TUI. - A real ABI. Typed exit codes, a versioned
--jsonenvelope, and a clean stream split -- so a script or agent can pin a contract instead of scraping prose. (See For agents & scripts.)
Same one-shot model, a citizen of the pipe. For interactive,
multi-turn work, reach for claude itself; for multiple providers,
a tool like llm. roba is Claude-only by
design -- the Claude-Code-native integration (sessions, permissions,
history) is the point.
Quick examples
# Just ask
# Compose: preamble + question + appendix
# Pull in files by glob
# Read-only review against the working-tree diff
# Continue the most recent session here (pass the prompt with -p, since
# -c takes an optional session id)
# Pipe-friendly: answer only, stdin in
|
[!NOTE]
-c(continue) and-w(worktree) take an optional value, so a space-separated word right after them is read as that value:roba -c "follow up"treatsfollow upas the session id. Pass the prompt explicitly with-pto disambiguate:roba -c -p "follow up".
Safe by default
roba starts read-only: claude may use Read, Glob, and Grep and
nothing else. You opt into more, explicitly:
This came from a real "oops" -- a streaming run quietly let claude
create a git branch when the user just wanted a chat. The default
doesn't regress. --permission-mode additionally sets claude's own
approval mode (plan, acceptEdits, ...), orthogonal to the
allow-list. Precedence across all layers: CLI flag > ROBA_* env >
profile > built-in default, and deny always wins over allow.
Configuration: profiles & aliases
A roba.toml lets you stop retyping flags and define your own verbs.
Files are discovered by walking up from the cwd (plus
~/.config/roba.toml); closer-to-cwd wins per key.
- Profiles are named bundles of flag defaults:
--profile reviewapplies[profile.review]. Adefaultprofile auto-applies. - Aliases are new verbs:
roba review 42expands an[alias.review]prompt template (with${1}/${pr}/$(...)shell substitution) plus default flags, and dispatches like a normal call. This is how you keep roba's built-in surface generic -- your domain knowledge lives in your aliases, not the binary.
The fully-commented roba-config.sample.toml
documents every key with worked examples; roba profile init drops it
in your project. Inspect with roba profile {list,show,active} and
roba alias {list,show}.
For agents & scripts
When something other than a human is calling, roba is a much cleaner ABI
than claude -p:
- stdout = the answer, stderr = everything else.
roba "..." | jqnever sees decoration. - Versioned
--jsonenvelope. Success:{ "version": 1, "result": { ... }, "refusal": bool }. Failure:{ "version": 1, "error": { kind, message, exit_code, chain } }. Pinversionand you've pinned the shape. - Typed exit codes:
0ok,1generic,2auth,3budget,4timeout. --no-retrysurfaces transient failures immediately (the caller decides whether to retry), and--trace PATHwrites the spawned session's events as JSONL so you can observe a run in flight.--dispatchis the unattended preset (--full-auto --worktree --fresh) for firing a worker that edits files in its own sandbox.
For an agent that invokes roba, skills/use-roba/SKILL.md
documents this contract in agent-readable form -- copy it to
~/.claude/skills/use-roba/SKILL.md.
Bring your own skills and agents
roba is a pure mechanical wrapper -- no bundled skill or agent library.
Drop skills into ~/.claude/skills/ and agents into ~/.claude/agents/;
Claude Code auto-discovers them. joshrotenberg/agent-tools
is one curated set if you want a starting point.
Status
Published on crates.io. The CLI surface (flag names, exit codes, config
schema, --json envelope) is intended to be stable across 0.x; the
library API (roba::*, for integration testing) may shift between minor
versions.
License
MIT OR Apache-2.0