Forge is an autonomous AI software-engineering agent. Point it at any GitHub issue and it will clone the repository, write the fix, and produce a verified git diff patch — all inside an isolated Docker sandbox, driven by any OpenAI-compatible model API.
It integrates with ElizaOS as a first-class action handler and can be deployed on decentralised compute via Nosana.
The only prerequisite is Docker.
git clone <your-repo-url>cd forgecp .env.example .envOpen .env and fill in three required values:
FORGE_MODEL=your-model-name# e.g. gpt-4o, models/gemini-2.0-flash-001FORGE_BASE_URL=https://...# OpenAI-compatible endpointFORGE_API_KEY=your-api-keydocker compose run --rm list-issues
# or specify a different repo:
docker compose run --rm list-issues --repo owner/repoOutput:
Open issues on owner/repo (5 shown):
# Title
------------------------------------------------------------------------
#3 Add input validation to signup form [bug]
#7 Dark mode flicker on page load [enhancement]
#12 Upgrade to Node 20
Set FORGE_REPO and FORGE_ISSUE in your .env, then:
docker compose run --rm forgeOr pass them directly:
docker compose run --rm forge run --repo owner/repo --issue 12Forge will clone the repo, work autonomously, and print a patch when done.
Set it up once — then just label issues on GitHub and Forge handles the rest.
Add to .env:
FORGE_WATCH_REPO=owner/repoFORGE_WATCH_LABEL=forge# label to watch forFORGE_WATCH_INTERVAL=60# seconds between pollsGITHUB_TOKEN=ghp_...# required to push the fix branch backStart in the background:
docker compose up watch -dThat's it. Go to GitHub, open any issue in your repo, and add the label forge. Within 60 seconds Forge picks it up, fixes it, and pushes the result to a branch named forge/issue-{N}. Review the branch and merge when you're happy.
- Already-processed issues are tracked in
trajectories/watch_state.json— Forge never double-processes the same issue. - The service has
restart: unless-stopped— it survives crashes and Docker restarts automatically. - Stop it any time with
docker compose down.
GitHub issue ──► add label "forge"
│
Forge detects it
(within 60 s)
│
┌──────────────────────┐
│ Docker sandbox │
│ 1. Clone repo │
│ 2. Agent loop │
│ think → act │
│ → observe │
│ 3. submit │
│ git diff patch │
└──────────────────────┘
│
Push branch
forge/issue-{N}
│
You review & merge
Scan a GitHub repo and show open issues.
forge list-issues --repo owner/repo
forge list-issues --repo owner/repo --label bug
forge list-issues --repo owner/repo --limit 50| Flag | Default | Description |
|---|---|---|
--repo | — | GitHub repository (owner/repo) |
--label | — | Filter by label |
--limit | 30 | Maximum issues to show |
Run the agent on a single issue or problem.
# Recommended — pick from list-issues output
forge run --repo owner/repo --issue 42
# Or with a full URL
forge run --github-url https://github.com/owner/repo/issues/42
# Inline problem text (no GitHub needed)
forge run --problem-text "Add rate-limiting to the /api/login endpoint"| Flag | Env var | Default | Description |
|---|---|---|---|
--repo | — | — | GitHub repository (use with --issue) |
--issue | — | — | Issue number |
--github-url | — | — | Full GitHub issue URL |
--problem-text | — | — | Inline problem statement |
--problem-file | — | — | Path to plain-text problem file |
--model | FORGE_MODEL | — | Model identifier |
--base-url | FORGE_BASE_URL | — | OpenAI-compatible API URL |
--api-key | FORGE_API_KEY | — | API key |
--image | — | forge-sandbox:latest | Docker sandbox image |
--output-dir | — | trajectories | Where to save .traj files |
--max-steps | — | 100 | Step limit |
--config | — | — | YAML config file (see Advanced) |
Poll a repo and automatically fix every issue that carries a given label.
When GITHUB_TOKEN is set, the fix is pushed to branch forge/issue-{N} automatically.
forge watch --repo owner/repo --label forge --interval 60| Flag | Env var | Default | Description |
|---|---|---|---|
--repo | FORGE_WATCH_REPO | — | GitHub repository |
--label | FORGE_WATCH_LABEL | forge | Label to watch for |
--interval | FORGE_WATCH_INTERVAL | 60 | Poll interval (seconds) |
--model | FORGE_MODEL | — | Model identifier |
--base-url | FORGE_BASE_URL | — | API base URL |
--api-key | FORGE_API_KEY | — | API key |
--image | FORGE_SANDBOX_IMAGE | forge-sandbox:latest | Sandbox image |
--output-dir | — | trajectories | Trajectory output dir |
Branch push: set
GITHUB_TOKENin.envand every completed fix is pushed toforge/issue-{N}on GitHub automatically.
Summarise trajectory results.
forge quick-stats # scans ./trajectories
forge quick-stats /path/to/trajs| Variable | Required | Description |
|---|---|---|
FORGE_MODEL | Yes | Model identifier passed to the API |
FORGE_BASE_URL | Yes | Base URL of an OpenAI-compatible endpoint |
FORGE_API_KEY | Yes | API key for the endpoint |
FORGE_REPO | For one-shot | GitHub repo (owner/repo) |
FORGE_ISSUE | For one-shot | Issue number |
FORGE_WATCH_REPO | For watch | Repo to monitor |
FORGE_WATCH_LABEL | No | Label to watch (default: forge) |
FORGE_WATCH_INTERVAL | No | Poll interval in seconds (default: 60) |
GITHUB_TOKEN | For branch push | PAT — required to push fix branches; also raises API rate limit and enables private repos |
RUST_LOG | No | Log filter — e.g. forge=debug (default: forge=warn) |
DOCKER_GID | No | Docker group GID on host (docker-compose socket mount) |
Forge runs as a standard Docker container on Nosana's decentralised compute network.
Edit nos_job_def/forge_job_definition.json — replace the $FORGE_* placeholders with your actual values, or pass them as environment variables via the Nosana CLI.
npm install -g @nosana/cli
nosana job post \
--file ./nos_job_def/forge_job_definition.json \
--market nvidia-4090 \
--timeout 120 \
--api <YOUR_NOSANA_API_KEY>Or paste the job definition JSON into the Nosana Dashboard.
Every run produces a <instance-id>.traj JSON file in output_dir with the complete agent history: every command, every output, every model response, and timing data.
forge quick-stats # summary counts
cat trajectories/*.traj # full detailMost users only need environment variables and CLI flags. For advanced use (custom system prompts, extended timeouts, batch runs), use a YAML config:
forge run --config example.yamlSee example.yaml in this repository for all available fields with comments.
forge-plugin exposes a SolveIssueAction that plugs into any ElizaOS agent:
use forge_plugin::action::{SolveIssueAction,SolveIssueParams};let result = SolveIssueAction::new().handle(SolveIssueParams{github_url:Some("https://github.com/owner/repo/issues/42".into()),model_name:Some("your-model".into()),base_url:Some("https://your-provider.example.com/v1".into()),api_key:Some("your-api-key".into()),
..Default::default()}).await?;println!("status: {:?}", result.exit_status);println!("patch: {:?}", result.submission);Rust 1.82+ required. Docker still needed at runtime.
# Build the sandbox image once
docker build -f Dockerfile.sandbox -t forge-sandbox:latest .# Build the forge binary
cargo build --release -p forge
# Run
./target/release/forge list-issues --repo owner/repoRun all tests:
cargo test --workspace
# Include Docker-gated integration tests:
cargo test --workspace -- --include-ignoredforge/crates/
├── forge-types Shared data types
├── forge-tools Response parsers
├── forge-model Model backends (OpenAI-compat, Anthropic, Replay, Human)
├── forge-env Docker runtime, bash sessions
├── forge-agent Agent loop, history processors
├── forge-run RunSingle, RunBatch, YAML config
├── forge-plugin ElizaOS integration
└── forge CLI binary (list-issues, run, watch, quick-stats)
MIT