Repository navigation
Expand file tree
/
Copy pathdevcontainer.json
More file actions
144 lines (135 loc) · 7.78 KB
/
Copy pathdevcontainer.json
File metadata and controls
144 lines (135 loc) · 7.78 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
// For format details, see https://aka.ms/devcontainer.json
{
"name": "Local Development",
"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:latest || exit 0",
"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"
],
"settings": {
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"zsh": { "path": "zsh" },
"bash": { "path": "bash", "icon": "terminal-bash" }
},
"extensions.ignoreRecommendations": true,
// ── Formatter settings (customize per project) ──────────────────
// Change "editor.defaultFormatter" to match your tooling:
// Biome: "biomejs.biome" | Prettier: "esbenp.prettier-vscode"
// OXC: "oxc.oxc-vscode" | None: remove these three settings
"editor.formatOnSave": true,
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"window.title": "${localWorkspaceFolderBasename}"
}
}
},
// 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"
],
"containerEnv": {
"TZ": "${localEnv:TZ:America/Edmonton}",
"DEVCONTAINER": "true",
"NODE_OPTIONS": "--max-old-space-size=4096",
"CLAUDE_CONFIG_DIR": "/home/node/.claude",
// 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"
},
// sudo chown fixes volume ownership — safety net in case Docker volume population didn't apply.
// The find command chowns all node_modules volume mount points in one pass.
// mise install reads .mise.toml and installs project-specific tool versions.
// bun install is skipped until the project has a package.json.
// Chromium is baked into the image via apt — no playwright install step needed.
// Projects' playwright.config.ts should use process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH.
"updateContentCommand": "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",
// Re-patch the Playwright MCP plugin's .mcp.json on every start. 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.
// No postCreateCommand: claude CLI calls there race the extension's OAuth sign-in
// (#58). Run `bash .devcontainer/init-plugins.sh` once after signing in.
"postStartCommand": "/usr/local/bin/patch-playwright-mcp"
}