Run code, shells, and the GitHub Copilot CLI inside VS Code devcontainers β straight from your terminal.
Renamed from
dcode. Same project, new name and a broader scope. The CLI binary is nowidc.
uv tool install git+https://github.com/rosstaco/InDevContainerIf you have the old dcode tool installed, remove it first:
uv tool uninstall dcode# Open current folder in VS Code via its devcontainer (was: dcode .)
idc code .
# Open a specific path
idc code /path/to/project
# Use VS Code Insiders
idc code -i .
# Drop into an interactive shell inside the running devcontainer
idc shell
# Run the GitHub Copilot CLI inside the running devcontainer
idc copilot --yolo --resumeIf the folder has no .devcontainer/devcontainer.json, idc code falls back to plain code <path>.
Open <path> (default: current directory) in VS Code via the configured devcontainer. Exit code is forwarded from the spawned editor.
Open an interactive shell inside the project's running devcontainer.
idc shell # current directory
idc shell ./my-project # specific path
idc shell --shell zsh # explicit shell executable (overrides settings)
idc shell -i # resolve VS Code Insiders user settingsShell selection priority (highest first):
--shellCLI flag (literal executable; no argument parsing)- Workspace
<workspace>/.vscode/settings.json:terminal.integrated.defaultProfile.linuxplus the matchingterminal.integrated.profiles.linuxentry devcontainer.jsoncustomizations.vscode.settingswith the same keys- Host user-level VS Code settings, such as
~/Library/Application Support/Code/User/settings.jsonon macOS,~/.config/Code/User/settings.jsonon Linux, or Windows-side settings via the WSL bridge - Container login shell from
getent passwd <user>(nologinandfalseare rejected) - Fallback:
/bin/bash, then/bin/sh
idc shell always reads the .linux terminal settings because devcontainers
run Linux, even on macOS and WSL hosts. Profile args and env are honored;
if a profile path is a list, the first entry is used. ${...} substitution in
profile values is not resolved in this version, so those values are passed
through verbatim with a warning.
SSH agent forwarding works automatically when VS Code is open and connected to
the devcontainer. idc shell detects the VS Code relay socket at
/tmp/vscode-ssh-auth-*.sock and sets SSH_AUTH_SOCK on docker exec. If no
socket is found, it prints a hint to open the project in VS Code first.
Exec the GitHub Copilot CLI (copilot) inside the project's running devcontainer.
Shares container resolution with idc shell (auto-build, auto-start prompts).
idc copilot # current directory, no copilot args
idc copilot --yolo --resume # cwd; --yolo and --resume go to copilot
idc copilot ./my-project --resume # explicit path; --resume goes to copilot
idc copilot . -- --some-flag # explicit `--` separator (rarely needed)
idc copilot -- weird-positional # escape hatch: first forwarded arg
# would otherwise be parsed as the pathThe first non-flag argument (if any) is the project path; everything else is forwarded verbatim to copilot inside the container. Use -- if the first forwarded token would otherwise look like a path.
copilot must be installed inside the container β idc copilot does a fast command -v copilot probe first and fails with a hint if it's missing. Add it via a devcontainer Feature, or install it inside the container (for example, npm install -g @github/copilot).
If you run idc shell (or idc copilot) in a project whose devcontainer has
never been built, idc will offer to build it for you so you don't have to
open VS Code first:
idc: no devcontainer is running for /path/to/proj. Build & start it now? [Y/n]
This uses the official @devcontainers/cli (the same Node.js CLI VS Code's
Dev Containers extension drives under the hood) so the resulting container
carries the same devcontainer.local_folder, devcontainer.config_file, and
devcontainer.metadata labels VS Code expects β open the project in VS Code
later and it'll attach to the same container.
If the CLI isn't installed, idc will offer to install it:
idc: install the Dev Containers CLI now from
https://raw.githubusercontent.com/devcontainers/cli/main/scripts/install.sh
into ~/.devcontainers (no root needed)? [y/N]
This downloads a self-contained install (bundled Node.js runtime included), so you don't need a host Node.js install. To install it manually:
# Self-contained install (recommended; bundles its own Node.js):
curl -fsSL https://raw.githubusercontent.com/devcontainers/cli/main/scripts/install.sh | sh
# Or, if you already have Node.js:
npm install -g @devcontainers/cliBuild progress (Docker layer pulls, feature installation, lifecycle hooks)
streams live above a pinned spinner so you can watch what the CLI is doing
without losing the loader UX. The same spinner shows briefly when idc code
launches VS Code so you always know idc is doing something.
If you decline the install, idc exits with a hint pointing at the
above commands and at idc code <path> (which opens VS Code, where the Dev
Containers extension can build the container instead). Auto-build always
prompts and never runs without an interactive TTY.
The shell runs as remoteUser from devcontainer.json when set, then
containerUser. When neither is set in devcontainer.json, idc reads the
container's devcontainer.metadata Docker label (written by the Dev Containers
extension / devcontainers/cli) and applies the same remoteUser β
containerUser resolution against the merged metadata layers, so users defined
by base images like mcr.microsoft.com/devcontainers/javascript-node
(remoteUser: node) are honored. If still nothing is set, the container
image's USER applies.
The working directory matches the URI logic: <workspaceFolder>/<worktree-relative-path>
for worktrees, otherwise <workspaceFolder>. The path is probed with test -d;
if it does not exist, idc falls back to the base <workspaceFolder>
with a warning, or omits -w entirely if that is missing too.
Limitations (apply to both idc shell and idc copilot):
- GPG agent forwarding is not yet supported. Commit signing inside the
container will not work unless you've configured your own GPG forwarding via
containerEnvand a bind mount. remoteEnvis not applied. The environment may differ from VS Code's integrated terminal; a warning is printed whenremoteEnvis present indevcontainer.json.- Variable substitution (
${env:VAR},${localEnv:VAR}) in terminal profile values is not resolved. - Devcontainer config inheritance (
extends, image-label metadata, Docker Compose serviceuser) is not merged; only the rawdevcontainer.jsonfile is read. For complex setups, shell selection may differ from VS Code's resolved view. - Requires an interactive terminal. Both
idc shellandidc copilotexit with an error when stdin or stdout is not a TTY (e.g. piped or scripted contexts).
Common errors:
- No
devcontainer.json: exits non-zero and points you atidc doctor. - Container not running, in a non-interactive context (e.g. piped): no
matching devcontainer was found and
idccannot prompt; run it interactively, or runidc code <path>first. - Container stopped:
idcwill prompt to start it. - Multiple matching containers: clean up the duplicate containers listed in the error.
- Docker not available: install/start Docker or Docker Desktop and try again.
- Dev Containers CLI not installed and user declined install: see the Auto-build section above for the curl/npm install commands.
code, shell, copilot, doctor, and update are subcommands, so
idc code, idc shell, etc. always invoke them. To open a folder literally
named shell, doctor, or update, prefix the path with ./:
idc code ./shell
idc code ./doctor
idc code "$(pwd)/update"Diagnose the local environment for idc and print a "what would idc code <path> do here?"
plan summary. Read-only β never patches settings.json or spawns the editor.
Checks: VS Code editor on PATH, Dev Containers extension, Docker daemon,
Dev Containers CLI on PATH (used by idc shell/idc copilot to auto-build a missing
devcontainer), git, WSL setup (distro, Windows-side settings.json,
dev.containers.executeInWSL), devcontainer discovery + parse, worktree
sanity, idc version vs latest GitHub release, install method.
idc doctor # inspect current directory
idc doctor /some/path # inspect a specific pathExit codes:
0β no failing checks (warnings allowed)1β one or more failing checks
Upgrade the installed idc tool via uv tool upgrade indevcontainer. Exit code is forwarded
from uv. Returns 1 if uv is not on PATH or if idc was not installed via
uv tool.
Check for an available update without installing it. Prints local version, latest GitHub release, and the release URL.
Exit codes:
0β up to date (or local version is ahead, e.g. a dev build)1β a newer release is available2β network or GitHub API error
When you run idc code . inside a git worktree, it automatically detects the main repo, finds the devcontainer config there, and opens the worktree folder inside the same container. This means all worktrees share a single devcontainer instance β same extensions, same Copilot context, multiple VS Code windows. πͺπͺπͺ
cd ~/repos/my-project
git worktree add .worktrees/pr-42 pr-42
# Opens pr-42 in the devcontainer defined in my-project
idc code .worktrees/pr-42
# Opens pr-99 in the SAME container, different window
git worktree add .worktrees/pr-99 pr-99
idc code .worktrees/pr-99
β οΈ The worktree must live inside the main repo directory tree (e.g..worktrees/) so it's accessible from the container's mounted volume.
idc code constructs a vscode-remote://dev-container+<hex-path>/workspaces/<name> URI and launches VS Code with --folder-uri. VS Code handles the container lifecycle automatically.
For worktrees, the hex-encoded path points to the main repo (so all worktrees resolve to the same container), while the workspace folder is adjusted to open the worktree subfolder inside the container.
idc shell and idc copilot skip the VS Code URI dance and docker exec -it directly into the container that VS Code (or the Dev Containers CLI auto-build) already created β sharing user, workdir, and SSH agent socket so the inner process behaves like VS Code's integrated terminal.
When idc code runs inside WSL, it:
-
Builds the URI using a Windows UNC path (
\\wsl.localhost\<distro>\β¦) so VS Code on Windows can resolve the folder. -
Auto-edits your Windows VS Code
settings.json(under%APPDATA%\Code\User\orCode - Insiders) to set:"dev.containers.executeInWSL": true"dev.containers.executeInWSLDistro": "<your-distro>"
This is required so the Dev Containers extension talks to Docker inside WSL instead of
docker.exeon Windows. Comments and trailing commas in yoursettings.jsonare preserved (in-place patching, not a rewrite).
To opt out, pre-set those keys to whatever values you want β idc only writes them when they're missing or differ from the desired values.
This project uses Conventional Commits (feat:, fix:, chore:, docs:, etc.). Releases are automated by release-please β merging a feat: or fix: commit to main opens/updates a release PR, and merging that PR creates the tag + GitHub Release.