Devcontainer Setup Skill
Creates a pre-configured devcontainer with Claude Code and language-specific tooling.
When to Use
-
User asks to "set up a devcontainer" or "add devcontainer support"
-
User wants a sandboxed Claude Code development environment
-
User needs isolated development environments with persistent configuration
When NOT to Use
-
User already has a devcontainer configuration and just needs modifications
-
User is asking about general Docker or container questions
-
User wants to deploy production containers (this is for development only)
Workflow
flowchart TB start([User requests devcontainer]) recon[1. Project Reconnaissance] detect[2. Detect Languages] generate[3. Generate Configuration] write[4. Write files to .devcontainer/] done([Done])
start --> recon
recon --> detect
detect --> generate
generate --> write
write --> done
Phase 1: Project Reconnaissance
Infer Project Name
Check in order (use first match):
-
package.json → name field
-
pyproject.toml → project.name
-
Cargo.toml → package.name
-
go.mod → module path (last segment after / )
-
Directory name as fallback
Convert to slug: lowercase, replace spaces/underscores with hyphens.
Detect Language Stack
Language Detection Files
Python pyproject.toml , *.py
Node/TypeScript package.json , tsconfig.json
Rust Cargo.toml
Go go.mod , go.sum
Multi-Language Projects
If multiple languages are detected, configure all of them in the following priority order:
-
Python - Primary language, uses Dockerfile for uv + Python installation
-
Node/TypeScript - Uses devcontainer feature
-
Rust - Uses devcontainer feature
-
Go - Uses devcontainer feature
For multi-language postCreateCommand , chain all setup commands:
uv run /opt/post_install.py && uv sync && npm ci
Extensions and settings from all detected languages should be merged into the configuration.
Phase 2: Generate Configuration
Start with base templates from resources/ directory. Substitute:
-
{{PROJECT_NAME}} → Human-readable name (e.g., "My Project")
-
{{PROJECT_SLUG}} → Slug for volumes (e.g., "my-project")
Then apply language-specific modifications below.
Base Template Features
The base template includes:
-
Claude Code with marketplace plugins (anthropics/skills, trailofbits/skills, trailofbits/skills-curated)
-
Python 3.13 via uv (fast binary download)
-
Node 22 via fnm (Fast Node Manager)
-
ast-grep for AST-based code search
-
Network isolation tools (iptables, ipset) with NET_ADMIN capability
-
Modern CLI tools: ripgrep, fd, fzf, tmux, git-delta
Language-Specific Sections
Python Projects
Detection: pyproject.toml , requirements.txt , setup.py , or *.py files
Dockerfile additions:
The base Dockerfile already includes Python 3.13 via uv. If a different version is required (detected from pyproject.toml ), modify the Python installation:
Install Python via uv (fast binary download, not source compilation)
RUN uv python install <version> --default
devcontainer.json extensions:
Add to customizations.vscode.extensions :
"ms-python.python", "ms-python.vscode-pylance", "charliermarsh.ruff"
Add to customizations.vscode.settings :
"python.defaultInterpreterPath": ".venv/bin/python", "[python]": { "editor.defaultFormatter": "charliermarsh.ruff", "editor.codeActionsOnSave": { "source.organizeImports": "explicit" } }
postCreateCommand: If pyproject.toml exists, chain commands:
rm -rf .venv && uv sync && uv run /opt/post_install.py
Node/TypeScript Projects
Detection: package.json or tsconfig.json
No Dockerfile additions needed: The base template includes Node 22 via fnm (Fast Node Manager).
devcontainer.json extensions:
Add to customizations.vscode.extensions :
"dbaeumer.vscode-eslint", "esbenp.prettier-vscode"
Add to customizations.vscode.settings :
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" }
postCreateCommand: Detect package manager from lockfile and chain with base command:
-
pnpm-lock.yaml → uv run /opt/post_install.py && pnpm install --frozen-lockfile
-
yarn.lock → uv run /opt/post_install.py && yarn install --frozen-lockfile
-
package-lock.json → uv run /opt/post_install.py && npm ci
-
No lockfile → uv run /opt/post_install.py && npm install
Rust Projects
Detection: Cargo.toml
Features to add:
"ghcr.io/devcontainers/features/rust:1": {}
devcontainer.json extensions:
Add to customizations.vscode.extensions :
"rust-lang.rust-analyzer", "tamasfe.even-better-toml"
Add to customizations.vscode.settings :
"[rust]": { "editor.defaultFormatter": "rust-lang.rust-analyzer" }
postCreateCommand: If Cargo.lock exists, use locked builds:
uv run /opt/post_install.py && cargo build --locked
If no lockfile, use standard build:
uv run /opt/post_install.py && cargo build
Go Projects
Detection: go.mod
Features to add:
"ghcr.io/devcontainers/features/go:1": { "version": "latest" }
devcontainer.json extensions:
Add to customizations.vscode.extensions :
"golang.go"
Add to customizations.vscode.settings :
"[go]": { "editor.defaultFormatter": "golang.go" }, "go.useLanguageServer": true
postCreateCommand:
uv run /opt/post_install.py && go mod download
Reference Material
For additional guidance, see:
-
references/dockerfile-best-practices.md
-
Layer optimization, multi-stage builds, architecture support
-
references/features-vs-dockerfile.md
-
When to use devcontainer features vs custom Dockerfile
Adding Persistent Volumes
Pattern for new mounts in devcontainer.json :
"mounts": [ "source={{PROJECT_SLUG}}-<purpose>-${devcontainerId},target=<container-path>,type=volume" ]
Common additions:
-
source={{PROJECT_SLUG}}-cargo-${devcontainerId},target=/home/vscode/.cargo,type=volume (Rust)
-
source={{PROJECT_SLUG}}-go-${devcontainerId},target=/home/vscode/go,type=volume (Go)
Output Files
Generate these files in the project's .devcontainer/ directory:
-
Dockerfile
-
Container build instructions
-
devcontainer.json
-
VS Code/devcontainer configuration
-
post_install.py
-
Post-creation setup script
-
.zshrc
-
Shell configuration
-
install.sh
-
CLI helper for managing the devcontainer (devc command)
Validation Checklist
Before presenting files to the user, verify:
-
All {{PROJECT_NAME}} placeholders are replaced with the human-readable name
-
All {{PROJECT_SLUG}} placeholders are replaced with the slugified name
-
JSON syntax is valid in devcontainer.json (no trailing commas, proper nesting)
-
Language-specific extensions are added for all detected languages
-
postCreateCommand includes all required setup commands (chained with && )
User Instructions
After generating, inform the user:
-
How to start: "Open in VS Code and select 'Reopen in Container'"
-
Alternative: devcontainer up --workspace-folder .
-
CLI helper: Run .devcontainer/install.sh self-install to add the devc command to PATH