From 789b22f350bdaae7c8d441ca8768fd0aa255ec8a Mon Sep 17 00:00:00 2001 From: Christian Klotz Date: Thu, 10 Sep 2026 14:35:10 +0200 Subject: [PATCH] docs(coding-agent): improve runtime and reference guidance --- packages/coding-agent/docs/configuration.md | 6 +- .../coding-agent/docs/containerization.md | 199 ++++++++++-------- packages/coding-agent/docs/docs.json | 76 +++---- .../docs/environment-variables.md | 4 +- packages/coding-agent/docs/interactive-use.md | 4 +- .../coding-agent/docs/models-and-providers.md | 10 +- packages/coding-agent/docs/models.md | 2 +- .../coding-agent/docs/prompt-templates.md | 2 +- .../coding-agent/docs/provider-reference.md | 8 +- packages/coding-agent/docs/rpc.md | 6 +- packages/coding-agent/docs/sdk.md | 2 +- packages/coding-agent/docs/security.md | 102 ++++++--- .../coding-agent/docs/settings-reference.md | 14 +- packages/coding-agent/docs/shell-aliases.md | 90 +++++++- packages/coding-agent/docs/terminal-setup.md | 183 +++++++++------- packages/coding-agent/docs/termux.md | 191 ++++++++--------- packages/coding-agent/docs/tmux.md | 72 +++---- packages/coding-agent/docs/windows.md | 60 ++++-- 18 files changed, 609 insertions(+), 422 deletions(-) diff --git a/packages/coding-agent/docs/configuration.md b/packages/coding-agent/docs/configuration.md index 95caf10de..7298de94f 100644 --- a/packages/coding-agent/docs/configuration.md +++ b/packages/coding-agent/docs/configuration.md @@ -25,9 +25,9 @@ For options that are not available through `/settings`, edit one of these files: Project settings override global settings. Nested setting objects are merged. Paths in global settings resolve from `~/.pi/agent`; paths in project settings resolve from `.pi`. -Use global settings for personal defaults. Use project settings only for behavior that should follow the repository. Project settings can load executable resources, so review [Project Trust](security.md#project-trust) before accepting them. +Use global settings for personal defaults. Use project settings only for behavior that should follow the repository. Project settings can load executable resources, so review [Project trust](security.md#understand-project-trust) before accepting them. -Model defaults use separate selectors. In `/model`, press `Ctrl+S` to save the selected startup model. In `/thinking`, press `Ctrl+S` to save the startup thinking level. See [Models and Providers](models-and-providers.md). +Model defaults use separate selectors. In `/model`, press `Ctrl+S` to save the selected startup model. In `/thinking`, press `Ctrl+S` to save the startup thinking level. See [Choose a Model](models-and-providers.md). The complete setting names, types, defaults, and precedence rules are in [Settings](settings-reference.md). @@ -78,7 +78,7 @@ Pi automatically watches only the active personal theme at `~/.pi/agent/themes/< Each resource guide covers its file format and discovery exceptions: [Extensions](extensions.md), [Skills](skills.md), [Prompt Templates](prompt-templates.md), [Themes](themes.md), and [Pi Packages](packages.md). -## Verify a change +## Verify configuration changes Use the interface that owns the configuration: diff --git a/packages/coding-agent/docs/containerization.md b/packages/coding-agent/docs/containerization.md index b83d69e39..f65b94e8f 100644 --- a/packages/coding-agent/docs/containerization.md +++ b/packages/coding-agent/docs/containerization.md @@ -1,53 +1,39 @@ -# Containerization +# Run Pi in an isolated environment -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. +Use an isolated environment to limit the files, credentials, processes, and network services that generated commands can access or affect. -There are two general options. You can either -1. run the whole `pi` process inside an isolated environment, or -2. run `pi` on the host and route tool execution into an isolated environment. +You can isolate the complete Pi process or keep Pi on the host and route selected tools into an isolated environment. -## Choose a pattern +## Choose an isolation method -| Pattern | What is isolated | Best for | Notes | -| --- | --- | --- | --- | -| Gondolin extension | Built-in tools and `!` commands | Local micro-VM isolation while keeping auth on host | See [`examples/extensions/gondolin/`](../examples/extensions/gondolin/). | -| Plain Docker | Whole `pi` process in a local container | Simple local isolation | Provider API keys enter the container. | -| OpenShell | Whole `pi` process in a policy-controlled sandbox | Local or remote managed sandbox | Requires an OpenShell gateway | -| Docker Sandboxes | Whole `pi` process in a managed sandbox | Local isolation with provider keys kept on the host | Requires Docker Sandboxes (`sbx`). | +| Method | Where Pi runs | What is isolated | Credential handling | Best for | +|---|---|---|---|---| +| Plain Docker | Container | Pi, built-in tools, `!` commands, and extensions | Credentials passed into the container | A straightforward local container boundary | +| Docker Sandboxes | Managed sandbox | Pi, built-in tools, `!` commands, and extensions | Provider credentials remain on the host and are substituted by the proxy | Managed local isolation without exposing the real provider key | +| OpenShell | Local or remote sandbox | Pi, built-in tools, `!` commands, and extensions | Policy-controlled credentials and inference routing | Filesystem, process, network, and credential policies | +| Gondolin extension | Host | Built-in tools and `!` commands | Stored Pi credentials remain on the host, but commands inherit host environment variables | A local micro-VM for tool execution while retaining the host interface | -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. +The method changes where extensions run. When the complete Pi process runs inside an isolated environment, its extensions run there too. When host Pi delegates built-in tools through Gondolin, other extension tools still run on the host unless they also delegate their work. -## Gondolin +## Decide what Pi can access -[Gondolin](https://github.com/earendil-works/gondolin) is a local Linux micro-VM. -Use the [example extension](../examples/extensions/gondolin) when you want `pi` on the host but all built-in tools routed into the VM. +An isolated process can still affect resources you expose to it: -Setup: +- A read-write host mount lets Pi modify those host files. +- Mounting `~/.pi/agent` exposes your Pi credentials, settings, extensions, and sessions. +- Environment variables passed into a container are available to processes inside it. +- Network access may allow code or tool output to leave the environment. +- Tool-only isolation does not constrain the host Pi process or extension tools that do not use the isolated backend. -```bash -cp -R packages/coding-agent/examples/extensions/gondolin ~/.pi/agent/extensions/gondolin -cd ~/.pi/agent/extensions/gondolin -npm install --ignore-scripts -``` +Expose only the working folder, credentials, and network destinations needed for the task. Use read-only mounts or copy files into and out of the environment when you do not want writes to affect the host. -Run from the project you want mounted: +## Run Pi in plain Docker -```bash -cd /path/to/project -pi -e ~/.pi/agent/extensions/gondolin -``` +Plain Docker provides the simplest whole-process container boundary. -The extension mounts the host cwd at `/workspace` in the VM and overrides `read`, `write`, `edit`, `bash`, `grep`, `find`, and `ls`. -User `!` commands are routed into the VM, as well. -File changes under `/workspace` write through to the host. +### Build the image -Requirements: Node.js >= 23.6.0 for `@earendil-works/gondolin`, plus QEMU (requires installation through your package manager). - -## Plain Docker - -Run the whole `pi` process in Docker when you want the simplest local container boundary. - -`Dockerfile.pi`: +Create `Dockerfile.pi`: ```dockerfile FROM node:24-bookworm-slim @@ -61,11 +47,17 @@ WORKDIR /workspace ENTRYPOINT ["pi"] ``` -Build and run: +Build it from the directory containing the file: ```bash docker build -t pi-sandbox -f Dockerfile.pi . +``` +### Start Pi + +From the working folder you want Pi to access, run: + +```bash docker run --rm -it \ -e ANTHROPIC_API_KEY \ -v "$PWD:/workspace" \ @@ -73,56 +65,29 @@ docker run --rm -it \ pi-sandbox ``` -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. +Replace `ANTHROPIC_API_KEY` with the credential required by your provider. The named `pi-agent-home` volume keeps container-local settings, credentials, and sessions between runs. -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. +Do not mount the host's `~/.pi/agent` unless the container should have access to your host Pi configuration and credentials. -## OpenShell +### Verify the workspace -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. -OpenShell can run sandboxes through a local gateway backed by Docker, Podman, or a VM runtime, or through a remote Kubernetes gateway. +Inside Pi, run: -Every sandbox requires an active gateway. -Register and select one before creating a sandbox: - -```bash -openshell gateway add --name -openshell gateway select +```text +!pwd ``` -Launch `pi` inside an OpenShell sandbox: +The command should report `/workspace`. Changes under `/workspace` write through to the mounted host folder. Remove the bind mount or use a read-only mount when that is not acceptable. -```bash -openshell sandbox create --name pi-sandbox --from pi -- pi -``` +## Run Pi with Docker Sandboxes -In this pattern, the whole `pi` process runs inside the sandbox. -Built-in tools, `!` commands, and extension tools execute inside the OpenShell boundary. +[Docker Sandboxes](https://docs.docker.com/ai/sandboxes/) runs the complete Pi process inside a managed sandbox. Its proxy can keep the real provider credential on the host and substitute it when requests leave the sandbox. -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. -Clone the repository inside the sandbox or use OpenShell file transfer commands: +Configure credentials before creating the sandbox. Do not run `/login` inside the sandbox because that writes a real credential into it. -```bash -openshell sandbox upload pi-sandbox ./repo /workspace -openshell sandbox download pi-sandbox /workspace/repo ./repo-out -``` +### Use a Claude Pro or Max token -OpenShell providers can keep raw model API keys outside the sandbox. -When inference routing is configured, code inside the sandbox can call `https://inference.local`, and the gateway injects the configured provider credentials upstream. -Configure Pi to use the corresponding OpenAI-compatible or Anthropic-compatible endpoint if you want model traffic to use this route. - -## Docker Sandboxes - -[Docker Sandboxes](https://docs.docker.com/ai/sandboxes/) is a managed sandbox runtime from Docker that runs the whole `pi` process inside a sandbox. -It is one of the container boundaries [No Built-in Sandbox](security.md#no-built-in-sandbox) points to. - -Unlike the Plain Docker pattern above, the provider credential is not passed into the container. -The sandbox receives a sentinel value instead, and the `sbx` proxy substitutes the real credential on egress to `api.anthropic.com`. -Credentials are wired at creation time, so store yours on the host before you create the sandbox. - -For a Claude Pro/Max subscription, run `claude setup-token` on a machine with Claude Code, then store the result on the host. -If an `anthropic` secret is already bound, remove it first: otherwise the proxy adds an `x-api-key` header alongside the Bearer token and Anthropic rejects the request. -`sbx secret set-custom` reads the token from stdin, so it stays out of shell history. +Generate the token with `claude setup-token` on a machine with Claude Code. If an `anthropic` secret is already configured, remove it first so the proxy does not add an API-key header alongside the bearer token: ```bash sbx secret rm anthropic @@ -133,24 +98,86 @@ sbx secret set-custom \ --placeholder 'sk-ant-oat01-{rand}' ``` -The sandbox gets an OAuth-shaped placeholder, not the real token, and the proxy swaps it on egress to that host; `ANTHROPIC_OAUTH_TOKEN` is a variable pi already reads and prefers over an API key, so no extra pi configuration is needed. +`sbx secret set-custom` reads the real token from standard input. The sandbox receives an OAuth-shaped placeholder, which the proxy replaces only for requests to the configured host. -For an API key, store it with `sbx secret set anthropic` instead. The kit wires it the same way, as a sentinel the proxy substitutes on egress. +For an Anthropic API key, use `sbx secret set anthropic` instead. -With the credential stored, launch `pi` from the project you want mounted: +### Start Pi + +Run this from the working folder you want mounted: ```bash sbx run --kit "docker.io/sbx/pi-kit:latest" pi ``` -The kit pre-bakes `pi` into its image, so the sandbox starts without installing anything, and the current directory is the sandbox workspace. - -Do not authenticate from inside the sandbox: `/login` there writes a real token into the container and defeats the proxy model. - -Scripted use works the same way: +For an existing sandbox, run Pi non-interactively with: ```bash sbx exec -- pi -p "list the failing tests" ``` -See the [kit documentation](https://github.com/docker/sbx-kits-contrib/tree/main/pi) for the full credential matrix, troubleshooting, and pinning. +See the [Pi kit documentation](https://github.com/docker/sbx-kits-contrib/tree/main/pi) for other providers, troubleshooting, and image pinning. + +## Run Pi with OpenShell + +[NVIDIA OpenShell](https://docs.nvidia.com/openshell/about/overview) provides local or remote sandboxes with filesystem, process, network, credential, and inference policies. + +### Select a gateway + +Every sandbox requires an active gateway: + +```bash +openshell gateway add --name +openshell gateway select +``` + +### Create the sandbox + +```bash +openshell sandbox create --name pi-sandbox --from pi -- pi +``` + +Pi, its built-in tools, `!` commands, and extension tools run inside the OpenShell boundary. + +### Transfer files to a remote sandbox + +A remote gateway does not bind-mount your host working folder. Clone the repository inside the sandbox or transfer files explicitly: + +```bash +openshell sandbox upload pi-sandbox ./working-folder /workspace +openshell sandbox download pi-sandbox /workspace/working-folder ./working-folder-out +``` + +OpenShell inference routing can keep raw model credentials outside the sandbox. When configured, point Pi at the corresponding OpenAI-compatible or Anthropic-compatible endpoint exposed by the gateway. + +## Route tools through Gondolin + +[Gondolin](https://github.com/earendil-works/gondolin) is a local Linux micro-VM. Its example extension keeps the Pi process and file-based provider credentials on the host while routing the built-in tools and user `!` commands into the VM. + +Commands inside the VM inherit the host process environment. Provider keys supplied through environment variables can therefore be visible inside the VM. Do not use this pattern as a credential boundary unless you remove sensitive variables or change the extension's environment handling. + +Gondolin requires Node.js 23.6 or newer and QEMU installed through your operating-system package manager. + +### Install the extension + +From a Pi source checkout: + +```bash +mkdir -p ~/.pi/agent/extensions +cp -R packages/coding-agent/examples/extensions/gondolin ~/.pi/agent/extensions/gondolin +cd ~/.pi/agent/extensions/gondolin +npm install --ignore-scripts +``` + +### Start Pi + +Run Pi from the working folder you want mounted: + +```bash +cd /path/to/working-folder +pi -e ~/.pi/agent/extensions/gondolin +``` + +The extension mounts the host working folder at `/workspace` in the VM and overrides `read`, `write`, `edit`, `bash`, `grep`, `find`, and `ls`. File changes under `/workspace` write through to the host. + +Other extension tools still run on the host unless they explicitly delegate their operations. Review the [Gondolin example](../examples/extensions/gondolin/) before adding tools that could bypass the VM boundary. diff --git a/packages/coding-agent/docs/docs.json b/packages/coding-agent/docs/docs.json index 9be1e28f8..3a28c2aaa 100644 --- a/packages/coding-agent/docs/docs.json +++ b/packages/coding-agent/docs/docs.json @@ -28,7 +28,7 @@ "path": "interactive-use.md" }, { - "title": "Models and Providers", + "title": "Choose a Model", "path": "models-and-providers.md" }, { @@ -45,6 +45,39 @@ } ] }, + { + "title": "Running Pi", + "items": [ + { + "title": "Run Pi Safely", + "path": "security.md" + }, + { + "title": "Isolate Pi", + "path": "containerization.md" + }, + { + "title": "Run Pi on Windows", + "path": "windows.md" + }, + { + "title": "Run Pi on Android", + "path": "termux.md" + }, + { + "title": "Configure Your Terminal", + "path": "terminal-setup.md" + }, + { + "title": "Run Pi in tmux", + "path": "tmux.md" + }, + { + "title": "Configure Shell Commands", + "path": "shell-aliases.md" + } + ] + }, { "title": "Customising Pi", "items": [ @@ -93,11 +126,11 @@ "title": "Reference", "items": [ { - "title": "CLI and Modes", + "title": "Command Line", "path": "cli.md" }, { - "title": "Provider Authentication", + "title": "Provider Setup", "path": "provider-reference.md" }, { @@ -121,11 +154,11 @@ "path": "themes.md" }, { - "title": "Session Format", + "title": "Session File Format", "path": "session-format.md" }, { - "title": "Compaction", + "title": "Compaction and Branch Summaries", "path": "compaction.md" }, { @@ -138,39 +171,6 @@ } ] }, - { - "title": "Operations and Platforms", - "items": [ - { - "title": "Security", - "path": "security.md" - }, - { - "title": "Containerization", - "path": "containerization.md" - }, - { - "title": "Windows", - "path": "windows.md" - }, - { - "title": "Termux on Android", - "path": "termux.md" - }, - { - "title": "tmux", - "path": "tmux.md" - }, - { - "title": "Terminal Setup", - "path": "terminal-setup.md" - }, - { - "title": "Shell Aliases", - "path": "shell-aliases.md" - } - ] - }, { "title": "Development", "items": [ diff --git a/packages/coding-agent/docs/environment-variables.md b/packages/coding-agent/docs/environment-variables.md index d19f149e4..6257b1618 100644 --- a/packages/coding-agent/docs/environment-variables.md +++ b/packages/coding-agent/docs/environment-variables.md @@ -6,7 +6,7 @@ Pi uses environment variables in three ways: - Pi sets process markers so child processes can identify Pi as the launching agent. - Commands run by the LLM-callable shell tools receive `PI_*` variables describing the current session. -Provider API-key variables are documented separately in [Provider Authentication](provider-reference.md#environment-variables-or-auth-file). +Provider API-key variables are documented separately in [Provider Setup](provider-reference.md#environment-variables-or-auth-file). ## Process Marker @@ -94,6 +94,6 @@ These variables are read by Pi itself: | `VISUAL`, `EDITOR` | External editor fallback when `externalEditor` is unset | | `HTTP_PROXY`, `HTTPS_PROXY` | Proxy outbound HTTP requests | -Provider credentials such as `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and cloud-provider configuration are listed in [Provider Authentication](provider-reference.md#environment-variables-or-auth-file). +Provider credentials such as `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and cloud-provider configuration are listed in [Provider Setup](provider-reference.md#environment-variables-or-auth-file). `PI_SERVER_DIR` and `PI_SERVER_ID` apply only to the source-only [experimental remote harness](development.md#experimental-remote-harness), not distributed builds. diff --git a/packages/coding-agent/docs/interactive-use.md b/packages/coding-agent/docs/interactive-use.md index 25258c9e9..46fa598d9 100644 --- a/packages/coding-agent/docs/interactive-use.md +++ b/packages/coding-agent/docs/interactive-use.md @@ -2,7 +2,7 @@ Run `pi` from the folder you want to work in. Pi uses that folder to discover files, instructions, and configuration, and to group saved sessions. If you have not installed Pi or chosen a model yet, follow the [Quickstart](quickstart.md). -Pi may ask whether you trust the working folder before loading its project resources. See [Project trust](security.md#project-trust). +Pi may ask whether you trust the working folder before loading its project resources. See [Project trust](security.md#understand-project-trust).

Pi interactive mode showing a conversation, editor, and status information

@@ -50,7 +50,7 @@ Type `/` to search the available commands. The commands you will use most often - `/login` and `/logout` manage provider access. - `/settings` changes common preferences. -Prompt templates, skills, and extensions can add more commands to the same menu. See [Models and Providers](models-and-providers.md), [Configuration](configuration.md), or the complete [CLI and Modes Reference](cli.md#interactive-slash-commands). +Prompt templates, skills, and extensions can add more commands to the same menu. See [Choose a Model](models-and-providers.md), [Configuration](configuration.md), or the complete [Command Line reference](cli.md#interactive-slash-commands). ## Continue or start over diff --git a/packages/coding-agent/docs/models-and-providers.md b/packages/coding-agent/docs/models-and-providers.md index 130b27b31..cc4f5d1fe 100644 --- a/packages/coding-agent/docs/models-and-providers.md +++ b/packages/coding-agent/docs/models-and-providers.md @@ -1,4 +1,4 @@ -# Models and Providers +# Choose a Model For a built-in provider, start with `/login`, then choose a model with `/model`. Use custom model configuration only when Pi does not already include the provider or endpoint you need. @@ -12,13 +12,13 @@ For a built-in provider, start with `/login`, then choose a model with `/model`. | An OpenAI-, Anthropic-, or Google-compatible endpoint | Add it to `models.json` | | A provider with a custom protocol or authentication flow | Build or install a provider extension | -See [Provider Authentication](provider-reference.md) for supported subscriptions, credential names, cloud-provider requirements, and resolution order. +See [Provider Setup](provider-reference.md) for supported subscriptions, credential names, cloud-provider requirements, and resolution order. ## Authenticate Run `/login` and select a provider. Pi stores credentials in `~/.pi/agent/auth.json`. Run `/logout` to remove stored credentials for a provider. -You can instead provide an API key through the provider's environment variable. This is useful in CI and other environments where Pi should not write credentials. The [Provider Authentication](provider-reference.md) reference lists every supported variable and `auth.json` key. +You can instead provide an API key through the provider's environment variable. This is useful in CI and other environments where Pi should not write credentials. [Provider Setup](provider-reference.md) lists every supported variable and `auth.json` key. Keep `auth.json` and any credential commands private. Project settings and extensions can execute inside the Pi process after you trust a project. Review [Security](security.md) before loading configuration from an untrusted directory. @@ -46,7 +46,7 @@ Use `models.json` when the endpoint speaks a protocol Pi already supports. Use a See [Custom Providers](custom-provider.md) for the extension workflow and [Custom Models](models.md) for the configuration format. -## Resolve common problems +## Troubleshooting ### A model does not appear @@ -58,7 +58,7 @@ Check whether the key came from an environment variable rather than `auth.json`. ### A subscription opens a browser on a remote machine -Complete the provider's headless authentication flow when available. Some providers let you paste the final redirect URL or authorization code back into Pi. See the provider-specific instructions in [Provider Authentication](provider-reference.md#subscriptions). +Complete the provider's headless authentication flow when available. Some providers let you paste the final redirect URL or authorization code back into Pi. See the provider-specific instructions in [Provider Setup](provider-reference.md#subscriptions). ### A compatible endpoint rejects requests diff --git a/packages/coding-agent/docs/models.md b/packages/coding-agent/docs/models.md index 86ca409a1..d839ba100 100644 --- a/packages/coding-agent/docs/models.md +++ b/packages/coding-agent/docs/models.md @@ -1,6 +1,6 @@ # Custom Models Reference -This reference describes the `~/.pi/agent/models.json` format for compatible endpoints such as Ollama, vLLM, LM Studio, and proxies. For choosing and connecting to a model, see [Models and Providers](models-and-providers.md). +This reference describes the `~/.pi/agent/models.json` format for compatible endpoints such as Ollama, vLLM, LM Studio, and proxies. For choosing and connecting to a model, see [Choose a Model](models-and-providers.md). ## Table of Contents diff --git a/packages/coding-agent/docs/prompt-templates.md b/packages/coding-agent/docs/prompt-templates.md index 4a36b7d74..c6b81c421 100644 --- a/packages/coding-agent/docs/prompt-templates.md +++ b/packages/coding-agent/docs/prompt-templates.md @@ -56,4 +56,4 @@ Place the template in your user or project prompt directory. Conventional prompt Settings and packages can select nested Markdown files; a package manifest can narrow discovery with explicit paths and globs. See [Loading resources](configuration.md#resources) for all supported locations and options. -Project templates become commands in the editor after trust is granted. Review their content before trusting an unfamiliar project. See [Security](security.md#project-trust). +Project templates become commands in the editor after trust is granted. Review their content before trusting an unfamiliar project. See [Security](security.md#understand-project-trust). diff --git a/packages/coding-agent/docs/provider-reference.md b/packages/coding-agent/docs/provider-reference.md index c32000fee..2638b60e9 100644 --- a/packages/coding-agent/docs/provider-reference.md +++ b/packages/coding-agent/docs/provider-reference.md @@ -1,6 +1,6 @@ -# Provider Authentication Reference +# Provider Setup Reference -This reference lists provider authentication methods, credential keys, cloud-provider requirements, and credential resolution order. For the setup workflow, see [Models and Providers](models-and-providers.md). +This reference lists provider authentication methods, credential keys, cloud-provider requirements, and credential resolution order. For choosing and connecting to a model, see [Choose a Model](models-and-providers.md). ## Table of Contents @@ -308,9 +308,9 @@ See [llama.cpp](llama-cpp.md) for server setup, model directory layout, environm ## Custom Providers -**Via models.json:** Add Ollama, LM Studio, vLLM, or any provider that speaks a supported API (OpenAI Completions, OpenAI Responses, Anthropic Messages, Google Generative AI). See [models.md](models.md). +Configure the service in `models.json` when it speaks an API that Pi already supports, such as OpenAI Completions, OpenAI Responses, Anthropic Messages, or Google Generative AI. This is the usual choice for Ollama, LM Studio, vLLM, and compatible proxies. See the [Custom Models reference](models.md) for the configuration format. -**Via extensions:** For providers that need custom API implementations or OAuth flows, create an extension. See [custom-provider.md](custom-provider.md) and [examples/extensions/custom-provider-gitlab-duo](../examples/extensions/custom-provider-gitlab-duo/). +Create a provider extension only when the service needs custom authentication, model discovery, request handling, or streaming. Follow the [Custom Providers guide](custom-provider.md), then use the checked [GitLab Duo provider example](../examples/extensions/custom-provider-gitlab-duo/) as a working implementation. ## Resolution Order diff --git a/packages/coding-agent/docs/rpc.md b/packages/coding-agent/docs/rpc.md index 85d70b48e..798ec2752 100644 --- a/packages/coding-agent/docs/rpc.md +++ b/packages/coding-agent/docs/rpc.md @@ -239,7 +239,7 @@ Response: } ``` -Messages are `AgentMessage` objects (see [Message Types](#message-types)). +Messages are `AgentMessage` objects (see [Types](#types)). ### Model @@ -1207,6 +1207,8 @@ There are two categories of extension UI methods: If a dialog method includes a `timeout` field, the agent-side will auto-resolve with a default value when the timeout expires. The client does not need to track timeouts. +### RPC UI limitations + Some `ExtensionUIContext` methods are not supported or degraded in RPC mode because they require direct TUI access: - `custom()` returns `undefined` - `setWorkingMessage()`, `setWorkingIndicator()`, `setFooter()`, `setHeader()`, `setEditorComponent()`, `setToolsExpanded()` are no-ops @@ -1388,7 +1390,7 @@ Dismiss any dialog method. The extension receives `undefined` (for select/input/ {"type": "extension_ui_response", "id": "uuid-3", "cancelled": true} ``` -## Error Handling +## Command and parse errors Failed commands return a response with `success: false`: diff --git a/packages/coding-agent/docs/sdk.md b/packages/coding-agent/docs/sdk.md index 5df95fe1f..f10ef19e4 100644 --- a/packages/coding-agent/docs/sdk.md +++ b/packages/coding-agent/docs/sdk.md @@ -124,7 +124,7 @@ See the focused examples for [models](../examples/sdk/02-custom-model.ts), [tool ## Resources -- [Models and Providers](models-and-providers.md) covers model selection and authentication; [Provider Authentication](provider-reference.md) and [Custom Models](models.md) provide exact configuration. +- [Choose a Model](models-and-providers.md) covers model selection and authentication; [Provider Setup](provider-reference.md) and [Custom Models](models.md) provide exact configuration. - [Configuration](configuration.md) explains normal discovery and settings; [Settings](settings-reference.md) lists every setting. - [Sessions and Context](sessions-and-context.md) explains session behavior; [Session Format](session-format.md) defines persisted entries. - [Extensions](extensions.md), [Skills](skills.md), and [Prompt Templates](prompt-templates.md) document resources supplied through a `ResourceLoader`. diff --git a/packages/coding-agent/docs/security.md b/packages/coding-agent/docs/security.md index b378dffe7..6178dd6c9 100644 --- a/packages/coding-agent/docs/security.md +++ b/packages/coding-agent/docs/security.md @@ -1,59 +1,97 @@ -# Security +# Run Pi safely -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. +Treat model-generated commands and code as untrusted. Pi can read, change, and execute files with the permissions of the account that started it, and it does not ask for approval before every tool call. Extensions, package installers, language servers, and other child processes run with those same permissions unless an operating-system or virtualization boundary restricts them. -## Project Trust +Files, comments, instructions, command output, and model responses can steer the model through prompt injection. Project trust controls which project resources load at startup, but it does not make that content or the resulting actions safe. -Project trust controls whether pi loads project-local settings, resources, packages, and extensions. 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. +Safety comes from limiting the files, credentials, processes, and network services Pi can access and affect if a generated action is wrong or hostile. Watching the transcript, using project trust, and reviewing changes do not create a security boundary. -Pi requires project trust when it finds any of these from the current working directory: +## Choose how to run Pi + +Different ways of running Pi place different limits on what generated commands can access: + +| How Pi runs | What remains protected | +|---|---| +| Directly, with the permissions of its operating-system user | Anything that user cannot access. A dedicated user account can narrow those permissions, but Pi still shares the operating system and network with other users. | +| Entirely inside a container, virtual machine, or sandbox | Host files and processes that you do not expose to the environment. Credentials and network services remain accessible if you make them available inside it. This is usually the strongest practical option. | +| Outside the isolated environment, with only its built-in tools running inside | Host resources are protected from actions performed through those tools. Pi itself and other extensions remain outside the boundary, so this is a narrower form of isolation. | + +The working folder controls resource discovery and the default location for tools, but it does not prevent commands from accessing other paths available to the Pi process. + +Whichever option you choose, only provide the files and services required for the task. Keep credentials outside the environment where possible, or use narrowly scoped, short-lived credentials. Restrict network access when commands do not need it. + +For setup instructions and the limitations of each isolation method, see [Run Pi in an isolated environment](containerization.md). + + + +## Understand project trust + +Project trust controls whether Pi loads most settings and resources supplied by a working folder. It prevents a folder from silently loading executable extensions before you approve it. + +Project trust is not a complete startup boundary. Pi reads the project `sessionDir` setting while selecting or creating a session, before it resolves project trust. Declining trust prevents the remaining project settings and protected resources from loading, but it cannot undo that initial session-directory lookup. + +Project trust does not limit what tool calls can access or affect. After Pi starts, enabled tools still use the operating-system permissions of the Pi process. Instructions and other content in the folder can also influence the model. + +### Resources protected by project trust + +Pi requires a project-trust decision when it finds any of these resources from the current working directory: - `.pi/settings.json` - `.pi/extensions`, `.pi/skills`, `.pi/prompts`, or `.pi/themes` - `.pi/SYSTEM.md` or `.pi/APPEND_SYSTEM.md` - project `.agents/skills` in the current directory or an ancestor directory -A bare `.pi` directory does not count as a project resource that requires trust. +A bare `.pi` directory does not require project trust. -When an interactive session starts in a working directory with resources that require trust and no saved decision for the current directory or a parent directory, pi follows `defaultProjectTrust` from global settings. The default value is `"ask"`, which asks whether to trust the project folder when UI is available. Saved decisions are stored by canonical directory in `~/.pi/agent/trust.json`, and the closest saved decision on the current or parent path applies before the global default. +Granting project trust allows Pi to load: -Granting project trust allows pi to load protected project resources, including: +- project settings +- extensions, skills, prompt templates, themes, and system-prompt files under `.pi` +- missing packages configured through project settings +- project-local and project-package extensions -- `.pi/settings.json` -- `.pi` resources such as extensions, skills, prompt templates, themes, and system prompt files -- missing project packages configured through project settings -- project-local extensions and project package-managed extensions +Declining project trust skips those protected resources, except for the initial `sessionDir` lookup described above. -Declining trust skips protected resources. Context files such as `AGENTS.override.md`, `AGENTS.md`, and `CLAUDE.md` are loaded regardless of project trust unless context loading is disabled. Before trust is resolved, pi only loads context files, 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. +Context files such as `AGENTS.override.md`, `AGENTS.md`, and `CLAUDE.md` load regardless of project trust unless you disable context loading. Treat instructions in a folder as untrusted input even when you decline project trust. -Non-interactive modes (`-p`, `--mode json`, and `--mode rpc`) do not show a trust prompt. Without an applicable saved trust decision, `defaultProjectTrust: "ask"` and `"never"` ignore such resources, while `"always"` trusts them. Use `--approve`/`-a` or `--no-approve`/`-na` to override project trust for one run. +### How Pi chooses a trust decision -## No Built-in Sandbox +A command-line `--approve` or `--no-approve` override applies first. When protected resources exist and there is no command-line override: -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. +1. User-level and command-line extensions can handle the `project_trust` event. The first extension that returns yes or no owns the decision. +2. If no extension decides, Pi looks for a saved decision for the current directory or one of its parents. The closest decision applies. +3. If no saved decision applies, Pi follows the global `defaultProjectTrust` setting, whose default is `"ask"`. -This is intentional. Pi is designed to operate on local source trees, run 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. +Saved decisions use canonical directory paths and live in: -Project trust is only an input-loading guard. It prevents a repository from silently changing pi's 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, context files, or build output is expected local-agent risk and cannot be reliably prevented by pi. +```text +~/.pi/agent/trust.json +``` -## Running Untrusted or Unmonitored Work +Use `/trust` to save a decision for future Pi processes. -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. +### Project trust without an interactive prompt -Common patterns are documented in [Containerization](containerization.md): +Print, JSON, and RPC modes cannot show the built-in trust prompt. If no command-line override, extension, or saved decision applies: -- run the whole `pi` process inside a container/sandbox -- run host pi while routing built-in tool execution into a Gondolin micro-VM -- mount only the workspace paths the agent should access -- avoid mounting host `~/.pi/agent` unless the container should access host sessions, settings, and credentials -- pass the minimum required API keys or use short-lived credentials -- restrict network access when the task does not need it -- review diffs and outputs before copying results back to trusted systems +- `defaultProjectTrust: "always"` loads protected project resources. +- `defaultProjectTrust: "ask"` or `"never"` skips them. -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. +Use `--approve` or `--no-approve` when an automated run needs an explicit one-time decision. -## Reporting Security Issues +## Reduce impact and improve recovery -To report a security issue, follow the repository [Security Policy](https://github.com/earendil-works/pi/blob/main/SECURITY.md). Do not open a public issue for security-sensitive reports. +These practices do not replace isolation, but they reduce exposure or make recovery easier: -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. +- Give Pi access only to files and services required for the task. +- Use snapshots, backups, or version control before substantial changes. +- Review extensions and packages before loading them. Extensions execute inside the Pi process. +- Prefer narrowly scoped, short-lived credentials. +- Review diffs and generated output before applying results to another system. +- Review sessions before exporting or sharing them. They can contain prompts, tool arguments, command output, file contents, and credentials exposed during the conversation. + +## Report a security issue + +Follow the repository [Security Policy](https://github.com/earendil-works/pi/blob/main/SECURITY.md). Do not open a public issue for a security-sensitive report. + +Expected local-agent behavior, prompt injection from untrusted content, lack of a built-in sandbox, and behavior from user-installed extensions or skills are generally outside the security boundary unless the report demonstrates a privilege-boundary bypass or access that the local user did not already have. diff --git a/packages/coding-agent/docs/settings-reference.md b/packages/coding-agent/docs/settings-reference.md index 47f529841..5d5643259 100644 --- a/packages/coding-agent/docs/settings-reference.md +++ b/packages/coding-agent/docs/settings-reference.md @@ -11,7 +11,7 @@ Edit the files directly or use `/settings` for common options. To save startup m ## Project Trust -Project settings load only after project trust is granted. See [Project Trust](security.md#project-trust) for the trust boundary, saved decisions, and command-line overrides. +Most project settings load only after project trust is granted. Pi reads the project `sessionDir` setting before resolving trust so it can select or create a session. Declining trust skips the remaining project settings. See [Understand project trust](security.md#understand-project-trust) for the trust boundary, saved decisions, and command-line overrides. ## All Settings @@ -89,7 +89,7 @@ Set `PI_SKIP_VERSION_CHECK=1` to disable the Pi version update check. Use `--off } ``` -### Warnings +### Warning settings | Setting | Type | Default | Description | |---------|------|---------|-------------| @@ -213,7 +213,7 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic | `terminal.clearOnShrink` | boolean | `false` | Clear empty rows when content shrinks (can cause flicker) | | `terminal.showTerminalProgress` | boolean | `false` | Show an indeterminate OSC 9;4 progress indicator in the terminal tab while Pi is working | | `terminal.hyperlinks` | boolean or `"auto"` | `"auto"` | Override OSC 8 hyperlink support (advanced, JSON-only) | -| `terminal.images` | string or boolean | `"auto"` | Override image protocol support with `"kitty"`, `"iterm2"`, `false`, or `"auto"` (advanced, JSON-only) | +| `terminal.images` | string or `false` | `"auto"` | Override image protocol support with `"kitty"`, `"iterm2"`, `false`, or `"auto"` (advanced, JSON-only) | | `terminal.trueColor` | boolean or `"auto"` | `"auto"` | Override truecolor support (advanced, JSON-only) | | `images.autoResize` | boolean | `true` | Resize images to 2000x2000 max. Applies to `@file` attachments, `read`, and images returned by tools | | `images.blockImages` | boolean | `false` | Block all images from being sent to LLM | @@ -374,9 +374,13 @@ See [packages.md](packages.md) for package management details. } ``` -## Project Overrides +## Project overrides -Project settings (`.pi/settings.json`) override global settings. Nested objects are merged: +Most project settings in `.pi/settings.json` override global settings. Nested objects are merged. + +The resource arrays `packages`, `extensions`, `skills`, `prompts`, and `themes` are an exception. Pi processes their global and project values separately, so a project array does not replace or disable the corresponding global array. + +For other settings, the merge works as follows: ```json // ~/.pi/agent/settings.json (global) diff --git a/packages/coding-agent/docs/shell-aliases.md b/packages/coding-agent/docs/shell-aliases.md index af0cd25f1..50393408c 100644 --- a/packages/coding-agent/docs/shell-aliases.md +++ b/packages/coding-agent/docs/shell-aliases.md @@ -1,13 +1,93 @@ -# Shell Aliases +# Configure shell commands -Pi runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default. +Pi starts a separate non-interactive shell process for each Bash command. Non-interactive Bash does not expand aliases by default and usually does not load the same startup files as an interactive terminal. -To enable your shell aliases, add to `~/.pi/agent/settings.json`: +Use `shellPath` to choose the Bash executable and `shellCommandPrefix` to run setup before each command. + +## Understand which shell Pi uses + +| Command source | Shell | +|---|---| +| Model calls the built-in `bash` tool | Pi's resolved Bash executable | +| You enter `!command` or `!!command` | The same resolved Bash executable | +| Model calls the optional `powershell` tool | PowerShell 7 (`pwsh.exe`) or Windows PowerShell | +| An extension provides or replaces a shell tool | The operations implemented by that extension | + +Pi normally invokes Bash with `bash -c`. On Unix systems, it uses `/bin/bash`, then `bash` on `PATH`, and finally `sh` when Bash is unavailable. Native Windows first checks the configured path, then Git Bash, then `bash.exe` on `PATH`. + +## Choose a Bash executable + +Set `shellPath` in `~/.pi/agent/settings.json` when Pi should use a specific executable: ```json { - "shellCommandPrefix": "shopt -s expand_aliases\neval \"$(grep '^alias ' ~/.zshrc)\"" + "shellPath": "~/.local/bin/bash" } ``` -Adjust the path (`~/.zshrc`, `~/.bashrc`, etc.) to match your shell config. +On Windows, use forward slashes or escape backslashes: + +```json +{ + "shellPath": "C:\\cygwin64\\bin\\bash.exe" +} +``` + +Run `/reload` after changing the setting. See [Run Pi on Windows](windows.md) for the native Windows defaults. + +## Run setup before every Bash command + +Set `shellCommandPrefix` to prepend shell setup to both the built-in `bash` tool and user-entered `!` or `!!` commands: + +```json +{ + "shellCommandPrefix": "export CI=1" +} +``` + +Pi joins the prefix and requested command with a newline. The prefix runs again for every command, so keep it fast and free of interactive prompts. + +## Enable Bash aliases + +Store aliases needed by Pi in a Bash-compatible file instead of parsing an entire interactive shell configuration. + +Create `~/.bash_aliases`: + +```bash +alias ll='ls -la' +alias gs='git status --short' +``` + +Then configure Pi to enable alias expansion and load the file: + +```json +{ + "shellCommandPrefix": "shopt -s expand_aliases\nsource ~/.bash_aliases" +} +``` + +Run `/reload`, then verify the alias through Pi: + +```text +!ll +``` + +The command should produce the same listing as `ls -la`. + +Aliases must use Bash-compatible syntax. Do not source an arbitrary `.zshrc` into Bash because zsh options, functions, and plugins may not parse or behave correctly there. + +## Troubleshooting + +### The prefix works for `!` but not for an extension tool + +`shellCommandPrefix` configures Pi's built-in Bash execution. An extension that replaces the `bash` tool or provides its own shell operations controls its own setup. Check that extension's documentation. + +### `shopt` is not found + +Pi has fallen back to `sh` or `shellPath` points to a non-Bash shell. Install Bash or set `shellPath` to a Bash executable before using Bash-specific setup such as `shopt`. + +### A setup command waits for input + +Remove interactive commands from `shellCommandPrefix`. The prefix runs in a non-interactive process before every Bash command. + +For the complete setting definitions, see [Shell settings](settings-reference.md#shell). diff --git a/packages/coding-agent/docs/terminal-setup.md b/packages/coding-agent/docs/terminal-setup.md index de91e3c5c..6aa9d20b7 100644 --- a/packages/coding-agent/docs/terminal-setup.md +++ b/packages/coding-agent/docs/terminal-setup.md @@ -1,73 +1,74 @@ -# Terminal Setup +# Configure your terminal -Pi uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration. +Most modern terminals work with Pi without additional setup. Use this page when modified keys, scrolling, links, images, colors, or input-method editor (IME) positioning do not behave as expected. -## Capability Overrides +Pi uses extended-key protocols so terminals can distinguish combinations such as `Shift+Enter` and `Alt+Enter` from plain `Enter`. Terminal proxies, multiplexers, and built-in IDE terminals can change or discard that information. -Pi auto-detects OSC 8 hyperlinks, inline image protocols, and truecolor. If detection fails behind a terminal proxy or multiplexer, use these advanced overrides: +## Troubleshooting -| Capability | Environment variable | JSON setting | -|------------|----------------------|--------------| -| OSC 8 hyperlinks | `PI_HYPERLINKS=1\|0\|auto` | `terminal.hyperlinks: true\|false\|"auto"` | -| Inline images | `PI_IMAGE_PROTOCOL=kitty\|iterm2\|none\|auto` | `terminal.images: "kitty"\|"iterm2"\|false\|"auto"` | -| Truecolor | `PI_TRUE_COLOR=1\|0\|auto` | `terminal.trueColor: true\|false\|"auto"` | +| Symptom | Start here | +|---|---| +| `Shift+Enter` submits instead of inserting a line | Your terminal's section below; for tmux, see [Run Pi in tmux](tmux.md) | +| `Alt+Enter` does not queue a follow-up | [WezTerm](#wezterm), [Alacritty](#alacritty), or [Windows Terminal](#windows-terminal) | +| Fullscreen scrolling is unusually slow | [iTerm2](#iterm2) | +| Links work but show no hover preview | [Ghostty](#ghostty) | +| Inline images or colors are not detected | [Override detected capabilities](#override-detected-capabilities) | +| An IME candidate window appears in the wrong place | [WezTerm](#wezterm) or [IntelliJ IDEA](#intellij-idea-integrated-terminal) | +| Modified keys fail only inside tmux | [Run Pi in tmux](tmux.md) | -Settings take precedence over environment variables; unset or `auto` preserves detection. Only force capabilities supported by the complete terminal path, since unsupported escape sequences can corrupt rendering. +Use `/hotkeys` to inspect Pi's active shortcuts. See [Keybindings](keybindings.md) to change them. ## Kitty -Works out of the box. +Kitty supports the required keyboard protocol without additional configuration. ## iTerm2 -### Regular TUI mode +Regular terminal mode works without additional configuration. -Works out of the box. +### Fix slow fullscreen scrolling -### Fullscreen TUI mode +In fullscreen mode, Pi owns the viewport, so iTerm2 sends mouse-wheel reports instead of scrolling native terminal history. Fast trackpad gestures can then move only about one line at a time. -Pi owns the viewport, so iTerm2 sends mouse-wheel reports instead of scrolling its native scrollback. With iTerm2's default fast-trackpad behavior, those reports can lose most of an accelerated wheel delta, making fullscreen scrolling much slower than regular scrolling. +To change this behavior: -If fast mouse-wheel gestures move only about one line at a time in fullscreen mode: +1. Open **iTerm2 > Settings > Advanced**. +2. Search for **Trackpad scrolls fast?**. +3. Set it to **No**. -1. Open **iTerm2 → Settings → Advanced**. -2. Search for **Trackpad scrolls fast?** and set it to **No**. - -This is an iTerm2-wide workaround and may also change native trackpad scrolling. The underlying behavior is tracked in [iTerm2 issue 9619](https://gitlab.com/gnachman/iterm2/-/work_items/9619). +This is an iTerm2-wide setting and can also change native trackpad scrolling. The underlying behavior is tracked in [iTerm2 issue 9619](https://gitlab.com/gnachman/iterm2/-/work_items/9619). ## Apple Terminal -Pi enables enhanced key reporting when available. If Terminal.app still sends plain Return for `Shift+Enter`, pi uses a local macOS modifier fallback to treat that Return as `Shift+Enter`. +Pi enables enhanced key reporting when available. If Terminal.app still sends plain Return for `Shift+Enter`, Pi uses a local macOS modifier fallback and treats it as `Shift+Enter`. -This fallback only works when pi runs on the same Mac as Terminal.app. It cannot detect the local keyboard over remote SSH. +The fallback works only when Pi runs on the same Mac as Terminal.app. It cannot inspect the local modifier state when Pi runs on another machine over SSH. ## Ghostty -Add to your Ghostty config (`~/Library/Application Support/com.mitchellh.ghostty/config` on macOS, `~/.config/ghostty/config` on Linux): +Add this mapping to Ghostty's configuration if `Alt+Backspace` does not work: -``` +```text keybind = alt+backspace=text:\x1b\x7f ``` -Older Claude Code versions may have added this Ghostty mapping: +The configuration file is `~/Library/Application Support/com.mitchellh.ghostty/config` on macOS and `~/.config/ghostty/config` on Linux. -``` +Older Claude Code configurations may contain: + +```text keybind = shift+enter=text:\n ``` -That mapping sends a raw linefeed byte. Inside pi, that is indistinguishable from `Ctrl+J`, so tmux and pi no longer see a real `shift+enter` key event. +This sends a raw linefeed, which Pi cannot distinguish from `Ctrl+J`. Remove the mapping if an older Claude Code installation is the only reason you added it. Pi already binds `Ctrl+J` as a newline alternative, so the mapping may appear to work while still preventing Pi and tmux from receiving a real `Shift+Enter` event. -If Claude Code 2.x or newer is the only reason you added that mapping, you can remove it, unless you want to use Claude Code in tmux, where it still requires that Ghostty mapping. +### Open links in fullscreen mode -Pi binds `Ctrl+J` as a default newline alias, so `Shift+Enter` keeps working in tmux via that remap without extra pi configuration. - -### Fullscreen TUI mode - -In fullscreen mode, links remain clickable, but Ghostty does not show its hover underline or lower-left URL preview while pi captures mouse input. Hold `Shift+Command` on macOS or `Shift+Ctrl` on Linux to use Ghostty's native link handling. +Links remain clickable in fullscreen mode, but Ghostty does not show its normal hover underline or URL preview while Pi captures mouse input. Hold `Shift+Command` on macOS or `Shift+Ctrl` on Linux to use Ghostty's native link handling. ## WezTerm -WezTerm usually works out of the box for `Shift+Enter` via xterm modifyOtherKeys. To use the Kitty keyboard protocol explicitly, create `~/.wezterm.lua`: +WezTerm normally reports `Shift+Enter` through xterm extended keys. To enable the Kitty keyboard protocol explicitly, create `~/.wezterm.lua`: ```lua local wezterm = require 'wezterm' @@ -76,7 +77,19 @@ config.enable_kitty_keyboard = true return config ``` -On macOS, WezTerm binds `Option+Enter` to fullscreen by default. To use `Option+Enter` for pi follow-up queueing, add this key override: +### Forward Alt+Enter on macOS + +WezTerm binds `Option+Enter` to fullscreen by default on macOS. To use it for Pi's follow-up queue, add this entry to your `config.keys` table: + +```lua +{ + key = 'Enter', + mods = 'ALT', + action = wezterm.action.SendString('\x1b[13;3u'), +} +``` + +A complete minimal configuration is: ```lua local wezterm = require 'wezterm' @@ -91,13 +104,20 @@ config.keys = { return config ``` -If you already have a `config.keys` table, add the entry to it. +### Position an IME candidate window in WSL -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. +If CJK IME candidates do not follow Pi's text cursor in WSL, show the hardware cursor: + +```bash +export PI_HARDWARE_CURSOR=1 +pi +``` + +You can instead set `showHardwareCursor` to `true` in Pi settings. ## Alacritty -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`: +Alacritty normally reports `Shift+Enter`. On macOS, `Option+Enter` can arrive as plain `Enter`. Add this to `~/.config/alacritty/alacritty.toml` to forward it to Pi: ```toml [[keyboard.bindings]] @@ -106,20 +126,13 @@ mods = "Alt" chars = "\u001b[13;3u" ``` -Restart Alacritty after changing the config. +Restart Alacritty after changing the file. -## VS Code (Integrated Terminal) +## VS Code integrated terminal -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. +VS Code 1.109.5 and newer enable the Kitty keyboard protocol in the integrated terminal by default. -VS Code versions older than 1.109.5 need an explicit terminal keybinding for `Shift+Enter`. - -`keybindings.json` locations: -- macOS: `~/Library/Application Support/Code/User/keybindings.json` -- Linux: `~/.config/Code/User/keybindings.json` -- Windows: `%APPDATA%\\Code\\User\\keybindings.json` - -Add to `keybindings.json`: +For an older version, add a `Shift+Enter` terminal binding to `keybindings.json`: ```json { @@ -130,9 +143,15 @@ Add to `keybindings.json`: } ``` -## Zed (Integrated Terminal) +The user `keybindings.json` file is normally located at: -Add these key bindings to your Zed `keymap.json`: +- macOS: `~/Library/Application Support/Code/User/keybindings.json` +- Linux: `~/.config/Code/User/keybindings.json` +- Windows: `%APPDATA%\\Code\\User\\keybindings.json` + +## Zed integrated terminal + +Add these bindings to Zed's `keymap.json`: ```json { @@ -147,46 +166,54 @@ Add these key bindings to your Zed `keymap.json`: ## Windows Terminal -Pi uses Windows-style keybindings when running natively on Windows or in WSL: +Windows Terminal uses Pi's Windows and WSL shortcut defaults. See [Keybindings](keybindings.md) for the complete list. -- `Alt+V` pastes an image or clipboard text. -- `Ctrl+F` searches the transcript in fullscreen mode, and `Ctrl+Up`/`Ctrl+Down` jump between marked messages. -- `Alt+P` cycles to the previous model. -- `Ctrl+Z` undoes editing on native Windows; WSL uses `Alt+Z` so `Ctrl+Z` can suspend pi. -- `Ctrl+Q` queues a follow-up message and `Alt+Q` restores queued messages. +### Forward Shift+Enter -Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward `Shift+Enter` for inserting a new line: +Open Windows Terminal's `settings.json` with `Ctrl+Shift+,` or **Settings > Open JSON file**. Add this object to its `actions` array: ```json { - "actions": [ - { - "command": { "action": "sendInput", "input": "\u001b[13;2u" }, - "keys": "shift+enter" - } - ] + "command": { "action": "sendInput", "input": "\u001b[13;2u" }, + "keys": "shift+enter" } ``` -Windows Terminal binds `Alt+Enter` to fullscreen by default. To use it instead of pi's `Ctrl+Q` default for follow-up queueing, configure Windows Terminal to send the key and bind `app.message.followUp` to `alt+enter` in pi. +Fully close and reopen Windows Terminal, then verify that `Shift+Enter` inserts a new line in Pi. -If you already have an `actions` array, add the object to it. Fully close and reopen Windows Terminal after changing its settings. +### Use Alt+Enter for follow-ups -## xfce4-terminal, terminator +Windows Terminal binds `Alt+Enter` to fullscreen by default. Pi therefore uses `Ctrl+Q` for follow-ups on Windows and WSL. -These terminals have limited escape sequence support. Modified Enter keys like `Ctrl+Enter` and `Shift+Enter` cannot be distinguished from plain `Enter`, preventing custom keybindings such as `submit: ["ctrl+enter"]` from working. +To use `Alt+Enter` instead, configure Windows Terminal to forward the key and bind `app.message.followUp` to `alt+enter` in Pi's `keybindings.json`. See [Keybindings](keybindings.md#custom-configuration). -For the best experience, use a terminal that supports the Kitty keyboard protocol: -- [Kitty](https://sw.kovidgoyal.net/kitty/) -- [Ghostty](https://ghostty.org/) -- [WezTerm](https://wezfurlong.org/wezterm/) -- [iTerm2](https://iterm2.com/) -- [Alacritty](https://github.com/alacritty/alacritty) (requires compilation with Kitty protocol support) +## xfce4-terminal and Terminator -## IntelliJ IDEA (Integrated Terminal) +These terminals cannot reliably distinguish modified Enter keys from plain `Enter`. Custom bindings such as `Ctrl+Enter` or `Shift+Enter` therefore may not work. -The built-in terminal has limited escape sequence support. Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal. +Use a terminal with modern extended-key support when you need those shortcuts, such as Kitty, Ghostty, WezTerm, iTerm2, Windows Terminal, or a compatible Alacritty build. -If you want the hardware cursor visible, set `PI_HARDWARE_CURSOR=1` before running pi (disabled by default for compatibility). +## IntelliJ IDEA integrated terminal -Consider using a dedicated terminal emulator for the best experience. +IntelliJ IDEA's built-in terminal cannot reliably distinguish `Shift+Enter` from plain `Enter`. Use `Ctrl+J` for a newline or run Pi in a terminal with modern extended-key support. + +If an IME candidate window does not follow the text cursor, show the hardware cursor: + +```bash +export PI_HARDWARE_CURSOR=1 +pi +``` + +## Override detected capabilities + +Pi automatically detects OSC 8 hyperlinks, inline image protocols, and truecolor support. A terminal proxy or multiplexer can make that detection inaccurate. + +| Capability | Environment variable | Setting | +|---|---|---| +| Hyperlinks | `PI_HYPERLINKS=1\|0\|auto` | `terminal.hyperlinks: true\|false\|"auto"` | +| Inline images | `PI_IMAGE_PROTOCOL=kitty\|iterm2\|none\|auto` | `terminal.images: "kitty"\|"iterm2"\|false\|"auto"` | +| Truecolor | `PI_TRUE_COLOR=1\|0\|auto` | `terminal.trueColor: true\|false\|"auto"` | + +Settings take precedence over environment variables. An unset value or `auto` preserves automatic detection. + +Only force a capability supported by the complete terminal path. Unsupported escape sequences can corrupt rendering. See [Environment Variables](environment-variables.md#pi-process-configuration) and [Settings](settings-reference.md) for the canonical value definitions. diff --git a/packages/coding-agent/docs/termux.md b/packages/coding-agent/docs/termux.md index 1dd355942..25cd584d7 100644 --- a/packages/coding-agent/docs/termux.md +++ b/packages/coding-agent/docs/termux.md @@ -1,126 +1,117 @@ -# Termux (Android) Setup +# Run Pi on Android with Termux -Pi runs on Android via [Termux](https://termux.dev/), a terminal emulator and Linux environment for Android. +Pi runs on Android through [Termux](https://termux.dev/), a terminal emulator and Linux environment. Text input, file tools, and shell commands are supported. Pi can copy text to the Android clipboard through Termux:API, but its clipboard-paste shortcut cannot read text or images from the Android clipboard. -## Prerequisites +## Before you begin -1. Install [Termux](https://github.com/termux/termux-app#installation) from GitHub or F-Droid (not Google Play, that version is deprecated) -2. Install [Termux:API](https://github.com/termux/termux-api#installation) from GitHub or F-Droid for clipboard and other device integrations +Install Termux from [GitHub or F-Droid](https://github.com/termux/termux-app#installation). Do not use the deprecated Google Play build. -## Installation +[Termux:API](https://github.com/termux/termux-api#installation) is optional. Install it only when you want Pi to copy text to the Android clipboard or shell commands to use Android device APIs. -```bash -# Update packages -pkg update && pkg upgrade +## Install Pi -# Install dependencies -pkg install nodejs termux-api git +1. Update Termux packages: -# Install pi -npm install -g --ignore-scripts @earendil-works/pi-coding-agent + ```bash + pkg update && pkg upgrade + ``` -# Create config directory -mkdir -p ~/.pi/agent +2. Install Node.js and Git: -# Run pi -pi -``` + ```bash + pkg install nodejs git + ``` -## Clipboard Support +3. Install Pi: -Clipboard operations use `termux-clipboard-set` and `termux-clipboard-get` when running in Termux. The Termux:API app must be installed for these to work. + ```bash + npm install -g --ignore-scripts @earendil-works/pi-coding-agent + ``` -Image clipboard is not supported on Termux (the `ctrl+v` image paste feature will not work). +4. Verify the installation: -## Example AGENTS.md for Termux + ```bash + pi --version + ``` -Create `~/.pi/agent/AGENTS.md` to help the agent understand the Termux environment: +5. Open the folder you want to work in and start Pi: -````markdown -# Agent Environment: Termux on Android + ```bash + cd /path/to/working-folder + pi + ``` -## Location -- **OS**: Android (Termux terminal emulator) -- **Home**: `/data/data/com.termux/files/home` -- **Prefix**: `/data/data/com.termux/files/usr` -- **Shared storage**: `/storage/emulated/0` (Downloads, Documents, etc.) +Continue with the main [Quickstart](quickstart.md#3-choose-a-model) to connect a model and run your first task. -## Opening URLs -```bash -termux-open-url "https://example.com" -``` +## Access Android shared storage -## Opening Files -```bash -termux-open file.pdf # Opens with default app -termux-open --chooser image.jpg # Choose app -``` +Termux cannot access shared Android storage until you grant permission. Run this once: -## Clipboard -```bash -termux-clipboard-set "text" # Copy -termux-clipboard-get # Paste -``` - -## Notifications -```bash -termux-notification -t "Title" -c "Content" -``` - -## Device Info -```bash -termux-battery-status # Battery info -termux-wifi-connectioninfo # WiFi info -termux-telephony-deviceinfo # Device info -``` - -## Sharing -```bash -termux-share -a send file.txt # Share file -``` - -## Other Useful Commands -```bash -termux-toast "message" # Quick toast popup -termux-vibrate # Vibrate device -termux-tts-speak "hello" # Text to speech -termux-camera-photo out.jpg # Take photo -``` - -## Notes -- Termux:API app must be installed for `termux-*` commands -- Use `pkg install termux-api` for the command-line tools -- Storage permission needed for `/storage/emulated/0` access -```` - -## Limitations - -- **No image clipboard**: Termux clipboard API only supports text -- **Storage access**: To access files in `/storage/emulated/0` (Downloads, etc.), run `termux-setup-storage` once to grant permissions - -## Troubleshooting - -### Clipboard not working - -Ensure both apps are installed: -1. Termux (from GitHub or F-Droid) -2. Termux:API (from GitHub or F-Droid) - -Then install the CLI tools: -```bash -pkg install termux-api -``` - -### Permission denied for shared storage - -Run once to grant storage permissions: ```bash termux-setup-storage ``` -### Node.js installation issues +After approval, Android shared storage is available under `/storage/emulated/0` and through the links Termux creates under `~/storage/`. + +Only grant this permission when Pi should be able to access those files. Commands and tools running in Termux use the same storage permissions as the Termux process. + +## Use clipboard commands + +Pi uses `termux-clipboard-set` when it copies text and `TERMUX_VERSION` is present. Shell commands can use both `termux-clipboard-get` and `termux-clipboard-set`. The Termux:API app and its command-line package must be installed: -If npm fails, try clearing the cache: ```bash -npm cache clean --force +pkg install termux-api ``` + +Verify the integration: + +```bash +printf 'Pi clipboard test' | termux-clipboard-set +termux-clipboard-get +``` + +The second command should print `Pi clipboard test`. + +The Termux clipboard API supports text only. Pi's clipboard-paste shortcut does not use `termux-clipboard-get`, so paste through the terminal or run the command explicitly when you need clipboard text in the editor. + +## Add Termux-specific instructions + +Pi detects that it is running in Termux, but it cannot infer how you want it to interact with Android. Add only the environment details relevant to your work to `~/.pi/agent/AGENTS.md`: + +````markdown +# Termux environment + +- Pi runs in Termux on Android. +- Shared Android storage is under `/storage/emulated/0`. +- Open URLs with `termux-open-url "https://example.com"`. +- Open files with `termux-open `. +- Do not access shared storage unless the task requires it. +```` + +Run `/reload` after changing the file during an active session. + +## Troubleshooting + +### Copying from Pi fails + +Confirm that you installed both components: + +1. The Termux:API Android app from the same source as Termux +2. The `termux-api` command-line package + +Then run the clipboard verification commands above outside Pi. If they fail there, fix the Termux:API installation before retrying Pi's copy command. + +### Shared storage reports permission denied + +Run `termux-setup-storage`, approve the Android permission request, and retry the path under `~/storage/` or `/storage/emulated/0`. + +### Pi is not found after installation + +Open a new Termux shell and run: + +```bash +npm prefix -g +command -v pi +``` + +Confirm that the global npm binary directory is on `PATH`, then reinstall Pi if the package is missing. diff --git a/packages/coding-agent/docs/tmux.md b/packages/coding-agent/docs/tmux.md index 0083b5f1f..091d61647 100644 --- a/packages/coding-agent/docs/tmux.md +++ b/packages/coding-agent/docs/tmux.md @@ -1,63 +1,55 @@ -# tmux Setup +# Run Pi in tmux -Pi works inside tmux, but tmux strips modifier information from certain keys by default. Without configuration, `Shift+Enter` and `Ctrl+Enter` are usually indistinguishable from plain `Enter`. +Pi works inside tmux, but tmux can report `Shift+Enter`, `Ctrl+Enter`, and plain `Enter` as the same key. Enable extended keys so Pi can distinguish them. -## Recommended Configuration +## Check your tmux version -Add to `~/.tmux.conf`: +```bash +tmux -V +``` + +For tmux 3.5 or newer, use the recommended CSI-u configuration below. For tmux 3.2 through 3.4, use the older-version configuration. + +## Enable extended keys in tmux 3.5 or newer + +Add these lines to `~/.tmux.conf`: ```tmux set -g extended-keys on set -g extended-keys-format csi-u ``` -Then restart tmux fully: +Pi requests extended-key reporting when the terminal does not provide the Kitty keyboard protocol directly. CSI-u is the most reliable format for forwarding modified keys through tmux. + +## Restart tmux + +The configuration applies to the tmux server. To guarantee that it is active, close your tmux sessions and start a new server. + +If you choose to stop the server from the command line, save your work first. This command terminates every session managed by that server: ```bash tmux kill-server tmux ``` -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. +## Verify modified keys -## Why `csi-u` Is Recommended +Start Pi inside the new tmux session and check that: -With only: +1. `Shift+Enter` inserts a new line in the editor. +2. `Enter` submits the prompt. +3. `Alt+Enter` queues a follow-up on macOS and Linux. Windows and WSL use `Ctrl+Q` by default. + +If these keys still behave like plain `Enter`, verify that the terminal outside tmux can report modified keys. See [Configure your terminal](terminal-setup.md). + +## Use tmux 3.2 through 3.4 + +These versions support extended keys but not `extended-keys-format csi-u`. Add only: ```tmux set -g extended-keys on ``` -tmux defaults to `extended-keys-format xterm`. When an application requests extended key reporting, modified keys are forwarded in xterm `modifyOtherKeys` format such as: +Pi supports the xterm `modifyOtherKeys` format used by these versions. Restart tmux and repeat the verification steps. -- `Ctrl+C` → `\x1b[27;5;99~` -- `Ctrl+D` → `\x1b[27;5;100~` -- `Ctrl+Enter` → `\x1b[27;5;13~` - -With `extended-keys-format csi-u`, the same keys are forwarded as: - -- `Ctrl+C` → `\x1b[99;5u` -- `Ctrl+D` → `\x1b[100;5u` -- `Ctrl+Enter` → `\x1b[13;5u` - -Pi supports both formats, but `csi-u` is the recommended tmux setup. - -## What This Fixes - -Without tmux extended keys, modified Enter keys collapse to legacy sequences: - -| Key | Without extkeys | With `csi-u` | -|-----|-----------------|--------------| -| Enter | `\r` | `\r` | -| Shift+Enter | `\r` | `\x1b[13;2u` | -| Ctrl+Enter | `\r` | `\x1b[13;5u` | -| Alt/Option+Enter | `\x1b\r` | `\x1b[13;3u` | - -This affects the default keybindings (`Enter` to submit, `Shift+Enter` for newline) and any custom keybindings using modified Enter. - -## Requirements - -- tmux 3.5 or later for `extended-keys-format csi-u` (run `tmux -V` to check) -- A terminal emulator that supports extended keys (Ghostty, Kitty, iTerm2, WezTerm, Windows Terminal) - -With tmux 3.2 through 3.4, omit `extended-keys-format csi-u`; Pi still supports tmux's default xterm `modifyOtherKeys` format. +For older versions, upgrade tmux or use Pi outside tmux rather than relying on modified Enter shortcuts. diff --git a/packages/coding-agent/docs/windows.md b/packages/coding-agent/docs/windows.md index 2517fd946..89d82114c 100644 --- a/packages/coding-agent/docs/windows.md +++ b/packages/coding-agent/docs/windows.md @@ -1,18 +1,40 @@ -# Windows Setup +# Run Pi on Windows -Pi uses Git Bash by default on Windows. Checked locations (in order): +Run Pi either as a native Windows process or inside Windows Subsystem for Linux (WSL). Native Windows uses Git Bash by default for Bash commands and can optionally expose PowerShell to the model. Pi inside WSL uses the Linux environment and its Bash installation. -1. Custom path from `~/.pi/agent/settings.json` -2. Git Bash (`C:\Program Files\Git\bin\bash.exe`) -3. `bash.exe` on PATH (Cygwin, MSYS2, WSL) +Follow the main [Quickstart](quickstart.md) to install and authenticate Pi. Use this page to choose and configure its command environment. -For most users, [Git for Windows](https://git-scm.com/download/win) is sufficient. +## Choose native Windows or WSL -## PowerShell Tool +| Environment | Command environment | Use it when | +|---|---|---| +| Native Windows with Git Bash | Git Bash for the built-in `bash` tool and `!` commands | Your files and development tools primarily live on Windows | +| Native Windows with the `powershell` tool | PowerShell for model tool calls; Bash remains available for `!` commands | The task depends on PowerShell modules or Windows-native commands | +| WSL | Linux Bash and tools inside the selected WSL distribution | Your files and toolchain already live in Linux or WSL | -The optional `powershell` tool runs commands through `pwsh.exe` when available, otherwise Windows PowerShell. It starts PowerShell with `-NoProfile -NonInteractive -ExecutionPolicy Bypass`. Administrator-enforced execution policies can still take precedence. +## Use Git Bash on native Windows -Use `defaultTools` to replace the model-facing `bash` tool: +For most native Windows users, installing [Git for Windows](https://git-scm.com/download/win) is sufficient. + +Pi resolves Bash in this order: + +1. `shellPath` from `~/.pi/agent/settings.json` +2. Git Bash under `Program Files` or `Program Files (x86)` +3. `bash.exe` on `PATH`, including Cygwin, MSYS2, or legacy WSL Bash + +Start Pi and enter this command to verify the shell: + +```text +!printf 'Bash is working\n' +``` + +If Pi cannot find Bash, it reports the locations it checked. Install Git for Windows, put another Bash executable on `PATH`, or configure `shellPath`. + +## Let the model use PowerShell + +The optional `powershell` tool runs commands through `pwsh.exe` when available, then falls back to Windows PowerShell. It starts PowerShell with `-NoProfile -NonInteractive -ExecutionPolicy Bypass`. Administrator-enforced execution policies can still take precedence. + +To replace the model-facing `bash` tool with `powershell`, add this to `~/.pi/agent/settings.json`: ```json { @@ -20,20 +42,24 @@ Use `defaultTools` to replace the model-facing `bash` tool: } ``` -Or enable both while comparing behavior: +Restart Pi, then ask it to run a harmless PowerShell command. The `!` and `!!` editor commands continue to use Bash. The `powershell` tool is available only when Pi runs as a native Windows process. -```json -{ - "defaultTools": ["read", "bash", "powershell", "edit", "write"] -} -``` +See [Settings](settings-reference.md#tools) for other tool combinations. -The `!` and `!!` editor commands still use Bash. +## Use a custom Bash executable -## Custom Bash Path +Set `shellPath` when Bash is installed somewhere Pi does not discover automatically: ```json { "shellPath": "C:\\cygwin64\\bin\\bash.exe" } ``` + +JSON uses backslashes for escape sequences. When you write a Windows path with backslashes, write each backslash twice, as shown above. + +See [Configure shell commands](shell-aliases.md) for command prefixes, aliases, and the complete shell-resolution behavior. + +## Configure Windows Terminal + +Windows Terminal reserves or rewrites some modified keys. See [Windows Terminal](terminal-setup.md#windows-terminal) to configure `Shift+Enter` and `Alt+Enter`, and [Keybindings](keybindings.md) for Pi's Windows and WSL shortcut defaults.