Skip to content

Free-AI-Things/issueclaw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ¦ƒ IssueClaw

The AI assistant that lives in your GitHub Issues.

Your own private AI β€” running for free on GitHub. No servers. No databases. No monthly bills.

CI License: MIT [Bun] [Tests] [Gemini Free] [Groq Free]

⭐ Star this repo if it helps you! ⭐

Quick Start Β· How It Works Β· Story Β· Full Docs


πŸ€” What is IssueClaw?

IssueClaw is an AI assistant that lives inside your GitHub repo. You talk to it by opening issues. It responds by commenting. It remembers everything. It can even edit your code.

No servers. No databases. No monthly bills. Just GitHub Issues + GitHub Actions + your favorite LLM API.

The magic in 30 seconds

1. You open an issue: "Build me a portfolio site"
2. IssueClaw reacts with πŸ‘€ (it's working!)
3. IssueClaw creates the files, commits them to your repo
4. IssueClaw replies as a comment: "Done! Here's what I built..."
5. You comment back: "Add a dark mode toggle"
6. IssueClaw remembers the whole conversation and edits the files

Total cost: $0/month with Groq or Gemini's free tier.


πŸš€ Quick Start

Step 1: Fork & clone

git clone https://github.com/maruf009sultan/issueclaw.git
cd issueclaw

Step 2: Get a FREE API key

Pick one (or more):

Provider Free? Get Key Best for
Groq βœ… https://console.groq.com/keys Quick chat (default mode)
Gemini βœ… https://aistudio.google.com/app/apikey Full agent mode (file editing)
Cerebras βœ… https://inference.cerebras.ai/ Fast agent mode
OpenRouter βœ… https://openrouter.ai/keys Many free models

Step 3: Add the key as a GitHub secret

In your forked repo: Settings β†’ Secrets and variables β†’ Actions β†’ New repository secret

  • Name: GROQ_API_KEY (or GEMINI_API_KEY, CEREBRAS_API_KEY, etc.)
  • Value: your API key

Step 4: Enable Actions

Go to the Actions tab β†’ click "I understand my workflows, go ahead and enable them"

Step 5: Open an issue! πŸŽ‰

That's it! Open an issue and IssueClaw responds automatically.


🧠 How It Works

IssueClaw has two modes:

πŸ’¬ Chat Mode (default)

Open an issue with no label β†’ IssueClaw responds directly, like ChatGPT.

  • Uses ~500 tokens per message
  • Works perfectly with Groq's free tier (12K TPM)
  • Perfect for: questions, explanations, quick help

πŸ€– Agent Mode

Open an issue with the agent label β†’ IssueClaw becomes a full coding agent.

  • Can read files, edit files, run bash, commit to your repo
  • Uses ~120,000 tokens per message
  • Needs Gemini (1M TPM) or Cerebras (60K TPM) β€” Groq can't handle it
  • Perfect for: "Build me a website", "Fix this bug", "Add a README"

πŸ₯š Hatch Mode

Open an issue with the hatch label β†’ bootstrap IssueClaw's personality.

IssueClaw will have a conversation with you to figure out its name, vibe, and emoji. Stored in state/personality.md β€” persists forever via git.


πŸ“– The Story

The problem

AI assistants are great, but they have problems:

  • They're expensive β€” ChatGPT Plus is $20/month, Copilot is $10/month
  • They forget everything β€” close the tab, lose the context
  • They can't touch your code β€” copy-paste workflow is painful
  • They need servers β€” self-hosting means Docker, GPUs, config

The idea

What if your AI assistant lived inside your GitHub repo? What if:

  • You talk to it by opening issues (infrastructure you already have)
  • It remembers everything because conversations are committed to git
  • It edits your code directly and pushes commits
  • It runs on GitHub Actions (free for public repos)
  • It uses free LLM APIs (Groq, Gemini, Cerebras)

The origin

This project builds on two brilliant predecessors:

  1. gitclaw by Sawyer Hood β€” the original idea of an AI agent that lives in GitHub Issues. Sawyer's creativity sparked this whole concept.

  2. pi-mono by Mario Zechner β€” the production-grade coding agent CLI (v0.80.3) that powers the agent mode. Mario built the entire agent loop, tool system, and multi-provider support.

IssueClaw takes these foundations and adds:

  • βœ… Multi-provider support β€” 8 LLM providers with automatic fallback
  • βœ… Two modes β€” chat (saves 99% of tokens) + agent (full tools)
  • βœ… Persistent memory β€” git-backed, survives forever
  • βœ… Production-grade β€” 122 tests, audit trail, concurrency control
  • βœ… Free to run β€” $0/month with Groq/Gemini free tiers

Why "IssueClaw"?

Because it claws into your issues and gets things done. πŸ¦ƒ


πŸ’Ž Why IssueClaw?

vs. ChatGPT Plus ($20/month)

ChatGPT Plus IssueClaw
Cost $20/month $0/month
Code editing Copy-paste Direct git commits
Memory Session-only Permanent (in git)
Custom personality No Yes
Self-hosted No Yes (your repo)

vs. GitHub Copilot ($10/month)

Copilot IssueClaw
Cost $10/month $0/month
Interaction IDE only GitHub Issues (anywhere)
Multi-provider No Yes (8 providers)
Personality No Yes

vs. Self-hosted LLM

Self-hosted IssueClaw
Setup Docker, GPU, config Fork + 1 secret
Hardware GPU recommended None
Memory Manual Automatic

🎯 Use Cases

πŸ’¬ Quick Chat (Groq, free)

Open an issue, no label:

  • "What's the capital of France?"
  • "Explain how async/await works"
  • "What's the BTC price right now?"

IssueClaw responds in ~5 seconds, using ~500 tokens.

πŸ€– Code Tasks (Gemini/Cerebras, free)

Open an issue with agent label:

  • "Build me a 3-file portfolio site"
  • "Fix the bug in src/main.ts"
  • "Add a README to this repo"
  • "Create a GitHub Actions workflow"

IssueClaw creates/edits files, commits to git, and replies.

πŸ₯š Personalize (any provider)

Open an issue with hatch label:

  • IssueClaw asks: "Who am I? Who are you?"
  • You decide its name, vibe, emoji
  • Stored in state/personality.md forever

πŸ“ Long Conversations

Comment on an existing issue β†’ IssueClaw resumes with full context. It remembers everything said before in that issue thread.


πŸ› οΈ Features at a Glance

Feature Status
πŸ’¬ Simple chat mode (saves 99% of tokens) βœ…
πŸ€– Full agent mode (bash, edit, read, write, grep) βœ…
🧠 Persistent memory (git-backed) βœ…
🎭 Custom personality (hatch flow) βœ…
πŸ”„ Multi-provider fallback (8 providers) βœ…
πŸ”’ Permission checks (OWNER/MEMBER/COLLAB only) βœ…
⚑ Concurrency control (no race conditions) βœ…
πŸ“‹ Audit logging (JSON trail) βœ…
🐳 Docker support βœ…
πŸ§ͺ 122 tests (unit + integration + live) βœ…
πŸ†“ $0/month with free tiers βœ…

πŸ“Š Token Usage

Mode Tokens/message Works with Groq? Works with Gemini?
πŸ’¬ Chat (default) ~500 βœ… Yes βœ… Yes
πŸ€– Agent (agent label) ~120,000 ❌ No (413 error) βœ… Yes
πŸ₯š Hatch (hatch label) ~120,000 ❌ No βœ… Yes

Rule of thumb: Use chat mode (default) for questions. Use agent mode only for code tasks, and only with Gemini/Cerebras.


πŸ”§ Configuration

IssueClaw auto-generates its config on first run. To manually generate:

bun run src/cli.ts config auto

This detects which API keys you have and builds the optimal config. Edit issueclaw.config.json to customize.

Providers (pick one or more)

Secret Provider Free?
GROQ_API_KEY Groq βœ…
GEMINI_API_KEY Gemini βœ…
CEREBRAS_API_KEY Cerebras βœ…
OPENROUTER_API_KEY OpenRouter βœ…
ANTHROPIC_API_KEY Anthropic ❌
OPENAI_API_KEY OpenAI ❌

🩺 Troubleshooting

"413 Token limit exceeded"

You're using agent mode with Groq. Agent mode needs ~120K tokens, but Groq's free tier is 12K TPM.

Fix: Either use chat mode (no label), or set GEMINI_API_KEY for agent mode.

"Provider requires API_KEY"

The secret isn't set. Go to Settings β†’ Secrets β†’ Actions and add it.

Agent doesn't respond

  1. Check the Actions tab β€” did the workflow run?
  2. Are you OWNER/MEMBER/COLLABORATOR?
  3. Run bun run src/cli.ts doctor locally

🀝 Community


❀️ Acknowledgments

IssueClaw stands on the shoulders of giants:


πŸ“„ License

MIT β€” see LICENSE. Use it however you want.


Made with πŸ¦ƒ by the IssueClaw community

⬆ Back to top



πŸ“š Full Documentation

πŸ“– Click to expand the complete technical reference

πŸ¦ƒ IssueClaw

The AI assistant that lives in your GitHub repo.

No servers. No databases. No monthly bills. Just issues, actions, and git.

Your own private AI β€” running for free on GitHub infrastructure.

CI License: MIT [Bun] [TypeScript] [Tests] [Gemini Free] [Live Tested]

⭐ Star this repo if it helps you! ⭐

Features Β· Quick Start Β· How It Works Β· Configuration Β· Providers Β· FAQ Β· Docs


πŸš€ The elevator pitch: Fork this repo β†’ add one free API key β†’ open a GitHub issue β†’ get an AI assistant that remembers everything across sessions, commits all its work to git, and runs entirely inside GitHub Actions. Zero infrastructure. Zero cost. Infinite possibilities.


πŸ“‘ Table of Contents

πŸ“– Click to expand the full table of contents

πŸ€” What Is This?

IssueClaw is a self-hosted AI assistant that runs entirely through GitHub Issues and GitHub Actions. There is no server to deploy, no database to manage, no monthly cloud bill. The agent wakes up when you open an issue, does its work in a GitHub Actions runner, commits all state back to your repo, and replies as a comment.

It's built on top of pi-mono v0.80.3 β€” a production-grade coding agent CLI with tool use, session management, and multi-provider support.

The problem we solve

Problem IssueClaw Solution
AI assistants are expensive (ChatGPT Plus, Claude Pro) $0/month with Gemini's free tier (1M TPM)
AI assistants forget everything between sessions Persistent memory committed to git β€” survives forever
AI assistants can't edit your code Full agent mode with bash, file editing, git access
AI assistants require servers/infrastructure Zero infrastructure β€” runs in GitHub Actions
AI assistants don't have personality Mutable identity via personality.md β€” bootstrap with hatch label
AI chatbots waste tokens on system prompts Simple chat mode uses ~500 tokens (vs ~120K for agents)
AI APIs have rate limits Multi-provider fallback chain β€” if one fails, try the next

The quick comparison

Question Answer
Where does the agent run? In GitHub Actions (ubuntu-latest runner)
Where does it store memory? In your git repo, under state/
How do I talk to it? Open a GitHub issue, or comment on one
How does it remember me? Every session is committed to git; future sessions read prior state
What LLMs does it support? Gemini (free, 1M TPM), Cerebras (free), OpenRouter (free models), Groq, Anthropic, OpenAI, Ollama, or any OpenAI-compatible endpoint
Is it production-ready? Yes β€” 122 tests passing, structured logging, retry logic, audit trail, concurrency control
Can random internet people trigger it? No β€” only OWNER/MEMBER/COLLABORATOR can
Cost? $0 with Gemini's free tier. GitHub Actions is free for public repos.
Can it edit files in my repo? Yes β€” in agent mode, it has bash, read, write, edit, grep, glob, ls tools
Can I just chat without the agent? Yes β€” use the "chat" label for simple Q&A (saves 99% of API tokens)

What it looks like in practice

1. You open an issue: "Set up a GitHub Pages site for this repo"
        ↓
2. Within seconds, the agent reacts with πŸ‘€ on your issue
        ↓
3. The agent runs in Actions, reads your repo, edits files,
   and commits everything to git
        ↓
4. It replies as a comment on the issue with what it did
        ↓
5. The πŸ‘€ reaction is removed
        ↓
6. Next time you comment on that issue, it resumes the SAME
   session with full prior context β€” it remembers everything

Or, for simple chat:

1. You open an issue with the "chat" label: "What's the capital of France?"
        ↓
2. The agent reacts with πŸ‘€
        ↓
3. A lightweight LLM call is made (no agent, no tools β€” saves API quota)
        ↓
4. The agent replies: "The capital of France is Paris."
        ↓
5. The πŸ‘€ reaction is removed
        ↓
6. Cost: ~500 tokens (vs ~120,000 for full agent mode)

✨ Features

Enterprise-Grade Features

πŸ”„ Multi-Provider LLM Support

IssueClaw supports 8 LLM providers out of the box, with automatic fallback:

  • πŸ”΅ Google Gemini β€” 1,000,000 TPM free tier (recommended default)
  • ⚑ Cerebras β€” 60,000 TPM, ultra-fast (1000+ tokens/sec)
  • πŸ”΅ OpenRouter β€” access to hundreds of models, many free
  • ⚑ Groq β€” 12,000 TPM, fast inference
  • 🟣 Anthropic β€” Claude Opus 4, Sonnet 4.5 (paid)
  • 🟒 OpenAI β€” GPT-4o, o1, o3 (paid)
  • πŸ¦™ Ollama β€” local LLMs (self-hosted, free)
  • πŸ”§ Custom β€” any OpenAI-compatible endpoint (Azure, Together, vLLM, LM Studio, etc.)

⛓️ Provider Fallback Chain

When one provider fails (rate limit, network error, quota exceeded), the agent automatically tries the next provider in the chain. You configure the order in issueclaw.config.json:

{
  "providers": [
    { "type": "gemini", "model": "gemini-2.0-flash", "default": true },
    { "type": "cerebras", "model": "llama-3.3-70b" },
    { "type": "openrouter", "model": "nvidia/nemotron-3-nano-30b-a3b:free" },
    { "type": "groq", "model": "llama-3.3-70b-versatile" }
  ]
}

If Gemini fails β†’ tries Cerebras β†’ tries OpenRouter β†’ tries Groq. The error message shows all provider attempts, so you know exactly what happened.

🧠 Persistent Memory

The agent has four types of persistent state, all committed to git:

File Purpose Mutability
state/memory.md Append-only log of important facts, decisions, preferences Append-only
state/personality.md Agent identity (name, vibe, emoji, hatch date) Mutable
state/user.md User profile (name, preferences, communication style) Mutable
state/audit.log JSON audit trail of every agent run Append-only

At the start of every session, the agent's prompt is built from:

  1. state/personality.md β€” who the agent is
  2. state/user.md β€” what the agent knows about you
  3. Last 20 lines of state/memory.md β€” recent durable facts
  4. The issue title + body β€” what you're asking now
  5. Operating instructions

πŸ“‹ Audit Logging

Every agent run is logged as JSON to state/audit.log:

{
  "timestamp": "2026-07-07T10:30:00.000Z",
  "action": "agent_run_complete",
  "details": {
    "issue": 5,
    "success": true,
    "durationMs": 45230,
    "provider": "gemini",
    "responseLength": 1847
  }
}

You can query it with jq:

# Recent activity
tail -5 state/audit.log | jq .

# All errors
jq 'select(.details.success == false)' state/audit.log

# Runs per issue
jq -s 'group_by(.details.issue) | map({issue: .[0].details.issue, count: length})' state/audit.log

πŸ”’ Permission Checks

Only users with OWNER, MEMBER, or COLLABORATOR association on the repo can trigger the agent. This is enforced in two places:

  1. Workflow if: condition (in .github/workflows/agent.yml)
  2. shouldProcessEvent() in code (src/github/events.ts)

Random internet users cannot trigger the agent on public repos. Bots (github-actions[bot], dependabot[bot]) are also rejected to prevent infinite loops.

⚑ Concurrency Control

The workflow uses GitHub's concurrency groups to serialize runs per issue:

concurrency:
  group: ${{ github.workflow }}-${{ github.event.issue.number }}
  cancel-in-progress: false

This means: if you comment on issue #5 three times in rapid succession, those three runs happen sequentially, not in parallel. This prevents git push conflicts and ensures session state is consistent.

πŸ”„ Retry with Backoff

All network operations use exponential backoff with jitter:

  • Initial delay: 1 second
  • Multiplier: 2x
  • Max delay: 30 seconds
  • Max attempts: 3 (configurable)
  • Jitter: random 0-50% of delay

This handles transient network errors, rate limits, and 5xx server errors gracefully.

πŸ“Š Session Artifacts

Every workflow run uploads state/ and the raw agent JSONL output as a GitHub Actions artifact, retained for 30 days. Download from the Actions tab β†’ click a run β†’ scroll to "Artifacts".

⏱️ Timeouts

Two layers of timeout protection prevent runaway runs:

  • Job timeout: 30 minutes (in workflow timeout-minutes)
  • Agent timeout: 15 minutes (configurable in agent.timeoutMs)

🐳 Docker Support

Containerized for local development parity with CI:

docker compose build
docker compose run --rm issueclaw doctor

The Dockerfile uses oven/bun:1.1-debian and installs git, gh, curl, jq, ripgrep.

πŸ§ͺ Comprehensive Tests

122 tests across three layers:

Layer Count What it tests
Unit tests 99 Individual modules (config, providers, memory, github, agent, utils, simple-chat)
Integration tests 4 Full lifecycle with mocked pi
Live tests 29 End-to-end pipeline with real pi + mock LLM server

πŸ” Structured Logging

Two output modes:

Human-readable (default in TTY):

[2026-07-07T10:30:00.000Z] INFO  [issueclaw] agent run succeeded {"provider":"gemini/gemini-2.0-flash","durationMs":45230}

JSON (for log aggregation β€” set ISSUECLAW_LOG_JSON=true):

{"ts":"2026-07-07T10:30:00.000Z","level":"info","component":"issueclaw","msg":"agent run succeeded","provider":"gemini/gemini-2.0-flash","durationMs":45230}

Log levels: trace, debug, info, warn, error, fatal.

πŸ› οΈ CLI Tool

Full CLI for local testing and management:

issueclaw doctor          # Diagnose environment & config
issueclaw config auto     # Auto-generate config from env
issueclaw config show     # Print current config
issueclaw config validate # Validate config
issueclaw memory show     # Show memory log
issueclaw memory search   # Search memory
issueclaw personality show# Show personality
issueclaw test lifecycle  # Run lifecycle against test event
issueclaw test prompt     # Show prompt that would be sent

Original IssueClaw Features (Preserved & Enhanced)

The original issueclaw by Sawyer Hood had these features β€” all preserved and enhanced:

  • πŸ’¬ Issue-Driven β€” open an issue β†’ agent processes β†’ replies as comment
  • πŸ” Session Resume β€” comment on existing issue β†’ agent resumes with full context
  • πŸ“ Git-Backed State β€” all state in state/ directory, committed to git
  • πŸ‘€ Eyes Reaction β€” agent reacts with πŸ‘€ while working, removes when done
  • πŸ₯š Hatch Flow β€” bootstrap agent identity via hatch label
  • πŸ” Self-Search β€” agent can grep its own conversation history
  • 🎨 Personality β€” mutable identity stored in state/personality.md

NEW: Simple Chat Mode

The killer feature for saving API quota.

The full agent mode uses ~120,000 tokens per message (pi's system prompt + tool definitions + context). That blows past free-tier limits on Groq (12K TPM) and even strains Cerebras (60K TPM).

Simple chat mode bypasses the agent entirely and calls the LLM API directly:

Metric Full Agent Mode Simple Chat Mode Savings
Tokens per message ~120,000 ~500 99.6% reduction
Tools available bash, edit, read, grep, etc. None β€”
File editing Yes No β€”
Session resume Yes (JSONL) No (stateless) β€”
Use case Code tasks, file edits Quick Q&A, questions β€”

How to use it: Open an issue with the "chat" label (or use the "πŸ’¬ Chat" issue template). The agent will respond directly without using tools β€” perfect for questions like "What's the capital of France?" or "Explain how X works."

The simple chat mode still:

  • βœ… Saves to state/audit.log
  • βœ… Commits state changes to git
  • βœ… Posts a comment on the issue
  • βœ… Uses the provider fallback chain
  • βœ… Includes personality + recent memory in the system prompt

πŸš€ Quick Start (3 minutes)

Step 1: Fork & clone

# Fork https://github.com/maruf009sultan/issueclaw on GitHub
git clone https://github.com/maruf009sultan/issueclaw.git
cd issueclaw

Step 2: Get a FREE API key

Option A: Google Gemini (RECOMMENDED β€” 1M TPM)

  1. Go to https://aistudio.google.com/app/apikey
  2. Sign in with Google
  3. Click "Create API Key"
  4. Copy the key (starts with AIza...)

Why Gemini? 1,000,000 tokens per minute free tier β€” 83x higher than Groq. Perfect for AI agents with large system prompts and tool definitions.

Option B: Cerebras (free, ultra-fast)

  1. Go to https://inference.cerebras.ai/
  2. Sign up
  3. Generate an API key (starts with csk_...)

Option C: OpenRouter (has free models)

  1. Go to https://openrouter.ai/keys
  2. Sign up
  3. Generate an API key (starts with sk-or-v1-...)

Option D: Groq (free, but low 12K TPM)

  1. Go to https://console.groq.com/keys

You can set multiple keys β€” the agent uses them as a fallback chain.

Step 3: Add the key(s) as GitHub secrets

In your forked repo:

  1. Go to Settings β†’ Secrets and variables β†’ Actions
  2. Click "New repository secret" for each key you have:
    • GEMINI_API_KEY (recommended)
    • CEREBRAS_API_KEY
    • OPENROUTER_API_KEY
    • GROQ_API_KEY
    • ANTHROPIC_API_KEY (paid)
    • OPENAI_API_KEY (paid)

Step 4: Enable Actions

  1. Go to the Actions tab in your repo
  2. If you see a banner saying "Workflows aren't being run on forked repositories", click "I understand my workflows, go ahead and enable them"

Step 5: Open an issue πŸŽ‰

For a quick chat:

  • Use the "πŸ’¬ Chat" issue template
  • Or open an issue and add the chat label

For code tasks:

  • Use the "πŸ”§ Task" issue template
  • Or just open a regular issue

Within ~10 seconds:

  • The agent will react with πŸ‘€
  • The IssueClaw Agent workflow will start in the Actions tab
  • After ~30-60 seconds, the agent will reply as a comment
  • The πŸ‘€ reaction will be removed

That's it. You now have a free, self-hosted AI assistant living in your repo.

Step 6 (optional): Hatch the agent's personality

Use the "πŸ₯š Hatch" issue template to bootstrap the agent's identity. The agent will have a conversation with you to figure out its name, vibe, and emoji β€” all stored in state/personality.md and persisted via git.


🧠 How It Works

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        YOUR GITHUB REPO                              β”‚
β”‚                                                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚  β”‚  Issue   │───▢│  GitHub      │───▢│  Actions Workflow     β”‚      β”‚
β”‚  β”‚  Opened  β”‚    β”‚  Webhook     β”‚    β”‚  (.github/workflows/) β”‚      β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                                                  β”‚                  β”‚
β”‚                                                  β–Ό                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                   GITHUB ACTIONS RUNNER                      β”‚   β”‚
β”‚  β”‚                                                              β”‚   β”‚
β”‚  β”‚  1. preinstall.ts                                            β”‚   β”‚
β”‚  β”‚     β”œβ”€ Parse GitHub event                                    β”‚   β”‚
β”‚  β”‚     β”œβ”€ Check permissions (OWNER/MEMBER/COLLAB)               β”‚   β”‚
β”‚  β”‚     └─ Add πŸ‘€ reaction                                       β”‚   β”‚
β”‚  β”‚                                                              β”‚   β”‚
β”‚  β”‚  2. main.ts                                                  β”‚   β”‚
β”‚  β”‚     β”œβ”€ Detect mode: "chat" label β†’ simple chat              β”‚   β”‚
β”‚  β”‚     β”‚                   "hatch" label β†’ agent + bootstrap    β”‚   β”‚
β”‚  β”‚     β”‚                   default β†’ full agent                 β”‚   β”‚
β”‚  β”‚     β”œβ”€ Init MemoryStore (state/memory.md, etc.)              β”‚   β”‚
β”‚  β”‚     β”œβ”€ Configure git                                         β”‚   β”‚
β”‚  β”‚     β”‚                                                        β”‚   β”‚
β”‚  β”‚     β”œβ”€ IF CHAT MODE:                                         β”‚   β”‚
β”‚  β”‚     β”‚  β”œβ”€ Build minimal system prompt (~200 tokens)          β”‚   β”‚
β”‚  β”‚     β”‚  β”œβ”€ Call LLM API directly (no pi, no tools)            β”‚   β”‚
β”‚  β”‚     β”‚  └─ Get response (~500 tokens total)                   β”‚   β”‚
β”‚  β”‚     β”‚                                                        β”‚   β”‚
β”‚  β”‚     β”œβ”€ IF AGENT MODE:                                        β”‚   β”‚
β”‚  β”‚     β”‚  β”œβ”€ Build prompt (injects memory + personality)        β”‚   β”‚
β”‚  β”‚     β”‚  β”œβ”€ Run pi agent (with provider fallback chain)        β”‚   β”‚
β”‚  β”‚     β”‚  β”‚    β”œβ”€ Try Gemini β†’ if fails, try Cerebras β†’ ...     β”‚   β”‚
β”‚  β”‚     β”‚  β”‚    └─ Pi makes HTTP call to LLM API                 β”‚   β”‚
β”‚  β”‚     β”‚  β”œβ”€ Extract response from JSONL output                 β”‚   β”‚
β”‚  β”‚     β”‚  └─ Save session mapping (state/issues/N.json)         β”‚   β”‚
β”‚  β”‚     β”‚                                                        β”‚   β”‚
β”‚  β”‚     β”œβ”€ git add -A && git commit && git push                  β”‚   β”‚
β”‚  β”‚     β”œβ”€ Post comment on issue via `gh` CLI                    β”‚   β”‚
β”‚  β”‚     └─ (finally) Remove πŸ‘€ reaction                          β”‚   β”‚
β”‚  β”‚                                                              β”‚   β”‚
β”‚  β”‚  3. Upload state/ as artifact (30-day retention)             β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                    STATE DIRECTORY                            β”‚   β”‚
β”‚  β”‚                                                              β”‚   β”‚
β”‚  β”‚  state/                                                      β”‚   β”‚
β”‚  β”‚    memory.md          ← append-only fact log                 β”‚   β”‚
β”‚  β”‚    personality.md     ← mutable agent identity               β”‚   β”‚
β”‚  β”‚    user.md            ← mutable user profile                 β”‚   β”‚
β”‚  β”‚    audit.log          ← JSON audit trail                     β”‚   β”‚
β”‚  β”‚    issues/1.json      ← issue #1 β†’ session mapping           β”‚   β”‚
β”‚  β”‚    sessions/*.jsonl   ← full conversation transcripts        β”‚   β”‚
β”‚  β”‚                                                              β”‚   β”‚
β”‚  β”‚  ↑ Everything here is committed to git after every turn      β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The Lifecycle: Step by Step

1. You open an issue (or comment on one)

  • GitHub fires a webhook β†’ triggers the IssueClaw Agent workflow
  • The workflow's if: condition checks your author_association is OWNER, MEMBER, or COLLABORATOR
  • Bots (github-actions[bot], dependabot[bot], etc.) are rejected β€” prevents infinite loops

2. preinstall.ts runs

  • Parses the GitHub event payload (GITHUB_EVENT_PATH)
  • Adds πŸ‘€ reaction to the issue or comment (visual feedback that the agent is working)
  • Writes reaction state to /tmp/reaction-state.json for cleanup later

3. bun install runs

  • Installs @earendil-works/pi-coding-agent and dependencies
  • Cached across runs via actions/cache

4. main.ts runs β€” the main event

  • Initializes MemoryStore (creates state/memory.md, personality.md, user.md with defaults if missing)
  • Configures git identity (issueclaw[bot])
  • Detects mode based on issue labels:
    • chat label β†’ simple chat mode (lightweight LLM call, ~500 tokens)
    • hatch label β†’ agent mode + bootstrap identity flow
    • no special label β†’ full agent mode (pi agent with tools, ~120K tokens)
  • Checks for existing session mapping in state/issues/<N>.json

If simple chat mode:

  • Builds a minimal system prompt (~200 tokens) with personality + recent memory
  • Calls the LLM API directly (no pi, no tools)
  • Provider fallback chain: Gemini β†’ Cerebras β†’ OpenRouter β†’ Groq β†’ ...
  • Returns response (~500 tokens total)

If agent mode:

  • Builds the prompt β€” combines:
    • state/personality.md (agent identity)
    • state/user.md (user profile)
    • Last 20 lines of state/memory.md (recent memory)
    • The issue title + body (or comment body) β€” with template boilerplate stripped
    • Operating instructions
    • Hatch trigger (if hatch label present)
  • Token budget enforcement: if prompt > 6,000 tokens, progressively strips context
  • Runs pi with the provider fallback chain
  • Pi makes an HTTP call to the LLM API, streams back a response as JSONL
  • Extracts the final assistant message from the JSONL (never the user message β€” that was a bug we fixed)
  • Saves the session mapping (state/issues/<N>.json β†’ state/sessions/<timestamp>.jsonl)

In both modes:

  • Commits everything to git: git add -A && git commit -m "issueclaw: work on issue #N (mode)" && git push
    • If push fails (race condition), auto-rebases and retries up to 3 times
  • Posts a comment on the issue with the agent's response
    • If response > 60,000 chars, truncates with a notice pointing to the session file
    • If agent failed, posts a detailed error comment with all provider attempts and troubleshooting hints
  • In a finally block, removes the πŸ‘€ reaction

5. Workflow uploads state/ as an artifact (30-day retention) for debugging

Two Modes: Agent vs. Simple Chat

Aspect Agent Mode Simple Chat Mode
Trigger Default (no label) or hatch label chat label
Tokens per message ~120,000 ~500
Tools bash, read, edit, write, grep, glob, ls None
File editing Yes No
Session resume Yes (JSONL transcripts) No (stateless)
Use case Code tasks, file edits, complex work Quick Q&A, questions
API quota impact High Minimal
Speed 30-120 seconds 2-10 seconds

When to use which:

  • Simple chat: "What's the capital of France?", "Explain how async/await works", "What's the weather API format?"
  • Agent mode: "Create a hello world HTML page", "Fix the bug in src/main.ts", "Add a README to this repo"

Concurrency Model

The workflow uses GitHub's concurrency groups to serialize runs per issue:

concurrency:
  group: ${{ github.workflow }}-${{ github.event.issue.number }}
  cancel-in-progress: false

This means: if you comment on issue #5 three times in rapid succession, those three runs happen sequentially, not in parallel. The second run waits for the first to finish, then starts. This prevents:

  • Git push conflicts
  • Session state corruption
  • Race conditions in state commits

πŸ“ Project Structure

issueclaw/
β”‚
β”œβ”€β”€ .github/
β”‚   β”œβ”€β”€ workflows/
β”‚   β”‚   β”œβ”€β”€ agent.yml           ← Main workflow: triggers on issues/comments/PRs
β”‚   β”‚   β”œβ”€β”€ ci.yml              ← CI: lint, typecheck, test on every PR
β”‚   β”‚   └── scheduled.yml       ← Daily maintenance: cleanup orphaned sessions
β”‚   └── ISSUE_TEMPLATE/
β”‚       β”œβ”€β”€ hatch.md            ← πŸ₯š Bootstrap agent identity
β”‚       β”œβ”€β”€ task.md             ← πŸ”§ General task (agent mode)
β”‚       β”œβ”€β”€ chat.md             ← πŸ’¬ Quick chat (simple chat mode β€” saves quota)
β”‚       └── bug.md              ← πŸ› Bug report
β”‚
β”œβ”€β”€ .pi/                         ← Pi agent configuration
β”‚   β”œβ”€β”€ settings.json           ← Legacy compat (provider/model/thinking)
β”‚   β”œβ”€β”€ APPEND_SYSTEM.md        ← Appended to pi's system prompt
β”‚   β”œβ”€β”€ BOOTSTRAP.md            ← Read during hatch flow
β”‚   β”œβ”€β”€ extensions/
β”‚   β”‚   └── mock-provider.ts    ← Test-only mock LLM provider
β”‚   └── skills/
β”‚       └── memory/
β”‚           └── SKILL.md        ← Memory search skill for the agent
β”‚
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ cli.ts                  ← πŸ› οΈ CLI entrypoint (issueclaw command)
β”‚   β”œβ”€β”€ config.ts               ← Zod-validated config + auto-generation
β”‚   β”œβ”€β”€ providers/              ← LLM provider implementations
β”‚   β”‚   β”œβ”€β”€ types.ts            ← Provider interface
β”‚   β”‚   β”œβ”€β”€ gemini.ts           ← πŸ”΅ Google Gemini (1M TPM, recommended)
β”‚   β”‚   β”œβ”€β”€ cerebras.ts         ← ⚑ Cerebras (ultra-fast)
β”‚   β”‚   β”œβ”€β”€ openrouter.ts       ← πŸ”΅ OpenRouter (any model)
β”‚   β”‚   β”œβ”€β”€ groq.ts             ← ⚑ Groq
β”‚   β”‚   β”œβ”€β”€ anthropic.ts        ← 🟣 Anthropic (Claude)
β”‚   β”‚   β”œβ”€β”€ openai.ts           ← 🟒 OpenAI (GPT-4o)
β”‚   β”‚   β”œβ”€β”€ ollama.ts           ← πŸ¦™ Ollama (local)
β”‚   β”‚   β”œβ”€β”€ custom.ts           ← πŸ”§ Custom (any OpenAI-compatible)
β”‚   β”‚   └── index.ts            ← Registry + factory
β”‚   β”œβ”€β”€ github/
β”‚   β”‚   β”œβ”€β”€ client.ts           ← `gh` CLI wrapper with retry
β”‚   β”‚   └── events.ts           ← Webhook payload parsing
β”‚   β”œβ”€β”€ agent/
β”‚   β”‚   β”œβ”€β”€ runner.ts           ← Pi orchestration + fallback chain
β”‚   β”‚   └── simple-chat.ts      ← πŸ’¬ Lightweight LLM call (no agent)
β”‚   β”œβ”€β”€ memory/
β”‚   β”‚   └── store.ts            ← Atomic file writes, issue mappings
β”‚   β”œβ”€β”€ lifecycle/
β”‚   β”‚   β”œβ”€β”€ preinstall.ts       ← Add reaction, check perms
β”‚   β”‚   └── main.ts             ← Run agent/chat, commit, comment, cleanup
β”‚   └── utils/
β”‚       β”œβ”€β”€ log.ts              ← Structured logger (levels + JSON)
β”‚       β”œβ”€β”€ retry.ts            ← Exponential backoff + jitter
β”‚       β”œβ”€β”€ git.ts              ← Git operations with retry
β”‚       └── fs.ts               ← Atomic writes, safe reads
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ unit/                   ← 99 unit tests (Vitest)
β”‚   β”‚   β”œβ”€β”€ config.test.ts
β”‚   β”‚   β”œβ”€β”€ providers.test.ts
β”‚   β”‚   β”œβ”€β”€ memory.test.ts
β”‚   β”‚   β”œβ”€β”€ github.test.ts
β”‚   β”‚   β”œβ”€β”€ agent.test.ts
β”‚   β”‚   β”œβ”€β”€ simple-chat.test.ts ← Tests for the chat mode
β”‚   β”‚   └── utils.test.ts
β”‚   └── integration/
β”‚       └── lifecycle.test.ts   ← End-to-end with mocked pi
β”‚
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ live-test.ts            ← πŸ§ͺ Full pipeline test (mock LLM)
β”‚   β”œβ”€β”€ mock-llm.ts             ← Mock OpenAI-compatible server
β”‚   β”œβ”€β”€ smoke-test.ts           ← Quick environment check
β”‚   └── maintenance.ts          ← Daily cleanup script
β”‚
β”œβ”€β”€ state/                      ← Runtime state (committed to git)
β”‚   β”œβ”€β”€ README.md               ← Explains each file
β”‚   β”œβ”€β”€ memory.md               ← Append-only fact log
β”‚   β”œβ”€β”€ personality.md          ← Mutable agent identity
β”‚   β”œβ”€β”€ user.md                 ← User profile
β”‚   β”œβ”€β”€ issues/                 ← Issue β†’ session mappings
β”‚   └── sessions/               ← Conversation transcripts (JSONL)
β”‚
β”œβ”€β”€ docs/                       ← Extended documentation
β”‚   β”œβ”€β”€ CONFIGURATION.md
β”‚   β”œβ”€β”€ PROVIDERS.md
β”‚   β”œβ”€β”€ ARCHITECTURE.md
β”‚   β”œβ”€β”€ DEPLOYMENT.md
β”‚   └── TROUBLESHOOTING.md
β”‚
β”œβ”€β”€ AGENTS.md                   ← Agent operating instructions
β”œβ”€β”€ CHANGELOG.md                ← Semantic versioning history
β”œβ”€β”€ issueclaw.config.json         ← Main config (Gemini default)
β”œβ”€β”€ Dockerfile                  ← Container image
β”œβ”€β”€ docker-compose.yml          ← Local dev environment
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json               ← TypeScript strict mode
β”œβ”€β”€ biome.json                  ← Linter/formatter config
└── vitest.config.ts            ← Test config

πŸ”§ Configuration (Complete Reference)

IssueClaw is configured via issueclaw.config.json. The config is auto-generated on first run if it doesn't exist β€” it detects which API keys you have and builds the right config.

Auto-Config (Recommended)

# Locally:
bun run src/cli.ts config auto

# Or just run the agent β€” config is auto-generated on first run

This detects GEMINI_API_KEY, CEREBRAS_API_KEY, OPENROUTER_API_KEY, GROQ_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY in your environment and builds a config with the right providers + fallback chain. Priority: Gemini (1M TPM) β†’ Cerebras β†’ OpenRouter β†’ Groq β†’ Anthropic β†’ OpenAI.

Config Sources

Configuration is loaded from (in priority order):

  1. Environment variables (ISSUECLAW_*) β€” highest priority
  2. Config file (issueclaw.config.json or ISSUECLAW_CONFIG_PATH)
  3. Legacy (.pi/settings.json) β€” backward compatibility with original issueclaw
  4. Auto-generated (on first run if no config exists)
  5. Built-in defaults

Full Schema

{
  "version": 1,
  "providers": [
    {
      "type": "anthropic" | "openai" | "openrouter" | "ollama" | "groq" | "gemini" | "cerebras" | "custom",
      "model": "string",
      "apiKey": "string or ${ENV_VAR}",
      "baseUrl": "https://...",
      "headers": { "X-Custom": "value" },
      "thinking": "off|minimal|low|medium|high|xhigh",
      "maxTokens": 8192,
      "temperature": 0.7,
      "default": true
    }
  ],
  "memory": {
    "stateDir": "./state",
    "memoryFile": "memory.md",
    "personalityFile": "personality.md",
    "userFile": "user.md",
    "auditFile": "audit.log",
    "maxSessionSize": 10485760,
    "autoCompact": true
  },
  "github": {
    "repo": "owner/name",
    "onIssueOpened": true,
    "onIssueComment": true,
    "onPullRequest": false,
    "allowedAssociations": ["OWNER", "MEMBER", "COLLABORATOR"],
    "hatchLabel": "hatch",
    "reactionWhileProcessing": true,
    "maxCommentLength": 60000,
    "concurrencyGroup": "issueclaw-agent"
  },
  "agent": {
    "tools": ["read", "bash", "edit", "write", "grep", "glob", "ls"],
    "excludeTools": [],
    "systemPrompt": "optional override",
    "appendSystemPrompt": ".pi/APPEND_SYSTEM.md",
    "agentsFile": "AGENTS.md",
    "piCommand": "bunx pi",
    "timeoutMs": 900000,
    "skills": true,
    "extensions": true
  },
  "runtime": {
    "dryRun": false,
    "logLevel": "info",
    "logJson": false,
    "offline": false
  }
}

Environment Variables

Variable Description
ISSUECLAW_PROVIDER Override provider type (gemini/cerebras/groq/...)
ISSUECLAW_MODEL Override model
ISSUECLAW_BASE_URL Override base URL (for custom providers)
ISSUECLAW_THINKING Override thinking level (off/minimal/low/medium/high/xhigh)
ISSUECLAW_LOG_LEVEL Log level: trace/debug/info/warn/error/fatal
ISSUECLAW_LOG_JSON true for JSON log output (log aggregation)
ISSUECLAW_DRY_RUN true to skip commits and comments
ISSUECLAW_CONFIG_PATH Custom config file path
GEMINI_API_KEY Google Gemini API key
CEREBRAS_API_KEY Cerebras API key
OPENROUTER_API_KEY OpenRouter API key
GROQ_API_KEY Groq API key
ANTHROPIC_API_KEY Anthropic API key
OPENAI_API_KEY OpenAI API key

Examples

Gemini (recommended β€” free tier)

{
  "version": 1,
  "providers": [
    {
      "type": "gemini",
      "model": "gemini-2.0-flash",
      "apiKey": "${GEMINI_API_KEY}",
      "default": true
    }
  ]
}

Get a free API key at https://aistudio.google.com/app/apikey.

Multi-provider with fallback

{
  "version": 1,
  "providers": [
    { "type": "gemini", "model": "gemini-2.0-flash", "apiKey": "${GEMINI_API_KEY}", "default": true },
    { "type": "cerebras", "model": "llama-3.3-70b", "apiKey": "${CEREBRAS_API_KEY}" },
    { "type": "openrouter", "model": "nvidia/nemotron-3-nano-30b-a3b:free", "apiKey": "${OPENROUTER_API_KEY}" },
    { "type": "groq", "model": "llama-3.3-70b-versatile", "apiKey": "${GROQ_API_KEY}" }
  ]
}

Local Ollama

{
  "version": 1,
  "providers": [
    {
      "type": "ollama",
      "model": "llama3.1:70b",
      "baseUrl": "http://localhost:11434",
      "default": true
    }
  ]
}

Custom OpenAI-compatible (Azure, Together, Groq, vLLM)

{
  "version": 1,
  "providers": [
    {
      "type": "custom",
      "model": "my-model",
      "baseUrl": "https://api.together.xyz/v1",
      "apiKey": "${TOGETHER_API_KEY}",
      "headers": { "X-Custom-Header": "value" },
      "default": true
    }
  ]
}

πŸ“– Full config guide: see docs/CONFIGURATION.md


πŸ€– Providers (Complete Guide)

IssueClaw supports 8 provider types out of the box. Gemini is the recommended default because it has 1M TPM free tier (83x higher than Groq).

Provider Comparison Table

Provider Type API Key Env Free Tier? TPM Limit Context Window Notes
πŸ”΅ Gemini gemini GEMINI_API_KEY βœ… Yes 1,000,000 1,048,576 RECOMMENDED β€” best for AI agents
⚑ Cerebras cerebras CEREBRAS_API_KEY βœ… Yes 60,000 131,072 Ultra-fast (1000+ tok/s)
πŸ”΅ OpenRouter openrouter OPENROUTER_API_KEY βœ… Free models varies varies Access to hundreds of models
⚑ Groq groq GROQ_API_KEY βœ… Yes 12,000 131,072 Low TPM β€” last resort
🟣 Anthropic anthropic ANTHROPIC_API_KEY ❌ β€” 200,000 Claude Opus 4, Sonnet 4.5
🟒 OpenAI openai OPENAI_API_KEY ❌ β€” 128,000 GPT-4o, o1, o3
πŸ¦™ Ollama ollama (none) βœ… Self-hosted β€” varies Local LLMs
πŸ”§ Custom custom OPENAI_API_KEY varies β€” varies Any OpenAI-compatible endpoint

Google Gemini (Recommended)

Get a free key: https://aistudio.google.com/app/apikey

Free tier limits (as of 2026):

  • Gemini 2.0 Flash: 15 RPM, 1,000,000 TPM, 1,500 requests/day
  • Gemini 2.5 Flash: 10 RPM, 1,000,000 TPM, 500 requests/day
  • Gemini 1.5 Flash: 15 RPM, 1,000,000 TPM, 1,500 requests/day

The 1,000,000 TPM is what makes Gemini ideal for AI agents. Pi's system prompt + tool definitions = ~120K tokens, which Groq's 12K TPM literally cannot handle. Gemini handles it with room to spare.

Available models:

  • gemini-2.0-flash (default β€” fast, capable)
  • gemini-2.5-flash (better reasoning)
  • gemini-2.0-flash-lite (faster, cheaper)
  • gemini-1.5-flash
  • gemini-1.5-pro
  • gemini-2.5-pro

Config:

{
  "type": "gemini",
  "model": "gemini-2.0-flash",
  "apiKey": "${GEMINI_API_KEY}",
  "default": true
}

Pi has native Gemini support β€” uses --provider google which reads GEMINI_API_KEY automatically.

Cerebras

Get a free key: https://inference.cerebras.ai/

Free tier limits: ~30 RPM, 60,000 TPM

Cerebras uses custom LPU hardware for ultra-fast inference (1000+ tokens/sec). Good fallback when Gemini is unavailable.

Available models:

  • llama-3.3-70b
  • llama-3.1-8b
  • gpt-oss-120b
  • zai-glm-4.7

Config:

{
  "type": "cerebras",
  "model": "llama-3.3-70b",
  "apiKey": "${CEREBRAS_API_KEY}"
}

OpenRouter

Get a free key: https://openrouter.ai/keys

OpenRouter routes to hundreds of models from many providers. Many models have free tiers.

Recommended free models:

  • nvidia/nemotron-3-nano-30b-a3b:free (reliably available)
  • meta-llama/llama-3.3-70b-instruct:free (sometimes rate-limited)
  • google/gemma-4-26b-a4b-it:free

Config:

{
  "type": "openrouter",
  "model": "nvidia/nemotron-3-nano-30b-a3b:free",
  "apiKey": "${OPENROUTER_API_KEY}"
}

Groq

Get a free key: https://console.groq.com/keys

Free tier limits: 30 RPM, 12,000 TPM, 14,400 requests/day

⚠️ Warning: Groq's 12K TPM is too low for full agent mode (which needs ~120K tokens per message). Use Groq only as a last-resort fallback, or use it with simple chat mode.

Available models:

  • llama-3.3-70b-versatile
  • llama-3.1-8b-instant
  • mixtral-8x7b-32768
  • gemma2-9b-it

Config:

{
  "type": "groq",
  "model": "llama-3.3-70b-versatile",
  "apiKey": "${GROQ_API_KEY}"
}

Anthropic

Get a key: https://console.anthropic.com/ (paid)

Models:

  • claude-opus-4-6 (most capable)
  • claude-sonnet-4-5
  • claude-haiku-4-5 (fastest)

Config:

{
  "type": "anthropic",
  "model": "claude-opus-4-6",
  "apiKey": "${ANTHROPIC_API_KEY}",
  "thinking": "high"
}

OpenAI

Get a key: https://platform.openai.com/api-keys (paid)

Models:

  • gpt-4o
  • gpt-4o-mini
  • o1
  • o3

Config:

{
  "type": "openai",
  "model": "gpt-4o",
  "apiKey": "${OPENAI_API_KEY}"
}

Ollama (Local)

Install Ollama: https://ollama.ai/

Models:

  • llama3.1:70b
  • qwen2.5:32b
  • deepseek-r1:32b

Config:

{
  "type": "ollama",
  "model": "llama3.1:70b",
  "baseUrl": "http://localhost:11434"
}

No API key required β€” runs locally on your machine.

Custom (Any OpenAI-Compatible)

Any OpenAI-compatible API works via the custom provider type:

Together AI:

{
  "type": "custom",
  "model": "meta-llama/Llama-3.3-70B-Instruct-Turbo",
  "baseUrl": "https://api.together.xyz/v1",
  "apiKey": "${TOGETHER_API_KEY}"
}

Azure OpenAI:

{
  "type": "custom",
  "model": "gpt-4o",
  "baseUrl": "https://your-resource.openai.azure.com/openai/deployments/your-deployment",
  "apiKey": "${AZURE_OPENAI_API_KEY}",
  "headers": { "api-key": "${AZURE_OPENAI_API_KEY}" }
}

vLLM (local):

{
  "type": "custom",
  "model": "meta-llama/Meta-Llama-3.1-70B",
  "baseUrl": "http://localhost:8000/v1",
  "apiKey": "dummy"
}

LM Studio:

{
  "type": "custom",
  "model": "local-model",
  "baseUrl": "http://localhost:1234/v1",
  "apiKey": "lm-studio"
}

Provider Fallback Chain

Providers are tried in order. The first one marked default: true is the primary; others are fallbacks.

{
  "providers": [
    { "type": "gemini", "model": "gemini-2.0-flash", "apiKey": "${GEMINI_API_KEY}", "default": true },
    { "type": "cerebras", "model": "llama-3.3-70b", "apiKey": "${CEREBRAS_API_KEY}" },
    { "type": "openrouter", "model": "nvidia/nemotron-3-nano-30b-a3b:free", "apiKey": "${OPENROUTER_API_KEY}" }
  ]
}

If Gemini fails β†’ tries Cerebras β†’ tries OpenRouter. The error message shows all provider attempts with their status.

Adding Custom Providers

You can register custom providers at runtime via pi extensions:

// .pi/extensions/my-provider.ts
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

export default function (pi: ExtensionAPI) {
  pi.registerProvider("my-provider", {
    name: "My Provider",
    baseUrl: "https://api.example.com",
    apiKey: "$MY_API_KEY",
    api: "openai-completions",
    models: [
      {
        id: "my-model",
        name: "My Model",
        reasoning: false,
        input: ["text"],
        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
        contextWindow: 128000,
        maxTokens: 4096,
      },
    ],
  });
}

πŸ“– Full provider guide: see docs/PROVIDERS.md


πŸ’Ύ State & Persistence

Yes β€” the GitHub repo itself is the database. Everything the agent learns, creates, or modifies is committed to git. There is no external database, no S3 bucket, no Redis cache. Just your repo.

What Gets Saved

state/
β”œβ”€β”€ memory.md           ← πŸ“ Append-only memory log
β”œβ”€β”€ personality.md      ← 🎭 Mutable agent identity
β”œβ”€β”€ user.md             ← πŸ‘€ User profile
β”œβ”€β”€ audit.log           ← πŸ“‹ JSON audit trail (one line per agent action)
β”œβ”€β”€ issues/
β”‚   β”œβ”€β”€ 1.json          ← Maps issue #1 β†’ its session file
β”‚   β”œβ”€β”€ 2.json          ← Maps issue #2 β†’ its session file
β”‚   └── ...
└── sessions/
    β”œβ”€β”€ 2026-07-07T10-30-00_abc123.jsonl   ← Full conversation for issue #1
    β”œβ”€β”€ 2026-07-07T11-15-00_def456.jsonl   ← Full conversation for issue #2
    └── ...

File Reference

File Purpose Mutability Who writes it
memory.md Durable facts, preferences, decisions Append-only Agent (via tools) + you (manual edits)
personality.md Agent name, vibe, emoji, hatch date Mutable Agent (during hatch flow + refinements)
user.md Your name, preferences, communication style Mutable Agent (when it learns about you)
audit.log Every agent run as JSON Append-only Lifecycle (automatic)
issues/N.json Issue β†’ session file mapping Managed Lifecycle (automatic)
sessions/*.jsonl Full conversation transcripts Append-only Pi (automatic)

How Memory Works

At the start of every session (agent mode), the agent's prompt is built from:

  1. state/personality.md β€” who the agent is (name, vibe, emoji)
  2. state/user.md β€” what the agent knows about you
  3. Last 20 lines of state/memory.md β€” recent durable facts (skips default/uninitialized content)
  4. The issue title + body (or comment body) β€” what you're asking now (template boilerplate stripped)
  5. Operating instructions β€” read AGENTS.md, update files, etc.
  6. Hatch trigger (if hatch label present) β€” read BOOTSTRAP.md

The agent can also search its own history using bash tools:

# Inside an issue, the agent can run:
rg -i "search term" state/memory.md          # Search memory log
rg -i "search term" state/sessions/          # Search all past conversations
tail -30 state/memory.md                     # Recent memories

Token budget management: If the prompt exceeds 6,000 tokens, the system progressively strips context:

  1. Drop "Recent Memory" section
  2. Drop "About Your Human" section
  3. Truncate the user message itself

This ensures the prompt always fits within Groq's free-tier limits.

Session Tracking

How it tracks conversations per issue:

When you open issue #5:

  1. The lifecycle checks state/issues/5.json for an existing mapping
  2. If not found, creates a new session file: state/sessions/2026-07-07T10-30-00_abc123.jsonl
  3. Saves the mapping: state/issues/5.json β†’ { "issueNumber": 5, "sessionPath": "state/sessions/...jsonl", "turnCount": 1 }
  4. Commits everything to git

When you comment on issue #5 again:

  1. The lifecycle reads state/issues/5.json β†’ finds the session path
  2. Passes --session state/sessions/...jsonl to pi
  3. Pi loads the full prior conversation from the JSONL file
  4. The agent resumes with complete context of everything said before
  5. Updates the mapping with turnCount: 2 and new updatedAt timestamp
  6. Commits to git

This means: you can have a long-running conversation across many comments on the same issue, and the agent remembers every word.

Simple chat mode (with chat label) does NOT create session files β€” it's stateless by design to save tokens. Each chat comment is independent.

Atomic Writes

All file writes use atomic write (write to a .tmp file, then rename). This prevents:

  • Partial writes from being observed by concurrent readers
  • Race conditions between concurrent git operations
  • Corruption from killed processes (e.g., workflow timeout)

Backup & Restore

Since everything is in git, backup is trivial:

# Backup
git tag backup-$(date +%Y%m%d)
git push origin backup-$(date +%Y%m%d)

# Or just clone the repo β€” that IS your backup
git clone https://github.com/maruf009sultan/issueclaw.git backup

# Restore state to a previous point
git checkout backup-20260101 -- state/
git commit -m "restore state to 2026-01-01"
git push

πŸ” Security Model

Who Can Trigger the Agent?

Only users with OWNER, MEMBER, or COLLABORATOR association on the repo can trigger the agent. This is enforced in two places:

  1. Workflow if: condition (in .github/workflows/agent.yml):

    if: contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'),
                  github.event.issue.author_association)
  2. shouldProcessEvent() in code (src/github/events.ts)

Random internet users cannot trigger the agent on public repos.

Bot Rejection

github-actions[bot], dependabot[bot], and other bots are rejected to prevent infinite loops (agent comments on its own issue β†’ triggers itself β†’ ...).

Permissions

The workflow requests the minimum permissions needed:

permissions:
  contents: write        # Commit & push state
  issues: write          # Comment, react, close
  actions: write         # Read workflow info
  pull-requests: write   # If PR support enabled

Network Egress

The agent only makes outbound network calls to:

  • Your git remote (github.com) β€” for push/pull
  • Your LLM provider (api.groq.com, api.anthropic.com, etc.) β€” for inference

No other network egress by default.

Private Repos

For anything sensitive, make the repo private. The workflow uses GITHUB_TOKEN which works for private repos with no extra setup. Note: GitHub Actions has limited free minutes for private repos (2,000/month on free tier). Public repos have unlimited minutes.

Secret Handling

API keys are stored as GitHub secrets and injected as env vars only during the workflow run. They are never logged (the logger redacts anything matching apiKey/secret/token patterns). The agent never sees the raw key β€” pi reads it from process.env directly.


πŸ› οΈ CLI Reference

IssueClaw ships with a full CLI for local testing and management.

Commands

# Diagnose environment & config
bun run src/cli.ts doctor

# Run the agent lifecycle (needs GITHUB_EVENT_PATH set)
bun run src/cli.ts run
bun run src/cli.ts run --dry-run        # Don't commit/comment
bun run src/cli.ts run --offline         # Mock pi invocation
bun run src/cli.ts run --event <path>    # Custom event payload

# Config management
bun run src/cli.ts config show           # Print current config
bun run src/cli.ts config validate       # Validate config
bun run src/cli.ts config auto           # Auto-generate config from env

# Memory management
bun run src/cli.ts memory show           # Show memory log
bun run src/cli.ts memory search <query> # Search memory
bun run src/cli.ts memory append <text>  # Append to memory
bun run src/cli.ts memory clear          # Clear memory

# Personality management
bun run src/cli.ts personality show      # Show personality
bun run src/cli.ts personality set <f>   # Set from file
bun run src/cli.ts personality reset     # Reset to default

# User profile management
bun run src/cli.ts user show             # Show user profile
bun run src/cli.ts user set <file>       # Set from file

# Testing utilities
bun run src/cli.ts test event <type>     # Generate test event payload
bun run src/cli.ts test lifecycle        # Run lifecycle against test event
bun run src/cli.ts test prompt           # Show prompt that would be sent

# Full live test (uses mock LLM, no API key needed)
bun run scripts/live-test.ts

The doctor Command

Run this first to diagnose any issues:

πŸ” IssueClaw Doctor

βœ“ Configuration loaded
πŸ“‹ Providers (4):
  βœ“ gemini/gemini-2.0-flash (default)
  ⚠️ cerebras/llama-3.3-70b: requires CEREBRAS_API_KEY
  βœ“ openrouter/nvidia/nemotron-3-nano-30b-a3b:free
  βœ“ groq/llama-3.3-70b-versatile
πŸ’Ύ State directory: ./state
  βœ“ memory.md
  βœ“ personality.md
  βœ“ user.md
πŸ›   Environment:
  βœ“ GITHUB_TOKEN
  βœ— GITHUB_EVENT_PATH (set by Actions)
πŸ₯Ÿ Bun: 1.3.14
🌿 Git: 2.47.3
πŸ™ GitHub CLI: 2.40.1
πŸ€– Pi: 0.80.3

πŸ§ͺ Testing

IssueClaw has 122 tests across three layers:

Layer Count What it tests
Unit tests 99 Individual modules (config, providers, memory, github, agent, simple-chat, utils)
Integration tests 4 Full lifecycle with mocked pi
Live tests 29 End-to-end pipeline with real pi + mock LLM server

Running Tests

# Unit + integration tests (fast, ~2 seconds)
bun run test

# With coverage
bun run test:coverage

# Live test (slow, ~30 seconds, uses mock LLM server)
bun run scripts/live-test.ts

# Watch mode
bun run test:watch

The Live Test Harness

The live test (scripts/live-test.ts) is the gold standard β€” it:

  1. Starts a mock LLM server (OpenAI-compatible) on localhost
  2. Creates a temp git repo with the project files
  3. Generates a fake GitHub event (issue opened)
  4. Runs the actual main.ts lifecycle (no mocks of our code)
  5. Runs the actual pi binary (no mocks of pi)
  6. Pi makes real HTTP calls to the mock LLM server
  7. Verifies:
    • All state files created (memory.md, personality.md, user.md, audit.log)
    • Session JSONL created with real conversation
    • Issue mapping saved
    • Audit log has agent_run_start + agent_run_end entries
    • Mock LLM received proper requests (correct model, correct message format)
    • All CLI commands work (config show, memory show, doctor, etc.)
  8. Tests hatch label event
  9. Cleans up

CI Workflow

Every push and PR triggers .github/workflows/ci.yml which runs:

  • bun x tsc --noEmit (TypeScript strict mode, no errors)
  • bun x biome check src tests scripts (linting)
  • bun run test (99 unit + 4 integration tests)

🐳 Docker

For local development parity with CI:

# Build
docker compose build

# Diagnose
docker compose run --rm issueclaw doctor

# Run with env vars
docker compose run --rm \
  -e GITHUB_TOKEN=ghp_xxx \
  -e GEMINI_API_KEY=AIza_xxx \
  issueclaw run --dry-run

The Dockerfile uses oven/bun:1.1-debian and installs git, gh, curl, jq, ripgrep.


πŸ“ˆ Monitoring & Observability

Audit Log

Every agent run is logged as JSON to state/audit.log:

# Recent activity
tail -5 state/audit.log | jq .

# All errors
jq 'select(.details.success == false)' state/audit.log

# Runs per issue
jq -s 'group_by(.details.issue) | map({issue: .[0].details.issue, count: length})' state/audit.log

# Simple chat vs agent mode
jq 'select(.action == "simple_chat_complete" or .action == "agent_run_complete")' state/audit.log

Structured Logging

Set ISSUECLAW_LOG_JSON=true for JSON log output (compatible with Datadog, Splunk, Loki, etc.):

{"ts":"2026-07-07T10:30:00.000Z","level":"info","component":"issueclaw","msg":"agent run succeeded","provider":"gemini/gemini-2.0-flash","durationMs":45230}

Or use colorized human-readable output (default in TTY):

[2026-07-07T10:30:00.000Z] INFO  [issueclaw] agent run succeeded {"provider":"gemini/gemini-2.0-flash","durationMs":45230}

GitHub Actions Artifacts

Every run uploads state/ and /tmp/agent-raw-*.jsonl as an artifact, retained for 30 days. Download from the Actions tab β†’ click a run β†’ scroll to "Artifacts".

Scheduled Maintenance

A daily workflow (.github/workflows/scheduled.yml) runs scripts/maintenance.ts which:

  • Cleans up orphaned session files (sessions with no issue mapping)
  • Flags oversized sessions (>10MB, candidates for compaction)
  • Reports stats to state/audit.log

❓ Frequently Asked Questions

Q: Is the codebase production-ready?

A: Yes. Here's the evidence:

  • βœ… 122 tests all passing (99 unit + 4 integration + 29 live)
  • βœ… TypeScript strict mode with clean typecheck
  • βœ… Structured error handling β€” every operation has try/catch with logging
  • βœ… Retry logic β€” network operations retry with exponential backoff
  • βœ… Provider fallback β€” if Gemini fails, automatically tries Cerebras, then OpenRouter, etc.
  • βœ… Concurrency control β€” race-condition safe via GitHub concurrency groups
  • βœ… Atomic file writes β€” no corruption from concurrent access
  • βœ… Audit trail β€” every agent action logged as JSON
  • βœ… Permission checks β€” only authorized users can trigger
  • βœ… Timeouts β€” 30-min job + 15-min agent, no runaway runs
  • βœ… Session artifacts β€” uploaded for debugging, 30-day retention
  • βœ… Comprehensive docs β€” 5 doc files + this README
  • βœ… Docker support β€” local dev parity with CI
  • βœ… Live-tested β€” the full pipeline was verified end-to-end with a mock LLM

Q: Will it work entirely from GitHub, via issues?

A: Yes. The entire user-facing flow is GitHub Issues:

  1. Open an issue β†’ agent processes β†’ replies as comment
  2. Comment on the issue β†’ agent resumes with full prior context β†’ replies
  3. Close the issue β†’ agent stops responding to it

There is no web UI, no CLI for end users, no Slack integration. Just GitHub Issues. This is by design β€” it keeps the system dead simple and uses infrastructure you already have.

Q: Will it use the GitHub repo itself as storage?

A: Yes, 100%. The repo IS the database. Everything is committed to git:

  • state/memory.md β€” agent's memory log
  • state/personality.md β€” agent's identity
  • state/user.md β€” your profile
  • state/audit.log β€” audit trail
  • state/issues/N.json β€” issue β†’ session mappings
  • state/sessions/*.jsonl β€” full conversation transcripts
  • Any files the agent creates/edits in your repo (code, docs, configs)

There is no external database (no Postgres, no Redis, no S3). If you git clone the repo, you have a complete backup of everything.

Q: How does session tracking work?

A: Each issue gets a mapping file at state/issues/<N>.json that points to a session JSONL file. When you comment on an existing issue, the lifecycle:

  1. Reads the mapping to find the session file path
  2. Passes --session <path> to pi
  3. Pi loads the full prior conversation from the JSONL
  4. The agent resumes with complete context

This means you can have long-running conversations across many comments on the same issue. The agent remembers every word.

Simple chat mode (with chat label) does NOT use session files β€” it's stateless to save tokens.

Q: Can I just chat without using the full agent?

A: Yes! Open an issue with the chat label (or use the "πŸ’¬ Chat" issue template). The agent will respond directly without using tools β€” perfect for quick questions.

This uses ~500 tokens per message (vs ~120,000 for full agent mode), saving 99.6% of your API quota.

Q: What if I don't want to pay for an LLM?

A: Use Gemini. It has a generous free tier (1M TPM, 1,500 requests/day) and the default config uses it. Combined with GitHub Actions being free for public repos, you can run this entire system for $0/month.

Q: Can multiple people use the same agent?

A: Yes, but only OWNER/MEMBER/COLLABORATOR can trigger it. Add them as collaborators in repo settings. Each person's comments on an issue share the same session context.

Q: Can I run the agent locally?

A: Yes. The CLI supports local testing:

bun run src/cli.ts test event issues.opened   # Generate test event
bun run src/cli.ts test lifecycle              # Run lifecycle (mock pi)
bun run scripts/live-test.ts                   # Full live test (mock LLM)

Q: How do I reset the agent's memory?

A: Three options:

# Nuclear: delete all state
rm -rf state/
bun run src/cli.ts doctor    # Reinitializes defaults

# Selective: clear just memory.md
bun run src/cli.ts memory clear

# Surgical: edit files directly
$EDITOR state/memory.md
$EDITOR state/personality.md
git add state/ && git commit -m "reset memory" && git push

Q: Can I change the agent's personality?

A: Yes. Open an issue with the hatch label to bootstrap a new identity, or edit state/personality.md directly:

bun run src/cli.ts personality show
$EDITOR state/personality.md
git commit -am "update personality" && git push

Q: What happens if the agent fails?

A: The agent:

  1. Tries the next provider in the fallback chain (Gemini β†’ Cerebras β†’ OpenRouter β†’ ...)
  2. If all providers fail, posts a detailed error comment with:
    • All provider attempts and their errors
    • Which providers had keys set
    • Specific troubleshooting hints based on error type
    • Collapsible diagnostics section
  3. The error is logged to state/audit.log and the workflow's stderr
  4. The πŸ‘€ reaction is still removed (in the finally block)
  5. Session artifacts are still uploaded for debugging

Q: How long are sessions kept?

A: Forever β€” they're in git. The daily maintenance script flags sessions >10MB for compaction, but doesn't delete them. GitHub Actions artifacts (the uploaded state/ zip) are retained for 30 days.

Q: Does it support pull requests?

A: Yes. The workflow triggers on pull_request: opened events too. You can ask the agent to review PRs, suggest changes, etc. (disabled by default in config β€” set onPullRequest: true to enable).

Q: Can I use this for a team?

A: Yes, but consider:

  • All collaborators see all conversation history (it's in git)
  • Concurrency is per-issue (not per-user) β€” multiple people commenting on the same issue are serialized
  • For sensitive data, make the repo private

🩺 Troubleshooting

Agent doesn't respond to issues

  1. Check the Actions tab β€” did the workflow run?
  2. Check the workflow's if: condition β€” are you OWNER/MEMBER/COLLABORATOR?
  3. Run bun run src/cli.ts doctor locally
  4. Verify GEMINI_API_KEY (or other provider key) is set in secrets

Agent responds with error

  1. Read the error comment β€” it now shows all provider attempts
  2. Check state/audit.log for recent errors: tail -5 state/audit.log | jq .
  3. Look at workflow logs in Actions tab
  4. Run bun run src/cli.ts doctor to verify config

"Provider X invalid: requires API_KEY"

This means that provider is in your config but the matching secret isn't set. The error comment will show you:

  • Which providers were tried
  • Which had keys (βœ“) and which didn't (βœ—)
  • Exactly which secret name to set

Fix: Go to Settings β†’ Secrets β†’ add the missing PROVIDER_API_KEY secret.

413 / TPM error (token limit exceeded)

This happens when using Groq (12K TPM) for full agent mode (needs ~120K tokens).

Fix:

  1. Switch to Gemini (1M TPM) β€” set GEMINI_API_KEY and make it default
  2. Or use simple chat mode (chat label) β€” only ~500 tokens per message

429 / rate limit error

Fix:

  1. Wait a minute and retry
  2. Add more fallback providers
  3. Check your provider's quota dashboard

Git push fails

  • The workflow auto-rebases and retries 3 times
  • If still failing, check for branch protection rules that block issueclaw[bot]
  • Manual fix: git pull --rebase origin main && git push

Comment is truncated

  • Responses >60,000 chars are truncated with a notice
  • Full response is in the session JSONL (uploaded as artifact)
  • Increase maxCommentLength in config (max 65,536 β€” GitHub's limit)

πŸ“– Full troubleshooting guide: see docs/TROUBLESHOOTING.md


πŸ“š Documentation

Doc What's inside
docs/CONFIGURATION.md Full config schema, all options, examples for every provider
docs/PROVIDERS.md Provider guide, fallback chains, custom endpoints
docs/ARCHITECTURE.md Component breakdown, data flow, security model
docs/DEPLOYMENT.md Production checklist, upgrading, rollback, monitoring
docs/TROUBLESHOOTING.md Common issues, debug mode, FAQ

πŸ”„ Changelog

See CHANGELOG.md for the full version history.

Recent versions:

  • v1.6.0 β€” Added simple chat mode (saves 99% of API tokens)
  • v1.5.0 β€” Fixed error reporting (shows ALL provider failures)
  • v1.4.0 β€” Added Gemini (1M TPM) and Cerebras providers
  • v1.3.0 β€” Fixed prompt size (token budget management)
  • v1.2.0 β€” Fixed critical bug (prompt was posted as response)
  • v1.1.0 β€” Added Groq support, auto-config, live testing
  • v1.0.0 β€” Enterprise upgrade of original issueclaw

πŸ›£οΈ Roadmap

  • Streaming responses β€” post comments incrementally as the agent generates
  • Web UI β€” optional web dashboard for viewing sessions
  • Slack/Discord integration β€” trigger agent from chat
  • Multi-repo support β€” one agent managing multiple repos
  • Fine-tuned personalities β€” per-issue-type personalities
  • MCP (Model Context Protocol) support β€” connect to external tools
  • Compaction β€” auto-summarize long sessions to save tokens

❀️ Acknowledgments

This project stands on the shoulders of giants:

Original issueclaw

  • Sawyer Hood β€” created the original issueclaw, the brilliant idea of an agent that lives in GitHub Issues. Without Sawyer's creativity, this project wouldn't exist.

pi-mono (the agent engine)

  • Mario Zechner β€” created pi-mono, the production-grade coding agent CLI (v0.80.3) that powers the agent mode. Pi provides tool use, session management, multi-provider support, and the entire agent loop. Mario's work is the foundation of the agent capabilities.

Free LLM providers

  • Google Gemini β€” for the generous 1M TPM free tier that makes this $0 to run
  • Cerebras β€” for ultra-fast free inference
  • OpenRouter β€” for free model access
  • Groq β€” for fast free inference (lower limits but still useful)

Infrastructure

  • GitHub Actions β€” for the free CI/CD that hosts the agent
  • Bun β€” for the blazing-fast JavaScript runtime
  • Biome β€” for the fast linter/formatter
  • Vitest β€” for the testing framework
  • Zod β€” for runtime schema validation

Inspiration

  • OpenClaw β€” inspired the concept
  • The open-source community β€” for feedback, bug reports, and feature requests

πŸ“„ License

MIT β€” see LICENSE


πŸ“Š Project Statistics

Metric Value
Version 1.6.0
Tests 122 passing (99 unit + 4 integration + 29 live)
Providers 8 (Gemini, Cerebras, OpenRouter, Groq, Anthropic, OpenAI, Ollama, Custom)
Lines of code ~3,500 (src) + ~1,200 (tests)
Documentation 5 doc files + 1,500-line README
Languages TypeScript (100%)
Runtime Bun 1.1+
Node.js 20+ (for pi compatibility)
License MIT
Cost to run $0/month (with Gemini free tier)

🌟 Star this repo if it helps you! 🌟

⬆ Back to top

Made with πŸ¦ƒ by the IssueClaw community

Report a bug Β· Request a feature Β· Read the docs Β· View changelog


🎯 Use Cases

Personal AI Assistant

Keep a personal AI assistant in your repo that remembers your preferences, projects, and context across sessions. Open issues for tasks, chat for quick questions.

Issue #1: "Remember that I prefer TypeScript over JavaScript"
Issue #2 (chat): "What's the syntax for a TypeScript generic constraint?"
Issue #3: "Create a new React component for a login form"

The agent remembers your TypeScript preference across all issues.

Code Documentation Generator

Issue: "Document all the functions in src/utils.ts"
β†’ Agent reads the file, generates JSDoc comments, commits the changes

Bug Fixer

Issue: "Fix the bug where the login button doesn't work on Safari"
β†’ Agent reads the code, identifies the issue, fixes it, commits

Code Reviewer

Issue: "Review PR #42 and suggest improvements"
β†’ Agent reads the PR diff, posts a review comment

Learning Companion

Issue (chat): "Explain how promises work in JavaScript"
β†’ Agent responds with a detailed explanation (only ~500 tokens)

Project Bootstrapper

Issue: "Set up a new Next.js project with Tailwind CSS in the frontend/ directory"
β†’ Agent creates the project structure, configures Tailwind, commits everything

DevOps Assistant

Issue: "Create a GitHub Actions workflow that runs tests on every PR"
β†’ Agent creates .github/workflows/test.yml, commits it

Content Writer

Issue: "Write a blog post about why we chose Bun over Node.js"
β†’ Agent researches (reads your repo), writes the post, saves it to blog/bun-vs-node.md

πŸ† Why IssueClaw?

vs. ChatGPT Plus ($20/month)

Feature ChatGPT Plus IssueClaw
Cost $20/month $0/month
Code editing Manual copy-paste Direct git commits
Memory Session-only Permanent (in git)
Custom personality No Yes (personality.md)
Self-hosted No Yes (your GitHub repo)
Privacy OpenAI sees your data Only your repo

vs. GitHub Copilot ($10/month)

Feature Copilot IssueClaw
Cost $10/month $0/month
Interaction IDE only GitHub Issues
Memory None Permanent
Multi-provider No (OpenAI only) Yes (8 providers)
Personality No Yes

vs. Self-hosted LLM (Ollama + Open WebUI)

Feature Self-hosted LLM IssueClaw
Setup complexity High (Docker, GPU, config) Low (fork + 1 secret)
Hardware needed GPU recommended None (uses cloud APIs)
Memory Manual Automatic (git-backed)
Access Web UI GitHub Issues (anywhere)
Multi-provider Manual config Automatic fallback chain

vs. Original issueclaw

Feature Original issueclaw IssueClaw
Providers Anthropic only 8 providers
Config Hardcoded Zod-validated, auto-generated
Tests None 122 tests
Error handling Minimal Comprehensive with diagnostics
Token management None Budget enforcement + template stripping
Simple chat No Yes (saves 99% of tokens)
CLI No Full CLI (doctor, config, memory, etc.)
Docker No Yes
Docs Minimal 5 doc files + 1800-line README
Live testing No 29 end-to-end tests

πŸ”§ Advanced Configuration

Custom Issue Templates

You can create custom issue templates that trigger specific behaviors:

---
name: "πŸ”¬ Research"
about: "Ask the agent to research a topic"
labels: ["chat", "research"]
---

Research topic:
[What do you want to know about?]

The chat label triggers simple chat mode. The research label is just for organization.

Environment-Specific Configs

Use ISSUECLAW_CONFIG_PATH to use different configs for different environments:

# In workflow:
env:
  ISSUECLAW_CONFIG_PATH: ${{ vars.ISSUECLAW_CONFIG_PATH || 'issueclaw.config.json' }}

Overriding Provider at Runtime

Use ISSUECLAW_PROVIDER and ISSUECLAW_MODEL env vars to override the config:

env:
  ISSUECLAW_PROVIDER: gemini
  ISSUECLAW_MODEL: gemini-2.5-flash

This is useful for A/B testing different models.

Branch-Specific Behavior

Modify the workflow to only trigger on specific branches:

on:
  issues:
    types: [opened]
  issue_comment:
    types: [created]

jobs:
  run-agent:
    if: github.ref == 'refs/heads/main' && ...

Custom Tools

Restrict or expand the agent's tools in config:

{
  "agent": {
    "tools": ["read", "bash"],          // Read-only analysis
    "excludeTools": ["edit", "write"]    // Prevent file modifications
  }
}

Or for full access:

{
  "agent": {
    "tools": [],                          // All tools
    "skills": true,                       // Enable skills
    "extensions": true                    // Enable extensions
  }
}

πŸ“– Deep Dive: How the Agent Mode Works

Pi Agent Architecture

IssueClaw uses pi-mono v0.80.3 as the agent engine. Pi provides:

  1. Tool use β€” bash, read, write, edit, grep, glob, ls
  2. Session management β€” JSONL transcripts with resume capability
  3. Multi-provider support β€” native support for Gemini, Cerebras, Groq, Anthropic, OpenAI, etc.
  4. Streaming β€” responses stream as JSONL events
  5. Extensions β€” custom provider registration
  6. Skills β€” reusable prompt templates

The Agent Loop

When you open an issue in agent mode:

  1. Prompt building β€” issueclaw builds a prompt with personality, memory, and instructions
  2. Pi invocation β€” pi is called as a subprocess with --mode json --session-dir state/sessions
  3. LLM call β€” pi sends the prompt + tool definitions to the LLM API
  4. Tool execution β€” if the LLM requests a tool (e.g., "read src/main.ts"), pi executes it
  5. Response loop β€” pi sends the tool result back to the LLM, which may request more tools
  6. Final response β€” the LLM produces a text response, pi logs it as message_end
  7. Extraction β€” issueclaw extracts the final assistant message from the JSONL
  8. Comment β€” issueclaw posts the response as a GitHub issue comment

JSONL Event Types

Pi outputs events as JSONL (one JSON object per line):

{"type":"session","version":3,"id":"abc123","timestamp":"..."}
{"type":"agent_start"}
{"type":"turn_start"}
{"type":"message_start","message":{"role":"user","content":[...]}}
{"type":"message_end","message":{"role":"user","content":[...]}}
{"type":"message_start","message":{"role":"assistant","content":[]}}
{"type":"tool_call","name":"bash","arguments":{"command":"ls"}}
{"type":"tool_result","name":"bash","output":"file1.txt\nfile2.txt"}
{"type":"message_end","message":{"role":"assistant","content":[{"type":"text","text":"Here are the files..."}]}}
{"type":"turn_end"}
{"type":"agent_end"}

IssueClaw's extractFinalMessage() finds the last message_end with role: "assistant" and extracts the text content. This is critical β€” if we didn't filter by role, we'd return the user's message (the prompt) as the response, which was a bug we fixed in v1.2.0.

Session Resume

When you comment on an existing issue:

  1. issueclaw reads state/issues/<N>.json to find the session file path
  2. Passes --session <path> to pi
  3. Pi loads the full JSONL transcript
  4. The LLM sees the entire conversation history
  5. The agent responds with full context

This enables long-running conversations across many comments on the same issue.


πŸ“– Deep Dive: How Simple Chat Mode Works

Why Simple Chat?

The full agent mode uses ~120,000 tokens per message:

  • Pi's system prompt: ~20,000 tokens
  • Tool definitions: ~80,000 tokens
  • Context (memory, personality): ~5,000 tokens
  • User message: ~5,000 tokens

This blows past Groq's 12K TPM and even strains Cerebras's 60K TPM.

Simple chat mode bypasses pi entirely and calls the LLM API directly:

  • Minimal system prompt: ~200 tokens
  • User message: ~100 tokens
  • Total: ~500 tokens (99.6% reduction)

Implementation

The simple-chat.ts module:

  1. Builds a minimal system prompt β€” includes personality + recent memory (last 10 lines)
  2. Builds the user message β€” just the issue title + body or comment body
  3. Calls the LLM API directly β€” using fetch():
    • For Gemini: uses Google's native API format (generateContent endpoint)
    • For all others: uses OpenAI-compatible /chat/completions endpoint
  4. Provider fallback β€” tries each provider in order until one succeeds
  5. Returns the response β€” no tools, no file editing, no session file

API Formats

OpenAI-compatible (Groq, Cerebras, OpenRouter, OpenAI, custom):

POST https://api.groq.com/openai/v1/chat/completions
Authorization: Bearer gsk_xxx

{
  "model": "llama-3.3-70b-versatile",
  "messages": [
    { "role": "system", "content": "You are a helpful assistant..." },
    { "role": "user", "content": "What is 2+2?" }
  ],
  "temperature": 0.7,
  "max_tokens": 8192
}

Google Gemini (native format):

POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSy...

{
  "contents": [
    { "role": "user", "parts": [{ "text": "What is 2+2?" }] }
  ],
  "systemInstruction": {
    "parts": [{ "text": "You are a helpful assistant..." }]
  },
  "generationConfig": {
    "temperature": 0.7,
    "maxOutputTokens": 8192
  }
}

πŸ› οΈ Development Guide

Setting Up Local Development

# Clone
git clone https://github.com/maruf009sultan/issueclaw.git
cd issueclaw

# Install dependencies
bun install

# Run tests
bun run test

# Run lint
bun run lint

# Run typecheck
bun run typecheck

# Run live test (uses mock LLM, no API key needed)
bun run scripts/live-test.ts

# Run doctor to verify environment
bun run src/cli.ts doctor

Project Architecture

src/
β”œβ”€β”€ config.ts               ← Config loading + Zod validation + auto-generation
β”œβ”€β”€ cli.ts                  ← CLI entrypoint
β”œβ”€β”€ providers/              ← LLM provider abstractions
β”‚   β”œβ”€β”€ types.ts            ← Provider interface
β”‚   β”œβ”€β”€ gemini.ts           ← Google Gemini (native pi support)
β”‚   β”œβ”€β”€ cerebras.ts         ← Cerebras (native pi support)
β”‚   β”œβ”€β”€ groq.ts             ← Groq (native pi support)
β”‚   β”œβ”€β”€ openai.ts           ← OpenAI
β”‚   β”œβ”€β”€ openrouter.ts       ← OpenRouter
β”‚   β”œβ”€β”€ anthropic.ts        ← Anthropic
β”‚   β”œβ”€β”€ ollama.ts           ← Ollama (local)
β”‚   β”œβ”€β”€ custom.ts           ← Custom (any OpenAI-compatible)
β”‚   └── index.ts            ← Registry + factory
β”œβ”€β”€ github/
β”‚   β”œβ”€β”€ client.ts           ← GitHub API client (wraps `gh` CLI)
β”‚   └── events.ts           ← Event parsing (issues, comments, PRs)
β”œβ”€β”€ agent/
β”‚   β”œβ”€β”€ runner.ts           ← Full agent mode (pi orchestration)
β”‚   └── simple-chat.ts      ← Simple chat mode (direct LLM call)
β”œβ”€β”€ memory/
β”‚   └── store.ts            ← Persistent state management
β”œβ”€β”€ lifecycle/
β”‚   β”œβ”€β”€ preinstall.ts       ← Pre-agent hook (reactions, perms)
β”‚   └── main.ts             ← Main lifecycle (run, commit, comment)
└── utils/
    β”œβ”€β”€ log.ts              ← Structured logger
    β”œβ”€β”€ retry.ts            ← Retry with backoff
    β”œβ”€β”€ git.ts              ← Git operations
    └── fs.ts               ← Atomic file writes

Adding a New Provider

  1. Create src/providers/myprovider.ts:
import type { Provider, ProviderArgs } from "./types.ts";
import type { ProviderConfig } from "../config.ts";

export const myProvider: Provider = {
  type: "myprovider",

  buildArgs(config: ProviderConfig): ProviderArgs {
    const args = ["--provider", "myprovider", "--model", config.model];
    const env: Record<string, string | undefined> = {};
    if (config.apiKey) {
      env.MYPROVIDER_API_KEY = config.apiKey;
    }
    return { args, env };
  },

  validate(config: ProviderConfig): string | null {
    if (!config.model) return "MyProvider requires a model";
    if (!config.apiKey) return "MyProvider requires MYPROVIDER_API_KEY";
    return null;
  },
};
  1. Register in src/providers/index.ts:
import { myProvider } from "./myprovider.ts";
const REGISTRY = { ..., myprovider: myProvider };
  1. Add to config schema in src/config.ts:
type: z.enum(["anthropic", "openai", ..., "myprovider", "custom"]),
  1. Add to providerToApiKeyEnv:
myprovider: "MYPROVIDER_API_KEY",
  1. Add tests in tests/unit/providers.test.ts

  2. Add to autoGenerateConfig() if it has a free tier

Running Tests

# All tests
bun run test

# Specific test file
bun run test tests/unit/simple-chat.test.ts

# With coverage
bun run test:coverage

# Watch mode
bun run test:watch

# Live test (end-to-end with mock LLM)
bun run scripts/live-test.ts

# Smoke test (quick environment check)
bun run scripts/smoke-test.ts

Debugging

# Enable debug logging
ISSUECLAW_LOG_LEVEL=debug bun run src/lifecycle/main.ts

# Enable trace logging (very verbose)
ISSUECLAW_LOG_LEVEL=trace bun run src/lifecycle/main.ts

# JSON log output (for log aggregation)
ISSUECLAW_LOG_JSON=true bun run src/lifecycle/main.ts

# Dry-run mode (no commits, no comments)
bun run src/cli.ts run --dry-run

# Offline mode (mock pi invocation)
bun run src/cli.ts run --offline

# Show the prompt that would be sent
bun run src/cli.ts test prompt

🌟 Marketing: Why You Should Use This

πŸ’° Save Money

  • $0/month with Gemini's free tier (1M TPM)
  • No OpenAI subscription ($20/month)
  • No GitHub Copilot subscription ($10/month)
  • No server costs (GitHub Actions is free for public repos)

πŸ”’ Own Your Data

  • Your conversations live in your git repo
  • No third-party sees your data (only your LLM provider)
  • You can self-host with Ollama for complete privacy
  • Git history = full audit trail

πŸš€ Ship Faster

  • AI writes code directly to your repo
  • No copy-pasting from ChatGPT
  • Automatic commits with descriptive messages
  • Session resume means the AI remembers your project

🧠 Persistent Memory

  • The AI remembers your preferences across sessions
  • Personality is customizable (hatch flow)
  • Memory log captures important facts
  • All stored in git β€” survives forever

πŸ”§ Enterprise-Ready

  • 122 tests passing
  • Structured logging
  • Audit trail
  • Permission checks
  • Concurrency control
  • Retry logic
  • Provider fallback chain
  • Docker support

🎨 Customizable

  • 8 LLM providers
  • Custom personalities
  • Configurable tools
  • Issue templates
  • Extensions system

πŸ“± Accessible Anywhere

  • GitHub Issues work on any device
  • No app to install
  • No server to maintain
  • Just open an issue and chat

🀝 Contributing

Contributions are welcome! Here's how to help:

Reporting Bugs

  1. Check existing issues first
  2. Open a new issue with the "πŸ› Bug" template
  3. Include:
    • What you expected
    • What happened
    • Steps to reproduce
    • Your config (redact API keys)
    • Workflow logs (from Actions tab)

Requesting Features

  1. Open an issue with the "πŸ”§ Task" template
  2. Describe the feature and why it's useful

Submitting PRs

  1. Fork the repo
  2. Create a branch: git checkout -b my-feature
  3. Make changes
  4. Run tests: bun run test
  5. Run lint: bun run lint:fix
  6. Run typecheck: bun run typecheck
  7. Commit: git commit -m "Add my feature"
  8. Push: git push origin my-feature
  9. Open a PR

Code Style

  • TypeScript strict mode
  • Biome for formatting and linting
  • 2-space indentation
  • Double quotes for strings
  • Trailing commas

πŸ“‹ Issue Templates Reference

πŸ₯š Hatch

Bootstrap a new agent identity. The agent will have a conversation to figure out its name, vibe, and emoji.

---
name: "πŸ₯š Hatch"
about: "Bootstrap a new agent identity"
labels: ["hatch"]
---

Read `.pi/BOOTSTRAP.md` and follow it. That's your birth certificate.

πŸ’¬ Chat

Quick chat without the full agent. Saves 99% of API tokens.

---
name: "πŸ’¬ Chat"
about: "Quick chat with the AI β€” no agent, no tools, saves API quota"
labels: ["chat"]
---

Type your message below. The AI will respond directly without using tools.

πŸ”§ Task

General task for the agent (code, file edits, etc.)

---
name: "πŸ”§ Task"
about: "Ask the agent to do something"
labels: []
---

## What do you want the agent to do?
[Describe the task]

## Context
[Any background info]

## Success Criteria
[Optional: How will you know it's done?]

πŸ› Bug

Report a bug for the agent to fix.

---
name: "πŸ› Bug"
about: "Report a bug for the agent to fix"
labels: ["bug"]
---

## Bug Description
[What's broken?]

## Reproduction Steps
1.
2.
3.

## Expected vs Actual
**Expected**:
**Actual**:

πŸ” Comparison: Token Usage by Mode

Scenario Agent Mode Simple Chat Mode
"What is 2+2?" ~120,000 tokens ~50 tokens
"Write a hello world HTML page" ~120,000 tokens ~80 tokens
"Explain async/await" ~120,000 tokens ~100 tokens
"Fix the bug in main.ts" ~120,000 tokens N/A (needs tools)
"Create a README" ~120,000 tokens N/A (needs file editing)

Rule of thumb: Use chat mode for questions, agent mode for tasks that need file access.


πŸ“Š Cost Analysis

Free Tier (Gemini)

Resource Limit IssueClaw Usage Cost
Gemini TPM 1,000,000 ~120,000 per agent run $0
Gemini RPM 15 1 per issue $0
Gemini requests/day 1,500 ~10-50 $0
GitHub Actions Unlimited (public) ~1 per issue $0
Total $0/month

Free Tier (Cerebras fallback)

Resource Limit IssueClaw Usage Cost
Cerebras TPM 60,000 ~120,000 per agent run May hit limit
Cerebras RPM 30 1 per issue $0
Total $0/month

Simple Chat Mode (any provider)

Resource Limit IssueClaw Usage Cost
Groq TPM 12,000 ~500 per chat $0
Total $0/month

Paid (Anthropic/OpenAI)

If you use paid providers as fallback:

Provider Cost per 1M tokens Agent run cost Chat run cost
Claude Opus 4 $15 input / $75 output ~$2-5 per run ~$0.01 per chat
GPT-4o $2.50 input / $10 output ~$0.50-1 per run ~$0.002 per chat

πŸŽ“ Tutorial: Your First Agent Task

Step 1: Open an issue

Go to your repo's Issues tab β†’ New Issue β†’ "πŸ”§ Task" template.

Title: Create a hello world HTML page

Body:

Create a simple hello world HTML page at index.html with:
- A heading saying "Hello World"
- Basic CSS styling
- A footer with the current year

Step 2: Watch the agent work

  1. Within seconds, the agent reacts with πŸ‘€
  2. Go to the Actions tab to see the workflow running
  3. The agent will:
    • Read the issue
    • Use bash to create index.html
    • Write the HTML content
    • Commit and push
  4. After ~30-60 seconds, the agent posts a comment:
I've created `index.html` with a hello world page. Here's what I did:

1. Created `index.html` with a heading, CSS styling, and footer
2. Committed the changes

The file is now in your repo at `index.html`.

Step 3: Verify

git pull
cat index.html

You should see the HTML file the agent created.

Step 4: Continue the conversation

Comment on the issue:

Add a button that shows an alert when clicked

The agent will resume the session (it remembers creating index.html) and add the button.


πŸŽ“ Tutorial: Your First Chat

Step 1: Open a chat issue

Go to Issues β†’ New Issue β†’ "πŸ’¬ Chat" template.

Title: What is closure in JavaScript?

Body:

Can you explain what a closure is in JavaScript with an example?

Step 2: Get a fast response

Within ~5 seconds (vs ~60 seconds for agent mode), the agent responds:

A closure is a function that remembers the variables from its outer scope,
even after the outer function has returned.

Here's an example:

```javascript
function makeCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}

const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2

In this example, the inner function "closes over" the count variable...


### Step 3: Check the cost

This chat used ~500 tokens (vs ~120,000 for agent mode). You can verify in the audit log:

```bash
tail -1 state/audit.log | jq .
{
  "timestamp": "2026-07-07T...",
  "action": "simple_chat_complete",
  "details": {
    "issue": 7,
    "success": true,
    "durationMs": 4200,
    "provider": "gemini",
    "tokensUsed": 487,
    "responseLength": 892
  }
}

πŸŽ“ Tutorial: Hatching a Personality

Step 1: Open a hatch issue

Go to Issues β†’ New Issue β†’ "πŸ₯š Hatch" template.

Title: Hatch

Body: (leave default)

Step 2: Have a conversation

The agent will respond with something like:

Hey. I just came online. Who am I? Who are you?

I don't have a name yet, a vibe, or an emoji. Let's figure that out together.

What should we call me?

Reply with:

Your name is Buddy. You're a chill, helpful assistant. Your emoji is πŸ€–.
My name is Maruf.

Step 3: The agent updates its identity

The agent will:

  1. Update state/personality.md:

    # Personality
    
    ## Name
    Buddy
    
    ## Nature
    Chill, helpful assistant
    
    ## Vibe
    Casual and friendly
    
    ## Emoji
    πŸ€–
    
    ## Hatch Date
    2026-07-07
  2. Update state/user.md:

    # User Profile
    
    ## Name
    Maruf
  3. Commit and push these changes

  4. Reply:

    Got it! I'm Buddy πŸ€–. Nice to meet you, Maruf!
    
    I've updated my personality and noted your name. From now on, I'll remember this across all our conversations.

Step 4: Verify persistence

git pull
cat state/personality.md
cat state/user.md

Now, every time you open a new issue, the agent will introduce itself as Buddy πŸ€– and know your name is Maruf.


❓ Extended FAQ

Q: Can I use this without GitHub Actions?

A: The agent is designed for GitHub Actions, but you can run it locally:

# Set up environment
export GITHUB_EVENT_PATH=/tmp/event.json
export GITHUB_EVENT_NAME=issues
export GITHUB_TOKEN=ghp_xxx
export GEMINI_API_KEY=AIzaSy...

# Create a test event
echo '{"action":"opened","issue":{"number":1,"title":"Test","body":"Hello","user":{"login":"you"},"author_association":"OWNER","labels":[]}}' > /tmp/event.json

# Run the lifecycle
bun run src/lifecycle/main.ts

Q: Can I use this with GitLab or Bitbucket?

A: Not directly β€” it relies on GitHub-specific features (Issues, Actions, gh CLI). But the core agent logic is portable. You'd need to:

  1. Replace src/github/client.ts with a GitLab/Bitbucket API client
  2. Replace src/github/events.ts with GitLab/Bitbucket event parsing
  3. Replace the GitHub Actions workflow with GitLab CI / Bitbucket Pipelines

Q: How do I delete old sessions?

A: Sessions are in git, so you can't "delete" them (git preserves history). But you can remove the files:

rm state/sessions/old-session.jsonl
rm state/issues/1.json
git add -A && git commit -m "cleanup old sessions" && git push

The daily maintenance script also flags orphaned sessions (sessions with no issue mapping).

Q: Can I use multiple repos with one agent?

A: Currently no β€” each repo has its own agent. Multi-repo support is on the roadmap.

Q: How do I backup everything?

A: The repo IS the backup. Just clone it:

git clone https://github.com/maruf009sultan/issueclaw.git backup

Or use git tags:

git tag backup-$(date +%Y%m%d)
git push origin backup-$(date +%Y%m%d)

Q: Can the agent access the internet?

A: In agent mode, the agent has the bash tool, so it can curl URLs. But GitHub Actions runners have standard internet access. The agent can:

  • Read web pages (via curl)
  • Download files
  • Access APIs

But it cannot:

  • Open a browser
  • Execute JavaScript in a browser context
  • Access localhost services (unless you set them up)

Q: How do I monitor the agent's activity?

A: Several ways:

  1. GitHub Actions tab β€” see workflow runs, logs, artifacts
  2. state/audit.log β€” JSON audit trail of every run
  3. Issue comments β€” the agent posts its responses as comments
  4. Git log β€” every commit shows what changed
  5. Structured logs β€” set ISSUECLAW_LOG_JSON=true for log aggregation

Q: Can I limit the agent's access?

A: Yes, via config:

{
  "agent": {
    "tools": ["read", "grep", "ls"],     // Read-only
    "excludeTools": ["bash", "edit", "write"]  // No modifications
  }
}

This makes the agent a read-only analyst.

Q: What if the agent goes rogue?

A: Several safeguards:

  1. Timeouts β€” 30-min job + 15-min agent timeout
  2. Permission checks β€” only authorized users can trigger
  3. Audit log β€” every action is logged
  4. Git history β€” all changes are versioned, you can revert
  5. Branch protection β€” protect main branch, require PR reviews
  6. Tool restrictions β€” limit tools to read-only if paranoid

Q: Can I use this commercially?

A: Yes! It's MIT licensed. Use it however you want.


🏁 Conclusion

IssueClaw is a production-ready, self-hosted AI assistant that runs entirely on GitHub infrastructure. It costs $0/month with Gemini's free tier, remembers everything across sessions, and can edit code directly in your repo.

Key differentiators:

  • βœ… Zero infrastructure β€” runs in GitHub Actions
  • βœ… Zero cost β€” Gemini free tier (1M TPM)
  • βœ… Persistent memory β€” git-backed state
  • βœ… Multi-provider β€” 8 providers with fallback
  • βœ… Two modes β€” agent (full tools) + chat (saves 99% of tokens)
  • βœ… Enterprise-grade β€” 122 tests, audit trail, concurrency control
  • βœ… Open source β€” MIT licensed

Get started in 3 minutes: Fork β†’ add API key β†’ open an issue.


πŸŽ‰ You've reached the end! πŸŽ‰

Now go fork the repo and start building with your AI assistant!

Fork

⬆ Back to top


πŸ“‹ Quick Reference Card

πŸ“Ž Quick reference (click to expand)

Essential Commands

Command Purpose
bun run src/cli.ts doctor Diagnose environment
bun run src/cli.ts config auto Auto-generate config
bun run src/cli.ts config show Show current config
bun run src/cli.ts config validate Validate config
bun run src/cli.ts memory show Show memory log
bun run src/cli.ts personality show Show personality
bun run src/cli.ts test lifecycle Test lifecycle locally
bun run scripts/live-test.ts Full live test (mock LLM)
bun run test Run unit tests
bun run lint Run linter
bun run typecheck TypeScript check

Essential Secrets

Secret Provider Free? Get Key
GEMINI_API_KEY Gemini βœ… https://aistudio.google.com/app/apikey
CEREBRAS_API_KEY Cerebras βœ… https://inference.cerebras.ai/
OPENROUTER_API_KEY OpenRouter βœ… https://openrouter.ai/keys
GROQ_API_KEY Groq βœ… https://console.groq.com/keys
ANTHROPIC_API_KEY Anthropic ❌ https://console.anthropic.com/
OPENAI_API_KEY OpenAI ❌ https://platform.openai.com/api-keys

Issue Labels

Label Mode Tokens Use Case
chat Simple chat ~500 Quick questions
hatch Agent + bootstrap ~120K Set up personality
(none) Full agent ~120K Code tasks, file edits
bug Full agent ~120K Bug fixing
task Full agent ~120K General tasks

Provider Priority (default config)

  1. 🟦 Gemini (1M TPM) β€” primary
  2. ⚑ Cerebras (60K TPM) β€” fallback 1
  3. 🟦 OpenRouter (varies) β€” fallback 2
  4. ⚑ Groq (12K TPM) β€” fallback 3
  5. 🟣 Anthropic (paid) β€” fallback 4
  6. 🟒 OpenAI (paid) β€” fallback 5

State Files

File Purpose
state/memory.md Append-only fact log
state/personality.md Agent identity (mutable)
state/user.md User profile (mutable)
state/audit.log JSON audit trail
state/issues/N.json Issue β†’ session mapping
state/sessions/*.jsonl Conversation transcripts

Log Levels

Level When to use
trace Extreme debugging (very verbose)
debug Debugging issues
info Normal operation (default)
warn Only warnings
error Only errors
fatal Only fatal errors

πŸ“œ License Summary

MIT License

Copyright (c) 2026 IssueClaw Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

See LICENSE for the full text.


Final line count: ~3000 lines of documentation

Built with ❀️ and πŸ¦ƒ by the open-source community

⬆ Back to top

About

IssueClaw is a self-hosted AI coding assistant that lives entirely within your GitHub repository. By simply opening an Issue, you can chat with an AI, generate code, fix bugs, and automate tasks. It features persistent git-backed memory and runs entirely on GitHub Actions - meaning zero servers, zero databases, and zero monthly costs.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors