An open-source AI developer agent that turns repository tasks into reviewable code changes.
Built by HarshitEthic · Open source · MIT licensed
PatchPilot is a local-first developer tool for giving an AI agent a real Git repository and a concrete engineering task. It analyzes the codebase, creates an implementation plan, generates structured file edits, applies them in an isolated workspace, runs detected tests, and exposes the resulting Git diff for review.
It is designed to sit between an issue and a pull request — with the developer kept in control of the final change.
┌────────────────────┐
│ GitHub repository │
└─────────┬──────────┘
↓
┌────────────────────┐
│ Task / GitHub issue│
└─────────┬──────────┘
↓
┌────────────────────┐
│ Analyze repository │
└─────────┬──────────┘
↓
┌────────────────────┐
│ Implementation plan│
└─────────┬──────────┘
↓
┌────────────────────┐
│ Create isolated │
│ Git branch │
└─────────┬──────────┘
↓
┌────────────────────┐
│ Generate file edits│
└─────────┬──────────┘
↓
┌────────────────────┐
│ Apply changes │
└─────────┬──────────┘
↓
┌────────────────────┐
│ Run tests │
└─────────┬──────────┘
↓
┌────────────────────┐
│ Repair if needed │
└─────────┬──────────┘
↓
┌────────────────────┐
│ Review Git diff │
└────────────────────┘
- 🧠 Repository-aware task planning
- ✍️ Structured code/file editing instead of trusting raw model-generated diffs
- 🧪 Automatic test-command detection with fail-closed, isolated Docker execution
- 🔁 Limited repair loop when tests fail
- 🌿 Automatic isolated Git branch per run
- ✅ Explicit workspace commit API with per-commit author identity
- 🐙 GitHub issue import via API
- 📦 Isolated per-run workspaces
- 🔍 Reviewable Git diffs
- 🏠 Local-first LLM support with Ollama
- 🔌 OpenAI/OpenRouter-compatible provider support
- ⚡ FastAPI backend + lightweight web UI
- 🐳 Local Docker sandbox for test execution (requires a separate local Docker daemon)
PatchPilot can now turn a GitHub issue into an agent task instead of making you copy the issue manually.
POST /api/import-issue
Content-Type: application/json
{
"repo": "owner/project",
"issue_number": 42
}The response contains the issue title, description, URL, and a normalized task string ready for the agent.
A direct lookup is also available:
GET /api/github/issue?repo=owner/project&issue_number=42Set GITHUB_TOKEN in backend/.env before using these endpoints. The token is never returned by the API.
Every agent run now creates a branch before applying changes:
main
└── patchpilot/fix-login-a1b2c3d4
├── AI edits
├── tests
└── reviewable diff
You can provide a branch name in the run request:
{
"repo_url": "https://github.com/owner/project.git",
"task": "Fix the expired-session redirect",
"branch_name": "fix/expired-session"
}If omitted, PatchPilot generates a unique patchpilot/... branch name automatically.
PatchPilot can also turn the reviewed workspace diff into a local Git commit:
POST /api/commit
Content-Type: application/json
{
"workspace_id": "<run workspace id>",
"message": "fix: handle expired sessions",
"author_name": "PatchPilot",
"author_email": "patchpilot@localhost"
}The endpoint stages the workspace with git add --all, refuses clean workspaces, creates the commit without modifying global Git identity, and returns the commit SHA and branch.
Important: branches and commits still exist only inside PatchPilot's cloned workspace. PatchPilot does not push to GitHub yet, so remote pull requests remain future roadmap work.
Most AI coding demos stop at "generate some code." PatchPilot is built around the engineering loop that happens after the generation:
understand → change → test → repair → review
The goal is not to replace a developer. The goal is to remove repetitive repository work while keeping the generated change visible and reviewable.
Import an issue directly:
owner/project #42
PatchPilot retrieves the title and description and turns them into an agent task.
Add a /health endpoint that returns the service status as JSON.
Useful for small, well-scoped changes where you still want a human-readable diff before merging.
Extract the duplicated validation logic into a reusable helper.
PatchPilot can make the change inside a temporary workspace and show the resulting diff.
Add unit tests for the password validation edge cases.
Use the planning stage as a fast first pass over an unfamiliar codebase before making the change yourself.
| Endpoint | Method | Purpose |
|---|---|---|
/api/health |
GET | Service health check |
/api/run |
POST | Clone, plan, edit, test, repair, and return a diff |
/api/execute |
POST | Execute a command inside an existing workspace |
/api/workspace |
POST | Inspect workspace files and current diff |
/api/commit |
POST | Stage and commit the current workspace changes |
/api/workspaces |
GET | List valid local workspaces with Git status |
/api/workspaces/{workspace_id} |
DELETE | Delete a workspace (dirty workspaces require force=true) |
/api/workspaces/cleanup |
POST | Preview or execute stale clean-workspace deletion |
/api/github/issue |
GET | Fetch a GitHub issue |
/api/import-issue |
POST | Convert a GitHub issue into an agent task |
/api/openapi-summary |
GET | Return PatchPilot feature metadata |
Workspace cleanup safety: POST /api/workspaces/cleanup with
{"max_age_hours":24} only previews candidates by default. Explicitly send
{"max_age_hours":24,"dry_run":false} to remove clean stale workspaces.
Dirty workspaces and workspaces containing ignored files are always
skipped by bulk cleanup, even with dry_run=false.
Deletion refuses symlinked workspace directories and invalid identifiers.
This is a local-only API: do not expose these endpoints to the public Internet.
The FastAPI application also exposes its generated API documentation when the backend is running:
http://127.0.0.1:8000/docs
┌──────────────────────┐
│ PatchPilot Web UI │
└──────────┬───────────┘
│ HTTP
↓
┌──────────────────────┐
│ FastAPI API │
└──────────┬───────────┘
│
┌─────────────────┼─────────────────┐
↓ ↓ ↓
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Git / Repo │ │ LLM Provider│ │ Test Runner │
│ + Branches │ │ Ollama/API │ │ + git diff │
└─────────────┘ └─────────────┘ └─────────────┘
↑
│
┌─────────────┐
│ GitHub API │
│ Issue import│
└─────────────┘
- Backend: Python, FastAPI
- Agent model: Ollama / OpenAI-compatible APIs
- Default model:
qwen2.5-coder:14b - Repository operations: Git
- GitHub integration: GitHub REST API
- Frontend: HTML, CSS, vanilla JavaScript
- Deployment: Docker / Docker Compose
PatchPilot works especially well as a local tool with Ollama.
git clone https://github.com/harshitethic/PatchPilot.git
cd PatchPilotInstall Ollama from the official installer, then make sure the model is available:
ollama pull qwen2.5-coder:14b
ollama listYou do not need to run ollama serve if the Ollama application/server is already running.
Copy the example environment file:
cd backend
cp .env.example .envThen add a GitHub token:
GITHUB_TOKEN=your_github_token
The token needs permission to read the repositories/issues you want PatchPilot to import. Keep .env private and never commit it.
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python3 -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reloadVerify:
curl http://127.0.0.1:8000/api/healthOpen another terminal:
cd frontend
python3 -m http.server 5500Then open:
http://localhost:5500
Repository:
https://github.com/octocat/Hello-World.git
Task:
Add a README section called "PatchPilot Test" explaining that this repository is being used to test an AI coding agent.
A successful run should produce:
- an implementation plan
- an isolated branch name
- the likely files to change
- a test result
- the applied file changes
- a final Git diff
GitHub issue #42
↓
/api/import-issue
↓
Normalized agent task
↓
/api/run
↓
New isolated branch
↓
AI implementation
↓
Tests + repair loop
↓
Reviewable diff
The local-first agent UI: provide a GitHub repository, describe the task, choose the model/provider, and run the agent.
PatchPilot returns the implementation plan, touched files, validation output, and the resulting Git diff for review.
The backend runs locally and exposes the PatchPilot API on 127.0.0.1:8000.
The frontend can be served locally with a lightweight Python HTTP server.
The backend accepts cross-origin browser calls from the local development UIs
(http://localhost:5500 and http://localhost:5173, including their
127.0.0.1 equivalents). It does not use wildcard CORS or credentialed
cross-origin requests. For a different trusted frontend, set
PATCHPILOT_ALLOWED_ORIGINS=https://trusted.example (comma-separated for
multiple origins). Insecure non-local HTTP origins and wildcards are rejected.
CORS is not authentication or a sandbox. Keep the backend bound to
127.0.0.1; do not expose it to arbitrary users or host untrusted projects
without stronger isolation and authentication.
PatchPilot does not execute repository test scripts on the host. Model-
selected commands and POST /api/execute are dispatched to a separate,
ephemeral Docker container using the isolation policy.
If Docker or the approved test image is unavailable, test execution fails
closed instead of falling back to local execution.
The container runner uses:
- No network access, no capabilities, no privilege escalation, a non-root user and a read-only root filesystem
- Read-only bind mount of the current repository; no host HOME, credentials, Docker socket, or parent workspace directories mounted
- Bounded memory (512 MiB), CPU (1 core), process count (64), temporary disk (64 MiB) and execution time (180 seconds by default)
- Bounded log capture, forced container cleanup after timeout and a strict command parser that never invokes a shell
- Preloaded test images (
docker pull python:3.12-slim-bookwormfor Python);--pull=neverkeeps runtime execution offline
Quick check (local):
docker pull python:3.12-slim-bookworm
python -m pip install -r backend/requirements.txt
PYTHONPATH=backend python -m unittest backend.tests.test_sandbox -vFor deterministic live Docker boundary checks, CI executes
backend/tests/docker_smoke.py with a real
container. Python unittest works in the base image. Project test suites
requiring third-party packages need an administrator-prepared offline
test image (e.g. PATCHPILOT_IMAGE_PYTHON=your-org/approved-image@sha256:...).
Repository files and the model cannot select arbitrary images.
Host Git boundary: Model-generated source edits cannot touch internal Git control files. Backend Git commands ignore repository hooks, filesystem monitor helpers, system/global Git config, credential helpers and unsafe transport protocols. The trusted Git binary receives argv directly without a shell. Regression tests verify that an executable hostile pre-commit hook cannot run during the commit workflow. This is separate from the Docker sandbox for project test commands.
Private diagnostic logs: The unauthenticated API returns only exit codes and
a generic log notice; raw container output is appended to the local
.workspaces/<id>/test-output.log with private file permissions, never
included in a network response. Inspect these files from the host when
debugging. Do not publish them; they may contain secrets printed by project
tests.
Important limits: Docker-based isolation is stronger than an executable allowlist but not a microVM, a proof of kernel confinement, or authentication. Cloning, Git actions and the agent backend still run on the local host. Keep the backend loopback-only, do not mount the Docker socket into the backend container, and do not expose this unauthenticated tool on the public internet. The Compose backend is loopback-published for safety but does not have access to a Docker daemon, so test execution from Compose fails closed by default.
See security boundaries and threat model and the tracked isolation requirements.
- Repository cloning
- Task analysis
- Implementation planning
- Structured file edits
- Test execution
- Repair loop
- Reviewable Git diff
- GitHub issue import
- Automatic isolated branches
- Commit changes from the agent
- Open pull requests automatically
- GitHub App authentication
- Streaming agent events
- File-aware tool calling
- Fail-closed isolated Docker test runner with resource limits and CI smoke tests
- Hardened multi-tenant microVM isolation, auth and deployment threat review
- Human approval gates
- Persistent runs and history
- CLI:
patchpilot run "Fix the auth bug" - Multi-agent code review
PatchPilot is open source and contributions are welcome.
Good places to start:
- improve repository analysis
- add provider adapters
- improve test detection
- strengthen sandboxing
- build the GitHub App / PR workflow
- add language-specific repository tooling
- improve the frontend and developer experience
See the repository issues and roadmap for areas to work on.
git checkout -b feature/your-change
# make your changes
# run tests / checks
git diff
git commit -m "feat: your change"Please keep pull requests focused and explain the behavior you changed.
PatchPilot is released under the MIT License.
PatchPilot is built and maintained by HarshitEthic as an open-source developer tooling project.
GitHub: https://github.com/harshitethic
Build tools developers actually want to use. Ship the source.



