{
  "$schema": "https://pi-tui.ratstack.sh/schema/patterns.schema.json",
  "categories": [
    {
      "id": "layout",
      "label": "Layout"
    },
    {
      "id": "lists",
      "label": "Lists and pickers"
    },
    {
      "id": "dialogs",
      "label": "Overlays and dialogs"
    },
    {
      "id": "status",
      "label": "Status and widgets"
    },
    {
      "id": "editors",
      "label": "Editors and drafts"
    },
    {
      "id": "keys",
      "label": "Keys and focus"
    },
    {
      "id": "rendering",
      "label": "Rendering and performance"
    },
    {
      "id": "tools",
      "label": "Tool and message output"
    },
    {
      "id": "themes",
      "label": "Theming"
    },
    {
      "id": "lifecycle",
      "label": "Lifecycle and mounting"
    },
    {
      "id": "animation",
      "label": "Animation"
    }
  ],
  "count": 64,
  "families": [
    {
      "categories": [
        {
          "id": "layout",
          "label": "Layout",
          "patterns": [
            "column-gauge",
            "hinge-panel",
            "section-loom",
            "status-ribbon"
          ]
        },
        {
          "id": "lists",
          "label": "Lists and pickers",
          "patterns": [
            "row-window",
            "detail-lens",
            "tab-deck",
            "branch-fold"
          ]
        },
        {
          "id": "dialogs",
          "label": "Overlays and dialogs",
          "patterns": [
            "shared-shell"
          ]
        },
        {
          "id": "status",
          "label": "Status and widgets",
          "patterns": [
            "keyed-slot",
            "signal-pair",
            "widget-dock"
          ]
        },
        {
          "id": "editors",
          "label": "Editors and drafts",
          "patterns": [
            "editor-steward"
          ]
        },
        {
          "id": "lifecycle",
          "label": "Lifecycle and mounting",
          "patterns": [
            "elastic-overlay"
          ]
        }
      ],
      "id": "structural",
      "intent": "Fit and compose terminal surfaces without combining their separate content owners.",
      "label": "Structural"
    },
    {
      "categories": [
        {
          "id": "lists",
          "label": "Lists and pickers",
          "patterns": [
            "match-ladder",
            "shrinking-sieve",
            "identity-anchor",
            "preview-basket"
          ]
        },
        {
          "id": "dialogs",
          "label": "Overlays and dialogs",
          "patterns": [
            "warning-gate",
            "abort-lantern",
            "dialog-fuse",
            "abort-tether",
            "idle-fuse",
            "settings-bench",
            "action-sieve"
          ]
        },
        {
          "id": "editors",
          "label": "Editors and drafts",
          "patterns": [
            "retry-buffer",
            "draft-fence",
            "prompt-trail"
          ]
        },
        {
          "id": "keys",
          "label": "Keys and focus",
          "patterns": [
            "action-compass",
            "input-switch",
            "focus-baton",
            "ghost-overlay",
            "field-baton",
            "control-baton",
            "pause-latch"
          ]
        },
        {
          "id": "rendering",
          "label": "Rendering and performance",
          "patterns": [
            "tail-anchor"
          ]
        },
        {
          "id": "lifecycle",
          "label": "Lifecycle and mounting",
          "patterns": [
            "event-relay"
          ]
        },
        {
          "id": "animation",
          "label": "Animation",
          "patterns": [
            "tick-heart"
          ]
        }
      ],
      "id": "behavioral",
      "intent": "Route selection, input, focus and timing through explicit interaction state.",
      "label": "Behavioral"
    },
    {
      "categories": [
        {
          "id": "dialogs",
          "label": "Overlays and dialogs",
          "patterns": [
            "done-contract"
          ]
        },
        {
          "id": "status",
          "label": "Status and widgets",
          "patterns": [
            "result-relay",
            "notice-fuse"
          ]
        },
        {
          "id": "editors",
          "label": "Editors and drafts",
          "patterns": [
            "draft-return"
          ]
        },
        {
          "id": "keys",
          "label": "Keys and focus",
          "patterns": [
            "input-lease"
          ]
        },
        {
          "id": "rendering",
          "label": "Rendering and performance",
          "patterns": [
            "refresh-lease"
          ]
        },
        {
          "id": "lifecycle",
          "label": "Lifecycle and mounting",
          "patterns": [
            "process-shell",
            "output-vault",
            "deferred-crest",
            "session-memento",
            "mode-fence"
          ]
        }
      ],
      "id": "lifecycle",
      "intent": "Tie UI, drafts, resources and saved state to their owning interaction or session.",
      "label": "Lifecycle"
    },
    {
      "categories": [
        {
          "id": "lists",
          "label": "Lists and pickers",
          "patterns": [
            "lazy-peek"
          ]
        },
        {
          "id": "status",
          "label": "Status and widgets",
          "patterns": [
            "work-caption"
          ]
        },
        {
          "id": "rendering",
          "label": "Rendering and performance",
          "patterns": [
            "render-funnel",
            "late-paint"
          ]
        },
        {
          "id": "tools",
          "label": "Tool and message output",
          "patterns": [
            "detail-fold",
            "call-capsule",
            "hinge-diff",
            "word-spotlight",
            "error-digest",
            "renderer-chain",
            "message-fold",
            "image-parachute"
          ]
        },
        {
          "id": "themes",
          "label": "Theming",
          "patterns": [
            "colour-sentry",
            "palette-deck"
          ]
        },
        {
          "id": "lifecycle",
          "label": "Lifecycle and mounting",
          "patterns": [
            "snapshot-lens"
          ]
        }
      ],
      "id": "presentation",
      "intent": "Project, cache and style visible output without changing the underlying work.",
      "label": "Presentation"
    }
  ],
  "generated": "2026-10-05T22:05:23.283Z",
  "links": {
    "agentGuide": "https://pi-tui.ratstack.sh/llms.txt",
    "corpus": "https://pi-tui.ratstack.sh/llms-full.txt",
    "index": "https://pi-tui.ratstack.sh/patterns.md",
    "schema": "https://pi-tui.ratstack.sh/schema/pattern.schema.json",
    "sitemap": "https://pi-tui.ratstack.sh/sitemap.xml",
    "skill": "https://pi-tui.ratstack.sh/skills/build-pi-tui-component.md"
  },
  "patterns": [
    {
      "aka": [
        "Display-column fitting"
      ],
      "category": "layout",
      "family": "structural",
      "id": "column-gauge",
      "intent": "Fit styled text to terminal columns before padding or framing it.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/column-gauge.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/column-gauge.md",
      "name": "Column Gauge",
      "url": "https://pi-tui.ratstack.sh/patterns/column-gauge/"
    },
    {
      "aka": [
        "Responsive panel"
      ],
      "category": "layout",
      "family": "structural",
      "id": "hinge-panel",
      "intent": "Switch between side-by-side and stacked sections as available space changes.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/hinge-panel.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/hinge-panel.md",
      "name": "Hinge Panel",
      "url": "https://pi-tui.ratstack.sh/patterns/hinge-panel/"
    },
    {
      "aka": [
        "Section composition"
      ],
      "category": "layout",
      "family": "structural",
      "id": "section-loom",
      "intent": "Compose a dashboard from focused render helpers under one layout budget.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/section-loom.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/section-loom.md",
      "name": "Section Loom",
      "url": "https://pi-tui.ratstack.sh/patterns/section-loom/"
    },
    {
      "aka": [
        "Footer segments"
      ],
      "category": "layout",
      "family": "structural",
      "id": "status-ribbon",
      "intent": "Compose a footer from independently visible and measured status segments.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/status-ribbon.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/status-ribbon.md",
      "name": "Status Ribbon",
      "url": "https://pi-tui.ratstack.sh/patterns/status-ribbon/"
    },
    {
      "aka": [
        "Windowed list"
      ],
      "category": "lists",
      "family": "structural",
      "id": "row-window",
      "intent": "Keep the selected item inside a bounded moving list window.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/row-window.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/row-window.md",
      "name": "Row Window",
      "url": "https://pi-tui.ratstack.sh/patterns/row-window/"
    },
    {
      "aka": [
        "List-detail view"
      ],
      "category": "lists",
      "family": "structural",
      "id": "detail-lens",
      "intent": "Derive a selected item's detail sections from a read-only snapshot.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/detail-lens.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/detail-lens.md",
      "name": "Detail Lens",
      "url": "https://pi-tui.ratstack.sh/patterns/detail-lens/"
    },
    {
      "aka": [
        "Tabbed view"
      ],
      "category": "lists",
      "family": "structural",
      "id": "tab-deck",
      "intent": "Keep separate keyboard-navigable data views behind a tab strip.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/tab-deck.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/tab-deck.md",
      "name": "Tab Deck",
      "url": "https://pi-tui.ratstack.sh/patterns/tab-deck/"
    },
    {
      "aka": [
        "Foldable tree"
      ],
      "category": "lists",
      "family": "structural",
      "id": "branch-fold",
      "intent": "Retain validated fold identifiers while navigating a session tree.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/branch-fold.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/branch-fold.md",
      "name": "Branch Fold",
      "url": "https://pi-tui.ratstack.sh/patterns/branch-fold/"
    },
    {
      "aka": [
        "Modal frame"
      ],
      "category": "dialogs",
      "family": "structural",
      "id": "shared-shell",
      "intent": "Wrap specialized dialog content in a shared themed frame.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/shared-shell.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/shared-shell.md",
      "name": "Shared Shell",
      "url": "https://pi-tui.ratstack.sh/patterns/shared-shell/"
    },
    {
      "aka": [
        "Keyed status slot"
      ],
      "category": "status",
      "family": "structural",
      "id": "keyed-slot",
      "intent": "Publish and clear compact state under one stable footer key.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/keyed-slot.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/keyed-slot.md",
      "name": "Keyed Slot",
      "url": "https://pi-tui.ratstack.sh/patterns/keyed-slot/"
    },
    {
      "aka": [
        "Status-widget pair"
      ],
      "category": "status",
      "family": "structural",
      "id": "signal-pair",
      "intent": "Pair a compact footer signal with a structured near-editor widget.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/signal-pair.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/signal-pair.md",
      "name": "Signal Pair",
      "url": "https://pi-tui.ratstack.sh/patterns/signal-pair/"
    },
    {
      "aka": [
        "Keyed widget"
      ],
      "category": "status",
      "family": "structural",
      "id": "widget-dock",
      "intent": "Mount and replace auxiliary content under a stable widget key.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/widget-dock.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/widget-dock.md",
      "name": "Widget Dock",
      "url": "https://pi-tui.ratstack.sh/patterns/widget-dock/"
    },
    {
      "aka": [
        "Single-owner editor"
      ],
      "category": "editors",
      "family": "structural",
      "id": "editor-steward",
      "intent": "Compose editor enhancements behind one replacement factory.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/editor-steward.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/editor-steward.md",
      "name": "Editor Steward",
      "url": "https://pi-tui.ratstack.sh/patterns/editor-steward/"
    },
    {
      "aka": [
        "Responsive overlay"
      ],
      "category": "lifecycle",
      "family": "structural",
      "id": "elastic-overlay",
      "intent": "Resolve overlay size and placement from current terminal dimensions.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/elastic-overlay.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/elastic-overlay.md",
      "name": "Elastic Overlay",
      "url": "https://pi-tui.ratstack.sh/patterns/elastic-overlay/"
    },
    {
      "aka": [
        "Ranked picker"
      ],
      "category": "lists",
      "family": "behavioral",
      "id": "match-ladder",
      "intent": "Rank matching options across weighted label and description fields.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/match-ladder.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/match-ladder.md",
      "name": "Match Ladder",
      "url": "https://pi-tui.ratstack.sh/patterns/match-ladder/"
    },
    {
      "aka": [
        "Incremental filter"
      ],
      "category": "lists",
      "family": "behavioral",
      "id": "shrinking-sieve",
      "intent": "Narrow existing candidates while a search query grows.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/shrinking-sieve.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/shrinking-sieve.md",
      "name": "Shrinking Sieve",
      "url": "https://pi-tui.ratstack.sh/patterns/shrinking-sieve/"
    },
    {
      "aka": [
        "Stable async selection"
      ],
      "category": "lists",
      "family": "behavioral",
      "id": "identity-anchor",
      "intent": "Retain the highlighted item's identity as asynchronous results arrive.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/identity-anchor.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/identity-anchor.md",
      "name": "Identity Anchor",
      "url": "https://pi-tui.ratstack.sh/patterns/identity-anchor/"
    },
    {
      "aka": [
        "Multi-select preview"
      ],
      "category": "lists",
      "family": "behavioral",
      "id": "preview-basket",
      "intent": "Keep selection separate from thumbnail loading and zoom inspection.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/preview-basket.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/preview-basket.md",
      "name": "Preview Basket",
      "url": "https://pi-tui.ratstack.sh/patterns/preview-basket/"
    },
    {
      "aka": [
        "Consequence confirmation"
      ],
      "category": "dialogs",
      "family": "behavioral",
      "id": "warning-gate",
      "intent": "Follow a consequential selection with a separate warning confirmation.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/warning-gate.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/warning-gate.md",
      "name": "Warning Gate",
      "url": "https://pi-tui.ratstack.sh/patterns/warning-gate/"
    },
    {
      "aka": [
        "Cancellable loader"
      ],
      "category": "dialogs",
      "family": "behavioral",
      "id": "abort-lantern",
      "intent": "Settle foreground loading before opening a separate result view.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/abort-lantern.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/abort-lantern.md",
      "name": "Abort Lantern",
      "url": "https://pi-tui.ratstack.sh/patterns/abort-lantern/"
    },
    {
      "aka": [
        "Countdown dialog"
      ],
      "category": "dialogs",
      "family": "behavioral",
      "id": "dialog-fuse",
      "intent": "Show remaining time before a transient dialog automatically dismisses.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/dialog-fuse.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/dialog-fuse.md",
      "name": "Dialog Fuse",
      "url": "https://pi-tui.ratstack.sh/patterns/dialog-fuse/"
    },
    {
      "aka": [
        "Abortable dialog"
      ],
      "category": "dialogs",
      "family": "behavioral",
      "id": "abort-tether",
      "intent": "Tie a built-in dialog's lifetime to an operation's abort signal.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/abort-tether.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/abort-tether.md",
      "name": "Abort Tether",
      "url": "https://pi-tui.ratstack.sh/patterns/abort-tether/"
    },
    {
      "aka": [
        "Idle dismissal"
      ],
      "category": "dialogs",
      "family": "behavioral",
      "id": "idle-fuse",
      "intent": "Reset a component-owned inactivity timer after every input.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/idle-fuse.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/idle-fuse.md",
      "name": "Idle Fuse",
      "url": "https://pi-tui.ratstack.sh/patterns/idle-fuse/"
    },
    {
      "aka": [
        "Settings panel"
      ],
      "category": "dialogs",
      "family": "behavioral",
      "id": "settings-bench",
      "intent": "Keep configuration interaction separate from the live activity view.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/settings-bench.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/settings-bench.md",
      "name": "Settings Bench",
      "url": "https://pi-tui.ratstack.sh/patterns/settings-bench/"
    },
    {
      "aka": [
        "Conditional actions"
      ],
      "category": "dialogs",
      "family": "behavioral",
      "id": "action-sieve",
      "intent": "Derive dialog choices from current control and completion state.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/action-sieve.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/action-sieve.md",
      "name": "Action Sieve",
      "url": "https://pi-tui.ratstack.sh/patterns/action-sieve/"
    },
    {
      "aka": [
        "Retryable draft"
      ],
      "category": "editors",
      "family": "behavioral",
      "id": "retry-buffer",
      "intent": "Keep the local draft editable after a failed send.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/retry-buffer.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/retry-buffer.md",
      "name": "Retry Buffer",
      "url": "https://pi-tui.ratstack.sh/patterns/retry-buffer/"
    },
    {
      "aka": [
        "Staged draft"
      ],
      "category": "editors",
      "family": "behavioral",
      "id": "draft-fence",
      "intent": "Keep inline draft edits separate from the committed queue snapshot.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/draft-fence.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/draft-fence.md",
      "name": "Draft Fence",
      "url": "https://pi-tui.ratstack.sh/patterns/draft-fence/"
    },
    {
      "aka": [
        "Prompt history"
      ],
      "category": "editors",
      "family": "behavioral",
      "id": "prompt-trail",
      "intent": "Browse submitted prompts while retaining the current editor draft.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/prompt-trail.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/prompt-trail.md",
      "name": "Prompt Trail",
      "url": "https://pi-tui.ratstack.sh/patterns/prompt-trail/"
    },
    {
      "aka": [
        "Semantic key controls"
      ],
      "category": "keys",
      "family": "behavioral",
      "id": "action-compass",
      "intent": "Resolve configurable actions through injected keybindings.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/action-compass.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/action-compass.md",
      "name": "Action Compass",
      "url": "https://pi-tui.ratstack.sh/patterns/action-compass/"
    },
    {
      "aka": [
        "Submitted input interception"
      ],
      "category": "keys",
      "family": "behavioral",
      "id": "input-switch",
      "intent": "Continue, transform or handle submitted input before normal processing.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/input-switch.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/input-switch.md",
      "name": "Input Switch",
      "url": "https://pi-tui.ratstack.sh/patterns/input-switch/"
    },
    {
      "aka": [
        "Overlay focus handoff"
      ],
      "category": "keys",
      "family": "behavioral",
      "id": "focus-baton",
      "intent": "Move keyboard ownership without closing a persistent overlay.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/focus-baton.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/focus-baton.md",
      "name": "Focus Baton",
      "url": "https://pi-tui.ratstack.sh/patterns/focus-baton/"
    },
    {
      "aka": [
        "Passive overlay"
      ],
      "category": "keys",
      "family": "behavioral",
      "id": "ghost-overlay",
      "intent": "Keep an overlay visible without automatically taking keyboard focus.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/ghost-overlay.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/ghost-overlay.md",
      "name": "Ghost Overlay",
      "url": "https://pi-tui.ratstack.sh/patterns/ghost-overlay/"
    },
    {
      "aka": [
        "Field focus"
      ],
      "category": "keys",
      "family": "behavioral",
      "id": "field-baton",
      "intent": "Switch keyboard focus between a choice list and an editable task field.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/field-baton.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/field-baton.md",
      "name": "Field Baton",
      "url": "https://pi-tui.ratstack.sh/patterns/field-baton/"
    },
    {
      "aka": [
        "Human takeover"
      ],
      "category": "keys",
      "family": "behavioral",
      "id": "control-baton",
      "intent": "Pause automatic output updates while the user controls an interactive job.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/control-baton.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/control-baton.md",
      "name": "Control Baton",
      "url": "https://pi-tui.ratstack.sh/patterns/control-baton/"
    },
    {
      "aka": [
        "Pause controls"
      ],
      "category": "keys",
      "family": "behavioral",
      "id": "pause-latch",
      "intent": "Keep pause, resume and quit controls inside the component input contract.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/pause-latch.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/pause-latch.md",
      "name": "Pause Latch",
      "url": "https://pi-tui.ratstack.sh/patterns/pause-latch/"
    },
    {
      "aka": [
        "Follow-tail view"
      ],
      "category": "rendering",
      "family": "behavioral",
      "id": "tail-anchor",
      "intent": "Follow new output only while the user remains at the bottom.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/tail-anchor.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/tail-anchor.md",
      "name": "Tail Anchor",
      "url": "https://pi-tui.ratstack.sh/patterns/tail-anchor/"
    },
    {
      "aka": [
        "Event-driven view"
      ],
      "category": "lifecycle",
      "family": "behavioral",
      "id": "event-relay",
      "intent": "Update visible UI from named extension event channels.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/event-relay.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/event-relay.md",
      "name": "Event Relay",
      "url": "https://pi-tui.ratstack.sh/patterns/event-relay/"
    },
    {
      "aka": [
        "Fixed-tick view"
      ],
      "category": "animation",
      "family": "behavioral",
      "id": "tick-heart",
      "intent": "Advance local view state and request redraws on a component-owned interval.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/tick-heart.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/tick-heart.md",
      "name": "Tick Heart",
      "url": "https://pi-tui.ratstack.sh/patterns/tick-heart/"
    },
    {
      "aka": [
        "Custom completion"
      ],
      "category": "dialogs",
      "family": "lifecycle",
      "id": "done-contract",
      "intent": "Resolve each custom interaction with a typed selection or cancellation.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/done-contract.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/done-contract.md",
      "name": "Done Contract",
      "url": "https://pi-tui.ratstack.sh/patterns/done-contract/"
    },
    {
      "aka": [
        "Async result widget"
      ],
      "category": "status",
      "family": "lifecycle",
      "id": "result-relay",
      "intent": "Replace pending feedback with a persistent non-modal result widget.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/result-relay.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/result-relay.md",
      "name": "Result Relay",
      "url": "https://pi-tui.ratstack.sh/patterns/result-relay/"
    },
    {
      "aka": [
        "Expiring status"
      ],
      "category": "status",
      "family": "lifecycle",
      "id": "notice-fuse",
      "intent": "Clear a one-off keyed notice after its display interval.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/notice-fuse.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/notice-fuse.md",
      "name": "Notice Fuse",
      "url": "https://pi-tui.ratstack.sh/patterns/notice-fuse/"
    },
    {
      "aka": [
        "Draft restoration"
      ],
      "category": "editors",
      "family": "lifecycle",
      "id": "draft-return",
      "intent": "Restore the captured editor draft after a temporary submission.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/draft-return.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/draft-return.md",
      "name": "Draft Return",
      "url": "https://pi-tui.ratstack.sh/patterns/draft-return/"
    },
    {
      "aka": [
        "Temporary input listener"
      ],
      "category": "keys",
      "family": "lifecycle",
      "id": "input-lease",
      "intent": "Intercept raw terminal controls only while their owning operation is active.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/input-lease.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/input-lease.md",
      "name": "Input Lease",
      "url": "https://pi-tui.ratstack.sh/patterns/input-lease/"
    },
    {
      "aka": [
        "Owned refresh"
      ],
      "category": "rendering",
      "family": "lifecycle",
      "id": "refresh-lease",
      "intent": "Pair asynchronous refresh triggers with component-owned cleanup.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/refresh-lease.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/refresh-lease.md",
      "name": "Refresh Lease",
      "url": "https://pi-tui.ratstack.sh/patterns/refresh-lease/"
    },
    {
      "aka": [
        "Terminal process view"
      ],
      "category": "lifecycle",
      "family": "lifecycle",
      "id": "process-shell",
      "intent": "Bind a temporary terminal process view to one custom interaction.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/process-shell.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/process-shell.md",
      "name": "Process Shell",
      "url": "https://pi-tui.ratstack.sh/patterns/process-shell/"
    },
    {
      "aka": [
        "Retained job view"
      ],
      "category": "lifecycle",
      "family": "lifecycle",
      "id": "output-vault",
      "intent": "Keep completed job output available after its foreground view closes.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/output-vault.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/output-vault.md",
      "name": "Output Vault",
      "url": "https://pi-tui.ratstack.sh/patterns/output-vault/"
    },
    {
      "aka": [
        "Deferred header"
      ],
      "category": "lifecycle",
      "family": "lifecycle",
      "id": "deferred-crest",
      "intent": "Mount optional startup content only after deferred discovery remains eligible.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/deferred-crest.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/deferred-crest.md",
      "name": "Deferred Crest",
      "url": "https://pi-tui.ratstack.sh/patterns/deferred-crest/"
    },
    {
      "aka": [
        "Session-saved view"
      ],
      "category": "lifecycle",
      "family": "lifecycle",
      "id": "session-memento",
      "intent": "Reconstruct deliberate view state from typed custom session entries.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/session-memento.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/session-memento.md",
      "name": "Session Memento",
      "url": "https://pi-tui.ratstack.sh/patterns/session-memento/"
    },
    {
      "aka": [
        "Mode-aware UI"
      ],
      "category": "lifecycle",
      "family": "lifecycle",
      "id": "mode-fence",
      "intent": "Keep terminal components separate from dialog-capable and no-UI modes.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/mode-fence.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/mode-fence.md",
      "name": "Mode Fence",
      "url": "https://pi-tui.ratstack.sh/patterns/mode-fence/"
    },
    {
      "aka": [
        "Lazy preview picker"
      ],
      "category": "lists",
      "family": "presentation",
      "id": "lazy-peek",
      "intent": "Load and cache preview detail only for items the user inspects.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/lazy-peek.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/lazy-peek.md",
      "name": "Lazy Peek",
      "url": "https://pi-tui.ratstack.sh/patterns/lazy-peek/"
    },
    {
      "aka": [
        "Working message"
      ],
      "category": "status",
      "family": "presentation",
      "id": "work-caption",
      "intent": "Set task-specific text in Pi's active working indicator.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/work-caption.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/work-caption.md",
      "name": "Work Caption",
      "url": "https://pi-tui.ratstack.sh/patterns/work-caption/"
    },
    {
      "aka": [
        "Coalesced redraw"
      ],
      "category": "rendering",
      "family": "presentation",
      "id": "render-funnel",
      "intent": "Collapse bursty redraw scheduling behind one pending timer.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/render-funnel.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/render-funnel.md",
      "name": "Render Funnel",
      "url": "https://pi-tui.ratstack.sh/patterns/render-funnel/"
    },
    {
      "aka": [
        "Width-keyed cache"
      ],
      "category": "rendering",
      "family": "presentation",
      "id": "late-paint",
      "intent": "Cache plain layout by width and apply theme styling during rendering.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/late-paint.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/late-paint.md",
      "name": "Late Paint",
      "url": "https://pi-tui.ratstack.sh/patterns/late-paint/"
    },
    {
      "aka": [
        "Expandable tool result"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "detail-fold",
      "intent": "Show compact progress and summaries with bounded expanded tool detail.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/detail-fold.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/detail-fold.md",
      "name": "Detail Fold",
      "url": "https://pi-tui.ratstack.sh/patterns/detail-fold/"
    },
    {
      "aka": [
        "Call-scoped renderer"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "call-capsule",
      "intent": "Retain a display shell through call and result renders of one tool execution.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/call-capsule.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/call-capsule.md",
      "name": "Call Capsule",
      "url": "https://pi-tui.ratstack.sh/patterns/call-capsule/"
    },
    {
      "aka": [
        "Adaptive diff"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "hinge-diff",
      "intent": "Choose compact, unified or split diff presentation from available width.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/hinge-diff.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/hinge-diff.md",
      "name": "Hinge Diff",
      "url": "https://pi-tui.ratstack.sh/patterns/hinge-diff/"
    },
    {
      "aka": [
        "Intraline diff"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "word-spotlight",
      "intent": "Emphasize changed words inside parsed patch lines.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/word-spotlight.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/word-spotlight.md",
      "name": "Word Spotlight",
      "url": "https://pi-tui.ratstack.sh/patterns/word-spotlight/"
    },
    {
      "aka": [
        "Diagnostic summary"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "error-digest",
      "intent": "Project structured errors into compact and expanded diagnostic output.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/error-digest.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/error-digest.md",
      "name": "Error Digest",
      "url": "https://pi-tui.ratstack.sh/patterns/error-digest/"
    },
    {
      "aka": [
        "Renderer decoration"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "renderer-chain",
      "intent": "Add tool rendering while preserving an existing renderer or fallback.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/renderer-chain.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/renderer-chain.md",
      "name": "Renderer Chain",
      "url": "https://pi-tui.ratstack.sh/patterns/renderer-chain/"
    },
    {
      "aka": [
        "Collapsible message"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "message-fold",
      "intent": "Render custom message content as a preview with expanded detail.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/message-fold.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/message-fold.md",
      "name": "Message Fold",
      "url": "https://pi-tui.ratstack.sh/patterns/message-fold/"
    },
    {
      "aka": [
        "Inline image fallback"
      ],
      "category": "tools",
      "family": "presentation",
      "id": "image-parachute",
      "intent": "Render terminal images where supported and text placeholders otherwise.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/image-parachute.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/image-parachute.md",
      "name": "Image Parachute",
      "url": "https://pi-tui.ratstack.sh/patterns/image-parachute/"
    },
    {
      "aka": [
        "Validated theme colours"
      ],
      "category": "themes",
      "family": "presentation",
      "id": "colour-sentry",
      "intent": "Validate colour overrides before using them in themed terminal output.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/colour-sentry.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/colour-sentry.md",
      "name": "Colour Sentry",
      "url": "https://pi-tui.ratstack.sh/patterns/colour-sentry/"
    },
    {
      "aka": [
        "Colour presets"
      ],
      "category": "themes",
      "family": "presentation",
      "id": "palette-deck",
      "intent": "Centralize coordinated colour choices behind named presets and a default.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/palette-deck.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/palette-deck.md",
      "name": "Palette Deck",
      "url": "https://pi-tui.ratstack.sh/patterns/palette-deck/"
    },
    {
      "aka": [
        "Snapshot status projection"
      ],
      "category": "lifecycle",
      "family": "presentation",
      "id": "snapshot-lens",
      "intent": "Derive compact status and bounded detail from lifecycle snapshots.",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/snapshot-lens.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/snapshot-lens.md",
      "name": "Snapshot Lens",
      "url": "https://pi-tui.ratstack.sh/patterns/snapshot-lens/"
    }
  ],
  "pi": "1.0.3",
  "title": "Pi TUI patterns"
}
