# Session configuration reference

> Agent session config keys, defaults, reload behavior, in-memory settings, and config surfaces used by runtime services.

- Repository: PrimeIntellect-ai/prime-agent
- GitHub: https://github.com/PrimeIntellect-ai/prime-agent
- Human docs: https://grok-wiki.com/public/docs/primeintellect-ai-prime-agent-3367c32760b1
- Complete Markdown: https://grok-wiki.com/public/docs/primeintellect-ai-prime-agent-3367c32760b1/llms-full.txt

## Source Files

- `packages/coding-agent/src/core/agent-session-config.ts`
- `packages/coding-agent/test/agent-session-config.test.ts`
- `packages/coding-agent/examples/sdk/10-settings.ts`
- `packages/coding-agent/src/core/agent-session.ts`
- `packages/coding-agent/test/suite/regressions/3616-settings-inmemory-reload.test.ts`
- `packages/coding-agent/test/suite/regressions/2753-reload-stale-resource-settings.test.ts`

---

---
title: "Session configuration reference"
description: "Agent session config keys, defaults, reload behavior, in-memory settings, and config surfaces used by runtime services."
---

Prime Agent splits session configuration across three surfaces that runtime services combine at create time and again on reload: durable `settings.json` via `SettingsManager`, per-session bootstrap via `AgentSessionRuntimeConfig`, and construction-time `createAgentSession` / `AgentSessionCreationOptions`. Project settings deep-merge over global settings; CLI and SDK options override resolved defaults for a single session without always writing them back to disk.

## Config surfaces

| Surface | Owner type / API | Persistence | Typical producers |
|---------|------------------|-------------|-------------------|
| Durable settings | `Settings` + `SettingsManager` | Global and project `settings.json` (or in-memory storage) | CLI `/settings`, package manager, SDK `SettingsManager.create` / `inMemory` |
| Runtime session config | `AgentSessionRuntimeConfig` | Session bootstrap only; merged with `mergeAgentSessionRuntimeConfig` | CLI args → `runtimeConfigFromArgs`, daemon worker create requests |
| Session construction | `CreateAgentSessionOptions` / `AgentSessionCreationOptions` | Session instance fields | `createAgentSession`, `createAgentSessionFromServices`, RLM subagent spawn |

```mermaid
flowchart TB
  subgraph durable["Durable settings"]
    GS["~/.prime/agent/settings.json"]
    PS[".prime/agent/settings.json"]
    SM["SettingsManager\ndeepMerge global + project"]
    GS --> SM
    PS --> SM
  end

  subgraph bootstrap["Session bootstrap"]
    CLI["CLI args / daemon create"]
    RC["AgentSessionRuntimeConfig"]
    CLI --> RC
  end

  subgraph services["AgentSessionServices"]
    AS["authStorage + modelRegistry"]
    RL["DefaultResourceLoader"]
    MCP["McpManager"]
    SM --> RL
    SM --> MCP
    AS --> MCP
  end

  subgraph session["AgentSession"]
    CA["createAgentSession /\ncreateAgentSessionFromServices"]
    AS2["AgentSession runtime"]
    CA --> AS2
  end

  SM --> CA
  RC --> CA
  RL --> CA
  MCP --> CA
  AS --> CA
  AS2 -->|"reload()"| SM
  AS2 -->|"reload()"| RL
```

## Settings files and merge rules

| Scope | Path | Role |
|-------|------|------|
| Global | `~/.prime/agent/settings.json` (`getAgentDir()` + `settings.json`) | Defaults for all projects |
| Project | `.prime/agent/settings.json` (`CONFIG_DIR_NAME` under cwd) | Overrides for the current project |

Merge behavior (`deepMergeSettings`):

- Project values win over global for the same key.
- Nested objects (for example `compaction`, `retry`, `terminal`) merge field-by-field.
- Arrays and primitives are replaced, not concatenated.
- `undefined` override values are skipped.

Global-only keys read from `globalSettings` (not the merged project overlay):

- `rlmMaxDepth`
- `idleEvictionMinutes` (daemon idle eviction policy)

`sessionDir` precedence when multiple sources set a directory:

1. CLI `--session-dir`
2. `PRIME_AGENT_SESSION_DIR`
3. Legacy `PRIME_AGENT_CODING_AGENT_SESSION_DIR`
4. `sessionDir` in settings

## `Settings` keys and defaults

Defaults below are the values getters apply when a key is omitted. Unset `defaultThinkingLevel` falls through to runtime `DEFAULT_THINKING_LEVEL` (`"medium"`), not a baked-in settings default of `"xhigh"`.

### Model and transport

| Key | Type | Default when unset | Notes |
|-----|------|--------------------|-------|
| `defaultProvider` | string | — | Saved default provider |
| `defaultModel` | string | — | Saved default model id |
| `recentModels` | string[] | `[]` | `"provider/id"`, most recent first, capped at 20 |
| `defaultThinkingLevel` | `"off" \| "minimal" \| "low" \| "medium" \| "high" \| "xhigh" \| "max"` | runtime `"medium"` | Session uses settings value if set |
| `defaultServiceTier` | service tier | `"default"` | Fast/priority tiers when supported |
| `thinkingBudgets` | object | — | Optional per-level token budgets |
| `enabledModels` | string[] | — | Model cycle patterns (same shape as `--models`) |
| `transport` | `"sse" \| "websocket" \| "auto"` | `"auto"` | Legacy `websockets` boolean migrates into this |
| `hideThinkingBlock` | boolean | `false` | UI hide for thinking blocks |

### Compaction, refine, branch summary, retry

| Key | Type | Default when unset |
|-----|------|--------------------|
| `compaction.enabled` | boolean | `true` |
| `compaction.reserveTokens` | number | `16384` |
| `compaction.keepRecentTokens` | number | `20000` |
| `compaction.agentCallable` | boolean | `true` (exposes compact skill) |
| `autoRefine.enabled` | boolean | `true` |
| `autoRefine.turnInterval` | number | `25` (min 1) |
| `autoRefine.compact` | boolean | `true` |
| `autoRefine.cooldownMs` | number | `1200000` (20 minutes) |
| `branchSummary.reserveTokens` | number | `16384` |
| `branchSummary.skipPrompt` | boolean | `false` |
| `retry.enabled` | boolean | `true` |
| `retry.maxRetries` | number | `3` |
| `retry.baseDelayMs` | number | `2000` |
| `retry.provider.timeoutMs` | number | SDK default |
| `retry.provider.maxRetries` | number | SDK default |
| `retry.provider.maxRetryDelayMs` | number | `60000` |

Legacy `retry.maxDelayMs` migrates to `retry.provider.maxRetryDelayMs`.

### Message delivery and daemon

| Key | Type | Default when unset | Notes |
|-----|------|--------------------|-------|
| `steeringMode` | `"all" \| "one-at-a-time"` | `"one-at-a-time"` | Legacy `queueMode` migrates here |
| `followUpMode` | `"all" \| "one-at-a-time"` | `"one-at-a-time"` | |
| `idleEvictionMinutes` | number \| `"off"` | `90` | Global only; `"none"` treated as `"off"` |
| `rlmMaxDepth` | number | env/runtime default | Global only |
| `sessionDir` | string | — | `~` expanded; see precedence above |

### Terminal, images, UI

| Key | Type | Default when unset | Notes |
|-----|------|--------------------|-------|
| `theme` | string | theme system fallback | Often resolved as `"dark"` / `"prime"` in UI |
| `quietStartup` | boolean | `false` | |
| `treeFilterMode` | enum | `"user-only"` | `default`, `no-tools`, `user-only`, `labeled-only`, `all` |
| `editorPaddingX` | number | `0` | Clamped 0–3 on set |
| `autocompleteMaxVisible` | number | `5` | Clamped 3–20 on set |
| `showHardwareCursor` | boolean | `false` unless `PI_HARDWARE_CURSOR=1` | |
| `terminal.showImages` | boolean | `true` | |
| `terminal.clearOnShrink` | boolean | `false` | |
| `terminal.showTerminalProgress` | boolean | `false` | |
| `terminal.fullscreen` | boolean | `true` | Overridden by `PI_FULLSCREEN=0/1` |
| `terminal.fullscreenMouse` | boolean | `true` | |
| `images.autoResize` | boolean | `true` | |
| `images.blockImages` | boolean | `false` | Blocks images to providers |
| `markdown.codeBlockIndent` | string | `"  "` | |
| `warnings.anthropicExtraUsage` | boolean | `true` (when read as warning flag) | |

### Shell, packages, resources, MCP

| Key | Type | Default when unset | Notes |
|-----|------|--------------------|-------|
| `shellPath` | string | — | Custom shell (for example Cygwin) |
| `shellCommandPrefix` | string | — | Prepended to every bash command |
| `npmCommand` | string[] | — | Argv for npm package operations |
| `packages` | `PackageSource[]` | `[]` | String or filtered object form |
| `extensions` | string[] | `[]` | Local paths; supports globs / `+` / `-` / `!` |
| `skills` | string[] | `[]` | Same path pattern rules |
| `prompts` | string[] | `[]` | Prompt templates |
| `themes` | string[] | `[]` | Theme paths |
| `enableSkillCommands` | boolean | `true` | `/skill:name` registration |
| `enableBuiltinSkills` | boolean | `true` | Built-in skill load |
| `bundledSkills.websearch` | boolean | `true` | Built-in websearch skill |
| `mcpServers` | record | — | User-declared HTTP/stdio MCP servers |
| `agentTraces.enabled` | boolean | `false` | |
| `onboardingShown` / `onboardingCompleted` | boolean | — | Onboarding completion flags |

Paths in global settings resolve relative to `~/.prime/agent`. Paths in project settings resolve relative to `.prime/agent`. Absolute paths and `~` are supported.

### Example `settings.json`

```json
{
  "defaultProvider": "anthropic",
  "defaultModel": "claude-sonnet-4-20250514",
  "defaultThinkingLevel": "high",
  "transport": "auto",
  "compaction": {
    "enabled": true,
    "reserveTokens": 16384,
    "keepRecentTokens": 20000,
    "agentCallable": true
  },
  "autoRefine": {
    "enabled": true,
    "turnInterval": 25,
    "cooldownMs": 1200000
  },
  "retry": {
    "enabled": true,
    "maxRetries": 3,
    "baseDelayMs": 2000,
    "provider": { "maxRetryDelayMs": 60000 }
  },
  "enabledModels": ["claude-*", "gpt-4o"],
  "packages": ["pi-skills"]
}
```

## `SettingsManager` API

<ParamField body="SettingsManager.create" type="(cwd, agentDir?) => SettingsManager">
Loads global and project settings from files under `agentDir` and `cwd`. Default `agentDir` is `getAgentDir()` (`~/.prime/agent`).
</ParamField>

<ParamField body="SettingsManager.inMemory" type="(settings?: Partial<Settings>) => SettingsManager">
No file I/O. Seeds global storage with the provided settings after migration. Used by tests and headless SDK runs.
</ParamField>

<ParamField body="SettingsManager.fromStorage" type="(storage: SettingsStorage) => SettingsManager">
Custom backend implementing lock-scoped read/write of JSON text for `"global"` and `"project"`.
</ParamField>

| Method | Behavior |
|--------|----------|
| `getGlobalSettings()` / `getProjectSettings()` | Structured clones of scoped objects |
| `applyOverrides(partial)` | Deep-merges into the **in-memory merged** view only; does not mark fields modified or write storage |
| `reload()` | Awaits write queue, reloads both scopes from storage, clears modified-field tracking, recomputes merge |
| `flush()` | Awaits queued persistence writes |
| `drainErrors(scope?)` | Returns and clears recorded load/save errors (`global` / `project`) |
| Typed getters/setters | Most setters update **global** settings, mark modified keys (including nested keys), and enqueue a locked merge-write |

Persistence rules:

- Setters queue writes; call `flush()` at durability boundaries.
- Writes only include fields marked modified in that session; concurrent external edits to other keys are preserved via lock + merge.
- If a scope failed to parse on load, subsequent saves for that scope are blocked and recorded as errors instead of overwriting a corrupt file.
- Project resource path setters (`setProjectPackages`, `setProjectExtensionPaths`, …) write the project file; global counterparts write the agent-dir file.

### In-memory settings and reload

`SettingsManager.inMemory` stores the initial snapshot in memory-backed global storage. Direct `reload()` and `DefaultResourceLoader.reload()` re-read that storage, so the initial keys survive reload. Setters (for example `setTheme`) update storage; after `flush()` + `reload()`, both the new and original keys remain. `applyOverrides` alone does **not** write storage and is dropped on reload.

```ts
import { createAgentSession, SessionManager, SettingsManager } from "@earendil-works/pi-coding-agent";

const settingsManager = SettingsManager.create(process.cwd());
settingsManager.applyOverrides({
  compaction: { enabled: false },
  retry: { enabled: true, maxRetries: 5, baseDelayMs: 1000 },
});

await createAgentSession({
  settingsManager,
  sessionManager: SessionManager.inMemory(),
});

settingsManager.setDefaultThinkingLevel("low");
await settingsManager.flush();

for (const { scope, error } of settingsManager.drainErrors()) {
  console.warn(`Warning (${scope} settings): ${error.message}`);
}

// Tests without disk:
const inMemorySettings = SettingsManager.inMemory({
  compaction: { enabled: false },
  retry: { enabled: false },
});
```

## `AgentSessionRuntimeConfig`

Runtime bootstrap for a session (CLI, daemon create, worker rehydrate). Merge with `mergeAgentSessionRuntimeConfig(base, override)`: override wins per field when defined; arrays are cloned; `extensionFlagValues` shallow-merges; `autonomous` deep-merges including gate `commands`.

| Field | Type | Role |
|-------|------|------|
| `cwd` | string | Effective working directory |
| `agentDir` | string | Global agent config directory |
| `sessionDir` | string | Session storage directory override |
| `provider` / `model` / `apiKey` | string | Model selection / one-shot API key |
| `systemPrompt` | string | Replace system prompt |
| `appendSystemPrompt` | string[] | Append prompt segments |
| `thinking` | `ThinkingLevel` | Initial thinking level |
| `models` | string[] | Scoped cycle models (else settings `enabledModels`) |
| `tools` | string[] | Tool allowlist |
| `noTools` / `noBuiltinTools` | boolean | Suppress all / built-in tools |
| `extensions` / `skills` / `promptTemplates` / `themes` | string[] | Extra resource paths (CLI paths resolved absolute at parse time) |
| `noExtensions` / `noSkills` / `noPromptTemplates` / `noThemes` / `noContextFiles` | boolean | Disable discovery classes |
| `autonomous` | `AgentAutonomousConfig` | Host autonomous continuation policy |
| `extensionFlagValues` | record | Extension CLI flags |
| `serializedRefine` | boolean | Sync refine between turns (print/json/rpc → daemon worker) |
| `initialGoal` | `{ objective; tokenBudget? }` | Seed top-level goal (rlmDepth 0 only; ignored if goal already persisted) |

CLI mapping (`runtimeConfigFromArgs`): non-interactive modes set `serializedRefine: true` for print/json/rpc; interactive and daemon app modes do not. Daemon server default config strips `initialGoal` so only explicit create requests seed goals.

### Autonomous defaults

| Field | Default |
|-------|---------|
| `enabled` | only when explicitly `true` |
| `maxContinuations` | `3` |
| `maxTurns` | `12` |
| `maxTokens` | `80000` |
| `timeoutMs` | `30 * 60 * 1000` |
| `gates.commands` | `[]` |
| `gates.maxRetries` | `3` |
| `gates.timeoutMs` | `5 * 60 * 1000` |
| `continuationPrompt` | built-in autonomous continuation text |

Subagent sessions (`rlmDepth > 0`) force autonomous `enabled: false` when resolving runtime session options, while still merging other autonomous fields.

## Services vs session construction

`createAgentSessionServices` builds cwd-bound infrastructure:

- `SettingsManager` (file or injected)
- `AuthStorage` / `ModelRegistry`
- `DefaultResourceLoader` (reads settings for packages, paths, built-in skill gates)
- `McpManager` (`getUserServers` ← `settingsManager.getMcpServers()`)
- Diagnostics for extension provider registration and unknown flags

`createAgentSession` / `createAgentSessionFromServices` then construct `AgentSession` with model, thinking, tools, autonomous, serialized refine, initial goal, and RLM metadata. Default thinking when neither option nor settings provide a level: `DEFAULT_THINKING_LEVEL` (`"medium"`), clamped to model capabilities.

| `CreateAgentSessionOptions` field | Default |
|-----------------------------------|---------|
| `cwd` | `process.cwd()` or session manager cwd |
| `agentDir` | `getAgentDir()` |
| `settingsManager` | `SettingsManager.create(cwd, agentDir)` |
| `sessionManager` | `SessionManager.create(cwd, …)` |
| `model` | settings default, else first available |
| `thinkingLevel` | settings, else `"medium"` |
| `tools` / `noTools` | built-in ipython + extension tools unless suppressed |
| `autonomous` / `serializedRefine` / `initialGoal` | optional host policy |

## Session `reload()` behavior

`AgentSession.reload()`:

1. Emits `session_shutdown` with reason `"reload"`.
2. `settingsManager.reload()` — re-reads global/project storage; **in-memory-only `applyOverrides` are discarded**.
3. Reloads `auth.json` so daemon client logins become visible.
4. Resets API providers; refreshes MCP user servers from reloaded settings.
5. `resourceLoader.reload()` — reapplies settings resource lists (packages, prompts, skills, extensions, themes).
6. Rebuilds runtime tools/extensions; may emit `session_start` reason `"reload"` and re-extend resources.

Regression coverage:

- Changing global `settings.json` `prompts` after startup, then `session.reload()`, updates both `settingsManager.getGlobalSettings().prompts` and the session’s loaded prompt templates (stale resource lists are not kept).
- In-memory settings keep their initial values across `reload()` and resource-loader reload.

Extension contexts captured before reload are stale: do not reuse a pre-reload `pi`/command `ctx` after `await ctx.reload()`.

## Config consumption map

| Runtime concern | Settings / config source |
|-----------------|--------------------------|
| Default model / thinking / service tier | `defaultProvider`, `defaultModel`, `defaultThinkingLevel`, `defaultServiceTier` |
| Compaction | `compaction.*` via `getCompactionSettings()` |
| Auto-refine cadence | `autoRefine.*` via `getAutoRefineSettings()` |
| Agent-level retry | `retry.*` / `getRetrySettings()` / `getProviderRetrySettings()` |
| Steering / follow-up queues | `steeringMode`, `followUpMode` |
| Transport + thinking budgets | `transport`, `thinkingBudgets` |
| Resource discovery | `packages`, `extensions`, `skills`, `prompts`, `themes`, enable flags |
| MCP | `mcpServers` |
| Shell tool | `shellPath`, `shellCommandPrefix` |
| Image pipeline | `images.*` |
| Daemon idle policy | `idleEvictionMinutes` (global) |
| RLM depth default | `rlmMaxDepth` (global) + env |
| Autonomous host policy | `AgentSessionRuntimeConfig.autonomous` / session options |
| Serialized refine / initial goal | runtime config → session construction |

## Troubleshooting

| Symptom | Likely cause | Check |
|---------|--------------|-------|
| Setting change ignored after edit | Edited project vs global scope, or nested merge left other fields | Inspect both `settings.json` files; call `session.reload()` or restart |
| Override lost after reload | Used `applyOverrides` without setters/storage write | Prefer setters + `flush()`, or re-apply after reload |
| Corrupt settings not updating | Parse error blocked saves | `drainErrors()`; fix JSON, then reload |
| Prompt/skill list stale | Resource settings updated on disk but session not reloaded | `await runtime.session.reload()` |
| Daemon idle eviction wrong | Set only in project settings | Set `idleEvictionMinutes` in global `~/.prime/agent/settings.json` |
| Thinking not `"xhigh"` | Unset settings use runtime default `"medium"` | Set `defaultThinkingLevel` explicitly |
| Transport not SSE | Default is `"auto"` | Set `transport` explicitly |
| In-memory test “forgets” keys | Relied on `applyOverrides` only | Seed `SettingsManager.inMemory({...})` or use setters |

## Related pages

<CardGroup>
  <Card title="Sessions and runtime" href="/sessions-runtime">
    Session lifecycle, services, events, and session-scoped vs durable state.
  </Card>
  <Card title="Settings and provider keys" href="/settings-providers">
    Provider registration, model selection, API keys, OAuth, and 401 recovery.
  </Card>
  <Card title="Sessions and full control" href="/sdk-sessions-control">
    SDK session management, settings injection, and full-control composition.
  </Card>
  <Card title="Long-running tasks" href="/long-running-tasks">
    Goals, compaction, heartbeats, autonomous mode, and retained subagents.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    Auth failures, resume selectors, provider 401s, and connection probes.
  </Card>
</CardGroup>
