
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
pi-design-deck
Advanced tools
Visual design deck for presenting multi-slide options with high-fidelity previews
A tool for Pi coding agent that presents multi-slide visual decision decks. On macOS, uses Glimpse to render in a native WKWebView window; falls back to a browser tab on other platforms. Each slide shows 2-4 high-fidelity previews — code diffs, architecture diagrams, UI mockups — and you pick one per slide. The agent gets back a clean selection map and moves on to implementation.
Just ask. The agent reaches for the design deck when visual comparison makes sense.
show me 3 architecture options for the backend
present a few UI directions for the settings page
what are my options for the auth flow? show me visually
read the PRD at docs/api-plan.md and present the key decisions
Three slash commands are also available for more structured flows:
/deck — general purpose. Give it a topic or run it bare./deck-plan docs/plan.md — reads a plan or PRD, identifies decision points, builds slides for each./deck-discover — interviews you first to gather requirements, then builds a deck from what it learned.The interview tool gathers structured input — you answer questions. The design deck is the other direction: the agent shows you visual options and you pick. They work together — interview discovers requirements, deck presents the resulting options — but they're distinct tools for distinct jobs.
The persistent server architecture means the browser stays open across tool re-invocations. When you click "Generate another option," the agent creates it and pushes it into the live deck via SSE — no page reloads, no lost state.
pi install npm:pi-design-deck
Restart pi to load the extension and the bundled design-deck skill.
Requirements:
pi install npm:glimpseui (optional, falls back to browser if not installed)https://github.com/user-attachments/assets/aff1bac6-8bc2-461a-8828-f588ce655f7f
The agent builds slides as JSON. Each slide is one decision, each option is one approach:
{
"title": "API Design",
"slides": [
{
"id": "auth",
"title": "Authentication Strategy",
"context": "Choose how users authenticate with the API.",
"columns": 2,
"options": [
{
"label": "JWT + Refresh Tokens",
"description": "Stateless, horizontally scalable",
"aside": "Tokens are self-contained — no session store needed.\nWatch for token size with many claims.",
"previewBlocks": [
{ "type": "code", "code": "const token = jwt.sign({ sub: user.id }, SECRET, { expiresIn: '15m' });\nres.cookie('refresh', refreshToken, { httpOnly: true });", "lang": "ts" },
{ "type": "mermaid", "content": "sequenceDiagram\n Client->>API: POST /login\n API->>Client: JWT + refresh cookie\n Client->>API: GET /data (Bearer JWT)\n API->>Client: 200 OK" }
],
"recommended": true
},
{
"label": "Session Cookies",
"description": "Server-side sessions with Redis backing",
"aside": "Simple mental model. Session invalidation is instant.\nRequires sticky sessions or shared session store.",
"previewBlocks": [
{ "type": "code", "code": "app.use(session({ store: new RedisStore({ client }), secret: SECRET }));", "lang": "ts" },
{ "type": "mermaid", "content": "sequenceDiagram\n Client->>API: POST /login\n API->>Redis: Store session\n API->>Client: Set-Cookie: sid=...\n Client->>API: GET /data (Cookie)\n API->>Redis: Lookup session" }
]
}
]
}
]
}
The browser opens, the user picks "JWT + Refresh Tokens", and the agent receives:
{ "auth": "JWT + Refresh Tokens" }
code (Prism.js syntax highlighting), mermaid (Mermaid.js diagrams), html (raw HTML), and image (served from disk). Mix freely within one option.previewHtml support for custom UI mockups with inline styles. Use when blocks aren't enough.columns property (1, 2, 3, or 4) per slide. Auto-detected from option count if omitted.\n for line breaks.Cmd+S saves the deck to disk. Use action: "list" to enumerate saved decks, action: "open" to reopen one by deck ID, or pass a file path to slides.action: "export" writes a read-only export.html next to the saved deck snapshot.Cmd+Shift+L (configurable). Persists in localStorage.role="radiogroup" on options, arrow key navigation, Space/Enter to select, number keys for quick pick.design_deck() with slides JSON — local HTTP server starts, opens in Glimpse on macOS when available, otherwise opens in the browseradd-options, deck stays open{ slideId: "selected label" }The server persists across tool re-invocations. When generate-more fires, the tool resolves with instructions for the agent to create a new option. The browser shows a skeleton placeholder with shimmer animation until the new option arrives via SSE.
Every option needs exactly one of previewBlocks or previewHtml (not both, not neither).
previewBlocks — structured array of typed blocks, rendered in order:
| Block | Required Fields | Description |
|---|---|---|
code | code, lang | Syntax-highlighted code (Prism.js + autoloader) |
mermaid | content | Mermaid diagram. Optional theme object for per-block overrides |
html | content | Raw HTML snippet |
image | src, alt | Image from disk (absolute path). Optional caption |
{
"previewBlocks": [
{ "type": "mermaid", "content": "graph TD\n A-->B-->C" },
{ "type": "code", "code": "export default router;", "lang": "ts" },
{ "type": "html", "content": "<div style='color:#888'>Implementation notes...</div>" }
]
}
previewHtml — raw HTML string injected directly into the preview container. Full control over styling:
{
"previewHtml": "<div style='font-family: system-ui; padding: 16px'><h3>Dashboard Layout</h3><div style='display: grid; grid-template-columns: 200px 1fr'>...</div></div>"
}
Image blocks reference absolute file paths. The server copies each file into a temp directory and serves it via /assets/ — the browser never sees the original path. Cleanup happens when the deck closes.
Each slide supports columns: 1 | 2 | 3 | 4 to control the grid layout. Omit it and the deck auto-detects based on option count. Use columns: 1 for wide architecture diagrams, columns: 2 for side-by-side comparisons, columns: 4 for many small items.
The aside field renders explanatory text below the preview with styled typography. Use \n for line breaks. Good for trade-off summaries, pros/cons, or implementation notes that complement the visual preview.
The slide ID "summary" is reserved for the built-in summary slide that appears after all user slides. Don't use it.
When the user clicks "Generate N options," the tool resolves with a structured prompt telling the agent which slide needs options, how many, what options already exist, and what format to use. The agent generates the requested options and pushes them all at once:
design_deck({
action: "add-options",
slideId: "arch",
options: '[{"label": "Serverless", "previewBlocks": [...]}, {"label": "Edge", "previewBlocks": [...]}]'
})
The browser shows the new options with entry animations. The add-options call blocks until the next user action (submit, cancel, or another generate-more).
The deck shows a model dropdown when 2+ models are available. Users pick which model generates new options. When a model other than the current one is selected, the generate-more result instructs the agent to use the built-in deck_generate tool, which spawns pi headlessly with that model.
The default model can be set in the UI (saved to settings) or in settings.json:
{
"designDeck": {
"generateModel": "google/gemini-3.1-pro"
}
}
Priority: browser selection > settings default > current model.
An optional text input next to the generate button lets users provide instructions that flow through to the agent (e.g., "make it more minimal" or "use WebSockets instead").
Manual save: Press Cmd+S (or Ctrl+S) at any time to save the current deck state to disk.
Auto-save on submit: Enabled by default. Saves a snapshot after successful submission with a -submitted suffix.
Auto-save on cancel: If you cancel a deck that has selections, it's automatically saved with a -cancelled suffix. This makes it easy to recover work if you accidentally close the tab or change your mind.
Loading a saved deck:
design_deck({ slides: "~/.pi/deck-snapshots/api-design-myapp-main-2026-02-22-143000/deck.json" })
The deck opens with selections pre-populated and image paths resolved relative to the snapshot directory.
Listing saved decks:
design_deck({ action: "list" })
Opening by deck ID:
design_deck({ action: "open", deckId: "api-design-myapp-main-2026-02-22-143000-submitted" })
Exporting standalone HTML:
design_deck({ action: "export", deckId: "api-design-myapp-main-2026-02-22-143000-submitted", format: "html" })
Snapshot structure:
~/.pi/deck-snapshots/
{title}-{project}-{branch}-{date}-{time}[-submitted|-cancelled]/
deck.json # Config + selections + metadata
images/ # Copied image assets (relative paths in JSON)
| Key | Action |
|---|---|
Arrow keys | Navigate slides (left/right) or options within a slide (up/down) |
Space / Enter | Select focused option |
1-9 | Quick-select option by number |
Enter (on last slide) | Submit |
Cmd+S | Save deck snapshot |
Cmd+Shift+L | Toggle theme (configurable) |
Escape | Cancel (confirmation bar if selections exist) |
Settings in ~/.pi/agent/settings.json under the designDeck key:
{
"designDeck": {
"port": 0,
"browser": "chrome",
"snapshotDir": "~/.pi/deck-snapshots",
"autoSaveOnSubmit": true,
"generateModel": "google/gemini-3.1-pro",
"theme": {
"mode": "dark",
"toggleHotkey": "mod+shift+l"
}
}
}
| Setting | Default | Description |
|---|---|---|
port | 0 (random) | Fixed port for the deck server |
browser | System default | Browser app to open (e.g., "chrome", "firefox") |
snapshotDir | ~/.pi/deck-snapshots | Directory for saved deck snapshots |
autoSaveOnSubmit | true | Auto-save snapshot on successful submit |
generateModel | — | Default model for generate-more (e.g., "google/gemini-3.1-pro") |
theme.mode | "dark" | "dark", "light", or "auto" (follows OS) |
theme.toggleHotkey | "mod+shift+l" | Hotkey string to toggle theme |
Migration: If you previously had deckGenerateModel under the interview key, it's automatically migrated to designDeck.generateModel on first load.
The agent handles these when you use the slash commands or ask in natural language. This documents the underlying tool API.
| Parameter | Type | Description |
|---|---|---|
slides | string | JSON string of deck config, or file path to a saved deck |
action | "add-options" | "add-option" | "replace-options" | "list" | "open" | "export" | Push/replace options, list saved decks, reopen a saved deck, or export one |
slideId | string | Target slide ID (required with actions) |
option | string | JSON string of one option (required with add-option) |
options | string | JSON string of option array (required with add-options or replace-options) |
deckId | string | Saved deck ID from action: "list" (required with open / export) |
format | string | Export format for action: "export" ("html" currently supported) |
Six modes of invocation:
design_deck({ slides: "<JSON>" })design_deck({ action: "add-options", slideId: "...", options: "<JSON array>" }) — blocks until next user actiondesign_deck({ action: "add-option", slideId: "...", option: "<JSON>" })design_deck({ action: "replace-options", slideId: "...", options: "<JSON array>" })design_deck({ action: "list" })design_deck({ action: "open" | "export", deckId: "..." })pi-design-deck/
├── index.ts # Tool registration, module-level state, lifecycle
├── generate-prompts.ts # Prompt builders for generate-more / regenerate
├── model-runner.ts # Headless pi spawner for deck_generate tool
├── deck-schema.ts # TypeScript types and validation (no dependencies)
├── deck-server.ts # HTTP server, SSE, asset serving, snapshots
├── server-utils.ts # Shared HTTP/session utilities
├── settings.ts # Settings with designDeck namespace + migration
├── schema.test.ts # 48 tests across 3 describe blocks
├── form/
│ ├── deck.html # HTML template (loads CSS/JS, Prism, Mermaid)
│ ├── css/ # Theme variables, layout, preview blocks, controls
│ └── js/ # Client: state, rendering, interaction, session
├── prompts/
│ ├── deck.md # /deck — general purpose
│ ├── deck-plan.md # /deck-plan — design from plan/PRD
│ └── deck-discover.md # /deck-discover — interview then design
└── skills/
└── design-deck/
└── SKILL.md # Agent skill for on-demand loading
The extension includes a design-deck skill at skills/design-deck/SKILL.md that teaches the agent when and how to use the design deck effectively — discovery-first vs deck-direct, slide structure, previewBlocks vs previewHtml, the generate-more loop, and model override patterns.
The skill is declared in package.json under pi.skills and is automatically discovered when the extension is installed. No manual copying needed.
The skill includes a reference library for 60 UI components with best practices, common layouts, and aliases. Each component links to component.gallery where the agent can browse real screenshots when needed.
Before: "Show me collapse options" → agent might not connect that to accordion, or know what components are available for the use case.
After: Agent has 60 components to suggest from. Knows collapse = accordion = disclosure = expander. Knows Blueprint = dense, dark-native; Ant = clean, blue primary. Can browse 100+ real implementations when it needs concrete references.
The reference enables discovery (find/suggest components), cross-referencing (connect related terms), and design vocabulary (know what systems look like) — plus guidance on when to show distinct design systems vs variations of one style.
A separate vocabulary lookup (LOOKUP.md) resolves ambiguous user terms to canonical components. When a user says "dropdown" (Select? Combobox? Dropdown menu?) or "popup" (Modal? Popover? Tooltip?) or describes intent ("I need something that expands"), the agent can consult the lookup to understand what they mean and ask the right clarifying questions when needed.
summary slide ID is reserved and cannot be used for custom slides.UI component reference data sourced from component.gallery by Iain Bean.
FAQs
Visual design deck for presenting multi-slide options with high-fidelity previews
The npm package pi-design-deck receives a total of 35 weekly downloads. As such, pi-design-deck popularity was classified as not popular.
We found that pi-design-deck demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.