{ "name": "dev stack", "build": { "dockerfile": "Dockerfile" }, // Every repo lands as a sibling inside /workspaces, which is ordinary // container filesystem, and /workspaces itself is the workspace root. // Nesting the other repos *inside* this one's bind mount instead would // make the Docker daemon create those mount points as root through the // bind, leaving root-owned empty directories behind on the host. // // With /workspaces as the workspace root, one Claude Code session started // there reaches every repo as an ordinary subdirectory, with no --add-dir // and no additionalDirectories permission entry. "workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/${localWorkspaceFolderBasename},type=bind", "workspaceFolder": "/workspaces", // One entry per repo, matching the directories listed in stack.conf. "mounts": [ "source=${localWorkspaceFolder}/../my-backend,target=/workspaces/my-backend,type=bind", "source=${localWorkspaceFolder}/../my-frontend,target=/workspaces/my-frontend,type=bind" ], // Host networking, so the servers see each other and the host browser as // plain localhost, with no forwardPorts list to keep in sync. "runArgs": ["--network=host"], // Environment for the servers: where each one keeps its dev state, which // address it listens on, where it finds the other half of the stack. // ${containerWorkspaceFolder} is /workspaces. "containerEnv": { // "MYAPP_DB_PATH": "${containerWorkspaceFolder}/my-backend/.dev/app.db", // "MYAPP_LISTEN_ADDR": "0.0.0.0:4747" }, "postCreateCommand": "${localWorkspaceFolderBasename}/.devcontainer/post-create.sh", "customizations": { "vscode": { "extensions": [ // One list for the whole stack, so both toolchains are here. ] } }, "features": { "ghcr.io/devcontainers/features/docker-in-docker:4": {} } }