Print mode

Print mode (-p / --print) runs IsonForge non-interactively. No REPL, no permission prompts, no live UI. Output streams to stdout, the process exits when done.

isonforge -p "<prompt>"

Print mode implies --yolo (all tools auto-approved) because there's no human in the loop to answer prompts. Set --max-turns and --max-budget-usd to keep autonomous runs bounded.

Reading stdin

If stdin is a pipe, IsonForge prepends its content to your prompt:

tail -200 app.log | isonforge -p "summarize anomalies"
git diff main | isonforge -p "find security issues in this diff"
cat README.md | isonforge -p "translate to Bahasa Indonesia"

Output formats

--output-format text (default) streams raw model content as it arrives. No extra wrapping.

--output-format json suppresses raw streaming and emits a single envelope at the end:

{
  "content": "...",
  "usage": {"input_tokens": 1234, "output_tokens": 567},
  "cost_usd": 0.0,
  "turns": 3,
  "tool_calls": [
    {"name": "read_file", "arguments": {"path": "src/auth.py"}},
    {"name": "edit_file", "arguments": {"path": "src/auth.py", "old_string": "...", "new_string": "..."}}
  ]
}

--output-format stream-json emits chunks as SSE-ish events (tool calls, deltas, usage). Use for streaming integration.

JSON-schema enforcement

--json-schema forces the final output to validate against a schema. Schema can be inline:

isonforge -p \
  --output-format json \
  --json-schema '{"type":"object","properties":{"summary":{"type":"string"},"severity":{"type":"string","enum":["low","med","high"]}},"required":["summary","severity"]}' \
  "review this code"

Or from a file:

isonforge -p --json-schema "$(cat ./schemas/review.json)" "review"

Schema is passed through to the backend's guided decoding so the model literally cannot produce invalid JSON. The content field in the JSON envelope is the schema-validated payload as a string. Parse it with jq:

isonforge -p --output-format json --json-schema "$(cat schema.json)" "extract" \
  | jq -r '.content | fromjson | .summary'

Budget caps

--max-turns <n> clamps the agentic loop. If the model would need more turns, it exits with code 2.

--max-budget-usd <usd> tracks cumulative cost from the streamed usage deltas and exits at the cap. Rate environment variables:

ISONFORGE_RATE_IN=0.50 ISONFORGE_RATE_OUT=2.00 \
  isonforge -p --max-budget-usd 0.10 "find the bug"

Rates are USD per million tokens. Default 0 / 0 (self-hosted, no per-token billing) makes the cap a no-op. Set explicit rates if you're routing IsonForge to a metered backend.

System prompt overrides

Print mode honors all four system-prompt flags. Useful for one-off agent configurations:

isonforge -p \
  --append-system-prompt "Output ONLY JSON. No prose. No code fences." \
  --output-format json \
  "extract structured data from stdin" < input.txt

For fully scripted, non-coding agents, replace the prompt entirely:

isonforge -p --system-prompt-file ./prompts/translator.txt "translate"

When you --system-prompt (or --system-prompt-file) replace, the default tool guidance, FORGE.md injection, and project metadata are all dropped. You take responsibility for whatever the task needs.

See System prompt customization.

Exit codes in scripts

Code Meaning
0 Success
1 General error
2 Budget hit (--max-turns or --max-budget-usd), or UserPromptSubmit hook blocked
130 Interrupted
isonforge -p --max-budget-usd 1.00 "audit" || echo "stopped at budget cap"

CI examples

Translate new strings on a PR:

isonforge -p "translate all new strings in i18n/en.json into Indonesian and write i18n/id.json"

Security review every diff:

- name: Security review
  env:
    ISONFORGE_API_KEY: ${{ secrets.ISONFORGE_API_KEY }}
  run: |
    git diff origin/main...HEAD | isonforge -p \
      --output-format json \
      --max-turns 5 \
      --append-system-prompt "Flag only real security issues. Be terse." \
      "review this diff" > review.json
    jq -r '.content' review.json

Bulk operations across files:

git diff main --name-only | xargs -I{} isonforge -p "summarize what changed in {}"

Not in print mode

These don't apply in print mode (no REPL):

For non-interactive use of those features, configure them via flags or settings instead.