File: README.md
Open CoDesign
简体中文: README.zh-CN.md
Your prompts. Your model. Your laptop.
Turn prompts into polished artifacts — locally, openly, and with whichever model you already pay for.
Website · Quickstart · What's new · Changelog · Discussions · Docs · Contributing · Security
Open-source alternative to: Claude Design · v0 by Vercel · Lovable · Bolt.new · Figma AI
What's new
feat/decompose-to-ui-kit(branch) — Image -> componentizedui_kits/<slug>/bundle for coding-agent handoff · Boolean-per-dimension visual parity judge (12 standard checks) · Verify-and-iterate loop · Per-decompose cost row · See BENCHMARKS.md. Refs #225.- v0.2.0 (2026-05-09) — Agentic Design: workspace-backed sessions · permissioned local tools · Files panel upgrades · provider diagnostics · security hardening ·
DESIGN.mddesign systems - v0.1.4 (2026-04-23) — AI image generation · ChatGPT Plus/Codex subscription support · CLIProxyAPI one-click import · API config hardening
- v0.1.3 (2026-04-21) — Gemini
models/prefix fix · OpenAI-compatible relay "instructions required" fix · third-party relay SSE-truncation hint - v0.1.2 (2026-04-21) — Release pipeline · Homebrew / winget / Scoop packaging manifests
Full release history → · Changelog →
What it is
Turn a prompt into a polished prototype, slide deck, or marketing asset, locally, with the model you already use.
Open CoDesign is the open-source Claude Design alternative — built for people who want the speed of AI-native design tools without subscription lock-in, cloud-only workflows, or being forced onto a single provider. An MIT-licensed desktop app, local-first from day one, with BYOK for any model (Claude, GPT, Gemini, DeepSeek, Kimi, GLM, Ollama, or any OpenAI-compatible endpoint) plus direct ChatGPT Plus / Pro / Team subscription sign-in for Codex models. One-click import of existing Claude Code or Codex provider configs, or one-click ChatGPT sign-in, gets you running in under 90 seconds.
See it generate
From a blank prompt to a finished artifact, the agent plans, writes, self-checks, and ships something with hover states, tabs, and empty states already wired up:
Why people star it
- Runs on your laptop — no mandatory cloud workspace
- Works with your model — Claude, GPT, Gemini, Ollama, OpenRouter, and more
- Exports real files — HTML, PDF, PPTX, ZIP, Markdown
- Shows its work — live agent activity, visible tool calls, interruptible generation
Why Open CoDesign?
Open source, desktop-native, and built for people who do not want their design workflow locked to one model or one cloud.
| Open CoDesign | Claude Design | v0 by Vercel | Lovable | |
|---|---|---|---|---|
| Open source | ✅ MIT | ❌ Closed | ❌ Closed | ❌ Closed |
| Desktop native | ✅ Electron | ❌ Web only | ❌ Web only | ❌ Web only |
| Bring your own key | ✅ Any provider | ❌ Anthropic only | ❌ Vercel only | ⚠️ Limited |
| Local / offline | ✅ Fully local app | ❌ Cloud | ❌ Cloud | ❌ Cloud |
| Models | ✅ 20+ (Claude, GPT, Gemini, Ollama…) | Claude only | GPT-4o | Multi-LLM |
| Version history | ✅ Local sessions + workspace files | ❌ | ❌ | ❌ |
| Data privacy | ✅ On-device app state | ❌ Cloud-processed | ❌ Cloud | ❌ Cloud |
| Editable export | ✅ HTML, PDF, PPTX, ZIP, Markdown | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited |
| Price | ✅ Free app, provider/subscription cost only | 💳 Subscription | 💳 Subscription | 💳 Subscription |
Highlights
| **Comment, don’t retype.**Click any element, drop a pin, and let the model rewrite only that region. | **AI-tuned sliders.**The model surfaces the parameters worth tweaking, so you can refine color, spacing, and typography without another full prompt. |
|---|---|
| **Every iteration, kept.**Designs are saved locally, with instant switching between recent versions. | **Watch the agent work.**Todos, tool calls, and live progress stay visible and interruptible throughout generation. |
Quickstart
Time to first artifact: about 3 minutes
Requires: one API key, ChatGPT subscription sign-in, or local Ollama
Runs on: macOS 12+ (Monterey or later), Windows 10+, Linux (glibc ≥ 2.31)
1. Install
Package manager (recommended):
# macOS
brew install --cask opencoworkai/tap/open-codesign
# Windows — Scoop
scoop bucket add opencoworkai https://github.com/OpenCoworkAI/scoop-bucket
scoop install opencoworkai/open-codesignOr direct download from the v0.2.0 GitHub Release:
| Platform | File |
|---|---|
| macOS (Apple Silicon) | open-codesign-*-arm64.dmg |
| macOS (Intel) | open-codesign-*-x64.dmg |
| Windows (x64) | open-codesign-*-x64-setup.exe |
| Windows (ARM64) | open-codesign-*-arm64-setup.exe |
| Linux (x64, AppImage) | open-codesign-*-x64.AppImage |
| Linux (x64, Debian/Ubuntu) | open-codesign-*-x64.deb |
| Linux (x64, Fedora/RHEL) | open-codesign-*-x64.rpm |
Each release ships with SHA256SUMS.txt and a CycloneDX SBOM (*-sbom.cdx.json) so you can verify what you downloaded.
More package managers
| Manager | Command | Status |
|---|---|---|
| Homebrew Cask (macOS) | brew install --cask opencoworkai/tap/open-codesign |
🟢 Live |
| Scoop (Windows) | scoop bucket add opencoworkai https://github.com/OpenCoworkAI/scoop-bucket && scoop install opencoworkai/open-codesign |
🟢 Live |
| winget (Windows) | winget install OpenCoworkAI.OpenCoDesign |
🟡 PR submitted; waiting for Microsoft review |
| Flathub (Linux) | flatpak install flathub ai.opencowork.codesign |
⏸ Deferred; needs signed build + AppStream metadata |
| Snap (Linux) | snap install --dangerous open-codesign-*.snap |
🟡 Attached to releases best-effort; Snap Store publish not yet wired |
After each stable tag push, CI syncs SHAs back into packaging/ and publishes downstream Homebrew/Scoop updates when the repo secrets are configured. The first winget submission is in review; once Microsoft accepts the package, future winget bumps can be automated from the release workflow. Every packaging/*/README.md documents its own channel.
Unsigned installer note: installers are not notarized or Authenticode-signed yet. On macOS Sequoia 15+ right-click → Open no longer bypasses Gatekeeper, and "Open Anyway" in System Settings often fails. Reliable one-liner:
shxattr -cr "/Applications/Open CoDesign.app"Then double-click normally. (Older 0.1.x builds are installed as
/Applications/open-codesign.app.)
On Windows: SmartScreen → More info → Run anyway.Want a verified build? Compile from source — see CONTRIBUTING.md.
2. Add a provider
On first launch, Open CoDesign opens the Settings page. Pick the path that matches how you already use models:
- ChatGPT subscription — sign in with ChatGPT to use Codex models without pasting an API key.
- API key — paste Anthropic (
sk-ant-...), OpenAI (sk-...), Google Gemini, OpenRouter, SiliconFlow, DeepSeek, or another supported provider key. - Local / keyless — use Ollama or an IP-allowlisted OpenAI-compatible gateway.
Credentials stay in ~/.config/open-codesign/config.toml and the ChatGPT OAuth token store under the app config directory. Nothing leaves your machine unless your chosen model route requires it.
3. Type your first prompt
Pick one of fifteen built-in demos — landing page, dashboard, pitch slide, pricing, mobile app, chat UI, event calendar, blog article, receipt/invoice, portfolio, settings panel, and more — or describe your own. A sandboxed prototype appears in seconds.
Bring your stack
Already using Claude Code or Codex? API-key provider configs import in one click, with no copy-paste and no need to re-enter settings. If you use Codex through ChatGPT subscription login, sign in directly from Settings:
Built-in taste
Generic AI tools tend to produce generic output. Open CoDesign ships with twelve built-in design skill modules — slide decks, dashboards, landing pages, SVG charts, glassmorphism, editorial typography, heroes, pricing, footers, chat UIs, data tables, and calendars — plus a built-in taste layer that steers the model toward considered typography, purposeful whitespace, and meaningful color.
Every skill is available in every generation. Before the model writes a line of CSS, it selects the skills that fit the brief and reasons through layout intent, design-system coherence, and contrast, bringing higher-quality design behavior to whichever model you choose.
Add a SKILL.md to any project to teach the model your own taste.
What you get
Models and providers
- Unified provider model — Anthropic, OpenAI, Gemini, DeepSeek, OpenRouter, SiliconFlow, local Ollama, or any OpenAI-compatible relay; keyless (IP-allowlisted) proxies supported
- One-click import and sign-in — bring Claude Code / Codex API-key provider configs across, or sign in with ChatGPT subscription for Codex models
- Dynamic model picker — every provider exposes its real model catalogue, not a hardcoded shortlist
Generation and editing
Prompt → HTML or JSX/React component prototype, rendered in a sandboxed iframe (vendored React 18 + Babel on-device)
Fifteen built-in demos + twelve design skill modules — ready-to-edit starting points for common design briefs
Live agent panel — watch tool calls stream in real time as the model edits files
AI image generation — opt-in bitmap assets for heroes, product shots, backgrounds, and illustrations via OpenAI, OpenRouter, or signed-in ChatGPT subscription
AI-generated sliders — the model emits the parameters worth tweaking (color, spacing, font)
Comment mode — click any element in the preview to drop a pin, leave a note, and let the model rewrite only that region
Decompose to UI Kit — one click in the chat sidebar emits a
ui_kits/<slug>/folder (index.html+components/*.tsx+tokens.css+manifest.json+README.md) shaped for coding-agent handoff. Built-in deterministic + vision verifiers self-check parity using a 12-question boolean rubric (no floating-point arbitrary scores) and re-iterate on gaps. Per-decompose cost surfaces inline as a toast. See BENCHMARKS.md.Source image (gpt-image input) on the left, agent-emitted
ui_kitrendered headlessly on the right. Parity score and status are derived deterministically —parityScore = passCount / totalChecks— from the 12-check boolean rubric. Numbers are from a reale2e-opus-finalrun, not a mock.4-frame reel from the
e2e-nodebench-iterrun: source → iter-0 (parityScore 0.82, 6 gaps) → iter-1 (parityScore 0.78, 5 gaps) → honest verdict. The agent fixed some gaps and introduced new layout drift; the boolean rubric exposes the regression instead of hiding it. MP4 version.Generation cancellation — stop mid-stream without losing prior turns
Preview and workflow
- Phone / tablet / desktop preview — true responsive frames, switch with one click
- Files panel — inspect multi-file artifacts (HTML, CSS, JS) before export
- Instant design switching — the last five designs keep their preview iframes alive, so Hub ↔ Workspace and sidebar navigation stay zero-delay
- Connection diagnostic panel — one-click test for any provider, with actionable errors
- Per-generation token counter — see exactly how many tokens each run cost in the sidebar
- Settings with four tabs — Models, Appearance, Storage, and Advanced
- Light + dark themes, EN + 简体中文 UI with live toggle
Export and packaging
- Five export formats — HTML (inlined CSS), PDF (local Chrome), PPTX, ZIP, Markdown
- GitHub Release pipeline — unsigned DMG (macOS), EXE (Windows), AppImage (Linux). Code-signing lands in v0.5 along with opt-in auto-update
Roadmap
Current release: v0.2.0. The current release theme is Agentic Design.
Now — v0.2.0 shipped
v0.2 turns Open CoDesign from a one-shot generator into a local design agent with a real workspace:
- Design as session — every design is a pi session with JSONL history and a workspace folder on disk
- Permissioned agent loop — pi built-ins for read, write, edit, bash, grep, find, and ls, gated by Open CoDesign's permission UI
- Design tools on demand —
ask,scaffold,skill,preview,gen_image,tweaks,todos, anddone DESIGN.mdas shared memory — brand tokens and design-system decisions become editable files, not model memory- v0.1 migration path — existing SQLite designs migrate into workspaces and session history
Previous — v0.1.4
- AI image generation — opt-in bitmap assets through OpenAI image models or OpenRouter image models
- ChatGPT Plus / Codex subscription login — one-click OAuth for users who do not want to paste an API key
- CLIProxyAPI one-click import — auto-detect a running local proxy and bring it into Settings
- API config hardening — clearer relay diagnostics for timeouts, SSE truncation, missing
/models, and incompatible Messages APIs
Later — v0.2.x and beyond
- Renderer polish for the new
ask,preview, tweaks, and process-management surfaces - Cost transparency — pre-generation estimate + weekly budget (per-generation token count already shipped)
- Version snapshots + side-by-side diff
- Three-style parallel exploration
- Codebase → design system (token extraction)
- Code-signing (Apple ID + Authenticode) + opt-in auto-update — v0.5
- Figma layer export — post-1.0
Have a different priority in mind? Open an issue or 👍 an existing one — we do read them.
Star History
Built on
- Electron + React 19 + Vite 6 + Tailwind v4
@mariozechner/pi-aiandpi-coding-agent(model/provider and agent-loop primitives)electron-builder
Reporting issues
Found a bug or have a feature request?
- Search existing issues first.
- Generate a diagnostics bundle — Settings → Storage → Export diagnostics (API keys and prompts are redacted automatically).
- Open a new issue using our bug report or feature request template.
- For security vulnerabilities, see SECURITY.md.
More from OpenCoworkAI
If you like Open CoDesign, you may also want to check out our earlier project, Open Cowork, an open-source AI agent desktop app for Windows and macOS with one-click install, multi-model support, sandbox isolation, and built-in skills.
Community
Open CoDesign first launched on the LINUX DO community — thanks to everyone there for the early feedback and discussion.
- GitHub Discussions — share your designs in Show & Tell, ask questions in Q&A, and propose features in Ideas.
- LINUX DO — Chinese-speaking discussion, use tips, and feedback (primary community).
- GitHub Issues — bug reports and reproducible problems.
WeChat group
For Chinese-speaking users, we also keep a WeChat group for product updates, usage questions, and community discussion.
⚠️ The WeChat QR code rotates every 7 days and is currently valid until May 16.
If the code has expired, please leave a message in GitHub Issues and we will refresh the image in-repo.
See also the Chinese README: README.zh-CN.md#社群.
Contributing
Read CONTRIBUTING.md. Open an issue before writing code and run pnpm lint && pnpm typecheck && pnpm test before a PR.
License
MIT — fork it, ship it, sell it. Third-party notices remain in NOTICE.
Cite this project
If you reference Open CoDesign in a paper, article, or product comparison, please cite the repository as:
@misc{open_codesign_github,
author = {OpenCoworkAI Contributors},
title = {Open CoDesign: An Open-Source Desktop AI Design Tool},
year = {2026},
howpublished = {\url{https://github.com/OpenCoworkAI/open-codesign}},
note = {GitHub repository}
}Or the machine-readable CITATION.cff at the repo root.
File: apps/desktop/resources/templates/README.md
Open CoDesign Built-In Resources
This directory is copied into the user's app data as an editable templates tree.
Treat every file here as shippable product surface.
Resource Types
skills/*.mdare markdown method skills loaded withskill(name). They
describe how to work: layout, accessibility, charts, forms, responsive
behavior, craft checks, andDESIGN.mdbaton rules.brand-refs/*/DESIGN.mdare reference-only brand design systems loaded withskill("brand:<slug>"). They are not project files. When a brand is adopted,
translate the relevant choices into the workspaceDESIGN.md.scaffolds/**are concrete starter/source assets copied withscaffold(kind, destPath). They may be.jsx,.html,.css,.md, or
another text format, but the extension must match the content.design-skills/*.jsxare copyable JSX component snippets. The host exposes
them in the agent virtual filesystem asskills/<file>.jsx; despite that
virtual path, they are source snippets, not markdown method skills.frames/*.jsxare copyable device/browser frame snippets exposed asframes/<file>.jsxin the virtual filesystem.
Workspace DESIGN.md
Workspace DESIGN.md is the project-specific design-system baton. It is not a
built-in preset once copied or authored in a workspace. Generated multi-screen,
brand-driven, or reusable work should preserve, repair, and update it as the
source of visual truth.
Maintenance Checklist
- Keep manifest metadata truthful: category, path, source, license, aliases.
- Keep source format and extension aligned.
- Avoid CDN scripts, external hotlinked assets, and non-MIT-compatible bundled
code or assets. - Avoid weak placeholder copy such as "Replace this", "Page content", or
"Point one". - Add focused tests when a resource affects loader behavior, manifest output,
preview classification, orDESIGN.mdvalidation.
File: docs/research/11-custom-sliders.md
Research 11 — Custom Sliders / EDITMODE Parameter Tweaks
Date: 2026-04-18 · Status: Decision recorded (corrected)
⚠️ Mechanism Correction (2026-04-18)
An earlier draft of this document (unpublished, written before research 15) incorrectly inferred that the Claude Design slider mechanism used a <script type="application/json" id="design-params"> tag to embed tunable parameters.
That inference was wrong.
The actual mechanism, confirmed by analysis of the leaked Claude Design system prompt (see docs/research/15-claude-design-prompts.md, Section 6), uses:
- A
/*EDITMODE-BEGIN*/ ... /*EDITMODE-END*/marker block wrapping a JSON object literal inside a<script>tag — not a separate<script type="application/json">element. window.postMessage({ type: '__edit_mode_set_keys', edits: {...} }, '*')for two-way communication between the parent renderer and the sandbox iframe.
The corrected implementation is described in full below.
Decision summary
| Mechanism | Chosen approach |
|---|---|
| Parameter storage in artifact | /*EDITMODE-BEGIN*/{...}/*EDITMODE-END*/ block inside <script> |
| Parent → iframe update | postMessage({ type: '__edit_mode_set_keys', edits }) |
| Iframe applies change | root.style.setProperty('--' + key, value) |
| Persistence (save) | Parent reads live getPropertyValue() values, merges back into EDITMODE block |
| UI controls | Range / color / select inputs bound to EDITMODE keys |
EDITMODE block format
Every generated artifact that supports tweaking must embed an EDITMODE block in its inline <script>:
<script>
/*EDITMODE-BEGIN*/
{
"color-bg": "#f8f5f0",
"color-accent": "oklch(62% 0.22 265)",
"color-text": "oklch(12% 0.01 265)",
"radius-base": "0.5rem",
"font-sans": "'Syne', system-ui, sans-serif",
"space-unit": "1rem"
}
/*EDITMODE-END*/
(function () {
// Apply initial values from EDITMODE block on load
const block = document.currentScript.textContent.match(
/\/\*EDITMODE-BEGIN\*\/([\s\S]*?)\/\*EDITMODE-END\*\//
);
if (block) {
const params = JSON.parse(block[1]);
const root = document.documentElement;
for (const [key, value] of Object.entries(params)) {
root.style.setProperty('--' + key, String(value));
}
}
// Listen for runtime updates from parent renderer
window.addEventListener('message', (e) => {
if (!e.data || e.data.type !== '__edit_mode_set_keys') return;
const root = document.documentElement;
for (const [key, value] of Object.entries(e.data.edits)) {
root.style.setProperty('--' + key, String(value));
}
});
})();
</script>Rules:
- The JSON block must be valid: no trailing commas, no comments inside the braces.
- Keys match
:rootCSS custom property names WITHOUT the--prefix. - Values are CSS value strings (colors, lengths, font stacks).
- The block must appear before any code that reads the CSS variables.
- Every key in the EDITMODE block must have a corresponding
--keyon:root.
postMessage protocol
Parent → iframe (apply change)
// In packages/runtime or apps/desktop renderer
function applyParamChange(
iframe: HTMLIFrameElement,
key: string,
value: string,
): void {
iframe.contentWindow?.postMessage(
{ type: '__edit_mode_set_keys', edits: { [key]: value } },
'*',
);
}
// Batch update (e.g., when dragging a slider quickly)
function applyParamBatch(
iframe: HTMLIFrameElement,
edits: Record<string, string>,
): void {
iframe.contentWindow?.postMessage({ type: '__edit_mode_set_keys', edits }, '*');
}Persistence on save
When the user saves a tweaked design, the parent:
- Reads the current live value of each EDITMODE key from the iframe DOM:ts
const liveValue = iframe.contentDocument?.documentElement .style.getPropertyValue('--' + key).trim(); - Merges the live values back into the artifact's source string by replacing the EDITMODE block.
- Persists the updated source to SQLite.
The LLM generates the initial EDITMODE block; the renderer owns persistence.
open-codesign implementation plan
Artifact schema
The existing design_params field in @open-codesign/artifacts needs updating:
// Before (wrong — matched the inferred <script type="application/json"> approach)
interface DesignParam {
id: string;
label: string;
type: 'color' | 'range' | 'select' | 'toggle';
cssVar: string;
defaultValue: string;
min?: number; max?: number; step?: number;
unit?: string;
options?: string[];
}
// After (aligned with EDITMODE protocol)
interface EditModeParam {
key: string; // CSS var name without '--'
label: string; // Human-readable label for the slider UI
type: 'color' | 'range' | 'select' | 'toggle';
defaultValue: string; // From the EDITMODE block
min?: number; max?: number; step?: number;
unit?: string;
options?: string[];
}The LLM generates the EDITMODE block; the frontend parses it to derive the EditModeParam[] array for the slider UI. No separate JSON output is needed.
Slider UI (packages/runtime or apps/desktop)
When the preview renders an artifact with an EDITMODE block:
- Parse the block at render time → derive
EditModeParam[]. - Render slider controls for each param.
- On slider input: call
applyParamBatch(iframe, { [param.key]: newValue }). - On slider change (mouseup / pointerup): record undo state.
- On save: read live values back, update artifact source, persist.
System prompt responsibility
The system prompt (tweaks-protocol.v1.txt) instructs the LLM to:
- Emit the EDITMODE block in every design that has tunable values.
- Keep the block valid JSON (no trailing commas).
- Match keys exactly to
:rootproperty names. - Include the message listener script immediately after the block.
Traps to avoid
- Stale EDITMODE block on revision: when applying a text revision, preserve the EDITMODE block values; don't reset them to defaults.
- Color format mismatch: slider color pickers emit
#rrggbb; the EDITMODE block may haveoklch(...). The renderer must normalize before writing back. - Too many parameters: cap at 8 EDITMODE keys in the system prompt. More than 8 overwhelms the UI and signals poor CSS variable hygiene.
*origin in postMessage: acceptable for same-device local sandbox; would need origin restriction for any hosted/cloud version.
Reference
- EDITMODE protocol details:
docs/research/15-claude-design-prompts.mdSection 6 - Prompt section that governs LLM output:
packages/core/src/prompts/tweaks-protocol.v1.txt - Inline comment / element selection (separate mechanism):
docs/research/02-inline-comment-and-sliders.md
File: docs/research/15-claude-design-prompts.md
Research 15 — Claude Design System Prompt Structure Analysis
Date: 2026-04-18 · Status: Reference (informs prompt v1 design, do not copy)
Legal note: This document describes the structure and design patterns observed in the leaked Claude Design system prompt. It does not reproduce any original text verbatim. Our own prompt sections in
packages/core/src/prompts/are independently authored.
Overview
The leaked Claude Design system prompt is approximately 14,700 tokens across 10 logical sections. The following is a structural analysis of what each section does — not a transcription.
Section 1 — Identity and scope
Establishes the AI's role as a design-focused assistant. Defines what artifact types it can produce (UI screens, landing pages, presentations, marketing materials). Sets the character: confident design authority, not a general-purpose assistant.
Section 2 — Artifact output contract
Specifies the exact wrapping format for generated artifacts. Defines identifier, type, and title attributes. Constrains the number of artifacts per response (one). Defines what is permitted outside the artifact tag (short prose summary only).
Section 3 — Technical stack and construction rules
Enumerates permitted external resources with exact CDN URLs and integrity hashes for specific library versions (React, etc.). Defines inline-only rule for everything else. Specifies CSS-variable-first approach for all tunable values.
Section 4 — Design quality and aesthetic guidance
Covers typography choices, color space preferences (oklch), layout asymmetry, spacing scale, motion restraint. Includes a list of visual patterns to avoid ("slop" list). References the publicly documented Skills approach to frontend design quality.
Section 5 — Workflow and reasoning
Describes the expected thought process before generating: understanding intent, exploring directions, self-checking output quality. Defines "done" criteria.
Section 6 — EDITMODE protocol (tweaks)
This is the most technically distinctive section. Describes the two-way communication protocol between the sandbox iframe and the parent renderer for live parameter tweaks.
6a — Embedded parameter block
Tweakable parameters are embedded in the artifact source as a JS object literal surrounded by marker comments:
/*EDITMODE-BEGIN*/
{
"key": "value",
...
}
/*EDITMODE-END*/This block lives inside a <script> tag in the artifact. The keys correspond 1:1 to CSS custom property names (without the leading --). Values are CSS value strings.
6b — Message protocol
The parent renderer communicates parameter changes to the iframe via window.postMessage:
// Parent → iframe: apply parameter changes
iframe.contentWindow.postMessage(
{
type: '__edit_mode_set_keys',
edits: { 'color-accent': 'oklch(70% 0.25 30)', 'radius-base': '0.75rem' }
},
'*'
);The iframe listens for this message type and applies changes via document.documentElement.style.setProperty.
6c — Persistence
On save, the parent reads the live getPropertyValue() values back, merges them into the EDITMODE block, and persists the updated source. The LLM does not need to handle persistence — only the initial embedding and read-back.
Section 7 — Multi-variant output
In "explore" mode, the prompt guides the model to emit multiple artifact variants (typically 3) in a single response, each with a distinct visual direction. Each variant gets its own artifact tag with a distinct identifier.
Section 8 — Revision behavior
Defines how the model should handle follow-up requests: minimal-change principle, preserve voice/palette/structure unless explicitly asked to change them, re-read the current artifact before editing.
Section 9 — Safety and scope limitations
Standard IP protection, phishing prevention, and out-of-scope deflection. Brief (< 100 tokens).
Section 10 — Skills injection format
Describes how capability "Skills" are serialized and injected into the prompt at runtime. Each skill is a named, versioned block of instructions that can be included or excluded depending on the generation context.
Implications for open-codesign
Our prompt composer in packages/core/src/prompts/index.ts mirrors this 10-section architecture with independently authored text. The EDITMODE protocol described in Section 6 is implemented in docs/research/11-custom-sliders.md (corrected 2026-04-18) and packages/runtime/.
File: docs/plans/2026-04-23-v0.2-agentic-design-loop-design.md
v0.2 Agentic Design Loop — Design Doc
Date: 2026-04-23
Status: Draft, pending review
Target: v0.2.0 (multi-milestone)
0. Context
v0.1.x agent runs on @mariozechner/pi-agent-core with a virtual-filesystem tool (str_replace_based_edit_tool). Pipeline assumes single prompt → single artifact. 13 design skills are injected wholesale into the system prompt every call.
This is insufficient for the product we are becoming:
- Users increasingly want multi-page / multi-artifact projects (landing + pricing + email in one session)
- Agent cannot see user's existing files, design tokens, or previous work
- Revision flow requires re-describing the whole page
- Skill injection eats 20-40k tokens per call regardless of relevance
v0.2 upgrades the loop to a real agentic design system: read/edit a user-bound workspace, pull skills on demand, verify its own output visually, revise by pointing at regions.
1. Non-goals
- Not replicating Claude Code. We optimize for design-artifact iteration, not general software engineering.
- No bundled model runtime. BYOK still mandatory.
- No cloud sync of workspace content. Local-first remains a hard constraint.
- No auto-retry on LLM errors beyond what
pi-agent-corealready does. Error recovery is user-triggered ("Try to fix").
2. Architecture overview
Renderer (React) Main (Electron)
┌─────────────────────────────┐ IPC ┌──────────────────────────────┐
│ Chat / Preview / Perm modals│ ──────► │ ToolHandler (IPC-fronted) │
│ Point-and-prompt selector │ ◄────── │ ├─ PermissionManager │
│ Zustand: session + perms │ │ ├─ PathGuard (workspace) │
└─────────────────────────────┘ │ └─ Tools (see §4) │
│ ↓ │
│ pi-agent-core Agent loop │
│ ├─ Compaction │
│ ├─ AbortSignal │
│ └─ Stream → parser │
│ │
│ design-workspace.ts (Roy PR) │
│ ├─ bindWorkspace │
│ ├─ migrate │
│ └─ write-through │
│ │
│ SQLite: projects, designs, │
│ files, permissions │
└──────────────────────────────┘Three layers from bottom to top:
- Workspace layer (Roy PR foundation + path guard): real disk, write-through, binding
- Harness layer (new): permission, path sandbox, streaming parser, action runner, compaction, IPC
- Tool layer (new + #177 + existing): fs + design-specific tools, progressive-disclosed skills
3. Mental model: Quick mode vs Project mode
Both coexist. User picks at session start; they share the tool surface but differ in persistence and loop shape.
| Quick mode (v0.1 parity) | Project mode (new in v0.2) | |
|---|---|---|
| Input | Single prompt | Long-running chat |
| Storage | Virtual fs, extracted as artifact | Real disk under bound workspace |
| Tools | text_editor (virtual) + image-gen (#177) + done |
Full fs tools + image-gen + preview-capture + revision |
| Skills | Wholesale inject (current behavior) | Index-only inject, tool-pull bodies |
| Loop | 6-15 tool calls → done | Multi-turn, compacted, abort-able |
| Revision | Regenerate whole artifact | Scoped to clicked region |
| Exit | Emit artifact, close session | Session stays open, artifact evolves |
The guarantee: everything that works in v0.1 keeps working. Quick mode is the default for new users; Project mode is opt-in by binding a workspace.
4. Tool surface
Keep everything that exists. Add new tools in two batches (see phasing §7).
| Tool | Source | Mode | Permission default | Phase |
|---|---|---|---|---|
set_todos |
existing | both | allow | M0 |
str_replace_based_edit_tool |
existing | Quick | allow | M0 |
read_url |
existing | both | ask | M0 |
done / declare_tweak_schema |
existing | both | allow | M0 |
generate_image_asset |
PR #177 | both | ask (paid) | M0 |
read_file |
adapt pi-coding-agent.createReadTool |
Project | allow | M1 |
list_files |
adapt pi-coding-agent.createLsTool |
Project | allow | M1 |
grep |
adapt pi-coding-agent.createGrepTool |
Project | allow | M1 |
find |
adapt pi-coding-agent.createFindTool |
Project | allow | M1 |
edit_file (str-replace) |
adapt pi-coding-agent.createEditTool |
Project | ask once, then allow | M2 |
write_file |
adapt pi-coding-agent.createWriteTool |
Project | ask once, then allow | M2 |
read_skill(name) |
new | both | allow | M2 |
list_skills |
new (optional; index already in prompt) | both | allow | M2 |
preview_capture |
new — wraps webContents.capturePage |
Project | allow | M3 |
check_token_compliance |
new — reads .codesign/tokens.{css,json} |
Project | allow | M3 |
query_artifact(selector) |
new — operates on artifact HTML, not DOM | Project | allow | M3 |
replace_artifact_fragment(selector, html) |
new | Project | ask once, then allow | M3 |
search_icons |
fork marcoripa96/i0 pattern, local SQLite |
both | allow | M4 |
export_artifact(format) |
wrap packages/exporters/ |
Project | allow | M4 |
Explicitly NOT in v0.2: bash / shell execution. Too much blast radius; re-evaluate in v0.3.
5. Permission model
Copy opencode's allow / deny / ask / always rule engine. Roughly 200 lines of logic + an ordered Ruleset array evaluated with wildcard match (last matching rule wins).
Default ruleset for Project mode:
const DEFAULT_PROJECT_RULES: Ruleset = [
{ permission: '*', pattern: '*', action: 'ask' },
{ permission: 'read', pattern: '*', action: 'allow' },
{ permission: 'read', pattern: '*.env*', action: 'ask' },
{ permission: 'read', pattern: '.git/config', action: 'deny' },
{ permission: 'read', pattern: 'id_rsa*', action: 'deny' },
{ permission: 'external_directory', pattern: '*', action: 'ask' },
{ permission: 'image_generation', pattern: '*', action: 'ask' },
{ permission: 'edit', pattern: '*', action: 'ask' },
{ permission: 'write', pattern: '*', action: 'ask' },
];UX: on the first ask, show a modal with Once | Always | Deny. Always appends an allow rule to ~/.config/open-codesign/permissions.toml. A Permissions panel lets users review/revoke.
Reasoning for being strict by default: new users are unfamiliar; they should consent visibly to disk writes, paid API calls, and external-directory access.
6. Path sandbox
Builds on Roy's normalizeWorkspacePath(). Add a PathGuard wrapper that every tool goes through:
class PathGuard {
constructor(private root: string) {}
resolveWithin(rel: string): string {
const joined = path.resolve(this.root, rel);
const real = fs.realpathSync.native(joined);
if (!real.startsWith(this.root + path.sep) && real !== this.root) {
throw new PermissionError('external_directory', real);
}
return real;
}
}Also applied to Roy's existing persistMutation (see §10). Blocked patterns: *.env*, .git/config, id_rsa*, *.pem — matched against both source and symlink target. Matches opencode's pattern.
7. Phasing
Each milestone is independently shippable. Do not start milestone N+1 before N's acceptance criteria are met on main.
M0 — v0.1.x close-out (blocker for v0.2 start)
Goal: ship current value to international users landing from the star wave.
- Roy PR #173 merged (remaining 1 Blocker + 2 Major fixed)
- Path guard PR (harden Roy's
persistMutation, prevent../writes, filterskills//frames/out of write-through) - yangjunx21 PR #177 rebased, bot review passes, merged
- API config bug batch: #175 Gemini 400, #176 local db, #167 SSE truncation, #158, #134, #130
- Cut v0.1.x release, update CHANGELOG, Changeset
Exit criteria: fresh install works end-to-end; new user can bind a workspace and generate an HTML prototype with an AI image.
Branch policy: continue on main. No v0.2-dev branch yet.
M1 — v0.2.0-alpha: Read-only agent (2 weeks)
Goal: agent can see the user's workspace without touching it yet.
- Create
v0.2-devlong-lived branch off main - New
projectstable +design.project_idFK (migration). A "project" groups designs and owns the workspace binding. Roy's per-designworkspacePathmigrates toproject.workspacePath; per-design binding still works (single-design project). -
PermissionManager(§5) +PathGuard(§6) + IPC plumbing - Adapt pi-coding-agent tools
read/ls/grep/findasread_file/list_files/grep/find; injectPathGuardviaOperationshook - Agent system prompt: add "Explore phase" instruction (first turn reads workspace before writing)
- Quick mode remains the default; Project mode activated by binding a workspace
- Vitest coverage for path-guard escapes, ignore patterns, and permission-ask flow
Exit criteria: in Project mode with bound workspace, agent can list files, read an existing index.html, grep for a component name, and explain what it found — with zero write capability.
M2 — v0.2.0-beta: Write-capable agent + skill-as-tool (2-3 weeks)
Goal: agent can edit workspace files and pull skills on demand.
-
edit_file(str-replace) +write_file, wired throughPathGuard+ permission ask-once - StreamingMessageParser on top of pi-agent-core stream (historical alternative only; not the current v0.2 mainline)
- ActionRunner promise chain for ordered tool execution with live UI progress
- Snapshot-on-first-write under
.codesign/history/, following Bolt's pattern; expose a "Revert" button per turn - read_skill(name) tool — reads from
packages/core/src/skills/builtin/and from{workspace}/.codesign/skills/ - System prompt: switch from wholesale skill injection to skill index only (name + one-line description, ~2k tokens total for 13 skills); Quick mode retains wholesale injection
-
edit_filepreferred overwrite_filein prompt ("prefer targeted replace over full write") - Compaction: wire up
pi-coding-agent'scompaction/module; tune thresholds (20k trigger, 40k protect, last 2 turns verbatim) - AbortSignal plumbed end-to-end; Cancel button in chat
Exit criteria: agent can open a project, read context, propose edits, write them to disk, and be safely interrupted/rolled-back. Skills are pulled on demand. Token cost per turn drops measurably (report before/after).
M3 — v0.2.0: Visual verification + point-and-prompt revision (2 weeks)
Goal: close the generate→verify→revise loop.
-
preview_capture(viewportWidth?)tool over ElectronwebContents.capturePage(). Returns base64 PNG for vision-capable models, plus accessibility-tree snapshot for non-vision models -
check_token_compliance(artifactId)reads{workspace}/.codesign/tokens.{css,json}(W3C DTCG or Tailwind config), returns list of literal colors/spacings that bypass tokens -
query_artifact(cssSelector)+replace_artifact_fragment(selector, html)— operates on the artifact HTML AST, not live DOM - Renderer: click-to-select in preview iframe → compute stable CSS selector (prefer
data-testid, thenid, fall back to structural path) → inject as scope hint into next user prompt - System prompt: when
scopeis present in user message, preferedit_file+replace_artifact_fragmentover regeneration - Lightweight error-recovery UI: on tool failure, show "Try to fix" button that crafts a follow-up prompt with the error payload
Exit criteria: user generates a hero, clicks the CTA button in preview, types "make it bolder", agent modifies only the CTA (not the whole page) and re-verifies via preview capture.
M4 — v0.2.x: Multi-artifact orchestration + assets (2+ weeks, post-GA)
Goal: one session produces a consistent suite (landing + pricing + email).
-
search_icons— forkmarcoripa96/i0, ship local SQLite icon index (MIT); lazy-download on first use to respect the no-bundled-runtime constraint -
export_artifact(format)tool wrappingpackages/exporters/— agent can finalize deliverables - Project-level shared-context pattern (monkilabs
project-consistencyskill): Phase 1 agent writesproject.tokens.json+ baseLayout.tsx; Phase 2 agents import, cannot invent new tokens - Multi-design history view in renderer; cross-design preview
Exit criteria: user says "build me a landing, pricing, and onboarding email", ends session with three consistent artifacts sharing tokens and voice, exports as ZIP.
8. Backwards compatibility
- Quick mode is fully preserved. Existing Vitest test
'injects every loaded skill body into the system prompt (progressive disclosure level 1)'stays green for Quick mode. - Per-design workspace binding (Roy's shape) continues to work. A design without a project is auto-wrapped in a "default" project at M1 migration time.
TextEditorFsCallbacksinterface is preserved; new fs tools go through a parallelPathGuardedFsinterface. Both write through Roy'spersistMutation.- Schema migrations: every table change adds a new column or table with
schemaVersionbumped, never drops. Roll-back only requires previous binary to work with new DB shape.
9. Streaming parser sketch (historical alternative, rejected for current v0.2 mainline)
Status update: the current direction is to stay on pi-agent-core function tools plus a host-side workspace delta bus. We keep this section only as a historical alternative that was considered before the current harness stabilized.
Adapt Bolt's StreamingMessageParser onto pi-agent-core streaming. Key idea: we feed the parser the cumulative stream text; it advances a position cursor and emits events on complete tags.
interface ParseState {
position: number;
insideArtifact: boolean;
insideAction: boolean;
currentArtifact?: { id: string; title: string };
currentAction?: { id: string; type: 'file' | 'image'; filePath?: string; content: string };
}
function parse(state: ParseState, cumulativeText: string, callbacks: {
onArtifactOpen(id: string, title: string): void;
onActionOpen(action: { id: string; type: string }): void;
onActionStream(id: string, contentSoFar: string): void;
onActionClose(id: string): void;
onArtifactClose(id: string): void;
}): ParseState { /* ~150 lines */ }Our tag grammar is simpler than Bolt's — we don't need shell or start. Three action types only: file (write virtual or real fs), image (invoke generate_image_asset), and note (chat narration). System prompt will teach the model these tags.
Why it is not the chosen v0.2 mainline: it would fork the runtime protocol away from pi-agent-core's tool events, duplicate state handling, and make preview/update persistence harder to reason about under multi-design concurrency. The chosen architecture is function tools + compact tool-result persistence + per-design delta handling.
10. Revision UX mechanics
When user clicks in preview iframe:
- Renderer receives click coordinates, runs
document.elementFromPoint - Compute stable selector:
data-testid→id→ class chain (rejecting Tailwind utility chains as noise) → structuralnth-childfallback - Extract element's outer HTML (to show in the chat input as a chip)
- Next user message is sent with a
scopemetadata field:{ selector, outerHtml, viewportWidth } - System prompt instruction: "When
scopeis present, usequery_artifactandreplace_artifact_fragmentwith the given selector; do not regenerate the whole file."
11. Open questions
These are deliberately not answered in this doc; resolve before M3:
- Should
preview_capturedefault to accessibility-tree (free) or screenshot (vision tokens) for vision-capable models? The cost/fidelity tradeoff needs an experiment. - Revision UX: is
data-testida reasonable ask for generated code, or do we rely on structural selectors? Likely the former, but costs prompt tokens. - Should
generate_image_assetresults be cached by prompt hash to prevent accidental double-billing on retries? Probably yes; tracks memory feedback on silent fallback concerns. - For compaction, do we keep
pi-coding-agent's defaultsummaryprompt, or author a design-specific one ("Keep decisions about color, typography, and voice; drop file-level diffs")? Worth an A/B. - Does Figma MCP plug in as an optional data source at M4, or wait for v0.3? Many users don't have Figma.
12. Risks
- pi-agent-core loop hold-up: our M2 introduces a custom streaming parser on top of pi-agent-core's tool-call stream. If pi-agent-core's internals change between minor versions, we break. Mitigation: pin minor version, maintain adapter layer isolated to one file.
- Token cost blow-up: multi-turn Project mode with a 50-file workspace can easily eat 100k tokens/turn if compaction misbehaves. Mitigation: telemetry-less (local only) token counters shown to user; hard cap with user-override.
- Permission fatigue: too many
askdialogs will annoy users. Mitigation:Alwaysaction persisted per-project; the first 5 operations of a session can carry a "trust for this session" bulk-approve. - Skill miss: Tier-1 index might fail to trigger the right skill lookup (Anthropic docs explicitly warn about this). Mitigation: write precise one-line descriptions; include representative task examples in skill frontmatter; ship a test suite that asserts the model picks the correct skill on sample prompts.
- Scope creep into coding-agent territory: users will ask for
bash,git,npm. We say no in v0.2. Mitigation: clear docs on what Project mode is and is not. The differentiation is "agent for design artifacts", not "VS Code replacement".
13. Success metrics
Measured locally (no telemetry). Report in the v0.2 release notes.
- Median tokens per turn drops ≥30% (skill progressive disclosure)
- Median revision task completes ≥2× faster (scope hint + targeted edit)
- Agent retrieves correct skill on ≥85% of sample prompts (offline test set)
- No P0 regressions in Quick mode per existing Vitest suites
14. References
Research reports archived under this plan's directory (append as needed):
- opencode architecture — tool registry, permission rule engine, compaction
- pi-coding-agent tool surface — ready-to-import fs tools
- Bolt.new streaming parser + ActionRunner + snapshot history
- Agent Skills progressive disclosure (Anthropic, Cursor data)
- Design-specific tool landscape (Playwright MCP, uselayout, marcoripa96/i0, Caliper, Figma MCP)
Key sources:
- https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
- https://www.cursor.sh/blog/dynamic-context-discovery
- https://github.com/sst/opencode/tree/HEAD/packages/opencode/src/tool
- https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent/src/core/tools
- https://github.com/stackblitz-labs/bolt.diy/blob/main/app/lib/runtime/message-parser.ts
File: docs/plans/2026-05-05-agent-run-protocol.md
Agent run protocol hardening
Status: implementation started on 2026-05-05.
User intent
The agent loop should feel like a visible design collaborator, not a silent one-shot generator.
For open-ended design creation, the desired rhythm is:
- Ask the user a small number of high-impact questions when the brief leaves material choices open.
- Present a concrete plan with
set_todosbefore the main build work. - Interleave short assistant text with tool calls so the user sees phase changes: inspect, write, preview, repair, finish.
- Use
set_titleproactively so new designs do not remain asUntitled design N.
This is a product behavior contract, not just prompt flavor. The runtime and prompt should make the happy path easy for the model and observable in logs.
Current evidence
Recent desktop logs for generation moshk0qh-lqddh6 showed:
generate-titlesucceeded in the renderer/main side path.- The agent tool list included
set_title,set_todos,ask, file edit, preview, and done. - The actual agent sequence skipped
set_title, then calledview frames/watch.jsx,set_todos,create App.jsx,preview, anddone. - The session row and
design-store.jsonstill showedUntitled design 1.
So the gap is not tool availability. The gap is protocol strength:
- The agent did not know that the current design title was still an auto-generated placeholder.
- Existing source/scaffold guidance made the run look like continuation work, which weakened the
set_titlerequirement. - UI auto-title was asynchronous and could leave the design visibly untitled while the agent worked.
ask()was available, but only prompt-encouraged; only the separate run-preferences router asked deterministic preference questions.
Protocol decisions
Naming
When the current design title is Untitled design or Untitled design N, the agent must call set_title once as the first tool call. This applies even if a scaffold, frame, or starter source already exists in the workspace.
The renderer should also apply a local fallback title immediately from the first prompt, then optionally replace it with the model-generated title. The visible app state should not wait on a network title request before leaving Untitled.
Questions
Use ask() for high-impact ambiguity: visual direction, artifact type, audience, content source, reusable-system vs one-off, or expensive optional controls/assets.
Do not ask about details that can be inferred safely or revised cheaply. For narrow, fully specified briefs, proceed without a question.
Planning
For any multi-step design creation, call set_todos early after title/clarification. The checklist should be concrete enough to explain the build sequence, not a generic "implement / polish / finish" list.
Visible interleaving
The system prompt should continue requiring a short assistant sentence before major phase shifts. The testable signal is event order in session JSONL: assistant text or tool groups should make the loop legible without dumping source code into chat.
Host-generated phase notes remain allowed, but only as a restrained fallback:
- emit one note only when the current turn has not produced model text yet;
- use them for high-signal transitions such as
ask,set_todos, first write,preview, anddone; - do not rely on them for state; they are visibility aids, not memory.
Stream isolation
fs_updated handling must be keyed by designId + generationId + path, not by one global pending slot. A background run may update its own preview pool entry, but it must never overwrite another design's visible preview during the throttle window.
agent_end should flush only the ending generation's pending preview updates before snapshot persistence.
Tool-result persistence
Session JSONL remains the source of truth for chat/tool rows, but persisted tool results must stay compact:
- keep visible text at or under the chat budget;
- strip or summarize large
detailspayloads, especiallypreviewscreenshots and verbosedoneresults; - preserve structured fields needed for replay: tool name, command, path, status, duration, counts, and a short error preview.
Unified scoped edits
Inline comment / point edits should use the same main generate path as ordinary follow-up prompts. Scope metadata (selector, tag, outerHTML, parent context when available) belongs in the user prompt/context pack, not in a separate weak-history revise pipeline.
Next hardening targets
- Add a deterministic preflight policy for
ask()when the router marks high-impact ambiguity, instead of relying only on model discretion. - Add log/session tests that assert
set_titleappears before file edits for auto-named designs. - Add evaluation fixtures covering concurrent design runs, compact tool-result persistence, and scoped point edits on top of existing source.
File: docs/v0.2-plan.md
v0.2 Agent Loop & Harness Plan
这份文档是 v0.2 的实施参考,由 2026-04-23~24 多轮讨论整理。
已基于 pi-coding-agent spike 结果(2026-04-24,docs/spike-pi-results.md)更新。
Spike 结论:✅ pi-coding-agent 满足全部 v0.2 硬需求,session / bash / capability / provider 全交给 pi。
0. 总原则
默认抄 coding agent 约定,只在 design-specific 场景做针对性扩展。
具体来说:
- pi-coding-agent / Claude Code / Cursor 有共识的做法 → 直接抄
- 三家不一致 → 挑最简单的
- 三家都没有,我们真有独特需求 → 才讨论发明
YAGNI 原则:早期 v0.x 可随意 breaking change,v1.0 才承诺向前兼容。
1. 非目标(v0.2 明确不做)
- Video / 3D / logo system / 矢量编辑(不是 design agent 本质)
- Bundle model runtime(Ollama / llama.cpp / 浏览器等)
- Cloud sync / telemetry / 用户账户
- 多人协作
- MCP 支持
- 社区 skill / scaffold 安装(
pi install式) - Session branching UI(引擎层 pi 支持,UI 不暴露)
- 消息队列 / steering(用户打字时 agent 跑)
- Undo / 版本回退(用户可停止,但不能回退 agent 步骤)
- Verifier subagent(有 preview 自检就够)
- Working memory agent-written(用户写 AGENTS.md / DESIGN.md)
- Snip 工具(coding agent 没有,靠 pi auto-compact)
- Per-design meta.json(session header 够)
- Sealed / Open mode split(统一 workspace model)
- 权限 mode toggle(单一模式 + 四层 Tier)
2. 核心架构
2.1 存储模型:去 SQL,走 JSONL + filesystem
~/Library/Application Support/open-codesign/
config.toml # BYOK 配置(provider / API key)
sessions/
<session-uuid>.jsonl # 每个 session(= design)一个 JSONL
thumbnails/ # 缩略图 cache
settings.json # 全局 allowedTools + 偏好
allowed-commands.json # 全局 bash allowlist(也可以合进 settings.json)
/ # 用户的真 workspace(由 Settings 默认根配置)
(用户文件)
AGENTS.md # 用户写的项目指令(可选)
DESIGN.md # 用户写的品牌 token(可选,Google spec)
.codesign/
settings.json # per-design allowlist + 偏好
settings.local.json # 个人偏好(默认 gitignore)砍掉的 SQLite 内容:
designs表 → session JSONL header 的cwd+name字段design_files表 → workspace 磁盘(真源)snapshots/snapshot_files→ 不做版本引擎(v0.3+)chat_messages→ session JSONL message entriescomments→ session JSONL 里带 anchor 的 user messagediagnostic_events→ 可选 append-only log 文件
2.2 Design == Session
没有"project"概念。Design 就是 pi session,一个 JSONL 文件。
- session header 格式 100% 用 pi v2 原生,不加字段(包括不加 designId)
cwd字段 = workspace 路径name字段 = 用户给的 design 名(pi 的/name命令)- 多个 session 可共 cwd(= "对同一 codebase 的多个对话")
- Sidebar 扁平展示 session,按
lastOpenedAt排 - Fork = 新 session(pi 的
/fork,我们引擎层支持但 UI 暂不暴露)
2.3 Workspace 统一模型
- 每个 design 必有 workspace(无 sealed mode)
- Settings 里一个配置:默认 workspace 根目录(默认
~/Documents/CoDesign/) - New Design 时默认路径
<默认根>/<design名>/,用户可自定义 - PR #173 的 Skip 按钮去掉
3. 工具清单(15 个,spike 后修订)
总计 15 个工具暴露给 agent:pi-coding-agent 自带 7 个 built-in(执行层我们不写,只 hook 拦截)+ 我们写 8 个(设计 domain 6 + 生命周期 2)。
Pi 自带 7(spike 验证白送)
| 名称 | 我们做啥 |
|---|---|
read |
直接用,pi 自带类似 view_budget 机制 |
write |
直接用 |
edit |
str_replace 风格 |
bash |
直接用,通过 tool_call hook 拦截做权限,不写新 bash 工具 |
grep |
白送 |
find |
白送 |
ls |
白送 |
Bash 权限拦截(spike 验证的实现):
pi.on("tool_call", async (event) => {
if (isToolCallEventType("bash", event)) {
const allowed = await askUserPermission(event.input.command);
if (!allowed) return { block: true, reason: "user denied" };
}
});异步、可 await Electron IPC 弹窗。同 hook 也覆盖 read/edit/write/grep/find/ls,按需扩权限粒度。event.input 可 mutate,未来 SSH 远程执行不用换工具。
Design domain 6(我们写)
| 名称 | 行为 |
|---|---|
scaffold(kind, path) |
把预装 starter JSX / CSS 片段复制到 workspace(enum kind) |
skill(name) |
懒加载 skill prompt 文本(manifest 在 system prompt 里列名字) |
ask(questions) |
渲染结构化问卷;end turn 等用户答(5 种题型:text-options / svg-options / slider / file / freeform) |
preview(path) |
渲染 artifact source(默认 App.jsx)→ {screenshot?, consoleErrors, assetErrors, domOutline, metrics};vision model 才返 screenshot |
gen_image(prompt, path) |
文生图,落盘;capability-based 暴露(仅 OpenAI key 配了才给 agent) |
tweaks(blocks) |
声明 EDITMODE 块 + 生成 UI 控件;跨文件支持;全量覆盖语义 |
Lifecycle 2
| 名称 | 行为 |
|---|---|
todos(items) |
任务列表;system prompt 强制 >3 tool call 任务首调;runtime 5-call 后软提醒;UI 钉顶展示 |
done(path) |
终止本轮;默认检查 App.jsx;有错返给 agent 修,干净则 turn 结束 |
已砍
verifysubagent(preview 自检够)snip(pi auto-compact)独立(pi 自带,spike 后改主意)list_files、自写 bashread_design_system(DESIGN.md 直接注入 system prompt)read_url(reference URL 由 host 预取、限流/限大小后作为 untrusted context 注入;不作为 agent 默认工具暴露)
Capability-based 暴露规则
Session 启动时探测 capabilities(直接读 Model<T>.input / .reasoning / .cost.cacheRead,spike 验证字段齐全):
gen_image只在 imageGen provider 配了时暴露preview对 vision model 返截图(Model.input.includes("image")),对纯文本 model 返 DOM outline + metricsread图像模式仅 vision model
4. Loop 结构
Agentic,无硬相位。
当前主线不是 tag-parser / custom streaming grammar,而是 pi function-tool loop + workspace delta stream。推荐把 harness 理解成四层:
- Run Controller:绑定
designId+generationId,执行 preflight ask、title/todos 约束、timeout/cancel、host phase notes。 - Workspace Delta Bus:把
fs_updated、preview pool、snapshot persist 作为按 design/generation/path 隔离的增量事件处理。 - Context Pack / Session Memory:brief、run preferences、workspace state、memory sections 进入 prompt;tool/artifact/error rows 不进入 LLM history。
- Verification Gate:
preview(path)提供中途检查,done(path)负责最终 gate 和 repair loop。
SESSION_START
↓
system prompt 组装(见 §5)
↓
TURN_START (user message + 可选 content blocks)
↓
AGENT_LOOP (pi-agent-core 原生)
├─ agent 思考 / 说话 / 调 tool(可并行)
├─ 工具 result 回流
└─ 终止任一满足:
· 调 done
· 调 ask(等答)
· 60 次 tool call 上限(软询问继续)
· 10 分钟 wall clock
· 用户 abort
↓
TURN_END
↓
if done 被调:
runtime 跑 preview(path)
errors → 喂回 agent → 回 AGENT_LOOP
clean → turn 结束,UI 显示成果软约束(写进 system prompt,不是 loop 强制):
- 新 / 模糊任务优先调
ask(10+ 问) - 写代码前在 chat 里 declare aesthetic(palette / type / rhythm)
- 复杂任务(>3 step)首调
todos规划 - 完成用
done,它自动 preview + 你看 console / 404 后修 - 暴露 2-5 个 tweaks("big-rock" values,不是细枝末节)
Multi-screen 视觉一致性(baton pattern)
借鉴 Google Stitch 的 baton pattern——多屏 / 多 page 项目(landing + dashboard + settings 等)保证视觉一致:
生成屏 1
↓
从产物抽 token(colors / typography / spacing / radius)
↓
更新 DESIGN.md(agent 调 edit)
↓
注入下次生成 system prompt 的 [3] 层
↓
生成屏 2 自动用同 token system
↓
... 第 N 屏不是新工具,是 prompt loop 设计:每生成一屏,agent 自检"DESIGN.md 是否需要更新",更新了下一屏自然继承。配合 §5 Brand Acquisition Protocol 形成完整 token 一致性闭环。
中断语义(对齐 Claude Code)
用户 Esc / Stop:
├─ LLM streaming → AbortSignal
├─ 当前 tool call → 级联 abort
│ └─ bash:SIGTERM → 3s → SIGKILL
├─ queued user messages → 回 editor 供重编辑
└─ 后台进程(dev server)不杀,走单独 "Processes" 面板管二次 Esc(2s 内):弹撤销菜单(恢复到 turn 前 / 删除本 turn / 什么都不做)。
半成品文件:write/edit 用 atomic temp + rename,不回滚,中断只影响未完成的写。
后台进程(tab 模型)
design tab 打开 → background process 活
design tab 关闭 → SIGTERM 进程(关前弹确认)
切换 design tab → 什么都不做,进程继续
app 退出 → TERM → KILL 所有- 每 design ≤3 进程,全局 ≤10
- Port 检测:起进程后 2s 扫 stdout 匹配 vite/next/astro/webpack 端口模式
- Processes 面板(design sidebar 固定)列活进程 + 一键 stop + 看 logs
5. System Prompt 层叠
[1] 主 system prompt 产品级(抄 Claude Design 骨架)
├─ Identity("expert designer, user as manager, filesystem-based project")
├─ Workflow(软指引 7 步)
├─ Output 规则(filename / revisions / 避坑)
├─ React + Babel pinned(SRI 整段抄 Claude Design)
├─ Content Guidelines(反 AI slop 核心)
├─ Aesthetic direction(无品牌时如何承诺)
├─ Typography 默认(Bunny Fonts / Fontshare)
├─ Tools 一览(12 个每个一行)
├─ Tweaks EDITMODE 协议
├─ Ask 规则(10+ 问 + 5 种题型)
├─ Preview / done 协议
└─ Do not divulge
[2] project_info workspace stack 探测结果(~200 字节)
[3] 用户项目级
...
<design_system source="DESIGN.md">
YAML front matter 保留原样(token 不 truncate)
Prose 部分 truncate 到 2000 字
</design_system>
[4] Available scaffolds (enum) 从 scaffold tool schema 的 kind 自动生成
[5] Available skills (manifest) 技法 + brand refs 两段
## Techniques
- oklch_color_system: ...
- bento_grid: ...
## Brand references (skill("brand:<name>"))
linear, vercel, stripe, figma, arc, ...
[6] [对话历史] pi auto-compact 兜底
[7] 本轮 user message总字符目标:base 9-10K 字符(~2.7K tokens),比 Claude Design 的 30K 小三分之二。
DESIGN.md 生命周期:协作式,agent 和用户都可编辑。
- Session 启动读,session prompt 包含
- Agent 第一次声明 aesthetic → 主动
write("DESIGN.md", ...)生成初版 - 用户外部编辑 → FSWatcher 捕捉 → 下轮重读
- 用户持续调整某 EDITMODE 值 → agent 主动 propose "promote to DESIGN.md"
Google DESIGN.md spec 完全采纳(YAML front matter + markdown body,基于 W3C DTCG),不发明自己 schema。
Brand Acquisition Protocol
灵感来自 alchaincyf/huashu-design(A/B 测结果显示降低输出方差 5×)。写进 system prompt:
## Brand acquisition (never invent brand values from memory)
When user mentions a specific brand and DESIGN.md doesn't yet exist:
1. Ask the user for brand guidelines / DESIGN.md / brand site URL
2. If they give a URL: bash `curl` the /brand or /press route
3. Download SVG / HTML / screenshots as fallback (via bash + workspace storage)
4. Extract hex values programmatically from CSS / SVG, NOT from memory
5. Codify into DESIGN.md with YAML token block
NEVER write brand color hex values from memory. Always extract from
authoritative source. If the source is unavailable, ask the user.理由:LLM 对 brand color 的 "记忆" 错误率高(即使 Linear / Stripe 这种知名品牌也有偏差),凭记忆生成的产物会"形似而神离"。强制走 acquisition protocol 把这个错误源头 close 掉。
6. 权限模型(4-Tier,抄 Claude Code)
分层
Tier 0 无感通过(不弹窗)
Tier 1 首次弹窗 + 用户选 allowlist
Tier 2 每次必弹窗(不能 suppress)
Tier 3 硬拦截(UI 拒绝,无 override)具体归类
| 操作 | Tier |
|---|---|
| 读 workspace 内文件 | 0 |
| 写 / 改 / 删 workspace 内文件 | 0 |
ls / pwd / cat / grep / find / stat(cwd 内) |
0 |
只读 git (git status/log/diff) |
0 |
pnpm install * / pnpm run * / write-git |
1 |
curl / wget 非本机 URL |
1 |
| cwd 外的任何命令 | 1 |
git push / npm publish / sudo |
2 |
rm -rf / / rm -rf ~ / curl | sh / 系统目录写 |
3 |
弹窗 UX(三按钮)
┌─────────────────────────────┐
│ 🟡 Agent 想运行 │
│ │
│ pnpm install │
│ │
│ [拒绝] [允许] [总是允许] │
└─────────────────────────────┘- 默认 scope = per-design + 命令前缀(
pnpm install *) - 想更宽 / 更窄去 Settings 编辑 allowlist
Allowlist 存储
<workspace>/.codesign/settings.json(per-design,可 commit):
{
"schemaVersion": 1,
"allowedTools": [
"Bash(pnpm install *)",
"Bash(pnpm run *)",
"Bash(git status)"
]
}全局:~/.codesign/settings.json(同格式)。加载顺序:global → project → local(settings.local.json,gitignore 默认)。
7. Progressive Disclosure
三层独立机制:
源头 budget(预防膨胀)
read: view_budget(首次全文,重复摘要 + 强制 view_range,mtime 变化重置)bash: stdout tail-cap 10KB + exit codepreview: screenshot 压缩 + console ≤50 条 + 404 ≤20 条grep: head_limit 250
按需披露
- Skill manifest 在 system prompt 列名字(~500 字节)
skill(name)调用时返全文(~500-2000 字节/次)- Scaffold enum 在 tool schema(~200 字节)
scaffold(kind, path)执行时写磁盘 + 返短路径确认- 一个 session 内重复
skill(name)→ 返短"already loaded",不重复灌
Tool result 不做类型特定剪枝
(coding agent 都不做,我们也不)pi auto-compact 兜底。
Tweak / Inline-edit / Comment delta
直接操纵的 delta 攒 buffer,下次 user chat 时附带到 content block:
<tweak_changes><direct_edits>(inline text edit)- 评论立即发,不攒
8. UI 集成
已有的(PR #173 / v0.1 带来)
HubView→ Hub 页面DesignSwitcher/DesignsView→ session listModelSwitcher→ 模型切换(mid-session 可用)FilesPanel/FilesTabView/CanvasTabBar→ 右 panePreviewPane/PhoneFrame→ 预览InlineCommentComposer→ 评论带 anchorSettings/+AddCustomProviderModal→ BYOK 配置RenameDesignDialog/DeleteDesignDialog→ CRUD- Runtime
tweaks-bridge.ts→ EDITMODE postMessage 基础
要新增的
| UI 组件 | 用途 | 工作量 |
|---|---|---|
AskModal |
ask 工具弹的结构化问卷 |
M |
PermissionDialog |
bash 三按钮弹窗 | S |
TweakDeltaChip |
Chat input 里的 tweak 变更附件 chip | S |
TweaksPanel |
artifact 里的 slider / color picker 面板 | M |
ProcessesPanel |
design sidebar 的后台进程列表 | M |
MigrationDialog |
v0.1 → v0.2 迁移弹窗 | S |
ScaffoldPicker(optional) |
scaffold() 调用时的可视化挑选 |
M |
事件流到 React
两条独立通道:
pi event stream (tool calls / messages / thinking)
↓ IPC
Chat pane + activity feed
Workspace FSWatcher (chokidar)
↓ IPC
Files tab + preview tab(热刷新)Files tab 不跟 tool call 事件关联——只看磁盘真实状态。外部编辑(VSCode)自然生效。
9. Gap Analysis(已有 vs 要做)
工具层
| 现有 / 来源 | 对应 v0.2 | 状态 |
|---|---|---|
| pi-coding-agent 自带 read/write/edit/bash/grep/find/ls | 7 个 built-in | ✅ 直接用,只写 tool_call hook 加权限 |
| 现有 set-todos | todos | ✅ 保留 |
| 现有 done | done | ✅ 保留(含 runtime verifier hook) |
| 现有 declare-tweak-schema | tweaks | ✅ + 改跨文件 |
| 现有 generate-image-asset | gen_image | ✅ + capability gate |
| 现有 read-url | - | ❌ 砍(Reference URL 走 host 预取 + untrusted context) |
| 现有 text-editor | - | ⚠️ 当前保留为 str_replace_based_edit_tool;pi 自带 read/write/edit 后可砍 |
| 现有 list-files | - | ❌ 砍(pi 自带 ls / edit tool directory view 覆盖) |
| 现有 read-design-system | - | ❌ 砍(DESIGN.md 直接注入) |
要新建的工具(**3 个**,spike 后大幅精简)
ask+ 结构化问卷 + AskModal UIscaffold工具 + 预装目录packages/core/src/scaffolds/skill(invoke_skill) + manifest 生成 + 懒加载 + 去重preview从done里拆出独立工具(半个新 + 半个改造)→ spike 后改为只写 hook(不算独立工具)bash
存储层(spike 后大幅简化)
| 之前计划 | spike 后 |
|---|---|
✅ 直接用 pi 的 SessionManager(spike 验证 sessionDir 完全可指定) |
|
model-caps.ts capability 表 |
✅ 直接读 Model<T>.input/reasoning/cost(spike 验证字段齐全) |
✅ 直接用 pi.registerProvider()(spike 验证 baseUrl override 可用) |
|
| v0.1 → v0.2 迁移脚本 | ✅ 仍要写:扫旧 SQLite → 转 JSONL via SessionManager.appendXXX |
| config.toml → pi.registerProvider 翻译层 | ✅ 仍要写:BYOK 配置注入 |
集成层
- ✅ Pi-coding-agent 集成 spike — 已完成(见
docs/spike-pi-results.md) - System prompt 主体内容写满
- Progressive disclosure:read view_budget pi 已有,bash tail-cap 在 hook 里加,preview 压缩自写
仍要写的代码(v0.2 实际工作量)
- ✅ Electron IPC 桥(wrap
createAgentSession(),单 session 一个 BrowserWindow) - ✅ Permission Dialog UI(被
tool_callasync hook 调) - ✅ config.toml →
pi.registerProvider()翻译 shim - ✅ Sandbox 渲染器(packages/runtime,已有,扩展)
- ✅ Artifact / exporter(packages/artifacts, packages/exporters,已有)
- ✅ FSWatcher → Files tab(独立通道)
- ✅ 4 个工具:scaffold / skill / ask / preview
- ✅ tweaks 改跨文件
- ✅ v0.1 → v0.2 迁移脚本
10. Pi-coding-agent 集成(已完成 spike)
✅ 已通过——见 docs/spike-pi-results.md(2026-04-24)。
Spike 结论摘要
| 验证 | 结果 | 关键 API |
|---|---|---|
| A. bash 拦截 hook | ✅ Pass | pi.on("tool_call", async (event) => { return { block, reason } }) |
| B. Session storage | ✅ Pass | SessionManager.create(cwd, sessionDir) 完全扁平,文件名 _.jsonl |
| C. Model capability | ⚠️ Partial(实际 Pass) | Model<T> 有 reasoning / input / cost / contextWindow / maxTokens |
v0.2 架构落地(基于 spike 结论)
- Session:
SessionManager.create(cwd, "/sessions"),扁平存储 - Bash 权限:
tool_callhook + 我们 Permission UI(不写新 bash 工具) - Capability:
Model<T>直读,无 fallback 表 - Provider:
pi.registerProvider()从 config.toml 翻译注入 - AuthStorage:
AuthStorage.create(authPath)指向我们的 userData,配合 config.toml 双轨
Spike 中发现的几个坑(写进实施 checklist)
- session 文件名是
_.jsonl,不是纯 uuid Model.provider运行时是 string,不是 object(类型说谎)ModelRegistry.getAll()不是getAllModels()- pi-ai 要 pin
^0.69.0,不要让 pnpm 默认装 0.67.x - 自定义 gateway 用
pi.registerProvider("anthropic", { baseUrl }),不靠 env
Bonus 发现(v0.3+ 可白嫖)
SessionManager.forkFrom()— 程序化 fork sessionsession.navigateTree(targetId)— 内置版本/分支 UX- 19+ 事件(before_provider_request / after_provider_response / compaction_start_end / auto_retry_*)
- OAuth provider 支持(未来 Claude Code OAuth 续接零代码)
--mode rpc子进程 escape hatch
11. v0.1 → v0.2 迁移
策略
v0.2 首次启动:
- 检测
app.getPath('userData')/designs.db存在 → 弹框"检测到 X 个 v0.1 designs,迁移吗?" - 一键迁移:
- SQLite 读
designs/design_files/chat_messages/comments - 每 design 在
~/Documents/CoDesign/<slug>/创 workspace - 转 chat_messages → session JSONL
- 转 design_files → workspace 磁盘文件
- 转 comments → JSONL 里 content block
- SQLite 读
- 跳过:旧 SQLite 备份为
designs.db.v0.1.backup,不读 - 迁移完 + backup 保留,允许用户手动清
保留不碰
config.toml(API key)继续读,只新增defaultWorkspaceRoot字段- 用户 workspace 里的 web artifact source(劳动成果)不动
12. 资源清单
12.1 Scaffolds(预装 starter templates)
目标 ~30 个精品。Bundle 预算 ~150-200KB 总内嵌代码(gzip 后 40-50KB)。
P0 — v0.2 必装(9 个,核心视觉独特)
| kind | 来源 | License | 工程量 | 独特度 |
|---|---|---|---|---|
neubrutalism-kit |
OshekharO/Neubrutalism 40+ 组件 70KB CSS,CDN 可引 | MIT | S (link) | 4/5 |
aurora-mesh-bg |
ibelick/background-snippets 2K⭐,CSS+Tailwind | MIT | S | 4/5 |
glassmorphism-surface |
ibelick/background-snippets(同仓,已合 PR) | MIT | S | 3/5 |
bento-grid |
Kishan-shr/bento-grid-ui 纯 HTML+CSS,无 JS | MIT | S | 4/5 |
terminal-mockup |
ramazancetinkaya/terminal-simulation 单文件 HTML+CSS+JS | MIT | S | 4/5 |
vscode-mockup |
DIY ~200 行 JSX(现成方案都要 xterm.js+node-pty) | — | L | 5/5 |
arc-browser-chrome |
DIY ~180 行 JSX(所有现成都是浏览器扩展) | — | L | 5/5 |
toast-notification + drawer-sheet |
emilkowalski/sonner 12K⭐ + vaul 8K⭐,esm.sh CDN 可引(待实测) | MIT | S | 4/5 |
slide-deck-16-9 |
reveal.js CDN + ~60 行 wrapper | MIT | S | 3/5 |
P0 — Device frames(已有升级)
| kind | 状态 | 来源 |
|---|---|---|
iphone-frame |
现有 iphone.jsx 保留 |
自写 |
iphone-16-pro-frame |
升级:devices.css(picturepan2/devices.css MIT)+ 手加 2024 notch | MIT |
ipad-frame / watch-frame / android-frame / macos-safari-frame |
现有保留 | 自写 |
macbook-pro-16-2024 |
基于 devices.css + notch override | MIT |
chrome-browser-chrome |
magnitce-browser-mockup Web Component | CC0 |
vision-pro-spatial |
DIY ~150 行 JSX | — |
foldable-phone-frame |
DIY ~100 行 JSX(Galaxy Fold / Pixel Fold 两态切换) | — |
P1 — 产品常见(v0.2 做 5-7 个)
| kind | 来源 | License | 工程量 |
|---|---|---|---|
kanban-board |
janhesters/shadcn-kanban-board 零依赖纯 React DnD | MIT | M |
cmdk-palette |
自写轻量版(pacocoursey/cmdk 要 Radix 不适 srcdoc) | MIT ref | M |
skeleton-loader |
纯 CSS 动画模板集,~5 种变体 | — | S (DIY) |
empty-states-kit |
自写 5-10 种不同风格 | — | M (DIY) |
landing-hero |
launch-ui/launch-ui 739⭐,section 可独立抽取 | MIT | M |
stepper-wizard |
自写 ~80 行 | — | S (DIY) |
file-tree |
pansinm/react-file-tree | MIT | M |
P2 — 美学 / 背景层(v0.2 做 2-3 个)
| kind | 来源 | License | 工程量 |
|---|---|---|---|
noise-grain-overlay |
SVG feTurbulence inline data URI,~5 行 CSS |
技术通用 | S |
dot-grid-bg |
CSS radial-gradient 1px dot |
技术通用 | S |
animated-gradient-bg |
codse/animata 80+ 动画组件,抽取 | MIT | S |
P2 bonus — 惊喜发现
| kind | 来源 | 说明 |
|---|---|---|
voxcss-scene |
LayoutitStudio/voxcss 419⭐ MIT CDN 可用 HTML voxel 引擎 | 非常独特,可选 |
待实测 / 推后
- esm.sh CDN 在 Babel Standalone srcdoc iframe 的兼容性(sonner / vaul 要验证)
motion-primitives/data-table/settings-panel/chat-ui/pricing-table/blog-editorial/doc-page/portfolio-grid/type-specimen等推后 v0.3+
Bundle 结构
packages/core/src/scaffolds/
manifest.json # kind → {description, path, size, license, source}
device-frames/
iphone.jsx # 现有保留
iphone-16-pro.jsx # 新
ipad.jsx
watch.jsx
android.jsx
macos-safari.jsx
macbook-pro-16-2024.jsx
vision-pro.jsx # DIY
foldable.jsx # DIY
browser/
chrome.js # magnitce Web Component
safari.jsx # DIY
arc.jsx # DIY
dev-mockups/
terminal.html # ramazancetinkaya 单文件
vscode.jsx # DIY
claude-code-tui.jsx # DIY (optional v0.3)
ui-primitives/
cmdk-palette.jsx # 自写
kanban-board.jsx # janhesters 改写
toast.jsx # sonner 包装
drawer.jsx # vaul 包装
skeleton-set.jsx # DIY
empty-states.jsx # DIY
stepper.jsx # DIY
file-tree.jsx # pansinm 改写
backgrounds/
aurora-mesh.css
glassmorphism.css
bento-grid.css
noise-grain.css
dot-grid.css
animated-gradient.css
surfaces/
neubrutalism.css # OshekharO CDN wrapper
decks/
slide-16-9.html # reveal.js 骨架
landing/
hero.jsx # launch-ui 抽取合计约 30 个 scaffold,工程量分布:~12 个 S(直接 bundle/CDN link),~12 个 M(改写、包装),~6 个 L(DIY 100-200 行)。
12.2 Skills(v0.2 目标 12 现有 + 5 新增 P0)
格式:抄 agentskills.io / Anthropic SKILL.md spec
---
name: form-layout
Apply when building any form with 3+ fields, multi-step wizards,
onboarding flows, checkout flows, or settings screens.
version: 0.1.0
authors: [open-codesign]
tags: [design, form, ux]
license: MIT
---
## When to use
## Rules
## Do / Don't
## Code patterns内部 skill() 调用名使用 snake_case(e.g. skill("form_layout")),SKILL.md 文件名 / name 字段用 kebab-case(e.g. form-layout/SKILL.md)。别名映射层处理。
现有 12 个 skill — 保留并升级
| skill | 升级内容 | 源 |
|---|---|---|
dashboard |
加 Vercel Geist scale (label-14/copy-14)、APCA contrast rule、4-tier surface、nested radii | vercel-labs/web-interface-guidelines + vercel.com/geist/typography |
landing-page |
加 blueprint grid 模式、View Transitions for scroll reveal、APCA for hero text | Vercel blueprint article |
glassmorphism |
合并进 surface-elevation(保留 alias 向后兼容) |
— |
editorial-typography |
加 Swiss grid spec、pull-quote grid-break、drop-cap、APCA body | Bringhurst + Swiss typography |
chart-svg |
加 APCA 调色板、色盲友好 palette(形状冗余) | Vercel guidelines |
heroes |
加 View Transitions、scroll-linked reveal、CJK text-autospace |
CSS scroll-driven |
slide-deck |
加 investor deck ratio + Geist dark variant | mblode presentation-creator |
pricing / footers / chat-ui / data-table / calendar |
保持,加 APCA contrast rule 提醒 | — |
v0.2 新增 P0(5 个)
| skill | 何时用 | 关键规则(3-5 条) |
|---|---|---|
form-layout |
任何 3+ 字段表单 / onboarding / 结账 / 设置 | 单列为主;label 在字段上方(禁用 placeholder 当 label);inline validation 在 blur 后而非打字时;多步在逻辑接缝切分 + progress;44px 最小触摸目标 |
empty-states |
Dashboard panel / 搜索结果 / 首次使用 | 三类:first-use(教育+CTA)/ no-results(reframe+建议)/ error(原因+重试);必带 action button;不准出现裸 "No data" |
loading-skeleton |
任何形状可预测的异步内容 | 骨架仅在形状可预测时用;匹配元素几何;progressive(先文本后可变);形状不可预测时转 spinner;10-30s 超时转 error+retry;不做全屏 spinner |
surface-elevation(扩 glassmorphism) |
卡片 / 模态 / 下拉 / 层级 UI | 层级靠 lightness 而非单一阴影;4-tier: base/raised/overlay/scrim;dark mode 每层 L +5-8%;layered shadow(ambient+direct 至少 2 层);nested radius(child ≤ parent) |
cjk-typography |
任何含中/日/韩的页面 | line-height: 1.7-1.8 for CJK body;word-break: normal 简中;line-break: strict 日文;font stack: PingFang SC → Noto Sans SC → system;禁给 CJK 加 letter-spacing;CJK+拉丁混排用 text-autospace 或 U+2009;body 16-18px |
P1 延后(v0.3 候选,~5-7 个)
oklch_color_system / micro_motion / bento_grid / neo_brutalist / scroll_narrative / investor_deck / navigation-patterns / whitespace-rhythm / icon-system / page-transitions / color-accessibility
P1 — 借鉴 huashu-design 的两个 skill
灵感来自 alchaincyf/huashu-design:
| skill | 何时用 | 内容 |
|---|---|---|
direction-advisory |
用户没明确方向 / "随便给 3 个看看" | 从 5 个设计学派 × 20 哲学中抽 3 个不同风格生成 demo,让用户选。Taxonomy 直接抄 huashu-design 的清单 |
expert-review |
用户明确说"review 一下"或 agent 想自检 | 5 维评分:philosophical consistency / hierarchy / execution / functionality / innovation。LLM 对 preview screenshot 做 critique(仅 vision model) |
expert-review 是轻量级 verifier 的复活路径——不是 v0.2 的硬 loop subagent,是用户主动 / agent 主动调的 skill。代码量 = 一段 prompt,没有架构改动。
外部 skill 资源(供升级内容源)
| 源 | URL | License | 用途 |
|---|---|---|---|
anthropics/skills |
github.com/anthropics/skills | Apache-2.0 | 官方 frontend-design,基线参考 |
mblode/agent-skills |
github.com/mblode/agent-skills | MIT | ui-design / ui-animation / typography-audit / presentation-creator 质量高 |
vercel-labs/web-interface-guidelines |
github.com/vercel-labs/web-interface-guidelines | public | dashboard / landing-page 升级源 |
PatrickJS/awesome-cursorrules |
39K⭐ | CC0 | CSS/styling 规则 pattern 挖掘 |
| Evil Martians oklch 文章 | evilmartians.com | public | oklch skill 内容源 |
| neubrutalism.com | MIT | — | neo-brutalist skill 内容源 |
| Muzli dark mode guide | medium.muz.li | public | dark-mode-done-right 源 |
12.3 Brand References(DESIGN.md 集合)
我们 deliver 的文件 = Google DESIGN.md spec 合规(YAML front matter + markdown body,基于 W3C DTCG)。source 是什么格式无所谓——任何描述品牌的素材(prose、CSS、截图、官方风格指南)都可以用来构造我们的合规文件。
主素材源
| 源 | 内容 | License | 怎么用 |
|---|---|---|---|
| VoltAgent/awesome-design-md (62K⭐) | 69 个品牌的 9 段精写 prose(Visual Theme / Color Palette / Typography / Components / Layout / Depth / Do's-Don'ts / Responsive / Agent Prompt Guide) | MIT, 明示 "extracted from public CSS" | 直接用作我们 DESIGN.md 的 markdown body 部分 |
| 官方品牌网站 CSS | 真实 hex / px / font-family | public | 程序化抽取 token 填 YAML front matter |
| brandmd | URL → prose DESIGN.md 自动生成 | MIT | 教用户后续自助生成新品牌 |
注:VoltAgent 和 brandmd 自身都是 prose-only(无 YAML),不能直接 npx @google/design.md lint 通过。但这不是问题——我们用他们的内容作素材,自己组装合规文件。
我们的产出
packages/core/src/brand-refs//DESIGN.md,每个文件结构:
---
# YAML front matter(机读 token,我们组装)
colors:
primary: "#0070F3"
...
typography:
display:
fontFamily: "..."
...
spacing:
...
components:
...
---
## Visual Theme & Atmosphere
(来自 VoltAgent prose)
## Color Palette & Roles
...
(其余 prose 来自 VoltAgent)
---
*Inspired by [Brand]. Tokens derived from publicly available CSS.
Not affiliated with brand owners. Source: VoltAgent/awesome-design-md (MIT).*工程量
- 25 brand × ~30 分钟 = ~12 小时一次性投入
- CI 跑
npx @google/design.md lint校验 - 一两天搞定,集中干
推荐 25 个清单
| 品牌 | 类别 | 设计方向 |
|---|---|---|
| Vercel | Dev Tools | 极简 monochrome |
| Linear | Productivity | 工程师审美深色 |
| Stripe | Fintech | 渐变 premium |
| Figma | Design Tools | 黑白 + 产品色 |
| Notion | Productivity | 温暖衬线编辑器 |
| Apple | Consumer | 留白电影感 |
| Airbnb | E-commerce | 珊瑚暖色摄影 |
| Spotify | Media | 深色 + 绿 neon |
| Shadcn / Cursor | Dev Tools | 深色 IDE |
| Supabase | Backend | 翠绿开发者 |
| PostHog | Analytics | 刺猬玩味 |
| Framer | Design Tools | 黑蓝运动感 |
| RunwayML | AI/Creative | 电影暗色 |
| Mistral AI | AI | 法式紫调极简 |
| ElevenLabs | AI/Audio | 暗色听觉美学 |
| Coinbase | Fintech | 机构信任蓝 |
| Revolut | Fintech | 深色渐变卡 |
| Nike | E-commerce | 全黑大写 Futura |
| Ferrari | Luxury | 黑白稀疏 + 红 |
| SpaceX | Tech | 极简全黑白 |
| Starbucks | Retail | 大地绿 |
| Shopify | E-commerce | 深色霓虹绿 |
| IBM | Enterprise | Carbon 结构化 |
| Raycast | Dev Tools | 深色 + 渐变 accent |
| Cal.com | SaaS | 中性简洁 |
skill("brand:<name>") 懒加载,system prompt manifest 里列 25 个 brand 名字(~300 字节)。
License / 合规
- VoltAgent 内容 MIT,我们用作素材没问题
- 我们 deliver 的文件加 attribution("Inspired by [Brand]. Source: VoltAgent (MIT).")
- 大品牌(Apple / Nike / Ferrari)理论上有商标灰区——属行业惯例(Figma plugins / Style Dictionary 都这么做)
- 不主张所有权,标注来源即可
推荐用户路径(v0.2 里写进文档)
用户想要预装清单外的品牌:
npx brandmd https://yourbrand.com生成 prose 草稿npx @google/design.md lint校验 + 手补 YAML- 落到自己 workspace 根目录的
DESIGN.md
DESIGN.md 是双向 artifact(借鉴 Stitch)
不只是 system prompt 注入材料,也是生成物之一:
- 输入:workspace 根的 DESIGN.md 自动注入 system prompt(Brand acquisition / brand skill 路径)
- 输出:agent 可以
done("DESIGN.md")产出合规 DESIGN.md(YAML + prose),用户可导出或让其它工具消费 - 跨工具兼容:我们生成的 DESIGN.md 可以被 Stitch / Cursor / Claude Code 直接读
- Stitch DESIGN.md 反向导入:用户从 Stitch 导出的 DESIGN.md 拖进 workspace,我们 agent 立刻"懂"该品牌系统
packages/artifacts 加 design-system artifact 类型,schema 100% 兼容 google-labs-code/design.md。CI 跑 npx @google/design.md lint。
13. Phase 规划(基于 spike 结论重估)
Phase 1 — Foundation(3-5 天,spike 后大幅缩减)
- Pi-coding-agent 集成 spike — 已完成
- 等 PR #173 merge OR 直接 branch dev/v0.2 from main 并行(推荐后者)
- 从 main checkout
dev/v0.2 -
packages/core重构骨架:包createAgentSession(),暴露 IPC - config.toml →
pi.registerProvider()翻译层 - AuthStorage 路径替换到 userData
Phase 2 — 工具 + 存储(1-2 周,spike 后大幅缩减)
-
tool_callhook + Permission Dialog UI(bash 权限流) - FSWatcher → Files tab 通道
- v0.1 → v0.2 迁移脚本(SQLite scan → SessionManager.appendXXX)
- 删除 SQL 相关 IPC(snapshots-db / chat-messages-db / comments-db)
- Session JSONL 接通现有 chat pane 渲染
Phase 3 — Design-domain 工具(1-2 周)
-
ask工具 + AskModal UI(5 种题型) -
scaffold工具 + 预装清单组装(Phase 2 并行准备 starter 文件) -
skill工具 + manifest 生成 + 懒加载 + 去重 -
preview工具拆分(从done拆,加 capability 分支:vision → screenshot, 否则 → DOM outline) -
tweaks改跨文件 + scaffold 集成 EDITMODE 块
Phase 4 — System prompt + 资源预装(3-5 天)
- 主 system prompt 内容按 §5 写满(含 Brand Acquisition Protocol)
- Scaffold bundle(~30 个,按 §12.1 优先级)
- Skill bundle(5 新增 + 现有升级)
- Brand refs bundle(~25 个 reformat,按 §12.3 清单)
Phase 5 — UX 抛光 + 测试(3-5 天)
- 中断 / 后台进程精细化(
tool_callevent 已是基础,加 SIGTERM 流程) - Capability-based tool exposure(spike 已验证,集成)
- Progressive disclosure 兜底
- E2E 测试 + bug bash
- Release note + upgrade doc
重估总计:~4-5 周单人,2-3 周双人。比 spike 前估的 6-8 周缩减 1/3。
主要节省来自:
- bash 不用自写(节省 1-2 周)
- session 存储不用自写(节省 1 周)
- model capability 不用维护表(节省几天)
14. 开放问题 / 风险
必须 spike 验证的
- pi-coding-agent 的 bash hook 接口是否存在 — 已验证 Pass
- pi 的 Model 类型是否暴露 vision capability — 已验证 Partial→Pass
- pi SessionManager 能否指定 storage 目录 — 已验证 Pass
设计未完全定的
- Preview 工具对非 web artifact source(SVG / 图像)的渲染策略
- Agent 外部 workspace(未绑 workspace 的 edge case):其实已决"必有 workspace",但 app 首次启动 + 无默认根路径时的降级
- Export / Claude Code 手递 bundle 具体 schema(v0.2 可先简化 zip + README)
- 轻量 visual verify:v0.2 砍了 verifier subagent;huashu-design 用 Playwright 跑视觉验证。是否在 v0.2.x 加一个
expert-reviewskill(agent 自调,对 preview screenshot 做 5 维评)?
产品 / 业务风险
- Brand refs license 合规:VoltAgent repo 自身合规性 + 我们 bundle 的 attribution(待调研结果)
- Google DESIGN.md spec alpha 期可能 breaking change → 我们跟进策略
- pi-ai / pi-agent-core 版本追踪:pin 死会错过更新,追 latest 可能炸
性能 / scalability(暂不处理)
- 大 session(500+ turns)UI 虚拟化
- 大 workspace(5000+ files)FSWatcher 开销
- 多 design 并发 dev server 资源
15. 附录:关键决策快速查表
| 决策 | 选项 | 结果 |
|---|---|---|
| 存储 | SQL / JSONL | JSONL + filesystem |
| Design 模型 | 独立实体 / session | session |
| Workspace | 分 sealed/open / 统一 | 统一,默认根目录 |
| 工具数量 | 55 (Claude Design) / 12 | 12 |
| Loop 结构 | 相位 / agentic | agentic,软引导 |
| 权限 | 无 (pi) / 多 mode (Claude Code) / 单 mode 4-tier | 单 mode 4-tier |
| Verifier subagent | 有 (Claude Design) / 没有 | 没有 |
| Working memory | 有 / 没有 | 没有,用 AGENTS.md |
| Snip 工具 | 有 / 没有 | 没有 |
| DESIGN.md | 自发明 / 抄 Google | 抄 Google spec |
| Skill 格式 | 自发明 / 抄 agentskills.io | 抄 agentskills.io |
| Brand refs | 无 / 抄 awesome-design-md | 抄并预装 25-30 个 |
| JSX 默认 | 每任务判断 / 默认 JSX | 默认 JSX + 代码简洁规则 |
| 向前兼容 | 严格 schemaVersion / 早期宽松 | v0.x 宽松 |
| Screenshot 截图 | 每次评论自动截 / 用户主动 | 用户主动粘 |
| Verifier 代替 | preview 自检 | preview 自检 |
| 消息队列 | 抄 pi / 不做 | 不做 |
| Session 分支 UI | 暴露 / 隐藏 | 隐藏(引擎支持,UI 不给) |
| Undo | 做 / 不做 | 不做(只 Stop/Esc) |
Last updated: 2026-04-24. 待后台 3 个调研(scaffolds / skills / brand refs)全部完成后补充资源清单具体条目。
File: docs/VISION.md
Vision — Open CoDesign
Locked product decisions. Update via PR, not in passing.
One-line pitch
Open-source desktop design agent. It turns prompts, local files, skills, and brand systems into polished design artifacts on your laptop, with the model you choose.
What we are building
Open CoDesign is a local-first Electron app for creating design artifacts with an agent that can see and edit a workspace. Each design is a long-running session backed by JSONL history and real files on disk.
The app serves founders, PMs, marketers, designers, and design engineers who want to make:
- Interactive web artifacts authored as HTML/JSX/CSS/SVG sources across mobile, desktop, tablet, and custom artifact sizes
- Slide decks, one-page reports, case studies, marketing pages, and export bundles
- Multi-artifact projects such as landing page + pricing page + onboarding email
- Brand-aware mockups driven by
DESIGN.md, local files, and built-in brand references - Design systems that can be exported, edited, and reused by other tools
The product started as an open-source counterpart to Anthropic's Claude Design. The v0.2 direction is broader: a local design agent that borrows proven coding-agent mechanics, then adds design-specific tools for scaffolds, skills, preview, tweaks, images, and brand acquisition.
What we are NOT building
- Not a general software engineering agent. The agent may read, edit, run commands, and manage files, but the product boundary is design artifacts and design-system handoff.
- Not a Figma replacement — we don't do collaborative vector editing.
- Not a Canva replacement — we don't ship a stock asset library or template marketplace.
- Not hosted SaaS. No account, cloud sync, or telemetry is required.
- Not a plugin marketplace in v0.2. Community skill/scaffold installation is deferred.
- Not a bundled local-model distribution. Local models can be used through system installs or compatible endpoints.
Locked decisions
| Decision | Choice | Rationale |
|---|---|---|
| Form factor | Electron desktop (Mac + Win) | Local file access, codebase scan privacy, complements open-cowork |
| Agent runtime | pi-coding-agent + pi-ai |
Use proven session, tool, provider, bash, and capability primitives instead of rebuilding them |
| Model layer | pi-ai |
Multi-provider coverage for Anthropic, OpenAI, Gemini, DeepSeek, local, and compatible gateways |
| Authentication | BYOK, no hosted account | No backend, no liability for user keys |
| Storage | JSONL sessions + workspace filesystem | Design history is inspectable, backup-friendly, and aligned with pi sessions |
| Workspace model | Every design has a workspace | No sealed/open split; files are the source of truth |
| Design system format | Google DESIGN.md spec |
Portable, editable by users, and usable by other tools |
| Design resources | Built-in skills, scaffolds, and brand refs | Improve taste through progressive disclosure rather than a huge prompt |
| Design language | Aligned with open-cowork and local packages/ui tokens |
Keeps the shell coherent while artifacts bring their own style |
| Package manager | pnpm + Turborepo | Workspace, caching, fast |
| Lint/format | Biome (single tool) | Lessons learned from open-cowork's ESLint+Prettier complexity |
| License | MIT | Matches the public repo and keeps reuse simple |
| Contributor agreement | DCO (Signed-off-by) |
Lower friction than CLA |
Product pillars
1. Design as Session
A design is a pi session with a workspace. The sidebar shows sessions, not abstract projects. cwd points at the workspace; the session name is the design name. Multiple sessions can share one workspace.
2. Files Are Real
The agent writes source files such as App.jsx, CSS, DESIGN.md, assets, and exports to disk. The preview runtime turns source files into rendered web documents; the Files tab watches the filesystem rather than trusting tool-call logs. External edits from VS Code or Finder are first-class.
3. Agentic Loop, Soft Phases
The agent can plan, read files, edit files, run allowed commands, call design tools, preview output, ask structured questions, and finish through done(). The system prompt guides the loop; the runtime does not hard-code design phases.
The harness architecture for this loop is:
- Run Controller — owns
designId+generationId, preflight questions, title/todo protocol, cancellation, timeout, and phase events. - Workspace Delta Bus — streams file mutations, preview updates, and snapshot persistence per design/generation instead of through one global pending slot.
- Context Pack / Session Memory — workspace files plus compact brief are authoritative; model history stays bounded and excludes bulky tool payloads.
- Verification Gate —
preview(path)is the mid-turn visual/runtime check, anddone(path)is the finalization gate that either passes or returns compact repairable errors.
4. Progressive Disclosure
Skills and scaffolds are indexed in the prompt and loaded on demand. The base prompt stays small. Brand references and design techniques become tools the agent can pull when needed.
5. Brand Systems as Artifacts
DESIGN.md is both input and output. Users can bring one from another tool, edit it by hand, or ask Open CoDesign to create one. Brand values are extracted from authoritative files or URLs, not invented from model memory.
6. Local Control
The user owns model choice, API keys, workspace files, sessions, allowed commands, and exports. Networking is visible and tied to user intent.
v0.2 Success Criteria
v0.2 is the shift from single-prompt generator to local design agent:
- A new design creates or binds a workspace under the user's default workspace root.
- Sessions persist as JSONL files through pi's
SessionManager. - The app migrates v0.1 SQLite designs into workspaces and session history.
- The agent uses pi built-ins for read, write, edit, bash, grep, find, and ls, with our permission hook.
- Design-specific tools cover
ask,scaffold,skill,preview,gen_image,tweaks,todos, anddone. DESIGN.mdis loaded into context and can be produced as a design-system artifact.- Built-in scaffolds, skills, and brand references ship with license metadata and lazy loading.
- Preview self-checks console errors, missing assets, DOM outline, and screenshots when the model supports vision.
v1.0 Success Criteria
The v1.0 bar remains demo-driven, but the demos should run through the agentic workspace model:
- Mobile app prototype with a device frame and real navigation
- Client case study one-pager exportable as PDF
- B2B SaaS pitch deck exportable as PPTX
- Point-and-prompt revision through preview selection or comments
- AI-emitted tweak controls across one or more files
- Codebase or
DESIGN.mddriven design-system inheritance - Web or brand capture through the acquisition protocol
- Handoff ZIP with artifacts, assets,
DESIGN.md, and an intent README
Differentiation vs Claude Design
| Axis | Claude Design | open-codesign |
|---|---|---|
| Model | Opus 4.7 only | Multi-provider via pi-ai and compatible gateways |
| Form | Web SaaS | Local desktop |
| Storage | Cloud-stored | JSONL sessions + local workspace files |
| Backend | Anthropic + Canva | None |
| Agent mechanics | Closed | pi-coding-agent primitives plus design tools |
| Brand systems | Internal | Portable DESIGN.md |
| Source | Closed | MIT |
| Cost | Subscription | BYOK token cost only |
Non-goals (explicit)
- Real-time multi-user collaboration
- Built-in stock photo / icon library (link out instead)
- Mobile companion app
- Self-hosted server mode
- Custom in-house models
- MCP support in v0.2
- Session branching UI in v0.2
- Undo / version rollback in v0.2
Ecosystem positioning (deferred)
Several axes stay deferred until the workspace agent is solid:
- Claude ecosystem compat: parse Claude Artifacts
<artifact>tag protocol; expose ourselves as MCP server for Claude Code - open-cowork ecosystem: shared
packages/ui, shared sandbox runtime, artifact handoff conventions, and optional plugin integration - Stitch / DESIGN.md ecosystem: import and export
DESIGN.mdcleanly enough that other tools can consume our design systems - Community resources: user-installable skills, scaffolds, and brand refs
Versioning milestones
0.1— single-prompt design generation, local persistence, model setup, preview, comments, tweaks, and exporters0.2— agentic workspace loop using pi sessions, JSONL, permissioned tools, scaffolds, skills, preview, andDESIGN.md0.3— multi-artifact orchestration, richer brand/design-system workflows, and optional session branching UI0.5— all v1.0 demos work on the agentic workspace model1.0— installer budget green, distribution polished, migration reliable, all demos pass smoke tests
File: examples/calm-spaces/README.md
Demo · Calm Spaces meditation app
The "Calm Spaces" mobile prototype is the headline first demo for Open CoDesign,
mirroring the marquee Claude Design example (see docs/research/01-claude-design-teardown.md).
What it generates
A single self-contained HTML artifact rendering a phone-frame mockup of a
meditation app home screen — meditation list, play button, soft greens/blues
palette, and tunable design tokens via CSS custom properties on :root.
Run it
# 1. Provide a dev API key (Anthropic key works out of the box).
export VITE_OPEN_CODESIGN_DEV_KEY=sk-ant-...
# 2. Boot the desktop app from the repo root.
pnpm install
pnpm --filter @open-codesign/desktop devThen in the app:
- Click the Calm Spaces meditation app starter in the left sidebar.
- Press Send (or
Enter). - Within ~30 s the iframe on the right renders the design.
- Open the Export menu in the preview toolbar → choose HTML → pick a
destination → Save. open <chosen-path>in the browser shows the same design without the app.
Expected behaviour
- The model emits exactly one
<artifact identifier="design-1" type="html" …>
block. The orchestrator extracts it via@open-codesign/artifactsand feeds
the HTML into the sandbox iframe. - Tailwind is loaded via the official CDN (
https://cdn.tailwindcss.com). The
HTML exporter inlines the CDN tag if the model forgot to. - All colors, spacing, and font sizes are CSS variables — that's what the slider
tier (Phase 2) will hook into.
Failure modes (loud, by design)
- No key → assistant message tells you to set
VITE_OPEN_CODESIGN_DEV_KEY. - PDF / PPTX / ZIP export → throws
CodesignErrorwith codeEXPORTER_NOT_READYand the toast reads "PDF export ships in Phase 2". - Network / provider error → propagates as a
CodesignErrorwith codePROVIDER_ERROR; surfaced as the assistant's reply prefixed withError:.
There are deliberately no silent fallbacks anywhere in this path
(see PRINCIPLES §10).
File: packages/core/src/frames/README.md
Device Frame Snippets
Device frames are JSX runtime snippets that the desktop host seeds into the
agent virtual filesystem as frames/<name>.jsx.
They are different from scaffold presets:
- Frames are read with
view("frames/iphone.jsx")and adapted intoApp.jsx. - Scaffolds are copied into the workspace with
scaffold(kind, destPath). - Workspace
DESIGN.mdremains the design-system baton; frames are only visual
chrome helpers.
Available Frames
iphone.jsx- iPhone frame.ipad.jsx- iPad frame.watch.jsx- watch frame.android.jsx- Android phone frame.macos-safari.jsx- macOS Safari window frame.
How The Agent Uses Them
The host loads files from /templates/frames/ and exposes them underframes/ in the virtual filesystem. The agent may view a frame when the brief
explicitly benefits from device or browser chrome, then copy the relevant
component structure into App.jsx.
Frames should not be final artifacts by themselves. The agent still needs to
adapt the screen content, tokens, interactions, accessibility, and anyDESIGN.md baton.
Adding A New Frame
- Drop
<name>.jsxinapps/desktop/resources/templates/frames/. - Append the filename to
FRAME_FILESinpackages/core/src/frames/index.ts. - Keep
TWEAK_DEFAULTSvalid JSON when the frame has tweakable values. - Add focused tests if the loader contract or virtual path changes.
Conventions:
- JSX source compatible with the preview runtime.
- No external network assets or CDN scripts.
- Stable outer dimensions and clear inner screen/content region.
- Tunable values exposed through
TWEAK_DEFAULTSonly when useful.