# Pie Pieui

> Use for any task in the Pie ecosystem — the Python `pie` CLI and FastAPI backend, the TypeScript `pieui` CLI and Next.js/React frontend, or both together. Covers project scaffolding, cards and pages, ajax handlers and the `stored` prop, backend↔frontend metadata sync, the card preview harness and pie-show MCP server, Centrifuge realtime, MongoDB/Beanie, Cloudflare Workers, the Express backend, remote component storage, and PieUI style isolation.

- Skill: `swarm-ai-labs/pie-pieui` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add swarm-ai-labs/pie-pieui`
- Raw SKILL.md: https://api.skillmd.com/api/skills/swarm-ai-labs/pie-pieui/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Swarm-AI-Labs (https://skillmd.com/u/swarm-ai-labs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/swarm-ai-labs/pie-pieui

---


# Pie / PieUI

One ecosystem, two CLIs:

- **`pie`** — Python/FastAPI backend. **Source of truth** for the command surface.
- **`pieui`** — TypeScript/Next.js frontend. Mirrors `pie` where a frontend analog exists.

```
┌──────────────────────────────────────────────┐
│      Platform (pieui.swarm.ing)              │
│      username/my-project/MyCard              │
│        ├── python/      ← pie card remote push
│        └── typescript/  ← pieui card remote push
└──────────────────────────────────────────────┘
          ↑ push/pull            ↑ push/pull
┌──────────────────┐   ┌─────────────────────────┐
│ Backend          │   │ Frontend                │
│ Python / FastAPI │   │ TypeScript / Next.js    │
│ `pie`            │   │ `pieui`                 │
│ pages/           │   │ piecomponents/          │
│ pages/components/│   │ app/                    │
└──────────────────┘   └─────────────────────────┘
```

## Read this first, then load one reference

This file is the map. Load the reference that matches the task — don't read them all.

| Reference | Load it for |
|---|---|
| `references/pie-commands.md` | exact `pie` syntax: any backend command, flags, db, cloudflare, taskrun |
| `references/pieui-commands.md` | exact `pieui` syntax: any frontend command, flags, registry |
| `references/preview-and-mcp.md` | rendering one card: the harness, `card show`, show-mcp tools, launching/registering the MCP server, preview providers |
| `references/runtime-contracts.md` | ajax endpoints & deps derivation, the `stored` prop, pieui 3.0.0 migration, the Express backend, Centrifuge recovery |
| `references/workflows-and-edge-cases.md` | envelope policy, end-to-end recipes, known edge cases, monorepo layout, reading check-sync output |
| `references/style-isolation.md` | a card looks wrong and you're tempted to edit `globals.css` |

## Command surface

| `pie` | `pieui` | Notes |
|---|---|---|
| `create` | `create` / `create-pie-app` / `create-pieui` | scaffold a project |
| `init` | `init` | set up in an existing dir; links the other side |
| `login` | `login` | writes `.pie/config.json` |
| `self-upgrade` | `self-upgrade` | `pie --pm uv\|poetry\|pip`, `pieui --pm bun\|npm\|pnpm\|yarn` |
| `card …` | `card …` | largest surface |
| `page add\|view\|ajax` | `page add\|view\|ajax` | |
| `web <mod:app> [verify\|build]` | — | backend only |
| `taskrun local\|remote` | — | backend only |
| `db …` | — | **divergence**: Beanie/MongoDB |
| `cloudflare init\|dev\|deploy` | — | **divergence**: Pyodide Worker |
| `card channels` / `card emit` | — | **divergence**: Centrifuge introspection |
| `card show*` | — | **divergence**: preview orchestration |
| — | `postbuild` | frontend only (manifest) |
| — | `registry dev\|build` | frontend only (preview harness) |
| — | `card add-story` / `generate-preview` / `remove` | frontend only |

`pie web` takes a **`module:attribute`**, not a verb: `pie web web:app verify`.
There is no top-level `pie card push` — pushing is `pie card remote push`.

**Cross-repo rule:** any user-facing change in `pie/__main__.py` or `pie/code/*` must
be mirrored in `pieui` (`src/code/{args,types}.ts`, `src/cli.ts`,
`src/code/commands/*`). A PostToolUse hook nudges about this; it is safely ignored
for the divergences marked above.

## Card types

| `pie` | `pieui` | Shape |
|---|---|---|
| `simple` | `simple` | only a `data` prop |
| `complex` | `complex` | `data` + `children` |
| `container` | `simple-container` | `data` + a single `content` slot |
| `complex-container` | `complex-container` | `data` + `content[]` array |

**The type is required on `pie`** (omitting it is an argparse error). Only
`pieui card add` defaults to `complex-container`. Note the different spelling of the
single-slot container.

Flags on both: `--io` (realtime), `--ajax` (AJAX), `--input` (typed `stored` prop),
`--from <ref>` (port from the other side). All combinable.

**Porting:** `--from` reads the counterpart's metadata — a source file, a components
dir, a PieMetadata `.json`, or a bare card name resolved via the configured
`frontendComponentsDir` / `backendComponentsDir`. Omit `--from` and it auto-resolves
by name. Prefer this over hand-writing the other side.

## Hard rules — never do manually

These must go through the CLI; doing them by hand breaks the registry or platform metadata.

| ❌ Never manually | ✅ Use instead |
|---|---|
| Create a file in `piecomponents/` | `pieui card add …` |
| Create `app/<path>/page.tsx` | `pieui page add <path>` |
| Edit `piecomponents/registry.ts` | updated automatically by `pieui card add/remove` |
| Create `pages/components/*.py` | `pie card add …` |
| Create `pages/*.py` | `pie page add …` |
| Add a methods/event key to `<PieCard methods={…}>` | `pieui card add-event <Card> <event>` |
| Delete a piecomponent directory | `pieui card remove <Name>` |

Plus:

- `"use client"` at the top of **every** PIE card TSX file.
- `<button type="button">` always — without it the browser submits to `/api/process/`.
- `is_typed=False` in every `AsyncPage` subclass that does not override `get_content`.
- Python `snake_case` → **camelCase** on the frontend (`send_label` → `sendLabel`).
- After editing `web.py` (new route) — **restart the backend process**.
- Never commit `.env`, `.pie/`, `.claude/`, `node_modules/`, `.next/`, `__pycache__/`, `.venv/`.
- `pie card add-event` is **not implemented** for Python sources — don't promise it.

## Keeping the two sides in sync

```bash
pie card check-sync [NAME]        # every card when NAME is omitted
pieui card check-sync <Name>      # frontend still requires a name
pie card dump-metadata <NAME>     # {"python": …} envelope — the raw input
pieui card dump-metadata <Name>   # {"typescript": …} envelope
```

`pie card check-sync` exits `0` when aligned, `1` on any finding or build failure. It
shells out to the frontend CLI (`bun $PIE_CHECK_SYNC_PIEUI_CLI` → `bunx pieui` →
`npx pieui`) and needs the `{"typescript": …}` envelope back, so a stale pieui fails
every card. Not every finding is a bug — see `references/workflows-and-edge-cases.md`.

## Environment & defaults

- **`pie`**: `uv run python -m pie …` inside the pie repo; the installed `pie` entrypoint
  elsewhere. Run from the target project root — config is read relative to CWD.
- **`pieui`**: prefer `bunx pieui …`; `bun src/cli.ts …` inside the pieui repo.
- Generated paths: backend `pages/components/` (`PIE_COMPONENTS_DIR`), frontend
  `piecomponents/` + `app/<path>/page.tsx`, preview harness `<project>/.pie/registry/`.
- Env: `PIE_USER_ID` / `PIE_API_KEY` (from `login`), `PIE_PROJECT` (or
  `PIE_PROJECT_SLUG`, defaults to the cwd name), `PIE_COMPONENTS_DIR`. `.env`
  auto-loads via python-dotenv.
- **API keys are per project** — a key for project A cannot read project B, even for
  the same user. Log in per project.
- Before committing in the pie repo: `task fmt` (CI enforces `ruff format --check`,
  which `task lint` does **not** cover), then `task lint`, `task typecheck`.

## Workflow

1. Decide which side owns the change — the backend (`pie`) is authoritative.
2. Run the narrowest command with explicit args. Prefer `card view` /
   `dump-metadata` / the MCP `list_cards` over reading source to learn a card's shape.
3. After a backend card change, run `pie card check-sync` and port with
   `card add --from` rather than hand-writing the counterpart.
4. After any user-facing `pie` CLI change, mirror it into `pieui` unless it falls
   under a documented divergence.
5. Report changed files and the follow-up command.

## Safety rules

- Destructive or outward-facing — require explicit user intent: `card remote remove`,
  `card remote public` / `private`, `db model remove`, `db import`, `db rollback`,
  `cloudflare deploy`.
- `db migrate` / `rollback --distance 0` means **all** migrations.
- `card emit` / `show-emit` publish real events — confirm the channel first.
- `card show` / `show-mcp` spawn a frontend `next dev`; if the user runs their own dev
  server on that port, confirm before replacing it.
- Don't run `pieui postbuild --append` unless the user wants built-in components merged.
- Don't commit machine-specific `.pie/config.json` paths unless the team wants that.

## When something breaks

- **Anything in the preview** → run the MCP `doctor` tool first; every failing check
  carries its own `fix`. Details in `references/preview-and-mcp.md`.
- **Stale CSS / build errors in the preview after the source is fixed** → the harness
  has its **own** cache: `rm -rf <project>/.pie/registry/.next`. Clearing the main app
  `.next` does nothing.
- **A card looks wrong** → fix the card, not `globals.css` (`references/style-isolation.md`).
- **Contract mismatches** → `references/workflows-and-edge-cases.md`.

