A production-ready VS Code devcontainer for intercepting and analyzing AI coding agent HTTP(S) traffic with mitmproxy.
This repository gives you a single container that includes:
mitmproxy/mitmweb- Claude Code CLI
- Gemini CLI
- OpenAI Codex CLI
- GitHub Copilot CLI
- OpenCode CLI
- agent-analyzer MVP (flow capture database + API + frontend)
It is built to work both:
- locally with VS Code + Docker
- in GitHub Codespaces
Most AI coding CLIs run over HTTPS and hide their wire-level requests/responses by default. This container provides a clean, repeatable setup where:
- certificate trust is pre-wired
- proxy environment configuration is automated
- each tool has a one-command launcher through the proxy
So you can focus on analysis instead of container plumbing.
┌───────────────────────────────┐
│ claude / gemini / codex / ... │
└──────────────┬────────────────┘
│ HTTP_PROXY / HTTPS_PROXY
▼
┌───────────────┐
│ mitmproxy │ (port 8080)
│ mitmweb │ (port 8081 UI)
└───────┬───────┘
▼
Internet APIs
- Clone this repository.
- Open it in VS Code.
- Run Dev Containers: Reopen in Container.
- Open two terminals in the container:
# Terminal 1
start-proxy
# Terminal 2
claude-via-proxyThen open the auth URL printed by start-proxy (it includes a required ?token=... query string).
The devcontainer uses zsh as the default shell for the node user and VS Code integrated terminal.
- Click Code → Codespaces → Create codespace on main.
- Wait for the devcontainer build to finish.
- In the Codespace terminal:
# Terminal 1
start-proxy
# Terminal 2
gemini-via-proxy- Open forwarded port 8081 (mitmweb UI) using the full auth URL printed by
start-proxy, usually:
https://<your-codespace-name>-8081.app.github.dev/?token=<token>
If 8081 does not auto-forward, use the Ports tab and forward it manually.
# Terminal 1
start-proxy
# Terminal 2
codex-via-proxy# start mitmproxy + analyzer capture + API on :5555
start-proxy --analyzeThen open http://localhost:5555 (or forwarded port 5555 in Codespaces) to browse captured flows.
# Terminal 1
mitmweb -p 8080 --web-port 8081 --web-host 0.0.0.0
# Terminal 2
source proxy-on
claude
# disable proxy for the current shell
source proxy-off| Command | Description |
|---|---|
start-proxy |
Start mitmweb in foreground with sane defaults |
claude-via-proxy |
Launch Claude Code routed through mitmproxy |
gemini-via-proxy |
Launch Gemini CLI routed through mitmproxy |
codex-via-proxy |
Launch Codex CLI routed through mitmproxy |
copilot-via-proxy |
Launch Copilot CLI routed through mitmproxy |
opencode-via-proxy |
Launch OpenCode routed through mitmproxy |
source proxy-on |
Set proxy vars in your current shell |
source proxy-off |
Unset proxy vars in your current shell |
test-proxy |
Verify tool binaries, scripts, and trust wiring |
| Tool | Auth method | Env var |
|---|---|---|
| Claude Code | API key or OAuth | ANTHROPIC_API_KEY |
| Gemini CLI | API key or OAuth | GEMINI_API_KEY |
| Codex CLI | API key or OAuth | OPENAI_API_KEY |
| Copilot CLI | GitHub token/device flow | COPILOT_GITHUB_TOKEN or GH_TOKEN |
| OpenCode | Provider-specific | provider-specific |
Tip: API keys are usually easier for proxy testing than OAuth callbacks.
Codex has known proxy gaps in some internal HTTP clients. Use this flow for reliable results:
# 1) Authenticate without proxy (recommended in containers)
codex login --device-auth
# 2) Then run through proxy
codex-via-proxyOr skip OAuth entirely:
export OPENAI_API_KEY=sk-...
codex-via-proxyThis devcontainer sets CODEX_CA_CERTIFICATE=/home/node/.mitmproxy/mitmproxy-ca-cert.pem (plus SSL_CERT_FILE) so Codex can trust the mitmproxy CA.
| Tool | Filter |
|---|---|
| Claude Code | ~d api.anthropic.com |
| Gemini CLI | ~d generativelanguage.googleapis.com |
| Codex CLI | ~d api.openai.com | ~d auth.openai.com |
| Copilot CLI | ~d api.githubcopilot.com | ~d copilot-proxy.githubusercontent.com |
| OpenCode | depends on selected provider |
start-proxy -p 9090 -w 9091
PROXY_PORT=9090 claude-via-proxystart-proxysetsweb_passwordso mitmweb UI authentication is required.- The token is persisted at
/home/node/.mitmproxy/mitmweb-token. - The printed UI URL includes
?token=<value>so browser login is one-click. - To set your own stable token/password:
MITMWEB_PASSWORD='your-long-random-secret' start-proxystart-proxy -f /tmp/capture.flowtest-proxyOn container start, the devcontainer seeds bash/zsh history with:
start-proxyclaude-via-proxygemini-via-proxycodex-via-proxycopilot-via-proxyopencode-via-proxysource proxy-onsource proxy-offtest-proxy
So you can use ↑ or reverse-search (Ctrl+R) immediately without retyping.
bash test/test-devcontainer.shRun start-proxy first in another terminal. The wrappers intentionally fail fast when port 8080 is closed.
This image pre-installs mitmproxy CA into system trust and sets:
NODE_EXTRA_CA_CERTSCODEX_CA_CERTIFICATE(for Codex CLI)SSL_CERT_FILEREQUESTS_CA_BUNDLE
If you still see trust errors, run test-proxy and verify the CA checks are passing.
Some OAuth flows are sensitive to interception. Authenticate once without proxy, then retry with *-via-proxy, or use API-key auth where available.
Use one of these reliable paths:
- Preferred:
codex login --device-authwithout proxy first, then runcodex-via-proxy. - Best for automation/interception: set
OPENAI_API_KEYand skip OAuth entirely.
codex-via-proxy now checks for auth state (/home/node/.codex/auth.json) when OPENAI_API_KEY is not set and will print guidance instead of failing deep in the OAuth flow.
Some license tiers may not allow self-signed proxy cert interception. Business/Enterprise tends to work better for this scenario.
- Confirm
start-proxyis running. - Forward port 8081 manually in the Ports tab.
- Use the printed URL in terminal output.
- Make sure you include
?token=...from the printed URL.
On some Codespaces starts, mounted volumes can come up root-owned. post-start.sh now auto-fixes ownership for mounted auth/config dirs on startup.
Additionally, each *-via-proxy launcher now performs a writable-directory preflight and auto-repairs ownership when possible.
If your Codespace was created before this fix, run once:
bash /usr/local/bin/post-start.shThen retry gemini, gemini-via-proxy, or opencode-via-proxy.
If permissions are still broken, rebuild the container so the latest /etc/sudoers.d/node configuration is applied.
.devcontainer/
├── devcontainer.json
├── Dockerfile
├── scripts/
│ ├── _proxy-common.sh
│ ├── proxy-on.sh
│ ├── proxy-off.sh
│ ├── start-proxy.sh
│ ├── claude-via-proxy.sh
│ ├── gemini-via-proxy.sh
│ ├── codex-via-proxy.sh
│ ├── copilot-via-proxy.sh
│ ├── opencode-via-proxy.sh
│ ├── setup-codex-config.sh
│ ├── post-start.sh
│ └── test-proxy.sh
└── test/
└── test-devcontainer.sh
- This project ships no credentials.
- Auth state is persisted in named Docker volumes for convenience.
- The container runs as non-root
nodeuser by default. codexsandbox is explicitly disabled in-container for Docker compatibility.
If you publish this repo, consider enabling a prebuilt container image for faster Codespaces startup.