@jx-grxf/patchpilot 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +13 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +71 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/agent.d.ts +21 -0
- package/dist/core/agent.js +346 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/codex.d.ts +22 -0
- package/dist/core/codex.js +242 -0
- package/dist/core/codex.js.map +1 -0
- package/dist/core/compute.d.ts +9 -0
- package/dist/core/compute.js +18 -0
- package/dist/core/compute.js.map +1 -0
- package/dist/core/doctor.d.ts +7 -0
- package/dist/core/doctor.js +226 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/env.d.ts +6 -0
- package/dist/core/env.js +103 -0
- package/dist/core/env.js.map +1 -0
- package/dist/core/gemini.d.ts +20 -0
- package/dist/core/gemini.js +177 -0
- package/dist/core/gemini.js.map +1 -0
- package/dist/core/json.d.ts +3 -0
- package/dist/core/json.js +95 -0
- package/dist/core/json.js.map +1 -0
- package/dist/core/modelClient.d.ts +8 -0
- package/dist/core/modelClient.js +42 -0
- package/dist/core/modelClient.js.map +1 -0
- package/dist/core/nvidia.d.ts +19 -0
- package/dist/core/nvidia.js +160 -0
- package/dist/core/nvidia.js.map +1 -0
- package/dist/core/ollama.d.ts +31 -0
- package/dist/core/ollama.js +176 -0
- package/dist/core/ollama.js.map +1 -0
- package/dist/core/openrouter.d.ts +27 -0
- package/dist/core/openrouter.js +168 -0
- package/dist/core/openrouter.js.map +1 -0
- package/dist/core/subagents.d.ts +14 -0
- package/dist/core/subagents.js +89 -0
- package/dist/core/subagents.js.map +1 -0
- package/dist/core/tokenAccounting.d.ts +6 -0
- package/dist/core/tokenAccounting.js +134 -0
- package/dist/core/tokenAccounting.js.map +1 -0
- package/dist/core/types.d.ts +90 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/workspace.d.ts +28 -0
- package/dist/core/workspace.js +616 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/tui/App.d.ts +6 -0
- package/dist/tui/App.js +1717 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/commands.d.ts +14 -0
- package/dist/tui/commands.js +210 -0
- package/dist/tui/commands.js.map +1 -0
- package/dist/tui/components/CommandSuggestions.d.ts +12 -0
- package/dist/tui/components/CommandSuggestions.js +12 -0
- package/dist/tui/components/CommandSuggestions.js.map +1 -0
- package/dist/tui/components/Composer.d.ts +13 -0
- package/dist/tui/components/Composer.js +29 -0
- package/dist/tui/components/Composer.js.map +1 -0
- package/dist/tui/components/Header.d.ts +25 -0
- package/dist/tui/components/Header.js +62 -0
- package/dist/tui/components/Header.js.map +1 -0
- package/dist/tui/components/OnboardingPanel.d.ts +38 -0
- package/dist/tui/components/OnboardingPanel.js +85 -0
- package/dist/tui/components/OnboardingPanel.js.map +1 -0
- package/dist/tui/components/Sidebar.d.ts +22 -0
- package/dist/tui/components/Sidebar.js +133 -0
- package/dist/tui/components/Sidebar.js.map +1 -0
- package/dist/tui/components/Transcript.d.ts +10 -0
- package/dist/tui/components/Transcript.js +111 -0
- package/dist/tui/components/Transcript.js.map +1 -0
- package/dist/tui/format.d.ts +29 -0
- package/dist/tui/format.js +202 -0
- package/dist/tui/format.js.map +1 -0
- package/dist/tui/hosts.d.ts +34 -0
- package/dist/tui/hosts.js +338 -0
- package/dist/tui/hosts.js.map +1 -0
- package/dist/tui/inputRouting.d.ts +8 -0
- package/dist/tui/inputRouting.js +94 -0
- package/dist/tui/inputRouting.js.map +1 -0
- package/dist/tui/platform.d.ts +2 -0
- package/dist/tui/platform.js +13 -0
- package/dist/tui/platform.js.map +1 -0
- package/dist/tui/systemStats.d.ts +25 -0
- package/dist/tui/systemStats.js +88 -0
- package/dist/tui/systemStats.js.map +1 -0
- package/dist/tui/types.d.ts +16 -0
- package/dist/tui/types.js +2 -0
- package/dist/tui/types.js.map +1 -0
- package/docs/showcase/patchpilot-showcase.svg +39 -0
- package/package.json +63 -0
package/.env.example
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Provider options: ollama, gemini, openrouter, nvidia, codex.
|
|
2
|
+
# codex uses your Codex CLI ChatGPT login. Run: codex login
|
|
3
|
+
PATCHPILOT_PROVIDER=codex
|
|
4
|
+
PATCHPILOT_MODEL=gpt-5.5
|
|
5
|
+
|
|
6
|
+
# Only needed for API providers.
|
|
7
|
+
GEMINI_API_KEY=your_gemini_api_key_here
|
|
8
|
+
OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
9
|
+
NVIDIA_API_KEY=your_nvidia_api_key_here
|
|
10
|
+
|
|
11
|
+
# Optional tuning shared by local and API providers.
|
|
12
|
+
PATCHPILOT_NUM_PREDICT=1024
|
|
13
|
+
PATCHPILOT_TEMPERATURE=0.1
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Johannes Grof
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# PatchPilot
|
|
4
|
+
|
|
5
|
+
**A local-first coding-agent TUI that makes repo changes visible, permissioned, and easy to review across local, remote, and cloud model routes.**
|
|
6
|
+
|
|
7
|
+
[](https://github.com/jx-grxf/PatchPilot/actions/workflows/ci.yml)
|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+
[](LICENSE)
|
|
14
|
+
|
|
15
|
+
<p>
|
|
16
|
+
<strong>Visible tools.</strong> Explicit permissions. Local Ollama. Remote Ollama. Gemini. OpenRouter. NVIDIA. Codex.
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Showcase
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<img src="docs/showcase/patchpilot-showcase.svg" alt="PatchPilot terminal interface overview" width="920">
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
PatchPilot is a terminal interface for running coding-agent tasks inside a repository. It shows what the agent is doing, keeps risky actions behind explicit permissions, and supports local Ollama, remote Ollama, Google Gemini, OpenRouter, NVIDIA NIM-compatible endpoints, and Codex CLI OAuth.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Contents
|
|
34
|
+
|
|
35
|
+
- [Highlights](#highlights)
|
|
36
|
+
- [Why This Exists](#why-this-exists)
|
|
37
|
+
- [Quick Start](#quick-start)
|
|
38
|
+
- [Usage](#usage)
|
|
39
|
+
- [Providers](#providers)
|
|
40
|
+
- [Remote Ollama](#remote-ollama)
|
|
41
|
+
- [Safety Model](#safety-model)
|
|
42
|
+
- [Tech Stack](#tech-stack)
|
|
43
|
+
- [Development](#development)
|
|
44
|
+
- [Roadmap](#roadmap)
|
|
45
|
+
- [Security and Legal](#security-and-legal)
|
|
46
|
+
- [License](#license)
|
|
47
|
+
|
|
48
|
+
## Highlights
|
|
49
|
+
|
|
50
|
+
| Feature | What it means |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Local-first by default | Uses Ollama on your own machine unless you choose another route. |
|
|
53
|
+
| Remote GPU workflow | Connect your laptop TUI to an Ollama host on a desktop, LAN, or Tailscale machine. |
|
|
54
|
+
| Cloud provider routes | Gemini, OpenRouter, NVIDIA, and Codex CLI OAuth are available from one TUI. |
|
|
55
|
+
| Guided onboarding | First-run setup walks through local/remote mode, provider auth, host discovery, and model choice. |
|
|
56
|
+
| Observable agent loop | Transcript, tool calls, telemetry, token counts, provider cache hits, latency, and cost estimates are visible. |
|
|
57
|
+
| Explicit permissions | File writes require `--apply`; shell commands require `--allow-shell`. |
|
|
58
|
+
| Workspace boundary | File tools are constrained to the selected project root and block common secret files. |
|
|
59
|
+
| Slash-command palette | Type `/` for browsable commands, provider switching, modes, models, diagnostics, and host selection. |
|
|
60
|
+
| Advisor subagents | Explorer, planner, and reviewer advisor calls can brief the main agent before it edits. |
|
|
61
|
+
| Ollama eject | `/eject` unloads the active Ollama model; `/eject all` clears models PatchPilot used in the session. |
|
|
62
|
+
| CI-ready TypeScript | Strict TypeScript, Vitest, GitHub Actions, and package verification are included. |
|
|
63
|
+
|
|
64
|
+
## Why This Exists
|
|
65
|
+
|
|
66
|
+
Most local coding-agent experiments fall into one of two traps: they are either raw scripts that feel painful to use, or polished tools that hide too much of what is happening. PatchPilot aims for the middle: a practical TUI where every file read, search, proposed write, command, model route, and token/cost signal stays visible.
|
|
67
|
+
|
|
68
|
+
The core workflow is intentionally simple:
|
|
69
|
+
|
|
70
|
+
1. Open a repository.
|
|
71
|
+
2. Pick local, remote, or cloud inference.
|
|
72
|
+
3. Ask for a patch, review, summary, or refactor plan.
|
|
73
|
+
4. Enable writes or shell commands only when the current task needs them.
|
|
74
|
+
5. Review the diff before committing.
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
Install the public CLI globally:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm install -g @jx-grxf/patchpilot
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
For source development, clone it, install dependencies, build it, and link the local CLI:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
git clone https://github.com/jx-grxf/PatchPilot.git
|
|
88
|
+
cd PatchPilot
|
|
89
|
+
npm install
|
|
90
|
+
npm run build
|
|
91
|
+
npm link
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For local Ollama inference:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
ollama pull qwen2.5-coder:7b
|
|
98
|
+
patchpilot doctor
|
|
99
|
+
patchpilot
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Then type a task inside the TUI:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
summarize this repository and point out the riskiest files
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
For a one-shot task from a different repository:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
cd /path/to/your/project
|
|
112
|
+
patchpilot "find likely test gaps in this repo"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Use build permissions only when you intentionally want PatchPilot to modify files or run commands:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
patchpilot "add tests for the parser" --apply --allow-shell
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
API keys are stored by onboarding in `~/.patchpilot/.env`.
|
|
122
|
+
|
|
123
|
+
## Usage
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
patchpilot [task] [options]
|
|
127
|
+
patchpilot doctor [options]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
| Option | Description |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `--workspace <path>` | Project root the agent may inspect. Defaults to the current directory. |
|
|
133
|
+
| `--provider <name>` | Model provider route. Supports `ollama`, `gemini`/`google`, `openrouter`/`open-router`, `nvidia`/`nim`, and `codex`/`openai`/`openai-codex`. |
|
|
134
|
+
| `--model <name>` | Model name for the selected provider. |
|
|
135
|
+
| `--ollama-url <url>` | Ollama base URL. Defaults to `http://127.0.0.1:11434`. |
|
|
136
|
+
| `--steps <count>` | Maximum agent loop steps before stopping. |
|
|
137
|
+
| `--thinking <mode>` | Step-budget mode: `fixed` or `adaptive`. |
|
|
138
|
+
| `--reasoning <effort>` | Provider reasoning effort: `low`, `medium`, `high`, `xhigh`, or `adaptive`. |
|
|
139
|
+
| `--apply` | Allows file writes inside the workspace. |
|
|
140
|
+
| `--allow-shell` | Allows shell commands inside the workspace. |
|
|
141
|
+
| `--no-subagents` | Disables explorer/planner/reviewer advisor calls for faster runs. |
|
|
142
|
+
|
|
143
|
+
Useful slash commands inside the TUI:
|
|
144
|
+
|
|
145
|
+
| Command | Description |
|
|
146
|
+
|---|---|
|
|
147
|
+
| `/help` | Show available commands. |
|
|
148
|
+
| `/help <command>` | Explain one command, for example `/help think` or `/help model`. |
|
|
149
|
+
| `/onboarding` | Open guided provider/auth/model setup. |
|
|
150
|
+
| `/mode plan` | Read-only planning mode. |
|
|
151
|
+
| `/mode build` | Implementation mode; writes and shell can still be toggled separately. |
|
|
152
|
+
| `/think fixed\|adaptive` | Switch between fixed and adaptive step budgets. |
|
|
153
|
+
| `/reasoning low\|medium\|high\|xhigh\|adaptive` | Set provider reasoning effort where supported. |
|
|
154
|
+
| `/write on\|off` | Enable or disable workspace writes. |
|
|
155
|
+
| `/shell on\|off` | Enable or disable shell commands. |
|
|
156
|
+
| `/agents on\|off` | Enable or disable advisor subagents. |
|
|
157
|
+
| `/provider ollama\|gemini\|openrouter\|nvidia\|codex` | Switch inference provider. |
|
|
158
|
+
| `/model <query>` | Search and switch the model for the current provider. |
|
|
159
|
+
| `/models [query\|number]` | Refresh, search, browse, or select provider models. |
|
|
160
|
+
| `/connect` | Scan LAN/Tailscale for reachable Ollama hosts. |
|
|
161
|
+
| `/connect <url>` | Connect to a specific Ollama host. |
|
|
162
|
+
| `/eject [model\|all]` | Unload Ollama model(s) from the active host. |
|
|
163
|
+
| `/hosts` | Re-scan reachable Ollama hosts. |
|
|
164
|
+
| `/doctor` | Run provider diagnostics from inside the TUI. |
|
|
165
|
+
| `/clear` | Clear the current transcript. |
|
|
166
|
+
| `/exit` | Quit PatchPilot. |
|
|
167
|
+
|
|
168
|
+
The transcript and sidebar have internal scroll areas. With an empty prompt, use left/right to choose the sidebar or transcript, then Page Up/Page Down and Home/End to navigate long sessions.
|
|
169
|
+
|
|
170
|
+
## Providers
|
|
171
|
+
|
|
172
|
+
| Provider route | Accepted values | Default model | Best for | Setup |
|
|
173
|
+
|---|---|---|---|---|
|
|
174
|
+
| Ollama local | `ollama` | `qwen2.5-coder:7b` | Private local coding work and offline experiments. | Install Ollama, pull a model, run `patchpilot`. |
|
|
175
|
+
| Ollama remote | `ollama` with `--ollama-url` or `/connect` | Host model inventory | Laptop editing with a stronger desktop/server GPU. | Expose Ollama on the host, then use `/connect` or `--ollama-url`. |
|
|
176
|
+
| Google Gemini | `gemini`, `google` | `gemini-2.5-flash` | Fast cloud inference through a Gemini API key. | Store `GEMINI_API_KEY` in `~/.patchpilot/.env` or use onboarding. |
|
|
177
|
+
| OpenRouter | `openrouter`, `open-router` | `openrouter/auto` | Broad model routing, auto model selection, and free variants. | Store `OPENROUTER_API_KEY` in `~/.patchpilot/.env` or use onboarding. |
|
|
178
|
+
| NVIDIA | `nvidia`, `nim` | `meta/llama-3.1-70b-instruct` | NVIDIA NIM OpenAI-compatible endpoints. | Store `NVIDIA_API_KEY` in `~/.patchpilot/.env` or use onboarding. |
|
|
179
|
+
| Codex CLI | `codex`, `openai`, `openai-codex` | `gpt-5.5` | Using an existing Codex CLI OAuth login. | Run `codex login`, then `patchpilot --provider codex`. |
|
|
180
|
+
|
|
181
|
+
Examples:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
patchpilot --provider ollama --model qwen2.5-coder:7b
|
|
185
|
+
patchpilot --provider gemini --model gemini-2.5-flash
|
|
186
|
+
patchpilot --provider openrouter --model openrouter/auto
|
|
187
|
+
patchpilot --provider nvidia --model meta/llama-3.1-70b-instruct
|
|
188
|
+
patchpilot --provider codex --model gpt-5.5
|
|
189
|
+
patchpilot --provider google --model gemini-2.5-flash
|
|
190
|
+
patchpilot --provider nim --model meta/llama-3.1-70b-instruct
|
|
191
|
+
patchpilot --provider openai --model gpt-5.5
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Provider diagnostics:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
patchpilot doctor --provider ollama
|
|
198
|
+
patchpilot doctor --provider gemini
|
|
199
|
+
patchpilot doctor --provider openrouter
|
|
200
|
+
patchpilot doctor --provider nvidia
|
|
201
|
+
patchpilot doctor --provider codex
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
PatchPilot caches model discovery for a short TTL inside the running TUI, so normal prompts do not re-query providers every time. Run `/models` again when you intentionally want to refresh the visible list.
|
|
205
|
+
|
|
206
|
+
PatchPilot reads provider cache telemetry when the provider reports it, for example Codex cached input tokens or OpenRouter `prompt_tokens_details.cached_tokens`, then displays cache hit rate as `cached / input`.
|
|
207
|
+
|
|
208
|
+
OpenRouter `:free` models are rate-limited by OpenRouter. PatchPilot warns when a selected model ID ends in `:free`.
|
|
209
|
+
|
|
210
|
+
## Remote Ollama
|
|
211
|
+
|
|
212
|
+
PatchPilot can run the TUI and workspace tools on one machine while sending model requests to Ollama on another machine. This is useful when your desktop has the GPU and your laptop is where you edit code.
|
|
213
|
+
|
|
214
|
+
Inside PatchPilot:
|
|
215
|
+
|
|
216
|
+
```text
|
|
217
|
+
/connect
|
|
218
|
+
/connect 1
|
|
219
|
+
/connect http://192.168.1.50:11434
|
|
220
|
+
/connect local
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
From the shell:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
patchpilot --ollama-url http://<host-ip>:11434
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
On a Windows desktop or remote host, expose Ollama on your private network:
|
|
230
|
+
|
|
231
|
+
1. Quit Ollama.
|
|
232
|
+
2. Set `OLLAMA_HOST` to `0.0.0.0:11434`.
|
|
233
|
+
3. Start Ollama again.
|
|
234
|
+
4. Allow inbound TCP traffic on port `11434` only on trusted private networks.
|
|
235
|
+
|
|
236
|
+
PatchPilot verifies candidates with Ollama's `/api/version` endpoint before listing them. It does not move file reads, writes, Git, or test commands to the remote host; only model requests are routed there.
|
|
237
|
+
|
|
238
|
+
For smaller local machines, reduce the request budget before starting PatchPilot:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
PATCHPILOT_NUM_CTX=4096 PATCHPILOT_NUM_PREDICT=768 patchpilot
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Safety Model
|
|
245
|
+
|
|
246
|
+
PatchPilot is designed to keep powerful actions boring and reviewable:
|
|
247
|
+
|
|
248
|
+
- File access is constrained to one workspace root.
|
|
249
|
+
- Secret-like files such as `.env`, `.npmrc`, SSH keys, and `.netrc` are blocked from normal file tools.
|
|
250
|
+
- Writes are disabled unless `--apply` is set.
|
|
251
|
+
- Shell commands are disabled unless `--allow-shell` is set.
|
|
252
|
+
- Shell execution uses a restricted single-command runner.
|
|
253
|
+
- Provider config is stored in `~/.patchpilot/.env`, not in the current repository by default.
|
|
254
|
+
- Tool output is shown in the transcript and fed back into the agent in clipped form.
|
|
255
|
+
- Cloud providers may process prompts and context remotely under their own terms.
|
|
256
|
+
|
|
257
|
+
This is still experimental agent tooling. Review diffs, avoid sensitive repositories when using cloud providers, and do not enable write or shell permissions casually.
|
|
258
|
+
|
|
259
|
+
## Tech Stack
|
|
260
|
+
|
|
261
|
+
| Layer | Technologies |
|
|
262
|
+
|---|---|
|
|
263
|
+
| Language | TypeScript, strict NodeNext ESM |
|
|
264
|
+
| Runtime | Node.js 22+ |
|
|
265
|
+
| TUI | Ink, React, ink-text-input |
|
|
266
|
+
| Agent protocol | JSON command envelope validated with Zod |
|
|
267
|
+
| Providers | Ollama chat API, Gemini generateContent API, OpenRouter OpenAI-compatible API, NVIDIA OpenAI-compatible API, Codex CLI OAuth backend |
|
|
268
|
+
| Tests | Vitest |
|
|
269
|
+
| CI | GitHub Actions |
|
|
270
|
+
|
|
271
|
+
More detail: [docs/architecture.md](docs/architecture.md)
|
|
272
|
+
|
|
273
|
+
## Development
|
|
274
|
+
|
|
275
|
+
Run the TUI from source:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
npm run dev -- "summarize this repository"
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Typecheck, test, and build:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
npm run typecheck
|
|
285
|
+
npm test
|
|
286
|
+
npm run build
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
If Vitest fails because a native optional dependency was installed incorrectly, run `npm ci` again before debugging PatchPilot itself.
|
|
290
|
+
|
|
291
|
+
## Roadmap
|
|
292
|
+
|
|
293
|
+
| Area | Planned work |
|
|
294
|
+
|---|---|
|
|
295
|
+
| Patch review | Rich diff preview before writes. |
|
|
296
|
+
| Permissions | Interactive approve/deny prompts per risky tool call. |
|
|
297
|
+
| Agents | Dedicated editor and test-runner roles with hard tool boundaries. |
|
|
298
|
+
| Memory | Repository summaries and local task state. |
|
|
299
|
+
| Model support | Native Ollama tool calling when model support is reliable. |
|
|
300
|
+
| Distribution | Signed macOS and Windows desktop shell with the CLI as a sidecar. |
|
|
301
|
+
| Efficiency | More token-cache-aware prompts and provider-specific cost reporting. |
|
|
302
|
+
|
|
303
|
+
## Security and Legal
|
|
304
|
+
|
|
305
|
+
PatchPilot can read files, write files, and run shell commands when you enable those capabilities. Use it only in repositories and environments you trust.
|
|
306
|
+
|
|
307
|
+
- Security reports: please use GitHub Security Advisories or contact the maintainer privately with reproduction steps and impact.
|
|
308
|
+
- License: this project is provided under the [MIT License](LICENSE).
|
|
309
|
+
- Warranty: the software is provided "AS IS", without warranties of any kind.
|
|
310
|
+
- Third-party services: model providers and external services are subject to their own terms, privacy policies, retention settings, and regional compliance requirements.
|
|
311
|
+
|
|
312
|
+
## License
|
|
313
|
+
|
|
314
|
+
PatchPilot is released under the [MIT License](LICENSE).
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { render } from "ink";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { defaultCodexModel } from "./core/codex.js";
|
|
7
|
+
import { loadPatchPilotEnv } from "./core/env.js";
|
|
8
|
+
import { defaultGeminiModel } from "./core/gemini.js";
|
|
9
|
+
import { normalizeModelProvider, readModelProvider } from "./core/modelClient.js";
|
|
10
|
+
import { defaultNvidiaModel } from "./core/nvidia.js";
|
|
11
|
+
import { runDoctor } from "./core/doctor.js";
|
|
12
|
+
import { defaultOllamaModel, resolveOllamaBaseUrl } from "./core/ollama.js";
|
|
13
|
+
import { defaultOpenRouterModel } from "./core/openrouter.js";
|
|
14
|
+
import { App } from "./tui/App.js";
|
|
15
|
+
loadPatchPilotEnv();
|
|
16
|
+
const defaultOllamaUrl = resolveOllamaBaseUrl();
|
|
17
|
+
const defaultProvider = readModelProvider();
|
|
18
|
+
const defaultModel = process.env.PATCHPILOT_MODEL ??
|
|
19
|
+
(defaultProvider === "gemini"
|
|
20
|
+
? defaultGeminiModel
|
|
21
|
+
: defaultProvider === "openrouter"
|
|
22
|
+
? defaultOpenRouterModel
|
|
23
|
+
: defaultProvider === "nvidia"
|
|
24
|
+
? defaultNvidiaModel
|
|
25
|
+
: defaultProvider === "codex"
|
|
26
|
+
? defaultCodexModel
|
|
27
|
+
: defaultOllamaModel);
|
|
28
|
+
const program = new Command();
|
|
29
|
+
program.enablePositionalOptions();
|
|
30
|
+
program
|
|
31
|
+
.name("patchpilot")
|
|
32
|
+
.description("Local-first coding agent TUI powered by Ollama and OpenAI-compatible providers.")
|
|
33
|
+
.version("0.2.0");
|
|
34
|
+
program
|
|
35
|
+
.command("doctor")
|
|
36
|
+
.description("Check local PatchPilot requirements.")
|
|
37
|
+
.option("--provider <name>", "Model provider: ollama, gemini, openrouter, nvidia, or codex.", defaultProvider)
|
|
38
|
+
.option("--check-url <url>", "Ollama base URL to verify", defaultOllamaUrl)
|
|
39
|
+
.option("--ollama-url <url>", "Alias for --check-url.")
|
|
40
|
+
.option("--check-model <name>", "Model name to verify", defaultModel)
|
|
41
|
+
.option("--model <name>", "Alias for --check-model.")
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
const results = await runDoctor(normalizeModelProvider(options.provider), options.ollamaUrl ?? options.checkUrl, options.model ?? options.checkModel);
|
|
44
|
+
for (const result of results) {
|
|
45
|
+
const marker = result.ok ? "ok" : "fail";
|
|
46
|
+
console.log(`${marker.padEnd(5)} ${result.name}: ${result.details}`);
|
|
47
|
+
}
|
|
48
|
+
process.exitCode = results.every((result) => result.ok) ? 0 : 1;
|
|
49
|
+
});
|
|
50
|
+
program
|
|
51
|
+
.argument("[task...]", "Task for the local coding agent.")
|
|
52
|
+
.option("--workspace <path>", "Workspace root", process.cwd())
|
|
53
|
+
.option("--provider <name>", "Model provider: ollama, gemini, openrouter, nvidia, or codex.", defaultProvider)
|
|
54
|
+
.option("--model <name>", "Model name", defaultModel)
|
|
55
|
+
.option("--ollama-url <url>", "Ollama base URL", defaultOllamaUrl)
|
|
56
|
+
.option("--steps <count>", "Maximum agent steps", "8")
|
|
57
|
+
.option("--thinking <mode>", "Thinking budget mode: fixed or adaptive.", process.env.PATCHPILOT_THINKING_MODE ?? "fixed")
|
|
58
|
+
.option("--reasoning <effort>", "Provider reasoning effort: low, medium, high, xhigh, or adaptive.", process.env.PATCHPILOT_REASONING_EFFORT ?? "medium")
|
|
59
|
+
.option("--apply", "Allow file writes inside the workspace.", false)
|
|
60
|
+
.option("--allow-shell", "Allow shell commands inside the workspace.", false)
|
|
61
|
+
.option("--no-subagents", "Disable planner and reviewer subagents for faster local runs.")
|
|
62
|
+
.action((taskParts, options) => {
|
|
63
|
+
const workspace = path.resolve(String(options.workspace));
|
|
64
|
+
const maxSteps = Number.parseInt(String(options.steps), 10);
|
|
65
|
+
render(_jsx(App, { initialTask: taskParts.join(" ").trim() || undefined, provider: readModelProvider({ PATCHPILOT_PROVIDER: String(options.provider) }), model: String(options.model), ollamaUrl: String(options.ollamaUrl), workspace: workspace, allowWrite: Boolean(options.apply), allowShell: Boolean(options.allowShell), maxSteps: Number.isFinite(maxSteps) ? maxSteps : 8, thinkingMode: String(options.thinking) === "adaptive" ? "adaptive" : "fixed", reasoningEffort: readReasoningEffort(String(options.reasoning)), subagents: options.subagents !== false }));
|
|
66
|
+
});
|
|
67
|
+
await program.parseAsync(process.argv);
|
|
68
|
+
function readReasoningEffort(value) {
|
|
69
|
+
return value === "low" || value === "medium" || value === "high" || value === "xhigh" || value === "adaptive" ? value : "medium";
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AgentEvent, ModelProvider, ReasoningEffort } from "./types.js";
|
|
2
|
+
export type AgentRunnerOptions = {
|
|
3
|
+
provider: ModelProvider;
|
|
4
|
+
model: string;
|
|
5
|
+
ollamaUrl: string;
|
|
6
|
+
workspace: string;
|
|
7
|
+
allowWrite: boolean;
|
|
8
|
+
allowShell: boolean;
|
|
9
|
+
maxSteps: number;
|
|
10
|
+
thinkingMode: "fixed" | "adaptive";
|
|
11
|
+
reasoningEffort: ReasoningEffort | "adaptive";
|
|
12
|
+
subagents: boolean;
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
};
|
|
15
|
+
export declare class AgentRunner {
|
|
16
|
+
private readonly client;
|
|
17
|
+
private readonly tools;
|
|
18
|
+
private readonly options;
|
|
19
|
+
constructor(options: AgentRunnerOptions);
|
|
20
|
+
run(task: string): AsyncGenerator<AgentEvent>;
|
|
21
|
+
}
|