Tutorial
Work in your project's dev container
A lot of repositories already say what they need to be built in — a
devcontainer.json naming an image, a user, some mounts. Sinclair
reads it, so a terminal in that project can be a terminal inside that
environment rather than one beside it. This walkthrough opens a shell in a
project's dev container, shares the container your editor already has running,
and writes a devcontainer.json that works for people and coding
agents alike.
Sinclair needs Docker or Podman and nothing else. It does
not need VS Code or the devcontainer CLI installed, and it
never requires a project to have a devcontainer.json — without one
it builds its own environment. The file is an input, not a dependency. See
Share one container with your agents for the
no-devcontainer path.
1. Open a shell inside it
From a pane in the project, open File ▸ Sandbox and pick
Use Sandbox for This Project, then Open Shell in Sandbox.
Sinclair reads the project's devcontainer.json, brings a container
up from it, and gives you an ordinary tab whose shell is inside.
Config files are looked for in the order the Dev Containers tooling uses:
.devcontainer/devcontainer.json
.devcontainer.json
.devcontainer/devcontainer.jsonc
Comments and trailing commas are fine — the file is parsed as JSONC, the same way Sinclair parses its own settings.
2. What Sinclair takes from the file
Only the fields that change how a container is created or entered. Anything
else in your devcontainer.json is ignored rather than guessed at.
| Field | What it does here |
|---|---|
image | Becomes the base of the image Sinclair builds, so your agents get the project's toolchain plus the agent CLI on top. |
containerEnv, remoteEnv | Merged into the container's environment. Your own sandbox-env wins on conflicts. |
mounts | Applied, in the engine's type=bind,source=…,target=… form. An entry that doesn't parse becomes a note, not a failure. |
remoteUser / containerUser | The user the container runs as, unless sandbox-user says otherwise. |
shutdownAction | Read to warn you — see step 4. |
workspaceFolder, workspaceMount | Read only to detect whether the project is mounted at its own path — see step 3. |
The ${localWorkspaceFolder},
${localWorkspaceFolderBasename},
${containerWorkspaceFolder}, and
${containerWorkspaceFolderBasename} variables all resolve.
Not used: features,
customizations, forwardPorts, and
postCreateCommand belong to the Dev Containers tooling, and
runArgs is left alone rather than passing arbitrary engine flags
through. A build.dockerfile is not built for you — point
sandbox-image at the image it produces and Sinclair uses it
as-is.
3. One thing worth changing: mount at your own path
By default the Dev Containers convention mounts your repo at
/workspaces/<name>. That is fine for a person, and awkward for
a coding agent: git records absolute paths when it creates a
worktree, so a worktree made inside the container has a .git
pointer that resolves nowhere on the host, and one made on the host resolves
nowhere inside.
Two spec-legal lines make the container path equal the host path, and the whole problem disappears:
// .devcontainer/devcontainer.json
{
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
"workspaceFolder": "${localWorkspaceFolder}"
}
When Sinclair creates the container itself it does this anyway. The lines matter for the container your editor creates, so both tools agree.
4. Don't let closing the editor kill a working team
shutdownAction defaults to stopContainer: close your
editor window and the container stops. If a team of agents is working in that
container, they stop with it, mid-task.
{
"shutdownAction": "none"
}
Sinclair reads this field and says so in the Containers panel
when it isn't none, so you find out before it costs you a run
rather than after.
5. Sharing one container with your editor
Sinclair looks before it creates. If a container is already running for this
folder — one VS Code's Dev Containers extension built, or one
devcontainer up started — Sinclair enters that one
instead of building a parallel environment beside it.
It also never stops or removes a container it did not create. Your editor is very likely attached to it, and Stop Sandbox pulling the floor out from under your editor session would be a bad surprise. The Containers panel tells you when the sandbox is one Sinclair adopted.
Discovery keys on the label the Dev Containers tooling stamps with the host workspace path:
docker ps -a --filter label=devcontainer.local_folder=$PWD
Sinclair stamps that same label on the containers it creates, so it works in both directions: open the project in VS Code afterwards and Reopen in Container finds the one already running rather than building a second.
6. If the project has no devcontainer.json
Nothing degrades. Sinclair generates a small image itself — a Debian base plus git, node, and your agent CLI — and builds it locally on first use. If you'd rather write a dev container the whole team shares, this is a reasonable starting point that works for people and agents:
// .devcontainer/devcontainer.json
{
"name": "api",
"image": "mcr.microsoft.com/devcontainers/javascript-node:22",
// Same path inside and out, so git worktrees stay valid on both sides.
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
"workspaceFolder": "${localWorkspaceFolder}",
// Closing your editor shouldn't stop a container with agents working in it.
"shutdownAction": "none",
"remoteUser": "node",
"containerEnv": { "DATABASE_URL": "postgres://host.docker.internal/dev" },
"mounts": ["type=volume,source=api-node-modules,target=${containerWorkspaceFolder}/node_modules"]
}
Sinclair layers the agent CLI onto that image, so you do not need to install
claude in it yourself.
Don't mount /var/run/docker.sock. It's a common dev container
convenience and a one-line container escape — it hands anything in the container
root on your host, which matters a great deal once agents are running there with
their permission prompts turned off.
7. Turning it off
To ignore a project's devcontainer.json and let Sinclair build its
own environment:
{
"sandbox-devcontainer": false
}
The rest of the sandbox — mounts, environment, resource ceilings, the image — is configured the same way either way. Every key is in the settings reference.
Where next
- Share one container with your agents — the same container, with a whole team inside it.
- Parallel agents in worktrees — how agents stay out of each other's way inside one container.
- Linux in a tab — throwaway containers, no config at all.