On this page
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. To save startup model defaults interactively, use /model and press Ctrl+S on the desired model. To save the startup thinking level, use /thinking and press Ctrl+S.
Project Trust
CopiedOn interactive startup, pi asks before trusting a project folder that contains project-local settings, resources, or project .agents/skills and has no saved decision for the folder or a parent folder in ~/.pi/agent/trust.json. Trusting a project allows pi to 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 an applicable saved trust decision, they use defaultProjectTrust from global settings: ask (default) and never ignore those project resources, while always trusts them. Pass --approve/-a or --no-approve/-na to override project trust for one run.
If no extension or saved decision applies, defaultProjectTrust controls the fallback behavior. Set it to "ask", "always", or "never" in ~/.pi/agent/settings.json, or change it with /settings.
pi config and package commands use the same project trust flow, except pi update never prompts. Pass --approve to trust project-local settings for one command or --no-approve to ignore them.
Use /trust in interactive mode to save a project trust decision for future sessions, including trust for the immediate parent folder. It writes ~/.pi/agent/trust.json only; the current session is not reloaded, so restart pi for changes to take effect.
All Settings
CopiedModel & Thinking
Copied| Setting | Type | Default | Description |
|---|---|---|---|
defaultProvider |
string | - | Startup provider (e.g., "anthropic", "openai"; saved with Ctrl+S in /model, or edited manually) |
defaultModel |
string | - | Startup model ID (saved with Ctrl+S in /model, or edited manually) |
defaultThinkingLevel |
string | - | Startup thinking level (saved with Ctrl+S in /thinking, or edited manually): "off", "minimal", "low", "medium", "high", "xhigh", "max" |
modelThinkingLevels |
object | - | Per-model startup thinking levels keyed by "provider/modelId"; configure from /settings → Default thinking level per model or edit manually |
hideThinkingBlock |
boolean | false |
Hide thinking blocks in output |
showCacheMissNotices |
boolean | false |
Show transcript notices for significant prompt-cache misses, compaction or branch-summary usage, and provider recovery diagnostics such as dropped Anthropic thinking blocks |
thinkingBudgets |
object | - | Custom token budgets per thinking level. Anthropic, Google, and Bedrock use these natively. OpenAI-compatible models use them when compat.thinkingTokenBudgetField (or supportsThinkingTokenBudget) is set. |
thinkingBudgets
Copied{
"thinkingBudgets": {
"minimal": 1024,
"low": 4096,
"medium": 10240,
"high": 32768
}
}
UI & Display
Copied| Setting | Type | Default | Description |
|---|---|---|---|
theme |
string | "dark" |
Theme name ("dark", "light", or custom) |
externalEditor |
string | $VISUAL, then $EDITOR, then Notepad on Windows or nano elsewhere |
Command for Ctrl+G external editor; takes precedence over environment variables |
quietStartup |
boolean | false |
Hide startup header |
defaultProjectTrust |
string | "ask" |
Fallback project trust behavior: "ask", "always", or "never". Global setting only |
collapseChangelog |
boolean | false |
Show condensed changelog after updates |
enableInstallTelemetry |
boolean | true |
Send the anonymous install/update ping and selected provider attribution headers. This does not control update checks |
enableAnalytics |
boolean | false |
Opt-in analytics data sharing. Currently only asked for during the experimental first-time setup (PI_EXPERIMENTAL=1) |
trackingId |
string | - | Analytics tracking identifier, generated when enableAnalytics is turned on |
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) |
outputPad |
number | 1 |
Horizontal padding for user messages, assistant messages, and thinking (0 or 1) |
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 |
tuiMode |
string | "regular" |
Interactive TUI mode: "regular" or experimental "fullscreen". Changes from /settings apply immediately; --tui-mode overrides this setting at startup |
fullscreenExitOutput |
string | "transcript" |
Fullscreen exit output: "transcript" prints the final transcript and resume hint, while "resume-hint" restores the previous screen and prints only the resume hint. Has no effect in regular TUI mode |
fullscreenScrollbar |
string | "auto" |
Fullscreen transcript scrollbar: "auto" shows it temporarily while scrolling or while the pointer is over its rightmost-column track, "always" reserves that column and keeps it visible, and "hidden" hides it. Has no effect in regular TUI mode |
fullscreenCopyOnSelect |
boolean | true |
Automatically copy selected text in fullscreen mode. When disabled, selections stay highlighted and Ctrl+X copies the active selection |
For VS Code, include --wait so pi resumes after the editor exits:
{
"externalEditor": "code --wait"
}
Telemetry and update checks
CopiedenableInstallTelemetry controls the anonymous install/update ping to https://pi.dev/api/report-install and Pi attribution headers for OpenRouter, NVIDIA NIM, and Cloudflare provider requests. Opting out disables both. It 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.
Network
Copied| Setting | Type | Default | Description |
|---|---|---|---|
httpProxy |
string | - | HTTP proxy URL applied as HTTP_PROXY and HTTPS_PROXY. Global setting only. |
{
"httpProxy": "http://127.0.0.1:7890"
}
Warnings
Copied| Setting | Type | Default | Description |
|---|---|---|---|
warnings.anthropicExtraUsage |
boolean | true |
Show a warning when Anthropic subscription auth may use paid extra usage |
{
"warnings": {
"anthropicExtraUsage": false
}
}
Compaction
Copied| 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) |
compaction.modelOverrides |
object | - | Per-model reserveTokens and keepRecentTokens overrides keyed by exact "provider/modelId" |
{
"compaction": {
"enabled": true,
"reserveTokens": 16384,
"keepRecentTokens": 20000
}
}
Per-model compaction overrides
Copied{
"compaction": {
"enabled": true,
"reserveTokens": 16384,
"keepRecentTokens": 20000,
"modelOverrides": {
"some-provider/big-model": {
"reserveTokens": 400000
},
"local/small-model": {
"reserveTokens": 2048,
"keepRecentTokens": 4096
}
}
}
}
Keys match exact, case-sensitive provider/modelId values, not names or glob patterns. Model IDs may contain slashes (for example, openrouter/anthropic/claude-sonnet-4).
Each token setting resolves independently: matching model override → ordinary compaction setting → built-in default. In the example, some-provider/big-model keeps the ordinary 20000 recent tokens. Token values must be non-negative safe integers. Invalid values in the matching model override produce an error when read; only omitted fields fall back to the ordinary setting. Model override entries must be objects. Invalid ordinary token settings produce an error when read, even if the active model has a valid override. Only omitted ordinary values use built-in defaults. Zero is accepted, but reserveTokens: 0 leaves no response margin and also sets the summarization output budget to zero.
Global and project settings merge recursively before model lookup. A project can override one field for a model without replacing its other fields or other models. A global model-specific value takes precedence over a project-wide fallback; override the same model entry in the project to change it.
enabled is not model-specific. The active model's token settings apply to manual compaction, automatic threshold checks (including between assistant turns), and overflow recovery. Switching models takes effect on the next check or compaction. Configure overrides in JSON; /settings retains the ordinary auto-compaction toggle.
See compaction.md for trigger and summarization behavior.
Branch Summary
Copied| Setting | Type | Default | Description |
|---|---|---|---|
branchSummary.reserveTokens |
number | 16384 |
Tokens reserved when selecting branch history; output is capped at 4096 tokens |
branchSummary.skipPrompt |
boolean | false |
Skip "Summarize branch?" prompt on /tree navigation (defaults to no summary) |
Retry
Copied| 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.maxAgentDelayMs |
number | 60000 |
Max agent-level retry delay (60s) |
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) |
Agent-level retries use exponential backoff capped by retry.maxAgentDelayMs, so long retry runs stay responsive after prolonged outages.
When a provider requests a retry delay longer than retry.provider.maxRetryDelayMs, the request fails immediately with an informative error instead of waiting silently. Set it to 0 to disable the limit.
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.
{
"retry": {
"enabled": true,
"maxRetries": 3,
"baseDelayMs": 2000,
"maxAgentDelayMs": 60000,
"provider": {
"timeoutMs": 3600000,
"maxRetries": 0,
"maxRetryDelayMs": 60000
}
}
}
Message Delivery
Copied| 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
Copied| 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) |
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.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 |
Shell
Copied| Setting | Type | Default | Description |
|---|---|---|---|
shellPath |
string | - | Custom shell path (e.g., for Cygwin on Windows); supports a leading ~ for the home directory |
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"]) |
Windows paths in JSON must use forward slashes or escaped backslashes:
{
"shellPath": "C:/Program Files/Git/bin/bash.exe"
}
{
"shellPath": "C:\\Program Files\\Git\\bin\\bash.exe"
}
{
"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.
Tools
Copied| Setting | Type | Default | Description |
|---|---|---|---|
defaultTools |
string[] | - | Built-in tools enabled initially. When omitted, Pi uses its standard defaults |
defaultTools selects the built-in tools enabled at startup. Extension and SDK custom tools remain enabled. Available built-ins are read, bash, powershell, edit, write, grep, find, and ls:
{
"defaultTools": ["bash", "edit", "write"]
}
On Windows, select powershell instead of bash, or include both:
{
"defaultTools": ["read", "powershell", "edit", "write"]
}
An empty array starts with no built-in tools while preserving extension and SDK custom tools. --tools replaces this behavior with a strict allowlist for all tools, --no-tools disables all tools, and --no-builtin-tools disables the built-in defaults. --exclude-tools filters the resulting list. A project defaultTools array replaces the global array.
Sessions
Copied| Setting | Type | Default | Description |
|---|---|---|---|
sessionDir |
string | - | Directory where session files are stored. Accepts absolute or relative paths, plus ~. |
{ "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
Copied| Setting | Type | Default | Description |
|---|---|---|---|
enabledModels |
string[] | - | Model patterns for Ctrl+P cycling (same format as --models CLI flag) |
{
"enabledModels": ["claude-*", "gpt-4o", "gemini-2*"]
}
Markdown
Copied| Setting | Type | Default | Description |
|---|---|---|---|
markdown.codeBlockIndent |
string | " " |
Indentation for code blocks |
markdown.mermaid |
string | "streaming" |
Mermaid rendering mode: "off", "final", or "streaming" |
Resources
CopiedThese 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
CopiedString form loads all resources from a package:
{
"packages": ["pi-skills", "@org/my-extension"]
}
Object form filters which resources to load:
{
"packages": [
{
"source": "pi-skills",
"skills": ["brave-search", "transcribe"],
"extensions": []
}
]
}
See packages.md for package management details.
Example
Copied{
"defaultProvider": "anthropic",
"defaultModel": "claude-sonnet-4-20250514",
"defaultThinkingLevel": "medium",
"modelThinkingLevels": {
"anthropic/claude-sonnet-4-20250514": "high"
},
"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
CopiedProject settings (.pi/settings.json) override global settings. Nested objects are merged:
// ~/.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 }
}