A template for running agentic development loops against GitHub issues. Built with Matt Pocock's Sandcastle.
Requires Node.js 24 or newer.
It can:
- Analyze a repository and create labeled GitHub issues.
- Select an issue from that queue.
- Implement it on a dedicated branch.
- Review the change and request corrections.
- Push an approved change, open a draft PR, and close the issue.
- Repeat until the queue is empty or the iteration limit is reached.
Run the same loop directly on your machine, inside a local Docker sandbox, or as a cloud job.
Repository analysis
↓
Labeled GitHub issues
↓
Implement → Review → Correct
↓
Draft pull request
↓
Repeat
Analysis is optional. You can also create and label issues yourself, then run only the implementation loop.
The orchestrator runs locally. Agent commands run in Docker against isolated Git worktrees.
npm run sandcastle:analyze:code
npm run sandcastle:implementThe sandbox image is built automatically when missing. Build it manually with npm run sandcastle:build.
The complete loop runs directly on the host.
SANDCASTLE_SANDBOX=none npm run sandcastle:analyze:code
SANDCASTLE_SANDBOX=none npm run sandcastle:implementUse only on a trusted, isolated machine. Git worktrees isolate changes, not host access.
The repository, dependencies, agent CLIs, and one selected loop are packaged into a linux/amd64 image. The image is the isolation boundary.
Build and run locally:
SCRIPT=sandcastle:implement npm run sandcastle:cloud:build
docker run --rm --env-file .env cloudharness:cloudDeploy as a Google Cloud Run job:
npm run infra:apply
SCRIPT=sandcastle:implement npm run sandcastle:cloud:deployCloud deployment requires Docker, Google Cloud CLI, Terraform, and a Google Cloud project with billing and suitable permissions.
PROJECT_ID, REGION, JOB_NAME, and TAG override deployment defaults. Images embed .env and the current environment by default; set EMBED_LOCAL_ENV=false to disable this. Treat embedded images as secret-bearing.
Remove the Cloud Run job, registry, and registry images with npm run infra:destroy. The versioned Terraform state bucket is retained intentionally.
Analyzers inspect project code, avoid duplicate open issues, and create findings with the configured label. They do not modify project code.
npm run sandcastle:analyze:security
npm run sandcastle:analyze:code
npm run sandcastle:analyze:duplicationChoose a harness or label:
npm run sandcastle:analyze:code -- --harness codex --tag-name backlognpm run sandcastle:implementFor each labeled issue, the loop:
- Runs an implementer and requires a committed change.
- Runs a separate read-only reviewer.
- Allows up to two implementation correction rounds.
- Pushes the approved branch and opens a draft PR.
- Closes the issue with the PR URL.
per-task creates one branch and PR per issue. per-session combines approved issues into one branch and PR.
SANDCASTLE_BRANCH_MODE=per-session \
SANDCASTLE_MAX_ITERATIONS=3 \
npm run sandcastle:implement -- --harness codex --tag-name SandcastleCLI flags override environment variables.
| Setting | Values | Default |
|---|---|---|
SANDCASTLE_HARNESS |
opencode, codex, claude-code |
opencode |
SANDCASTLE_SANDBOX |
docker, none |
docker |
SANDCASTLE_BRANCH_MODE |
per-task, per-session |
per-task |
SANDCASTLE_TAG_NAME |
GitHub label | Sandcastle |
SANDCASTLE_MAX_ITERATIONS |
Positive integer | 10 |
OpenCode uses DeepSeek V4 Pro for implementation and Big Pickle for review. Codex uses GPT-5.6 Terra for both. Claude Code uses Claude Opus 4.8 for implementation and Claude Sonnet 4.6 for review; set CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY.
GitHub token permissions:
- Analysis: Issues read/write and Metadata read.
- Implementation: also Contents read/write and Pull requests read/write.
Runtime flags and environment variables configure individual runs. To change the template defaults, edit:
.sandcastle/labels.ts— changeDEFAULT_LABELto select a different GitHub issue queue by default..sandcastle/models.ts— change the allowed harnesses, default harness, and models used by implementer and reviewer agents.
For example, model selection is centralized in createImplementerModel() and createReviewModel(). Keep both functions aligned with the credentials available in your execution environment.
Agent behavior can be customized further in .sandcastle/prompts/. Review rules live in .sandcastle/CODING_STANDARDS.md.
.agents/skills/contains optional interactive workflows for planning, research, TDD, review, triage, prototypes, and architecture work. Read eachSKILL.mdfor usage.- DCG guards supported agents against known destructive commands. Install with
npm run setup:dcg. .sandcastle/CODING_STANDARDS.mddefines rules used by review workflows.
Sandcastle excludes its own .sandcastle/ runner infrastructure from project analysis, implementation, tests, and commits.