An exec is one command run inside a box. Foreground exec keeps output and exit code in your current terminal. Background exec lets the work continue after you disconnect.
Foreground
sys9 run box exec <box-id> [flags] <command...>
Add -- only when the remote command itself starts with flag-like tokens and you need to stop local flag parsing.
Common flags:
--deadline--user--workdir-e KEY=VALUE-i-t
Foreground exec stays attached to the current connection.
Use -i to keep local stdin open. Add -t for terminal programs such as shells or TUIs.
Prefer exec flags over shell glue when only the command context changes:
sys9 run box exec my-box --workdir /work/app git status
sys9 run box exec my-box -e NODE_ENV=test printenv NODE_ENV
Save shell wrappers for commands that actually need shell syntax such as pipes, redirections, or here-docs.
box exec streams remote output directly and returns the remote exit code. It does not support --json or --output json.
Background
sys9 run box exec-bg <box-id> [flags] <command...>
sys9 run box exec-bg pull-output <exec-id> [--wait <duration>] [--cursor <token> | --from-start]
sys9 run box exec-bg write-stdin <exec-id> [--eof]
sys9 run box exec-bg kill <exec-id>
Background exec starts work and prints the exec_id, current state, deadlines, and the command to read output.
Background exec works well for servers, watchers, long tests, or other work you plan to inspect later.
Use JSON when a script needs the full exec view:
sys9 run --json box exec-bg my-box sleep 30
pull-output is also a stream command. It renders mixed background output and rejects --json.
write-stdin and kill print short OK: confirmations by default and support JSON for automation.
History
sys9 run box execs ls <box-id> [--limit <n>] [--cursor <token>]
sys9 run box execs inspect <exec-id>
Use history when you need the state, command, exit code, or output cursor for an exec.
execs ls prints a table by default. If there is another page, it prints the next cursor command. Use --json to include items and next_cursor in stdout.