Repository navigation
Expand file tree
/
Copy pathdevcontainer.json
More file actions
158 lines (148 loc) · 8.69 KB
/
Copy pathdevcontainer.json
File metadata and controls
158 lines (148 loc) · 8.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// For format details, see https://aka.ms/devcontainer.json
{
"name": "Claude Code Sandbox",
"dockerComposeFile": "docker-compose.yml",
"service": "devcontainer",
"workspaceFolder": "/workspace",
// Pull the prebuilt image on the HOST before the build, so "Rebuild Without
// Cache" always layers on the freshest base. Replaces `pull_policy: always` in
// docker-compose.yml, which breaks on Linux/WSL2 when `updateRemoteUserUID`
// builds a local-only image (issue #109). `|| exit 0` keeps offline/outage opens
// working (valid in POSIX sh and Windows cmd.exe). Keep in sync with the compose image.
"initializeCommand": "docker pull ghcr.io/gatezh/devcontainers/claude-code-sandbox:latest || exit 0",
// Capabilities required for iptables firewall setup
"capAdd": ["NET_ADMIN", "NET_RAW"],
"init": true,
"updateRemoteUserUID": true,
"remoteUser": "node",
"otherPortsAttributes": { "onAutoForward": "silent" },
"customizations": {
"vscode": {
"extensions": [
// **AI Agents**
// Claude Code - AI coding assistant with chat, inline edits, and terminal integration
"anthropic.claude-code",
// **Runtime**
// Bun - Bun runtime support (debugging, lockfile viewer, bundler integration)
"oven.bun-vscode",
// **Code Quality**
// OXC - Fast linter and formatter for JavaScript/TypeScript (Rust-based)
"oxc.oxc-vscode",
// **Tailwind**
// Tailwind CSS IntelliSense - autocomplete, syntax highlighting, linting for Tailwind classes
"bradlc.vscode-tailwindcss",
// Tailwind Fold - collapse long Tailwind class strings in the editor for readability
"stivo.tailwind-fold",
// **General**
// YAML - YAML language support (for workflows and docker-compose)
"redhat.vscode-yaml",
// Markdown Preview Github Styles - renders Markdown preview with GitHub's CSS
"bierner.markdown-preview-github-styles",
// Markdown Preview Mermaid Support - renders Mermaid diagrams in Markdown preview
"bierner.markdown-mermaid",
// Docker - Dockerfile and Compose syntax, linting, and image management
"ms-azuretools.vscode-docker",
// **Spelling**
// Code Spell Checker - catches typos in code and comments
"streetsidesoftware.code-spell-checker",
// **JavaScript / TypeScript**
// npm IntelliSense - autocomplete npm imports in import statements
"christian-kohler.npm-intellisense",
// TypeScript Error Translator - human-readable TS error messages
"mattpocock.ts-error-translator",
// **CSS / Colors**
// Color Info - preview CSS colors on hover
"bierner.color-info",
// Colorize - visualize CSS colors inline in the editor
"kamikillerto.vscode-colorize",
// **Frameworks**
// Drizzle ORM Snippets - code snippets for Drizzle ORM
"drizzle-team.drizzle-orm-snippets",
// **Testing**
// Playwright - run, debug, and generate Playwright tests from VS Code
"ms-playwright.playwright",
// **Sandbox Theme**
// Claude Theme - provides "Claude Dark" referenced by workbench.colorTheme
"SamiHindi.claude-theme-sami-hindi"
],
"settings": {
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"zsh": { "path": "zsh" },
"bash": { "path": "bash", "icon": "terminal-bash" }
},
"extensions.ignoreRecommendations": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"window.title": "${localWorkspaceFolderBasename}",
// Sandbox visual identity — Claude Dark theme with coral remote indicator
"workbench.colorTheme": "Claude Dark",
"workbench.colorCustomizations": {
"statusBarItem.remoteBackground": "#C15F3C",
"statusBarItem.remoteForeground": "#ffffff"
},
"claudeCode.allowDangerouslySkipPermissions": true
}
}
},
// Named volumes keep node_modules OFF the host machine and persist across rebuilds.
// Uses ${localWorkspaceFolderBasename} so default and sandbox variants share volumes.
// Replace "myproject" with your project name (must match across both variants).
"mounts": [
// ── node_modules isolation (one per workspace) ─────────────────────
// Each workspace with a package.json needs its own volume mount.
// Without one, node_modules lands in the bind mount and shows up on the host.
"source=myproject-node-modules-root-${localWorkspaceFolderBasename},target=/workspace/node_modules,type=volume",
// ── Monorepo: uncomment and customize for your structure ──────────
// "source=myproject-node-modules-api-${localWorkspaceFolderBasename},target=/workspace/services/api/node_modules,type=volume",
// "source=myproject-node-modules-web-${localWorkspaceFolderBasename},target=/workspace/apps/web/node_modules,type=volume",
// ── Persistent config ──────────────────────────────────────────────
"source=myproject-claude-config-${localWorkspaceFolderBasename},target=/home/node/.claude,type=volume",
"source=myproject-zsh-history-${localWorkspaceFolderBasename},target=/commandhistory,type=volume",
// gh CLI auth/state (~/.config/gh/hosts.yml) — keeps `gh auth login` across rebuilds
"source=myproject-gh-config-${localWorkspaceFolderBasename},target=/home/node/.config/gh,type=volume",
// cf CLI login (~/.config/cloudflare) — keeps `cf auth login` across rebuilds
"source=myproject-cloudflare-config-${localWorkspaceFolderBasename},target=/home/node/.config/cloudflare,type=volume",
// ── Firewall script ────────────────────────────────────────────────
// The image provides iptables/ipset packages and sudo rule but NOT the script itself.
// Each project provides its own script via bind mount to customize the domain allowlist.
"source=${localWorkspaceFolder}/.devcontainer/claude-sandbox/init-firewall.sh,target=/usr/local/bin/init-firewall.sh,type=bind"
],
"containerEnv": {
"TZ": "${localEnv:TZ:America/Edmonton}",
"DEVCONTAINER": "true",
"NODE_OPTIONS": "--max-old-space-size=4096",
"CLAUDE_CONFIG_DIR": "/home/node/.claude",
// Optional — only needed when the sandbox is used without the default variant, whose
// sign-in lands on the shared ~/.claude volume. Resolves to "" when the host var is
// unset. See "Sandbox Authentication" section in README.
"CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}",
// Git config for every process, outranking the ~/.gitconfig the extension copies in:
// trust /workspace, send git@github.com: remotes over HTTPS, and authenticate github.com
// only through gh (the empty helper drops VS Code's, as `gh auth setup-git` does).
"GIT_CONFIG_COUNT": "4",
"GIT_CONFIG_KEY_0": "safe.directory",
"GIT_CONFIG_VALUE_0": "/workspace",
"GIT_CONFIG_KEY_1": "url.https://github.com/.insteadOf",
"GIT_CONFIG_VALUE_1": "git@github.com:",
"GIT_CONFIG_KEY_2": "credential.https://github.com.helper",
"GIT_CONFIG_VALUE_2": "",
"GIT_CONFIG_KEY_3": "credential.https://github.com.helper",
"GIT_CONFIG_VALUE_3": "!gh auth git-credential"
},
// The find command chowns all node_modules volume mount points in one pass.
// Chromium is baked into the sandbox image (firewall blocks runtime install).
// bun install and init-plugins.sh are skipped when their file is absent. Plugins
// install here, before postStartCommand brings the firewall up.
"postCreateCommand": "sudo find /workspace -maxdepth 4 -name node_modules -type d -exec chown node {} + && sudo chown -R node /home/node/.claude /commandhistory /home/node/.config/gh /home/node/.config/cloudflare && mise install && if [ -f package.json ]; then bun install; fi && if [ -f .devcontainer/init-plugins.sh ]; then bash .devcontainer/init-plugins.sh; fi",
// Firewall init (bind-mounted from project) + re-patch the Playwright MCP
// plugin's .mcp.json. The patch is defense in depth alongside the SessionStart
// hook in /etc/claude-code/managed-settings.json, which handles the case where
// the plugin auto-updates mid-container-run. See issues #85, #87, #98.
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh && /usr/local/bin/patch-playwright-mcp",
"waitFor": "postStartCommand"
}