# Settings Pi uses JSON settings files with project settings overriding global settings. | Location | Scope | |----------|-------| | `~/.pi/agent/settings.json` | Global (all projects) | | `.pi/settings.json` | Project (current directory) | Edit directly or use `/settings` for common options. ## Project Trust 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. 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. `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`. 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. ## All Settings ### Model & Thinking | Setting | Type | Default | Description | |---------|------|---------|-------------| | `defaultProvider` | string | - | Default provider (e.g., `"anthropic"`, `"openai"`) | | `defaultModel` | string | - | Default model ID | | `defaultThinkingLevel` | string | - | `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"` | | `hideThinkingBlock` | boolean | `false` | Hide thinking blocks in output | | `thinkingBudgets` | object | - | Custom token budgets per thinking level | #### thinkingBudgets ```json { "thinkingBudgets": { "minimal": 1024, "low": 4096, "medium": 10240, "high": 32768 } } ``` ### UI & Display | Setting | Type | Default | Description | |---------|------|---------|-------------| | `theme` | string | `"dark"` | Theme name (`"dark"`, `"light"`, or custom) | | `quietStartup` | boolean | `false` | Hide startup header | | `collapseChangelog` | boolean | `false` | Show condensed changelog after updates | | `enableInstallTelemetry` | boolean | `true` | Send an anonymous install/update version ping after first install or changelog-detected updates. This does not control update checks | | `doubleEscapeAction` | string | `"tree"` | Action for double-escape: `"tree"`, `"fork"`, or `"none"` | | `treeFilterMode` | string | `"default"` | Default filter for `/tree`: `"default"`, `"no-tools"`, `"user-only"`, `"labeled-only"`, `"all"` | | `editorPaddingX` | number | `0` | Horizontal padding for input editor (0-3) | | `autocompleteMaxVisible` | number | `5` | Max visible items in autocomplete dropdown (3-20) | | `showHardwareCursor` | boolean | `false` | Show the terminal cursor while TUI positions it for IME support | ### Telemetry and update checks `enableInstallTelemetry` only controls the anonymous install/update ping to `https://pi.dev/api/report-install`. Opting out of telemetry does not disable update checks; Pi can still fetch `https://pi.dev/api/latest-version` to look for the latest version. Set `PI_SKIP_VERSION_CHECK=1` to disable the Pi version update check. Use `--offline` or `PI_OFFLINE=1` to disable all startup network operations described here, including update checks, package update checks, and install/update telemetry. ### pi.dev Integration `/share` uses pi.dev for unlisted session sharing when an authenticated pi.dev profile is already available; otherwise it falls back to the GitHub gist backend. Setup, `/pi.dev`, and `/share pi.dev` create or sign in to a pi.dev profile when needed, storing the pi.dev OAuth credential in `auth.json` under `pi.dev`. `PI_DEV_URL` overrides the pi.dev API base URL. Creating or signing in to a pi.dev profile during setup or with `/pi.dev` enables background sync of session activity analytics metadata. `/share pi.dev` signs in only to store shared sessions and does not change activity sync. Disable sync with `/settings` or `piDev.activitySync.enabled`. | Setting | Type | Default | Description | |---------|------|---------|-------------| | `piDev.activitySync.enabled` | boolean | `false` | Enable background activity sync after pi.dev profile setup | | `piDev.activitySync.intervalHours` | number | `24` | Minimum hours between background sync attempts | | `piDev.activitySync.deviceId` | string | auto | Stable device ID used for pi.dev activity sync | Activity sync omits raw message content, tool arguments, thinking text, error text, labels, names, and custom data. Non-secret sync timestamps are stored in `activity-sync.json`. `PI_OFFLINE=1` disables background sync. ```json { "piDev": { "activitySync": { "deviceId": "019eab26-10a1-79a4-94b0-dc6914f6a82d", "enabled": true, "intervalHours": 24 } } } ``` ### Warnings | Setting | Type | Default | Description | |---------|------|---------|-------------| | `warnings.anthropicExtraUsage` | boolean | `true` | Show a warning when Anthropic subscription auth may use paid extra usage | ```json { "warnings": { "anthropicExtraUsage": false } } ``` ### Compaction | Setting | Type | Default | Description | |---------|------|---------|-------------| | `compaction.enabled` | boolean | `true` | Enable auto-compaction | | `compaction.reserveTokens` | number | `16384` | Tokens reserved for LLM response | | `compaction.keepRecentTokens` | number | `20000` | Recent tokens to keep (not summarized) | ```json { "compaction": { "enabled": true, "reserveTokens": 16384, "keepRecentTokens": 20000 } } ``` ### Branch Summary | Setting | Type | Default | Description | |---------|------|---------|-------------| | `branchSummary.reserveTokens` | number | `16384` | Tokens reserved for branch summarization | | `branchSummary.skipPrompt` | boolean | `false` | Skip "Summarize branch?" prompt on `/tree` navigation (defaults to no summary) | ### Retry | Setting | Type | Default | Description | |---------|------|---------|-------------| | `retry.enabled` | boolean | `true` | Enable automatic agent-level retry on transient errors | | `retry.maxRetries` | number | `3` | Maximum agent-level retry attempts | | `retry.baseDelayMs` | number | `2000` | Base delay for agent-level exponential backoff (2s, 4s, 8s) | | `retry.provider.timeoutMs` | number | SDK default | Provider/SDK request timeout in milliseconds | | `retry.provider.maxRetries` | number | `0` | Provider/SDK retry attempts | | `retry.provider.maxRetryDelayMs` | number | `60000` | Max server-requested delay before failing (60s) | When a provider requests a retry delay longer than `retry.provider.maxRetryDelayMs` (e.g., Google's "quota will reset after 5h"), the request fails immediately with an informative error instead of waiting silently. Set to `0` to disable the cap. Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explicitly needed. Setting it above `0` can make SDK/provider retries handle out-of-usage-limit errors before Pi sees them, which may block the agent until the provider quota resets in some circumstances. ```json { "retry": { "enabled": true, "maxRetries": 3, "baseDelayMs": 2000, "provider": { "timeoutMs": 3600000, "maxRetries": 0, "maxRetryDelayMs": 60000 } } } ``` ### Message Delivery | Setting | Type | Default | Description | |---------|------|---------|-------------| | `steeringMode` | string | `"one-at-a-time"` | How steering messages are sent: `"all"` or `"one-at-a-time"` | | `followUpMode` | string | `"one-at-a-time"` | How follow-up messages are sent: `"all"` or `"one-at-a-time"` | | `transport` | string | `"auto"` | Preferred transport for providers that support multiple transports: `"sse"`, `"websocket"`, `"websocket-cached"`, or `"auto"` | | `httpIdleTimeoutMs` | number | `300000` | HTTP header/body idle timeout in milliseconds, also used by providers with explicit stream idle timeouts. Set to `0` to disable. | | `websocketConnectTimeoutMs` | number | `15000` | WebSocket connect/open handshake timeout in milliseconds for providers that support WebSocket transports. Set to `0` to disable. | ### Terminal & Images | Setting | Type | Default | Description | |---------|------|---------|-------------| | `terminal.showImages` | boolean | `true` | Show images in terminal (if supported) | | `terminal.imageWidthCells` | number | `60` | Preferred inline image width in terminal cells | | `terminal.clearOnShrink` | boolean | `false` | Clear empty rows when content shrinks (can cause flicker) | | `images.autoResize` | boolean | `true` | Resize images to 2000x2000 max | | `images.blockImages` | boolean | `false` | Block all images from being sent to LLM | ### Shell | Setting | Type | Default | Description | |---------|------|---------|-------------| | `shellPath` | string | - | Custom shell path (e.g., for Cygwin on Windows) | | `shellCommandPrefix` | string | - | Prefix for every bash command (e.g., `"shopt -s expand_aliases"`) | | `npmCommand` | string[] | - | Command argv used for npm package lookup/install operations (e.g., `["mise", "exec", "node@20", "--", "npm"]`) | ```json { "npmCommand": ["mise", "exec", "node@20", "--", "npm"] } ``` `npmCommand` is used for all npm package-manager operations, including installs, uninstalls, and dependency installs inside git packages. User-scoped npm packages install under `~/.pi/agent/npm/`; project-scoped npm packages install under `.pi/npm/`. Use argv-style entries exactly as the process should be launched. When `npmCommand` is configured, git package dependency installs use plain `install` to avoid npm-specific flags in wrappers or alternate package managers. ### Sessions | Setting | Type | Default | Description | |---------|------|---------|-------------| | `sessionDir` | string | - | Directory where session files are stored. Accepts absolute or relative paths, plus `~`. | ```json { "sessionDir": ".pi/sessions" } ``` When multiple sources specify a session directory, precedence is `--session-dir`, `PI_CODING_AGENT_SESSION_DIR`, then `sessionDir` in settings.json. ### Model Cycling | Setting | Type | Default | Description | |---------|------|---------|-------------| | `enabledModels` | string[] | - | Model patterns for Ctrl+P cycling (same format as `--models` CLI flag) | ```json { "enabledModels": ["claude-*", "gpt-4o", "gemini-2*"] } ``` ### Markdown | Setting | Type | Default | Description | |---------|------|---------|-------------| | `markdown.codeBlockIndent` | string | `" "` | Indentation for code blocks | ### Resources These settings define where to load extensions, skills, prompts, and themes from. Paths in `~/.pi/agent/settings.json` resolve relative to `~/.pi/agent`. Paths in `.pi/settings.json` resolve relative to `.pi`. Absolute paths and `~` are supported. | Setting | Type | Default | Description | |---------|------|---------|-------------| | `packages` | array | `[]` | npm/git packages to load resources from | | `extensions` | string[] | `[]` | Local extension file paths or directories | | `skills` | string[] | `[]` | Local skill file paths or directories | | `prompts` | string[] | `[]` | Local prompt template paths or directories | | `themes` | string[] | `[]` | Local theme file paths or directories | | `enableSkillCommands` | boolean | `true` | Register skills as `/skill:name` commands | Arrays support glob patterns and exclusions. Use `!pattern` to exclude. Use `+path` to force-include an exact path and `-path` to force-exclude an exact path. #### packages String form loads all resources from a package: ```json { "packages": ["pi-skills", "@org/my-extension"] } ``` Object form filters which resources to load: ```json { "packages": [ { "source": "pi-skills", "skills": ["brave-search", "transcribe"], "extensions": [] } ] } ``` See [packages.md](packages.md) for package management details. ## Example ```json { "defaultProvider": "anthropic", "defaultModel": "claude-sonnet-4-20250514", "defaultThinkingLevel": "medium", "theme": "dark", "compaction": { "enabled": true, "reserveTokens": 16384, "keepRecentTokens": 20000 }, "retry": { "enabled": true, "maxRetries": 3 }, "enabledModels": ["claude-*", "gpt-4o"], "warnings": { "anthropicExtraUsage": true }, "packages": ["pi-skills"] } ``` ## Project Overrides Project settings (`.pi/settings.json`) override global settings. Nested objects are merged: ```json // ~/.pi/agent/settings.json (global) { "theme": "dark", "compaction": { "enabled": true, "reserveTokens": 16384 } } // .pi/settings.json (project) { "compaction": { "reserveTokens": 8192 } } // Result { "theme": "dark", "compaction": { "enabled": true, "reserveTokens": 8192 } } ```