Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Settings, configuration, and trust

Configuration directory

The runtime resolves the agent configuration directory (<agent-dir>) in this order:

  1. PI_CODING_AGENT_DIR environment variable.
  2. The platform home directory (HOME on Unix, USERPROFILE on Windows) with /.pi/agent appended.

Source: crates/pi-coding/src/resources.rs:26-41.

Within <agent-dir> the CLI reads:

  • settings.json — global startup defaults and operational settings.
  • models.json — custom providers and model overrides.
  • auth.json — stored provider credentials.
  • trust.json — persisted project trust decisions.
  • sessions/ — native Pi v3 JSONL session files.
  • skills/, prompts/, themes/ — global resources.

Project-local resources are loaded from <workspace>/.pi/ only when that project is trusted. Source: crates/pi-coding/src/resource_manager.rs:49-70.

Project trust

By default, rpi asks before loading project-local .pi resources (skills, prompts, themes, keybindings, extensions, agents, and package settings). Trust decisions are stored in <agent-dir>/trust.json, versioned as TRUST_STORE_VERSION = 1, and scoped to the canonical project path. The resolver walks parent directories, so a decision at <workspace> covers <workspace>/sub-project.

Source: crates/pi-coding/src/trust.rs:67-140 and crates/pi-coding/src/trust.rs:180-216.

Default behavior is controlled by settings.json:

{
  "defaultProjectTrust": "ask"
}

Allowed values:

  • "ask" — prompt for trust in interactive modes; treat as untrusted in headless modes (default).
  • "always" — trust every project with a .pi directory without asking.
  • "never" — never trust project-local resources.

One-run overrides:

rpi -a "hello"           # --approve: trust this project's .pi for this run
rpi --no-approve "hello" # refuse project .pi for this run

Headless modes (--print, --mode json, --mode rpc) never prompt. In headless mode an unset or "ask" decision is treated as untrusted, so use --approve when you need project resources. If the project has no .pi directory, it is implicitly trusted.

Source: crates/pi-coding/src/trust.rs:37-43 and crates/pi-cli/src/args.rs:168-174.

settings.json

Global settings live at <agent-dir>/settings.json. Project settings live at <workspace>/.pi/settings.json and are merged on top of global settings when trusted. Unknown fields are retained across merges so other product modules can use them.

Source: crates/pi-coding/src/settings.rs:666-669 and crates/pi-coding/src/settings.rs:729-843.

{
  "defaultProvider": "openai",
  "defaultModel": "openai/gpt-5",
  "defaultThinkingLevel": "medium",
  "defaultProjectTrust": "ask",
  "theme": "dark",
  "compaction": {
    "enabled": true,
    "reserveTokens": 8192,
    "keepRecentTokens": 4096
  },
  "terminal": {
    "showImages": true,
    "imageWidthCells": 80,
    "clearOnShrink": false,
    "showTerminalProgress": true
  },
  "images": {
    "autoResize": true,
    "blockImages": false
  },
  "retry": {
    "enabled": true,
    "maxRetries": 3,
    "baseDelayMs": 2000,
    "provider": {
      "timeoutMs": 60000,
      "maxRetries": 3,
      "maxRetryDelayMs": 60000
    }
  },
  "transport": "auto",
  "timeoutMs": 60000,
  "maxRetryDelayMs": 60000,
  "temperature": 0.7,
  "maxTokens": 4096,
  "cacheRetention": "short",
  "thinkingBudgets": {
    "minimal": 1024,
    "low": 2048,
    "medium": 4096,
    "high": 8192
  },
  "scopedModels": ["openai/*", "anthropic/*"],
  "branchSummary": {
    "reserveTokens": 16384,
    "skipPrompt": false
  },
  "keybindings": {
    "toggleTheme": "ctrl+t"
  },
  "quietStartup": false,
  "showThinking": true,
  "exposeSessionEnvironment": true,
  "doubleEscapeAction": "tree",
  "orchestration": {
    "process": false,
    "tasks": false,
    "todo": false,
    "maxConcurrency": 8,
    "maxRecursionDepth": 8,
    "mailboxCapacity": 1000,
    "maxToolsPerAgent": 16
  },
  "packages": [
    "git:github.com/owner/pi-my-tools",
    { "source": "./my-pi-tools", "extensions": ["*"] }
  ],
  "extensions": ["ext-id"],
  "skills": ["rust-review"],
  "prompts": ["custom-prompt"],
  "themes": ["solarized"]
}

Known fields

FieldPurpose
defaultProviderDefault provider id used when no model flag is given.
defaultModelDefault model id used when no --model is given.
defaultThinkingLevelDefault reasoning level (off, minimal, low, medium, high, xhigh, max).
defaultProjectTrust"ask", "always", or "never".
approvalModeGlobal host tool policy: yolo allows all tools, write confirms Exec, and ask confirms every tool call. Project settings cannot override it.
steeringModeSteering queue mode (all or one-at-a-time).
followUpModeFollow-up queue mode (all or one-at-a-time).
sessionDirOverride the session storage directory.
sessionImportSourcesAllowed session import sources (omp, codex, claude, grok, droid).
sessionTtlDaysStartup session TTL pruning age in days (default 30; must be > 0).
authScopeActive credential scope label; PI_AUTH_SCOPE overrides it at runtime.
themeInitial TUI theme name.
compactionContext compaction limits (enabled, reserveTokens, keepRecentTokens).
terminalLegacy TUI rendering options (showImages, imageWidthCells, clearOnShrink, showTerminalProgress).
imagesImage display options (autoResize, blockImages) plus generation overrides (genModel, genBaseUrl, genApiKey).
retryRetry policy (enabled, maxRetries, baseDelayMs, plus optional provider overrides).
autoRetry, maxRetries, baseDelayMsTop-level legacy aliases for the same retry fields.
transportStream transport (auto, sse, web-socket, web-socket-cached).
timeoutMsHTTP/stream timeout.
httpIdleTimeoutMsIdle HTTP connection timeout.
websocketConnectTimeoutMsWebSocket connect timeout.
maxRetryDelayMsMaximum delay between retries.
temperatureSampling temperature, finite and 0..=2.
maxTokensMaximum tokens per model request.
cacheRetentionCache retention (none, short, long).
responsesStatefulChainOpt-in stateful turn chaining for OpenAI Responses API models (default false); see configuration-profiles.md.
thinkingBudgetsPer-level token budgets (minimal, low, medium, high).
scopedModels / enabledModelsAlias for the same model-pattern allowlist.
branchSummaryBranch-summary token reserve and skipPrompt.
keybindingsAction-to-chord map (value is a string or array of strings).
quietStartupSuppress non-essential startup messages.
showThinking / hideThinkingBlockControl whether thinking blocks are shown.
showImages, imageWidthCells, autoResizeImagesTop-level legacy aliases for terminal/image options.
exposeSessionEnvironmentForward session environment to tools.
doubleEscapeActionTUI action on double-escape (fork, tree, none).
orchestrationOrchestration tool gates, concurrency limits, workflow isolation, and soft budgets (see orchestration.md and workflows.md).
selectorOptional model-selector thresholds (advanced).
agentsPer-agent runtime settings (settings.agents.<name>.enabled/model/tools); see orchestration.md.
packagesLocal/git package sources to install/load.
extensions, skills, prompts, themesResource names to load from configured packages and discovered paths.
sandboxOpt-in Linux filesystem sandbox for bash (enabled, network, allowedPaths, deniedPaths, readOnly); see sandbox-isolation.md.
liveHold-to-talk voice configuration (enabled, sttBaseUrl, sttApiKey, sttModel, language, allowInsecure); see live.md.
memoryMemory backend (backend: local/hindsight/off; Hindsight HTTP endpoint/token, plaintext opt-in, bank/scoping, recall policy, injection, and per-operation timeouts); see memory.md.
hooksHost hooks: external commands observing/gating session events; see hooks.md.
permissionRulesPath-level permission rules evaluated before the approval mode; see security.md.
mcpServersMCP servers for the mcp tool (name, transport, command/args/env, url, disabled); see mcp.md.

Source: crates/pi-coding/src/settings.rs:342-416, crates/pi-coding/src/settings.rs:970-1096, and crates/pi-coding/src/settings.rs:1104-1129.

Supported operational settings coverage

The following keys are the supported operational settings coverage used by the runtime. Any other field may exist but is either a startup default, a resource list, or module-specific configuration.

SettingApplied by
approvalModesession_run_blueprint host approval hook
steeringModesteering_mode
followUpModefollow_up_mode
retryretry_settings / apply_session_options
compactionapply_session_options
transportapply_session_options
timeoutMsapply_session_options
maxRetryDelayMsapply_session_options
temperatureapply_session_options
maxTokensapply_session_options
cacheRetentionapply_session_options
thinkingBudgetsapply_session_options
scopedModelsscoped_model_patterns
enabledModelsscoped_model_patterns (legacy alias)
terminaltui_runtime
imagestui_runtime
themetui_runtime / resource validation
keybindingstui_runtime
branchSummarybranch_summary_settings
quietStartuptui_runtime
hideThinkingBlocktui_runtime
showThinkingtui_runtime
exposeSessionEnvironmentexpose_session_environment
doubleEscapeActiontui_runtime
orchestrationorchestration tool gates

Source: crates/pi-coding/src/settings.rs:302-330.

Model and thinking-level precedence

When the CLI starts without an explicit model:

  1. --model / -m flag.
  2. Resumed session's saved model (when --resume or --continue is used).
  3. settings.json defaultModel.
  4. First authenticated model in the catalog.

Thinking level precedence:

  1. --think flag.
  2. Thinking level parsed from a :level model suffix (anthropic/claude-sonnet-4-5:high).
  3. Resumed session's saved thinking level.
  4. settings.json defaultThinkingLevel.
  5. medium.

The final level is clamped to the resolved model's supported levels.

Live reload semantics

Configuration and resources are loaded into an atomic snapshot.

  • rpi reload validates the current settings/resource graph and prints a structured snapshot, including generation, trust, discovered resources, and diagnostics. It always runs headlessly and emits JSON.
  • SettingsManager::reload() re-reads global settings and, when the project is trusted, project settings, then recomputes the effective snapshot.
  • ResourceManager::stage_reload() builds a new candidate snapshot without replacing the active one. commit_reload() swaps the active snapshot only after validation succeeds; any error leaves the previous generation in place.
  • Interactive TUI /reload and REPL reload call the same stage-and-commit path, so malformed files never silently replace a working configuration.
  • Settings writes performed through update_global or update_project are atomic (temp file + fs::rename + directory sync). Session-only overrides via apply_overrides are never persisted.

Source: crates/pi-cli/src/commands.rs:145-180, crates/pi-coding/src/settings.rs:729-843, and crates/pi-coding/src/resource_manager.rs:139-253.

Trust boundaries

  • No project-local configuration is loaded unless the project is trusted. Use -a/--approve or set defaultProjectTrust explicitly.
  • approvalMode is a global safety policy and is rejected in project .pi/settings.json; --approval-mode is the explicit one-run override. It is independent of --approve/--no-approve, which control only project resource trust.
  • Interactive approval runs before the existing host hook and extension reducer. Headless modes fail closed whenever the selected policy requires confirmation.
  • Bash tool commands run in the configured working directory (--cwd).
  • API keys are never printed in error messages or logs.
  • models.json and auth.json values may contain $VAR / ${VAR} templates, which are expanded from the current process environment or an explicit env map. Command-valued values (!command) are rejected.

Custom config path for tests or isolation

export PI_CODING_AGENT_DIR="<workspace>/.my-pi-config"
mkdir -p "$PI_CODING_AGENT_DIR"
rpi --print "hello"