Claude research sandbox
Create a sandboxed autonomous research environment with Docker, GPU access, and a multi-session Claude loop. Use when the user wants to set up an autonomous research project.From its SKILL.md
npx -y skills add fanurs/claude-research-sandboxAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
12.3 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
Research Sandbox Skill
You are scaffolding a Docker sandbox for autonomous research. Your job is to get the container running FAST. Do NOT do deep research — the autonomous loop will handle that later.
Phase 1: Environment Probe (run BEFORE asking the user anything)
Run silently and remember the results:
id -u
id -g
docker --version
nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null || echo "NO_GPU"
dpkg -l | grep nvidia-container-toolkit 2>/dev/null || echo "NO_NVIDIA_TOOLKIT"
git config --global user.name 2>/dev/null || echo ""
git config --global user.email 2>/dev/null || echo ""
command -v npm >/dev/null 2>&1 && echo "HAS_NPM" || echo "NO_NPM"
If Docker is missing, stop and report. If no GPU, warn the user (we remove deploy: from compose later). The git config and npm results are inputs to Phase 2 (Q2 branching) and Phase 5c (install decision) — do not ask the user for any of this.
Phase 2: Intake (verbatim)
Send ONE message containing (a) a preview list of the questions, then (b) the questions themselves using the exact wording written below. Do not paraphrase, reorder, summarize, or soften. The only permitted variation is the conditional branch in Q3 (git identity), chosen from the Phase 1 probe. If the user answers partially, re-ask only the missing pieces, still verbatim.
Opening preview (show this first, verbatim):
Before I start, here's what I'll ask you (5 items):
- Research question + project slug
- Where to scaffold (new subdirectory / here / custom path)
- Git identity inside the container
- Email notifications (optional)
- Model and effort preference (optional)
Answer in one message; anything missing I'll re-ask.
Then the questions (verbatim):
1. Research question. What is your research question? I suggest the project slug
<propose a short kebab-case slug>— OK, or what would you prefer?2. Scaffold location. Where should I put the project?
subdir(default) — create./<slug>/under your current directory and scaffold inside it.here— scaffold directly into your current directory (<absolute cwd path>).- or give me an absolute or relative path — I'll create it if it doesn't exist.
3. Git identity (inside the container). [If BOTH
user.nameanduser.emailwere detected on the host, use exactly this line:] I detected<NAME> <EMAIL>from your host git config. Use this inside the container? (yes — or supply an alternate name + email.) [Otherwise, use exactly this line:] No git identity found on the host. What name and email should I use for commits inside the container?4. Email notifications (optional). Want end-of-session report emails via Resend? (yes/no) If yes: recipient email? Sender name + address (must be on a Resend-verified domain, e.g.
Your Name <[email protected]>)?5. Model / effort (optional). Which Claude model for sessions? (Press Enter for default, or e.g.
claude-opus-4-6.) Effort level? (Press Enter for unset, or one of: low / medium / high / max.)
Wait for all answers before proceeding to Phase 3.
Phase 3: Scaffold
3.0. Enter target directory (based on Q2 answer)
Before writing anything, resolve the scaffold location and cd into it. All subsequent paths in Phase 3+ are relative to this target directory.
subdir(default):mkdir <slug> && cd <slug>. If./<slug>/already exists and is non-empty, STOP and ask the user: different slug? delete existing? proceed anyway? Wait for an answer before continuing.here: stay in the current working directory. If it's non-empty (anything other than.git/and hidden dotfiles), show the user the existing top-level entries and ask for explicit confirmation before proceeding. If it's already a git repo, warn that you'll be runninggit init/ adding files on top.- Custom path (absolute or relative):
mkdir -p <path> && cd <path>. Apply the same non-empty check ashere.
Report the resolved absolute path back to the user in one line (e.g. Scaffolding into: /home/you/projects/<slug>) so they can confirm mentally before the scaffold runs.
3a. Copy templates with substitution
Read each file from ${CLAUDE_SKILL_DIR}/templates/ and write it to the current directory (the target from Phase 3.0), replacing:
__PROJECT_NAME__→ project slug__UID__→ host UID__GID__→ host GID
Mapping:
templates/Dockerfile→Dockerfiletemplates/docker-compose.yml.template→docker-compose.ymltemplates/loop.sh→loop.shtemplates/protocol.md→protocol.mdtemplates/.gitignore→.gitignoretemplates/scripts/*→scripts/*templates/scripts/send_report_email.py→scripts/send_report_email.py(if email enabled)templates/tools/viewer/*→tools/viewer/*templates/README.md→README.md
Make loop.sh and all scripts/*.sh executable.
If NO GPU, remove the deploy: block from docker-compose.yml.
If email enabled:
In scripts/send_report_email.py, replace:
__REPORT_EMAIL_TO__→ recipient email address__RESEND_FROM__→ sender name and email (e.g.Automated Name <[email protected]>)
Add .env.email to .gitignore (already in template).
3b. Generate research-specific files
Write these based on your existing knowledge — do NOT do web searches. Keep them concise.
-
README.md— Overwrite the template README with a project-specific version that includes:- Project title and one-line description
- Research question and why it matters (2-3 paragraphs, was old
prompts/00-context.md) - Research directions / approaches to explore (was old
prompts/01-research-directions.md):- Priority 1: "Understand the data and establish baselines"
- 2-3 more directions worth exploring
- Note: "Refine this list after the first few sessions"
- Any datasets/resources the user mentioned
- Known state of the art (rough, from your knowledge)
- Then keep all the framework sections from the template (Quick Start, Controls, etc.)
-
CLAUDE.md— Hard runtime rules only (session-workflow rules live inprotocol.md):# Hard Rules - You are running inside Docker at `/workspace` - Follow `protocol.md` every session — it defines the workflow, code organization, commit format, and session rules - Re-read `state/plan.md` at the end of every session to decide where you stand: stay within the shift's threads (adding sub-tasks to an existing thread is fine, inventing new threads is drift) and run `./scripts/stop.sh` once all threads in the shift are complete - Threads in `state/plan.md` are executed in numerical order (T1 → T2 → T3 → …). Do not start a later thread until every `[ ]` in lower-numbered threads within the shift's brackets is ticked. The numbering IS the order. - Always use GPU. If `torch.cuda.is_available()` is False, STOP. - Estimate VRAM before training - NEVER include Co-Authored-By lines or mention AI coauthorship in commits - Do NOT modify `protocol.md` or `scripts/` - You may update `README.md` as understanding deepens -
state/next_action.md— Bootstrap the first session:# Next Action This is the very first session. Do the following: 1. Read README.md and protocol.md to understand the project and session protocol 2. Explore and download relevant data 3. Create a research plan in state/plan.md IF one doesn't already exist; otherwise treat the existing plan as your source of truth and do not overwrite it 4. Update the journal and write the next action ## Context <One sentence restating the research question>
3c. Initialize Python project
Do NOT run uv on the host. Just write these two files directly:
pyproject.toml:
[project]
name = "<project-slug>"
version = "0.1.0"
description = "<one-line research description>"
requires-python = ">=3.12"
dependencies = []
.python-version:
3.12
The container has uv installed. The first autonomous session will run uv sync inside the container.
3d. Create runtime directories
mkdir -p state logs results checkpoints data src playground reports/figures tests
3e. Write config (if model/effort specified)
If the user specified a model or effort level, write .research-config:
CLAUDE_MODEL="<model>"
CLAUDE_EFFORT="<effort>"
3f. Initialize git
git init -b main
git add -A
git commit -m "Initial scaffold from research-sandbox"
Phase 4: Build and Start
docker compose up -d --build
Phase 5: Verify
Run inside container via docker exec:
nvidia-smi(skip if no GPU)uv --versionclaude --versionvim --version | head -1- Write permission test:
touch /workspace/state/_test && rm /workspace/state/_test
Report a brief summary table to the user.
5a. Git config inside container
docker exec __PROJECT_NAME__-sandbox git config --global user.name "<name>"
docker exec __PROJECT_NAME__-sandbox git config --global user.email "<email>"
5b. Email Setup (if enabled)
The skill never touches the user's API key. Generate a stub file in the project directory (NOT from templates/ — that would put a secret-shaped file in the skill repo) and hand off to the user to fill in.
-
Create
.env.emailwith a placeholder and short setup guide, then lock permissions:cat > .env.email <<'EOF' RESEND_API_KEY=REPLACE_THIS_WITHOUT_ANY_QUOTE # How to get a Resend API key (rough guide — see https://resend.com/docs for anything tricky): # 1. Sign up at https://resend.com and create an API key from the dashboard. # 2. Add + verify your sending domain (Resend → Domains → Add Domain; follow DNS steps). # 3. Paste the key above, replacing REPLACE_THIS_WITHOUT_ANY_QUOTE. # No quotes, no trailing spaces, no repeated `RESEND_API_KEY=` prefix. # 4. Make sure the sender address you configured during setup uses that verified domain. # # This file is gitignored and chmod 400 — keep it that way. EOF chmod 400 .env.emailDo NOT read or echo this file after creation.
-
Tell the user (verbatim):
I created
.env.emailwith a placeholder. Open it, replaceREPLACE_THIS_WITHOUT_ANY_QUOTEwith your actual Resend API key, then let me know — I'll run a test send. -
Wait for confirmation. Then test from inside the container:
docker exec -w /workspace __PROJECT_NAME__-sandbox bash -c 'set -a && source /workspace/.env.email && set +a && uv run python /workspace/scripts/send_report_email.py --test 2>&1' -
Ask: "Did you receive the test email?" If it fails, debug without reading
.env.email— rely on stderr from the script only.
5c. Log Viewer Setup (auto-detect, do not ask)
Use the HAS_NPM / NO_NPM result from the Phase 1 probe. Do not ask the user.
-
If
HAS_NPM: runcd tools/viewer && npm install, then tell the user:Log viewer installed. To watch sessions in your browser: cd tools/viewer && npm start Then open http://localhost:3000 The viewer runs on the HOST (not inside the container). It reads log files from the bind-mounted logs/ directory. -
If
NO_NPM: skip the install silently. Tell the user:npm wasn't found on the host, so the log viewer is skipped. If you want it later: install Node.js/npm, then run cd tools/viewer && npm install && npm start
Phase 6: User Auth
Tell the user:
Container is ready. Authenticate Claude:
docker exec -it __PROJECT_NAME__-sandbox claude /login
Let me know when done.
After confirmation, test with:
docker exec __PROJECT_NAME__-sandbox claude --dangerously-skip-permissions -p "Say hello" --output-format json
Then tell the user:
All set! To start the autonomous research loop:
./scripts/start-loop.sh
To watch (web UI): cd tools/viewer && npm start → http://localhost:3000
To watch (raw): docker exec -it __PROJECT_NAME__-sandbox tmux attach -t research
To stop: ./scripts/stop.sh
To stop after N: ./scripts/stop.sh 50
Status: ./scripts/status.sh
Reports: ls reports/
What ships with it: 20 files
53.7 KB alongside SKILL.md, 12 of them executable
templates/
- docker-compose.yml.template535 B
- Dockerfile815 B
- .gitignore344 B
- loop.shruns3.6 KB
- protocol.md9.4 KB
- README.md5.5 KB
- scripts/cleanup.shruns907 B
- scripts/pause.shruns168 B
- scripts/resume.shruns138 B
- scripts/run_session.shruns1.9 KB
- scripts/send_report_email.pyruns3.5 KB
- scripts/shell.shruns84 B
- scripts/start-loop.shruns1.6 KB
- scripts/start.shruns406 B
- scripts/status.shruns1.6 KB
- scripts/stop.shruns646 B
- tools/viewer/package.json170 B
- tools/viewer/public/index.html15.4 KB
- tools/viewer/server.jsruns1.8 KB
- README.md5.2 KB