surgent 0.7.0-alpha.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/LICENSE +21 -0
- package/README.md +407 -0
- package/bin/surgent.js +211 -0
- package/dist/optimizers/LICENSE +21 -0
- package/dist/optimizers/index.js +1984 -0
- package/dist/optimizers/index.js.map +7 -0
- package/dist/optimizers/package.json +31 -0
- package/package.json +45 -0
- package/src/agent/built-in/documenter.md +58 -0
- package/src/agent/built-in/general.md +107 -0
- package/src/agent/built-in/planner.md +73 -0
- package/src/agent/built-in/scout.md +97 -0
- package/src/agent/command.ts +140 -0
- package/src/agent/helpers.ts +95 -0
- package/src/agent/index.ts +9 -0
- package/src/agent/storage.ts +287 -0
- package/src/agent/types.ts +28 -0
- package/src/checkpoint/git.ts +173 -0
- package/src/checkpoint/index.ts +117 -0
- package/src/checkpoint/snapshot.ts +28 -0
- package/src/checkpoint/stage.ts +59 -0
- package/src/checkpoint/store.ts +108 -0
- package/src/cleanup/checkpoint.ts +31 -0
- package/src/cleanup/helpers.ts +24 -0
- package/src/cleanup/index.ts +21 -0
- package/src/cleanup/permission.ts +74 -0
- package/src/cleanup/subsession.ts +46 -0
- package/src/commands/helpers.ts +217 -0
- package/src/commands/index.ts +79 -0
- package/src/commands/render.ts +95 -0
- package/src/commands/types.ts +11 -0
- package/src/mcp-client/call-tool.ts +143 -0
- package/src/mcp-client/client.ts +90 -0
- package/src/mcp-client/command.ts +257 -0
- package/src/mcp-client/helpers.ts +153 -0
- package/src/mcp-client/index.ts +21 -0
- package/src/mcp-client/list-tools.ts +84 -0
- package/src/mcp-client/storage.ts +190 -0
- package/src/mcp-client/types.ts +34 -0
- package/src/mcp-client/validation.ts +115 -0
- package/src/optimizers/compactor/bash.ts +159 -0
- package/src/optimizers/compactor/grep.ts +141 -0
- package/src/optimizers/compactor/index.ts +132 -0
- package/src/optimizers/deduplicator/helpers.ts +75 -0
- package/src/optimizers/deduplicator/index.ts +23 -0
- package/src/optimizers/deduplicator/resources.ts +77 -0
- package/src/optimizers/deduplicator/state.ts +119 -0
- package/src/optimizers/deduplicator/types.ts +14 -0
- package/src/optimizers/entries.ts +104 -0
- package/src/optimizers/index.ts +17 -0
- package/src/optimizers/inspector/helpers.ts +60 -0
- package/src/optimizers/inspector/index.ts +89 -0
- package/src/optimizers/inspector/inspect.ts +88 -0
- package/src/optimizers/inspector/types.ts +7 -0
- package/src/optimizers/languages/go.ts +79 -0
- package/src/optimizers/languages/grammar.ts +200 -0
- package/src/optimizers/languages/index.ts +75 -0
- package/src/optimizers/languages/java.ts +64 -0
- package/src/optimizers/languages/python.ts +63 -0
- package/src/optimizers/languages/rust.ts +71 -0
- package/src/optimizers/languages/symbols.ts +95 -0
- package/src/optimizers/languages/tree-sitter-languages.d.ts +23 -0
- package/src/optimizers/languages/types.ts +134 -0
- package/src/optimizers/languages/typescript.ts +116 -0
- package/src/optimizers/mapper/files.ts +94 -0
- package/src/optimizers/mapper/index.ts +133 -0
- package/src/optimizers/mapper/types.ts +6 -0
- package/src/optimizers/pruner/cleanup.ts +121 -0
- package/src/optimizers/pruner/context.ts +46 -0
- package/src/optimizers/pruner/index.ts +45 -0
- package/src/optimizers/pruner/session.ts +34 -0
- package/src/optimizers/pruner/types.ts +18 -0
- package/src/permission/bash.ts +124 -0
- package/src/permission/command.ts +111 -0
- package/src/permission/components/prompt.ts +255 -0
- package/src/permission/components/rules-list.ts +342 -0
- package/src/permission/constants.ts +48 -0
- package/src/permission/helpers.ts +156 -0
- package/src/permission/index.ts +134 -0
- package/src/permission/pattern.ts +51 -0
- package/src/permission/piignore.ts +148 -0
- package/src/permission/precedence.ts +54 -0
- package/src/permission/resolution.ts +116 -0
- package/src/permission/storage.ts +142 -0
- package/src/permission/types.ts +57 -0
- package/src/questionnaire/component.ts +357 -0
- package/src/questionnaire/helpers.ts +220 -0
- package/src/questionnaire/index.ts +67 -0
- package/src/questionnaire/schemas.ts +50 -0
- package/src/questionnaire/types.ts +47 -0
- package/src/redactor/index.ts +34 -0
- package/src/redactor/patterns.ts +234 -0
- package/src/redactor/secrets.ts +113 -0
- package/src/subagent/helpers.ts +93 -0
- package/src/subagent/index.ts +81 -0
- package/src/subagent/storage.ts +100 -0
- package/src/subagent/subsession.ts +266 -0
- package/src/subagent/types.ts +83 -0
- package/src/subagent/validation.ts +100 -0
- package/src/ui/components/action-select-list.ts +165 -0
- package/src/ui/components/bash-mode.ts +281 -0
- package/src/ui/components/extended-select-list.ts +166 -0
- package/src/ui/components/form-field.ts +184 -0
- package/src/ui/components/form.ts +179 -0
- package/src/ui/components/frame.ts +60 -0
- package/src/ui/components/input-mode-indicator.ts +64 -0
- package/src/ui/components/keybound.ts +150 -0
- package/src/ui/components/lines.ts +27 -0
- package/src/ui/components/placeholder-input.ts +59 -0
- package/src/ui/components/scoped-input.ts +78 -0
- package/src/ui/components/scrollable-view.ts +155 -0
- package/src/ui/index.ts +40 -0
- package/src/utils.ts +206 -0
- package/src/web-tools/index.ts +15 -0
- package/src/web-tools/providers/brave.ts +55 -0
- package/src/web-tools/providers/firecrawl.ts +66 -0
- package/src/web-tools/providers/index.ts +50 -0
- package/src/web-tools/providers/jina.ts +48 -0
- package/src/web-tools/providers/native.ts +57 -0
- package/src/web-tools/providers/tavily.ts +56 -0
- package/src/web-tools/settings.ts +15 -0
- package/src/web-tools/web-fetch/helpers.ts +66 -0
- package/src/web-tools/web-fetch/index.ts +91 -0
- package/src/web-tools/web-fetch/parser.ts +51 -0
- package/src/web-tools/web-fetch/storage.ts +65 -0
- package/src/web-tools/web-fetch/types.ts +8 -0
- package/src/web-tools/web-login/helpers.ts +79 -0
- package/src/web-tools/web-login/index.ts +100 -0
- package/src/web-tools/web-login/types.ts +4 -0
- package/src/web-tools/web-search/helpers.ts +36 -0
- package/src/web-tools/web-search/index.ts +98 -0
- package/src/web-tools/web-search/types.ts +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 surgent
|
|
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,407 @@
|
|
|
1
|
+
# surgent
|
|
2
|
+
|
|
3
|
+
**A terminal coding agent that keeps context focused, delegates specialized work, and puts you in control of every change.**
|
|
4
|
+
|
|
5
|
+
surgent works inside an existing repository. Give it an engineering task and it can inspect the codebase, make a plan, edit files, run commands and tests, research the web, and report the result without forcing you to manage the agent's internal machinery.
|
|
6
|
+
|
|
7
|
+
It is designed for software engineers who want an agent that feels at home in a terminal: direct enough for quick fixes, structured enough for multi-step work, and careful enough for real repositories.
|
|
8
|
+
|
|
9
|
+
## Why surgent
|
|
10
|
+
|
|
11
|
+
- **More useful context.** surgent navigates code structurally and reduces repetitive tool output so the model can spend more of its context on the task.
|
|
12
|
+
- **Repository-grounded work.** Project instructions, source files, command output, and session history stay connected to the work at hand.
|
|
13
|
+
- **Specialists when they help.** Built-in agents cover implementation, planning, codebase research, and documentation. The main agent can delegate focused work instead of filling one conversation with every detail.
|
|
14
|
+
- **Plans that do not crowd the coding session.** Explore and refine a plan in a separate session, then hand the finished plan back for implementation.
|
|
15
|
+
- **Explicit safety controls.** Review actions as they happen, save reusable permission rules, block sensitive paths, or switch modes when you need more or less autonomy.
|
|
16
|
+
- **Recoverable edits.** In Git repositories, surgent checkpoints edits made through its file tools and can restore the corresponding code state when you rewind or fork a session.
|
|
17
|
+
- **Model freedom.** Use models from Google, Anthropic, OpenAI, OpenRouter, Bedrock, and many other supported providers.
|
|
18
|
+
- **Extensible tooling.** Connect local or remote MCP servers and give the agent access to web search and URL fetching.
|
|
19
|
+
|
|
20
|
+
## What you can do
|
|
21
|
+
|
|
22
|
+
surgent is useful anywhere the task is easier to describe than to execute manually:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
Find the race condition behind the flaky queue tests, fix the root cause,
|
|
26
|
+
and run the smallest test set that proves the behavior.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
Trace how authentication state reaches the API client. Explain the current
|
|
31
|
+
design and identify places where an expired token can still be used.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
Add CSV export to the reporting command. Follow existing CLI conventions,
|
|
36
|
+
update tests, and document the new flag.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
Review this branch for correctness regressions. Do not modify files.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
- Node.js 22.19 or newer
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
Install surgent globally from npm:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm install -g surgent
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Confirm the command is available:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
surgent --version
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Starting surgent**
|
|
62
|
+
|
|
63
|
+
From the repository you want to work on, run:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cd /path/to/your-project
|
|
67
|
+
surgent
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Update or remove**
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm install -g surgent@latest # update
|
|
74
|
+
npm uninstall -g surgent # remove
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Optimizers for Pi
|
|
78
|
+
|
|
79
|
+
`@surgent/optimizers` is a Pi extension package that keeps code navigation and tool output focused, while being cache friendly. This extension is already built into surgent.
|
|
80
|
+
|
|
81
|
+
- `code_map` and `inspect` use Tree-sitter to navigate symbols and declarations in TypeScript/JavaScript, Python, Go, Java, and Rust.
|
|
82
|
+
- It compacts noisy Bash and grep output.
|
|
83
|
+
- It deduplicates previously read resource content, removes superseded `read` or `inspect` results
|
|
84
|
+
- It prunes empty `ls` or `find` results from context.
|
|
85
|
+
|
|
86
|
+
To use the optimizers with Pi instead of surgent, install the standalone package:
|
|
87
|
+
|
|
88
|
+
> **Important:** Install either surgent or `@surgent/optimizers` on a machine or configuration, not both. Surgent already includes the optimizers; installing both registers duplicate tools and hooks.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pi install npm:@surgent/optimizers
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Verify the package is installed:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pi list
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Start Pi in a repository, then ask the agent to use `code_map` to locate symbols and `inspect` to read a selected declaration.
|
|
101
|
+
|
|
102
|
+
## Connect a model
|
|
103
|
+
|
|
104
|
+
surgent defaults to the Google provider. The quickest setup is a Gemini API key:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
export GEMINI_API_KEY="your-api-key"
|
|
108
|
+
surgent --provider google
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Other common choices work the same way:
|
|
112
|
+
|
|
113
|
+
| Provider | Environment variable | Start command |
|
|
114
|
+
| ---------- | -------------------- | ------------------------------- |
|
|
115
|
+
| Anthropic | `ANTHROPIC_API_KEY` | `surgent --provider anthropic` |
|
|
116
|
+
| OpenAI | `OPENAI_API_KEY` | `surgent --provider openai` |
|
|
117
|
+
| OpenRouter | `OPENROUTER_API_KEY` | `surgent --provider openrouter` |
|
|
118
|
+
|
|
119
|
+
List models available to your current installation:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
surgent --list-models
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Select a model directly with a provider-qualified model ID:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
surgent --model <provider>/<model-id>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Provider keys are secrets. Keep them in your shell environment or a secret manager, never in the repository.
|
|
132
|
+
|
|
133
|
+
## Quick start
|
|
134
|
+
|
|
135
|
+
For a new repository, initialize concise project instructions first:
|
|
136
|
+
|
|
137
|
+
```text
|
|
138
|
+
/init
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`/init` inspects the repository and creates or updates `AGENTS.md` with verified commands, architecture notes, conventions, and project-specific guidance. Future sessions automatically benefit from those instructions.
|
|
142
|
+
|
|
143
|
+
Then describe the outcome you want:
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
Add input validation to the user creation endpoint. Match the existing error
|
|
147
|
+
format, add focused tests, and run them.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
surgent will inspect the relevant code, ask for permission where required, make the changes, validate them, and summarize the result.
|
|
151
|
+
|
|
152
|
+
## Everyday workflows
|
|
153
|
+
|
|
154
|
+
### Start with a task
|
|
155
|
+
|
|
156
|
+
Open the interactive TUI with an initial request:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
surgent "Find and fix the failing type check in the billing module"
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Name a longer-running session so it is easy to find later:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
surgent --name "Refactor billing retries"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Plan before editing
|
|
169
|
+
|
|
170
|
+
Use a separate planning session for work that spans components or has unclear tradeoffs:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
/plan Replace the in-memory job scheduler with a durable queue
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
You can review the plan, send feedback, save it for later, or forward the final version into the main session for implementation.
|
|
177
|
+
|
|
178
|
+
Run `/plan` with no arguments to list saved plans. Resume one by selecting it or passing its plan ID:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
/plan <plan-id>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Run a one-shot task
|
|
185
|
+
|
|
186
|
+
Use print mode in scripts or for short, non-interactive work:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
surgent -p "Summarize the public API exposed by src/client"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Perform a read-only review
|
|
193
|
+
|
|
194
|
+
Limit the active tools to read-only operations:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
surgent --tools read,grep,find,ls -p \
|
|
198
|
+
"Review src/auth for correctness and security regressions"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Include files in the first message
|
|
202
|
+
|
|
203
|
+
Prefix a path with `@` to attach text, images, or other relevant files:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
surgent @spec.md @architecture.png "Implement the first milestone"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Resume previous work
|
|
210
|
+
|
|
211
|
+
Continue the most recent session:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
surgent --continue
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Choose from saved sessions:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
surgent --resume
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Sessions can also be forked, exported to HTML, or started without persistence. Run `surgent --help` for the complete set of session options.
|
|
224
|
+
|
|
225
|
+
### Run shell commands from the TUI
|
|
226
|
+
|
|
227
|
+
Start input with `!` to run a shell command and include its result in the conversation:
|
|
228
|
+
|
|
229
|
+
```text
|
|
230
|
+
!npm test
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Start with `!!` to run a command without adding its result to model context:
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
!!git status
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Use `Ctrl+Alt+B` to cycle persistently between prompt input, context-included shell input, and regular shell input.
|
|
240
|
+
|
|
241
|
+
## Interactive commands
|
|
242
|
+
|
|
243
|
+
| Command | Purpose |
|
|
244
|
+
| ----------------------- | ------------------------------------------------------------- |
|
|
245
|
+
| `/init` | Create or update repository-specific `AGENTS.md` instructions |
|
|
246
|
+
| `/plan [request]` | Start, refine, save, or resume an isolated planning session |
|
|
247
|
+
| `/agent` | Select, create, edit, or remove agent profiles |
|
|
248
|
+
| `/permissions` | View and manage file, shell, web, and MCP permission rules |
|
|
249
|
+
| `/mcp` | Add, edit, enable, disable, or remove MCP servers |
|
|
250
|
+
| `/web-login [provider]` | Configure credentials for web search and fetch providers |
|
|
251
|
+
|
|
252
|
+
The bundled agent profiles cover these common roles:
|
|
253
|
+
|
|
254
|
+
| Agent | Best for |
|
|
255
|
+
| ------------ | ------------------------------------------------------------------- |
|
|
256
|
+
| `general` | Implementation, debugging, tests, and command-heavy repository work |
|
|
257
|
+
| `planner` | Repository-grounded plans for complex changes |
|
|
258
|
+
| `scout` | Read-only codebase research and execution tracing |
|
|
259
|
+
| `documenter` | User-facing Markdown and project documentation |
|
|
260
|
+
|
|
261
|
+
Use `/agent` to start a new session with a specialist or create a project-specific or global profile. Profiles can constrain tools, files, shell commands, MCP servers, models, and thinking levels.
|
|
262
|
+
|
|
263
|
+
## Command-line essentials
|
|
264
|
+
|
|
265
|
+
| Option | Purpose |
|
|
266
|
+
| ------------------------- | --------------------------------------------- |
|
|
267
|
+
| `-p`, `--print` | Process a prompt non-interactively and exit |
|
|
268
|
+
| `-c`, `--continue` | Continue the previous session |
|
|
269
|
+
| `-r`, `--resume` | Select a saved session |
|
|
270
|
+
| `--name <name>` | Give a session a memorable name |
|
|
271
|
+
| `--provider <name>` | Select a model provider |
|
|
272
|
+
| `--model <pattern>` | Select a model or provider-qualified model ID |
|
|
273
|
+
| `--thinking <level>` | Set the model thinking level |
|
|
274
|
+
| `--tools <names>` | Enable only the listed tools |
|
|
275
|
+
| `--exclude-tools <names>` | Disable selected tools |
|
|
276
|
+
| `--no-session` | Run without saving session history |
|
|
277
|
+
| `--offline` | Disable startup network operations |
|
|
278
|
+
| `--export <file>` | Export a session as HTML |
|
|
279
|
+
|
|
280
|
+
Run `surgent --help` for all options, supported credential environment variables, and examples.
|
|
281
|
+
|
|
282
|
+
## Permissions and safety
|
|
283
|
+
|
|
284
|
+
surgent has three permission modes. Press `Alt+M` to cycle between them:
|
|
285
|
+
|
|
286
|
+
| Mode | Behavior |
|
|
287
|
+
| ---------- | ------------------------------------------------------------------ |
|
|
288
|
+
| Assistant | Prompts when an action is not already covered by a permission rule |
|
|
289
|
+
| YOLO | Runs actions allowed by the active agent without prompting |
|
|
290
|
+
| Restricted | Limits actions to explicitly allowed access |
|
|
291
|
+
|
|
292
|
+
Use `/permissions` to manage reusable rules for:
|
|
293
|
+
|
|
294
|
+
- File reads and writes
|
|
295
|
+
- Shell commands
|
|
296
|
+
- Web requests
|
|
297
|
+
- MCP tool calls
|
|
298
|
+
|
|
299
|
+
Rules can apply to the current session, the current project, all projects, or permanently. More specific rules take precedence.
|
|
300
|
+
|
|
301
|
+
### Keep paths out of agent reach
|
|
302
|
+
|
|
303
|
+
Add sensitive or irrelevant paths to `.piignore`:
|
|
304
|
+
|
|
305
|
+
```gitignore
|
|
306
|
+
.env*
|
|
307
|
+
secrets/**
|
|
308
|
+
production-data/**
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Negated patterns can re-include a safe example:
|
|
312
|
+
|
|
313
|
+
```gitignore
|
|
314
|
+
secrets/**
|
|
315
|
+
!secrets/example.env
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
On the first run in a repository, surgent uses an existing `.gitignore` as the starting point for `.piignore`. Ignored paths are blocked from file access even in YOLO mode.
|
|
319
|
+
|
|
320
|
+
surgent also keeps its project-local `.pi` working data out of Git through the repository's local exclude file. Checkpoints complement Git; they are not a replacement for commits, branches, or backups.
|
|
321
|
+
|
|
322
|
+
## MCP and web access
|
|
323
|
+
|
|
324
|
+
### Connect MCP servers
|
|
325
|
+
|
|
326
|
+
Run `/mcp` and choose **Add MCP server**. surgent supports:
|
|
327
|
+
|
|
328
|
+
- Local servers launched over standard input/output
|
|
329
|
+
- Remote servers reached over HTTP
|
|
330
|
+
- Project-scoped or global configurations
|
|
331
|
+
|
|
332
|
+
New servers are disabled until you enable them. In the MCP list, press `Tab` to enable or disable a server; surgent checks the connection before enabling it.
|
|
333
|
+
|
|
334
|
+
### Configure web providers
|
|
335
|
+
|
|
336
|
+
surgent can search the web and fetch public URLs when a task needs current documentation or external context. Run `/web-login` to configure optional provider credentials for Tavily, Brave Search, Firecrawl, or Jina.
|
|
337
|
+
|
|
338
|
+
Web and MCP actions pass through the same permission system as file and shell operations.
|
|
339
|
+
|
|
340
|
+
## Tips for better results
|
|
341
|
+
|
|
342
|
+
- Describe the outcome, constraints, and validation you expect. A task such as "fix login" leaves more ambiguity than "reject expired refresh tokens, preserve the existing error shape, and run the auth tests."
|
|
343
|
+
- Let surgent inspect before prescribing a patch. Existing abstractions and tests often point to a smaller solution.
|
|
344
|
+
- Use `/plan` when a change spans several systems or needs a design decision.
|
|
345
|
+
- Use a read-only tool set for audits and reviews.
|
|
346
|
+
- Put stable repository facts in `AGENTS.md`; keep one-off task details in the prompt.
|
|
347
|
+
- Commit or stash valuable work before enabling YOLO mode or requesting broad changes.
|
|
348
|
+
|
|
349
|
+
## Troubleshooting
|
|
350
|
+
|
|
351
|
+
### `surgent: command not found`
|
|
352
|
+
|
|
353
|
+
Confirm npm's global binary directory is on your `PATH`, then open a new shell.
|
|
354
|
+
|
|
355
|
+
### No models are available
|
|
356
|
+
|
|
357
|
+
Check that the provider's environment variable is set in the same shell, then inspect matching models:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
surgent --list-models <search>
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
You can also check whether a configured provider is ready:
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
surgent auth check --provider <provider>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### A file cannot be read or edited
|
|
370
|
+
|
|
371
|
+
Check `.piignore`, the active agent's file limits, the current permission mode, and saved rules under `/permissions`. Path blocks in `.piignore` remain active in every mode.
|
|
372
|
+
|
|
373
|
+
### An MCP server has no tools
|
|
374
|
+
|
|
375
|
+
Open `/mcp`, verify the command or URL, and enable the server with `Tab`. A server must pass its connection check before surgent makes its tools available.
|
|
376
|
+
|
|
377
|
+
## Development
|
|
378
|
+
|
|
379
|
+
For source development, install dependencies and link the local command:
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
pnpm install
|
|
383
|
+
npm link
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
`pnpm build` builds only the distributable optimizer package in `dist/optimizers`. npm runs this build automatically through `prepack` when packaging surgent.
|
|
387
|
+
|
|
388
|
+
To publish the standalone optimizer artifact after building it:
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
npm publish ./dist/optimizers --access public
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Reference
|
|
395
|
+
|
|
396
|
+
surgent is built on [Pi](https://github.com/earendil-works/pi), created by [Mario Zechner](https://github.com/badlogic) and developed by its maintainers and contributors. Pi provides the agent runtime, TUI, model integration, extension system, and SDK that make surgent possible.
|
|
397
|
+
|
|
398
|
+
Refer to the upstream repository for Pi installation, configuration, providers, extension APIs, SDK usage, and other runtime documentation.
|
|
399
|
+
|
|
400
|
+
- [Pi repository](https://github.com/earendil-works/pi)
|
|
401
|
+
- [Pi coding agent](https://github.com/earendil-works/pi/tree/main/packages/coding-agent)
|
|
402
|
+
- [Pi documentation](https://github.com/earendil-works/pi/tree/main/packages/coding-agent/docs)
|
|
403
|
+
- [Pi contributors](https://github.com/earendil-works/pi/graphs/contributors)
|
|
404
|
+
|
|
405
|
+
## License
|
|
406
|
+
|
|
407
|
+
surgent is available under the [MIT License](LICENSE).
|
package/bin/surgent.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { main } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { dirname, resolve } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
|
|
11
|
+
process.title = "surgent";
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
const PACKAGE_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
const AGENT_ENTRY_URL = import.meta.resolve("@earendil-works/pi-coding-agent");
|
|
16
|
+
const LOCAL_PI_SUBDIRS = ["agents", "plans"];
|
|
17
|
+
const BUILT_IN_META = {
|
|
18
|
+
documenter: {
|
|
19
|
+
tools: ["code_map", "inspect", "read", "find", "grep", "ls", "edit", "write", "questionnaire"],
|
|
20
|
+
"files.write": ["**/*.md"],
|
|
21
|
+
},
|
|
22
|
+
planner: {
|
|
23
|
+
tools: ["read", "grep", "find", "ls", "web_fetch", "web_search", "questionnaire"],
|
|
24
|
+
},
|
|
25
|
+
scout: {
|
|
26
|
+
tools: ["ls", "find", "grep", "code_map", "inspect", "read", "web_fetch", "web_search"],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function isMissingFileError(error) {
|
|
31
|
+
return Boolean(error) && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function initBuiltInMeta() {
|
|
35
|
+
const settingsPath = resolve(homedir(), ".pi", "agent", "settings.json");
|
|
36
|
+
let settings;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
settings = JSON.parse(await readFile(settingsPath, "utf8"));
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (!isMissingFileError(error)) throw error;
|
|
42
|
+
settings = {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const meta = { ...settings.agent?.meta };
|
|
46
|
+
let changed = false;
|
|
47
|
+
for (const [name, builtInMeta] of Object.entries(BUILT_IN_META)) {
|
|
48
|
+
if (Object.hasOwn(meta, name)) continue;
|
|
49
|
+
meta[name] = builtInMeta;
|
|
50
|
+
changed = true;
|
|
51
|
+
}
|
|
52
|
+
if (!changed) return;
|
|
53
|
+
|
|
54
|
+
settings.agent = { ...settings.agent, meta };
|
|
55
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
56
|
+
await writeFile(settingsPath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function getGitExcludePath(cwd) {
|
|
60
|
+
try {
|
|
61
|
+
const excludePath = (
|
|
62
|
+
await new Promise((resolveOutput, rejectOutput) => {
|
|
63
|
+
let stdout = "";
|
|
64
|
+
const childProcess = spawn(
|
|
65
|
+
process.platform === "win32" ? "git.cmd" : "git",
|
|
66
|
+
["rev-parse", "--git-path", "info/exclude"],
|
|
67
|
+
{ cwd, env: process.env, stdio: ["ignore", "pipe", "ignore"] },
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
childProcess.stdout.on("data", (chunk) => {
|
|
71
|
+
stdout += chunk.toString();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
childProcess.on("error", (error) => {
|
|
75
|
+
rejectOutput(error);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
childProcess.on("close", (exitCode) => {
|
|
79
|
+
if (exitCode === 0) {
|
|
80
|
+
resolveOutput(stdout);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
rejectOutput(new Error("Git exclude path resolution failed."));
|
|
84
|
+
});
|
|
85
|
+
})
|
|
86
|
+
).trim();
|
|
87
|
+
|
|
88
|
+
if (excludePath) {
|
|
89
|
+
return resolve(cwd, excludePath);
|
|
90
|
+
}
|
|
91
|
+
} catch {}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function ensurePiExcluded(cwd) {
|
|
95
|
+
const excludePath = await getGitExcludePath(cwd);
|
|
96
|
+
if (!excludePath) return;
|
|
97
|
+
|
|
98
|
+
let excludeContents = "";
|
|
99
|
+
try {
|
|
100
|
+
excludeContents = await readFile(excludePath, "utf8");
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (!isMissingFileError(error)) return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const existingPatterns = excludeContents.split(/\r?\n/).map((line) => line.trim());
|
|
106
|
+
if (existingPatterns.includes(".pi")) return;
|
|
107
|
+
|
|
108
|
+
const separator = excludeContents.length > 0 && !excludeContents.endsWith("\n") ? "\n" : "";
|
|
109
|
+
await writeFile(excludePath, `${excludeContents}${separator}.pi\n`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function syncPiIgnore(cwd) {
|
|
113
|
+
const piIgnorePath = resolve(cwd, ".piignore");
|
|
114
|
+
try {
|
|
115
|
+
await readFile(piIgnorePath, "utf8");
|
|
116
|
+
return;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if (!isMissingFileError(error)) return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (existsSync(resolve(cwd, ".pi"))) return;
|
|
122
|
+
const gitIgnorePath = resolve(cwd, ".gitignore");
|
|
123
|
+
let gitIgnoreContents = "";
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
gitIgnoreContents = await readFile(gitIgnorePath, "utf8");
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
await writeFile(piIgnorePath, gitIgnoreContents);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function isJsonModeActive(args) {
|
|
135
|
+
for (let i = 0; i < args.length - 1; i++) {
|
|
136
|
+
const arg = args[i];
|
|
137
|
+
if (arg === "--mode" && args[i + 1] === "json") {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function rewriteHelpLine(line) {
|
|
145
|
+
if (/^pi\b/.test(line)) {
|
|
146
|
+
return line.replace(/^pi\b/, "surgent");
|
|
147
|
+
}
|
|
148
|
+
if (/^(\s+)pi\b/.test(line)) {
|
|
149
|
+
return line.replace(/^(\s+)pi\b/, "$1surgent");
|
|
150
|
+
}
|
|
151
|
+
if (/^Alias:\s+pi\b/.test(line)) {
|
|
152
|
+
return line.replace(/^Alias:\s+pi\b/, "Alias: surgent");
|
|
153
|
+
}
|
|
154
|
+
return line.replace(/(["'`])pi(?=[\s-])/g, "$1surgent");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function rewriteHelpText(text) {
|
|
158
|
+
return text.split("\n").map(rewriteHelpLine).join("\n");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function runRewrittenHelp(args) {
|
|
162
|
+
const cliPath = fileURLToPath(new URL("./cli.js", AGENT_ENTRY_URL));
|
|
163
|
+
|
|
164
|
+
await new Promise((resolve, reject) => {
|
|
165
|
+
const child = spawn(process.execPath, [cliPath, ...args], {
|
|
166
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
167
|
+
env: process.env,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
let stdout = "";
|
|
171
|
+
let stderr = "";
|
|
172
|
+
|
|
173
|
+
child.stdout.on("data", (chunk) => {
|
|
174
|
+
stdout += chunk.toString();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
child.stderr.on("data", (chunk) => {
|
|
178
|
+
stderr += chunk.toString();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
child.on("error", reject);
|
|
182
|
+
child.on("close", (code) => {
|
|
183
|
+
if (stdout) process.stdout.write(rewriteHelpText(stdout));
|
|
184
|
+
if (stderr) process.stderr.write(rewriteHelpText(stderr));
|
|
185
|
+
process.exitCode = code ?? 0;
|
|
186
|
+
resolve();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
await initBuiltInMeta();
|
|
192
|
+
|
|
193
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
194
|
+
await runRewrittenHelp(args);
|
|
195
|
+
} else {
|
|
196
|
+
const cwd = process.cwd();
|
|
197
|
+
if (!isJsonModeActive(args)) {
|
|
198
|
+
await ensurePiExcluded(cwd);
|
|
199
|
+
await syncPiIgnore(cwd);
|
|
200
|
+
}
|
|
201
|
+
for (const localPiSubdir of LOCAL_PI_SUBDIRS) {
|
|
202
|
+
await mkdir(resolve(cwd, ".pi", localPiSubdir), { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const srcDir = resolve(PACKAGE_DIR, "src");
|
|
206
|
+
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
207
|
+
const extensionArgs = entries
|
|
208
|
+
.filter((entry) => entry.isDirectory())
|
|
209
|
+
.flatMap((entry) => ["--extension", resolve(srcDir, entry.name)]);
|
|
210
|
+
await main([...extensionArgs, ...args]);
|
|
211
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 surgent
|
|
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.
|