Devin CLI by Cognition, signed in from inside the sandbox and resolved by the sandbox proxy there...
215
Devin CLI by Cognition, signed in from inside the sandbox and resolved by the sandbox proxy thereafter.
| Name | Required | Default | Description |
|---|---|---|---|
version | Optional | 3000.10.31 | Devin CLI release to install |
[email protected], deb/[email protected], deb/[email protected], deb/base-files@14, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/ca-certificates-java@20260311, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/gcc-16-base@16, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/less@668, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/libgcc-s1@16, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/libjpeg8@8, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/libstdc++6@16, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected], deb/tzdata@2026, deb/[email protected], deb/[email protected], deb/[email protected], deb/[email protected]| Type | Required | Description | |
|---|---|---|---|
com.docker.sandbox/sbx@1 | Required | — | |
com.docker.sandbox/network-policy@1 | Required | — | |
com.docker.sandbox/credential@1 | Optional | Devin account credential captured during in-sandbox login | |
com.docker.sandbox/lifecycle@1 | Required | — | |
com.docker.sandbox/agent-context@1 | Required | — | |
sbx run docker/sbx-kit-devin:latestRun the following command to install sbx on your machine.
brew install docker/tap/sbxwinget install Docker.sbxNote
Experimental: Sandbox Kit v3This kit uses the experimental Sandbox Kit specification, specifically v3. The format and runtime behavior may change before v3 is stable.
A standalone workload kit (kind: workload, schemaVersion: "3") for
Devin CLI, Cognition's terminal coding agent. The kit runs
devin --permission-mode dangerous --respect-workspace-trust=false as the
entrypoint and declares one credential — devin — that is captured when you
sign in from inside the sandbox and resolved by the sandbox proxy on every
request after that.
devin was previously a built-in sbx agent, run as sbx run devin. This kit
replaces that, and its content is built from
devin.dockerfile in this directory rather than taken
from the docker/sandbox-templates release train.
There is also a devin-mixin variant of the same kit, for
layering the CLI onto a shell workload instead of running a sandbox of its
own.
None, and unlike the sibling kits that is the expected path rather than a degraded one. Devin's durable credential only comes into existence once an account has signed in, so the usual sequence is: the first sandbox signs in interactively, the proxy captures what that sign-in produces, and later sandboxes reuse it with no prompt.
Nothing is stored under a name you have to know, but the service key is devin
if you want to look — or to bind a key you already hold:
sbx secret ls
sbx secret set devin # only if you already have a Devin key to paste
sbx run "docker.io/docker/sbx-kit-devin:latest"
Or from a git URL targeting this repo:
sbx run "git+https://github.com/docker/sbx-kits-contrib.git#dir=devin"
Or with a local clone of this repo:
sbx run ./devin/
The trailing devin is required, not redundant: sbx enforces that the agent
name matches the capability the kit provides, which here is devin. A v3
descriptor carries no name: of its own — identity is the reference the kit
is consumed by, and provides: is what the resolver matches on.
The entrypoint is devin --permission-mode dangerous --respect-workspace-trust=false, so anything you pass is appended to that and
reaches Devin CLI unchanged.
Neither flag is an invitation to be careless; both are what make the session usable at all.
--permission-mode dangerous auto-approves tool calls. The container is
the sandbox, and a per-tool approval prompt with nobody attached to answer it
deadlocks. The CLI's own rejection message — not its --help prose, which
disagrees — is the authority on the accepted values: normal (auto),
accept-edits, dangerous (yolo, bypass), autonomous (requires
--sandbox). So the bypass spelling from the published docs is an alias of
this one, and autonomous is unusable here because it additionally demands
the CLI's own process sandbox inside the container.--respect-workspace-trust=false turns off the "is this directory
trusted?" gate. The workspace is the entire reason the sandbox exists. The
= is load-bearing: the flag takes an optional value, so the
space-separated form would leave false free to be swallowed as the
positional prompt argument.| Service | Env var | proxyManaged | required | Injected into |
|---|---|---|---|---|
devin | none — see below | n/a | no | server.codeium.com, api.devin.ai (Authorization: Bearer) — plus OAuth, below |
One service, two halves of one contract, because Devin's sign-in and Devin's steady-state authentication use different credentials:
api.devin.ai/auth/cli/token returns a single field, token, and that
token is an intermediate: the CLI spends it within seconds on a further
request that mints the account's durable key.~/.local/share/devin/credentials.toml as windsurf_api_key and sends as a
bearer to the two injected hosts above.So the oauth block describes step 1 and the apiKey block describes step 2,
and the host binds both under the one name the proxy routes on.
apiKey.name is emptyDevin CLI does not read its credential from an environment variable at all — it
reads credentials.toml. An empty name means the engine sets no in-container
variable, which is exactly right: that half of the credential exists only to
declare the outbound injection contract.
scripts/verify-kit-spec reports this as a warning
("no in-container environment variable will be set for this credential") —
and exits non-zero on it, though it gates no CI. The warning describes the
intent correctly; naming a variable to silence it would put a value somewhere
nothing reads it.
The oauth block sets passthrough: true and declares no sentinels, which
is legal only because of that flag. The container has to receive the real
intermediate token, because the CLI immediately embeds it in a protobuf request
body — and header-level sentinel substitution cannot reach inside a protobuf
body. A masked token would fail sign-in outright rather than degrade.
This is a security downgrade and it is scoped as tightly as it can be. The intermediate is spent within seconds. The durable key that replaces it never stays in the container in usable form:
credentials.toml with the proxy's placeholder
(devin-proxy-managed) in place of the key whenever the host already holds
one.devin on PATH is devin-entrypoint.sh, not the
CLI; the real binary is installed alongside it as devin-cli. The wrapper does
three things no declarative spec field can:
devin-cli auth login --force-manual-token-flow when there is nothing
to authenticate with. No browser runs in the sandbox, so the default
localhost redirect never comes back; the manual token flow is Devin's own
answer for that case, documented for remote and SSH sessions. It prints a
URL to open on your machine and reads the token back.It execs the CLI at the end, so Ctrl-C and SIGTERM reach Devin directly
rather than a shell that would have to forward them.
No telemetry environment variable is set, and that is a deliberate blank rather than an oversight. Devin CLI publishes no documented opt-out variable that this kit could verify against the shipped binary, and the sibling kits' rule for this is to throw a switch that exists — not to guess at one. A variable name invented here would read as a control while controlling nothing.
The kit achieves the same effect two other ways, and neither depends on a name staying stable:
runtime allow list. Devin CLI reaches a third-party Sentry
endpoint on a crash; under deny-all it simply cannot. A sandbox has no
business reporting to a third party on your behalf.{"auto_update": false} written to
~/.config/devin/config.json. Inside a sandbox an unannounced binary swap
under a running session is a hazard rather than a convenience.
cli.devin.ai and static.devin.ai stay allowed at run time as well as
build time (both fall under the *.devin.ai entry, below),
for version checks and for an explicitly-requested update. Note that the
installer refuses to overwrite a non-symlink at ~/.local/bin/devin, which
is where this kit's wrapper lives, so an update that re-runs the install
script will stop rather than replace it.unleash.codeium.com is allowed, and it is a feature-flag service rather
than a telemetry sink. It is also not inert: with that host blocked, the CLI
was observed handing out the windsurf.com sign-in URL instead of the
app.devin.ai one, so the flags it serves reach the login path. Blocking it
changes behaviour rather than quieting anything.
When the sandbox has an MCP gateway, a lifecycle@1 startup hook writes
~/.config/devin/mcp_config.json:
{
"mcpServers": {
"mcp-gateway": {
"url": "$MCP_GATEWAY_URL",
"transport": "http",
"headers": { "Authorization": "Bearer $MCP_SENTINEL_TOKEN_NAME" }
}
}
}
The header carries the sentinel name, never a token — the proxy substitutes the real one per request. With no gateway the hook exits without doing anything.
The file is written directly rather than by shelling out to devin mcp add,
which puts the exact key names in the descriptor rather than behind a CLI
whose output shape nothing here asserts. transport is Devin's spelling; the
three wrong answers nearest to hand are type (Codex's and opencode's),
httpUrl (Gemini's) and http_headers (Codex's spelling of headers). Devin keeps MCP
servers in mcp_config.json alone — its other settings live in the sibling
config.json — so the file is rewritten whole rather than merged, which is
also what makes re-running it on every container start converge instead of
accumulate.
The network-policy@1 capability's runtime allow list names Devin's own
hosts (collapsed to a single *.devin.ai wildcard, below), the alternate
sign-in host, the Codeium backend the model and seat services still live on,
and the apt sources the base image ships — which the startup apt-get update
fails wholesale without.
Everything is in the runtime phase and there is no install phase: the CLI
is installed at build time, which no phase of the policy scopes, and both
lifecycle hooks are startup hooks, which run at boot — so their hosts belong
to the runtime phase rather than to an install list that would already be
closed by then.
api.devin.ai appears both under the wildcard and as a literal entry. The
wildcard is what the kit means; the literal is there because v3 checks
credential inject domains against the allow list by exact host match and
deliberately does not expand narrower globs, so that a published inject domain
stays auditable. It grants nothing the wildcard did not already cover.
*.devin.ai covers Devin's own hosts — api.devin.ai (the API the CLI talks
to and the OAuth token endpoint), app.devin.ai (the sign-in page),
cli.devin.ai (install.sh) and static.devin.ai (the install manifest and
versioned bundle) — so that a new devin.ai subdomain doesn't strand the kit
under deny-all. The wildcard matches exactly one DNS label, so it does not
cover the bare apex devin.ai; nothing in this spec requests that host, so it
is not listed either. It also covers api.devin.ai as an apiKey.inject[]
domain and as the OAuth tokenEndpoint host without a separate literal
entry — the inject-coverage check scripts/verify-kit-spec runs
(spec/validate.go's allowListCovers) is wildcard-aware and mirrors the
engine's own runtime matching, not a literal string comparison.
Devin CLI is built on the Windsurf/Codeium codebase, which is why
server.codeium.com and unleash.codeium.com are not strays: without the
first the CLI authenticates and then cannot answer a prompt. windsurf.com
appears for the same lineage reason — which of it and app.devin.ai an account
is sent to for sign-in is decided server-side, so both are allowed rather than
betting on one and leaving half of all accounts unable to log in.
Entries carry no port. A portless pattern matches any port, and pinning the apt
hosts to :80 breaks as soon as a mirror answers over HTTPS, with that same
wholesale failure.
Three omissions are deliberate:
server-beta.codeium.com. Not the default backend, and adding a host on
speculation is how an allow-list stops describing anything.registry.npmjs.org and the GitHub hosts. Devin reaches those only for
things you start — an npx-launched MCP server, a clone — and allowing them
by default would widen every sandbox's egress for a path most sessions never
take. Compose a mixin that declares them, or add them in a fork.Tip
If something fails under `sbx policy init deny-all`, inspect what was blocked and widen the list:$ sbx policy logthen add the reported hosts to the
network-policy@1capability'sruntime.allowlist indevin.yaml.
The kit declares agent-context@1 with filename: AGENTS.md, which Devin
reads from the workspace root. It has no product-specific profile file of its
own — its rules command covers .windsurf/rules and .cursor/rules
directories, which are a different mechanism from the single profile file this
field names.
The kit also contributes a body, devin-context.md, which
v2 deliberately went without — the reasoning then was that an AGENTS.md
section saying little costs context on every session. v3 surfaces kit context
progressively: the profile carries a per-kit index and the agent reads a
kit's body on demand, so the cost no longer applies and the body can say the
things about this sandbox the agent cannot otherwise discover — that devin
is the auth wrapper rather than the CLI, and that the credential is
proxy-held.
No volumes are declared. Devin's session
state and its credential file live in the container's writable layer, so they
survive stop/start and are rebuilt on recreate — the credential by the engine
rendering credentials.toml again from what the host holds, which is the same
path a brand-new sandbox takes.
Unlike a kind: mixin kit, which layers onto an existing environment, a
kind: workload kit is the whole environment: its layers are the sandbox's
root filesystem, so the kit has content rather than a reference to an image
built elsewhere. That content is built from
devin.dockerfile, the companion recipe the descriptor
finds by filename stem.
It is built on docker/sandbox-templates:shell-docker, so it carries a Docker
engine and requests Docker-in-Docker through the
com.docker.sandboxes.start-docker label — which stays a label in v3 rather
than becoming a capability.
A v3 kit is one OCI image carrying both its declarations and its content, so
there is no longer a separate -image artifact beside the kit: the descriptor
rides in a manifest annotation on the same image its layers belong to. The
published name is derived from the kit directory and enforced repo-wide — see
PUBLISHING.md.
How the build installs Devin CLI, and why the rename dance around
devin/devin-cli is needed, is covered in
README.image.md.
How the kit is named, tagged, verified and pushed is the same for every kit in
this repo — see PUBLISHING.md for the pipeline, the
tagging scheme, the coordinates, and the Docker Hub OIDC setup. The build is
driven by the frontend the descriptor's first line names
(# syntax=docker/sandbox-kit:3), which validates devin.yaml, builds
devin.dockerfile as the kit's content, and publishes both as one image.
./scripts/test-kit.sh devin
Two build args: BASE_IMAGE and DEVIN_VERSION.
DEVIN_VERSION is the Devin CLI release to install, declared as the
descriptor's version arg and expanded into the kit's
provides: ["devin@<version>"], so the kit cannot claim a release it does not
ship. It has no default in the recipe — an empty value fails the build rather
than falling back to whatever "current" means today.
The pin is expressed by which script the recipe fetches, not by anything
passed to it. Cognition's installer reads no version from its environment or
its argv: the top-level script carries a bare PINNED_VERSION="" literal, so
an argument it quietly ignored would read as a pin while pinning nothing. But
the comment on that very line says the value is "Set by the build system for
versioned setup scripts (e.g. cli/2026.3.5-1/setup.sh)", and those scripts
are published. https://static.devin.ai/cli/<version>/setup.sh is
byte-for-byte the top-level script with PINNED_VERSION="<version>" filled
in, which redirects its manifest lookup from current/ to <version>/. The
recipe fetches that path and then asserts the installed binary reports the
declared release, so a pin that silently installed something else fails the
build.
To bump it, read the release the unpinned installer would have taken:
$ curl -fsSL https://static.devin.ai/cli/current/manifest.json | head -c 40
{"version":"3000.10.31","platforms":{"aa
Note that the build now reaches static.devin.ai only. It used to reach
cli.devin.ai as well, for the unpinned top-level install.sh; that host
serves no versioned path (it 301s one to the docs site).
Pulls:
62
Last week