Skip to content

Commit 7186ee4

Browse files
gatezhclaude
andauthored
docs(claude-code): address setup gotchas and add sandbox-fetch-docs skill (#50)
* docs(claude-code): add setup gotchas for Playwright, sandbox, and firewall (#49) - Add @playwright/test devDependency prerequisite to Playwright Version Strategy - Explain why sandbox variant omits node_modules volumes (no passwordless sudo) - Show git add after chmod +x for firewall script executable bit - Add macOS troubleshooting note for stale Docker gRPC-FUSE xattr Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(claude-code): add sandbox-fetch-docs skill for doc lookups behind firewall - Add .claude/skills/sandbox-fetch-docs.md teaching Claude Code to use node_modules, raw.githubusercontent.com, GitHub API, and npm registry instead of blocked vendor doc sites - Reference skill in README with setup instructions and file structure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f9ee88a commit 7186ee4

2 files changed

Lines changed: 136 additions & 1 deletion

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
name: sandbox-fetch-docs
3+
description: Use when needing to verify implementation against official library docs, check API contracts, or look up how a dependency works — especially after bugs caused by wrong assumptions about a library's API. Triggers on "check the docs", "verify against docs", "official documentation", "how does X API work", "canonical implementation".
4+
---
5+
6+
# Fetch Documentation in Sandbox
7+
8+
## Overview
9+
10+
This sandbox only has network access to GitHub and npm registry. All other domains (vendor doc sites, CDNs, search engines) are firewalled. Use these approaches in priority order — do NOT attempt blocked approaches.
11+
12+
## Approach Priority
13+
14+
```dot
15+
digraph fetch_docs {
16+
rankdir=TB;
17+
"Need library docs?" [shape=doublecircle];
18+
"Installed in node_modules?" [shape=diamond];
19+
"Read local source + types" [shape=box, style=filled, fillcolor="#d4edda"];
20+
"Public repo on GitHub?" [shape=diamond];
21+
"Fetch via raw.githubusercontent.com" [shape=box, style=filled, fillcolor="#d4edda"];
22+
"Browse via GitHub Contents API" [shape=box, style=filled, fillcolor="#d4edda"];
23+
"Need package metadata?" [shape=diamond];
24+
"Query npm registry" [shape=box, style=filled, fillcolor="#d4edda"];
25+
"Ask user for help" [shape=box, style=filled, fillcolor="#fff3cd"];
26+
27+
"Need library docs?" -> "Installed in node_modules?";
28+
"Installed in node_modules?" -> "Read local source + types" [label="yes"];
29+
"Installed in node_modules?" -> "Public repo on GitHub?" [label="no"];
30+
"Read local source + types" -> "Public repo on GitHub?" [label="need more context"];
31+
"Public repo on GitHub?" -> "Fetch via raw.githubusercontent.com" [label="know file path"];
32+
"Public repo on GitHub?" -> "Browse via GitHub Contents API" [label="need to discover files"];
33+
"Public repo on GitHub?" -> "Need package metadata?" [label="no repo"];
34+
"Fetch via raw.githubusercontent.com" -> "Need package metadata?" [label="need more"];
35+
"Browse via GitHub Contents API" -> "Fetch via raw.githubusercontent.com" [label="found path"];
36+
"Need package metadata?" -> "Query npm registry" [label="yes"];
37+
"Need package metadata?" -> "Ask user for help" [label="no"];
38+
}
39+
```
40+
41+
## 1. Installed node_modules (fastest, always works)
42+
43+
The definitive source for how a library behaves at the exact version you're using:
44+
45+
```bash
46+
# Find the package (Bun layout — other managers use different paths, e.g. node_modules/PACKAGE)
47+
find node_modules/.bun -path "*PACKAGE_NAME*" -type d -maxdepth 3
48+
49+
# Read type definitions (the API contract)
50+
# Look for index.d.mts, index.d.ts, or index.d.cts
51+
Read: node_modules/.bun/PACKAGE@VERSION/node_modules/PACKAGE/dist/index.d.mts
52+
53+
# Read source implementation (how it actually works)
54+
Grep: pattern in node_modules/.bun/PACKAGE@VERSION/node_modules/PACKAGE/dist/index.mjs
55+
```
56+
57+
**When to use:** Always start here. Types show the API contract, source shows the implementation. This is more reliable than docs which may be outdated or describe a different version.
58+
59+
## 2. Raw GitHub content (no auth needed)
60+
61+
Fetch files directly from public repos via `raw.githubusercontent.com`:
62+
63+
```bash
64+
# WebFetch or curl — both work
65+
WebFetch: https://raw.githubusercontent.com/OWNER/REPO/BRANCH/path/to/file.ts
66+
67+
# Common branches to try: main, master, canary
68+
# Example: Resend SDK email handling
69+
WebFetch: https://raw.githubusercontent.com/resend/resend-node/main/src/emails/emails.ts
70+
```
71+
72+
If `main` returns 404, try `master` or `canary`. Use the Contents API (below) to discover the default branch and file paths.
73+
74+
## 3. GitHub Contents API (no auth, ~60 req/hr)
75+
76+
Browse repo structure when you don't know file paths:
77+
78+
```bash
79+
# List directory contents
80+
curl -s https://api.github.com/repos/OWNER/REPO/contents/src/path
81+
82+
# Read repo README
83+
curl -s https://api.github.com/repos/OWNER/REPO/readme
84+
85+
# Get file content (base64-encoded, decode with jq)
86+
curl -s https://api.github.com/repos/OWNER/REPO/contents/path/to/file | jq -r '.content' | base64 -d
87+
```
88+
89+
## 4. npm registry (package metadata only)
90+
91+
```bash
92+
curl -s https://registry.npmjs.org/PACKAGE/latest | jq '.version, .description, .repository'
93+
```
94+
95+
Useful for finding the GitHub repo URL when you don't know it.
96+
97+
## What NEVER works in this sandbox
98+
99+
| Approach | Why |
100+
|----------|-----|
101+
| WebFetch to vendor sites (resend.com, hono.dev, drizzle.team, etc.) | Firewall blocks non-GitHub domains |
102+
| WebSearch | Search engines not whitelisted |
103+
| `gh` CLI | Installed but not authenticated |
104+
| GitHub code search API (`/search/code`) | Requires authentication |
105+
| CDNs (unpkg, jsdelivr, cdnjs) | Not whitelisted |
106+
107+
Do NOT attempt these — they waste time with connection timeouts and auth errors.

‎claude-code/README.md‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ Add to your project's `.devcontainer/devcontainer.json`:
8282

8383
### Sandbox variant
8484

85+
> **No node_modules volumes** — the sandbox variant does not have passwordless sudo (only `sudo /usr/local/bin/init-firewall.sh` is allowed), so the `sudo chown` used in the default variant to fix volume ownership won't work. Let node_modules live in the bind mount instead.
86+
8587
```jsonc
8688
{
8789
"name": "Claude Code Sandbox",
@@ -171,7 +173,24 @@ Default-deny iptables firewall. The image provides the packages and sudo rule; t
171173

172174
See the [devcontainer-claude-bun firewall script](../devcontainer-claude-bun/.devcontainer/init-firewall.sh) for a complete example.
173175

174-
Mark as executable: `chmod +x init-firewall.sh`
176+
Mark as executable and ensure git tracks the executable bit:
177+
178+
```bash
179+
chmod +x .devcontainer/claude-sandbox/init-firewall.sh
180+
git add .devcontainer/claude-sandbox/init-firewall.sh # ensures git tracks +x (100755)
181+
```
182+
183+
> **Troubleshooting (macOS):** If the firewall script fails with "command not found" despite correct permissions (`stat` shows `rwxr-xr-x`, git shows `100755`), stale Docker Desktop metadata may be overriding the file mode. Fix by removing the cached extended attribute:
184+
>
185+
> ```bash
186+
> xattr -d com.docker.grpcfuse.ownership .devcontainer/claude-sandbox/init-firewall.sh
187+
> ```
188+
189+
### Sandbox-only: Claude Code skill for fetching docs
190+
191+
The sandbox firewall blocks vendor doc sites, so Claude Code can't `WebFetch` or `WebSearch` as it normally would. The image includes a [sandbox-fetch-docs](.claude/skills/sandbox-fetch-docs.md) skill that teaches Claude Code how to look up library documentation using only allowed network paths (node_modules, raw.githubusercontent.com, GitHub Contents API, npm registry).
192+
193+
Copy `.claude/skills/sandbox-fetch-docs.md` into your project's `.claude/skills/` directory so Claude Code picks it up automatically.
175194
176195
### Sandbox Authentication
177196
@@ -231,6 +250,9 @@ Add `.env.local` to `.gitignore`. Note: Docker will fail to start if `.env.local
231250
├── init-firewall.sh ← firewall script (customize domain allowlist)
232251
├── .env.example ← template for auth token (checked in)
233252
└── .env.local ← actual auth token (gitignored)
253+
.claude/
254+
└── skills/
255+
└── sandbox-fetch-docs.md ← teaches Claude Code to fetch docs within sandbox firewall
234256
```
235257
236258
## Workspace Directory Layout
@@ -260,6 +282,12 @@ The image uses a two-layer strategy so that any project can use any `@playwright
260282
| System deps (`install-deps`) | OS libraries (libgbm, libnss3, …) | Yes (needs root) | Stable across nearby versions |
261283
| Browser binary (`install --only-shell`) | Headless Chromium shell | Yes, as cache | Exact match required |
262284

285+
**Prerequisite:** Your project must have `@playwright/test` in `devDependencies`. Without it, `npx` will prompt interactively to download the `playwright` package, which hangs container creation (no TTY). Pin it to the image's baked version (check `$PLAYWRIGHT_VERSION`) or your preferred version:
286+
287+
```bash
288+
bun add -d @playwright/test # or: npm install -D @playwright/test
289+
```
290+
263291
**One-time project setup** — add this to your container creation command (`updateContentCommand` or `postCreateCommand`, as shown in [Quick Start](#quick-start)):
264292

265293
```bash

0 commit comments

Comments
 (0)