* Revert "fix(coding-agent): use alternate logic to find Bun's node_modules (#3861)"
This reverts commit c241c6d6d0. The logic
is faulty: the original strategy of looking for node_modules by asking
the package manager is not incorrect even on bun. Instead, it should
learn a different method of asking the package manager for node_modules
when the *package manager* is bun, not the *runtime*.
* feat(coding-agent): detect bun as package manager and use alternate root query
When `"npmCommand": ["bun"]` is configured in settings.json, pi fails to
start because it invokes `bun root -g`, which doesn't exist:
error: Failed to run bun root -g: error: Script not found "root"
Add a (simple) check for Bun being used as package manager, and instead
build the relative path starting from Bun's bin directory.
9.7 KiB
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.
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
{
"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 terminal cursor |
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.
Warnings
| Setting | Type | Default | Description |
|---|---|---|---|
warnings.anthropicExtraUsage |
boolean | true |
Show a warning when Anthropic subscription auth may use paid extra usage |
{
"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) |
{
"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 | SDK default | 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.
{
"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 | "sse" |
Preferred transport for providers that support multiple transports: "sse", "websocket", or "auto" |
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"]) |
{
"npmCommand": ["mise", "exec", "node@20", "--", "npm"]
}
npmCommand is used for all npm package-manager operations, including installs, uninstalls, and dependency installs inside git packages. 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.
Normally the package manager's global modules location is queried using root -g. As a special case, if the first element of npmCommand is "bun", the modules location will instead be queried with pm bin -g.
Sessions
| 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, --session-dir CLI flag takes precedence over sessionDir in settings.json.
Model Cycling
| 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
| 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:
{
"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
{
"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:
// ~/.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 }
}