Shebang scripts
Shebang scripts are a CLI-only feature. They are not available in the
interactive shell.
contree run -I shebang runs inside a sandbox:
chmod +x, and run it directly:
-I (interpreter) flag reads the script, strips the shebang line, and
sends the body as stdin to /bin/sh -s inside the sandbox.
Combining flags
Shebang flags stack. A disposable run with a 10-second timeout:-D is set, the session image is not advanced – the script runs in
a throwaway sandbox.
Passing arguments
Extra arguments after the script name are forwarded to the shell:The
-S flag on /usr/bin/env is required because the contree entry point
is a Python script. Without -S, the kernel sees a nested shebang
(script -> script -> binary) and returns ENOEXEC. Using /usr/bin/env -S
(a real binary) splits the argument string and avoids this.Execution modes
Direct command
The default mode. Each positional argument becomes a separate argv entry:Shell mode
-s joins all arguments into a single shell expression:
- CLI
- Shell
&& chains.
Piped stdin
Piped stdin is a CLI-only feature. It is not available in the interactive
shell.
Detached mode
-d spawns the operation and exits immediately, printing the operation UUID:
- CLI
- Shell
Exit codes
Exit code propagation is a CLI-only feature useful for scripting. The
interactive shell does not expose sandbox exit codes.
contree run works naturally in if, &&, ||, and set -e
scripts:
Environment variables
Pass environment variables into the sandbox with-e:
- CLI
- Shell
KEY=VALUE.
Output truncation
By default, stdout/stderr is capped at 64 KiB in the API response. Override with-T:
Monitor operations
List running and recent operations:Fan-out + wait
When several independent steps can run at the same time, spawn each one detached and join them withcontree op wait (alias contree operation wait). The wait command polls the API and prints one row
per operation as soon as it reaches a terminal status, with columns
uuid, status, exit_code, timed_out, duration, and any other
scalar field the API returns. The status column is the server’s
verdict (did the API run the job?) and is reported verbatim; the
sandbox process’s own exit code is in the separate exit_code column.
The CLI exit status is 1 when any op finished non-SUCCESS, or the
actual exit_code when a SUCCESS op exited non-zero, so the wait
still composes naturally with &&.
op wait is a pure observer — it polls completion status but
does not touch local session state. That makes the pattern most
natural with --disposable (no image to track). For non-disposable
fan-out, the result images live only on the server; the
detached-<op-uuid> branches created at spawn time still point at
the starting image and never get moved. See the non-disposable
recovery example below.-f json must come BEFORE the subcommand so that jq
gets JSON; the default run -d formatter is plain.
op wait will not bind them into the session:
detached-<op-uuid>
branch per spawn. They all point at the image that existed when the
fan-out started, so they are mostly cosmetic — feel free to delete
them with contree session branch --prune when you no longer need
them.
Useful flags:
--timeout SECONDS— cap on the wait (default 60). If the deadline hits before every operation reaches a terminal status,op waitemits one extra row per unfinished op withtimed_out=trueand the operation’s last observed status (e.g.EXECUTING), then exits with status1.--all— wait for every currently active operation in the project, not just the ones you passed.
op wait exits non-zero whenever any operation finished with a
non-SUCCESS status (so it composes naturally with shell &&
chains), even when no --timeout was hit.
Scripting patterns
Shell piping and command substitution are CLI-only features. These patterns
are not available in the interactive shell.
-q with other tools:
Output formats
The
--format flag is global and set at CLI launch time. In the interactive
shell, the format is fixed for the entire session and cannot be changed
mid-session.-f / --format to control output. The flag is global and goes
before the subcommand:
default
: Table-like output optimized for human reading. Some commands (like
run) use a custom default that prints only stdout/stderr.
table
: Aligned columns with headers. Identical to default for most commands.
csv
: Comma-separated values with a header row. Useful for spreadsheet import
or cut/awk processing.
tsv
: Tab-separated values with a header row. Works well with column -t.
json
: One JSON object per line (JSONL/NDJSON). Each output row is a separate
JSON object. Suitable for jq processing.
json-pretty
: All rows collected into a single pretty-printed JSON array. Output is
flushed at the end.
Examples
Streaming behavior
json and json-pretty formatters support streaming output from
commands like run and show – stdout/stderr are included in the
JSON payload.
csv, tsv, and table formatters do not include stdout/stderr
from sandbox execution. Use default or json formats to see
sandbox output.
Session management in scripts
Script-level session management with
eval and CONTREE_SESSION is a
CLI-only pattern. The interactive shell manages sessions automatically.eval $(contree use ...) pattern exports the session key into your
shell. In scripts, set CONTREE_SESSION explicitly to control which
session you operate on:
$$ (PID) or a fixed name gives you a predictable, isolated session
per script run.
You now know the full CLI. Next: Configuration & Profiles.