# Pi TUI patterns

> 64 terminal UI patterns for Pi extensions, read from the source of Nico Bailon's public repos. Each pattern has GoF-style notes, frames rendered at 40, 60, 80 and 120 columns in dark and light themes, and links to the code it came from.

Every page on this site has a Markdown twin, and every pattern has a JSON record. You never need to parse HTML here. Every page URL answers in Markdown by default and in HTML when you ask for `text/html`.

## Read this site

- [Pattern index](https://pi-tui.ratstack.sh/patterns.md): every pattern by family and category, with its intent
- [Full corpus](https://pi-tui.ratstack.sh/llms-full.txt): every pattern's full text in one response
- [Pattern data](https://pi-tui.ratstack.sh/patterns.json): the index as JSON, with each pattern's page, Markdown and JSON URLs
- [Pattern schema](https://pi-tui.ratstack.sh/schema/pattern.schema.json): JSON Schema for each `/patterns/<id>.json` record
- [Skill: build a Pi TUI component](https://pi-tui.ratstack.sh/skills/build-pi-tui-component.md): pick a pattern, apply it with Pi's APIs, and check it at four widths in both themes
- [Research overview](https://pi-tui.ratstack.sh/index.md): where the patterns came from, what Nico built into Pi, and the method
- [HTTP API](https://pi-tui.ratstack.sh/openapi.json): every tool as `POST /api/<name>`, with inputs, outputs and errors
- [MCP server](https://pi-tui.ratstack.sh/mcp): the same tools over MCP, with discovery at [/.well-known/mcp.json](https://pi-tui.ratstack.sh/.well-known/mcp.json)
- [Sitemap](https://pi-tui.ratstack.sh/sitemap.xml): every HTML page, Markdown twin and JSON file

## Choose the next action

1. Find a pattern by job: `search({ query: "scrolling list with search", limit: 5 })`. Filter with `family` or `category`; `list({})` returns the valid ids.
2. Read it: `read({ id: "hinge-panel" })`, or fetch `/patterns/<id>.md`. Its "For agents" section says when to choose it over its neighbours and what to check.
3. Follow it: `related({ id })` lists the patterns it names and the patterns that name it.
4. Check its states: `states({ id, width: 40, theme: "dark" })` returns each state's frames and every check verdict with its evidence.
5. Combine steps: `execute` runs one short program that calls the tools above, so a search and a read cost one request.

To build a component, load the [skill](https://pi-tui.ratstack.sh/skills/build-pi-tui-component.md) first.

## Connect with MCP

Point any MCP client at `https://pi-tui.ratstack.sh/mcp`. Protocol 2026-07-28 is stateless and has no `initialize` handshake: every request sends `MCP-Protocol-Version`, `Mcp-Method`, and the `params._meta` block shown here.

```sh
curl --request POST 'https://pi-tui.ratstack.sh/mcp' \
  --header 'accept: application/json, text/event-stream' \
  --header 'content-type: application/json' \
  --header 'MCP-Protocol-Version: 2026-07-28' \
  --header 'Mcp-Method: tools/list' \
  --data '{"id":"pi-tui-tools","jsonrpc":"2.0","method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/clientCapabilities":{},"io.modelcontextprotocol/clientInfo":{"name":"pi-tui-example","version":"0.1.0"},"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}'
```

Older clients (2025-11-25 back to 2024-11-05) send `initialize` as usual. Each one gets its own session, held by a Durable Object so it survives between requests.

Each IP may make 120 API or MCP requests per 60 seconds. `execute` also allows 6 calls per IP and 300 total calls per 60 seconds. Cloudflare counts these limits separately in each location.

## Run code: one program instead of several calls

`POST /api/execute` or the MCP `execute` tool runs the `code` value as the body of an async function in a sandbox with no network. `return` sets `result`, and `console.log` output appears in `logs`.

```js
const found = await tools.search({ query: "overlay focus", limit: 1 });
const pattern = await tools.read({ id: found.matches[0].id });
return { id: pattern.id, intent: pattern.intent, states: pattern.states.length };
```

```sh
curl --request POST 'https://pi-tui.ratstack.sh/api/execute' \
  --header 'content-type: application/json' \
  --data '{"code":"const r = await tools.search({ query: \"status line\", limit: 1 }); return r.matches[0].id"}'
```

## Families

- [Structural](https://pi-tui.ratstack.sh/patterns.md#structural) (14 patterns): Fit and compose terminal surfaces without combining their separate content owners.
- [Behavioral](https://pi-tui.ratstack.sh/patterns.md#behavioral) (24 patterns): Route selection, input, focus and timing through explicit interaction state.
- [Lifecycle](https://pi-tui.ratstack.sh/patterns.md#lifecycle) (11 patterns): Tie UI, drafts, resources and saved state to their owning interaction or session.
- [Presentation](https://pi-tui.ratstack.sh/patterns.md#presentation) (15 patterns): Project, cache and style visible output without changing the underlying work.

## Categories

- Layout (4): [Column Gauge](https://pi-tui.ratstack.sh/patterns/column-gauge.md), [Hinge Panel](https://pi-tui.ratstack.sh/patterns/hinge-panel.md), [Section Loom](https://pi-tui.ratstack.sh/patterns/section-loom.md), [Status Ribbon](https://pi-tui.ratstack.sh/patterns/status-ribbon.md)
- Lists and pickers (9): [Row Window](https://pi-tui.ratstack.sh/patterns/row-window.md), [Detail Lens](https://pi-tui.ratstack.sh/patterns/detail-lens.md), [Tab Deck](https://pi-tui.ratstack.sh/patterns/tab-deck.md), [Branch Fold](https://pi-tui.ratstack.sh/patterns/branch-fold.md), [Match Ladder](https://pi-tui.ratstack.sh/patterns/match-ladder.md), [Shrinking Sieve](https://pi-tui.ratstack.sh/patterns/shrinking-sieve.md), [Identity Anchor](https://pi-tui.ratstack.sh/patterns/identity-anchor.md), [Preview Basket](https://pi-tui.ratstack.sh/patterns/preview-basket.md), [Lazy Peek](https://pi-tui.ratstack.sh/patterns/lazy-peek.md)
- Overlays and dialogs (9): [Shared Shell](https://pi-tui.ratstack.sh/patterns/shared-shell.md), [Warning Gate](https://pi-tui.ratstack.sh/patterns/warning-gate.md), [Abort Lantern](https://pi-tui.ratstack.sh/patterns/abort-lantern.md), [Dialog Fuse](https://pi-tui.ratstack.sh/patterns/dialog-fuse.md), [Abort Tether](https://pi-tui.ratstack.sh/patterns/abort-tether.md), [Idle Fuse](https://pi-tui.ratstack.sh/patterns/idle-fuse.md), [Settings Bench](https://pi-tui.ratstack.sh/patterns/settings-bench.md), [Action Sieve](https://pi-tui.ratstack.sh/patterns/action-sieve.md), [Done Contract](https://pi-tui.ratstack.sh/patterns/done-contract.md)
- Status and widgets (6): [Keyed Slot](https://pi-tui.ratstack.sh/patterns/keyed-slot.md), [Signal Pair](https://pi-tui.ratstack.sh/patterns/signal-pair.md), [Widget Dock](https://pi-tui.ratstack.sh/patterns/widget-dock.md), [Result Relay](https://pi-tui.ratstack.sh/patterns/result-relay.md), [Notice Fuse](https://pi-tui.ratstack.sh/patterns/notice-fuse.md), [Work Caption](https://pi-tui.ratstack.sh/patterns/work-caption.md)
- Editors and drafts (5): [Editor Steward](https://pi-tui.ratstack.sh/patterns/editor-steward.md), [Retry Buffer](https://pi-tui.ratstack.sh/patterns/retry-buffer.md), [Draft Fence](https://pi-tui.ratstack.sh/patterns/draft-fence.md), [Prompt Trail](https://pi-tui.ratstack.sh/patterns/prompt-trail.md), [Draft Return](https://pi-tui.ratstack.sh/patterns/draft-return.md)
- Keys and focus (8): [Action Compass](https://pi-tui.ratstack.sh/patterns/action-compass.md), [Input Switch](https://pi-tui.ratstack.sh/patterns/input-switch.md), [Focus Baton](https://pi-tui.ratstack.sh/patterns/focus-baton.md), [Ghost Overlay](https://pi-tui.ratstack.sh/patterns/ghost-overlay.md), [Field Baton](https://pi-tui.ratstack.sh/patterns/field-baton.md), [Control Baton](https://pi-tui.ratstack.sh/patterns/control-baton.md), [Pause Latch](https://pi-tui.ratstack.sh/patterns/pause-latch.md), [Input Lease](https://pi-tui.ratstack.sh/patterns/input-lease.md)
- Rendering and performance (4): [Tail Anchor](https://pi-tui.ratstack.sh/patterns/tail-anchor.md), [Refresh Lease](https://pi-tui.ratstack.sh/patterns/refresh-lease.md), [Render Funnel](https://pi-tui.ratstack.sh/patterns/render-funnel.md), [Late Paint](https://pi-tui.ratstack.sh/patterns/late-paint.md)
- Tool and message output (8): [Detail Fold](https://pi-tui.ratstack.sh/patterns/detail-fold.md), [Call Capsule](https://pi-tui.ratstack.sh/patterns/call-capsule.md), [Hinge Diff](https://pi-tui.ratstack.sh/patterns/hinge-diff.md), [Word Spotlight](https://pi-tui.ratstack.sh/patterns/word-spotlight.md), [Error Digest](https://pi-tui.ratstack.sh/patterns/error-digest.md), [Renderer Chain](https://pi-tui.ratstack.sh/patterns/renderer-chain.md), [Message Fold](https://pi-tui.ratstack.sh/patterns/message-fold.md), [Image Parachute](https://pi-tui.ratstack.sh/patterns/image-parachute.md)
- Theming (2): [Colour Sentry](https://pi-tui.ratstack.sh/patterns/colour-sentry.md), [Palette Deck](https://pi-tui.ratstack.sh/patterns/palette-deck.md)
- Lifecycle and mounting (8): [Elastic Overlay](https://pi-tui.ratstack.sh/patterns/elastic-overlay.md), [Event Relay](https://pi-tui.ratstack.sh/patterns/event-relay.md), [Process Shell](https://pi-tui.ratstack.sh/patterns/process-shell.md), [Output Vault](https://pi-tui.ratstack.sh/patterns/output-vault.md), [Deferred Crest](https://pi-tui.ratstack.sh/patterns/deferred-crest.md), [Session Memento](https://pi-tui.ratstack.sh/patterns/session-memento.md), [Mode Fence](https://pi-tui.ratstack.sh/patterns/mode-fence.md), [Snapshot Lens](https://pi-tui.ratstack.sh/patterns/snapshot-lens.md)
- Animation (1): [Tick Heart](https://pi-tui.ratstack.sh/patterns/tick-heart.md)
