# Custom Extensions

Local TypeScript extensions in `extensions/` — the custom logic that makes this config unique.

> 📋 **Architecture Decision Records:** Each extension has a lightweight ADR in
> [`docs/adr/`](adr/) documenting the problem solved, alternatives considered, and
> evidence from harness research. See the [ADR index](adr/README.md).

## Extension List

Each extension lives in its own folder under `extensions/` with an `index.ts` entry point.

| Extension               | What it does                                                                                                                                                                       |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`enhanced-edit/`**    | Replaces the built-in `edit` tool with 9-level fuzzy matching, atomic `multi_edit` batching, and auto-injected LSP diagnostics                                                     |
| **`toon-transformer/`** | Converts JSON tool output to TOON format — saves ~40–60% tokens on structured data                                                                                                 |
| **`project-context/`**  | Auto-loads `AGENTS.md` / `CONTEXT.md` / `.opencode` docs from your project                                                                                                         |
| **`questionnaire/`**    | Structured multi-question UI with tab navigation                                                                                                                                   |
| **`todo/`**             | Persistent todo list tool                                                                                                                                                          |
| **`cosmetics/`**        | Unified indicator + splash screen with extensible persona system. Default: Kirby (Juergen mode). One event loop, multiple skins.                                                   |
| **`clipboard/`**        | Multi-slot session scratchpad — `clipboard_write`/`clipboard_read` for caching derived values (shell commands, paths, expressions)                                                 |
| **`code-intel/`**       | `inspect_code`, `find_symbol`, `search_config` — tree-sitter outlines (`outline.ts` + `format-outline.ts`), function extraction with dedup, definition/usage search, config search |

## Shared Modules

`extensions/shared/` contains reusable modules used across extensions:

| Module             | Purpose                                                       |
| ------------------ | ------------------------------------------------------------- |
| `design-system.ts` | Barrel re-export (animations, colors, glyphs, kirby, text)    |
| `animations.ts`    | Animation frame utilities, indicators, progress bars          |
| `colors.ts`        | Color constants, palettes, wavy gradient helpers              |
| `glyphs.ts`        | Unicode glyph constants, box drawing characters               |
| `kirby.ts`         | Kirby ASCII art frames, status types, animation state         |
| `text.ts`          | Text formatting, diff preview, table utilities                |
| `diff-renderer.ts` | Diff rendering with line number gutter (used by text.ts)      |
| `noise-dirs.ts`    | Noise directory/file exclusions (used by code-intel)          |
| `lang-registry.ts` | File extension → language ID mapping (used by code-intel)     |
| `exec.ts`          | Shell exec wrapper, rg binary resolution (used by code-intel) |

Extension-specific modules that were previously in `shared/` are now in their owning extension folders:

- `questionnaire/types.ts`, `questionnaire/ui.ts`, `questionnaire/component.ts`
- `todo/component.ts`, `todo/handlers.ts`
- `toon-transformer/state.ts`, `toon-transformer/toon-transformer-core.ts`, `toon-transformer/toon-validator.ts`

## Writing Extensions

Extensions export a default function receiving `ExtensionAPI`:

```typescript
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

export default function (pi: ExtensionAPI) {
  // Register a tool
  pi.registerTool({
    name: "my-tool",
    description: "...",
    parameters: {},
    execute: handler,
  });

  // Register a slash command
  pi.registerCommand("cmd", { description: "...", execute: handler });

  // Lifecycle hooks
  pi.on("turn_start", async (event, ctx) => {});
  pi.on("before_agent_start", async (event, ctx) => {});

  // Session access
  pi.appendEntry(entry);
  // ctx.sessionManager in event handlers
}
```

**To add an extension:** Create `extensions/my-ext/` with an `index.ts` entry point and a minimal `package.json`:

```json
{
  "name": "pi-my-ext-extension",
  "version": "1.0.0",
  "type": "module",
  "pi": {
    "extensions": ["./index.ts"]
  }
}
```

**To add shared code:** Put it in `extensions/shared/` and import as `../shared/module.js` from within an extension folder.
