interceptor macos container run <image> --cmd "..." runs an OCI image inside Apple's container runtime (macOS 26+). Sandboxed Linux escape hatch with mounts, env, network policy, and a bounded timeout. Pipe-drain hardening ensures large stdout/stderr (>16-64 KB) never deadlocks.
interceptor macos container run docker.io/library/alpine:3 --cmd "echo hello"
interceptor macos container run docker.io/library/python:3.12 \
--cmd "python -c 'import json; print(json.dumps({\"ok\": True}))'" \
--network off
interceptor macos container run my-image \
--env KEY=val --env DEBUG=1 \
--volume "/Users/me/data:/data:ro" \
--network isolated \
--timeout 30000Returns: { exitCode, stdout, stderr, durationMs, image, command, network }.
--network |
container CLI mapping | Use |
|---|---|---|
off (default) |
--network none |
No outbound traffic. Best for build/test. |
isolated |
--network default |
Container's own NAT; can reach the internet but not the host. |
host |
--network host |
Shares the host's network stack. Use with care. |
--volume host:container[:mode] accepts ro (default) or rw. The host path is expandingTildeInPath-resolved, so ~/Documents/x:/x works. Multiple --volume flags are allowed.
The bridge searches in order, with the first match winning:
INTERCEPTOR_CONTAINER_BIN(env override; full path)/opt/homebrew/bin/container(Apple silicon Homebrew, default)/usr/local/bin/container(Intel / direct .pkg)/Applications/container.app/Contents/MacOS/container(future GUI)
If none are found, the call returns:
container_run: Apple's `container` runtime not found. Searched: <paths>.
Install via `brew install container` (macOS 26+ required), then `container system start`.
A naive Foundation.Process driver typically uses the documented Foundation/Pipe deadlock pattern:
task.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile() // ← deadlocks if child wrote >pipe bufferThe current implementation:
- Installs
readabilityHandleron stdout and stderr beforetask.run()and accumulates each chunk into anNSLock-guardedLockedData. - Resolves the response from
task.terminationHandler(final drain onavailableData, then clear handler, then complete via anAtomicFlagone-shot latch). - SIGTERM at
--timeout, SIGKILL +2s grace if the child ignores SIGTERM. Both timers owned by an@unchecked SendableTimerHolderthat the termination handler cancancelAll()safely.
Acceptance criteria are codified in Tests/InterceptorBridgeTests/ContainerDomainTests.swift.