outboundctl
The outboundctl command-line tool: where it lives, how it finds the rule store, what it may change, its output formats and its exit codes.
outboundctl is the command-line companion that ships inside Outbound.app. It reads and writes the same rule store and settings the app uses, so scripts, MDM post-install jobs and terminal sessions can list rules, subscribe to blocklists, export history and more.
The pages in this chapter cover every command. This page covers the parts they all share.
Where the tool lives
Section titled “Where the tool lives”If Outbound is installed in /Applications, its bundled tool is at /Applications/Outbound.app/Contents/MacOS/outboundctl. Run it directly, or add an alias to your shell profile:
alias outboundctl=/Applications/Outbound.app/Contents/MacOS/outboundctlRunning the copy inside the app matters: it is the copy that updates with the app. When another program launches outboundctl for you (the MCP server installer, for example) it registers this same path.
outboundctl reads the saved store directly. Most changes go through Outbound’s background agent, which asks for the same approval the app does and passes the change to the filter extension. Some commands, such as answering an alert or activating a licence, work only through the agent, so the agent must be running. Saving a rule is not confirmation that the filter has accepted it; changes that loosen protection wait for approval in the app.
The rule store
Section titled “The rule store”The rule store is rules.json in the Outbound app group container:
~/Library/Group Containers/5GS535L4GD.com.outboundfirewall.outbound/rules.jsonsettings.json (blocklists, profiles and the app’s policy choices) sits beside it, and so do the audit log, the analytics database and the folders the background agent uses. Rule and settings commands resolve the rules path once per invocation.
Set OUTBOUND_STORE_PATH to work on a different rules file, for example one you are preparing for deployment:
OUTBOUND_STORE_PATH=/tmp/staging/rules.json outboundctl rules listAn empty value counts as unset. The override points at the rules file itself. Settings and store lock files sit beside it. History has its own directory and override, described under history. Symlinks in the override are resolved once at the start of the command.
Running as root
Section titled “Running as root”Under sudo or an MDM post-install script, root’s own home has no app group container, so outboundctl without OUTBOUND_STORE_PATH uses the container of the user signed in at the console instead. When nobody is signed in (a login window or an SSH-only Mac), the tool stops with an error instead of silently writing under /var/root:
running as root with no user logged in at the console; set OUTBOUND_STORE_PATH to the rules file to useRoot-created files keep root as their owner on purpose: a root-owned rules.json or settings.json is how the app recognises an administrator’s override. Inside the console user’s container, new directories and the store’s .bak and .lock files receive that user’s ownership so the app can keep writing there.
Root is the administrator, and it may change rules even when the organisation has turned editing off for users. What root cannot do is bypass the outboundctl switch or the settings lock, and it cannot restore a backup or set a preference that loosens protection. See the settings lock and managed preferences.
What outboundctl may change
Section titled “What outboundctl may change”Settings › Security › Command Line has a picker, outboundctl changes, that decides what the tool may change: “Loosening protection and AI changes always ask; Off makes the command line read-only.”
- Allow tightening: changes that only tighten protection are made straight away; anything that loosens protection asks for your approval in Outbound.
- Ask every time (the default): every change waits for your approval in Outbound.
- Off: read-only. Commands that would change something stop with status 77.
Changes also stop with status 77 when:
- The settings lock covers the area the command changes. Unlock it with an administrator account in the app.
- The organisation has turned off editing of rules (
UsersMayEditRules): the refusal names it and says to run as root to override. Root passes this gate.
prefs set and backup restore also refuse changes that loosen protection, even for root, with status 77. See Security settings.
Previews, plans and requests
Section titled “Previews, plans and requests”--dry-runpreviews a change without making it. For changes that go through the agent, it prints aplan_id, what the change would add, remove or change, and the store revision it was planned against.--plan <id>applies a saved plan. Approval is still required, and a plan made against an older store is refused with status 65.--no-waitreturns while a change waits for approval.outboundctl requests listshows waiting requests,requests status <id>reads a decision without approving it, andrequests cancel <id>withdraws one.outboundctl policy showprints the effective policy and whether each value comes from you or from your organisation.
Closing Terminal, or stopping the command, also closes its waiting approval prompt without applying the change.
Output formats
Section titled “Output formats”Read commands print plain text by default. Add --output to choose another format:
| Format | What you get |
|---|---|
text |
Plain text for reading (the default) |
json |
One JSON document; --json is short for --output json |
ndjson |
One JSON object per line; following commands such as history tail --follow stream this way |
tsv |
Tab-separated rows for spreadsheets and shell tools |
legacy-json |
The older JSON shape of commands such as rules list and history list, kept for existing scripts |
Other flags work with every command:
--quietsuppresses success text but keeps machine output and errors.--timeout <seconds>bounds calls to Outbound’s services (default 30 seconds).
outboundctl schema prints the bundled JSON Schemas for structured replies; outboundctl schema <kind> prints one. In history list, history tail and audit output, small numbers such as 0 and 1 stay numbers (history export writes every JSON Lines value as a string), and following output reaches a file or another program as each batch arrives.
What machine-readable output shows
Section titled “What machine-readable output shows”With --output json, ndjson, tsv or legacy-json, outboundctl follows the same disclosure policy as AI tools. It shows website domains instead of full host names, “address” instead of IP addresses and networks, “local network” for local names, and app names instead of paths. User names are never shown. history list, history tail, history export and alerts list follow the same rule in plain text too, and so does any line of plain text that is a JSON record. See What AI tools can see.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
| 0 | Success, including when something was already in the state you asked for |
| 1 | Runtime failure |
| 2 | Declined: the change was not approved in Outbound |
| 64 | Usage error: unknown command, missing or unknown option, wrong number of arguments |
| 65 | Not valid: a bad rule, address, port, pin, feed or value; a stale plan or revision; an alert that was already answered; or a broken audit chain, naming the first bad sequence |
| 66 | Not found: a rule, blocklist, profile or file |
| 69 | Unavailable: missing analytics, the background agent is off, the request was cancelled, or it timed out |
| 75 | Pending, rate limited or expired |
| 77 | Not allowed: policy, the settings lock, a managed restriction, a missing root key, or audit export without root |
outboundctl help exit-codes prints the same list. Command errors go to stderr with the outboundctl: prefix. Many usage errors also point to outboundctl --help. The MCP server reports protocol and tool errors in its JSON replies.
Help, manual and completions
Section titled “Help, manual and completions”outboundctl --help (or -h, or help) prints the full command list and syntax, and outboundctl help <command> prints one command’s flags. outboundctl version prints the tool’s own version string. Running outboundctl with no command prints the usage text as an error.
The manual page ships inside the app. Copy Outbound.app/Contents/Resources/man/outboundctl.1 to /usr/local/share/man/man1/ to read it with man outboundctl.
Shell completions:
outboundctl completion zsh > ~/.zfunc/_outboundctl # add ~/.zfunc to fpath before compinitsource <(outboundctl completion bash)outboundctl completion fish > ~/.config/fish/completions/outboundctl.fishNew in 1.3
Section titled “New in 1.3”- Answer connection alerts with
alerts list,alerts explainandalerts answer. - Activate, check and release a licence with
license activate,license statusandlicense deactivate. - Allow or block an app for one server with
allowanddeny, for a while with--for. - Speed limits per app with
limit,limit listandlimit clear. - Encrypted DNS status, tests, exceptions and the captive-portal pause with
dns. - A bounded diagnostic capture with
capture. - More rule commands:
rules show,priority,duplicate,merge,global,note,restore-note,repairandapprove. - Review
previewandpromote, and blocklistentries,newandapprove. - History
delete,retention,rotate-keyanddiscard-unreadable. uninstall --all-users, and prefs keyshide-my-connections,allow-scripted-alerts,verify-hostnamesandrule-sounds.