@earendil-works/pi-coding-agent 0.78.0 → 0.79.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/CHANGELOG.md +68 -0
- package/README.md +26 -6
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +3 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +1 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +2 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +3 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +7 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +4 -3
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +3 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +9 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/export-html/template.js +19 -6
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +4 -4
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +9 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +41 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +25 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +2 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +29 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +3 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +3 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +47 -13
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/provider-attribution.d.ts +4 -0
- package/dist/core/provider-attribution.d.ts.map +1 -0
- package/dist/core/provider-attribution.js +72 -0
- package/dist/core/provider-attribution.js.map +1 -0
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +3 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/resource-loader.d.ts +13 -2
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +129 -54
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -33
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +92 -68
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +71 -30
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts +10 -0
- package/dist/core/trust-manager.d.ts.map +1 -0
- package/dist/core/trust-manager.js +133 -0
- package/dist/core/trust-manager.js.map +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +195 -6
- package/dist/main.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -2
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +7 -0
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +0 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -12
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +22 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts +20 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/trust-selector.js +86 -0
- package/dist/modes/interactive/components/trust-selector.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +7 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +87 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +1 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +55 -8
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +54 -22
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +22 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/docs/containerization.md +111 -0
- package/docs/docs.json +8 -0
- package/docs/extensions.md +58 -12
- package/docs/index.md +2 -0
- package/docs/packages.md +3 -1
- package/docs/prompt-templates.md +1 -1
- package/docs/providers.md +5 -0
- package/docs/rpc.md +1 -1
- package/docs/sdk.md +5 -0
- package/docs/security.md +57 -0
- package/docs/settings.md +10 -0
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +36 -2
- package/docs/themes.md +1 -1
- package/docs/tmux.md +4 -2
- package/docs/tui.md +10 -1
- package/docs/usage.md +16 -4
- package/examples/extensions/README.md +2 -0
- package/examples/extensions/custom-header.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/index.ts +1 -1
- package/examples/extensions/gondolin/index.ts +531 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +1 -1
- package/examples/extensions/interactive-shell.ts +1 -1
- package/examples/extensions/overlay-qa-tests.ts +152 -81
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/qna.ts +1 -1
- package/examples/extensions/question.ts +1 -1
- package/examples/extensions/questionnaire.ts +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/snake.ts +1 -1
- package/examples/extensions/space-invaders.ts +1 -1
- package/examples/extensions/summarize.ts +1 -1
- package/examples/extensions/tic-tac-toe.ts +1 -1
- package/examples/extensions/todo.ts +1 -1
- package/examples/extensions/tools.ts +5 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +5 -8
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Containerization
|
|
2
|
+
|
|
3
|
+
Pi runs with all permissions by default, but in some cases, you will want to have more control over what directories Pi can write to and which accesses it has.
|
|
4
|
+
|
|
5
|
+
There are two general options. You can either
|
|
6
|
+
1. run the whole `pi` process inside an isolated environment, or
|
|
7
|
+
2. run `pi` on the host and route tool execution into an isolated environment.
|
|
8
|
+
|
|
9
|
+
## Choose a pattern
|
|
10
|
+
|
|
11
|
+
| Pattern | What is isolated | Best for | Notes |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| OpenShell | Whole `pi` process in a policy-controlled sandbox | Local or remote managed sandbox | Requires an OpenShell gateway |
|
|
14
|
+
| Gondolin extension | Built-in tools and `!` commands | Local micro-VM isolation while keeping auth on host | See [`examples/extensions/gondolin/`](../examples/extensions/gondolin/). |
|
|
15
|
+
| Plain Docker | Whole `pi` process in a local container | Simple local isolation | Provider API keys enter the container. |
|
|
16
|
+
|
|
17
|
+
Extensions run wherever the `pi` process runs. If you run host `pi` with a tool-routing extension, other custom extension tools still run on the host unless they also delegate their operations.
|
|
18
|
+
|
|
19
|
+
## OpenShell
|
|
20
|
+
|
|
21
|
+
Use [NVIDIA OpenShell](https://docs.nvidia.com/openshell/about/overview) when you want a policy-controlled sandbox with filesystem, process, network, credential, and inference controls.
|
|
22
|
+
OpenShell can run sandboxes through a local gateway backed by Docker, Podman, or a VM runtime, or through a remote Kubernetes gateway.
|
|
23
|
+
|
|
24
|
+
Every sandbox requires an active gateway.
|
|
25
|
+
Register and select one before creating a sandbox:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
openshell gateway add <gateway-url> --name <name>
|
|
29
|
+
openshell gateway select <name>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Launch `pi` inside an OpenShell sandbox:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
openshell sandbox create --name pi-sandbox --from pi -- pi
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
In this pattern, the whole `pi` process runs inside the sandbox.
|
|
39
|
+
Built-in tools, `!` commands, and extension tools execute inside the OpenShell boundary.
|
|
40
|
+
|
|
41
|
+
If the gateway is remote, project files are not bind-mounted from the host, meaning writes in the sandbox are not reflected on your machine.
|
|
42
|
+
Clone the repository inside the sandbox or use OpenShell file transfer commands:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
openshell sandbox upload pi-sandbox ./repo /workspace
|
|
46
|
+
openshell sandbox download pi-sandbox /workspace/repo ./repo-out
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
OpenShell providers can keep raw model API keys outside the sandbox.
|
|
50
|
+
When inference routing is configured, code inside the sandbox can call `https://inference.local`, and the gateway injects the configured provider credentials upstream.
|
|
51
|
+
Configure Pi to use the corresponding OpenAI-compatible or Anthropic-compatible endpoint if you want model traffic to use this route.
|
|
52
|
+
|
|
53
|
+
## Gondolin
|
|
54
|
+
|
|
55
|
+
[Gondolin](https://github.com/earendil-works/gondolin) is a local Linux micro-VM.
|
|
56
|
+
Use the [example extension](../examples/extensions/gondolin) when you want `pi` on the host but all built-in tools routed into the VM.
|
|
57
|
+
|
|
58
|
+
Setup:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
cp -R packages/coding-agent/examples/extensions/gondolin ~/.pi/agent/extensions/gondolin
|
|
62
|
+
cd ~/.pi/agent/extensions/gondolin
|
|
63
|
+
npm install --ignore-scripts
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Run from the project you want mounted:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cd /path/to/project
|
|
70
|
+
pi -e ~/.pi/agent/extensions/gondolin
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The extension mounts the host cwd at `/workspace` in the VM and overrides `read`, `write`, `edit`, `bash`, `grep`, `find`, and `ls`.
|
|
74
|
+
User `!` commands are routed into the VM, as well.
|
|
75
|
+
File changes under `/workspace` write through to the host.
|
|
76
|
+
|
|
77
|
+
Requirements: Node.js >= 23.6.0 for `@earendil-works/gondolin`, plus QEMU (requires installation through your package manager).
|
|
78
|
+
|
|
79
|
+
## Plain Docker
|
|
80
|
+
|
|
81
|
+
Run the whole `pi` process in Docker when you want the simplest local container boundary.
|
|
82
|
+
|
|
83
|
+
`Dockerfile.pi`:
|
|
84
|
+
|
|
85
|
+
```dockerfile
|
|
86
|
+
FROM node:24-bookworm-slim
|
|
87
|
+
|
|
88
|
+
RUN apt-get update \
|
|
89
|
+
&& apt-get install -y --no-install-recommends bash ca-certificates git ripgrep \
|
|
90
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
91
|
+
RUN npm install -g --ignore-scripts @earendil-works/pi-coding-agent
|
|
92
|
+
|
|
93
|
+
WORKDIR /workspace
|
|
94
|
+
ENTRYPOINT ["pi"]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Build and run:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
docker build -t pi-sandbox -f Dockerfile.pi .
|
|
101
|
+
|
|
102
|
+
docker run --rm -it \
|
|
103
|
+
-e ANTHROPIC_API_KEY \
|
|
104
|
+
-v "$PWD:/workspace" \
|
|
105
|
+
-v pi-agent-home:/root/.pi/agent \
|
|
106
|
+
pi-sandbox
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The `-v "$PWD:/workspace"` mounts your current directory into the container at /workspace such that reads and writes in `/workspace` inside Docker directly affect your host files, like in the Gondolin example.
|
|
110
|
+
|
|
111
|
+
Use a named volume for `/root/.pi/agent` if you want container-local settings and sessions. Mounting your host `~/.pi/agent` exposes host auth and session files to the container.
|
package/docs/docs.json
CHANGED
package/docs/extensions.md
CHANGED
|
@@ -109,7 +109,7 @@ pi -e ./my-extension.ts
|
|
|
109
109
|
|
|
110
110
|
> **Security:** Extensions run with your full system permissions and can execute arbitrary code. Only install from sources you trust.
|
|
111
111
|
|
|
112
|
-
Extensions are auto-discovered from
|
|
112
|
+
Extensions are auto-discovered from trusted locations. Project-local `.pi/extensions` entries load only after the project is trusted.
|
|
113
113
|
|
|
114
114
|
| Location | Scope |
|
|
115
115
|
|----------|-------|
|
|
@@ -270,6 +270,7 @@ Run `npm install` in the extension directory, then imports from `node_modules/`
|
|
|
270
270
|
```
|
|
271
271
|
pi starts
|
|
272
272
|
│
|
|
273
|
+
├─► project_trust (user/global and CLI extensions only, before project resources load)
|
|
273
274
|
├─► session_start { reason: "startup" }
|
|
274
275
|
└─► resources_discover { reason: "startup" }
|
|
275
276
|
│
|
|
@@ -334,6 +335,25 @@ exit (Ctrl+C, Ctrl+D, SIGHUP, SIGTERM)
|
|
|
334
335
|
└─► session_shutdown
|
|
335
336
|
```
|
|
336
337
|
|
|
338
|
+
### Startup Events
|
|
339
|
+
|
|
340
|
+
#### project_trust
|
|
341
|
+
|
|
342
|
+
Fired before pi decides whether to trust a project with trust inputs (`.pi`, `AGENTS.md`/`CLAUDE.md`, or `.agents/skills`). It runs during startup and when session replacement (for example `/resume`) enters a cwd whose trust has not been resolved in the current process. Only user/global extensions and CLI `-e` extensions participate; project-local extensions are not loaded until after trust is resolved.
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
pi.on("project_trust", async (event, ctx) => {
|
|
346
|
+
// event.cwd - current working directory
|
|
347
|
+
// ctx has a limited trust context: cwd, mode, hasUI, and select/confirm/input/notify UI helpers
|
|
348
|
+
if (await ctx.ui.confirm("Trust project?", event.cwd)) {
|
|
349
|
+
return { trusted: "yes", remember: true };
|
|
350
|
+
}
|
|
351
|
+
return { trusted: "undecided" };
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
A `project_trust` handler must return `{ trusted: "yes" | "no" | "undecided" }`. A user/global or CLI extension that returns `"yes"` or `"no"` owns the decision; the first yes/no decision wins and suppresses the built-in trust prompt. Use `remember: true` to persist a yes/no decision; otherwise it applies only to the current process. Return `"undecided"` to let later handlers or the built-in trust flow decide. Check `ctx.hasUI` before prompting. If no handler returns yes/no, normal trust resolution continues, including the built-in trust prompt when UI is available.
|
|
356
|
+
|
|
337
357
|
### Resource Events
|
|
338
358
|
|
|
339
359
|
#### resources_discover
|
|
@@ -860,9 +880,13 @@ All handlers receive `ctx: ExtensionContext`.
|
|
|
860
880
|
|
|
861
881
|
UI methods for user interaction. See [Custom UI](#custom-ui) for full details.
|
|
862
882
|
|
|
883
|
+
### ctx.mode
|
|
884
|
+
|
|
885
|
+
Current run mode: `"tui"`, `"rpc"`, `"json"`, or `"print"`. Use `ctx.mode === "tui"` to guard terminal-only features such as `custom()`, component factories, terminal input, and direct TUI rendering.
|
|
886
|
+
|
|
863
887
|
### ctx.hasUI
|
|
864
888
|
|
|
865
|
-
`false` in print mode (`-p`) and JSON mode.
|
|
889
|
+
`true` in TUI and RPC modes. `false` in print mode (`-p`) and JSON mode. Use this to guard dialog methods (`select`, `confirm`, `input`, `editor`) and fire-and-forget methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) that work in both TUI and RPC modes. In RPC mode, some TUI-specific methods are no-ops or return defaults (see [rpc.md](rpc.md#extension-ui-protocol)).
|
|
866
890
|
|
|
867
891
|
### ctx.cwd
|
|
868
892
|
|
|
@@ -978,6 +1002,19 @@ pi.on("before_agent_start", (event, ctx) => {
|
|
|
978
1002
|
|
|
979
1003
|
Command handlers receive `ExtensionCommandContext`, which extends `ExtensionContext` with session control methods. These are only available in commands because they can deadlock if called from event handlers.
|
|
980
1004
|
|
|
1005
|
+
### ctx.getSystemPromptOptions()
|
|
1006
|
+
|
|
1007
|
+
Returns the base inputs Pi currently uses to build the system prompt.
|
|
1008
|
+
|
|
1009
|
+
```typescript
|
|
1010
|
+
const options = ctx.getSystemPromptOptions();
|
|
1011
|
+
const contextPaths = options.contextFiles?.map((file) => file.path) ?? [];
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
This has the same shape and mutability as `before_agent_start` `event.systemPromptOptions`: custom prompt, active tools, tool snippets, prompt guidelines, appended system prompt text, cwd, loaded context files, and loaded skills. It may include full context file contents, so treat it as sensitive extension-local data and avoid exposing it through command lists, logs, or autocomplete metadata.
|
|
1015
|
+
|
|
1016
|
+
This reports the current base prompt inputs. It does not include per-turn `before_agent_start` chained system-prompt changes, later `context` event message mutations, or `before_provider_request` payload rewrites.
|
|
1017
|
+
|
|
981
1018
|
### ctx.waitForIdle()
|
|
982
1019
|
|
|
983
1020
|
Wait for the agent to finish streaming:
|
|
@@ -2371,7 +2408,7 @@ const result = await ctx.ui.custom<string | null>(
|
|
|
2371
2408
|
);
|
|
2372
2409
|
```
|
|
2373
2410
|
|
|
2374
|
-
For advanced positioning (anchors, margins, percentages, responsive visibility), pass `overlayOptions`. Use `onHandle` to control visibility programmatically:
|
|
2411
|
+
For advanced positioning (anchors, margins, percentages, responsive visibility), pass `overlayOptions`. Use `onHandle` to control focus or visibility programmatically:
|
|
2375
2412
|
|
|
2376
2413
|
```typescript
|
|
2377
2414
|
const result = await ctx.ui.custom<string | null>(
|
|
@@ -2379,12 +2416,19 @@ const result = await ctx.ui.custom<string | null>(
|
|
|
2379
2416
|
{
|
|
2380
2417
|
overlay: true,
|
|
2381
2418
|
overlayOptions: { anchor: "top-right", width: "50%", margin: 2 },
|
|
2382
|
-
onHandle: (handle) => {
|
|
2419
|
+
onHandle: (handle) => {
|
|
2420
|
+
handle.focus(); // focus this overlay and bring it to the visual front
|
|
2421
|
+
// handle.unfocus({ target: editorComponent }); // release input to a specific component
|
|
2422
|
+
// handle.setHidden(true/false); // toggle visibility
|
|
2423
|
+
// handle.hide(); // permanently remove
|
|
2424
|
+
}
|
|
2383
2425
|
}
|
|
2384
2426
|
);
|
|
2385
2427
|
```
|
|
2386
2428
|
|
|
2387
|
-
|
|
2429
|
+
A focused visible overlay can reclaim input after temporary non-overlay custom UI closes. If you intentionally want another component to keep input while the overlay stays visible, call `handle.unfocus({ target })`. Passing `{ target: null }` releases the overlay without focusing another component.
|
|
2430
|
+
|
|
2431
|
+
See [tui.md](tui.md) for the full `OverlayOptions` and `OverlayHandle` API and [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for examples.
|
|
2388
2432
|
|
|
2389
2433
|
### Custom Editor
|
|
2390
2434
|
|
|
@@ -2509,14 +2553,14 @@ const highlighted = highlightCode(code, lang, theme);
|
|
|
2509
2553
|
|
|
2510
2554
|
## Mode Behavior
|
|
2511
2555
|
|
|
2512
|
-
| Mode |
|
|
2513
|
-
|
|
2514
|
-
| Interactive | Full TUI
|
|
2515
|
-
| RPC (`--mode rpc`) | JSON protocol
|
|
2516
|
-
| JSON (`--mode json`) |
|
|
2517
|
-
| Print (`-p`) |
|
|
2556
|
+
| Mode | `ctx.mode` | `ctx.hasUI` | Notes |
|
|
2557
|
+
|------|------------|-------------|-------|
|
|
2558
|
+
| Interactive | `"tui"` | `true` | Full TUI with terminal rendering |
|
|
2559
|
+
| RPC (`--mode rpc`) | `"rpc"` | `true` | Dialogs and notifications via JSON protocol; `custom()` returns `undefined`. See [rpc.md](rpc.md) |
|
|
2560
|
+
| JSON (`--mode json`) | `"json"` | `false` | Event stream to stdout; UI methods are no-ops |
|
|
2561
|
+
| Print (`-p`) | `"print"` | `false` | Extensions run but can't prompt |
|
|
2518
2562
|
|
|
2519
|
-
|
|
2563
|
+
Use `ctx.mode === "tui"` before TUI-specific features (`custom()`, component factories, terminal input). Use `ctx.hasUI` before dialog and notification methods that work in both TUI and RPC modes.
|
|
2520
2564
|
|
|
2521
2565
|
## Examples Reference
|
|
2522
2566
|
|
|
@@ -2543,6 +2587,7 @@ All examples in [examples/extensions/](../examples/extensions/).
|
|
|
2543
2587
|
| `shutdown-command.ts` | Graceful shutdown command | `registerCommand`, `shutdown()` |
|
|
2544
2588
|
| **Events & Gates** |||
|
|
2545
2589
|
| `permission-gate.ts` | Block dangerous commands | `on("tool_call")`, `ui.confirm` |
|
|
2590
|
+
| `project-trust.ts` | Decide or defer project trust from a user/global or CLI extension | `on("project_trust")`, trust UI, required trust result |
|
|
2546
2591
|
| `protected-paths.ts` | Block writes to specific paths | `on("tool_call")` |
|
|
2547
2592
|
| `confirm-destructive.ts` | Confirm session changes | `on("session_before_switch")`, `on("session_before_fork")` |
|
|
2548
2593
|
| `dirty-repo-guard.ts` | Warn on dirty git repo | `on("session_before_*")`, `exec` |
|
|
@@ -2582,6 +2627,7 @@ All examples in [examples/extensions/](../examples/extensions/).
|
|
|
2582
2627
|
| `ssh.ts` | SSH remote execution | `registerFlag`, `on("user_bash")`, `on("before_agent_start")`, tool operations |
|
|
2583
2628
|
| `interactive-shell.ts` | Persistent shell session | `on("user_bash")` |
|
|
2584
2629
|
| `sandbox/` | Sandboxed tool execution | Tool operations |
|
|
2630
|
+
| `gondolin/` | Route built-in tools and `!` commands into a Gondolin micro-VM | Tool operations, built-in tool overrides, `on("user_bash")` |
|
|
2585
2631
|
| `subagent/` | Spawn sub-agents | `registerTool`, `exec` |
|
|
2586
2632
|
| **Games** |||
|
|
2587
2633
|
| `snake.ts` | Snake game | `registerCommand`, `ui.custom`, keyboard handling |
|
package/docs/index.md
CHANGED
|
@@ -41,6 +41,8 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
41
41
|
- [Quickstart](quickstart.md) - install, authenticate, and run a first session.
|
|
42
42
|
- [Using Pi](usage.md) - interactive mode, slash commands, context files, and CLI reference.
|
|
43
43
|
- [Providers](providers.md) - subscription and API-key setup for built-in providers.
|
|
44
|
+
- [Security](security.md) - project trust, sandbox boundaries, and vulnerability reporting.
|
|
45
|
+
- [Containerization](containerization.md) - sandbox pi with OpenShell, Gondolin, or Docker.
|
|
44
46
|
- [Settings](settings.md) - global and project settings.
|
|
45
47
|
- [Keybindings](keybindings.md) - default shortcuts and custom keybindings.
|
|
46
48
|
- [Sessions](sessions.md) - session management, branching, and tree navigation.
|
package/docs/packages.md
CHANGED
|
@@ -38,7 +38,9 @@ pi update --extension npm:@foo/bar
|
|
|
38
38
|
|
|
39
39
|
These commands manage pi packages, not the pi CLI installation. To uninstall pi itself, see [Quickstart](quickstart.md#uninstall).
|
|
40
40
|
|
|
41
|
-
By default, `install` and `remove` write to user settings (`~/.pi/agent/settings.json`). Use `-l` to write to project settings (`.pi/settings.json`) instead. Project settings can be shared with your team, and pi installs any missing packages automatically on startup.
|
|
41
|
+
By default, `install` and `remove` write to user settings (`~/.pi/agent/settings.json`). Use `-l` to write to project settings (`.pi/settings.json`) instead. Project settings can be shared with your team, and pi installs any missing packages automatically on startup after the project is trusted.
|
|
42
|
+
|
|
43
|
+
Project package commands read project settings only when the project is trusted. Use `--approve` to trust project-local files for one command, or `--no-approve` to ignore them for one command.
|
|
42
44
|
|
|
43
45
|
To try a package without installing it, use `--extension` or `-e`. This installs to a temporary directory for the current run only:
|
|
44
46
|
|
package/docs/prompt-templates.md
CHANGED
|
@@ -9,7 +9,7 @@ Prompt templates are Markdown snippets that expand into full prompts. Type `/nam
|
|
|
9
9
|
Pi loads prompt templates from:
|
|
10
10
|
|
|
11
11
|
- Global: `~/.pi/agent/prompts/*.md`
|
|
12
|
-
- Project: `.pi/prompts/*.md`
|
|
12
|
+
- Project: `.pi/prompts/*.md` (only after the project is trusted)
|
|
13
13
|
- Packages: `prompts/` directories or `pi.prompts` entries in `package.json`
|
|
14
14
|
- Settings: `prompts` array with files or directories
|
|
15
15
|
- CLI: `--prompt-template <path>` (repeatable)
|
package/docs/providers.md
CHANGED
|
@@ -49,9 +49,11 @@ pi
|
|
|
49
49
|
| Provider | Environment Variable | `auth.json` key |
|
|
50
50
|
|----------|----------------------|------------------|
|
|
51
51
|
| Anthropic | `ANTHROPIC_API_KEY` | `anthropic` |
|
|
52
|
+
| Ant Ling | `ANT_LING_API_KEY` | `ant-ling` |
|
|
52
53
|
| Azure OpenAI Responses | `AZURE_OPENAI_API_KEY` | `azure-openai-responses` |
|
|
53
54
|
| OpenAI | `OPENAI_API_KEY` | `openai` |
|
|
54
55
|
| DeepSeek | `DEEPSEEK_API_KEY` | `deepseek` |
|
|
56
|
+
| NVIDIA NIM | `NVIDIA_API_KEY` | `nvidia` |
|
|
55
57
|
| Google Gemini | `GEMINI_API_KEY` | `google` |
|
|
56
58
|
| Mistral | `MISTRAL_API_KEY` | `mistral` |
|
|
57
59
|
| Groq | `GROQ_API_KEY` | `groq` |
|
|
@@ -62,6 +64,7 @@ pi
|
|
|
62
64
|
| OpenRouter | `OPENROUTER_API_KEY` | `openrouter` |
|
|
63
65
|
| Vercel AI Gateway | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway` |
|
|
64
66
|
| ZAI | `ZAI_API_KEY` | `zai` |
|
|
67
|
+
| ZAI Coding Plan (China) | `ZAI_CODING_CN_API_KEY` | `zai-coding-cn` |
|
|
65
68
|
| OpenCode Zen | `OPENCODE_API_KEY` | `opencode` |
|
|
66
69
|
| OpenCode Go | `OPENCODE_API_KEY` | `opencode-go` |
|
|
67
70
|
| Hugging Face | `HF_TOKEN` | `huggingface` |
|
|
@@ -84,8 +87,10 @@ Store credentials in `~/.pi/agent/auth.json`:
|
|
|
84
87
|
```json
|
|
85
88
|
{
|
|
86
89
|
"anthropic": { "type": "api_key", "key": "sk-ant-..." },
|
|
90
|
+
"ant-ling": { "type": "api_key", "key": "..." },
|
|
87
91
|
"openai": { "type": "api_key", "key": "sk-..." },
|
|
88
92
|
"deepseek": { "type": "api_key", "key": "sk-..." },
|
|
93
|
+
"nvidia": { "type": "api_key", "key": "nvapi-..." },
|
|
89
94
|
"google": { "type": "api_key", "key": "..." },
|
|
90
95
|
"opencode": { "type": "api_key", "key": "..." },
|
|
91
96
|
"opencode-go": { "type": "api_key", "key": "..." },
|
package/docs/rpc.md
CHANGED
|
@@ -1003,7 +1003,7 @@ Some `ExtensionUIContext` methods are not supported or degraded in RPC mode beca
|
|
|
1003
1003
|
- `getTheme()` returns `undefined`
|
|
1004
1004
|
- `setTheme()` returns `{ success: false, error: "..." }`
|
|
1005
1005
|
|
|
1006
|
-
Note: `ctx.hasUI` is `true` in RPC mode because the dialog and fire-and-forget methods are functional via the extension UI sub-protocol.
|
|
1006
|
+
Note: `ctx.mode` is `"rpc"` and `ctx.hasUI` is `true` in RPC mode because the dialog and fire-and-forget methods are functional via the extension UI sub-protocol. Use `ctx.mode === "tui"` to guard TUI-specific features like `custom()` that require a real terminal.
|
|
1007
1007
|
|
|
1008
1008
|
### Extension UI Requests (stdout)
|
|
1009
1009
|
|
package/docs/sdk.md
CHANGED
package/docs/security.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Pi is a local coding agent. It runs with the permissions of the user account that starts it, and it treats files writable by that user as inside the same local trust boundary.
|
|
4
|
+
|
|
5
|
+
## Project Trust
|
|
6
|
+
|
|
7
|
+
Project trust controls whether pi loads project-local inputs. It is not a sandbox and it does not restrict what the model can ask tools to do after you start working in a directory.
|
|
8
|
+
|
|
9
|
+
Pi considers a project to have trust inputs when it finds any of these from the current working directory:
|
|
10
|
+
|
|
11
|
+
- `.pi/` in the current directory
|
|
12
|
+
- `AGENTS.md` or `CLAUDE.md` in the current directory or an ancestor directory
|
|
13
|
+
- `.agents/skills` in the current directory or an ancestor directory
|
|
14
|
+
|
|
15
|
+
When an interactive session starts in a project with trust inputs and no saved decision, pi asks whether to trust the project. Saved decisions are stored per canonical working directory in `~/.pi/agent/trust.json`.
|
|
16
|
+
|
|
17
|
+
Trusting a project allows pi to load project-local inputs, including:
|
|
18
|
+
|
|
19
|
+
- project instructions from `AGENTS.md` or `CLAUDE.md`
|
|
20
|
+
- `.pi/settings.json`
|
|
21
|
+
- `.pi` resources such as extensions, skills, prompt templates, themes, and system prompt files
|
|
22
|
+
- missing project packages configured through project settings
|
|
23
|
+
- project-local extensions and project package-managed extensions
|
|
24
|
+
|
|
25
|
+
Declining trust skips those project-local inputs. Before trust is resolved, pi only loads user/global extensions and CLI `-e` extensions. User/global and CLI extensions can handle the `project_trust` event; the first extension that returns a yes/no decision owns the decision.
|
|
26
|
+
|
|
27
|
+
Non-interactive modes (`-p`, `--mode json`, and `--mode rpc`) do not show a trust prompt. Without a saved trust decision, they ignore project-local inputs unless `--approve`/`-a` is passed. Use `--no-approve`/`-na` to ignore project-local inputs for one run even when the project is trusted.
|
|
28
|
+
|
|
29
|
+
## No Built-in Sandbox
|
|
30
|
+
|
|
31
|
+
Pi does not include a built-in sandbox. Built-in tools can read files, write files, edit files, and run shell commands with the permissions of the pi process. Extensions are TypeScript modules that run with the same permissions. Package installs, shell commands, language servers, test commands, and other developer tools behave as ordinary local processes.
|
|
32
|
+
|
|
33
|
+
This is intentional. Pi is designed to operate on local source trees, invoke project toolchains, and integrate with the user's existing development environment. A partial in-process sandbox would be easy to misunderstand as a security boundary while still depending on the host shell, filesystem, package managers, credentials, and extension code. Real isolation needs to come from the operating system or a virtualization/container boundary.
|
|
34
|
+
|
|
35
|
+
Project trust is only an input-loading guard. It prevents a repository from silently changing pi's instructions, settings, or extensions before you approve it. It does not make untrusted code, untrusted prompts, or untrusted model output safe. Prompt injection from repository files, comments, documentation, or build output is expected local-agent risk and cannot be reliably prevented by pi.
|
|
36
|
+
|
|
37
|
+
## Running Untrusted or Unmonitored Work
|
|
38
|
+
|
|
39
|
+
For untrusted repositories, generated code you do not intend to monitor closely, or unattended automation, run pi in a contained environment. Use a container, VM, micro-VM, remote sandbox, or policy-controlled sandbox with only the files and credentials required for the task.
|
|
40
|
+
|
|
41
|
+
Common patterns are documented in [Containerization](containerization.md):
|
|
42
|
+
|
|
43
|
+
- run the whole `pi` process inside OpenShell or Docker
|
|
44
|
+
- run host pi while routing built-in tool execution into a Gondolin micro-VM
|
|
45
|
+
- mount only the workspace paths the agent should access
|
|
46
|
+
- avoid mounting host `~/.pi/agent` unless the container should access host sessions, settings, and credentials
|
|
47
|
+
- pass the minimum required API keys or use short-lived credentials
|
|
48
|
+
- restrict network access when the task does not need it
|
|
49
|
+
- review diffs and outputs before copying results back to trusted systems
|
|
50
|
+
|
|
51
|
+
If you bind-mount a host workspace read/write, writes from inside the container or VM can still modify host files. Use read-only mounts or copy files into and out of the sandbox when you need stronger protection from unintended writes.
|
|
52
|
+
|
|
53
|
+
## Reporting Security Issues
|
|
54
|
+
|
|
55
|
+
To report a security issue, follow the repository [Security Policy](https://github.com/earendil-works/pi-mono/blob/main/SECURITY.md). Do not open a public issue for security-sensitive reports.
|
|
56
|
+
|
|
57
|
+
Expected local-agent behavior, lack of a built-in sandbox, prompt injection from untrusted content, and behavior of user-installed extensions or skills are generally outside the security boundary unless the report demonstrates a real privilege-boundary bypass or shows how pi grants access that the local user did not already have.
|
package/docs/settings.md
CHANGED
|
@@ -9,6 +9,16 @@ Pi uses JSON settings files with project settings overriding global settings.
|
|
|
9
9
|
|
|
10
10
|
Edit directly or use `/settings` for common options.
|
|
11
11
|
|
|
12
|
+
## Project Trust
|
|
13
|
+
|
|
14
|
+
On interactive startup, pi asks before trusting a project folder that contains project-local inputs and has no saved decision in `~/.pi/agent/trust.json`. Trusting a project allows pi to read project instructions (`AGENTS.md`/`CLAUDE.md`), load `.pi/settings.json` and `.pi` resources, install missing project packages, and execute project extensions.
|
|
15
|
+
|
|
16
|
+
Non-interactive modes (`-p`, `--mode json`, and `--mode rpc`) do not show a trust prompt. Without a saved trust decision, they ignore project-local inputs unless `--approve`/`-a` is passed. Use `--no-approve`/`-na` to ignore project-local inputs for one run even when the project is trusted.
|
|
17
|
+
|
|
18
|
+
`pi config` assumes project trust for that command so you can view and change project resource settings before starting a session. It does not save a trust decision; starting a session in that folder still prompts. Pass `--no-approve` to hide project-local inputs in `pi config`.
|
|
19
|
+
|
|
20
|
+
Use `/trust` in interactive mode to save a project trust decision for future sessions. It writes `~/.pi/agent/trust.json` only; the current session is not reloaded, so restart pi for changes to take effect.
|
|
21
|
+
|
|
12
22
|
## All Settings
|
|
13
23
|
|
|
14
24
|
### Model & Thinking
|
package/docs/skills.md
CHANGED
|
@@ -26,7 +26,7 @@ Pi loads skills from:
|
|
|
26
26
|
- Global:
|
|
27
27
|
- `~/.pi/agent/skills/`
|
|
28
28
|
- `~/.agents/skills/`
|
|
29
|
-
- Project:
|
|
29
|
+
- Project (only after the project is trusted):
|
|
30
30
|
- `.pi/skills/`
|
|
31
31
|
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
|
32
32
|
- Packages: `skills/` directories or `pi.skills` entries in `package.json`
|
package/docs/terminal-setup.md
CHANGED
|
@@ -40,7 +40,7 @@ If you want `Shift+Enter` to keep working in tmux via that remap, add `ctrl+j` t
|
|
|
40
40
|
|
|
41
41
|
## WezTerm
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
WezTerm usually works out of the box for `Shift+Enter` via xterm modifyOtherKeys. To use the Kitty keyboard protocol explicitly, create `~/.wezterm.lua`:
|
|
44
44
|
|
|
45
45
|
```lua
|
|
46
46
|
local wezterm = require 'wezterm'
|
|
@@ -49,16 +49,50 @@ config.enable_kitty_keyboard = true
|
|
|
49
49
|
return config
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
On macOS, WezTerm binds `Option+Enter` to fullscreen by default. To use `Option+Enter` for pi follow-up queueing, add this key override:
|
|
53
|
+
|
|
54
|
+
```lua
|
|
55
|
+
local wezterm = require 'wezterm'
|
|
56
|
+
local config = wezterm.config_builder()
|
|
57
|
+
config.keys = {
|
|
58
|
+
{
|
|
59
|
+
key = 'Enter',
|
|
60
|
+
mods = 'ALT',
|
|
61
|
+
action = wezterm.action.SendString('\x1b[13;3u'),
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
return config
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
If you already have a `config.keys` table, add the entry to it.
|
|
68
|
+
|
|
52
69
|
On WSL, WezTerm may require a visible hardware cursor for IME candidate window positioning. If CJK IME candidates do not follow the text cursor, set `PI_HARDWARE_CURSOR=1` before running pi or set `showHardwareCursor` to `true` in settings.
|
|
53
70
|
|
|
71
|
+
## Alacritty
|
|
72
|
+
|
|
73
|
+
Alacritty usually works out of the box for `Shift+Enter`. On macOS, `Option+Enter` may arrive as plain `Enter`. To use `Option+Enter` for pi follow-up queueing, add to `~/.config/alacritty/alacritty.toml`:
|
|
74
|
+
|
|
75
|
+
```toml
|
|
76
|
+
[[keyboard.bindings]]
|
|
77
|
+
key = "Enter"
|
|
78
|
+
mods = "Alt"
|
|
79
|
+
chars = "\u001b[13;3u"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Restart Alacritty after changing the config.
|
|
83
|
+
|
|
54
84
|
## VS Code (Integrated Terminal)
|
|
55
85
|
|
|
86
|
+
VS Code 1.109.5 and newer enable Kitty keyboard protocol in the integrated terminal by default, so `Shift+Enter` should work out of the box.
|
|
87
|
+
|
|
88
|
+
VS Code versions older than 1.109.5 need an explicit terminal keybinding for `Shift+Enter`.
|
|
89
|
+
|
|
56
90
|
`keybindings.json` locations:
|
|
57
91
|
- macOS: `~/Library/Application Support/Code/User/keybindings.json`
|
|
58
92
|
- Linux: `~/.config/Code/User/keybindings.json`
|
|
59
93
|
- Windows: `%APPDATA%\\Code\\User\\keybindings.json`
|
|
60
94
|
|
|
61
|
-
Add to `keybindings.json
|
|
95
|
+
Add to `keybindings.json`:
|
|
62
96
|
|
|
63
97
|
```json
|
|
64
98
|
{
|
package/docs/themes.md
CHANGED
|
@@ -20,7 +20,7 @@ Pi loads themes from:
|
|
|
20
20
|
|
|
21
21
|
- Built-in: `dark`, `light`
|
|
22
22
|
- Global: `~/.pi/agent/themes/*.json`
|
|
23
|
-
- Project: `.pi/themes/*.json`
|
|
23
|
+
- Project: `.pi/themes/*.json` (only after the project is trusted)
|
|
24
24
|
- Packages: `themes/` directories or `pi.themes` entries in `package.json`
|
|
25
25
|
- Settings: `themes` array with files or directories
|
|
26
26
|
- CLI: `--theme <path>` (repeatable)
|
package/docs/tmux.md
CHANGED
|
@@ -18,7 +18,7 @@ tmux kill-server
|
|
|
18
18
|
tmux
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
Pi requests extended key reporting automatically when Kitty keyboard protocol is not available. With `extended-keys-format csi-u`, tmux forwards modified keys in CSI-u format, which is the most reliable configuration.
|
|
21
|
+
Pi requests extended key reporting automatically when Kitty keyboard protocol is not available. With `extended-keys-format csi-u`, tmux forwards modified keys in CSI-u format, which is the most reliable configuration. The `extended-keys-format` option requires tmux 3.5 or later.
|
|
22
22
|
|
|
23
23
|
## Why `csi-u` Is Recommended
|
|
24
24
|
|
|
@@ -57,5 +57,7 @@ This affects the default keybindings (`Enter` to submit, `Shift+Enter` for newli
|
|
|
57
57
|
|
|
58
58
|
## Requirements
|
|
59
59
|
|
|
60
|
-
- tmux 3.
|
|
60
|
+
- tmux 3.5 or later for `extended-keys-format csi-u` (run `tmux -V` to check)
|
|
61
61
|
- A terminal emulator that supports extended keys (Ghostty, Kitty, iTerm2, WezTerm, Windows Terminal)
|
|
62
|
+
|
|
63
|
+
With tmux 3.2 through 3.4, omit `extended-keys-format csi-u`; Pi still supports tmux's default xterm `modifyOtherKeys` format.
|
package/docs/tui.md
CHANGED
|
@@ -145,8 +145,11 @@ const result = await ctx.ui.custom<string | null>(
|
|
|
145
145
|
// Responsive: hide on narrow terminals
|
|
146
146
|
visible: (termWidth, termHeight) => termWidth >= 80,
|
|
147
147
|
},
|
|
148
|
-
// Get handle for programmatic visibility control
|
|
148
|
+
// Get handle for programmatic focus and visibility control
|
|
149
149
|
onHandle: (handle) => {
|
|
150
|
+
// handle.focus() - focus this overlay and bring it to the visual front
|
|
151
|
+
// handle.unfocus() - release input to normal fallback
|
|
152
|
+
// handle.unfocus({ target }) - release input to a specific component or null
|
|
150
153
|
// handle.setHidden(true/false) - toggle visibility
|
|
151
154
|
// handle.hide() - permanently remove
|
|
152
155
|
},
|
|
@@ -154,6 +157,12 @@ const result = await ctx.ui.custom<string | null>(
|
|
|
154
157
|
);
|
|
155
158
|
```
|
|
156
159
|
|
|
160
|
+
### Overlay Focus
|
|
161
|
+
|
|
162
|
+
A focused visible overlay keeps input ownership across temporary non-overlay UI. If an overlay opens another `ctx.ui.custom()` component without `{ overlay: true }`, that replacement UI receives input while it is active; when it closes, the focused overlay can reclaim input.
|
|
163
|
+
|
|
164
|
+
Use `handle.unfocus()` when a visible overlay should stop owning input and let TUI fall back to another visible capturing overlay or the previous focus target. Use `handle.unfocus({ target })` when a specific component should receive input while the overlay stays visible. Passing `{ target: null }` intentionally leaves no focused component until focus is set again.
|
|
165
|
+
|
|
157
166
|
### Overlay Lifecycle
|
|
158
167
|
|
|
159
168
|
Overlay components are disposed when closed. Don't reuse references - create fresh instances:
|
package/docs/usage.md
CHANGED
|
@@ -96,8 +96,8 @@ See [Sessions](sessions.md) and [Compaction](compaction.md) for details.
|
|
|
96
96
|
Pi loads `AGENTS.md` or `CLAUDE.md` at startup from:
|
|
97
97
|
|
|
98
98
|
- `~/.pi/agent/AGENTS.md` for global instructions
|
|
99
|
-
- parent directories, walking up from the current working directory
|
|
100
|
-
- the current directory
|
|
99
|
+
- parent directories, walking up from the current working directory when the project is trusted
|
|
100
|
+
- the current directory when the project is trusted
|
|
101
101
|
|
|
102
102
|
Use context files for project conventions, commands, safety rules, and preferences. Disable loading with `--no-context-files` or `-nc`.
|
|
103
103
|
|
|
@@ -110,6 +110,16 @@ Replace the default system prompt with:
|
|
|
110
110
|
|
|
111
111
|
Append to the default prompt without replacing it with `APPEND_SYSTEM.md` in either location.
|
|
112
112
|
|
|
113
|
+
### Project Trust
|
|
114
|
+
|
|
115
|
+
On interactive startup, pi asks before trusting a project folder that contains project-local inputs and has no saved decision in `~/.pi/agent/trust.json`. Trusting a project allows pi to read project instructions (`AGENTS.md`/`CLAUDE.md`), load `.pi/settings.json` and `.pi` resources, install missing project packages, and execute project extensions.
|
|
116
|
+
|
|
117
|
+
Non-interactive modes (`-p`, `--mode json`, and `--mode rpc`) do not show a trust prompt. Without a saved trust decision, they ignore project-local inputs unless `--approve`/`-a` is passed. Use `--no-approve`/`-na` to ignore project-local inputs for one run even when the project is trusted.
|
|
118
|
+
|
|
119
|
+
`pi config` assumes project trust for that command so you can view and change project resource settings before starting a session. It does not save a trust decision; starting a session in that folder still prompts. Pass `--no-approve` to hide project-local inputs in `pi config`.
|
|
120
|
+
|
|
121
|
+
Use `/trust` in interactive mode to save a project trust decision for future sessions. It writes `~/.pi/agent/trust.json` only; the current session is not reloaded, so restart pi for changes to take effect.
|
|
122
|
+
|
|
113
123
|
## Exporting and Sharing Sessions
|
|
114
124
|
|
|
115
125
|
Use `/export [file]` to write a session to HTML.
|
|
@@ -138,7 +148,7 @@ pi list # List installed packages
|
|
|
138
148
|
pi config # Enable/disable package resources
|
|
139
149
|
```
|
|
140
150
|
|
|
141
|
-
These commands manage pi packages, not the pi CLI installation. To uninstall pi itself, see [Quickstart](quickstart.md#uninstall).
|
|
151
|
+
These commands manage pi packages, not the pi CLI installation. To uninstall pi itself, see [Quickstart](quickstart.md#uninstall). Project package commands accept `--approve`/`--no-approve` to trust or ignore project-local package settings for one command.
|
|
142
152
|
|
|
143
153
|
See [Pi Packages](packages.md) for package sources and security notes.
|
|
144
154
|
|
|
@@ -219,6 +229,8 @@ pi --no-extensions -e ./my-extension.ts
|
|
|
219
229
|
| `--system-prompt <text>` | Replace default prompt; context files and skills are still appended |
|
|
220
230
|
| `--append-system-prompt <text>` | Append to system prompt |
|
|
221
231
|
| `--verbose` | Force verbose startup |
|
|
232
|
+
| `-a`, `--approve` | Trust project-local files for this run |
|
|
233
|
+
| `-na`, `--no-approve` | Ignore project-local files for this run |
|
|
222
234
|
| `-h`, `--help` | Show help |
|
|
223
235
|
| `-v`, `--version` | Show version |
|
|
224
236
|
|
|
@@ -275,7 +287,7 @@ pi --exclude-tools ask_question
|
|
|
275
287
|
| `PI_PACKAGE_DIR` | Override package directory, useful for Nix/Guix store paths |
|
|
276
288
|
| `PI_OFFLINE` | Disable startup network operations, including update checks, package update checks, and install/update telemetry |
|
|
277
289
|
| `PI_SKIP_VERSION_CHECK` | Skip the Pi version update check at startup. This prevents the `pi.dev` latest-version request |
|
|
278
|
-
| `PI_TELEMETRY` | Override install/update telemetry: `1`/`true`/`yes` or `0`/`false`/`no`. This does not disable update checks |
|
|
290
|
+
| `PI_TELEMETRY` | Override install/update telemetry and provider attribution headers: `1`/`true`/`yes` or `0`/`false`/`no`. This does not disable update checks |
|
|
279
291
|
| `PI_CACHE_RETENTION` | Set to `long` for extended prompt cache where supported |
|
|
280
292
|
| `VISUAL`, `EDITOR` | External editor for Ctrl+G |
|
|
281
293
|
|
|
@@ -19,10 +19,12 @@ cp permission-gate.ts ~/.pi/agent/extensions/
|
|
|
19
19
|
| Extension | Description |
|
|
20
20
|
|-----------|-------------|
|
|
21
21
|
| `permission-gate.ts` | Prompts for confirmation before dangerous bash commands (rm -rf, sudo, etc.) |
|
|
22
|
+
| `project-trust.ts` | Demonstrates the `project_trust` event for user/global and CLI extensions |
|
|
22
23
|
| `protected-paths.ts` | Blocks writes to protected paths (.env, .git/, node_modules/) |
|
|
23
24
|
| `confirm-destructive.ts` | Confirms before destructive session actions (clear, switch, fork) |
|
|
24
25
|
| `dirty-repo-guard.ts` | Prevents session changes with uncommitted git changes |
|
|
25
26
|
| `sandbox/` | OS-level sandboxing using `@anthropic-ai/sandbox-runtime` with per-project config |
|
|
27
|
+
| `gondolin/` | Route built-in tools and `!` commands into a Gondolin micro-VM |
|
|
26
28
|
|
|
27
29
|
### Custom Tools
|
|
28
30
|
|
|
@@ -47,7 +47,7 @@ function getPiMascot(theme: Theme): string[] {
|
|
|
47
47
|
export default function (pi: ExtensionAPI) {
|
|
48
48
|
// Set custom header immediately on load (if UI is available)
|
|
49
49
|
pi.on("session_start", async (_event, ctx) => {
|
|
50
|
-
if (ctx.
|
|
50
|
+
if (ctx.mode === "tui") {
|
|
51
51
|
ctx.ui.setHeader((_tui, theme) => {
|
|
52
52
|
return {
|
|
53
53
|
render(_width: number): string[] {
|