mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
Refs #7756, #5607. Problem: when a wrapper or another package manager provides Pi (mise, a `PNPM_HOME` wrapper such as nub, Nix), `pi update` cannot update it and prints "pi cannot self-update this installation." Users with several machines have to remember which tool updates Pi on which machine. Example: ```sh export PI_SELF_UPDATE_COMMAND="mise use -g npm:{packageName}@{version}" pi update # Updating pi with mise use -g npm:@earendil-works/pi-coding-agent@1.4.0... # Updated pi from 1.3.0 to 1.4.0 ``` or in `~/.pi/agent/settings.json`: ```json { "selfUpdateCommand": ["nix", "profile", "upgrade", "pi"] } ``` Behavior: - `pi update` still checks pi.dev first. The command runs only when a newer release exists, or with `--force`, and the release note prints first. - Placeholders come from that release: `{packageName}`, `{version}`, `{installSpec}` (`<packageName>@<version>`). A package rename announced by pi.dev flows into them. - `PI_SELF_UPDATE_COMMAND` takes precedence and is split on whitespace (no quoting). The setting is argv, for arguments with spaces, and is read only from global settings, so a project's `.pi/settings.json` cannot inject a command. - The configured command replaces Pi's own update logic for every install method, including installer-managed installs: it is explicit user intent. - Exit code 0 does not prove an update. Pi reports "Updated pi from X to Y" when its own `package.json` now shows Y (in-place updates) or when `pi --version` from PATH reports Y (wrappers such as mise or Nix that install each version into a new directory). Otherwise it warns: ``Ran <cmd>, but `pi --version` reports X, not Y.`` - "cannot self-update this installation" now mentions the env var and setting. Docs: `docs/cli.md` (new "Custom update command" section), `docs/settings.md`, `docs/environment-variables.md`, `--help` env list, regenerated `schemas/settings.schema.json`. Tests: unit tests for argv resolution and placeholders in `test/config.test.ts`; CLI tests in `test/package-command-paths.test.ts` for env precedence over the setting and the managed install, global-only setting gated by the version check, and command failure. `npm run check` passes. Manual end-to-end check with real mise 2026.10.23 in a sandboxed HOME, running this branch as the mise-installed 1.3.0 (`PI_PACKAGE_DIR` pointing at mise's install): | Scenario | Result | |---|---| | `mise use -g npm:{packageName}@{version}` | mise installs 1.4.0; `Updated pi from 1.3.0 to 1.4.0` | | Already 1.4.0 | `pi is already up to date (v1.4.0)`, mise not run | | In-place `npm install -g --prefix <dir> {installSpec}` via the setting | `Updated pi from 1.3.0 to 1.4.0` | | Command `true` (exit 0, installs nothing) | ``Ran true, but `pi --version` reports 1.3.0, not 1.4.0.`` | This PR is AI-generated.
103 lines
5.9 KiB
Markdown
103 lines
5.9 KiB
Markdown
# Environment Variables
|
|
|
|
Pi uses environment variables in three ways:
|
|
|
|
- Variables such as `PI_OFFLINE` configure the Pi process.
|
|
- 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 [Providers](providers.md#use-an-api-key-from-the-environment).
|
|
|
|
## Process Marker
|
|
|
|
The CLI and RPC entry points set two process markers:
|
|
|
|
- `AI_AGENT=pi` is a generic marker that lets tooling identify Pi as the agent that launched the process.
|
|
- `PI_CODING_AGENT=true` is Pi-specific and lets child processes detect that they run inside Pi.
|
|
|
|
Child processes inherit both markers. They are not session-specific and are not set automatically when Pi is embedded through the SDK.
|
|
|
|
## Shell Tool Session Environment
|
|
|
|
Commands run by the `bash` and `powershell` tools receive the current Pi session state:
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `PI_SESSION_ID` | Current session ID |
|
|
| `PI_SESSION_FILE` | Absolute path to the current session JSONL file; unset for ephemeral sessions |
|
|
| `PI_PROVIDER` | Currently selected model provider |
|
|
| `PI_MODEL` | Currently selected model ID |
|
|
| `PI_REASONING_LEVEL` | Current effective reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max` |
|
|
|
|
The values are resolved when each command starts. Switching models or changing the reasoning level therefore affects the next shell command without restarting Pi. `PI_PROVIDER` and `PI_MODEL` identify the selected Pi model, not a different upstream model that a router may choose internally.
|
|
|
|
When asked which model or provider is running, inspect these variables instead of inferring the answer from the system prompt:
|
|
|
|
```bash
|
|
printf '%s/%s\n' "$PI_PROVIDER" "$PI_MODEL"
|
|
printf 'reasoning=%s session=%s\n' "$PI_REASONING_LEVEL" "$PI_SESSION_ID"
|
|
```
|
|
|
|
The session file can be inspected directly when the session is persistent:
|
|
|
|
```bash
|
|
if [ -n "$PI_SESSION_FILE" ]; then
|
|
tail -n 1 "$PI_SESSION_FILE"
|
|
fi
|
|
```
|
|
|
|
These variables are injected into the LLM-callable `bash` and `powershell` tools. They are not injected into user-entered `!` or `!!` commands.
|
|
|
|
### Custom Shell Tools
|
|
|
|
Tools created with `createBashTool()` or `createPowerShellTool()` expose the session environment by default when registered with Pi. Injection happens before `spawnHook`, so a hook receives the variables in `ctx.env`:
|
|
|
|
```typescript
|
|
const bashTool = createBashTool(cwd, {
|
|
spawnHook: (ctx) => ({
|
|
...ctx,
|
|
env: { ...ctx.env, CI: "1" },
|
|
}),
|
|
});
|
|
```
|
|
|
|
Disable session metadata independently of the spawn hook:
|
|
|
|
```typescript
|
|
const powershellTool = createPowerShellTool(cwd, {
|
|
exposeSessionEnvironment: false,
|
|
spawnHook: (ctx) => ctx,
|
|
});
|
|
```
|
|
|
|
When disabled, Pi removes inherited values for these variables so nested Pi processes do not expose stale parent-session metadata.
|
|
|
|
## Pi Process Configuration
|
|
|
|
These variables are read by Pi itself:
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `PI_CODING_AGENT_DIR` | Override the config directory; default is `~/.pi/agent` |
|
|
| `PI_CODING_AGENT_SESSION_DIR` | Override session storage; overridden by `--session-dir` |
|
|
| `PI_PACKAGE_DIR` | Override the package directory, useful for Nix/Guix store paths |
|
|
| `PI_OFFLINE` | Disable automatic network activity, including model catalog refreshes |
|
|
| `PI_SKIP_VERSION_CHECK` | Disable the `pi.dev` latest-version request |
|
|
| `PI_SELF_UPDATE_COMMAND` | Command `pi update` runs to update Pi itself, split on whitespace, with `{packageName}`, `{version}`, and `{installSpec}` placeholders. Takes precedence over the `selfUpdateCommand` setting. See [Custom update command](cli.md#custom-update-command) |
|
|
| `PI_TELEMETRY` | Override install/update telemetry and provider attribution headers: `1`/`true`/`yes` or `0`/`false`/`no` |
|
|
| `PI_CODEMODE_MAX_WORKERS` | Maximum codemode workers alive at once across all sessions in the process; default `2`. Each worker's script may use up to 256 MB. Raise it when one process runs several sessions, such as in-process subagents. Further scripts wait for a free worker. See [Codemode](codemode.md) |
|
|
| `PI_CACHE_RETENTION` | Set to `long` for extended provider prompt caching where supported |
|
|
| `PI_SHARE_VIEWER_URL` | Override the base URL used by `/share` |
|
|
| `PI_RADIUS_GATEWAY` | Override the Radius gateway origin used by `/bug` uploads |
|
|
| `PI_CLEAR_ON_SHRINK` | Set to `1` to clear empty rows when rendered content shrinks; the `terminal.clearOnShrink` setting takes precedence. See [Settings](settings.md) |
|
|
| `PI_HARDWARE_CURSOR` | Set to `1` to show the hardware cursor; see [Terminal setup](terminal-setup.md) |
|
|
| `PI_CLIPBOARD_OSC52` | Set to `1` to also send copied text to the terminal with OSC 52 after the local clipboard write, as Pi does over SSH. Use it when a remote client reaches Pi without SSH variables, such as a multiplexer attached from another machine or a remote IDE daemon |
|
|
| `PI_HYPERLINKS` | Override OSC 8 hyperlink detection with `1`, `0`, or `auto` |
|
|
| `PI_PROGRAM_STATUS` | Override OSC 7501 program status detection: `1` always reports, `0` never reports; otherwise Pi reports only after the terminal confirms support. See [Terminal setup](terminal-setup.md#program-status) |
|
|
| `PI_IMAGE_PROTOCOL` | Override inline image detection with `kitty`, `iterm2`, `none`, or `auto` |
|
|
| `PI_TRUE_COLOR` | Override truecolor detection with `1`, `0`, or `auto` |
|
|
| `PI_TUI_ESC_TIMEOUT` | How long to wait after a lone ESC before treating it as Escape, in milliseconds; defaults to `100` over SSH and `10` otherwise. Increase if Alt-key input is misread as Escape |
|
|
| `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 provider-specific configuration are listed in [Providers](providers.md#use-an-api-key-from-the-environment).
|