Skip to main content

Headless & CI

byteask with no arguments opens the interactive TUI, which needs a terminal. For scripts, pipelines and CI, use byteask exec - it runs one task to completion and exits.

byteask exec "explain what src/parser.rs does"
byteask exec - # read the prompt from stdin
echo "review this diff" | byteask exec -

You do not need script -q /dev/null or a pty wrapper. If you find yourself reaching for one, you are running the TUI; add exec.


The sandbox - read this first​

The engine's default for shell commands is read-only when sandbox support is available. That is the single most important thing to know about headless runs, because a read-only sandbox means the agent cannot compile anything: cc cannot write its object files, and it cannot even write to TMPDIR. You will see errors like:

clang++: error: unable to make temporary file: Read-only file system

That is the sandbox working as designed, not a broken toolchain.

Platform fallbacks

On Linux without bwrap, and in the current Windows wrapper without sandbox helpers, the wrapper defaults to danger-full-access instead. Do not assume an implicit sandbox in CI. Supply an explicit --sandbox mode and install its platform requirements; the explicit flag prevents that fallback. See Sandboxing for the platform details.

ModeFlagWhat the agent's shell commands can do
read-only(default)Read files, run analysis. No writes anywhere, including TMPDIR.
workspace-write--sandbox workspace-writeRead anywhere; write inside the working directory. Builds, test runs and generated files work.
danger-full-access--sandbox danger-full-accessNo sandbox at all. Only for throwaway containers.

If you want the agent to build, test, or write files, pass --sandbox workspace-write.

byteask exec --sandbox workspace-write "build the project and fix any compile errors"

-s is the short form. Approvals are non-interactive in exec, so there is no prompt to escalate with - the mode you pass on the command line is the mode you get for the whole run.

Tools that are not affected by the sandbox​

The sandbox governs the agent's shell tool. ByteAsk's built-in native tools run as direct children of the engine and are not subject to it, so they work even under the default read-only mode - including the ones that compile and execute code:

FamilyTools
Build / analyse / run C and C++cpp_sanitize (ASan, UBSan, Valgrind), cpp_check, cpp_tidy, cpp_format, cpp_compile_db, cpp_nav, cpp_layout
Performancecpp_perf, cpp_bench
Binaries and debuggingcpp_binary, cpp_symbolize, cpp_decompile, debug, debug_session, debug_attach, debug_record
Online servicescpp_godbolt, cpp_insights, cpp_intrinsic
Grounded documentation searchautosar_ref, mcu_ref, fpga_ref, hft_ref, grid_ref, scpi_ref, x86_ref

So "the sandbox is read-only" does not mean "ByteAsk can only do static analysis". A read-only run can still build your program under AddressSanitizer and run it. What a read-only run cannot do is let the model hand-roll its own clang++ -fsanitize=address ... through the shell.

Native tool output

Native tool calls appear in human-readable output and as tool events in --json, including the tool name, arguments, result, and completion status. If an older installation omits those events, run byteask --update before using the output in a CI pipeline.


Machine-readable output​

--json​

Streams the session as JSON Lines on stdout - one event per line. Use it when a pipeline needs to consume the run rather than a human reading it.

byteask exec --json "list every TODO in src/ with its file and line" > run.jsonl

-o / --output-last-message​

Writes just the agent's final message to a file. Usually what you want when the rest of the transcript is noise.

byteask exec -o review.md "review src/parser.rs and list defects with file:line"
cat review.md

--output-schema - structured output​

Point at a JSON Schema file to request a structured final response that your pipeline can parse and validate. See provider support for the supported schema constraints.

byteask exec --output-schema schema.json -o result.json "…"
jq . result.json

The CLI requests strict output. For an OpenAI-compatible strict schema:

  • every object must set "additionalProperties": false;
  • every property must be listed in that object's "required" array - there are no optional fields.

If you want a field to be omittable, model it as an empty string or an empty array instead.


Recipe: read-only review that proposes fix diffs​

A common CI shape is "review this code, do not touch it, and tell me exactly what to change". Under the default read-only sandbox the agent cannot write files or apply patches - so ask it to return the diffs as data.

Download the ready-made schema:

curl -fsSLO https://code.byteask.ai/patches.schema.json

It describes:

{
"summary": "…",
"patches": [
{ "file": "src/pool.hpp", "unified_diff": "--- a/…\n+++ b/…\n@@ …", "rationale": "…" }
]
}

Run it:

byteask exec \
--sandbox read-only \
--output-schema patches.schema.json \
-o patches.json \
"Review include/pool.hpp for memory-safety defects. Use cpp_sanitize to confirm each finding
at runtime before reporting it. Do not modify any file. Return one patch per file that needs
changing, as a unified diff I can pass to 'git apply'. If a finding has no safe fix, return no
patch for it and explain why in the summary."

Then apply what you agree with:

jq -r '.patches[].unified_diff' patches.json | git apply --check - # dry run
jq -r '.patches[].unified_diff' patches.json | git apply -

Keep investigation separate​

A schema pulls the model toward answering immediately. This is the important one, and it is true on every model, not just some. Once a response schema is attached, the model is biased to produce a conforming answer now rather than to spend turns calling tools first - we have observed a model return {"patches": [], "summary": ""} without opening the file at all.

So --output-schema works best on a final-answer turn, not spread across a long agentic run. If the task needs real investigation, split it:

# 1. investigate, no schema - let the agent use its tools freely
byteask exec --sandbox workspace-write -o findings.md \
"Find and confirm memory-safety bugs in include/. Use cpp_sanitize. Write up what you proved."

# 2. convert the findings into structured patches, with the schema
byteask exec --output-schema patches.schema.json -o patches.json \
"Turn these confirmed findings into unified diffs. $(cat findings.md)"

The instruction "use cpp_sanitize to confirm each finding before reporting it" in the single-command form above is doing real work - without it, a schema-constrained run will often skip straight to an answer.

Provider support​

ByteAsk forwards output schemas to OpenAI, Anthropic, and Gemini using each provider's structured-output format. Providers support different subsets of JSON Schema; Gemini, for example, cannot enforce every keyword. A model server you add yourself must support structured output through its selected API.

Validate the returned JSON against your schema before applying changes in CI. Pin the model, test the schema with that model, and keep the investigation and structured-output steps separate when the task needs tool use.


Other flags worth knowing headless​

FlagWhy it matters in CI
--skip-git-repo-checkRequired when the working directory is not a Git repository.
--ephemeralWrites no session files to disk. Good for ephemeral runners.
--ignore-user-configIgnores ~/.byteask/config.toml so a runner's behaviour does not depend on a stray local file.
--color neverSuppresses ANSI escapes in captured logs.
-m MODELPins the model. Do this in CI - the default can change between releases.

See the CLI Reference for the full flag list.