Files
oh-my-pi/packages/coding-agent/examples/extensions
can1357 2867e1f4e3 feat(deps): added pi.zod exports and removed TypeBox package exports
- Added canonical `pi.zod` schema API exports and removed TypeBox package exports/imports.
- Migrated Tool schema typing from TypeBox to shared `TSchema`/Zod flow with legacy TypeBox compatibility.
- Updated AI provider adapters and MCP/agent builders to convert tool params through `toolWireSchema()`.
- Reworked schema validation from AJV to Zod-safe parsing with `fromTypeBox`, `toolWireSchema`, and meta schema checks.
2026-05-15 14:46:54 +02:00
..

Extension Examples

Example extensions for pi-coding-agent.

Usage

# Load an extension with --extension flag
pi --extension examples/extensions/permission-gate.ts

# Or copy to extensions directory for auto-discovery
cp permission-gate.ts ~/.omp/agent/extensions/

Examples

Lifecycle & Safety

Extension Description
permission-gate.ts Prompts for confirmation before dangerous bash commands (rm -rf, sudo, etc.)
protected-paths.ts Blocks writes to protected paths (.env, .git/, node_modules/)
confirm-destructive.ts Confirms before destructive session actions (clear, switch, branch)
dirty-repo-guard.ts Prevents session changes with uncommitted git changes

Custom Tools

Extension Description
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
subagent/ Delegate tasks to specialized subagents with isolated context windows

Commands & UI

Extension Description
plan-mode.ts Claude Code-style plan mode for read-only exploration with /plan command
tools.ts Interactive /tools command to enable/disable tools with session persistence
handoff.ts Transfer context to a new focused session via /handoff <goal>
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
snake.ts Snake game with custom UI, keyboard handling, and session persistence

Git Integration

Extension Description
git-checkpoint.ts Creates git stash checkpoints at each turn for code restoration on branch
auto-commit-on-exit.ts Auto-commits on exit using last assistant message for commit message

System Prompt & Compaction

Extension Description
pirate.ts Demonstrates systemPromptAppend to dynamically modify system prompt
custom-compaction.ts Custom compaction that summarizes entire conversation

External Dependencies

Extension Description
chalk-logger.ts Uses chalk from parent node_modules (demonstrates jiti module resolution)
with-deps/ Extension with its own package.json and dependencies
file-trigger.ts Watches a trigger file and injects contents into conversation

Writing Extensions

See docs/extensions.md for full documentation.

import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";

export default function (pi: ExtensionAPI) {
	const z = pi.zod;

	// Subscribe to lifecycle events
	pi.on("tool_call", async (event, ctx) => {
		if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
			const ok = await ctx.ui.confirm("Dangerous!", "Allow rm -rf?");
			if (!ok) return { block: true, reason: "Blocked by user" };
		}
	});

	// Register custom tools
	pi.registerTool({
		name: "greet",
		label: "Greeting",
		description: "Generate a greeting",
		parameters: z.object({
			name: z.string().describe("Name to greet"),
		}),
		async execute(toolCallId, params, onUpdate, ctx, signal) {
			return {
				content: [{ type: "text", text: `Hello, ${params.name}!` }],
				details: {},
			};
		},
	});

	// Register commands
	pi.registerCommand("hello", {
		description: "Say hello",
		handler: async (args, ctx) => {
			ctx.ui.notify("Hello!", "info");
		},
	});
}

Legacy TypeBox-style schemas (pi.typebox) remain available for older extensions and are backed by a tiny Zod-shim — prefer pi.zod directly for new code.

const { Type } = pi.typebox;
parameters: Type.Object({ name: Type.String() });

Key Patterns

Use StringEnum for discriminated string tool args (required for Google API compatibility):

import { StringEnum } from "@oh-my-pi/pi-ai";

const { z } = pi.zod;

// Good — Google-safe enum wiring
parameters: z.object({
	action: StringEnum(["list", "add"] as const),
});

// Avoid raw union-of-literals patterns that don't degrade well for strict JSON Schema providers

State persistence via details:

// Store state in tool result details for proper branching support
return {
	content: [{ type: "text", text: "Done" }],
	details: { todos: [...todos], nextId }, // Persisted in session
};

// Reconstruct on session events
pi.on("session_start", async (_event, ctx) => {
	for (const entry of ctx.sessionManager.getBranch()) {
		if (entry.type === "message" && entry.message.toolName === "my_tool") {
			const details = entry.message.details;
			// Reconstruct state from details
		}
	}
});