Autonomous AI agents that pull issues from a task manager, implement them, and push code — continuously. Inspired by AI Coding Factories.
How it works
Workers poll a task manager for unassigned issues, claim one, clone the repo, invoke an AI agent to implement it, commit and push the result, then loop back for the next issue. The task manager is the single source of truth — no local task store.
The task management backend is pluggable via the TASK_MANAGER environment variable (default: jira).
[Jira] ← issues queue
↓ workers poll for unassigned open issues
[Worker pool: claude | copilot | codex | ...]
↓ push to trunk, post comments, transition status
[Jira + Git]
Installation
Clone the repository and run the setup script:
git clone https://github.com/jaksa76/ai-coding-factory.git
cd ai-coding-factory
./setup.shsetup.sh will:
- Check prerequisites (
docker,git) - Ask which AI agent you want to use (claude, copilot, ...)
- Create symlinks in
bin/for all tools (loop,implement,plan,factory,task-manager,worker-builder,agent) - Add
bin/to yourPATHin your shell config - Collect your credentials and write them to an env file (e.g.
.env.factory)
Re-run setup.sh at any time to update credentials or change the agent.
Configuration
All configuration is passed via environment variables. setup.sh writes these to an env file for you, but you can also set them manually.
Task manager
The default backend is jira. Provide your Jira credentials:
export TASK_MANAGER=jira # optional, jira is the default export PROJECT=MYPROJ export JIRA_SITE=mycompany.atlassian.net export JIRA_EMAIL=worker@mycompany.com export JIRA_TOKEN=<jira-api-token> export JIRA_ASSIGNEE_ACCOUNT_ID=<jira-account-id>
For GitHub Issues, use:
export TASK_MANAGER=github export PROJECT=owner/repo export GH_ASSIGNEE=myuser export GH_TOKEN=<github-pat>
For the TODO backend, use:
export TASK_MANAGER=todo export PROJECT=TODO.md export TODO_ASSIGNEE=myuser
PROJECT is the canonical target passed to loop --project:
- Jira: project key, for example
MYPROJ - GitHub: repository in
owner/repoform - TODO: path to the todo file
Git
export GIT_REPO_URL=https://github.com/myorg/myrepo.git export GIT_USERNAME=myuser export GIT_TOKEN=<github-pat>
AI agent
Claude (API key):
export ANTHROPIC_API_KEY=<your-api-key>
Claude (subscription): log in with claude login first, then import your credentials (see below). Or set them manually from ~/.claude/.credentials.json:
export CLAUDE_ACCESS_TOKEN=<access-token> export CLAUDE_REFRESH_TOKEN=<refresh-token> export CLAUDE_TOKEN_EXPIRES_AT=<timestamp> export CLAUDE_SUBSCRIPTION_TYPE=pro
GitHub Copilot:
export GH_TOKEN=<your-github-token> export GH_USERNAME=<your-github-username>
Optional
export FEATURE_BRANCHES=true # create a feature branch + PR per issue export PLAN_BY_DEFAULT=true # require a planning step for all issues export NO_ISSUES_WAIT=60 # seconds to wait when no issues are available export INTER_ISSUE_WAIT=1200 # seconds to wait between issues export IMPLEMENTATION_PROMPT="..." # override the default implementation prompt export PLANNING_PROMPT="..." # override the default planning prompt
Running
There are three ways to run workers: directly, via Docker, or via the factory.
Directly
Run the loop script directly on your machine (no Docker required):
This uses whatever agent script is on your PATH (set by setup.sh) and the environment variables in your current shell. Useful for development and testing.
Via Docker
Build a worker image and run it with your env file:
docker build -f workers/claude/Dockerfile -t worker-claude .
docker run --env-file .env.factory worker-claudeVia the factory (multiple workers)
Use factory to manage multiple Docker workers at once:
factory workers # start 1 implementation worker factory workers 3 # start 3 implementation workers factory workers --env-file .env.factory # pass credentials to workers
This uses the worker-claude image by default. Override with FACTORY_WORKER_IMAGE=<image>. Images are automatically built or rebuilt when missing or outdated.
You can also set the env file globally:
export FACTORY_ENV_FILE=.env.factory
factory workers 3Monitor and control workers:
factory status # list running workers factory logs <worker-id> # stream a worker's output factory stop <worker-id> # stop a specific worker factory stop --all # stop all workers
For lower-level control (e.g. a specific image):
factory add --image worker-copilot 2
Via AWS ECS (Fargate)
To run workers on AWS ECS Fargate instead of local Docker, create a runtime symlink in the factory directory pointing to runtime-aws:
ln -sf runtime-aws factory/runtime
Then set the required AWS variables:
export FACTORY_AWS_REGION=us-east-1 export FACTORY_AWS_CLUSTER=ai-coding-factory export FACTORY_AWS_SUBNET_ID=subnet-... export FACTORY_AWS_SECURITY_GROUP_ID=sg-...
All other factory commands (factory workers, factory status, factory logs, etc.) work the same way.
Feature branches
To open a PR per issue instead of pushing directly to the default branch:
export FEATURE_BRANCHES=trueOr add a needs-branch label to individual Jira issues. The worker creates feature/<ISSUE-KEY>, pushes it, opens a PR, posts a comment with the PR URL, and attempts to transition the issue to In Review.
Individual issues can opt out with the skip-branch label (takes precedence over FEATURE_BRANCHES=true).
Importing Claude credentials
If you use a Claude subscription, OAuth tokens expire periodically. After running claude login to refresh them, import the new credentials into your env file with:
factory import-claude-credentials --env-file .env.factory
This reads ~/.claude/.credentials.json and updates the CLAUDE_* variables in your env file in place.
Planning
If your workflow requires a planning step before implementation, run planner workers alongside your regular workers. Planners claim issues, generate a written plan, commit it to plans/<ISSUE-KEY>.md in the repo, and move on. A human reviews the plan; once approved, a regular implementation worker picks the issue up.
Build the planner image
docker build -f planner/Dockerfile -t planner-claude .Start planner workers
factory planners # start 1 planning worker factory planners 2 # start 2 planning workers factory planners --env-file .env.factory # pass environment variables to planners
This uses the planner-claude image by default. Override with FACTORY_PLANNER_IMAGE=<image>.
Workflow
- Planner claims an eligible issue and generates
plans/<ISSUE-KEY>.md - Issue is transitioned to Awaiting Plan Review
- Human reviews and approves the plan (transitions issue to Plan Approved)
- Regular implementation worker picks it up from the Plan Approved queue
Opt-in / opt-out
By default, planning is opt-in. Add a needs-plan label to an issue to require a planning step for that specific issue.
To require planning for all issues by default, set:
export PLAN_BY_DEFAULT=trueIndividual issues can bypass planning with the skip-plan label (takes precedence over PLAN_BY_DEFAULT=true).