An autonomous GitHub coding agent β like a teammate that fixes issues, opens PRs, and reviews pull requests (with a GitHub Advanced Securityβstyle security pass).
Multi-provider Β· Vision-aware Β· Self-hosted Β· Original open-source code.
Providers:
Β AnthropicΒ Β·Β OpenAIΒ Β·Β GeminiΒ Β·Β Vertex AIΒ Β·Β AWS BedrockΒ Β·Β GroqΒ Β·Β TogetherΒ Β·Β OllamaΒ Β·Β OpenAI-compatible
π shipiit.github.io/forge Β Β·Β Live examples Β Β·Β Docs
On this page: Quick start Β· Deploy as an App Β· Use as an Action Β· How it works Β· Config Β· Roadmap
| Capability | How you trigger it | |
|---|---|---|
| π οΈ | Fix an issue β open a PR β investigates the repo, writes the fix on a branch, runs the tests, opens a PR that closes the issue | Label agent-fix, or comment /fix |
| π | Review a PR β inline comments + summary verdict, quality and security lenses, scoped strictly to the changed files | Open a PR, or comment /review / /review always |
| π‘οΈ | Security review β flags SSRF, injection, secrets, authzβ¦ with severity, a CWE, and a suggested-fix block | Auto on PRs, or comment /security |
| π¬ | Whole-repo audit β maps entry points, follows untrusted input to dangerous sinks, one grouped report | Comment /audit |
| π | Change-history document β one entry per merged change, written from that diff alone; arrives as a PR | history: true in agent.yml |
| β° | Routines β a saved skill plus its triggers: cron, on-demand, or any repository event, each with filters | routines: in agent.yml, /run <name> |
| π§© | Skills β 7 built-in prompt packs with enforced tool allowlists; override from your repo or the workflow | /code-review, /triage, β¦ |
| π | Auto-fix failing CI β reads the logs, corrects the code, re-runs the suite, pushes a ci-fix commit |
Automatic on forge/* branches |
| π | Release notes β generated from the commits in the release | On release.published |
| π | Invite as a reviewer β request @shipit-forge on any PR and it reviews on demand |
Add it as a PR reviewer |
| π¬ | Answer @mentions β explains code on issues; on a PR it can push a follow-up commit to the branch | Comment @shipit-forge <ask> |
| πΌοΈ | Reads screenshots β pulls images out of issue/PR bodies and feeds them to vision models | Automatic |
It never merges and never approves. Every change is a pull request you control, and the review check run
always completes as neutral so it can't block a merge through branch protection.
- 9 providers β Anthropic, OpenAI, Gemini, Vertex AI, AWS Bedrock, Groq, Together, Ollama, or any
OpenAI-compatible endpoint. Set
FORGE_FALLBACK_PROVIDERSfor a fallback chain when one has an outage. - Prompt caching β the system prompt, every tool schema, and the growing transcript are cached
(Anthropic
cache_control, BedrockcachePoint), so repeated context bills at roughly a tenth of the input rate. OpenAI and Gemini automatic caching is reported too. - Extended thinking β
FORGE_THINKING_BUDGETon Anthropic and Gemini;reasoning_effortis set automatically for OpenAI's o-series and gpt-5 (includingmax_completion_tokens). - Token discipline β a tool allowlist strips unused schemas from every turn, context compaction elides
stale tool output once a transcript grows large, and
read_filewindows big files instead of dumping them. - Cost reporting β every comment and PR carries a footer with tokens used, how many were served from cache, and the estimated spend.
- Per-model output caps β a shared 16k budget is clamped to what each model actually accepts.
- Usage recording β opt-in, and off unless you ask for it. Every run, turn, tool call, finding and transcript is written to a local SQLite file, which the dashboard reads.
- Deterministic per-edit checks β every write is scanned for risky patterns (dynamic execution, unsafe
deserialization, DOM injection, hardcoded credentials, weak crypto, workflow edits) with no model call
and no token cost. Add your own rules in
.forge/security-patterns.json. - Sandboxed tools β path-jailed file access, a command denylist, process-group timeouts, and output caps.
- Secret redaction on every log path.
- Live Dependabot alerts and SARIF (CodeQL, Semgrep) merged into the same triaged report.
- Whole-organization rollout β the App installs once across every repo; the Action needs no server at all.
- GitHub Enterprise Server β set
GHES_HOSTNAMEand everything else is identical. - Repo instruction files β
FORGE.md/AGENTS.mdas project context,REVIEW.mdas highest-priority review instructions that override the defaults. - Trigger filters β author, title, body, base/head branch, labels, draft, merged, with
equals Β· contains Β· starts_with Β· is_one_of Β· is_not_one_of Β· matches_regex.
Pick the one that fits β they all share the same engine.
| Best for | Install | Run | |
|---|---|---|---|
| β CLI / local | Trying it on your machine, scripting, CI of your own | git clone https://github.com/shipiit/forge.git && cd forge && npm install && npm run build |
node dist/cli.js fix --repo /path/to/repo --task "β¦" --provider fake |
| β‘ GitHub Action | Per-repo or per-org, your own keys, zero infra | Copy examples/forge.yml β .github/workflows/forge.yml, add a provider secret |
Label an issue agent-fix, comment /review, or @shipit-forge β¦ β it runs in your Actions |
| β’ Hosted GitHub App | Org-wide, one-click install for many repos | Deploy the webhook server (Render / Cloud Run / Docker), then register via app.yml |
Install on the org β events trigger it automatically on a server you host |
Not sure? Start with β CLI +
--provider fake(no keys, 2 min). Want it on GitHub without hosting β β‘ Action. Want org-wide one-click β β’ App. Full per-distribution credential setup for all four providers:deploy/PROVIDERS.md.
Jump to: β CLI Β· β‘ Action Β· β’ App
Prerequisites: Node.js β₯ 20 (22 recommended), git, and (optional but
faster search) ripgrep.
# 1. Clone
git clone https://github.com/shipiit/forge.git
cd forge
# 2. Install dependencies
npm install
# 3. Build (compiles TypeScript β dist/)
npm run build
# 4. Verify everything works (546 unit + integration tests)
npm testThat's it β you now have the forge CLI at node dist/cli.js. (Optionally npm link to get a
global forge command.)
The agent engine runs locally with a built-in fake provider β no API keys needed, great for a first look:
node dist/cli.js fix --repo /path/to/any/repo --task "fix the failing login test" --provider fakeIt clones nothing (works on the path you give), runs the tool loop, and prints what changed.
The easiest, safest way to add your credentials. It writes a gitignored .env with chmod 600
so secrets never get committed:
node dist/cli.js setupπ§ ShipIT Forge β provider setup
Which provider?
1) Vertex AI Gemini
2) Anthropic
3) OpenAI
4) AWS Bedrock
> 1
GCP project id: <your-gcp-project-id>
Location [us-central1]:
Model [gemini-2.5-pro]:
Provide the service-account key. Either:
β’ a path to the JSON file, or
β’ paste the JSON, then a line with just END
path or paste> <paste your service-account JSON, or a file path>
β
Wrote .env (chmod 600) and updated .gitignore. Your secrets are gitignored.
Setting up Vertex AI credentials (step by step):
- In Google Cloud Console β IAM & Admin β Service Accounts, create a service account (or reuse one).
- Give it the Vertex AI User role (
roles/aiplatform.user). - Keys β Add key β JSON to download the key file. Keep it private β never commit it.
- Run
forge setup, choose Vertex AI Gemini, enter your project id, and either paste the JSON or give the path to the downloaded file.
When you paste, the JSON is validated and saved to .forge/vertex-sa.json (chmod 600, gitignored);
when you give a path, it's referenced in place. Either way nothing secret is ever committed.
export LLM_PROVIDER=vertex
export VERTEX_PROJECT=my-gcp-project
export VERTEX_LOCATION=us-central1
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
node dist/cli.js fix --repo /path/to/repo --task "β¦" --provider vertexSee .env.example for every provider's variables, and
deploy/PROVIDERS.md for step-by-step credential setup for all four
providers (Vertex Gemini, Bedrock, OpenAI, Anthropic) across CLI / Action / App.
Make a tiny buggy repo and let Forge fix it:
# 1. A throwaway repo with a deliberate bug + a test
mkdir /tmp/forge-try && cd /tmp/forge-try && git init -q
printf 'export const add = (a, b) => a - b; // bug\n' > sum.js
printf "import test from 'node:test'; import assert from 'node:assert'; import {add} from './sum.js';\ntest('adds', () => assert.strictEqual(add(2,3), 5));\n" > sum.test.js
printf '{"type":"module","scripts":{"test":"node --test"}}\n' > package.json
git add -A && git commit -qm init
# 2. Point Forge at it with your provider (Vertex shown)
cd - # back to the forge repo
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
node dist/cli.js fix --repo /tmp/forge-try \
--task "add() subtracts instead of adding; fix it so the tests pass" \
--provider vertex --model gemini-2.5-proForge will read sum.js, change a - b β a + b, run node --test, confirm it passes, and print
the diff. (This exact flow is verified working against Vertex AI Gemini 2.5 Pro.) β
Publishing the code β running the agent. GitHub stores your repo and the App registration, but the agent runs on your server. GitHub sends webhooks β your server clones the repo, calls the model, and opens the PR/review. Docker is just a portable way to run that server anywhere.
1. Deploy the webhook server (runs 24/7 β no laptop). Pick a host:
- No GCP, easiest: Render β connect the repo, set env vars, done (uses
render.yaml). - Google Cloud Run (one command): see
deploy/DEPLOY.mdPROJECT=your-gcp-project-id APP_ID=β¦ WEBHOOK_SECRET=β¦ \ PRIVATE_KEY_FILE=./shipit-forge.private-key.pem ./deploy/cloudrun.sh
- Any host with Docker (Railway, Fly.io, a VPS):
docker build -t shipit-forge . && docker run -p 3000:3000 --env-file .env shipit-forge
It's a standard Node/Docker app β it just needs a public HTTPS URL. Set the provider/App env vars
(see deploy/PROVIDERS.md); on non-GCP hosts pass the Vertex key as
VERTEX_CREDENTIALS_JSON (the server writes it to a file at boot). Never set WEBHOOK_PROXY_URL in production.
2. Register the GitHub App (one click)
With the server running, open its URL (e.g. http://localhost:3000 in dev, or your public URL).
Probot serves a registration page driven by app.yml:
- Click Register a GitHub App β it redirects you to GitHub with the name, permissions, and
events pre-filled from
app.yml. - Pick the owner β choose your organization (e.g.
shipiit) so the App belongs to the org. - Confirm. GitHub creates the App and redirects back; Probot automatically writes
APP_ID,PRIVATE_KEY, andWEBHOOK_SECRETinto your.env. Add your provider vars and restart.
Prefer manual? GitHub β Settings β Developer settings β GitHub Apps β New GitHub App, then copy
the permissions/events from app.yml.
Keep it private while testing.
app.ymlhaspublic: false, so only orgs you administer can install it β perfect for trying it inside your own org first. Flip topublic: truelater to allow any org and to list it on the Marketplace.
Set the App icon β in the App's Settings β Display information β Logo, upload
assets/logo.png (the anvil-and-spark mark). A 512Γ512 and a 1024Γ1024
(logo-1024.png) export are included.
3. Install on your org (test it) β App page β Install App β your org β pick one test repo
(or All repositories). Then open an issue with the agent-fix label, or request @shipit-forge on a
PR, and watch it work. Once it behaves, widen to all repos and/or make it public.
4. Invite & test it β in any repo of that org:
- open an issue and add the label
agent-fix(or comment/fix) β Forge opens a fix PR; - open a PR β Forge auto-reviews it; or request
@shipit-forgeas a reviewer on an existing PR; - comment
/review,/security, or@shipit-forge <ask>anywhere.
Watch it work: the server logs every event and tool call (with secrets redacted). For Docker,
docker logs -f <container>. A failed run still comments on the issue/PR explaining what happened.
You can receive real GitHub webhooks on your laptop using a proxy β no hosting needed:
cp .env.example .env # fill in APP_ID, PRIVATE_KEY, WEBHOOK_SECRET + your provider vars
npm run dev # starts the webhook server with hot reload
# Probot prints a smee.io proxy URL on first run; set it as the App's webhook URL.This is the fastest way to try the App end-to-end and invite it on a test PR before committing to a hosting provider.
Prefer "just add a file" with no hosting and no app registration? Use the Action β each repo/org runs Forge in its own CI with its own provider key. This is the per-org-credentials model (like Claude Code's Action).
- Add your provider key as a repo/org secret (Settings β Secrets and variables β Actions),
e.g.
VERTEX_SA_JSON,OPENAI_API_KEY, orANTHROPIC_API_KEY. - Copy
examples/forge.ymlto.github/workflows/forge.yml(full guide, incl. acting as your own App bot like Claude:deploy/GITHUB_ACTIONS.md):
name: ShipIT Forge
on:
issues: { types: [opened, labeled] }
issue_comment: { types: [created] }
pull_request: { types: [opened, synchronize, review_requested] }
pull_request_review_comment: { types: [created] }
permissions: { contents: write, pull-requests: write, issues: write, checks: read, statuses: read, actions: write }
jobs:
forge:
runs-on: ubuntu-latest
steps:
- uses: shipiit/forge@v2
with: { provider: vertex }
env:
LLM_PROVIDER: vertex
VERTEX_PROJECT: ${{ vars.VERTEX_PROJECT }}
VERTEX_CREDENTIALS_JSON: ${{ secrets.VERTEX_SA_JSON }}That's it β label an issue agent-fix, comment /review on a PR, or @shipit-forge anything, and
it runs in your Actions with your key and compute. No server to host, nothing to register.
Action vs hosted App: the Action = per-org keys, zero infra, runs in their CI. The App (above) = one server you host and pay for, one-click install for others. Same engine.
Where the money goes, which tool is slow, and why a particular run cost what it did.
Recording is opt-in and off by default β it stores repository names, actor logins and error strings,
which is not something to switch on for somebody without asking. Set FORGE_USAGE_DB (a path) or
FORGE_USAGE=1 on whichever surface runs the agent β the App, the Action, or the CLI β and runs start
landing in it.
# 1. Record into a local database
export FORGE_USAGE_DB=.forge/usage.db
# 2. Serve the API (always authenticated; prints a token if you have not set one)
npx forge dashboard --db .forge/usage.db --port 4300
# 3. Open the dashboard and point it at that API under "Connection"
# https://shipiit.github.io/forge/dashboardWhat it answers:
| Page | Question it answers |
|---|---|
| Overview | What did this month cost, how much did caching save, what is the success rate? |
| Runs | Every run, sortable, with a turn-by-turn breakdown and the full transcript. |
| Events | Which trigger, surface and actor started the work β and what each one costs. |
| Tool reliability | p95 latency and error rate per tool, plus every failure with what it said. |
| Findings | Every finding the review and audit flows reported, by severity, lens and file. |
Opening a run shows each turn's latency, tokens and cache reads (so you can watch the cache grow), the tool calls with their arguments, the findings, the commit or PR it produced, and the transcript rendered as a conversation rather than a wall of JSON.
Everything is token-gated. There is no unauthenticated mode: the standalone server generates a token when you have not configured one and prints it with the URL, and it binds to loopback unless you say otherwise. To mount it on a hosted App's existing webhook server instead:
FORGE_USAGE_DB=/data/usage.db
FORGE_DASHBOARD_TOKEN=<a long random string> # without it, nothing is mounted at all
FORGE_DASHBOARD_ORIGIN=https://your-site # only if the dashboard is served elsewhereIt appears at /usage on the same host. Retention runs at startup: transcripts are kept 14 days, diffs and
tool calls 90, and the run/turn/finding history β the trend data, and the small part β forever.
Storage: metadata in SQLite, payloads gzipped to disk beside it. Roughly 20 KB per run, so a thousand runs a month is about 20 MB a year.
Per-repo via .github/agent.yml (all optional), with env-var defaults:
model: gemini-2.5-pro # provider-specific model id
trigger_label: agent-fix
auto_fix: label # label | opened | off
auto_review: always # always | requested | off
test_command: "npm test" # else auto-detected
review_depth: standard # light | standard | deep
ignore_paths: ["dist/**", "*.lock"]| Env var | Default | Effect |
|---|---|---|
LLM_PROVIDER |
anthropic |
vertex Β· bedrock Β· openai Β· anthropic |
FORGE_AUTO_FIX |
label |
opened = attempt a PR on every new issue (full auto) |
FORGE_AUTO_REVIEW |
always |
requested = only when invited / /review |
MAX_ITERATIONS |
25 |
Max agent tool-loop steps per run |
issue / PR event ββΆ Probot webhook ββΆ clone repo (sandbox)
β
agent loop βββββββββ (LLM + tools, provider-agnostic)
read Β· search Β· edit Β· multi_edit Β· glob Β· git_history Β· run_bash Β· run_tests
β
verify (tests) βββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββ
βΌ βΌ βΌ
open PR (Closes #n) PR review (inline + @mention reply
security + suggestions)
- Provider layer (
src/providers) β oneLLMClientinterface; adapters normalize chat + tool-calling + images for Anthropic, Vertex Gemini, OpenAI, Bedrock. Swap providers with one env var. - Tools (
src/agent/tools) βread_file,write_file,edit_file,multi_edit,list_dir,glob,read_image,search,git_history,run_bash(sandboxed: allow/deny, timeout, no network),run_tests(auto-detected). - Agent loop (
src/agent/loop.ts) β chat β tool calls β results β repeat, with retries, iteration + token limits, and a repo-map for fast orientation. - GitHub layer (
src/github) β vision image extraction, workspace clone/branch/commit/push, PR composer, diff-aware security review composer; wired to webhooks insrc/app.ts.
npm test # vitest β 546 unit + integration tests
npm run typecheckEverything is testable without credentials: a scripted fake provider drives the agent loop, and each real adapter is verified via pure normalization functions + injected mock clients. CI runs typecheck + tests + build on every push.
Coverage is weighted toward the logic that decides what the agent does β routing, filters, review
scoping, config parsing, and the workflow generator β because those are the parts that fail quietly
rather than loudly. A malformed agent.yml, an invalid regex in a filter, or a finding on a file the
PR never touched all have a test pinning the behaviour.
- Agent engine, 11 tools, sandbox, retries
- 4 provider adapters + vision
- GitHub App: issueβPR, PR review, security lens, @mentions
- Review line-safety,
.github/agent.yml, secret redaction, CI - Live provider smoke run (verified on Vertex Gemini 2.5 Pro)
- Follow-up commits when @mentioned on a PR
- Secure
forge setupwizard (paste/point-to credentials, gitignored) - Recorded handler integration tests (mocked Octokit)
- Cost tracking (per-run token + USD estimate)
- CodeQL/SARIF ingestion (merge scanner findings into review)
- Multi-pass self-review (agent critiques its own diff β draft PR on blockers)
- npm-publishable package (
files, bin,prepublishOnly) - GitHub Action distribution (per-org credentials, no server)
- Sub-agents β orchestrator can delegate focused subtasks (depth-bounded)
- Marketplace listing kit + privacy policy (
deploy/MARKETPLACE.md) - Spend caps + per-repository rate limiting
- Findings β trackable issues, with fingerprints so a re-run does not refile them
- Review thread resolution (no duplicate comments on a re-review)
- Usage recording + dashboard (runs, turns, tools, findings, transcripts)
- Submit the Marketplace listing (needs the public, verified, hosted App β your step)
ShipIT Forge is original open-source code. It does not copy or reuse any proprietary source. It follows the same public, event-driven pattern as other GitHub coding bots, implemented from scratch.
Issues and PRs welcome! Read CONTRIBUTING.md for the dev setup, project layout,
how to add a provider, and the PR checklist. Use the issue templates (π bug / π‘ feature) when
opening an issue. Run npm test before pushing β and feel free to let Forge review your PR. π
mainis protected: every change lands via PR, ShipIT Forge auto-reviews it (security + code), and a maintainer gives the final approval.
MIT Β© Rahul Raj
Autonomous GitHub coding agent β fixes issues, opens PRs, reviews code with a security lens.
π Website Β Β·Β π Examples Β Β·Β π Docs Β Β·Β β GitHub
Built by Rahul Raj Β· MIT licensed Β· Made with π¨