@iinm/plain-agent 1.7.19 → 1.7.21
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/README.md +82 -118
- package/config/agents.predefined/sandbox-configurator.md +16 -18
- package/config/config.predefined.json +15 -15
- package/config/prompts.predefined/shortcuts/configure.md +60 -0
- package/package.json +1 -3
- package/src/agentLoop.mjs +3 -1
- package/src/cliCost.mjs +67 -32
- package/src/cliFormatter.mjs +1 -1
- package/src/cliInteractive.mjs +1 -1
- package/src/config.d.ts +2 -2
- package/src/config.mjs +1 -1
- package/src/costTracker.mjs +58 -19
- package/src/env.mjs +0 -6
- package/src/main.mjs +2 -6
- package/src/model.d.ts +1 -1
- package/src/tools/patchFile.mjs +11 -12
- package/src/utils/notify.mjs +3 -2
- package/src/voiceInputGemini.mjs +58 -210
- package/src/voiceInputOpenAI.mjs +63 -220
- package/src/voiceInputSession.mjs +295 -2
- package/bin/plain-notify-terminal-bell +0 -3
package/README.md
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="https://pub-0bb49aa929f242d49c89ed8c297932b5.r2.dev/plain-agent/plain-agent-logo.png" alt="plain-agent logo" width="320">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
1
|
# Plain Agent
|
|
6
2
|
|
|
7
|
-
A lightweight CLI-based coding agent
|
|
3
|
+
A lightweight CLI-based coding agent.
|
|
8
4
|
|
|
9
5
|
## Why Plain Agent?
|
|
10
6
|
|
|
@@ -23,6 +19,7 @@ A lightweight CLI-based coding agent with zero framework dependencies.
|
|
|
23
19
|
|
|
24
20
|
## Limitations
|
|
25
21
|
|
|
22
|
+
- **CLI only** — Plain Agent does not provide a terminal UI.
|
|
26
23
|
- **Sequential subagent execution** — Subagents run one at a time rather than
|
|
27
24
|
in parallel. The trade-off is full visibility: every step is streamed to
|
|
28
25
|
your terminal so you can follow exactly what each subagent is doing.
|
|
@@ -31,7 +28,7 @@ A lightweight CLI-based coding agent with zero framework dependencies.
|
|
|
31
28
|
|
|
32
29
|
- Node.js 22 or later
|
|
33
30
|
- LLM provider credentials
|
|
34
|
-
-
|
|
31
|
+
- Bash / Docker for sandboxed execution
|
|
35
32
|
- [ripgrep](https://github.com/burntsushi/ripgrep)
|
|
36
33
|
- [fd](https://github.com/sharkdp/fd)
|
|
37
34
|
|
|
@@ -52,8 +49,8 @@ Create the configuration.
|
|
|
52
49
|
```js
|
|
53
50
|
// ~/.config/plain-agent/config.local.json
|
|
54
51
|
{
|
|
55
|
-
"model": "
|
|
56
|
-
// "model": "
|
|
52
|
+
"model": "claude-sonnet-4-6+thinking-high",
|
|
53
|
+
// "model": "gpt-5.5+thinking-high",
|
|
57
54
|
|
|
58
55
|
// Configure the providers you want to use
|
|
59
56
|
"platforms": [
|
|
@@ -83,15 +80,11 @@ Create the configuration.
|
|
|
83
80
|
"provider": "gemini",
|
|
84
81
|
"apiKey": "<GEMINI_API_KEY>",
|
|
85
82
|
"model": "gemini-3-flash-preview"
|
|
86
|
-
// Optional
|
|
87
|
-
// "baseURL": "<proxy_url>"
|
|
88
83
|
|
|
89
84
|
// Or use Vertex AI (Requires gcloud CLI to get authentication token)
|
|
90
85
|
// "provider": "gemini-vertex-ai",
|
|
91
86
|
// "baseURL": "https://aiplatform.googleapis.com/v1beta1/projects/<project_id>/locations/<location>",
|
|
92
87
|
// "model": "gemini-3-flash-preview"
|
|
93
|
-
// Optional:
|
|
94
|
-
// "account": "<service_account_email>"
|
|
95
88
|
},
|
|
96
89
|
|
|
97
90
|
// askURL: Answers questions based on provided URL content.
|
|
@@ -100,15 +93,8 @@ Create the configuration.
|
|
|
100
93
|
"provider": "gemini",
|
|
101
94
|
"apiKey": "<GEMINI_API_KEY>"
|
|
102
95
|
"model": "gemini-3-flash-preview"
|
|
103
|
-
// Optional
|
|
104
|
-
// "baseURL": "<proxy_url>"
|
|
105
96
|
|
|
106
97
|
// Or use Vertex AI (Requires gcloud CLI to get authentication token)
|
|
107
|
-
// "provider": "gemini-vertex-ai",
|
|
108
|
-
// "baseURL": "https://aiplatform.googleapis.com/v1beta1/projects/<project_id>/locations/<location>",
|
|
109
|
-
// "model": "gemini-3-flash-preview"
|
|
110
|
-
// Optional:
|
|
111
|
-
// "account": "<service_account_email>"
|
|
112
98
|
}
|
|
113
99
|
},
|
|
114
100
|
|
|
@@ -166,6 +152,7 @@ Create the configuration.
|
|
|
166
152
|
```
|
|
167
153
|
|
|
168
154
|
```js
|
|
155
|
+
// OpenAI-compatible provider (Ollama) example with a custom model
|
|
169
156
|
{
|
|
170
157
|
"platforms": [
|
|
171
158
|
{
|
|
@@ -268,31 +255,26 @@ Create the configuration.
|
|
|
268
255
|
```
|
|
269
256
|
</details>
|
|
270
257
|
|
|
271
|
-
|
|
272
|
-
|
|
273
258
|
Run the agent.
|
|
274
259
|
|
|
275
260
|
```sh
|
|
276
261
|
plain
|
|
277
|
-
|
|
278
|
-
# Or
|
|
279
|
-
plain -m <model+variant>
|
|
280
262
|
```
|
|
281
263
|
|
|
282
|
-
(Optional) Set up a sandbox for your project with the `sandbox-configurator` agent.
|
|
283
|
-
|
|
284
264
|
```
|
|
285
|
-
|
|
265
|
+
plain -m <model+variant>
|
|
286
266
|
```
|
|
287
267
|
|
|
288
|
-
|
|
268
|
+
Press **Ctrl-C** to pause auto-approve. The agent will finish the current tool call, then return to the prompt.
|
|
289
269
|
|
|
290
|
-
|
|
291
|
-
|
|
270
|
+
Display the help message.
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
/help
|
|
292
274
|
```
|
|
293
275
|
|
|
294
276
|
Run in batch mode (non-interactive).
|
|
295
|
-
In batch mode, config files are not loaded automatically. Only the files specified with
|
|
277
|
+
In batch mode, config files are not loaded automatically. Only the files specified with `-c` are loaded.
|
|
296
278
|
|
|
297
279
|
```sh
|
|
298
280
|
plain batch \
|
|
@@ -301,66 +283,48 @@ plain batch \
|
|
|
301
283
|
"Add tests for ..."
|
|
302
284
|
```
|
|
303
285
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
/help
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Show aggregated token cost per day across sessions.
|
|
311
|
-
Each finished session appends a record to `~/.local/share/plain-agent/usage.jsonl`,
|
|
312
|
-
and `plain cost` reads that log. The period defaults to the first day of the
|
|
313
|
-
current month through today; override it with `--from` / `--to`. Multiple
|
|
314
|
-
currencies (e.g., USD and JPY) are aggregated separately.
|
|
286
|
+
Show daily token costs across sessions. `plain cost` reads
|
|
287
|
+
`~/.local/share/plain-agent/usage.jsonl`; use `--from` / `--to` to set the
|
|
288
|
+
period. Currencies are shown separately.
|
|
315
289
|
|
|
316
290
|
```sh
|
|
317
291
|
plain cost
|
|
318
|
-
plain cost --from 2026-04-01 --to 2026-04-30
|
|
319
292
|
```
|
|
320
293
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
294
|
+
```
|
|
295
|
+
plain cost --from 2026-04-01 --to 2026-04-30
|
|
296
|
+
```
|
|
324
297
|
|
|
325
|
-
|
|
298
|
+
(Optional) Configure plain-agent for your project.
|
|
326
299
|
|
|
327
|
-
|
|
300
|
+
```
|
|
301
|
+
/configure Auto-approve file writes and patches
|
|
302
|
+
```
|
|
328
303
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
- **tmux_command**: Run a tmux command.
|
|
333
|
-
- **ask_web**: Use the web search to answer questions that need up-to-date information or supporting sources. (requires Google API key or Vertex AI configuration).
|
|
334
|
-
- **ask_url**: Use one or more provided URLs to answer a question. Include the URLs in your question. (requires Google API key or Vertex AI configuration).
|
|
335
|
-
- **delegate_to_subagent**: Delegate a subtask to a subagent. The agent switches to a subagent role within the same conversation, focusing on the specified goal.
|
|
336
|
-
- **report_as_subagent**: Report completion and return to the main agent. Used by subagents to communicate results and restore the main agent role. After reporting, the subagent's conversation history is removed from the context.
|
|
337
|
-
- **compact_context**: Compact the conversation context by discarding prior messages and reloading task state from a memory file. Use when the context has grown large but the task is not yet complete. Can also be invoked via the `/compact` slash command.
|
|
304
|
+
```
|
|
305
|
+
/configure Set up a sandbox for this project
|
|
306
|
+
```
|
|
338
307
|
|
|
339
308
|
## Configuration
|
|
340
309
|
|
|
310
|
+
Files are loaded in the following order. Settings in later files override earlier ones.
|
|
311
|
+
|
|
341
312
|
```
|
|
342
313
|
~/.config/plain-agent/
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
314
|
+
├── (1) config.json # User configuration
|
|
315
|
+
├── (2) config.local.json # User local configuration (including secrets)
|
|
316
|
+
├── prompts/ # Global/User-defined prompts
|
|
317
|
+
└── agents/ # Global/User-defined agent roles
|
|
347
318
|
|
|
348
319
|
<project-root>
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
320
|
+
└── .plain-agent/
|
|
321
|
+
├── (3) config.json # Project-specific configuration
|
|
322
|
+
├── (4) config.local.json # Project-specific local configuration (including secrets)
|
|
323
|
+
├── memory/ # Task-specific memory files
|
|
324
|
+
├── prompts/ # Project-specific prompts
|
|
325
|
+
└── agents/ # Project-specific agent roles
|
|
355
326
|
```
|
|
356
327
|
|
|
357
|
-
The agent loads configuration files in the following order. Settings in later files will override those in earlier files.
|
|
358
|
-
|
|
359
|
-
- `~/.config/plain-agent/config.json`
|
|
360
|
-
- `~/.config/plain-agent/config.local.json`
|
|
361
|
-
- `.plain-agent/config.json`
|
|
362
|
-
- `.plain-agent/config.local.json`
|
|
363
|
-
|
|
364
328
|
### Example
|
|
365
329
|
|
|
366
330
|
<details>
|
|
@@ -423,19 +387,19 @@ The agent loads configuration files in the following order. Settings in later fi
|
|
|
423
387
|
"patterns": [
|
|
424
388
|
{
|
|
425
389
|
"toolName": { "$regex": "^(write_file|patch_file)$" },
|
|
426
|
-
"input": { "filePath": { "$regex": "
|
|
390
|
+
"input": { "filePath": { "$regex": "^\\.plain-agent/memory/.+\\.md$" } },
|
|
427
391
|
"action": "allow"
|
|
428
392
|
},
|
|
429
393
|
{
|
|
430
394
|
"toolName": { "$regex": "^(write_file|patch_file)$" },
|
|
431
|
-
"input": { "filePath": { "$regex": "^
|
|
395
|
+
"input": { "filePath": { "$regex": "^src/" } },
|
|
432
396
|
"action": "allow"
|
|
433
397
|
},
|
|
434
398
|
|
|
435
399
|
// ⚠️ Arbitrary code execution can access unauthorized files and networks. Always use a sandbox.
|
|
436
400
|
{
|
|
437
401
|
"toolName": "exec_command",
|
|
438
|
-
"input": { "command": "npm", "args": ["run", { "$regex": "^(
|
|
402
|
+
"input": { "command": "npm", "args": ["run", { "$regex": "^(lint|test)$" }] },
|
|
439
403
|
"action": "allow"
|
|
440
404
|
},
|
|
441
405
|
|
|
@@ -511,8 +475,8 @@ The agent loads configuration files in the following order. Settings in later fi
|
|
|
511
475
|
}
|
|
512
476
|
},
|
|
513
477
|
|
|
514
|
-
// Override default notification command
|
|
515
|
-
// "notifyCmd": "
|
|
478
|
+
// Override default notification command (falls back to terminal bell)
|
|
479
|
+
// "notifyCmd": { "command": "plain-notify-desktop", "args": [] }
|
|
516
480
|
|
|
517
481
|
// (Optional) Voice input. See "Voice Input" below.
|
|
518
482
|
// "voiceInput": {
|
|
@@ -523,10 +487,35 @@ The agent loads configuration files in the following order. Settings in later fi
|
|
|
523
487
|
```
|
|
524
488
|
</details>
|
|
525
489
|
|
|
490
|
+
## Available Tools
|
|
491
|
+
|
|
492
|
+
The agent can use the following tools to assist with tasks:
|
|
493
|
+
|
|
494
|
+
- **exec_command**: Run a command without shell interpretation.
|
|
495
|
+
- **write_file**: Write a file.
|
|
496
|
+
- **patch_file**: Patch a file.
|
|
497
|
+
- **tmux_command**: Run a tmux command.
|
|
498
|
+
- **ask_web**: Use the web search to answer questions that need up-to-date information or supporting sources. (requires Google API key or Vertex AI configuration).
|
|
499
|
+
- **ask_url**: Use one or more provided URLs to answer a question. Include the URLs in your question. (requires Google API key or Vertex AI configuration).
|
|
500
|
+
- **delegate_to_subagent**: Delegate a subtask to a subagent. The agent switches to a subagent role within the same conversation, focusing on the specified goal.
|
|
501
|
+
- **report_as_subagent**: Report completion and return to the main agent. Used by subagents to communicate results and restore the main agent role. After reporting, the subagent's conversation history is removed from the context.
|
|
502
|
+
- **compact_context**: Compact the conversation context by discarding prior messages and reloading task state from a memory file. Use when the context has grown large but the task is not yet complete. Can also be invoked via the `/compact` slash command.
|
|
503
|
+
|
|
526
504
|
## Prompts
|
|
527
505
|
|
|
528
506
|
You can define reusable prompts in Markdown files.
|
|
529
507
|
|
|
508
|
+
### Locations
|
|
509
|
+
|
|
510
|
+
The agent searches for prompts in the following directories:
|
|
511
|
+
|
|
512
|
+
- `~/.config/plain-agent/prompts/`
|
|
513
|
+
- `.plain-agent/prompts/`
|
|
514
|
+
- `.claude/commands/`
|
|
515
|
+
- `.claude/skills/`
|
|
516
|
+
|
|
517
|
+
The prompt ID is the relative path of the file without the `.md` extension. For example, `.plain-agent/prompts/commit.md` becomes `/prompts:commit`.
|
|
518
|
+
|
|
530
519
|
### Prompt File Format
|
|
531
520
|
|
|
532
521
|
```md
|
|
@@ -548,30 +537,8 @@ import: https://raw.githubusercontent.com/anthropics/claude-code/5cff78741f54a0d
|
|
|
548
537
|
- Parallel execution of subagents is not supported. Delegate to subagents sequentially.
|
|
549
538
|
```
|
|
550
539
|
|
|
551
|
-
```md
|
|
552
|
-
---
|
|
553
|
-
import: https://raw.githubusercontent.com/anthropics/claude-code/db8834ba1d72e9a26fba30ac85f3bc4316bb0689/plugins/code-review/commands/code-review.md
|
|
554
|
-
---
|
|
555
|
-
|
|
556
|
-
- Parallel execution of subagents is not supported. Delegate to subagents sequentially.
|
|
557
|
-
- If CLAUDE.md is not found, refer to AGENTS.md instead for project rules and conventions.
|
|
558
|
-
- If the PR branch is already checked out, review changes from local files instead of fetching from GitHub.
|
|
559
|
-
- After explaining the review results to the user, ask whether to post the comments to GitHub as well.
|
|
560
|
-
```
|
|
561
|
-
|
|
562
540
|
Remote prompts are fetched and cached locally. The local content will be appended to the imported content.
|
|
563
541
|
|
|
564
|
-
### Locations
|
|
565
|
-
|
|
566
|
-
The agent searches for prompts in the following directories:
|
|
567
|
-
|
|
568
|
-
- `~/.config/plain-agent/prompts/`
|
|
569
|
-
- `.plain-agent/prompts/`
|
|
570
|
-
- `.claude/commands/`
|
|
571
|
-
- `.claude/skills/`
|
|
572
|
-
|
|
573
|
-
The prompt ID is the relative path of the file without the `.md` extension. For example, `.plain-agent/prompts/commit.md` becomes `/prompts:commit`.
|
|
574
|
-
|
|
575
542
|
### Shortcuts
|
|
576
543
|
|
|
577
544
|
Prompts located in a `shortcuts/` subdirectory (e.g., `.plain-agent/prompts/shortcuts/commit.md`) can be invoked directly as a top-level command (e.g., `/commit`).
|
|
@@ -580,6 +547,14 @@ Prompts located in a `shortcuts/` subdirectory (e.g., `.plain-agent/prompts/shor
|
|
|
580
547
|
|
|
581
548
|
Subagents are specialized agents designed for specific tasks.
|
|
582
549
|
|
|
550
|
+
### Locations
|
|
551
|
+
|
|
552
|
+
The agent searches for subagent definitions in the following directories:
|
|
553
|
+
|
|
554
|
+
- `~/.config/plain-agent/agents/`
|
|
555
|
+
- `.plain-agent/agents/`
|
|
556
|
+
- `.claude/agents/`
|
|
557
|
+
|
|
583
558
|
### Subagent File Format
|
|
584
559
|
|
|
585
560
|
```md
|
|
@@ -602,14 +577,6 @@ Use AGENTS.md instead of CLAUDE.md in this project.
|
|
|
602
577
|
|
|
603
578
|
Remote subagents are fetched and cached locally. The local content will be appended to the imported content.
|
|
604
579
|
|
|
605
|
-
### Locations
|
|
606
|
-
|
|
607
|
-
The agent searches for subagent definitions in the following directories:
|
|
608
|
-
|
|
609
|
-
- `~/.config/plain-agent/agents/`
|
|
610
|
-
- `.plain-agent/agents/`
|
|
611
|
-
- `.claude/agents/`
|
|
612
|
-
|
|
613
580
|
## Claude Code Plugin Support
|
|
614
581
|
|
|
615
582
|
Example:
|
|
@@ -653,9 +620,10 @@ and send them like regular text.
|
|
|
653
620
|
|
|
654
621
|
### Providers
|
|
655
622
|
|
|
656
|
-
**OpenAI Realtime**
|
|
623
|
+
**OpenAI Realtime**
|
|
657
624
|
|
|
658
625
|
```js
|
|
626
|
+
// ~/.config/plain-agent/config.local.json
|
|
659
627
|
{
|
|
660
628
|
"voiceInput": {
|
|
661
629
|
"provider": "openai",
|
|
@@ -666,9 +634,10 @@ and send them like regular text.
|
|
|
666
634
|
}
|
|
667
635
|
```
|
|
668
636
|
|
|
669
|
-
**Gemini Live**
|
|
637
|
+
**Gemini Live**
|
|
670
638
|
|
|
671
639
|
```js
|
|
640
|
+
// ~/.config/plain-agent/config.local.json
|
|
672
641
|
{
|
|
673
642
|
"voiceInput": {
|
|
674
643
|
"provider": "gemini",
|
|
@@ -683,8 +652,7 @@ and send them like regular text.
|
|
|
683
652
|
|
|
684
653
|
- `toggleKey` — Rebind the toggle. Accepts `"ctrl-<char>"` where `<char>`
|
|
685
654
|
is a letter (a-z) or one of `[ \ ] ^ _`. Defaults to `"ctrl-o"`.
|
|
686
|
-
- `recorder` — Override recorder auto-detection. Must write raw 16-bit
|
|
687
|
-
little-endian mono PCM to stdout at 24 kHz (OpenAI) or 16 kHz (Gemini).
|
|
655
|
+
- `recorder` — Override recorder auto-detection, e.g. `{ "command": "sox", "args": ["-q", "-d", "-b", "16", "-c", "1", "-r", "24000", "-e", "signed-integer", "-t", "raw", "-"] }`. Must write raw 16-bit little-endian mono PCM to stdout at 24 kHz (OpenAI) or 16 kHz (Gemini).
|
|
688
656
|
|
|
689
657
|
## Development
|
|
690
658
|
|
|
@@ -705,13 +673,9 @@ npx npm-check-updates -t minor -c 3 -u
|
|
|
705
673
|
## Release
|
|
706
674
|
|
|
707
675
|
```sh
|
|
708
|
-
npm run check
|
|
709
|
-
|
|
710
|
-
git commit -m "<message>"
|
|
711
|
-
|
|
712
676
|
npm version <major|minor|patch>
|
|
713
|
-
git push --follow-tags
|
|
714
677
|
|
|
678
|
+
git push --follow-tags
|
|
715
679
|
gh release create $(git describe --tags) --generate-notes
|
|
716
680
|
|
|
717
681
|
npm publish --access public
|
|
@@ -63,9 +63,10 @@ Present the analysis results and ask the user to confirm. Show:
|
|
|
63
63
|
3. **Volume configuration** (e.g., "node_modules + npm cache")
|
|
64
64
|
4. **Setup install command** (e.g., "npm ci")
|
|
65
65
|
|
|
66
|
-
Ask
|
|
66
|
+
Ask the following questions one at a time, waiting for the user's answer before proceeding to the next:
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
1. Do you want to mount `~/.gitconfig` into the sandbox? (This allows git commit inside the sandbox.)
|
|
69
|
+
2. Are there any commands that must run on the host instead of inside the container? (e.g. `gh`, `docker` — tools that require host credentials or sockets.) If so, which ones?
|
|
69
70
|
|
|
70
71
|
## Step 3: Generate run.sh
|
|
71
72
|
|
|
@@ -115,7 +116,7 @@ set -eu -o pipefail
|
|
|
115
116
|
|
|
116
117
|
this_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
117
118
|
|
|
118
|
-
#
|
|
119
|
+
# Build Docker image and setup sandbox (install runtime and dependencies with network access)
|
|
119
120
|
"$this_dir/sandbox/run.sh" --verbose --allow-net 0.0.0.0/0 mise use node@lts
|
|
120
121
|
"$this_dir/sandbox/run.sh" --verbose --allow-net 0.0.0.0/0 npm ci
|
|
121
122
|
|
|
@@ -125,21 +126,19 @@ npm ci
|
|
|
125
126
|
|
|
126
127
|
`--allow-net 0.0.0.0/0` is needed only during setup for downloading packages. It should NOT be in run.sh for normal usage.
|
|
127
128
|
|
|
128
|
-
## Step 5:
|
|
129
|
+
## Step 5: Update config.json
|
|
129
130
|
|
|
130
|
-
|
|
131
|
+
Show the user the following config and explain:
|
|
132
|
+
|
|
133
|
+
- `--skip-build` assumes the image is already built (run `setup.sh` first to build)
|
|
134
|
+
- `--keep-alive 30` reuses the container for 30 seconds between commands for performance
|
|
135
|
+
|
|
136
|
+
If the user specified any unsandboxed commands in Step 2, also include and explain:
|
|
137
|
+
|
|
138
|
+
- They run **unsandboxed** because they need host access.
|
|
131
139
|
|
|
132
140
|
```json
|
|
133
141
|
{
|
|
134
|
-
"autoApproval": {
|
|
135
|
-
"patterns": [
|
|
136
|
-
{
|
|
137
|
-
"toolName": "exec_command",
|
|
138
|
-
"input": { "command": { "$regex": "^(gh|docker)$" } },
|
|
139
|
-
"action": "ask"
|
|
140
|
-
}
|
|
141
|
-
]
|
|
142
|
-
},
|
|
143
142
|
"sandbox": {
|
|
144
143
|
"command": ".plain-agent/sandbox/run.sh",
|
|
145
144
|
"args": ["--skip-build", "--keep-alive", "30"],
|
|
@@ -154,7 +153,6 @@ After generating all files, instruct the user to add the following to their `.pl
|
|
|
154
153
|
}
|
|
155
154
|
```
|
|
156
155
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
- `gh` and `docker` run unsandboxed (host access needed), so they should also be set to `ask` in `autoApproval` to avoid being auto-approved alongside other shell commands. Place this `ask` pattern before any broad `allow` pattern for `exec_command`, since `autoApproval` patterns are evaluated in order and the first match wins.
|
|
156
|
+
Adjust the regex to match the commands the user specified. If none, omit `sandbox.rules`.
|
|
157
|
+
|
|
158
|
+
After the user confirms, write the config into `.plain-agent/config.json` (merge if the file already exists).
|
|
@@ -813,7 +813,7 @@
|
|
|
813
813
|
}
|
|
814
814
|
},
|
|
815
815
|
{
|
|
816
|
-
"name": "gpt-5.
|
|
816
|
+
"name": "gpt-5.5",
|
|
817
817
|
"variant": "thinking-medium",
|
|
818
818
|
"platform": {
|
|
819
819
|
"name": "openai",
|
|
@@ -823,7 +823,7 @@
|
|
|
823
823
|
"model": {
|
|
824
824
|
"format": "openai-responses",
|
|
825
825
|
"config": {
|
|
826
|
-
"model": "gpt-5.
|
|
826
|
+
"model": "gpt-5.5",
|
|
827
827
|
"reasoning": { "effort": "medium", "summary": "auto" },
|
|
828
828
|
"store": false,
|
|
829
829
|
"include": ["reasoning.encrypted_content"]
|
|
@@ -833,14 +833,14 @@
|
|
|
833
833
|
"currency": "USD",
|
|
834
834
|
"unit": "1M",
|
|
835
835
|
"costs": {
|
|
836
|
-
"input_tokens":
|
|
837
|
-
"input_tokens_details.cached_tokens": -
|
|
838
|
-
"output_tokens":
|
|
836
|
+
"input_tokens": 5,
|
|
837
|
+
"input_tokens_details.cached_tokens": -4.5,
|
|
838
|
+
"output_tokens": 30
|
|
839
839
|
}
|
|
840
840
|
}
|
|
841
841
|
},
|
|
842
842
|
{
|
|
843
|
-
"name": "gpt-5.
|
|
843
|
+
"name": "gpt-5.5",
|
|
844
844
|
"variant": "thinking-high",
|
|
845
845
|
"platform": {
|
|
846
846
|
"name": "openai",
|
|
@@ -850,7 +850,7 @@
|
|
|
850
850
|
"model": {
|
|
851
851
|
"format": "openai-responses",
|
|
852
852
|
"config": {
|
|
853
|
-
"model": "gpt-5.
|
|
853
|
+
"model": "gpt-5.5",
|
|
854
854
|
"reasoning": { "effort": "high", "summary": "auto" },
|
|
855
855
|
"store": false,
|
|
856
856
|
"include": ["reasoning.encrypted_content"]
|
|
@@ -860,14 +860,14 @@
|
|
|
860
860
|
"currency": "USD",
|
|
861
861
|
"unit": "1M",
|
|
862
862
|
"costs": {
|
|
863
|
-
"input_tokens":
|
|
864
|
-
"input_tokens_details.cached_tokens": -
|
|
865
|
-
"output_tokens":
|
|
863
|
+
"input_tokens": 5,
|
|
864
|
+
"input_tokens_details.cached_tokens": -4.5,
|
|
865
|
+
"output_tokens": 30
|
|
866
866
|
}
|
|
867
867
|
}
|
|
868
868
|
},
|
|
869
869
|
{
|
|
870
|
-
"name": "gpt-5.
|
|
870
|
+
"name": "gpt-5.5",
|
|
871
871
|
"variant": "thinking-xhigh",
|
|
872
872
|
"platform": {
|
|
873
873
|
"name": "openai",
|
|
@@ -877,7 +877,7 @@
|
|
|
877
877
|
"model": {
|
|
878
878
|
"format": "openai-responses",
|
|
879
879
|
"config": {
|
|
880
|
-
"model": "gpt-5.
|
|
880
|
+
"model": "gpt-5.5",
|
|
881
881
|
"reasoning": { "effort": "xhigh", "summary": "auto" },
|
|
882
882
|
"store": false,
|
|
883
883
|
"include": ["reasoning.encrypted_content"]
|
|
@@ -887,9 +887,9 @@
|
|
|
887
887
|
"currency": "USD",
|
|
888
888
|
"unit": "1M",
|
|
889
889
|
"costs": {
|
|
890
|
-
"input_tokens":
|
|
891
|
-
"input_tokens_details.cached_tokens": -
|
|
892
|
-
"output_tokens":
|
|
890
|
+
"input_tokens": 5,
|
|
891
|
+
"input_tokens_details.cached_tokens": -4.5,
|
|
892
|
+
"output_tokens": 30
|
|
893
893
|
}
|
|
894
894
|
}
|
|
895
895
|
},
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Update plain-agent configuration based on user needs.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Fetch the latest README and help the user configure plain-agent for this project. Before each step, briefly explain to the user what you are about to do and why.
|
|
6
|
+
|
|
7
|
+
## Security Rule (Non-Negotiable)
|
|
8
|
+
|
|
9
|
+
**Never write credentials** (API keys, tokens, passwords, secrets) into any config file.
|
|
10
|
+
|
|
11
|
+
When a setting requires a credential:
|
|
12
|
+
1. Tell the user it must go into `.plain-agent/config.local.json`.
|
|
13
|
+
2. Show the exact JSON snippet they need to add.
|
|
14
|
+
3. Do not modify that file yourself.
|
|
15
|
+
|
|
16
|
+
If the user wants a setting applied globally (`~/.config/plain-agent/`), show them the exact snippet and tell them to add it manually. Do not access the home directory.
|
|
17
|
+
|
|
18
|
+
## Step 1: Fetch the Latest README
|
|
19
|
+
|
|
20
|
+
Fetch the latest README from GitHub as the authoritative reference for all configuration options:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
gh api --method GET -H "Accept: application/vnd.github.v3.raw" "repos/iinm/plain-agent/contents/README.md?ref=main"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Step 2: Read the Current Config
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
cat .plain-agent/config.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Step 3: Ask the User What They Want
|
|
33
|
+
|
|
34
|
+
Ask what the user wants to configure. Common topics:
|
|
35
|
+
|
|
36
|
+
- **Model** — which LLM to use (`model` field)
|
|
37
|
+
- **Auto-approval rules** — which tool calls to allow automatically (`autoApproval`)
|
|
38
|
+
- **Sandbox** — isolated execution environment (`sandbox`)
|
|
39
|
+
- **MCP servers** — external tool integrations (`mcpServers`)
|
|
40
|
+
- **Claude Code plugins** — reuse Claude Code plugin prompts/agents (`claudeCodePlugins`)
|
|
41
|
+
- **Voice input** — voice transcription settings (`voiceInput`)
|
|
42
|
+
- **Notifications** — custom notify command (`notifyCmd`)
|
|
43
|
+
|
|
44
|
+
If the request is vague, ask a focused clarifying question before proceeding.
|
|
45
|
+
|
|
46
|
+
**If the user wants to configure Sandbox**: immediately delegate to the `sandbox-configurator` agent and do not proceed further yourself.
|
|
47
|
+
|
|
48
|
+
## Step 4: Apply Changes
|
|
49
|
+
|
|
50
|
+
Update `.plain-agent/config.json`. Rules:
|
|
51
|
+
|
|
52
|
+
- Merge carefully — preserve all existing keys.
|
|
53
|
+
- Only write to `.plain-agent/config.json`. Never access files outside the project directory.
|
|
54
|
+
- For credential-requiring fields, use a placeholder like `"<YOUR_API_KEY>"` and instruct the user to add the real value to `.plain-agent/config.local.json` themselves.
|
|
55
|
+
|
|
56
|
+
## Step 5: Summarize
|
|
57
|
+
|
|
58
|
+
1. Show a diff or summary of what changed.
|
|
59
|
+
2. If any credentials were skipped, show the snippet the user needs to add to `config.local.json`.
|
|
60
|
+
3. Tell the user to restart `plain` for changes to take effect.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iinm/plain-agent",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.21",
|
|
4
4
|
"description": "A lightweight CLI-based coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
12
|
"plain": "./bin/plain",
|
|
13
|
-
"plain-interrupt": "./bin/plain-interrupt",
|
|
14
13
|
"plain-notify-desktop": "./bin/plain-notify-desktop",
|
|
15
|
-
"plain-notify-terminal-bell": "./bin/plain-notify-terminal-bell",
|
|
16
14
|
"plain-sandbox": "./sandbox/bin/plain-sandbox"
|
|
17
15
|
},
|
|
18
16
|
"files": [
|
package/src/agentLoop.mjs
CHANGED
|
@@ -128,7 +128,9 @@ export function createAgentLoop({
|
|
|
128
128
|
|
|
129
129
|
const { message: assistantMessage, providerTokenUsage } = modelOutput;
|
|
130
130
|
stateManager.appendMessages([assistantMessage]);
|
|
131
|
-
|
|
131
|
+
if (providerTokenUsage) {
|
|
132
|
+
agentEventEmitter.emit("providerTokenUsage", providerTokenUsage);
|
|
133
|
+
}
|
|
132
134
|
|
|
133
135
|
// Gemini may stop with "thinking" -> continue
|
|
134
136
|
const lastContent = assistantMessage.content.at(-1);
|