From 36bb1d3865120b42397004db7782e66c90a82bea Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 13 Jan 2026 18:33:59 +0100 Subject: [PATCH] docs: update extension examples READMEs and fix plan-mode references - Add missing extensions to examples/extensions/README.md: questionnaire.ts, truncated-tool.ts, model-status.ts, rainbow-editor.ts, custom-footer.ts, custom-header.ts, overlay-test.ts, shutdown-command.ts, interactive-shell.ts, claude-rules.ts, mac-system-theme.ts - Update plan-mode.ts -> plan-mode/ (now a directory) - Add new System Integration section - Update docs/extensions.md plan-mode.ts -> plan-mode/index.ts (17 refs) - Add questionnaire.ts to registerTool and ctx.ui.select() examples - Expand examples/README.md description --- packages/coding-agent/docs/extensions.md | 34 +++++++++---------- packages/coding-agent/examples/README.md | 7 ++-- .../examples/extensions/README.md | 22 ++++++++++-- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/packages/coding-agent/docs/extensions.md b/packages/coding-agent/docs/extensions.md index 2dca34ea..e8ef3bd7 100644 --- a/packages/coding-agent/docs/extensions.md +++ b/packages/coding-agent/docs/extensions.md @@ -439,7 +439,7 @@ pi.on("before_agent_start", async (event, ctx) => { }); ``` -**Examples:** [claude-rules.ts](../examples/extensions/claude-rules.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts), [ssh.ts](../examples/extensions/ssh.ts) +**Examples:** [claude-rules.ts](../examples/extensions/claude-rules.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [ssh.ts](../examples/extensions/ssh.ts) #### agent_start / agent_end @@ -453,7 +453,7 @@ pi.on("agent_end", async (event, ctx) => { }); ``` -**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts) +**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts) #### turn_start / turn_end @@ -469,7 +469,7 @@ pi.on("turn_end", async (event, ctx) => { }); ``` -**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts), [status-line.ts](../examples/extensions/status-line.ts) +**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [status-line.ts](../examples/extensions/status-line.ts) #### context @@ -483,7 +483,7 @@ pi.on("context", async (event, ctx) => { }); ``` -**Examples:** [plan-mode.ts](../examples/extensions/plan-mode.ts) +**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts) ### Model Events @@ -528,7 +528,7 @@ pi.on("tool_call", async (event, ctx) => { }); ``` -**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts), [protected-paths.ts](../examples/extensions/protected-paths.ts) +**Examples:** [chalk-logger.ts](../examples/extensions/chalk-logger.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [protected-paths.ts](../examples/extensions/protected-paths.ts) #### tool_result @@ -550,7 +550,7 @@ pi.on("tool_result", async (event, ctx) => { }); ``` -**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts) +**Examples:** [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts) ### User Bash Events @@ -724,7 +724,7 @@ pi.registerTool({ }); ``` -**Examples:** [hello.ts](../examples/extensions/hello.ts), [question.ts](../examples/extensions/question.ts), [todo.ts](../examples/extensions/todo.ts), [truncated-tool.ts](../examples/extensions/truncated-tool.ts) +**Examples:** [hello.ts](../examples/extensions/hello.ts), [question.ts](../examples/extensions/question.ts), [questionnaire.ts](../examples/extensions/questionnaire.ts), [todo.ts](../examples/extensions/todo.ts), [truncated-tool.ts](../examples/extensions/truncated-tool.ts) ### pi.sendMessage(message, options?) @@ -749,7 +749,7 @@ pi.sendMessage({ - `"nextTurn"` - Queued for next user prompt. Does not interrupt or trigger anything. - `triggerTurn: true` - If agent is idle, trigger an LLM response immediately. Only applies to `"steer"` and `"followUp"` modes (ignored for `"nextTurn"`). -**Examples:** [file-trigger.ts](../examples/extensions/file-trigger.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts) +**Examples:** [file-trigger.ts](../examples/extensions/file-trigger.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts) ### pi.sendUserMessage(content, options?) @@ -796,7 +796,7 @@ pi.on("session_start", async (_event, ctx) => { }); ``` -**Examples:** [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts), [snake.ts](../examples/extensions/snake.ts), [tools.ts](../examples/extensions/tools.ts) +**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [snake.ts](../examples/extensions/snake.ts), [tools.ts](../examples/extensions/tools.ts) ### pi.setSessionName(name) @@ -831,7 +831,7 @@ pi.registerCommand("stats", { }); ``` -**Examples:** [custom-footer.ts](../examples/extensions/custom-footer.ts), [custom-header.ts](../examples/extensions/custom-header.ts), [handoff.ts](../examples/extensions/handoff.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [send-user-message.ts](../examples/extensions/send-user-message.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts) +**Examples:** [custom-footer.ts](../examples/extensions/custom-footer.ts), [custom-header.ts](../examples/extensions/custom-header.ts), [handoff.ts](../examples/extensions/handoff.ts), [pirate.ts](../examples/extensions/pirate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [send-user-message.ts](../examples/extensions/send-user-message.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts) ### pi.registerMessageRenderer(customType, renderer) @@ -850,7 +850,7 @@ pi.registerShortcut("ctrl+shift+p", { }); ``` -**Examples:** [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts) +**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts) ### pi.registerFlag(name, options) @@ -869,7 +869,7 @@ if (pi.getFlag("--plan")) { } ``` -**Examples:** [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts) +**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts) ### pi.exec(command, args, options?) @@ -893,7 +893,7 @@ const names = all.map(t => t.name); // Just names if needed pi.setActiveTools(["read", "bash"]); // Switch to read-only ``` -**Examples:** [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts), [tools.ts](../examples/extensions/tools.ts) +**Examples:** [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [tools.ts](../examples/extensions/tools.ts) ### pi.setModel(model) @@ -1244,7 +1244,7 @@ ctx.ui.notify("Done!", "info"); // "info" | "warning" | "error" ``` **Examples:** -- `ctx.ui.select()`: [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts), [question.ts](../examples/extensions/question.ts) +- `ctx.ui.select()`: [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts), [dirty-repo-guard.ts](../examples/extensions/dirty-repo-guard.ts), [git-checkpoint.ts](../examples/extensions/git-checkpoint.ts), [permission-gate.ts](../examples/extensions/permission-gate.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [question.ts](../examples/extensions/question.ts), [questionnaire.ts](../examples/extensions/questionnaire.ts) - `ctx.ui.confirm()`: [confirm-destructive.ts](../examples/extensions/confirm-destructive.ts) - `ctx.ui.editor()`: [handoff.ts](../examples/extensions/handoff.ts) - `ctx.ui.setEditorText()`: [handoff.ts](../examples/extensions/handoff.ts), [qna.ts](../examples/extensions/qna.ts) @@ -1346,8 +1346,8 @@ ctx.ui.theme.fg("accent", "styled text"); // Access current theme ``` **Examples:** -- `ctx.ui.setStatus()`: [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts), [status-line.ts](../examples/extensions/status-line.ts) -- `ctx.ui.setWidget()`: [plan-mode.ts](../examples/extensions/plan-mode.ts) +- `ctx.ui.setStatus()`: [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [status-line.ts](../examples/extensions/status-line.ts) +- `ctx.ui.setWidget()`: [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts) - `ctx.ui.setFooter()`: [custom-footer.ts](../examples/extensions/custom-footer.ts) - `ctx.ui.setHeader()`: [custom-header.ts](../examples/extensions/custom-header.ts) - `ctx.ui.setEditorComponent()`: [modal-editor.ts](../examples/extensions/modal-editor.ts) @@ -1398,7 +1398,7 @@ const result = await ctx.ui.custom( Overlay components should define a `width` property to control their size. The overlay is centered by default. See [overlay-test.ts](../examples/extensions/overlay-test.ts) for a complete example. -**Examples:** [handoff.ts](../examples/extensions/handoff.ts), [plan-mode.ts](../examples/extensions/plan-mode.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts), [overlay-test.ts](../examples/extensions/overlay-test.ts) +**Examples:** [handoff.ts](../examples/extensions/handoff.ts), [plan-mode/index.ts](../examples/extensions/plan-mode/index.ts), [preset.ts](../examples/extensions/preset.ts), [qna.ts](../examples/extensions/qna.ts), [snake.ts](../examples/extensions/snake.ts), [summarize.ts](../examples/extensions/summarize.ts), [todo.ts](../examples/extensions/todo.ts), [tools.ts](../examples/extensions/tools.ts), [overlay-test.ts](../examples/extensions/overlay-test.ts) ### Custom Editor diff --git a/packages/coding-agent/examples/README.md b/packages/coding-agent/examples/README.md index 40183e56..ac632e43 100644 --- a/packages/coding-agent/examples/README.md +++ b/packages/coding-agent/examples/README.md @@ -10,9 +10,12 @@ Programmatic usage via `createAgentSession()`. Shows how to customize models, pr ### [extensions/](extensions/) Example extensions demonstrating: - Lifecycle event handlers (tool interception, safety gates, context modifications) -- Custom tools (todo lists, subagents) +- Custom tools (todo lists, questions, subagents, output truncation) - Commands and keyboard shortcuts -- External integrations (git, file watchers) +- Custom UI (footers, headers, editors, overlays) +- Git integration (checkpoints, auto-commit) +- System prompt modifications and custom compaction +- External integrations (SSH, file watchers, system theme sync) ## Documentation diff --git a/packages/coding-agent/examples/extensions/README.md b/packages/coding-agent/examples/extensions/README.md index 9ab2ef9c..7353ea61 100644 --- a/packages/coding-agent/examples/extensions/README.md +++ b/packages/coding-agent/examples/extensions/README.md @@ -30,8 +30,10 @@ cp permission-gate.ts ~/.pi/agent/extensions/ |-----------|-------------| | `todo.ts` | Todo list tool + `/todos` command with custom rendering and state persistence | | `hello.ts` | Minimal custom tool example | -| `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions | +| `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions with custom UI | +| `questionnaire.ts` | Multi-question input with tab bar navigation between questions | | `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) | +| `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) | | `ssh.ts` | Delegate all tools to a remote machine via SSH using pluggable operations | | `subagent/` | Delegate tasks to specialized subagents with isolated context windows | @@ -40,17 +42,24 @@ cp permission-gate.ts ~/.pi/agent/extensions/ | Extension | Description | |-----------|-------------| | `preset.ts` | Named presets for model, thinking level, tools, and instructions via `--preset` flag and `/preset` command | -| `plan-mode.ts` | Claude Code-style plan mode for read-only exploration with `/plan` command | +| `plan-mode/` | Claude Code-style plan mode for read-only exploration with `/plan` command and step tracking | | `tools.ts` | Interactive `/tools` command to enable/disable tools with session persistence | | `handoff.ts` | Transfer context to a new focused session via `/handoff ` | | `qna.ts` | Extracts questions from last response into editor via `ctx.ui.setEditorText()` | | `status-line.ts` | Shows turn progress in footer via `ctx.ui.setStatus()` with themed colors | +| `model-status.ts` | Shows model changes in status bar via `model_select` hook | | `snake.ts` | Snake game with custom UI, keyboard handling, and session persistence | | `send-user-message.ts` | Demonstrates `pi.sendUserMessage()` for sending user messages from extensions | | `timed-confirm.ts` | Demonstrates AbortSignal for auto-dismissing `ctx.ui.confirm()` and `ctx.ui.select()` dialogs | | `modal-editor.ts` | Custom vim-like modal editor via `ctx.ui.setEditorComponent()` | +| `rainbow-editor.ts` | Animated rainbow text effect via custom editor | | `notify.ts` | Desktop notifications via OSC 777 when agent finishes (Ghostty, iTerm2, WezTerm) | -| `summarize.ts` | Summarize the conversation so far with GPT-5.2, and show in a nice transient UI | +| `summarize.ts` | Summarize conversation with GPT-5.2 and show in transient UI | +| `custom-footer.ts` | Custom footer with git branch and token stats via `ctx.ui.setFooter()` | +| `custom-header.ts` | Custom header via `ctx.ui.setHeader()` | +| `overlay-test.ts` | Test overlay rendering with inline text inputs | +| `shutdown-command.ts` | Adds `/quit` command demonstrating `ctx.shutdown()` | +| `interactive-shell.ts` | Run interactive commands (vim, htop) with full terminal via `user_bash` hook | ### Git Integration @@ -64,8 +73,15 @@ cp permission-gate.ts ~/.pi/agent/extensions/ | Extension | Description | |-----------|-------------| | `pirate.ts` | Demonstrates `systemPromptAppend` to dynamically modify system prompt | +| `claude-rules.ts` | Scans `.claude/rules/` folder and lists rules in system prompt | | `custom-compaction.ts` | Custom compaction that summarizes entire conversation | +### System Integration + +| Extension | Description | +|-----------|-------------| +| `mac-system-theme.ts` | Syncs pi theme with macOS dark/light mode | + ### External Dependencies | Extension | Description |