# Setup

Use Pi 0.99.1 or newer and Node.js 22.19.0 or newer. Development dependencies and CI use Pi 1.2.0. Upgrade Pi before installing this OpenPI version. Install the public Pi package:

```sh
pi install npm:@tt-a1i/openpi
```

To inspect the current source before loading it, install directly from GitHub instead:

```sh
pi install git:github.com/openpi-dev/openpi
```

Pi installs the package dependencies automatically. Restart Pi or run `/reload` after installation.

## Optional web search

The repository-owned `extensions/web-search/` Pi extension is off by default. **Settings → Web search** or `/openpi-setup enable web search` sets `web_search_enabled`. Search defaults to the current Session model and reuses Pi's actual protocol, connection, and credentials. It is a provider-hosted tool in the same model request, without a second model/provider stack, independent summary request, external search key, or OpenPI capability group. The model decides when to search. No provider, protocol, or model fallback is performed.

OpenAI Responses/Codex Responses and Anthropic Messages are implemented. Known official endpoint/model combinations are eligible; unsupported protocols and unknown gateways receive no native search tool. A custom connection requires an explicit `web_search_model_support` declaration after verified native execution or the user's explicit capability confirmation: true enables support, false denies support, and null restores automatic detection. The declaration is bound to the exact current provider, model, API, and base URL. API compatibility, a familiar model name, and DeepSeek's consumer website search do not establish hosted-search support. Existing subscription credentials do not establish Anthropic API search entitlement.

Pi owns cancellation, transport, usage, persistence, forks, and compaction. Native output and exact search terminal evidence are retained on the assistant message; citations become clickable links. Only retained messages from the identical connection replay native blocks, including after the feature is disabled. Web projection exposes bounded search activity rather than opaque provider output. Direct/Workflow children exclude the extension, so hosted tools cannot bypass their tool allowlists. Native output and aggregate replay are bounded to 256 KiB; an oversized history requires Session compaction. Anthropic `pause_turn` is an explicit error: automatic protocol continuation is not implemented by this adapter. No webpage cache or stored-content paging system is added.

The legacy `web_access_action` remains for explicit management of an already selected optional Pi package, including native reviewed confirmation and an explicit later reload. It is never a fallback from current-model search. Previously installed external search extensions must be disabled separately to avoid conflicting search tools.

## Response preferences and visible reasoning levels

Settings → Configuration submits response preferences through the existing `/openpi-setup` episode. `response_verbosity` accepts `default`, `low`, `medium`, or `high`; `response_reasoning_summary` accepts `default`, `auto`, `concise`, `detailed`, or `none`. Both default to `default`, which leaves Pi's native request unchanged. Overrides apply only to the parent Session's current model using OpenAI Responses or Codex Responses. Child Sessions retain their native Pi request parameters. A reasoning-summary override additionally requires native reasoning support and existing reasoning parameters. `none` removes only the summary request, preserving effort and other reasoning fields. Other APIs remain unchanged. A compatible API does not establish every model's acceptance of these optional values.

The visible reasoning-level controls are presentation preferences and save directly without a model turn. `web_hidden_thinking_levels` stores a unique list drawn from `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`; the default `[]` hides none. The picker filters Pi's native available levels while retaining the current selection. It does not add model support or change the Session's native thinking level. Both entry points use the same validated configuration and persistence lifecycle.

## Read-only git tools

`git-read` registers `git_show`, `git_diff`, and `git_log` (read-only git inspection) as model tools. They are a plan-mode boundary: visible only while `/plan` is armed or restored for that Session, and removed when planning ends. Children receive these tools only when they are active in the parent and permitted by their role allowlist. Ordinary file and content search uses Pi's native `grep`/`find` tools or `rg`/`fd` shell commands. The git tools require a system `git`.

While Plan Mode is active, raw Bash `git diff`, `git show`, and `git whatchanged` are refused, as are diff-generating `git log` options such as `-p`, `--stat`, `--name-only`, and `-L`. Use `git_log` to find commits and `git_diff` / `git_show` to inspect changes; the latter commands always pass `--no-ext-diff --no-textconv --no-color`, so repository-configured `diff.external` and textconv drivers are not executed. This guarantee is scoped to the Git diff-driver boundary rather than every possible hostile Git configuration; the remaining allowlisted Git investigation commands still run inside Pi's existing project Trust boundary.

## Theme

Add the included theme to `~/.pi/agent/settings.json` while keeping your existing settings:

```json
{
  "theme": "github-dark-default"
}
```

Pi will load the extensions and theme the next time it starts. OpenPI's Subagent and Workflow Skill files remain in the package, and the model reads them through Pi's native skill mechanism when needed; ordinary turns do not inline them in the system prompt.

The terminal theme above remains Pi-owned. OpenPI Web has separate package-owned appearance preferences: `system`, `light`, and `dark` modes; chat width from 820-2000px; chat font size from 12-24px; and whether thinking blocks start expanded. `system`, 820px, 14px, and collapsed are the defaults. The complete `ui.webAppearance` object defaults to `{ "palette": "default", "accent": "", "background": "", "foreground": "", "font": "codex" }`. Palettes are `default`, `mist`, `rose`, and `pine`; fonts are `codex` (Codex default), `sans`, `serif`, and `mono`. Legacy `system` maps to `codex` when reading configuration or importing a theme. The default stack is `-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`: SF Pro with PingFang on macOS, Segoe UI first on Windows, and the platform sans-serif fallback elsewhere. No proprietary font files are bundled. Each color must be empty (use the theme default) or `#RRGGBB`. The object is replaced as a whole, with every field required and unknown fields rejected. The legacy `ui.webTheme` values `mist`, `rose`, and `pine` remain valid and take precedence as old presets; replace them by saving a new mode together with the appearance object. Web controls save these presentation values directly through the shared validated configuration writer and apply the saved response without a model turn or chat message. They remain available during running turns and Plan mode. `/openpi-setup` can also change the same values through `ui_web_appearance`; its no-argument status reports the palette, theme-default or custom colors, and font. Both paths share `my-pi-setup.json`, locking, validation, unknown-field preservation, and atomic persistence.

The optional [OpenPI Browser Bridge](web/browser-extension/README.md) 0.4.0 supports Chrome, Edge, Brave and Chromium 145+ plus native tabs in macOS Safari 26+ and Firefox 128+. The Browser settings page guides one step at a time in a separate window: open the browser's settings, locate the illustrated control, select the bundled extension, then connect. Document Picture-in-Picture keeps the guide floating where supported; otherwise it uses a normal popup, with an inline fallback if blocked. Safari uses Add Temporary Extension in Developer settings; Firefox uses Load Temporary Add-on on about:debugging and selects manifest.json. These temporary installations must be reloaded after browser restart; permanent distribution needs signed packages. Chromium uses Developer mode and Load unpacked. The actual browser must confirm installation and site access. Only a matching live handshake reports Connected; advancing a step never grants control. Embedded control and navigation enhancement require Chromium. Safari/Firefox expose DOM semantics and screenshots of native tabs; nested frames must be opened separately.

Exit Plan mode before starting `/openpi-setup`, including from Web settings. The command checks the current Session branch before starting a setup turn, and queued requests are checked again before delivery. Web disables package configuration controls during planning and offers the existing Plan exit action once the Session is idle; exiting does not start a model turn or authorize implementation. Settings reports the latest setup episode from persisted tool receipts, including unchanged saves, failures, cancellation, and an unconfirmed save. A completed turn or an assistant's claim alone is not proof that configuration was saved.

## Configure this package

Web appearance controls directly save only their presentation fields; their success status is based on the completed write. Other package-owned settings forms submit requests through `/openpi-setup`. Role/model choices, concurrency, skill and plugin configuration requests remain visible in that episode, including required confirmation and its final apply/closure receipt. A setup submission message is not proof of persistence. Pi-owned model definitions and credentials have separate direct forms backed by Pi's `models.json` and native login API; secrets never enter the setup prompt.

The Web model page offers Account, Third-party providers, and Custom model API when adding a connection. Account choices come from Pi's registered OAuth providers. Browser, device-code, and manual callback interactions are shown only when requested by that native provider. Only the idle active Session may start sign-in; settings navigation stays locked until the native flow settles, including after cancellation. Existing accounts support reauthentication and confirmed sign-out. Pi owns the shared credential store; signing out also affects other Sessions using that credential. A configured credential does not prove endpoint availability. Credential persistence and model-list refresh are reported separately if the latter fails. These controls introduce no OpenPI preference or second account store.

After saving a connection, choose a model for the current Session and optionally make it the default for new Sessions. The separate New-session default row reads and writes Pi's global `settings.json` through its native SettingsManager, confirming persistence before displaying success. Changing only this default leaves existing Sessions unchanged; trusted project model overrides are displayed separately. Current-Session selection uses Pi's Session model and exact provider/model identity, so identical model names on different connections remain distinct. Provider marks use restrained brand accents. Pi keeps one credential per provider ID; reauthentication replaces it, while distinct custom connections use distinct IDs.

Web shows the original setup command and its results, including failed or unapplied requests, rather than hiding the configuration episode. Appearance controls wait for the current run to settle before accepting another change. Chat-width and font-size reset buttons request the existing defaults through the same setup entry point. The model tree selects the editable Pi definition and retains unsaved drafts within the same Session; narrow screens use a labeled settings-section selector.

In the TUI, setup requests default to `[OpenPi] <command>` and the original user request (including the `my-pi-setup` alias); long or multiline requests wrap naturally. Pi's `app.tools.expand` action (`Ctrl+O` by default) shows the complete original prompt through native rendering. Expansion is host-owned: hosts without a custom-message disclosure-click API do not offer a click toggle. Legacy or invalid command/request metadata falls back to Pi's full native display. This is presentation only: Session content, model input, setup authority, and receipts are unchanged. Web keeps its existing command/request projection; RPC/JSON and HTML exports retain the full prompt rather than the TUI summary. See [Issue #654](https://github.com/openpi-dev/openpi/issues/654).

Each delivered setup request explicitly announces its new episode. Success and closure messages apply only to their completed episode; a later `/openpi-setup` request can activate the writer again without reusing the prior episode's authority.
The `compact` footer preset resolves to `plain` style with the default single-row layout; it is not a separate stored style. Applying it to the default footer does not change its appearance. Successful setup receipts distinguish saving the document from changing effective settings and list only fields that actually changed. Keeping defaults without invoking the writer does not create a file.

Explicit field assignments retain their meaning: `footerStyle="compact"` is invalid; the allowed styles are `plain`, `powerline`, and `powerline-mono`. Setup should explain the legal choices and wait for a valid choice instead of silently applying a preset or default. Requesting the `compact` preset is valid and resets both style and layout. Tool writes reject invalid footer styles and presets; stored invalid styles block writes rather than being repaired automatically.

The personal `my-pi-setup.json` document uses `configVersion: 1`. A missing file uses built-in defaults without creating a file. Unversioned documents migrate only on an explicit save. Malformed JSON, read errors, unsupported versions, and invalid known fields block writes and are reported by `/openpi-setup`; rendering uses safe defaults while the file remains intact. Repair the file, or explicitly remove it to reset. Unknown fields are warned about and preserved; changes that would remove unknown fields are rejected. Diagnostics show field paths, not raw values or post-edit command contents.

On Session start or extension reload with a UI available, OpenPI issues one brief notification if configuration loading has errors or warnings, directing the user to `/openpi-setup` for full diagnostics. Errors explicitly report the safe-default fallback and blocked writes; legacy documents and unknown fields produce a warning. Missing or valid current-version files stay quiet. This check does not start a model turn, expose the writer, or modify the file. Non-UI callers can obtain diagnostics through the existing setup command.

Setup saves under the existing cross-process lock and waits for current-session configuration consumers to apply. An apply failure restores the previous document and reapplies its configuration, provided the file still matches this write. Concurrent external changes are preserved; an incomplete recovery is reported as an error. This is not an atomic update of all running Pi processes or a crash-recovery journal. No additional setup command, preview UI, or statusline package is required.

Use the single canonical package-owned command. `/my-pi-setup` remains a compatibility alias. With no arguments, the current model explains the configurable areas and uses `ask_user`: first run initializes them; later runs explain the saved state and ask whether to keep it, change one area, or review everything. With arguments, it treats the rest as a targeted natural-language request. Persist still goes through the typed `configure_my_pi_setup` tool. The writer stays hidden while a busy Session queues the setup request, becomes active only when that exact request is delivered to the model, and is hidden again afterward. One successful apply completes the episode. If the run settles without a successful apply, OpenPI appends a visible, durable closure receipt to the Session and later model context; it says that the writer is hidden and re-entry requires `/openpi-setup <request>`. OpenPI also verifies that the active writer belongs to the package source before announcing an active setup episode; duplicate or mismatched sources fail closed without injecting the setup request. A later configuration change starts a new episode with `/openpi-setup <request>` rather than reusing the hidden tool:

```text
/openpi-setup
/openpi-setup 开启下一步预测，使用 seal/deepseek-v4-flash，关闭推理
/openpi-setup 关闭下一步预测
/openpi-setup workflow 同时跑 16 个 agent，总任务最多 256 个
/openpi-setup 当前 Pi Session 的 Workflow、Direct 和 BTW 最多同时运行 6 个 child
/openpi-setup Web theme follows the system
/openpi-setup use dark theme in OpenPI Web
/openpi-setup use the mist theme with 960px chat width
/openpi-setup use 16px chat text and expand thinking by default
/openpi-setup 显示大标题
/openpi-setup 切换 Footer 为 powerline
/openpi-setup 用 mono powerline Footer
/openpi-setup Footer 用 compact
/openpi-setup Footer 两行：cwd flex model / context cost flex git
/openpi-setup Footer 只显示 model、thinking、context、cache 和 git
/openpi-setup 关闭自定义状态栏
/openpi-setup 编辑后自动跑 npm run format
/openpi-setup 关闭 post-edit 命令
/openpi-setup 给 explorer 指定当前 Registry 中可用的模型
/openpi-setup 清除 explorer 的模型，让它继承父模型
```

OpenPI ships one fixed, resident model tool set: Subagent and Workflow tools are active from the start of every Session and do not change with model actions or runtime state. Only explicit user boundaries alter the model-visible list: `/plan` adds the read-only git tools, `plan_ready`, `ask_user`, and `human_handoff`; an `/openpi-setup` episode adds `configure_my_pi_setup`, `ask_user`, and `human_handoff`; browser control follows the saved setup permission. Next-action suggestions default to off. Run `/openpi-setup` to explicitly choose an available model and reasoning level. After a fully settled main-agent run, one suggestion may appear as dim inline text on the first row of an empty editor; reserved cells at the row end keep CJK IME preedit from overwriting it. `Right` accepts it into the editor without submitting, while any other editor input dismisses it. Suggestions are ephemeral and never enter session history or model context. Workflows default to 8 concurrent agents and 128 total agent calls per run; configurable hard maxima are 64 and 1024. A separate `child_execution_limit` is off by default. When explicitly set to 1-64, it is a FIFO cap on active child executions shared only by Workflow, Direct Subagent, and BTW within one top-level Pi Session; their existing Workflow 8/local call limits, Direct pool 4, and BTW pool 2 remain in force. A dormant child, parent Session, model request, token, cost, and provider quota do not consume this limit. `/subagents` shows the shared limit, held/queued counts, origin counts, and generic blocking reason without exposing task text. Reducing the configured limit below live held slots is rejected and rolled back; cancellation and shutdown reject queued attempts but do not claim an active child has stopped before its actual terminal lifecycle settles. The large decorative header defaults off and the custom dashboard footer defaults on with a one-line plain layout (`model context |flex| git pr cwd`; `thinking`, `cache`, `cost`, and `throughput` remain opt-in metrics). Footer presets are `powerline`, `powerline-mono`, and `compact`; style can also be set independently to `plain`, `powerline`, or `powerline-mono`. Custom layouts use a 2D `footerLines` array with at most one `flex` per row for left/right alignment. Nerd Font affects powerline separator glyphs (``) and adds Codex-style outline icons to compact read, terminal, edit, search, and directory activity rows; all accompanying text remains readable without it. Footer metrics use one Codicon outline family (`` model, `` context, and `` directory) plus `⎇` for the branch. A Nerd Font containing Codicons renders them as designed; without one, the text labels remain readable even if an icon falls back to an empty box. Footer changes apply immediately in the active TUI session. Subagent results default to a compact status summary; full mode remains available as a per-user setting, and `app.tools.expand` (`Ctrl+O` by default) reveals the available child report. Ordinary `read`, `grep`, `find`, and `ls` operations render as one-line semantic activity summaries. Bash and Write/Edit default to the same activity-row projection, showing the target, running/success/failure state, and useful line or diff counts without replaying stdout or previews. Select full independently for Bash or Write/Edit to keep Pi's native rendering expanded. `app.tools.expand` temporarily restores the native arguments, output, errors, diff, timing, images, truncation notices, and full-output metadata; it never changes Session history or model context. An optional post-edit command is off by default: set one (for example `npm run format`, maximum 500 characters) and it runs once in the background after each interactive-TUI turn with successful Write/Edit operations, with failures reported as a notification. It deliberately does not guess whether arbitrary Bash commands changed files. Built-in Agent roles `explorer`, `implementer`, `reviewer`, and `advisor` are shared by `subagent_spawn.agent_type` and Workflow `agent(..., { agent_type })`; all inherit the parent model and currently active child-eligible tools by default. Explicit custom role `tools` lists narrow that surface; omitted lists inherit it. Built-in investigator roles suggest read-only work but do not impose a read-only tool boundary outside Plan Mode. Existing role files are preserved, so an old global `explorer.md` allowlist continues to exclude Bash/network tools until deliberately edited. `/openpi-setup` may assign a currently available Registry model to any subset; clearing one returns it to inheritance and omitted roles stay unchanged. Model precedence is explicit call > selected role-file model > setup assignment > parent inheritance; effort is explicit call > selected role > parent. A trusted project `.pi/agents/<role>.md` overrides global `~/.pi/agent/agents/<role>.md`, which overrides the complete built-in role definition. Normal overrides appear as an informational `Agent roles` summary with aligned role names and home-relative source paths; only the effective definitions are shown. Invalid files, unavailable tools, and blocked fallbacks remain separate warnings, with their source and diagnostic detail. Role-model changes apply to the next spawn or Workflow agent call without reload. Configuration is stored privately at `~/.pi/agent/my-pi-setup.json`.

OpenPI Web appearance defaults to `system` mode, the `default` palette, theme-default colors, the `codex` font (Codex default), 820px chat width, 14px chat font size, and collapsed thinking blocks. Mode and the complete `ui.webAppearance` object use the contract described above, including compatibility with legacy `mist`, `rose`, and `pine` theme presets. The browser consumes every appearance value from each authoritative snapshot without writing a competing local preference.

Web General settings directly save the existing `ui.subagentResultDisplay`, `ui.bashToolDisplay`, and `ui.fileMutationDisplay` choices (`compact` by default, or `full`) through the shared appearance writer. They control the corresponding tool disclosures. Consecutive reasoning, tools and activities form one group in native order; assistant prose and other messages separate phases. A single activity appears directly. Activity groups open while running and collapse to an icon, action summary and counts when the run settles, independently of inner detail preferences. A completed timed turn starts with its elapsed-time disclosure collapsed, hiding intermediate updates, reasoning and tools together while leaving the final answer visible below. During execution this process starts expanded. Reasoning stays at its chronological position, has its own single-line preview and expands to Markdown. Footer controls save `ui.customFooter` / `ui.footerStyle` for the Pi terminal footer. Workflow limits, suggestions, and post-edit controls submit natural-language requests through the canonical `/openpi-setup` episode; only a native configuration receipt confirms a change.

A running group's folded summary shows its actual current activity: the tool's icon and target, or the current reasoning preview. Reasoning, tool and other activity counts appear with the disclosure arrow on hover or keyboard focus; touch devices always retain these affordances. Thinking bodies default to collapsed and their arrows follow the same rule. A fine line connects consecutive tools after thinking within the same native assistant message; prose and message boundaries break the line, without inferring cross-message causality. Its expanded list is capped at 360px or half the viewport height and scrolls internally; new activity follows the bottom only while the reader stays there. Upward reading pauses following until a deliberate return to the bottom or the latest-content control. Only current activity uses a slow, intermittent text shimmer; an expanded group title stays still, and reduced motion disables the effect. Expanded thinking retains all available text; oversized saved thinking loads by exact native message and part identity, with explicit further pages. Context compaction states remain native Pi facts. These are presentation behaviors, not additional configuration choices.

Current-turn steering shares the elapsed-time disclosure of the exact native initial input. Folding preserves user inputs and the exact native final answer; expanding preserves their chronological positions. Legacy records without that input identity retain their existing boundaries. Text, tools and the elapsed separator share the conversation width; tools and thinking follow the conversation font size. When reading above the bottom, a centered button above the composer returns to the latest content. It shows three animated dots during execution and a down arrow afterward, respecting reduced motion. The redundant generic running line is hidden visually.

Thinking rows use the same outline Lightbulb mark in Chat and Trajectory. Trajectory groups saved records by native user messages, folds contiguous Session changes and searches already loaded messages, returned reasoning, tool arguments and results without merging their original groups. Tool details provide Overview / Input / Result tabs with keyboard navigation; ordinary messages show their content directly. Record IDs and timestamps remain available under Record information. The list and inspector stack when the conversation panel is narrow, including beside other workbench panes. These are display changes with no additional preference, history scan, model request or execution timer; missing or ambiguous receipts remain unknown. See the [trajectory evidence boundary](docs/research/WEB_TRAJECTORY_2026-09-07.md).

Returning to a saved reading position reveals only the disclosure path to its native row and restores conversation and bounded-group offsets. A bookmarked collapsed summary stays collapsed. Keyboard latest navigation retains conversation focus, and narrow large-text file rows can stack the action and filename while retaining diff counts. Observation loss freezes cached running indicators as unconfirmed; native success, failure and stop receipts remain unchanged. These behaviors use existing reading and appearance owners without another preference or Session store.

Direct Web footer saves update the configuration for Pi's command-line interface. A separate already-running Pi interface refreshes its footer at the next session start or native setup apply; a Web settings event does not itself reconfigure another live Pi session.

Web Skills and Plugins use the same settings shell, search and scope filters. Add, update, remove, invocation and bulk actions submit reviewed natural-language requests through `/openpi-setup`; Pi owns installation, discovery, trust and persistence. Resource-only requests must preserve unrelated OpenPI preferences and do not need the OpenPI preference writer. Installed and configured package versions and disabled/missing entries are projected from native settings without executing resources. The skills.sh link opens an external directory; browsing does not install anything.

Refreshing reads the catalog; explicitly confirmed resource reload calls native Pi reload only for the idle active Session with the matching file identity. Resolve missing or version-mismatched packages through setup first. Configuration persistence and Session loading are separate facts, and changes never trigger automatic reload.

On Windows, OpenPI enables Pi's `clearOnShrink` compatibility behavior for
the regular TUI so shrinking slash-command autocomplete lists do not leave
stale rows on screen. Fullscreen TUI keeps its configured behavior. The
native `PI_CLEAR_ON_SHRINK=0` setting remains an explicit opt-out.

Legacy `footerItems` is accepted and migrated at the input boundary, but new setup writes persist only canonical `footerLines`. Configurations written by this version are not guaranteed to retain their Footer layout when read by an older OpenPI version.

Web projects and conversations share a collapsible pinned section, with up to 100 items in one manual order. Project and conversation menus support pin/unpin; conversations also retain their row pin. Manual order supports dragging across both item types and Move up / Move down. The section menu saves `ui.webPinnedSort`: `manual` (default) or `updated` (recently updated), through the same validated writer as appearance preferences. `/openpi-setup` can change the same choice. Pins and their order are stored in the Web session directory’s workspace metadata. Archive hides conversation pins; restoring reveals their saved positions.

Web sidebar grouping uses `ui.webSidebarGrouping`: `project` (default) or `list`. The conversation order shared by project groups and the recent list uses `ui.webChatsSort`: `updated` (default) or `manual`. `ui.webProjectsInRecents` defaults to `true`, including conversations from unpinned projects in the recent list; turning it off shows ungrouped conversations there. These presentation preferences save directly from the sidebar or through `/openpi-setup`. Imported empty projects, exact Session order and reading state share the existing atomic workspace metadata. Reading state synchronizes between browser tabs on the same Host and survives restarts. Both read and unread edits require the revision actually seen; a late edit cannot overwrite a newer result or another window's mark. The first unread result is recovered from Pi's native branch order, so a later running, cancelled or uncertain turn cannot clear it. These projections use existing native receipts without another execution log, wall-clock ordering or treating an unknown runtime as idle.

Code Mode defaults to disabled (`codeMode.enabled: false`) in ordinary CLI and Web parent Sessions. With `codeMode.enabled: true`, OpenPI activates Pi's registered native `codemode` alongside ordinary tools; the model chooses when to compose calls. `/openpi-setup` changes this default through `code_mode_enabled`, applies it to the current Session, and displays it in the no-argument status. Existing native `defaultTools` selections and CLI/SDK tool restrictions take precedence: a native `+codemode` selection remains active even when the package default is off. Activation does not overwrite native settings, load a missing/disabled built-in extension, or make a model request. Children retain their existing inherited tool restrictions. Web's separate agent directory has its own configuration; changing the CLI preference does not change Web's preference.
Web sidebar width defaults to 340px (220–520px remains valid to preserve existing narrow preferences); tool pane width defaults to 520px (360–720px). Dragging or keyboard resizing saves `ui.webSidebarWidth` / `ui.webAuxiliaryWidth` through the shared appearance writer. Reload restores the preferred widths; a small viewport clamps only their visible sizes. `/openpi-setup` exposes the same choices as `ui_web_sidebar_width` and `ui_web_auxiliary_width`.

<!-- config-contract: codeMode.enabled webSearch.enabled webSearch.modelSupport response.verbosity response.reasoningSummary suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls childExecutions childExecutions.maxActive browser.control browser.embedded browser.defaultBrowser browser.externalBrowsers ui.webTheme ui.webAppearance ui.webChatWidth ui.webSidebarWidth ui.webAuxiliaryWidth ui.webChatFontSize ui.webExpandThinking ui.webHiddenThinkingLevels ui.webPinnedSort ui.webSidebarGrouping ui.webChatsSort ui.webProjectsInRecents ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->

Browser model control defaults to off. Web Settings → Browser provides installation guidance and connection checks. Its master switch, per-browser grants and default selector submit `/openpi-setup` requests; the active model saves them through the episode-scoped configuration tool. Direct `/openpi-setup` requests use `browser_control` (default false), `browser_embedded` (true), `browser_default` (`embedded`) and `browser_external` (empty list). Request acceptance is not a saved configuration: controls reflect persisted state. A disabled master switch rejects every model browser operation, including during active turns, while ordinary iframe browsing remains available.

Browser choices are `embedded`, `chrome`, `edge`, `brave`, `chromium`, `safari`, and `firefox`. Choosing a default does not grant access. Safari/Firefox use a separate portable extension build with the same OpenPI tool and permission lifecycle; the Pi core and upstream pi-computer-use package are unchanged.

Web model configuration can query an explicitly supplied provider connection, search its model catalog and add up to 100 selected models in one revision-checked native `models.json` write. Existing model metadata and credentials are preserved. Discovery uses Pi credentials only for the matching saved endpoint, or an optional temporary key that is not persisted. Catalog queries are bounded to ten seconds, 1 MiB and 500 models, reject redirects, and never send prompts. New models inherit the form's context/output and reasoning defaults; verify these in advanced parameters. Manual configuration remains available when the catalog is unsupported. No additional OpenPI preference is introduced.

### Post-edit lifecycle

Use a finite, foreground command such as `npm run format`, not a watcher, server, or detached background writer. Post-edit remains off by default and runs only in the interactive TUI, once per settled turn with successful native Write/Edit operations. Bash is not inspected for file changes.

The next Agent start (including a background completion's parent wake-up) waits for outstanding commands to finish, and all tool calls in this Session also join them before executing. This includes read-only and custom tools: a tool-name allowlist cannot reliably identify every workspace reader. Tools that do not access files wait too; only successful native Write/Edit results schedule post-edit. Nonzero exits and interrupted commands produce bounded, sanitized notifications; neither triggers an automatic repair loop or a test-acceptance gate. A command that does not exit can keep the next turn waiting: there is no automatic timeout that silently releases this boundary. Canceling the waiting Agent releases its wait without permitting its tool call or forgetting the still-running command; session teardown can then request command cancellation.

Each queued run captures its command and working directory at settlement. Configuration changes affect future runs; disabling post-edit discards queued runs but lets the active command finish. Session start/shutdown discards queued work and requests cancellation, without treating an abort request as process completion. Results from the old session do not notify the new one.

This coordinates one extension instance's foreground commands with its Agent. It does not lock the workspace against other Sessions, Subagents, external editors, user shell commands, or detached descendants. Pi's command cancellation does not guarantee termination of an entire process tree; keep all command writes in the foreground and inspect interrupted work before relying on its files.

## Optional cross-session communication

[pi-intercom](https://github.com/nicobailon/pi-intercom) is an independently maintained Pi package for communication between top-level Sessions. OpenPI does not detect, recommend, install, configure, migrate, or remove it. If you need that capability, review its repository and install it through Pi's native package command:

```sh
pi install npm:pi-intercom
```

OpenPI Direct Subagents and Workflow children use their native parent/child result channels instead. To preserve process-level identity isolation, their Resource Loader excludes pi-intercom extensions and Skills installed from npm, Git, or local package sources without excluding ordinary project resources that merely share the same directory name.

## Other commands added by this fork

- `/sessions` searches and previews project sessions before switching.
- `/cron every <5m> <prompt>`, `/cron in <30s> <prompt>`, `/cron list`, and `/cron remove <id>` schedule a prompt for this session. Jobs are in-memory and session-scoped (cleared on shutdown), fire only while the session is idle, and use a duration grammar (`30s`/`5m`/`2h`, minimum 30s) rather than crontab fields, because the scheduler polls about every 30 seconds. Jobs due in the same poll are delivered as one triggered turn while retaining each job's id and recurrence metadata; if that atomic delivery fails, every due job remains pending for retry.
- `/plan [objective]` explores read-only before changing anything and adds the read-only git tools to the current Session for the episode. While armed it blocks `edit`, `write`, mutating Bash, raw Git diff-rendering commands, `subagent_send` and `workflow`; read/grep/find/ls, `git_log`/`git_diff`/`git_show`, and verified non-diff Git/GitHub Bash commands (including read-only `rg`/`fd`) stay available. It permits `subagent_spawn`, but the harness narrows every newly spawned planning child to investigation-only tools; agent types can narrow that list further, never widen it. The model must submit the complete plan through parent-only `plan_ready`; the write gate stays closed until `/plan` prepares an editable implementation prompt for the current or a fresh Session. `/plan off` cancels.
