From 79085b1c9030356d345ce5bc4c019f348996da14 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 7 May 2026 12:35:02 +0100 Subject: [PATCH 1/4] feat(devcontainer): refresh dev image and auto-update Claude Code Updates the development container to base on Go 1.25 Trixie, add the Claude Code devcontainer feature, mount the host's gh config and Claude commands/settings into the container, forward the dev/docs/MCP ports, and pass GH_TOKEN through. postCreateCommand symlinks the mounted Claude config into ~/.claude, adds a `claude --dangerously-skip-permissions` alias, and runs `sudo env "PATH=$PATH" npm update -g @anthropic-ai/claude-code` so the update can write to the root-owned global node_modules while still locating the nvm-managed npm binary. Co-Authored-By: Claude Opus 4.7 (1M context) --- .devcontainer/dev/devcontainer.json | 67 +++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/.devcontainer/dev/devcontainer.json b/.devcontainer/dev/devcontainer.json index 47825618..d0d1e462 100644 --- a/.devcontainer/dev/devcontainer.json +++ b/.devcontainer/dev/devcontainer.json @@ -1,14 +1,55 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/go . { - "name": "pgEdge MCP Server — Development", - "image": "mcr.microsoft.com/devcontainers/go:1.24", - "features": { - "ghcr.io/devcontainers/features/node:1": { "version": "20" }, - "ghcr.io/devcontainers/features/docker-in-docker:2": {} - }, - "customizations": { - "vscode": { - "extensions": ["golang.go"] - } - }, - "postCreateCommand": "go mod download && cd web && npm ci" -} + "name": "pgEdge MCP Server — Development", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/go:2-1.25-trixie", + "features": { + "ghcr.io/devcontainers/features/github-cli:1": { + "installDirectlyFromGitHubRelease": true, + "version": "latest" + }, + "ghcr.io/devcontainers-extra/features/claude-code:1": { + "version": "latest" + } + }, + "mounts": [ + "source=${localEnv:HOME}/.config/gh,target=/home/vscode/.config/gh,type=bind", + "source=${localEnv:HOME}/.claude/commands,target=/home/vscode/.claude-host/commands,type=bind,readonly", + "source=${localEnv:HOME}/.claude/settings.json,target=/home/vscode/.claude-host/settings.json,type=bind,readonly" + ], + "initializeCommand": "export GH_TOKEN=$(gh auth token 2>/dev/null)", + "containerEnv": { + "GH_TOKEN": "${localEnv:GH_TOKEN}" + }, + "postCreateCommand": "mkdir -p ~/.claude && ln -sf ~/.claude-host/commands ~/.claude/commands && ln -sf ~/.claude-host/settings.json ~/.claude/settings.json && echo 'alias claude=\"claude --dangerously-skip-permissions\"' >> ~/.bashrc && sudo env \"PATH=$PATH\" npm update -g @anthropic-ai/claude-code", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [5173, 8000, 8080], + "portsAttributes": { + "5173": { + "label": "NLA", + "onAutoForward": "notify" + }, + "8000": { + "label": "Docs", + "onAutoForward": "notify" + }, + "8080": { + "label": "MCP", + "onAutoForward": "notify" + }, + } + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "go version", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} \ No newline at end of file From fdfb9eadb000ae02b78d30aa672304267cce095a Mon Sep 17 00:00:00 2001 From: Dave Page Date: Fri, 15 May 2026 16:02:11 +0100 Subject: [PATCH 2/4] fix(devcontainer): address CodeRabbit and Codacy review feedback - Drop trailing comma after the 8080 portsAttributes entry so the Jackson Linter (strict JSON) stops flagging line 45. - Make the ~/.claude/settings.json symlink in postCreateCommand conditional on the bind-mounted file existing, so machines without a host-side settings.json do not start with a dangling symlink. - Replace the broken initializeCommand/containerEnv GH_TOKEN dance (localEnv is resolved before initializeCommand runs, so the export never reached the container) with an export appended to ~/.bashrc that uses the already bind-mounted ~/.config/gh credentials. - Surface the claude --dangerously-skip-permissions alias via a new postAttachCommand notice and document the unalias / direct binary escape hatch, so the bypass is no longer silently in effect. - Remove the stale commented-out template stubs ("features": {} and "postCreateCommand": "go version") that no longer matched reality. Co-Authored-By: Claude Opus 4.7 (1M context) --- .devcontainer/dev/devcontainer.json | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/.devcontainer/dev/devcontainer.json b/.devcontainer/dev/devcontainer.json index d0d1e462..ce0106ed 100644 --- a/.devcontainer/dev/devcontainer.json +++ b/.devcontainer/dev/devcontainer.json @@ -18,14 +18,8 @@ "source=${localEnv:HOME}/.claude/commands,target=/home/vscode/.claude-host/commands,type=bind,readonly", "source=${localEnv:HOME}/.claude/settings.json,target=/home/vscode/.claude-host/settings.json,type=bind,readonly" ], - "initializeCommand": "export GH_TOKEN=$(gh auth token 2>/dev/null)", - "containerEnv": { - "GH_TOKEN": "${localEnv:GH_TOKEN}" - }, - "postCreateCommand": "mkdir -p ~/.claude && ln -sf ~/.claude-host/commands ~/.claude/commands && ln -sf ~/.claude-host/settings.json ~/.claude/settings.json && echo 'alias claude=\"claude --dangerously-skip-permissions\"' >> ~/.bashrc && sudo env \"PATH=$PATH\" npm update -g @anthropic-ai/claude-code", - - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, + "postCreateCommand": "mkdir -p ~/.claude && ln -sf ~/.claude-host/commands ~/.claude/commands && if [ -f ~/.claude-host/settings.json ]; then ln -sf ~/.claude-host/settings.json ~/.claude/settings.json; fi && echo 'export GH_TOKEN=$(gh auth token 2>/dev/null)' >> ~/.bashrc && echo 'alias claude=\"claude --dangerously-skip-permissions\"' >> ~/.bashrc && sudo env \"PATH=$PATH\" npm update -g @anthropic-ai/claude-code", + "postAttachCommand": "echo '⚠️ NOTICE: This dev container aliases `claude` to `claude --dangerously-skip-permissions`. Run `unalias claude` or invoke `/usr/local/bin/claude` directly to restore safety prompts.'", // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [5173, 8000, 8080], @@ -41,15 +35,12 @@ "8080": { "label": "MCP", "onAutoForward": "notify" - }, + } } - // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "go version", - // Configure tool-specific properties. // "customizations": {}, // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "root" -} \ No newline at end of file +} From fbb60922b95e8a59093d6fcee97120d051c38c79 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Fri, 15 May 2026 16:08:17 +0100 Subject: [PATCH 3/4] fix(devcontainer): drop ineffective GH_TOKEN plumbing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit correctly noted that appending `export GH_TOKEN=...` to ~/.bashrc only sets the variable for interactive shells; VS Code tasks, extensions, and other non-interactive processes never see it. No tool inside the dev container actually reads $GH_TOKEN — every reference in the repo is in GitHub Actions workflows that run on hosted runners, not here. The bind-mounted ~/.config/gh already authenticates the `gh` CLI itself, and consumers that need the raw token can call `gh auth token` explicitly. Remove the bashrc export and add a short comment documenting how auth flows so the next reader does not re-add a plumbing line that does not work. Co-Authored-By: Claude Opus 4.7 (1M context) --- .devcontainer/dev/devcontainer.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.devcontainer/dev/devcontainer.json b/.devcontainer/dev/devcontainer.json index ce0106ed..6715304a 100644 --- a/.devcontainer/dev/devcontainer.json +++ b/.devcontainer/dev/devcontainer.json @@ -18,7 +18,10 @@ "source=${localEnv:HOME}/.claude/commands,target=/home/vscode/.claude-host/commands,type=bind,readonly", "source=${localEnv:HOME}/.claude/settings.json,target=/home/vscode/.claude-host/settings.json,type=bind,readonly" ], - "postCreateCommand": "mkdir -p ~/.claude && ln -sf ~/.claude-host/commands ~/.claude/commands && if [ -f ~/.claude-host/settings.json ]; then ln -sf ~/.claude-host/settings.json ~/.claude/settings.json; fi && echo 'export GH_TOKEN=$(gh auth token 2>/dev/null)' >> ~/.bashrc && echo 'alias claude=\"claude --dangerously-skip-permissions\"' >> ~/.bashrc && sudo env \"PATH=$PATH\" npm update -g @anthropic-ai/claude-code", + // The bind-mounted ~/.config/gh already authenticates the `gh` CLI + // inside the container, so we do not plumb GH_TOKEN through the + // environment; tools that need the raw token can call `gh auth token`. + "postCreateCommand": "mkdir -p ~/.claude && ln -sf ~/.claude-host/commands ~/.claude/commands && if [ -f ~/.claude-host/settings.json ]; then ln -sf ~/.claude-host/settings.json ~/.claude/settings.json; fi && echo 'alias claude=\"claude --dangerously-skip-permissions\"' >> ~/.bashrc && sudo env \"PATH=$PATH\" npm update -g @anthropic-ai/claude-code", "postAttachCommand": "echo '⚠️ NOTICE: This dev container aliases `claude` to `claude --dangerously-skip-permissions`. Run `unalias claude` or invoke `/usr/local/bin/claude` directly to restore safety prompts.'", // Use 'forwardPorts' to make a list of ports inside the container available locally. From 6d95660daaa67fed0954a82b1ce989dff37844ca Mon Sep 17 00:00:00 2001 From: Dave Page Date: Fri, 15 May 2026 16:13:31 +0100 Subject: [PATCH 4/4] fix(devcontainer): make claude alias append idempotent Guard the bashrc alias append with `grep -qxF` so re-running postCreateCommand on container rebuilds does not stack duplicate `alias claude="claude --dangerously-skip-permissions"` lines. Addresses the CodeRabbit follow-up on fbb6092. Co-Authored-By: Claude Opus 4.7 (1M context) --- .devcontainer/dev/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/dev/devcontainer.json b/.devcontainer/dev/devcontainer.json index 6715304a..d49e148c 100644 --- a/.devcontainer/dev/devcontainer.json +++ b/.devcontainer/dev/devcontainer.json @@ -21,7 +21,7 @@ // The bind-mounted ~/.config/gh already authenticates the `gh` CLI // inside the container, so we do not plumb GH_TOKEN through the // environment; tools that need the raw token can call `gh auth token`. - "postCreateCommand": "mkdir -p ~/.claude && ln -sf ~/.claude-host/commands ~/.claude/commands && if [ -f ~/.claude-host/settings.json ]; then ln -sf ~/.claude-host/settings.json ~/.claude/settings.json; fi && echo 'alias claude=\"claude --dangerously-skip-permissions\"' >> ~/.bashrc && sudo env \"PATH=$PATH\" npm update -g @anthropic-ai/claude-code", + "postCreateCommand": "mkdir -p ~/.claude && ln -sf ~/.claude-host/commands ~/.claude/commands && if [ -f ~/.claude-host/settings.json ]; then ln -sf ~/.claude-host/settings.json ~/.claude/settings.json; fi && grep -qxF 'alias claude=\"claude --dangerously-skip-permissions\"' ~/.bashrc || echo 'alias claude=\"claude --dangerously-skip-permissions\"' >> ~/.bashrc && sudo env \"PATH=$PATH\" npm update -g @anthropic-ai/claude-code", "postAttachCommand": "echo '⚠️ NOTICE: This dev container aliases `claude` to `claude --dangerously-skip-permissions`. Run `unalias claude` or invoke `/usr/local/bin/claude` directly to restore safety prompts.'", // Use 'forwardPorts' to make a list of ports inside the container available locally.