Concepts
brigd
On this page
brigd is an optional daemon that gives other tools one socket to ask Brig through. It keeps the session inventory, and it controls boot and teardown when several callers want the same sandbox.
When to run it #
The CLI has no client for brigd. Every brig command talks to the runtime directly, whether or not brigd runs.
Run brigd in one of these cases:
- A second tool drives several sandboxes from one process.
- A client wants boots on one sandbox serialized across several callers.
brigd uses the same internal/wrap library as the CLI, so it builds a sandbox the same way.
If brigd is not running, brig doctor marks it -- and never !!. The -- mark means absent and not a problem:
-- brigd not running (no socket at ~/.brig/brigd.sock)Scope #
brigd does not proxy exec. It controls the sandbox lifecycle, and the CLI controls the terminal. brig sh gives your terminal to a process in the guest: it replaces itself with the runtime.
Running it #
brigd # $XDG_RUNTIME_DIR/brigd.sock if set, else ~/.brig/brigd.sock
brigd --socket /tmp/brigd.sockbrigd creates the socket with mode 0600, so it belongs to the invoking user alone. The socket controls the lifecycle of sandboxes that hold live credentials.
The kernel limits the length of a unix socket path.
| Platform | Limit |
|---|---|
| macOS | 103 bytes |
| Linux | 107 bytes |
brigd refuses a longer path before the bind. The error names the limit, the length, and the source of the path.
One daemon serves one socket path. If a daemon already serves the path, a second brigd exits non-zero and names that process. It does not take the path over.
The lock is a brigd.sock.lock file beside the socket. The daemon holds the lock while it runs. If the daemon dies, the kernel releases the lock.
Protocol #
The protocol is line-delimited JSON: one request per line, one response per line.
{"v":1,"op":"ensure","agent":"claude-code","name":"refactor"}
{"v":1,"op":"status"}
{"v":1,"op":"stop","agent":"claude-code","name":"refactor"}
{"v":1,"op":"version"}| Request field | Meaning |
|---|---|
v |
The protocol version. See Protocol version |
op |
ensure, status, stop or version |
agent |
A profile name or alias |
name |
The optional session name. It follows the same rules as brig --name |
id |
Optional. See Request id |
A response:
{"v":1,"ok":true,"code":0,"sessions":[{"agent":"claude-code","name":"refactor",
"sandbox":"brig-claude-code-refactor","workspace":"/Users/me/brig/claude-code-refactor",
"running":true}]}An error comes back as {"v":1,"ok":false,"code":...,"error":"..."}, not as a closed connection.
An example with socat:
echo '{"op":"ensure","agent":"claude"}' | socat - UNIX-CONNECT:$HOME/.brig/brigd.sockThe version op #
version returns the build of the daemon. The fields are the same ones that brig version --json prints for the CLI:
{"v":1,"ok":true,"code":0,"version":"v0.2.0",
"commit":"131e3bc5615df5ff74e6b5af9a5bcf2ed42b1d57","commitTime":"2026-09-15T09:36:19Z",
"modified":false}If the build had no git history, commit and commitTime are absent. modified is always present. It is true if the tree had uncommitted changes.
Protocol version #
v is the protocol version. It is 1 today.
| Request | What brigd does |
|---|---|
v is 1 |
Serves it |
No v |
Reads it as version 1 |
A v that brigd does not know |
Refuses it with code 2 and an error that names the versions it speaks |
Every response carries v.
Request id #
A request can carry id, which is any string. The response returns it unchanged. A client that pipelines several requests on one connection can use id to match each response to its request. A request with no id gets a response with no id.
{"v":1,"id":"boot-42","op":"ensure","agent":"claude-code"}
{"v":1,"id":"boot-42","ok":true,"code":0,"sessions":[...]}Exit code #
A response carries code beside error. brigd uses the same codes for the same causes as brig. The CLI reference lists them.
{"v":1,"op":"ensure","agent":"no-such-profile"}
{"v":1,"ok":false,"code":3,"error":"unknown agent \"no-such-profile\""}Peer check #
brigd does not rely on the socket mode alone. On each accepted connection, it reads the uid of the peer from the kernel. The peer cannot forge that uid.
| Platform | Mechanism |
|---|---|
| Linux | SO_PEERCRED |
| macOS | LOCAL_PEERCRED |
If the uid is not its own, brigd writes one line and closes the connection:
{"v":1,"ok":false,"code":1,"error":"connection from uid 1001 refused: this socket serves only its owner, uid 1000"}Session liveness #
For every report, brigd reads running from the runtime and not from the inventory. A sandbox that something else stopped is reported as stopped.
brigd cannot ask the runtime if its binary is gone, a permission error comes back, or containerd is down. The session then carries runningError, and running has no meaning:
{"agent":"claude-code","sandbox":"brig-claude-code","workspace":"/Users/me/brig/claude-code",
"running":false,"runningError":"nerdctl ps: exit status 1: cannot connect to containerd"}Warning Show a session with
runningErroras "cannot tell", not as a stopped sandbox. In that case,running:falsedoes not mean that the sandbox exited.
Warnings #
The messages of a run that you must act on come back as warnings, one line each. Three examples: a credential that was not forwarded and the reason, a secret about to expire, an image that did not verify. The CLI prints the same lines on the terminal.
The progress messages of a run go to the stderr of brigd, not to the client. One example is the line that says a boot started. An ensure with no problems returns no warnings.
Connection limits #
| Limit | Value | What happens past it |
|---|---|---|
| Idle connection | Five minutes with nothing sent | The connection is closed |
| Response delivery | Thirty seconds | The connection is closed |
| Request line | 1 MiB, newline excluded | An error is written to the client, then the connection is closed |
Every read resets the idle deadline. An ensure that boots for a minute does not reach it, and neither does a request that arrives in pieces.
A response is one line of JSON and fits the socket buffer. Only a client that sends a request and then stops reading reaches the delivery limit.
After an over-length request, brigd cannot tell the next request from the rest of that one, so it closes the connection.
brigd sends the over-length error when the request reaches the limit, usually while the client still writes. A client that reads while it writes sees the error. A client that reads only after its write returns sees a broken pipe.
Behaviour #
ensure #
ensure prepares the guest home, resolves credentials, verifies the image and checks the share. Then it boots the sandbox only if needed.
brigd serializes work on one sandbox. Two clients that ask for the same sandbox at the same time get one boot.
No prompts #
brigd never prompts. Image verification prompts when an image that claims to be from Brig does not verify. brigd refuses a request that needs that prompt. The error carries the reason and the setting that overrides it.
To let such a request through, set BRIG_VERIFY=off or fix the image.
Runtime resolution #
brigd resolves the runtime for each request, from the profile that the request names. A profile with runtimeBin uses the same binary through brigd as through the CLI. If a profile names a missing binary, that request fails and no other.
status and stop #
status reads liveness from the runtime, as Session liveness describes. This covers a brig stop that did not go through brigd.
stop stops a running sandbox even if the inventory does not list it.
Restarts #
The inventory is in memory. It holds only what this brigd process did. The runtime is the source of truth.
On start, brigd loads the profile registry and listens. It does not ask the runtime which sandboxes it started before.
After a restart:
- The sandboxes keep running.
statusshows none of them until something asks for them again.brig ls, which reads the runtime directly, shows them throughout.
Stability #
Stability lists the protocol as stable.
Within a version, a field can be added. No field is renamed or removed. A client that ignores unknown fields continues to work. A change that breaks such a client becomes a new version (v: 2). The CLI reference sets the same rule for --json output.