raunen

Scripting

A prompt as an argument runs one turn and exits. That is enough to drop raunen into a pipeline โ€” or, with --json, into a program.

Plain text

The answer goes to stdout and everything else โ€” thinking, tool calls, switches, warnings โ€” to stderr, so a pipe gets the reply and nothing else:

shell
$ raunen 'summarise the diff on this branch' | pbcopy

Machine-readable

When a program consumes the result, --json prints one document instead:

shell
$ raunen --json 'what does main.go do?'
{
  "output": "It parses flags, loads the config, and starts either the TUI or a\n"
              "single one-shot turn.",
  "exit_code": 0,
  "model": "ollama/qwen3.5:latest",
  "session_id": "20260820-091144-2ee0",
  "steps": 2,
  "tool_calls": [
    { "name": "read", "status": "success" },
    { "name": "grep", "status": "success" }
  ],
  "usage": { "prompt": 4192, "completion": 210, "total": 4402 }
}

raunen --json 'review this branch' | jq -r .output for the prose, or jq -e '.tool_calls[] | select(.status=="error")' to fail a pipeline when a tool did.

Failed runs still print JSON

The document is printed even when the run fails, with the reason in error โ€” a consumer parsing stdout should never have to handle "sometimes there is JSON and sometimes there is not":

failure
{
  "output": "",
  "error": "This request requires more credits, or fewer max_tokens.",
  "exit_code": 1,
  "model": "openrouter/moonshotai/kimi-k3",
  "tool_calls": [],
  "usage": { "total": 0 }
}

tool_calls is always an array, never null, so it can be measured on a turn that called nothing. A tool that failed is reported as "status": "error" with the message, but does not fail the run โ€” the model is told and usually recovers. And model is the model that answered, which is not always the one asked for, since escalation can move up the ladder mid-turn.

ExitMeaning
0the turn finished
1it failed; error says why
130interrupted with ctrl+c

130 is the shell's convention for SIGINT, there so a script can tell "the user stopped this" from "the model failed". An interrupted run still prints its document, with whatever the model had produced in output.

The session is saved either way

A one-shot turn and an interactive one produce the same kind of conversation, so raunen 'question' followed by raunen --continue picks it up. --no-save opts out for a throwaway question, and then session_id is empty rather than naming a session that was never written. The conversation is saved before the result is reported, so a turn that ran out of context is still resumable.