The computer watches your GitHub Issues and makes PRs for them.
_______________
| ___________ |
| | | |
| | HELLO | |
| | WORLD | |
| |___________| |
|_______________|
_[_____]_
[_________]
- Polling Loop:
get_issues.pypolls GitHub for unclaimed issues - Issue Processing: For each issue, it clones the repo and runs Claude Code headless with the issue prompt
- Sandboxed Execution: Claude Code works autonomously to create a PR or comment on the issue
The system runs Claude Code inside a macOS VM (via Tart) to isolate operations:
-
Host (
host/): Orchestrates VM lifecycle and token managementbuild-sandbox.sh: Creates a fresh VM from base image and installs dependenciesrun-sandbox.sh: Starts the VM, copies code, pushes tokens, and runs the polling looprefresh-token.py: Periodically generates fresh GitHub App tokens (every 30 min) and pushes them to the VM via SSH
-
Sandbox (
sandbox/): Runs inside the VMget_issues.py: Main script that polls issues and invokes Claude Codegh-wrapper.py: Wrapper aroundghCLI that injects the GitHub token from a filegit-credential-app.py: Git credential helper that provides the GitHub token for git operationssandbox-inner.sh: Entry point that starts the polling loop inside the VM
- GitHub App Private Key: Used by the host to generate installation tokens. Passed to
run-sandbox.shvia environment config JSON. - GitHub App Installation Token: Short-lived (1 hour) token generated from the private key. Refreshed every 30 minutes and pushed to the VM at
~/.github-app-token. - Claude Code OAuth Token: Personal token for Claude Code authentication. Pushed to the VM at
~/.claude-oauth-tokenduring VM startup.
The token architecture ensures:
- The VM never has access to the long-lived private key
- Tokens are automatically refreshed before expiration
- Git and GitHub CLI operations work seamlessly via credential helpers and wrappers