A minimal harness demonstrating long-running autonomous coding with the Claude Agent SDK. This demo implements a two-agent pattern (initializer + coding agent) with GitHub as the core project management system for tracking all work.
- GitHub Integration: All work is tracked as GitHub issues, not local files
- Real-time Visibility: Watch agent progress directly in your GitHub repository
- Session Handoff: Agents communicate via GitHub issue comments, not text files
- Two-Agent Pattern: Initializer creates GitHub repo & issues, coding agents implement them
- Browser Testing: Puppeteer MCP for UI verification
- Claude Opus 4.5: Uses Claude's most capable model by default
# Install Claude Code CLI (latest version required)
npm install -g @anthropic-ai/claude-code
# Install Python dependencies
pip install -r requirements.txtYou need two authentication tokens:
Claude Code OAuth Token:
# Generate the token using Claude Code CLI
claude setup-token
# Set the environment variable
export CLAUDE_CODE_OAUTH_TOKEN='your-oauth-token-here'GitHub Personal Access Token:
# Get your token from: https://github.com/settings/tokens
# Required scopes: repo, workflow
export GITHUB_TOKEN='ghp_xxxxxxxxxxxxx'claude --version # Should be latest version
pip show claude-code-sdk # Check SDK is installedpython autonomous_agent_demo.py --project-dir ./my_projectFor testing with limited iterations:
python autonomous_agent_demo.py --project-dir ./my_project --max-iterations 3┌─────────────────────────────────────────────────────────────┐
│ GITHUB-INTEGRATED WORKFLOW │
├─────────────────────────────────────────────────────────────┤
│ app_spec.txt ──► Initializer Agent ──► GitHub Issues (50) │
│ │ │
│ ┌─────────────────────────▼──────────┐ │
│ │ GITHUB REPOSITORY │ │
│ │ ┌────────────────────────────┐ │ │
│ │ │ Issue: Auth - Login flow │ │ │
│ │ │ Status: Open → Closed │ │ │
│ │ │ Comments: [session notes] │ │ │
│ │ └────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
│ │ │
│ Coding Agent queries GitHub │
│ ├── Search for open issues │
│ ├── Add "working on it" comment │
│ ├── Implement & test with Puppeteer │
│ ├── Add comment with implementation notes│
│ └── Close issue │
└─────────────────────────────────────────────────────────────┘
-
Initializer Agent (Session 1):
- Reads
app_spec.txt - Creates a new GitHub repository
- Creates 50 GitHub issues with detailed test steps
- Creates a META issue for session tracking
- Sets up project structure,
init.sh, and git
- Reads
-
Coding Agent (Sessions 2+):
- Queries GitHub for highest-priority open issues
- Runs verification tests on previously completed features
- Claims issue (adds "working on it" comment)
- Implements the feature
- Tests via Puppeteer browser automation
- Adds implementation comment to issue
- Closes the issue
- Updates META issue with session summary
Instead of local text files, agents communicate through:
- Issue Comments: Implementation details, blockers, context
- META Issue: Session summaries and handoff notes
- Issue Status: Open / Closed workflow
| Variable | Description | Required |
|---|---|---|
CLAUDE_CODE_OAUTH_TOKEN |
Claude Code OAuth token (from claude setup-token) |
Yes |
GITHUB_TOKEN |
GitHub personal access token with repo scope | Yes |
| Option | Description | Default |
|---|---|---|
--project-dir |
Directory for the project | ./autonomous_demo_project |
--max-iterations |
Max agent iterations | Unlimited |
--model |
Claude model to use | claude-opus-4-5-20251101 |
github-agent-harness/
├── autonomous_agent_demo.py # Main entry point
├── agent.py # Agent session logic
├── client.py # Claude SDK + MCP client configuration
├── security.py # Bash command allowlist and validation
├── progress.py # Progress tracking utilities
├── prompts.py # Prompt loading utilities
├── github_config.py # GitHub configuration constants
├── prompts/
│ ├── app_spec.txt # Application specification
│ ├── initializer_prompt.md # First session prompt (creates GitHub repo & issues)
│ └── coding_prompt.md # Continuation session prompt (works issues)
└── requirements.txt # Python dependencies
After running, your project directory will contain:
my_project/
├── .github_project.json # GitHub project state (marker file)
├── app_spec.txt # Copied specification
├── init.sh # Environment setup script
├── .claude_settings.json # Security settings
└── [application files] # Generated application code
| Server | Transport | Purpose |
|---|---|---|
| GitHub | stdio | Project management - issues, comments, repositories |
| Puppeteer | stdio | Browser automation for UI testing |
This demo uses defense-in-depth security (see security.py and client.py):
- OS-level Sandbox: Bash commands run in an isolated environment
- Filesystem Restrictions: File operations restricted to project directory
- Bash Allowlist: Only specific commands permitted (npm, node, git, etc.)
- MCP Permissions: Tools explicitly allowed in security settings
Before running, ensure you have:
- A GitHub account
- A personal access token with
repoandworkflowscopes (from Settings > Developer settings > Personal access tokens) - The agent will automatically create a repository and populate it with issues
The initializer agent will create:
- A new GitHub repository named after your app
- 50 feature issues based on
app_spec.txt - 1 META issue for session tracking and handoff
All subsequent coding agents will work from this GitHub repository.
Edit prompts/app_spec.txt to specify a different application to build.
Edit prompts/initializer_prompt.md and change "50 issues" to your desired count.
Edit security.py to add or remove commands from ALLOWED_COMMANDS.
"CLAUDE_CODE_OAUTH_TOKEN not set"
Run claude setup-token to generate a token, then export it.
"GITHUB_TOKEN not set"
Get your personal access token from https://github.com/settings/tokens
Required scopes: repo, workflow
"Appears to hang on first run"
Normal behavior. The initializer is creating a GitHub repository and 50 issues with detailed descriptions. Watch for [Tool: mcp__github__create_issue] output.
"Command blocked by security hook"
The agent tried to run a disallowed command. Add it to ALLOWED_COMMANDS in security.py if needed.
"MCP server connection failed"
Verify your GITHUB_TOKEN is valid and has appropriate scopes (repo, workflow). The GitHub MCP server uses stdio transport with the @modelcontextprotocol/server-github package.
Open your GitHub repository to see:
- The repository created by the initializer agent
- All 50 issues organized with labels
- Real-time status changes (Open → Closed)
- Implementation comments on each issue
- Session summaries on the META issue
This is based on the Linear-Coding-Agent-Harness but uses GitHub instead:
Key Changes:
- Uses GitHub Issues instead of Linear Issues
- Uses GitHub MCP Server (
@modelcontextprotocol/server-github) instead of Linear MCP - Status workflow: Open/Closed instead of Todo/In Progress/Done
- Labels instead of priority fields
- Repository-based instead of team/project-based
- Issue comments for all communication
Advantages:
- More accessible (GitHub is ubiquitous)
- No Linear account needed
- Easier to share and collaborate
- Direct integration with git hosting
MIT License - see LICENSE for details.