One session doing everything is the slow way to build on Pithy. It designs the data model, writes the Worker, builds the client and reads build logs, on one model, in one context. The pithy plugin for Claude Code splits that work across a team: a server, a web client, a mobile client and a runner, each on the model you choose. When it finds something the kit cannot do, it files the issue.
Install it
You need the pithy CLI first, from Install. Then, inside Claude Code:
/plugin marketplace add pithy-sh/pithy#release
/plugin install pithy@pithy#release is deliberate. The marketplace is the kit’s own repository, and its default branch runs ahead of npm between releases. A plugin read from it would name commands your installed pithy does not have yet. The release branch moves only when the kit is published, so the plugin you install names exactly the commands your CLI has.
Install from one source. Either pithy@pithy, from this marketplace, or pithy@synced, from Anthropic’s plugin directory. Not both: each loads its own copy, so every agent and skill would appear twice.
Building a game? pithy-games adds game design, a Unity client and playtests with simulated players, and installs pithy with it. Build a game with the Claude Code plugin covers it.
/plugin install pithy-games@pithyKeep it current
The plugin’s version is the pithy CLI’s version, so an update arrives once per release and never between. Claude Code keeps your cached copy until that version moves.
Claude Code does not auto-update a third-party marketplace by default. To turn it on, run /plugin, open Marketplaces, choose pithy, then Enable auto-update. To update by hand:
/plugin marketplace update pithyUpgrade the CLI at the same time. A plugin newer than your CLI will reach for commands it does not have.
The team
| Agent | Default | Job |
|---|---|---|
| Main session | Opus, high. Set it with /model and /effort | Capabilities, data model, auth flows, your users’ agents, which clients. The decisions that are expensive to get wrong |
server | Sonnet, medium | The Worker: pithy.config.ts, capabilities, app routes, migrations, and pithy contract. A route’s power gate, and, when the design has them, mcp() beside auth() and the routes it makes tools |
client-web | Sonnet, medium | A React app in the same Worker: pithy ui add react, @pithy-sh/vite, @pithy-sh/ui-react, the kit’s TypeScript clients. Cookie sessions with CSRF, or bearer. With mcp composed, the agent consent and connected-applications screens |
client-mobile | Sonnet, medium | The Expo app pithy ui add react-native scaffolds into an apps/<name>/ of its own, for the app stores: the kit’s bearer session with the token in secure device storage, device headers at sign-in, native Apple and Google sign-in, and a one-time-code handoff for every other provider. With mcp composed, the agent consent and connected-applications screens |
runner | Haiku, low. Bash and Read only | Runs pithy dev, the tests, typecheck and builds, and deploys an environment you approved. Returns a summary, never raw logs |
Web and mobile are two agents because they authenticate two ways. A browser holds a cookie session or a bearer token in memory; a phone holds its session token in its Keychain or Keystore. One agent holding both would mix them.
The runner cannot edit anything. It holds Bash and Read and nothing else, so the cheapest model on the team is never the one changing your code.
Choose each agent’s model
Every agent’s model and effort are plugin settings: server_model, server_effort, client_web_model, client_web_effort, client_mobile_model, client_mobile_effort, runner_model and runner_effort, with the defaults above. Change them with /plugin, or from a shell. An option you leave out keeps its value:
echo '{"server_model": "opus", "server_effort": "high"}' | claude plugin configure pithy@pithy --values-stdin/new-app and /deploy pass your choice on every agent they dispatch, and it outranks the agent’s own default. An agent the main session reaches for on its own, outside those skills, runs on its own default. A plugin cannot put a setting into an agent’s definition, and it cannot set the main session’s model either, so that one is yours to set.
The skills
/new-app asks what pithy init asks — web, mobile or both — then scaffolds the project with pithy init --target, adding --react-native for mobile or both so the Expo app is scaffolded too, adds the capabilities, and brings in only the agents the answer needs. A mobile project gets no web agent, and a web project gets no mobile one. Once the server has composed the capabilities, the mobile agent runs pithy ui add react-native on that app to add the screens for them.
/app-design settles the capabilities, the data model and the auth flows before any code. It runs in the main session, one question at a time, because those are the decisions a cheaper model should not make. It also asks whether your app’s own users should connect their AI agents to it, and recommends no unless you name a use. On a yes it settles who may connect one, which routes become tools with each one’s permanent operation name and effect, reads first, and the power each needs, and its summary carries that as a tool table the server agent builds from. Those screens are web screens, so agents need a web front end even for a mobile-only app.
/deploy takes the app to staging or production, and connects the dashboard. Below is what it asks and what it never does.
/operate lets the session administer one deployed environment, staging unless you say otherwise, through pithy mcp connect. Its tools are your Worker’s own admin routes, served on your machine, and your Worker audits every call as an agent’s. It is not your app’s own /mcp endpoint, which /app-design settles.
- It grants the reads first.
manifest:readplus only the reads you need. Never--scope all, and never a scope that writes, sends, charges, deletes or touches a credential on the first grant. - You run the connect. It hands you
! pithy mcp connect …with every scope named, because the command registers a credential under your sign-in. Then restart Claude Code, or run/mcp. - A read needs no question. Anything else needs your yes, for that one call. It reads each tool’s kind from its MCP annotations, never from its name, and a yes is never for the next call or a loop.
- It widens the grant only on your yes, naming each scope, with
pithy mcp connect --update. pithy mcp statusis its to run.pithy mcp disconnectis yours.
/report-kit-gap files what the kit cannot do against pithy-sh/pithy:
- It searches the open issues first. A match gets a comment, not a duplicate.
- It fills the bug or feature form, with
pithy --version,pithy doctor --jsonand the plugins that were active. - Its repro is written fresh. Never your code, and never a secret.
- It files with
ghonly on your explicit yes. Withoutgh, it hands you a prefilled issue link instead. - It leaves a comment at the workaround naming the issue, so the workaround is found and removed when the fix ships.
Deploy, and connect the dashboard
Ask for a deploy in any session, days into a build or on the first: /deploy, or just say so. The team checks your Cloudflare credentials with pithy doctor, shows what pithy provision --dry-run would create on your account, and asks. On your yes the runner provisions, migrates and deploys that one environment, and reports each Worker’s address.
- A yes is for one environment. A yes to staging is not a yes to production.
- Production takes a phrase you type.
yes, i really want to provision prod. The team passes it on exactly as typed and never writes it itself. A run that exits 5 stops the team and comes back to you. - Then the dashboard. After a staging or production deploy with no connection, it offers to connect the Pithy dashboard, and asks you what the connection is for. Your answer is recorded as its purpose, in your words. On your yes the main session runs
pithy dashboard connectitself, not the runner, so the sign-in address and short code reach you while it waits. You approve the connection in your browser. - The dashboard or an agent, never both. An environment holds one connection. Connect the dashboard and
/operatecannot connect there, so the team says so before it offers, and points you at/operateif you want the session to run that environment instead. - Connecting names you. The connection records who authorized it from your
pithy cloudflare connectsession, so it is refused under an account token, and the team says so rather than retrying.
It never runs pithy remove or a rollback. Those stay yours.
The agents build against the contract
Every client is built against the Worker’s OpenAPI document, which pithy contract writes to apps/<worker>/openapi.json, and against asyncapi.json beside it when the Worker serves a socket. The server agent keeps both current, and the client agents read them rather than guessing a route or a frame. A client in a language Pithy ships no client for generates its calls from the same file.
What it builds on
The AGENTS.md block pithy init writes, the documentation server pithy docs connect adds, pithy mcp for administering a deployed environment, and pithy schema --json. The plugin organizes the work; those are still how each agent learns and reaches the kit.
Three MCP servers, and each does one thing:
| Server | Who connects | What it serves |
|---|---|---|
pithy.sh/mcp | Your session, through pithy docs connect | Pithy’s documentation |
pithy mcp | Your session, through pithy mcp connect and /operate | Your deployed Worker’s admin routes, for one environment, on your machine |
Your app’s own /mcp | Your app’s users’ agents | The routes your design made tools, as the user who connected. /app-design asks whether you want one |
Outside Claude Code
The agents and skills drive the pithy CLI through a shell. Where a shell is not available, as on claude.ai, the skills that run commands cannot run them.