How it works
Orka is a thin CLI. It shells out to whichever container engine you have installed — it does not speak the Docker API directly.
Isolation model
orka runs the agent inside a container. The agent process has no access to the
host filesystem beyond what you explicitly mount in. API keys and other
environment variables are passed in selectively rather than inherited from the
host shell environment wholesale. All Linux capabilities are dropped at
container start (--cap-drop=ALL); the agent cannot acquire elevated privileges.
Shadow mounts
When a mounted directory contains a .orkashadow file, or when a global
~/.config/orka/orkashadow file exists, orka identifies every file matched
by those patterns and mounts a zero-byte read-only file over each one inside
the container. The matched path is still visible to the agent but its content
is inaccessible and writes are refused. This keeps credentials, proprietary
logic, or other sensitive material out of the agent’s context without
excluding the surrounding directory from the mount.
Both files use .gitignore syntax. Global patterns apply to every mount;
per-repo patterns apply only to the directory they accompany. Per-repo
patterns are evaluated after global ones and can negate global matches with
!. See shadow files for syntax reference and setup.
Backend
orka supports two classes of backend.
Container engines (Docker, Podman, and Apple container in alpha) build an OCI image
for the agent harness and run each session inside a container. orka shells out
to the engine binary — it runs docker build, docker run, and so on as
subprocesses. Behaviour therefore matches whatever version of the engine is
installed on the host. Docker is the default; --engine podman and
--engine container select alternatives. Pass --dry-run to see the exact
commands that would be issued.
Bubblewrap (--engine bubblewrap) is a Linux-only user-namespace sandbox.
It does not build or cache any image. Instead, it bind-mounts a subset of the
host filesystem into a new namespace and runs the agent binary directly. The
agent binary must already be installed on the host. See
choosing a backend for a full comparison.
Agent harnesses
Three agent harnesses are supported: pi, claude-code, and codex. Each harness
has its own Dockerfile and produces a separate image. Images are tagged and
cached independently, so switching harnesses does not invalidate the cache for
others. The harness is selected per invocation with --harness.
Image building
This section applies to container engine backends (Docker, Podman). The bubblewrap backend does not build or cache any image.
orka builds the agent image on every invocation. The base layer — which
installs system packages, agent-browser, and Chromium — changes rarely and is
kept as a separate cached image (orka-base). The agent layer on top, which
installs the agent harness itself, is what gets rebuilt when orka is updated
or a new harness version is pinned with --harness-version. A full cache
bypass is available with --no-cache.
To replace the base layer with a custom one — for example to use a different
distribution or strip agent-browser — place a Dockerfile.base in
~/.config/orka/. See custom base image for details.
User and permission mirroring
For container engine backends, orka reads the invoking user’s UID, GID, and username from the host and passes them as build arguments. The container image creates a matching user before starting the agent. Files written inside the container are therefore owned by the host user, not root, and paths that include the home directory resolve correctly because the username matches.
At run time the two engines reach that result differently. Docker is given
--user uid:gid. Podman is given --userns=keep-id instead, which maps the
host user into the container at the same UID on its own. The two are not
combined: --user would make Podman look the numeric UID back up as a name,
which fails outright for users who live in LDAP or sssd rather than
/etc/passwd.
For the bubblewrap backend, no user mapping is needed. The agent process runs as the invoking user directly.
Inspecting a run
Pass --dry-run to print the exact build and run commands that would be issued without executing them. Because orka shells out to the engine binary, the output is a literal sequence of commands you can copy and run yourself.