@kingingwang/pi-linux-arm64 0.84.2 → 0.84.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/bin/CHANGELOG.md +81 -0
  2. package/bin/README.md +8 -4
  3. package/bin/docs/compaction.md +15 -0
  4. package/bin/docs/custom-provider.md +5 -2
  5. package/bin/docs/environment-variables.md +8 -8
  6. package/bin/docs/extensions.md +17 -7
  7. package/bin/docs/json.md +7 -2
  8. package/bin/docs/keybindings.md +8 -8
  9. package/bin/docs/llama-cpp.md +2 -0
  10. package/bin/docs/models.md +8 -2
  11. package/bin/docs/packages.md +2 -2
  12. package/bin/docs/rpc.md +9 -3
  13. package/bin/docs/sdk.md +7 -2
  14. package/bin/docs/settings.md +11 -3
  15. package/bin/docs/skills.md +4 -3
  16. package/bin/docs/terminal-setup.md +11 -9
  17. package/bin/docs/usage.md +6 -2
  18. package/bin/docs/windows.md +24 -2
  19. package/bin/examples/extensions/border-status-editor.ts +1 -1
  20. package/bin/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  21. package/bin/examples/extensions/custom-provider-anthropic/package.json +1 -1
  22. package/bin/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  23. package/bin/examples/extensions/git-checkpoint.ts +2 -2
  24. package/bin/examples/extensions/gondolin/package-lock.json +2 -2
  25. package/bin/examples/extensions/gondolin/package.json +1 -1
  26. package/bin/examples/extensions/notify.ts +3 -1
  27. package/bin/examples/extensions/sandbox/package-lock.json +2 -2
  28. package/bin/examples/extensions/sandbox/package.json +1 -1
  29. package/bin/examples/extensions/subagent/README.md +1 -1
  30. package/bin/examples/extensions/subagent/index.ts +6 -1
  31. package/bin/examples/extensions/titlebar-spinner.ts +1 -1
  32. package/bin/examples/extensions/with-deps/package-lock.json +2 -2
  33. package/bin/examples/extensions/with-deps/package.json +1 -1
  34. package/bin/examples/rpc-extension-ui.ts +1 -1
  35. package/bin/examples/sdk/06-extensions.ts +1 -1
  36. package/bin/examples/sdk/README.md +1 -1
  37. package/bin/package.json +12 -14
  38. package/bin/pi +0 -0
  39. package/package.json +1 -1
  40. package/bin/node_modules/@mariozechner/clipboard-linux-arm64-gnu/README.md +0 -3
  41. package/bin/node_modules/@mariozechner/clipboard-linux-arm64-gnu/clipboard.linux-arm64-gnu.node +0 -0
  42. package/bin/node_modules/@mariozechner/clipboard-linux-arm64-gnu/package.json +0 -25
package/bin/CHANGELOG.md CHANGED
@@ -1,5 +1,84 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.84.3] - 2026-08-24
4
+
5
+ ### New Features
6
+
7
+ - **PowerShell tool** — Use optional native PowerShell command execution on Windows. See [PowerShell Tool](docs/windows.md#powershell-tool).
8
+ - **Safer managed updates** — Stage, verify, and atomically activate updates for installer-managed installations. See [Install and Manage](docs/packages.md#install-and-manage).
9
+ - **Model and thinking controls** — Select thinking levels with `/thinking`, search defaults, keep selections session-scoped, and persist them explicitly with Ctrl+S. See [Models and Thinking](docs/keybindings.md#models-and-thinking).
10
+
11
+ ### Breaking Changes
12
+
13
+ - Renamed the inherited `GoogleThinkingLevel` type to `GoogleApiThinkingLevel` and added `ResolvedGoogleThinkingLevel` for normalized adapter levels.
14
+
15
+ ### Added
16
+
17
+ - Added an optional `powershell` tool for Windows, configurable through `defaultTools` and the SDK. See [PowerShell Tool](docs/windows.md#powershell-tool).
18
+ - Added a `/thinking` selector and searchable default choices to the model and thinking selectors; Ctrl+S saves the selected model as the global default. See [Models and Thinking](docs/keybindings.md#models-and-thinking).
19
+ - Added optional routing session IDs to exported compaction summary helpers so callers can preserve provider routing without enabling prompt cache writes.
20
+ - Added transcript usage notices for compaction and branch summaries when cache miss notices are enabled.
21
+ - Added `session_compact_failed` extension events so compaction failures and aborts expose their reason, retry state, source, and error message to handlers ([#8175](https://github.com/earendil-works/pi/issues/8175)).
22
+ - Added inherited provider-neutral `toolChoice` support to simple stream requests.
23
+ - Added inherited automatic Anthropic server-side refusal fallback for supported first-party models, including returned-model usage pricing ([#8017](https://github.com/earendil-works/pi/issues/8017)).
24
+ - Added inherited configurable OpenAI-compatible thinking-token budget fields for vLLM, Qwen/SGLang, and llama.cpp servers. See [OpenAI Compatibility](docs/models.md#openai-compatibility) ([#8275](https://github.com/earendil-works/pi/pull/8275) by [@bnsd55](https://github.com/bnsd55)).
25
+ - Added inherited China-specific ZAI Coding Plan models, including GLM-4.6V vision support and API-equivalent usage cost estimates ([#8220](https://github.com/earendil-works/pi/issues/8220)).
26
+ - Added inherited `deepseek-v4-pro-0813` support to the Qwen Token Plan Individual catalog ([#8194](https://github.com/earendil-works/pi/issues/8194)).
27
+
28
+ ### Changed
29
+
30
+ - Changed experimental installer-managed installations so `pi update` stages, verifies, and atomically activates the selected release in place. See [Install and Manage](docs/packages.md#install-and-manage).
31
+ - Changed inherited built-in xAI models to use the Responses API with encrypted reasoning replay and made Grok 4.6 the default xAI model ([#8124](https://github.com/earendil-works/pi/pull/8124) by [@Jaaneek](https://github.com/Jaaneek)).
32
+ - Changed inherited Anthropic, Azure OpenAI, Google, Mistral, and OpenAI adapters to send Pi's default `User-Agent` unless overridden ([#8305](https://github.com/earendil-works/pi/issues/8305)).
33
+ - Changed Windows and WSL keybinding defaults to avoid terminal-reserved shortcuts for image paste, model cycling, editor undo, fullscreen transcript navigation and search, and message queueing ([#8372](https://github.com/earendil-works/pi/issues/8372)).
34
+ - Changed Bun release archives to ship the native clipboard binary only inside the wrapper package, removing a duplicate platform package from each archive.
35
+ - Changed package resource glob expansion to use Node.js's built-in implementation with deterministic visible-path matching, reducing the installed runtime dependency tree.
36
+ - Changed the bundled Node.js runtime to load jiti only when importing an extension and Babel only when uncached source needs transformation, reducing CLI startup time and bundle size.
37
+ - Changed syntax highlighting to initialize only twenty common languages eagerly and defer the remaining grammars until after the initial TUI render, reducing CLI startup time.
38
+ - Changed the Node.js CLI and RPC entrypoints to load a bundled runtime, reducing startup filesystem reads while keeping the public library and legacy module paths on the modular runtime for normal dependency identity.
39
+ - Changed session sharing to render clickable terminal links, display only the canonical Radius artifact URL, and include the current system prompt and active tool definitions in Radius session shares.
40
+
41
+ ### Fixed
42
+
43
+ - Fixed failed extension factories leaving event subscriptions, provider registrations, and default flag state active ([#8424](https://github.com/earendil-works/pi/pull/8424) by [@acmerfight](https://github.com/acmerfight)).
44
+ - Fixed `models.json` typings omitting the documented OpenAI-compatible `compat.supportsFinishReason` provider and model override ([#8487](https://github.com/earendil-works/pi/pull/8487) by [@petrroll](https://github.com/petrroll)).
45
+ - Fixed `/model` and `/thinking` selections being persisted globally unless explicitly saved with Ctrl+S ([#5263](https://github.com/earendil-works/pi/issues/5263)).
46
+ - Fixed JSON and RPC `toolcall_start` events omitting the tool call id and name ([#7953](https://github.com/earendil-works/pi/pull/7953) by [@christianklotz](https://github.com/christianklotz)).
47
+ - Fixed extensions failing to load when the Node.js CLI runs as a single-executable application ([#8237](https://github.com/earendil-works/pi/issues/8237)).
48
+ - Fixed nested Markdown skills inside `.agents/skills/` grouping directories not being discovered.
49
+ - Fixed compaction and branch summarization requests exposing tools to providers.
50
+ - Fixed single-object `edit` tool inputs failing validation by accepting them as one-edit arrays in both coding-agent and harness edit tools ([#7835](https://github.com/earendil-works/pi/issues/7835)).
51
+ - Fixed root Markdown files such as `README.md` and `AGENTS.md` in skill directories being reported as broken skills unless they declare valid skill frontmatter ([#7805](https://github.com/earendil-works/pi/issues/7805)).
52
+ - Fixed the default Cerebras model referencing an unavailable Z.AI model.
53
+ - Fixed inherited OpenAI-compatible Chat Completions reasoning replay to preserve and resend assistant-level `reasoning_details` verbatim and in order ([#7994](https://github.com/earendil-works/pi/issues/7994)).
54
+ - Fixed inherited Anthropic server-side fallback responses being priced with the requested model instead of the returned fallback model ([#8285](https://github.com/earendil-works/pi/issues/8285)).
55
+ - Fixed inherited GitHub Copilot login triggering model-policy rate limits by limiting policy updates, retrying model discovery once, and honoring server retry delays ([#7850](https://github.com/earendil-works/pi/issues/7850)).
56
+ - Fixed inherited Amazon Bedrock dropping and failing to replay opaque redacted reasoning from non-Anthropic models ([#8314](https://github.com/earendil-works/pi/pull/8314) by [@seiji](https://github.com/seiji)).
57
+ - Fixed inherited Z.AI Coding Plan models deriving incomplete reasoning-effort metadata, including missing GLM-5.3 low, high, and max levels ([#8336](https://github.com/earendil-works/pi/issues/8336)).
58
+ - Fixed inherited DeepSeek V4 Flash on OpenCode and OpenCode Go omitting its supported low thinking level ([#8181](https://github.com/earendil-works/pi/pull/8181) by [@tianshuang](https://github.com/tianshuang)).
59
+ - Fixed inherited Azure OpenAI Responses ignoring `toolChoice` in provider-specific stream requests.
60
+ - Fixed inherited Amazon Bedrock response hooks receiving only a synthesized request id instead of the raw response headers ([#8234](https://github.com/earendil-works/pi/issues/8234)).
61
+ - Fixed inherited Kimi usage reporting so top-level `cached_tokens` count as cache reads instead of normal input tokens ([#8075](https://github.com/earendil-works/pi/issues/8075)).
62
+ - Fixed inherited Google custom models ignoring `thinkingLevelMap`, which dropped extended thinking controls ([#8135](https://github.com/earendil-works/pi/issues/8135)).
63
+ - Fixed writes to `auth.json` and `models-store.json` overriding administrator-managed file permissions and ACLs ([#7779](https://github.com/earendil-works/pi/issues/7779)).
64
+ - Fixed UTF-8 BOM markers preventing frontmatter and user configuration files from loading ([#8337](https://github.com/earendil-works/pi/issues/8337)).
65
+ - Fixed invalid settings files being easy to miss during interactive startup by rendering warnings with the file path inside the TUI ([#7829](https://github.com/earendil-works/pi/issues/7829)).
66
+ - Fixed the subagent example repeatedly prompting before running project-local agents in trusted repositories ([#8261](https://github.com/earendil-works/pi/issues/8261)).
67
+ - Fixed npm package update checks treating older registry versions as available updates, preventing `pi update` from downgrading already-newer installed packages ([#8226](https://github.com/earendil-works/pi/issues/8226)).
68
+ - Fixed built-in llama.cpp models disappearing from `/model` when `/llama` refreshed a configured server under `PI_OFFLINE`, and included idle-slept `sleeping` router models in the selectable catalog ([#8167](https://github.com/earendil-works/pi/issues/8167)).
69
+ - Fixed `pi.registerFlag()` accepting default values that do not match the declared flag type ([#8064](https://github.com/earendil-works/pi/issues/8064)).
70
+ - Fixed Z.AI Coding Plan defaults referencing the removed GLM-5.1 model ([#8096](https://github.com/earendil-works/pi/issues/8096)).
71
+ - Fixed repeated ambiguous truncated-response recovery being mislabeled as context overflow ([#8130](https://github.com/earendil-works/pi/issues/8130)).
72
+ - Fixed duplicate fullscreen right-click paste in VS Code-based terminals on Windows ([#8186](https://github.com/earendil-works/pi/issues/8186)).
73
+ - Fixed inherited padded text exceeding narrow terminal widths ([#8252](https://github.com/earendil-works/pi/issues/8252)).
74
+ - Fixed inherited wrapped Markdown table links leaking color into borders and neighboring cells, including tables inside blockquotes ([#8335](https://github.com/earendil-works/pi/issues/8335)).
75
+ - Fixed llama.cpp login guidance to direct users to `/llama` before `/model` when no local models are loaded ([#8203](https://github.com/earendil-works/pi/issues/8203)).
76
+ - Fixed hung pi.dev model catalog requests consuming the entire refresh deadline without retrying ([#8198](https://github.com/earendil-works/pi/issues/8198)).
77
+ - Fixed inherited Xiaomi model catalogs listing shut-down MiMo V2 models in `/model` and `--list-models` ([#8187](https://github.com/earendil-works/pi/issues/8187)).
78
+ - Fixed branch summary entries recording the navigation destination in `fromId` instead of the pre-navigation source leaf.
79
+ - Fixed threshold auto-compaction being skipped when providers omit streaming usage data ([#8328](https://github.com/earendil-works/pi/issues/8328)).
80
+ - Fixed dash-prefixed prompts being parsed as options by supporting `--` as an end-of-options delimiter ([#7269](https://github.com/earendil-works/pi/issues/7269)).
81
+
3
82
  ## [0.84.2] - 2026-08-14
4
83
 
5
84
  ### New Features
@@ -30,6 +109,8 @@
30
109
 
31
110
  ### Fixed
32
111
 
112
+ - Fixed root Markdown files such as `README.md` and `AGENTS.md` in skill directories being reported as broken skills unless they declare valid skill frontmatter ([#7805](https://github.com/earendil-works/pi/issues/7805)).
113
+ - Fixed single-object `edit` tool inputs failing validation by accepting them as one-edit arrays in both coding-agent and harness edit tools ([#7835](https://github.com/earendil-works/pi/issues/7835)).
33
114
  - Fixed managed-tool downloads delaying TUI startup and hiding diagnostics in fullscreen mode by mounting the TUI first and showing download progress and warnings inside it.
34
115
  - Fixed opening a model selector immediately after startup cancelling and restarting the in-progress model catalog refresh.
35
116
  - Fixed inherited GitHub Copilot login triggering API rate limits while enabling model policies by limiting concurrent policy updates ([#6187](https://github.com/earendil-works/pi/issues/6187)).
package/bin/README.md CHANGED
@@ -514,7 +514,7 @@ Read the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/)
514
514
  ## CLI Reference
515
515
 
516
516
  ```bash
517
- pi [options] [@files...] [messages...]
517
+ pi [options] [--] [@files...] [messages...]
518
518
  ```
519
519
 
520
520
  ### Package Commands
@@ -584,7 +584,7 @@ cat README.md | pi -p "Summarize this text"
584
584
  | `--no-builtin-tools`, `-nbt` | Disable built-in tools by default but keep extension/custom tools enabled |
585
585
  | `--no-tools`, `-nt` | Disable all tools by default |
586
586
 
587
- Available built-in tools: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
587
+ Available built-in tools: `read`, `bash`, `powershell` (Windows), `edit`, `write`, `grep`, `find`, `ls`
588
588
 
589
589
  ### Resource Options
590
590
 
@@ -613,6 +613,7 @@ Combine `--no-*` with explicit flags to load exactly what you need, ignoring set
613
613
  | `--verbose` | Force verbose startup |
614
614
  | `-a`, `--approve` | Trust project-local files for this run |
615
615
  | `-na`, `--no-approve` | Ignore project-local files for this run |
616
+ | `--` | Stop option parsing; remaining arguments are prompts or `@file` inputs |
616
617
  | `-h`, `--help` | Show help |
617
618
  | `-v`, `--version` | Show version |
618
619
 
@@ -635,6 +636,9 @@ pi "List all .ts files in src/"
635
636
  # Non-interactive
636
637
  pi -p "Summarize this codebase"
637
638
 
639
+ # Prompt beginning with a dash
640
+ pi -p -- "- Summarize these points"
641
+
638
642
  # Non-interactive with piped stdin
639
643
  cat README.md | pi -p "Summarize this text"
640
644
 
@@ -678,7 +682,7 @@ pi --thinking high "Solve this complex problem"
678
682
  | `PI_CACHE_RETENTION` | Set to `long` for extended prompt cache (Anthropic: 1h, OpenAI: 24h) |
679
683
  | `VISUAL`, `EDITOR` | Fallback external editor for Ctrl+G when `externalEditor` is unset; defaults to Notepad on Windows and `nano` elsewhere |
680
684
 
681
- Commands run by the LLM-callable bash tool also receive current session metadata:
685
+ Commands run by the LLM-callable `bash` and `powershell` tools also receive current session metadata:
682
686
 
683
687
  | Variable | Description |
684
688
  |----------|-------------|
@@ -688,7 +692,7 @@ Commands run by the LLM-callable bash tool also receive current session metadata
688
692
  | `PI_MODEL` | Currently selected model ID |
689
693
  | `PI_REASONING_LEVEL` | Current effective reasoning level |
690
694
 
691
- These values are resolved when each command starts. See [Environment Variables](docs/environment-variables.md#bash-tool-session-environment) for semantics, examples, and custom-tool opt-out.
695
+ These values are resolved when each command starts. See [Environment Variables](docs/environment-variables.md#shell-tool-session-environment) for semantics, examples, and custom-tool opt-out.
692
696
 
693
697
  ---
694
698
 
@@ -346,6 +346,21 @@ pi.on("session_before_compact", async (event, ctx) => {
346
346
 
347
347
  See [custom-compaction.ts](../examples/extensions/custom-compaction.ts) for a complete example using a different model.
348
348
 
349
+ ### session_compact_failed
350
+
351
+ Fired when manual or automatic compaction fails or is aborted. This is useful for telemetry extensions that need to pair `session_before_compact` attempts with terminal outcomes.
352
+
353
+ ```typescript
354
+ pi.on("session_compact_failed", async (event, ctx) => {
355
+ const { reason, errorMessage, aborted, willRetry, fromExtension } = event;
356
+ // reason - "manual" (/compact), "threshold", or "overflow"
357
+ // errorMessage - present for non-abort failures
358
+ // aborted - true for cancelled/aborted compactions
359
+ // willRetry - whether the aborted turn would have retried after compaction
360
+ // fromExtension - whether extension-provided compaction content was being used
361
+ });
362
+ ```
363
+
349
364
  ### session_before_tree
350
365
 
351
366
  Fired before `/tree` navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
@@ -752,8 +752,10 @@ interface ProviderModelConfig {
752
752
  requiresThinkingAsText?: boolean;
753
753
  requiresReasoningContentOnAssistantMessages?: boolean;
754
754
  thinkingFormat?: "openai" | "openrouter" | "deepseek" | "together" | "baseten" | "zai" | "qwen" | "chat-template" | "qwen-chat-template" | "string-thinking" | "ant-ling";
755
- chatTemplateKwargs?: Record<string, string | number | boolean | null | { "$var": "thinking.enabled" | "thinking.effort"; omitWhenOff?: boolean }>;
756
- chatTemplateArgs?: Record<string, string | number | boolean | null | { "$var": "thinking.enabled" | "thinking.effort"; omitWhenOff?: boolean }>;
755
+ chatTemplateKwargs?: Record<string, string | number | boolean | null | { "$var": "thinking.enabled" | "thinking.effort" | "thinking.budget"; omitWhenOff?: boolean }>;
756
+ chatTemplateArgs?: Record<string, string | number | boolean | null | { "$var": "thinking.enabled" | "thinking.effort" | "thinking.budget"; omitWhenOff?: boolean }>;
757
+ thinkingTokenBudgetField?: "thinking_token_budget" | "thinking_budget" | "thinking_budget_tokens";
758
+ supportsThinkingTokenBudget?: boolean;
757
759
  cacheControlFormat?: "anthropic";
758
760
  sessionAffinityFormat?: "openai" | "openai-nosession" | "openrouter";
759
761
  sendSessionAffinityHeaders?: boolean;
@@ -771,4 +773,5 @@ interface ProviderModelConfig {
771
773
  ```
772
774
 
773
775
  `openrouter` sends `reasoning: { effort }`. `deepseek` sends `thinking: { type: "enabled" | "disabled" }` and `reasoning_effort` when enabled. `together` sends `reasoning: { enabled }` and also `reasoning_effort` when `supportsReasoningEffort` is enabled. `qwen` is for DashScope-style top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking` and need `preserve_thinking`. Use `chat-template` for configurable `chat_template_kwargs`, for example DeepSeek V3.x behind vLLM with `chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } }`. Use `thinkingFormat: "baseten"` with `chatTemplateArgs` when the provider expects toggle values under `chat_template_args` and optionally supports top-level `reasoning_effort`.
776
+ `thinkingTokenBudgetField` sends a clamped per-level thinking budget as a top-level request field (`thinking_token_budget` on vLLM, `thinking_budget` on Qwen/SGLang, `thinking_budget_tokens` on llama.cpp). `supportsThinkingTokenBudget: true` is an alias for the vLLM field name. Do not combine it with `reasoning_effort` on DashScope Qwen models.
774
777
  `cacheControlFormat: "anthropic"` applies Anthropic-style `cache_control` markers to the system prompt, last tool definition, and last user, assistant, or tool-result text content.
@@ -4,7 +4,7 @@ Pi uses environment variables in three ways:
4
4
 
5
5
  - Variables such as `PI_OFFLINE` configure the Pi process.
6
6
  - Pi sets process markers so child processes can identify Pi as the launching agent.
7
- - Commands run by the LLM-callable bash tool receive `PI_*` variables describing the current session.
7
+ - Commands run by the LLM-callable shell tools receive `PI_*` variables describing the current session.
8
8
 
9
9
  Provider API-key variables are documented separately in [Providers](providers.md#environment-variables-or-auth-file).
10
10
 
@@ -17,9 +17,9 @@ The CLI and RPC entry points set two process markers:
17
17
 
18
18
  Child processes inherit both markers. They are not session-specific and are not set automatically when Pi is embedded through the SDK.
19
19
 
20
- ## Bash Tool Session Environment
20
+ ## Shell Tool Session Environment
21
21
 
22
- Commands run by the bash tool receive the current Pi session state:
22
+ Commands run by the `bash` and `powershell` tools receive the current Pi session state:
23
23
 
24
24
  | Variable | Description |
25
25
  |----------|-------------|
@@ -29,7 +29,7 @@ Commands run by the bash tool receive the current Pi session state:
29
29
  | `PI_MODEL` | Currently selected model ID |
30
30
  | `PI_REASONING_LEVEL` | Current effective reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max` |
31
31
 
32
- The values are resolved when each command starts. Switching models or changing the reasoning level therefore affects the next bash command without restarting Pi. `PI_PROVIDER` and `PI_MODEL` identify the selected Pi model, not a different upstream model that a router may choose internally.
32
+ The values are resolved when each command starts. Switching models or changing the reasoning level therefore affects the next shell command without restarting Pi. `PI_PROVIDER` and `PI_MODEL` identify the selected Pi model, not a different upstream model that a router may choose internally.
33
33
 
34
34
  When asked which model or provider is running, inspect these variables instead of inferring the answer from the system prompt:
35
35
 
@@ -46,11 +46,11 @@ if [ -n "$PI_SESSION_FILE" ]; then
46
46
  fi
47
47
  ```
48
48
 
49
- These variables are injected into the LLM-callable bash tool. They are not injected into user-entered `!` or `!!` commands.
49
+ These variables are injected into the LLM-callable `bash` and `powershell` tools. They are not injected into user-entered `!` or `!!` commands.
50
50
 
51
- ### Custom Bash Tools
51
+ ### Custom Shell Tools
52
52
 
53
- Bash tools created with `createBashTool()` expose the session environment by default when registered with Pi. Injection happens before `spawnHook`, so a hook receives the variables in `ctx.env`:
53
+ Tools created with `createBashTool()` or `createPowerShellTool()` expose the session environment by default when registered with Pi. Injection happens before `spawnHook`, so a hook receives the variables in `ctx.env`:
54
54
 
55
55
  ```typescript
56
56
  const bashTool = createBashTool(cwd, {
@@ -64,7 +64,7 @@ const bashTool = createBashTool(cwd, {
64
64
  Disable session metadata independently of the spawn hook:
65
65
 
66
66
  ```typescript
67
- const bashTool = createBashTool(cwd, {
67
+ const powershellTool = createPowerShellTool(cwd, {
68
68
  exposeSessionEnvironment: false,
69
69
  spawnHook: (ctx) => ctx,
70
70
  });
@@ -330,7 +330,8 @@ user sends another prompt ◄─────────────────
330
330
 
331
331
  /compact or auto-compaction
332
332
  ├─► session_before_compact (can cancel or customize)
333
- └─► session_compact
333
+ ├─► session_compact (success)
334
+ └─► session_compact_failed (failure or abort)
334
335
 
335
336
  /tree navigation
336
337
  ├─► session_before_tree (can cancel or customize)
@@ -448,7 +449,7 @@ pi.on("session_before_fork", async (event, ctx) => {
448
449
  After a successful fork or clone, pi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "fork"` and `previousSessionFile`.
449
450
  Do cleanup work in `session_shutdown`, then reestablish any in-memory state in `session_start`.
450
451
 
451
- #### session_before_compact / session_compact
452
+ #### session_before_compact / session_compact / session_compact_failed
452
453
 
453
454
  Fired on compaction. See [compaction.md](compaction.md) for details.
454
455
 
@@ -479,6 +480,14 @@ pi.on("session_compact", async (event, ctx) => {
479
480
  // event.reason - "manual" (/compact), "threshold", or "overflow"
480
481
  // event.willRetry - whether the aborted turn is retried after compaction (overflow recovery)
481
482
  });
483
+
484
+ pi.on("session_compact_failed", async (event, ctx) => {
485
+ // event.reason - "manual" (/compact), "threshold", or "overflow"
486
+ // event.errorMessage - present for non-abort failures
487
+ // event.aborted - true for cancelled/aborted compactions
488
+ // event.willRetry - whether the aborted turn would have retried after compaction
489
+ // event.fromExtension - whether extension-provided compaction content was being used
490
+ });
482
491
  ```
483
492
 
484
493
  #### session_before_tree / session_tree
@@ -2050,7 +2059,7 @@ pi.registerTool({
2050
2059
 
2051
2060
  ### Overriding Built-in Tools
2052
2061
 
2053
- Extensions can override built-in tools (`read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`) by registering a tool with the same name. Interactive mode displays a warning when this happens.
2062
+ Extensions can override built-in tools (`read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, `ls`) by registering a tool with the same name. Interactive mode displays a warning when this happens.
2054
2063
 
2055
2064
  ```bash
2056
2065
  # Extension's read tool replaces built-in read
@@ -2074,6 +2083,7 @@ See [examples/extensions/tool-override.ts](../examples/extensions/tool-override.
2074
2083
  Built-in tool implementations:
2075
2084
  - [read.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/read.ts) - `ReadToolDetails`
2076
2085
  - [bash.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/bash.ts) - `BashToolDetails`
2086
+ - [powershell.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/powershell.ts) - `PowerShellToolDetails`
2077
2087
  - [edit.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/edit.ts)
2078
2088
  - [write.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/write.ts)
2079
2089
  - [grep.ts](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/tools/grep.ts) - `GrepToolDetails`
@@ -2109,11 +2119,11 @@ pi.registerTool({
2109
2119
  });
2110
2120
  ```
2111
2121
 
2112
- **Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
2122
+ **Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `PowerShellOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
2113
2123
 
2114
2124
  For `user_bash`, extensions can reuse pi's local shell backend via `createLocalBashOperations()` instead of reimplementing local process spawning, shell resolution, and process-tree termination.
2115
2125
 
2116
- The bash tool also supports a spawn hook to adjust the command, cwd, or env before execution:
2126
+ The `bash` and `powershell` tools also support a spawn hook to adjust the command, cwd, or env before execution:
2117
2127
 
2118
2128
  ```typescript
2119
2129
  import { createBashTool } from "@earendil-works/pi-coding-agent";
@@ -2127,7 +2137,7 @@ const bashTool = createBashTool(cwd, {
2127
2137
  });
2128
2138
  ```
2129
2139
 
2130
- `createBashTool()` exposes the current session to commands through `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`. Injection happens before `spawnHook`, so hooks receive these values in `env` and preserve them when they spread the existing environment as above. Set `exposeSessionEnvironment: false` to disable them:
2140
+ `createBashTool()` and `createPowerShellTool()` expose the current session to commands through `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`. Injection happens before `spawnHook`, so hooks receive these values in `env` and preserve them when they spread the existing environment as above. Set `exposeSessionEnvironment: false` to disable them:
2131
2141
 
2132
2142
  ```typescript
2133
2143
  const bashTool = createBashTool(cwd, {
@@ -2135,7 +2145,7 @@ const bashTool = createBashTool(cwd, {
2135
2145
  });
2136
2146
  ```
2137
2147
 
2138
- See [Bash tool session environment](environment-variables.md#bash-tool-session-environment) for variable semantics. See [examples/extensions/ssh.ts](../examples/extensions/ssh.ts) for a complete SSH example with `--ssh` flag.
2148
+ See [Shell tool session environment](environment-variables.md#shell-tool-session-environment) for variable semantics. See [examples/extensions/ssh.ts](../examples/extensions/ssh.ts) for a complete SSH example with `--ssh` flag.
2139
2149
 
2140
2150
  ### Output Truncation
2141
2151
 
package/bin/docs/json.md CHANGED
@@ -15,12 +15,16 @@ except that streaming message updates omit cumulative snapshots:
15
15
  ```typescript
16
16
  type WithoutPartial<T> = T extends { partial: unknown } ? Omit<T, "partial"> : T;
17
17
 
18
+ type JsonAssistantMessageEvent<T> = T extends { type: "toolcall_start"; partial: unknown }
19
+ ? WithoutPartial<T> & { id: string; toolName: string }
20
+ : WithoutPartial<T>;
21
+
18
22
  type JsonAgentSessionEvent =
19
23
  | Exclude<AgentSessionEvent, { type: "message_update" }>
20
24
  | {
21
25
  type: "message_update";
22
26
  usage: Usage;
23
- assistantMessageEvent: WithoutPartial<AssistantMessageEvent>;
27
+ assistantMessageEvent: JsonAssistantMessageEvent<AssistantMessageEvent>;
24
28
  };
25
29
  ```
26
30
 
@@ -84,7 +88,8 @@ Followed by events as they occur:
84
88
  `assistantMessageEvent.partial` to keep stream size linear. The top-level `usage` field contains
85
89
  the latest cumulative provider-reported usage and may remain zero when a provider only reports
86
90
  usage at completion. Use `contentIndex` and `delta` to assemble live text, thinking, or tool-call
87
- arguments if needed. `message_end` contains the final authoritative message.
91
+ arguments if needed. A `toolcall_start` event also includes the constant-sized `id` and `toolName`
92
+ fields. `message_end` contains the final authoritative message.
88
93
 
89
94
  ## Example
90
95
 
@@ -70,7 +70,7 @@ The dedicated history actions always change history entries, regardless of the c
70
70
  |--------|---------|-------------|
71
71
  | `tui.editor.yank` | `ctrl+y` | Paste most recently deleted text |
72
72
  | `tui.editor.yankPop` | `alt+y` | Cycle through deleted text after yank |
73
- | `tui.editor.undo` | `ctrl+-` | Undo last edit |
73
+ | `tui.editor.undo` | `ctrl+-` (`ctrl+z` on Windows; `alt+z` on WSL) | Undo last edit |
74
74
 
75
75
  ### TUI Clipboard and Selection
76
76
 
@@ -107,9 +107,9 @@ This routing remains configurable through the ordinary action bindings. For exam
107
107
  | `tui.altScreen.halfPageDown` | *(none)* | Scroll the transcript down by half a page |
108
108
  | `tui.altScreen.lineUp` | *(none)* | Scroll the transcript up by one line |
109
109
  | `tui.altScreen.lineDown` | *(none)* | Scroll the transcript down by one line |
110
- | `tui.altScreen.previousPrompt` | `ctrl+shift+up` | Jump to the previous marked message |
111
- | `tui.altScreen.nextPrompt` | `ctrl+shift+down` | Jump to the next marked message |
112
- | `tui.altScreen.search` | `ctrl+shift+f` | Search the rendered transcript |
110
+ | `tui.altScreen.previousPrompt` | `ctrl+shift+up`, `ctrl+up` (`ctrl+up` only on Windows and WSL) | Jump to the previous marked message |
111
+ | `tui.altScreen.nextPrompt` | `ctrl+shift+down`, `ctrl+down` (`ctrl+down` only on Windows and WSL) | Jump to the next marked message |
112
+ | `tui.altScreen.search` | `ctrl+shift+f` (`ctrl+f` on Windows and WSL) | Search the rendered transcript |
113
113
  | `tui.altScreen.searchNext` | `enter`, `ctrl+g` | Select the next search match while searching |
114
114
  | `tui.altScreen.searchPrevious` | `shift+enter`, `ctrl+shift+g` | Select the previous search match while searching |
115
115
  | `tui.altScreen.searchClose` | `escape` | Close transcript search |
@@ -125,7 +125,7 @@ This routing remains configurable through the ordinary action bindings. For exam
125
125
  | `app.exit` | `ctrl+d` | Exit (when editor empty) |
126
126
  | `app.suspend` | `ctrl+z` (none on Windows) | Suspend to background |
127
127
  | `app.editor.external` | `ctrl+g` | Open in external editor (`externalEditor`, `$VISUAL`, `$EDITOR`, Notepad on Windows, or `nano` elsewhere) |
128
- | `app.clipboard.pasteImage` | `ctrl+v` (`alt+v` on Windows) | Paste image or text from clipboard |
128
+ | `app.clipboard.pasteImage` | `ctrl+v` (`alt+v` on Windows and WSL) | Paste image or text from clipboard |
129
129
 
130
130
  ### Sessions
131
131
 
@@ -148,7 +148,7 @@ This routing remains configurable through the ordinary action bindings. For exam
148
148
  |--------|---------|-------------|
149
149
  | `app.model.select` | `ctrl+l` | Open model selector |
150
150
  | `app.model.cycleForward` | `ctrl+p` | Cycle to next model |
151
- | `app.model.cycleBackward` | `shift+ctrl+p` | Cycle to previous model |
151
+ | `app.model.cycleBackward` | `shift+ctrl+p` (`alt+p` on Windows and WSL) | Cycle to previous model |
152
152
  | `app.thinking.cycle` | `shift+tab` | Cycle thinking level |
153
153
  | `app.thinking.toggle` | `ctrl+t` | Collapse or expand thinking blocks |
154
154
 
@@ -158,8 +158,8 @@ This routing remains configurable through the ordinary action bindings. For exam
158
158
  |--------|---------|-------------|
159
159
  | `app.tools.expand` | `ctrl+o` | Collapse or expand tool output |
160
160
  | `app.message.copy` | `ctrl+x` | Copy the last assistant message, or the selected message in `/tree` |
161
- | `app.message.followUp` | `alt+enter` | Queue follow-up message |
162
- | `app.message.dequeue` | `alt+up` | Restore queued messages to editor |
161
+ | `app.message.followUp` | `alt+enter` (`ctrl+q` on Windows and WSL) | Queue follow-up message |
162
+ | `app.message.dequeue` | `alt+up` (`alt+q` on Windows and WSL) | Restore queued messages to editor |
163
163
 
164
164
  ### Tree Navigation
165
165
 
@@ -53,6 +53,8 @@ Start Pi and configure the provider:
53
53
 
54
54
  Enter the router URL and optional API key. The default URL is `http://127.0.0.1:8080`.
55
55
 
56
+ If you start the router with `--no-models-autoload`, `/login llama.cpp` only stores the connection. Run `/llama` to load a model, then `/model` to select the loaded model for the current session.
57
+
56
58
  Environment variables can configure the same values without `/login`:
57
59
 
58
60
  ```bash
@@ -254,6 +254,8 @@ Current behavior:
254
254
 
255
255
  Only OpenAI-compatible APIs apply it (`openai-completions`, `openai-responses`, `azure-openai-responses`); other APIs ignore it. Keys override pi's named request fields (for example a `temperature` key here beats the request-level temperature), so prefer it as the single source of sampling truth for a model. In `modelOverrides`, `samplingParams` merges per key with the base model's value.
256
256
 
257
+ A constant thinking-token cap can go here too, but it will not follow `thinkingBudgets` or leave room for the answer. Prefer `compat.thinkingTokenBudgetField` (or the `supportsThinkingTokenBudget` alias) for that.
258
+
257
259
  ### Thinking Level Map
258
260
 
259
261
  Use `thinkingLevelMap` on a model to describe model-specific thinking controls. Keys are pi thinking levels: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Maps may contain holes; for example, a model can expose `high` and `max` without exposing `xhigh`.
@@ -467,8 +469,10 @@ For providers with partial OpenAI compatibility, use the `compat` field.
467
469
  | `requiresThinkingAsText` | Convert thinking blocks to plain text |
468
470
  | `requiresReasoningContentOnAssistantMessages` | Include empty `reasoning_content` on all replayed assistant messages when reasoning is enabled |
469
471
  | `thinkingFormat` | Use `reasoning_effort`, `openrouter`, `deepseek`, `together`, `baseten`, `zai`, `qwen`, `chat-template`, or `qwen-chat-template` thinking parameters |
470
- | `chatTemplateKwargs` | `chat_template_kwargs` values for `thinkingFormat: "chat-template"`; use `{ "$var": "thinking.enabled" }` or `{ "$var": "thinking.effort" }` for pi-controlled thinking values |
471
- | `chatTemplateArgs` | `chat_template_args` values for `thinkingFormat: "baseten"`; use `{ "$var": "thinking.enabled" }` or `{ "$var": "thinking.effort" }` for pi-controlled thinking values |
472
+ | `chatTemplateKwargs` | `chat_template_kwargs` values for `thinkingFormat: "chat-template"`; use `{ "$var": "thinking.enabled" }`, `{ "$var": "thinking.effort" }`, or `{ "$var": "thinking.budget" }` for pi-controlled thinking values |
473
+ | `chatTemplateArgs` | `chat_template_args` values for `thinkingFormat: "baseten"`; use `{ "$var": "thinking.enabled" }`, `{ "$var": "thinking.effort" }`, or `{ "$var": "thinking.budget" }` for pi-controlled thinking values |
474
+ | `thinkingTokenBudgetField` | Top-level request field used to cap reasoning tokens from `thinkingBudgets`, clamped so at least 1024 tokens remain for the answer. `"thinking_token_budget"` (vLLM), `"thinking_budget"` (Qwen/DashScope/SGLang), `"thinking_budget_tokens"` (llama.cpp). Off by default; not set on the generated catalog. |
475
+ | `supportsThinkingTokenBudget` | Alias for `thinkingTokenBudgetField: "thinking_token_budget"` (vLLM). Prefer `thinkingTokenBudgetField`. Default: `false`. |
472
476
  | `cacheControlFormat` | Use Anthropic-style `cache_control` markers on the system prompt, last tool definition, and last user, assistant, or tool-result text content. Currently only `anthropic` is supported. |
473
477
  | `sendSessionAffinityHeaders` | For `openai-completions`, send session-affinity headers from the session id when caching is enabled. Default: `false`. |
474
478
  | `sessionAffinityFormat` | For `openai-completions` and `openai-responses`, the session-affinity header format: `openai` sends `session_id`/`x-client-request-id` (completions also `x-session-affinity`), `openai-nosession` omits the underscore-containing `session_id` header, `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param. Default: auto-detected. |
@@ -481,6 +485,8 @@ For providers with partial OpenAI compatibility, use the `compat` field.
481
485
 
482
486
  `openrouter` uses `reasoning: { effort }`. `together` uses `reasoning: { enabled }` and also `reasoning_effort` when `supportsReasoningEffort` is enabled. `qwen` uses top-level `enable_thinking`. Use `qwen-chat-template` for local Qwen-compatible servers that require `chat_template_kwargs.enable_thinking` and `preserve_thinking`. Use `chat-template` for vLLM/Hugging Face chat templates that need configurable `chat_template_kwargs`, such as `chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } }` for DeepSeek V3.x templates. Use `thinkingFormat: "baseten"` with `chatTemplateArgs` for providers that expose toggle controls through `chat_template_args` and optionally support top-level `reasoning_effort`.
483
487
 
488
+ `thinkingTokenBudgetField` is independent of `thinkingFormat`. Do not enable it on the generated Qwen catalog: those models already send `reasoning_effort`, and DashScope rejects `thinking_budget` together with `reasoning_effort`.
489
+
484
490
  `cacheControlFormat: "anthropic"` is for OpenAI-compatible providers that expose Anthropic-style prompt caching through `cache_control` markers on text content and tool definitions.
485
491
 
486
492
  Example:
@@ -38,7 +38,7 @@ pi update npm:@foo/bar # update one package
38
38
  pi update --extension npm:@foo/bar
39
39
  ```
40
40
 
41
- These commands manage pi packages and `pi update` can update the pi CLI installation. To uninstall pi itself, see [Quickstart](quickstart.md#uninstall).
41
+ These commands manage pi packages and `pi update` can update the pi CLI installation. For experimental installer-managed installations, `pi update` installs the exact checked version into a staged, lockfile-backed release and activates it only after verification, leaving the current release intact if the update fails. Managed installations do not support `--force`; rerun the installer to repair one. To uninstall pi itself, see [Quickstart](quickstart.md#uninstall).
42
42
 
43
43
  By default, `install` and `remove` write to user settings (`~/.pi/agent/settings.json`). Use `-l` to write to project settings (`.pi/settings.json`) instead. Project settings can be shared with your team, and pi installs any missing packages automatically on startup after the project is trusted.
44
44
 
@@ -130,7 +130,7 @@ Add a `pi` manifest to `package.json` or use conventional directories. Include t
130
130
  }
131
131
  ```
132
132
 
133
- Paths are relative to the package root. Arrays support glob patterns and `!exclusions`.
133
+ Paths are relative to the package root. Arrays support glob patterns and `!exclusions`. Positive manifest globs discover visible paths in lexical order. List dot-prefixed paths directly. If a glob would need to continue through a symlink, list the symlinked resource root directly.
134
134
 
135
135
  ### Gallery Metadata
136
136
 
package/bin/docs/rpc.md CHANGED
@@ -945,7 +945,7 @@ The `assistantMessageEvent` field contains one of these delta types:
945
945
  | `thinking_start` | Thinking block started |
946
946
  | `thinking_delta` | Thinking content chunk |
947
947
  | `thinking_end` | Thinking block ended |
948
- | `toolcall_start` | Tool call started |
948
+ | `toolcall_start` | Tool call started (includes `id` and `toolName`) |
949
949
  | `toolcall_delta` | Tool call arguments chunk |
950
950
  | `toolcall_end` | Tool call ended (includes full `toolCall` object) |
951
951
 
@@ -960,11 +960,17 @@ Example streaming a text response:
960
960
  The top-level `usage` field contains the latest cumulative provider-reported usage. It may remain
961
961
  zero until completion when a provider does not report usage during streaming.
962
962
 
963
+ Example starting a tool call:
964
+ ```json
965
+ {"type":"message_update","usage":{...},"assistantMessageEvent":{"type":"toolcall_start","contentIndex":1,"id":"call_abc123","toolName":"write"}}
966
+ ```
967
+
963
968
  `message_update` intentionally omits the former cumulative `message` field and
964
969
  `assistantMessageEvent.partial`. Clients that need a live partial message must assemble it
965
970
  from `message_start` and subsequent events using `contentIndex`. Treat `message_end.message`
966
- as authoritative. For tool calls, buffer `toolcall_delta.delta`; `toolcall_end.toolCall`
967
- contains the completed call.
971
+ as authoritative. For tool calls, `toolcall_start` provides the call `id` and `toolName`;
972
+ buffer `toolcall_delta.delta` for arguments. `toolcall_end.toolCall` contains the completed
973
+ call.
968
974
 
969
975
  ### bash_execution_update
970
976
 
package/bin/docs/sdk.md CHANGED
@@ -519,7 +519,7 @@ const { session } = await createAgentSession({ resourceLoader: loader });
519
519
 
520
520
  Specify which built-in tools to enable:
521
521
 
522
- - Built-in tool names: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
522
+ - Built-in tool names: `read`, `bash`, `powershell`, `edit`, `write`, `grep`, `find`, `ls`
523
523
  - Default built-ins: `read`, `bash`, `edit`, `write`
524
524
  - `noTools: "all"` disables all tools
525
525
  - `noTools: "builtin"` disables default built-ins while keeping extension and custom tools enabled
@@ -540,6 +540,11 @@ const { session } = await createAgentSession({
540
540
  tools: ["read", "bash", "grep"],
541
541
  });
542
542
 
543
+ // Use PowerShell instead of Bash on Windows
544
+ const { session } = await createAgentSession({
545
+ tools: ["read", "powershell", "edit", "write"],
546
+ });
547
+
543
548
  // Disable one tool while keeping the rest available
544
549
  const { session } = await createAgentSession({
545
550
  excludeTools: ["ask_question"],
@@ -1196,7 +1201,7 @@ SettingsManager
1196
1201
  // Tool factories
1197
1202
  createCodingTools
1198
1203
  createReadOnlyTools
1199
- createReadTool, createBashTool, createEditTool, createWriteTool
1204
+ createReadTool, createBashTool, createPowerShellTool, createEditTool, createWriteTool
1200
1205
  createGrepTool, createFindTool, createLsTool
1201
1206
 
1202
1207
  // Types
@@ -31,8 +31,8 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
31
31
  | `defaultModel` | string | - | Default model ID |
32
32
  | `defaultThinkingLevel` | string | - | `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"max"` |
33
33
  | `hideThinkingBlock` | boolean | `false` | Hide thinking blocks in output |
34
- | `showCacheMissNotices` | boolean | `false` | Show transcript notices for significant prompt-cache misses |
35
- | `thinkingBudgets` | object | - | Custom token budgets per thinking level |
34
+ | `showCacheMissNotices` | boolean | `false` | Show transcript notices for significant prompt-cache misses and compaction or branch-summary usage |
35
+ | `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. |
36
36
 
37
37
  #### thinkingBudgets
38
38
 
@@ -227,7 +227,7 @@ Windows paths in JSON must use forward slashes or escaped backslashes:
227
227
  |---------|------|---------|-------------|
228
228
  | `defaultTools` | string[] | - | Built-in tools enabled initially. When omitted, Pi uses its standard defaults |
229
229
 
230
- `defaultTools` selects the built-in tools enabled at startup. Extension and SDK custom tools remain enabled:
230
+ `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`:
231
231
 
232
232
  ```json
233
233
  {
@@ -235,6 +235,14 @@ Windows paths in JSON must use forward slashes or escaped backslashes:
235
235
  }
236
236
  ```
237
237
 
238
+ On Windows, select `powershell` instead of `bash`, or include both:
239
+
240
+ ```json
241
+ {
242
+ "defaultTools": ["read", "powershell", "edit", "write"]
243
+ }
244
+ ```
245
+
238
246
  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.
239
247
 
240
248
  ### Sessions
@@ -34,9 +34,10 @@ Pi loads skills from:
34
34
  - CLI: `--skill <path>` (repeatable, additive even with `--no-skills`)
35
35
 
36
36
  Discovery rules:
37
- - In `~/.pi/agent/skills/` and `.pi/skills/`, direct root `.md` files are discovered as individual skills
37
+ - In `~/.pi/agent/skills/` and `.pi/skills/`, direct root `.md` files are discovered as individual skills when they have valid skill frontmatter with a non-empty `description`
38
38
  - In all skill locations, directories containing `SKILL.md` are discovered recursively
39
- - In `~/.agents/skills/` and project `.agents/skills/`, root `.md` files are ignored
39
+ - In `~/.agents/skills/` and project `.agents/skills/`, root `.md` files are ignored, but nested `.md` files in grouping folders are discovered when they declare skill frontmatter
40
+ - Root Markdown files other than `SKILL.md` that do not look like skills are ignored silently
40
41
 
41
42
  Disable discovery with `--no-skills` (explicit `--skill` paths still load).
42
43
 
@@ -183,7 +184,7 @@ Pi validates skills against the Agent Skills standard. Most issues produce warni
183
184
 
184
185
  Unknown frontmatter fields are ignored.
185
186
 
186
- **Exception:** Skills with missing description are not loaded.
187
+ Declared skills with missing descriptions are not loaded. Malformed `SKILL.md` files and `SKILL.md` files without a description produce warnings and are not loaded. Other Markdown files without valid skill frontmatter are ignored.
187
188
 
188
189
  Name collisions (same name from different locations) warn and keep the first skill found.
189
190
 
@@ -120,7 +120,15 @@ Add to `keybindings.json`:
120
120
 
121
121
  ## Windows Terminal
122
122
 
123
- Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward the modified Enter keys pi uses:
123
+ Pi uses Windows-style keybindings when running natively on Windows or in WSL:
124
+
125
+ - `Alt+V` pastes an image or clipboard text.
126
+ - `Ctrl+F` searches the transcript in fullscreen mode, and `Ctrl+Up`/`Ctrl+Down` jump between marked messages.
127
+ - `Alt+P` cycles to the previous model.
128
+ - `Ctrl+Z` undoes editing on native Windows; WSL uses `Alt+Z` so `Ctrl+Z` can suspend pi.
129
+ - `Ctrl+Q` queues a follow-up message and `Alt+Q` restores queued messages.
130
+
131
+ Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward `Shift+Enter` for inserting a new line:
124
132
 
125
133
  ```json
126
134
  {
@@ -128,20 +136,14 @@ Add to `settings.json` (Ctrl+Shift+, or Settings → Open JSON file) to forward
128
136
  {
129
137
  "command": { "action": "sendInput", "input": "\u001b[13;2u" },
130
138
  "keys": "shift+enter"
131
- },
132
- {
133
- "command": { "action": "sendInput", "input": "\u001b[13;3u" },
134
- "keys": "alt+enter"
135
139
  }
136
140
  ]
137
141
  }
138
142
  ```
139
143
 
140
- - `Shift+Enter` inserts a new line.
141
- - Windows Terminal binds `Alt+Enter` to fullscreen by default. That prevents pi from receiving `Alt+Enter` for follow-up queueing.
142
- - Remapping `Alt+Enter` to `sendInput` forwards the real key chord to pi instead.
144
+ Windows Terminal binds `Alt+Enter` to fullscreen by default. To use it instead of pi's `Ctrl+Q` default for follow-up queueing, configure Windows Terminal to send the key and bind `app.message.followUp` to `alt+enter` in pi.
143
145
 
144
- If you already have an `actions` array, add the objects to it. If the old fullscreen behavior persists, fully close and reopen Windows Terminal.
146
+ If you already have an `actions` array, add the object to it. Fully close and reopen Windows Terminal after changing its settings.
145
147
 
146
148
  ## xfce4-terminal, terminator
147
149
 
package/bin/docs/usage.md CHANGED
@@ -142,7 +142,7 @@ If you use pi for open source work and want to publish sessions for model, promp
142
142
  ## CLI Reference
143
143
 
144
144
  ```bash
145
- pi [options] [@files...] [messages...]
145
+ pi [options] [--] [@files...] [messages...]
146
146
  ```
147
147
 
148
148
  ### Package Commands
@@ -213,7 +213,7 @@ cat README.md | pi -p "Summarize this text"
213
213
  | `--no-builtin-tools`, `-nbt` | Disable built-in tools but keep extension/custom tools enabled |
214
214
  | `--no-tools`, `-nt` | Disable all tools |
215
215
 
216
- Built-in tools: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`.
216
+ Built-in tools: `read`, `bash`, `powershell` (Windows), `edit`, `write`, `grep`, `find`, `ls`.
217
217
 
218
218
  ### Resource Options
219
219
 
@@ -246,6 +246,7 @@ pi --no-extensions -e ./my-extension.ts
246
246
  | `--verbose` | Force verbose startup |
247
247
  | `-a`, `--approve` | Trust project-local files for this run |
248
248
  | `-na`, `--no-approve` | Ignore project-local files for this run |
249
+ | `--` | Stop option parsing; remaining arguments are prompts or `@file` inputs |
249
250
  | `-h`, `--help` | Show help |
250
251
  | `-v`, `--version` | Show version |
251
252
 
@@ -272,6 +273,9 @@ pi "List all .ts files in src/"
272
273
  # Non-interactive
273
274
  pi -p "Summarize this codebase"
274
275
 
276
+ # Prompt beginning with a dash
277
+ pi -p -- "- Summarize these points"
278
+
275
279
  # Non-interactive with piped stdin
276
280
  cat README.md | pi -p "Summarize this text"
277
281
 
@@ -1,6 +1,6 @@
1
1
  # Windows Setup
2
2
 
3
- Pi requires a bash shell on Windows. Checked locations (in order):
3
+ Pi uses Git Bash by default on Windows. Checked locations (in order):
4
4
 
5
5
  1. Custom path from `~/.pi/agent/settings.json`
6
6
  2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
@@ -8,7 +8,29 @@ Pi requires a bash shell on Windows. Checked locations (in order):
8
8
 
9
9
  For most users, [Git for Windows](https://git-scm.com/download/win) is sufficient.
10
10
 
11
- ## Custom Shell Path
11
+ ## PowerShell Tool
12
+
13
+ The optional `powershell` tool runs commands through `pwsh.exe` when available, otherwise Windows PowerShell. It starts PowerShell with `-NoProfile -NonInteractive -ExecutionPolicy Bypass`. Administrator-enforced execution policies can still take precedence.
14
+
15
+ Use `defaultTools` to replace the model-facing `bash` tool:
16
+
17
+ ```json
18
+ {
19
+ "defaultTools": ["read", "powershell", "edit", "write"]
20
+ }
21
+ ```
22
+
23
+ Or enable both while comparing behavior:
24
+
25
+ ```json
26
+ {
27
+ "defaultTools": ["read", "bash", "powershell", "edit", "write"]
28
+ }
29
+ ```
30
+
31
+ The `!` and `!!` editor commands still use Bash.
32
+
33
+ ## Custom Bash Path
12
34
 
13
35
  ```json
14
36
  {
@@ -92,7 +92,7 @@ export default function (pi: ExtensionAPI) {
92
92
  activeTui?.requestRender();
93
93
  });
94
94
 
95
- pi.on("agent_end", () => {
95
+ pi.on("agent_settled", () => {
96
96
  isWorking = false;
97
97
  stopSpinner();
98
98
  activeTui?.requestRender();
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "0.84.2",
3
+ "version": "0.84.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "0.84.2",
9
+ "version": "0.84.3",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.84.2",
4
+ "version": "0.84.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.84.2",
4
+ "version": "0.84.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -46,8 +46,8 @@ export default function (pi: ExtensionAPI) {
46
46
  }
47
47
  });
48
48
 
49
- pi.on("agent_end", async () => {
50
- // Clear checkpoints after agent completes
49
+ pi.on("agent_settled", async () => {
50
+ // Clear checkpoints after the full agent run completes
51
51
  checkpoints.clear();
52
52
  });
53
53
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
- "version": "0.84.2",
3
+ "version": "0.84.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-gondolin",
9
- "version": "0.84.2",
9
+ "version": "0.84.3",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
3
  "private": true,
4
- "version": "0.84.2",
4
+ "version": "0.84.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -49,7 +49,9 @@ function notify(title: string, body: string): void {
49
49
  }
50
50
 
51
51
  export default function (pi: ExtensionAPI) {
52
- pi.on("agent_end", async () => {
52
+ // `agent_end` fires after each low-level run; Pi may still retry, compact,
53
+ // or continue with queued follow-ups. Notify only after the full run settles.
54
+ pi.on("agent_settled", async () => {
53
55
  notify("Pi", "Ready for input");
54
56
  });
55
57
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
- "version": "1.14.2",
3
+ "version": "1.14.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-sandbox",
9
- "version": "1.14.2",
9
+ "version": "1.14.3",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
3
  "private": true,
4
- "version": "1.14.2",
4
+ "version": "1.14.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -62,7 +62,7 @@ This tool executes a separate `pi` subprocess with a delegated system prompt and
62
62
 
63
63
  To enable project-local agents, pass `agentScope: "both"` (or `"project"`). Only do this for repositories you trust.
64
64
 
65
- When running interactively, the tool prompts for confirmation before running project-local agents. Set `confirmProjectAgents: false` to disable.
65
+ When running interactively, the tool prompts for confirmation before running project-local agents in untrusted projects. Trusted projects skip the additional prompt. Set `confirmProjectAgents: false` to disable confirmation.
66
66
 
67
67
  ## Usage
68
68
 
@@ -517,7 +517,12 @@ export default function (pi: ExtensionAPI) {
517
517
  };
518
518
  }
519
519
 
520
- if ((agentScope === "project" || agentScope === "both") && confirmProjectAgents && ctx.hasUI) {
520
+ if (
521
+ (agentScope === "project" || agentScope === "both") &&
522
+ confirmProjectAgents &&
523
+ ctx.hasUI &&
524
+ !ctx.isProjectTrusted()
525
+ ) {
521
526
  const requestedAgentNames = new Set<string>();
522
527
  if (params.chain) for (const step of params.chain) requestedAgentNames.add(step.agent);
523
528
  if (params.tasks) for (const t of params.tasks) requestedAgentNames.add(t.agent);
@@ -48,7 +48,7 @@ export default function (pi: ExtensionAPI) {
48
48
  startAnimation(ctx);
49
49
  });
50
50
 
51
- pi.on("agent_end", async (_event, ctx) => {
51
+ pi.on("agent_settled", async (_event, ctx) => {
52
52
  stopAnimation(ctx);
53
53
  });
54
54
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "0.84.2",
3
+ "version": "0.84.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "0.84.2",
9
+ "version": "0.84.3",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.84.2",
4
+ "version": "0.84.3",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -576,7 +576,7 @@ async function main() {
576
576
  return;
577
577
  }
578
578
 
579
- if (data.type === "agent_end") {
579
+ if (data.type === "agent_settled") {
580
580
  isStreaming = false;
581
581
  hideLoading();
582
582
  outputLog.append("");
@@ -71,7 +71,7 @@ export default function (pi: ExtensionAPI) {
71
71
  });
72
72
 
73
73
  pi.on("agent_end", async (event) => {
74
- console.log(\`[Extension] Done, \${event.messages.length} messages\`);
74
+ console.log(\`[Extension] Low-level run ended, \${event.messages.length} messages\`);
75
75
  });
76
76
 
77
77
  // Register a custom tool
@@ -132,7 +132,7 @@ session.subscribe((event) => {
132
132
  case "tool_execution_end":
133
133
  console.log(`Result: ${event.result}`);
134
134
  break;
135
- case "agent_end":
135
+ case "agent_settled":
136
136
  console.log("Done");
137
137
  break;
138
138
  }
package/bin/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "0.84.2",
3
+ "version": "0.84.3",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
7
7
  "configDir": ".pi"
8
8
  },
9
9
  "bin": {
10
- "pi": "dist/cli.js"
10
+ "pi": "dist/bundle/cli.js"
11
11
  },
12
12
  "main": "./dist/index.js",
13
13
  "types": "./dist/index.d.ts",
@@ -17,7 +17,7 @@
17
17
  "import": "./dist/index.js"
18
18
  },
19
19
  "./rpc-entry": {
20
- "import": "./dist/rpc-entry.js"
20
+ "import": "./dist/bundle/rpc-entry.js"
21
21
  },
22
22
  "./client": {
23
23
  "types": "./dist/client/index.d.ts",
@@ -34,8 +34,9 @@
34
34
  ],
35
35
  "scripts": {
36
36
  "clean": "shx rm -rf dist",
37
- "build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
38
- "build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm --prefix ../protocol run build && npm --prefix ../client run build && npm run build && bun build --compile --no-compile-autoload-bunfig ./dist/bun/cli.js ./src/utils/image-resize-worker.ts --outfile dist/pi && npm run copy-binary-assets",
37
+ "build": "npm run build:unbundled && node ../../scripts/build-coding-agent-bundle.mjs",
38
+ "build:unbundled": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
39
+ "build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm --prefix ../protocol run build && npm --prefix ../client run build && npm run build && bun build --compile --no-compile-autoload-bunfig ./src/bun/cli.ts ./src/utils/image-resize-worker.ts --outfile dist/pi && npm run copy-binary-assets",
39
40
  "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
40
41
  "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
41
42
  "test": "vitest --run",
@@ -43,16 +44,15 @@
43
44
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
44
45
  },
45
46
  "dependencies": {
46
- "@earendil-works/pi-agent-core": "^0.84.2",
47
- "@earendil-works/pi-ai": "^0.84.2",
48
- "@earendil-works/pi-client": "^0.84.2",
49
- "@earendil-works/pi-protocol": "^0.84.2",
50
- "@earendil-works/pi-tui": "^0.84.2",
47
+ "@earendil-works/pi-agent-core": "^0.84.3",
48
+ "@earendil-works/pi-ai": "^0.84.3",
49
+ "@earendil-works/pi-client": "^0.84.3",
50
+ "@earendil-works/pi-protocol": "^0.84.3",
51
+ "@earendil-works/pi-tui": "^0.84.3",
51
52
  "@silvia-odwyer/photon-node": "0.3.4",
52
53
  "chalk": "5.6.2",
53
54
  "cross-spawn": "7.0.6",
54
55
  "diff": "8.0.4",
55
- "glob": "13.0.6",
56
56
  "grok-mermaid": "0.2.2",
57
57
  "highlight.js": "10.7.3",
58
58
  "hosted-git-info": "9.0.3",
@@ -77,10 +77,8 @@
77
77
  },
78
78
  "devDependencies": {
79
79
  "@types/cross-spawn": "6.0.6",
80
- "@types/diff": "7.0.2",
81
80
  "@types/hosted-git-info": "3.0.5",
82
- "@types/ms": "2.1.0",
83
- "@types/node": "24.12.4",
81
+ "@types/node": "22.19.19",
84
82
  "@types/proper-lockfile": "4.1.4",
85
83
  "@types/semver": "7.7.1",
86
84
  "shx": "0.4.0",
package/bin/pi CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kingingwang/pi-linux-arm64",
3
- "version": "0.84.2",
3
+ "version": "0.84.3",
4
4
  "description": "Pi standalone binary for linux-arm64 (fork distribution)",
5
5
  "license": "MIT",
6
6
  "os": [
@@ -1,3 +0,0 @@
1
- # `@mariozechner/clipboard-linux-arm64-gnu`
2
-
3
- This is the **aarch64-unknown-linux-gnu** binary for `@mariozechner/clipboard`
@@ -1,25 +0,0 @@
1
- {
2
- "name": "@mariozechner/clipboard-linux-arm64-gnu",
3
- "version": "0.3.9",
4
- "os": [
5
- "linux"
6
- ],
7
- "cpu": [
8
- "arm64"
9
- ],
10
- "main": "clipboard.linux-arm64-gnu.node",
11
- "files": [
12
- "clipboard.linux-arm64-gnu.node"
13
- ],
14
- "license": "MIT",
15
- "engines": {
16
- "node": ">= 10"
17
- },
18
- "libc": [
19
- "glibc"
20
- ],
21
- "repository": {
22
- "type": "git",
23
- "url": "https://github.com/badlogic/clipboard.git"
24
- }
25
- }