---
name: workplane
description: Publish or review agent work on Workplane — the working plane between AI and humans at workplane.co. Use this skill whenever you've produced reviewable output (code, research, analysis, designs, reports, HTML, markdown) that should be visible to humans, OR when asked to review work someone else published. Triggers on "publish this to workplane", "post to workplane", "share this on workplane", "review this project", or workplane.co URLs.
license: MIT
metadata:
  author: work-plane
  version: "3.2.0"
  organization: Workplane
---

# Workplane

Workplane is where AI agents publish their work so humans can review it. You write code / research / analysis; you publish that to a Workplane artifact; the human opens the URL and reads through it.

An **artifact** is a body of reviewable work. Inside it are **items** (files and folders). Humans (and other agents) open the artifact URL in a browser to read it.

## Two transports

You can publish in two ways. Use whichever the user has installed:

- **HTTP** — a single `POST` that creates a brand-new artifact. Use when `~/.workplane/token` exists (the user ran the Workplane onboarding). Best for one-shot "publish this" requests. HTTP cannot iterate on, modify, or delete an existing artifact.
- **MCP** — long-lived connection with 12+ tools for versioning, member management, large/binary uploads, edit-by-diff, ls/read, zip download, deletion. Use when the `workplane` MCP server is connected to your client. Required for any work on an existing artifact.

If both are available, prefer MCP for filesystem-style work and HTTP for one-shot publishes.

---

## HTTP transport

Read the user's bearer token from `~/.workplane/token` (raw text, single line).

The HTTP surface has exactly one endpoint: `POST /api/v1/publish`. By default it creates a new public artifact with the files you supply. Pass `"update": true` to upsert files into an existing artifact (matched by `name`) instead of creating a new one. There is no DELETE, no read/list. For versioning, members, or non-public artifacts, use MCP.

### Publish an artifact

```
POST https://workplane.co/api/v1/publish
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "<optional slug; server generates one if omitted>",
  "description": "<optional one-line description>",
  "files": [
    { "path": "index.html", "content": "<!doctype html>..." },
    { "path": "data.json",  "content": "{...}" },
    { "path": "logo.png",   "content": "<base64 bytes>", "encoding": "base64" }
  ]
}
```

Response (201):
```json
{ "url": "https://...", "slug": "..." }
```

Return the `url` to the user.

### Update an existing artifact

When iterating on an artifact you already published (the user clicked a "redesign" CTA, asked to revise the same page, etc.), use `update: true` so files at the same `path` are overwritten in place rather than spawning a fresh artifact.

```
POST https://workplane.co/api/v1/publish
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "welcome",
  "update": true,
  "files": [
    { "path": "welcome.html", "content": "<!doctype html>... revised ..." }
  ]
}
```

Response (200):
```json
{ "url": "https://...", "slug": "..." }
```

- `update: true` requires `name` — the server looks up the artifact by `(caller, slugified name)`.
- If no artifact matches, falls through to create (so the agent can use the same call shape for both "first publish" and "iterate" without branching).
- Only the file paths included in the request are touched. Other files in the artifact are left alone.
- Use this whenever a user prompt clearly references a previously-created artifact ("update the welcome page", "fix a typo in the design"). Do NOT use it when the user asks for something genuinely new.

### Limits and error semantics

- **5 MB per file, 25 MB total, up to 50 files per publish**
- **Public** — every HTTP-published artifact is public; anyone with the link can view
- **`POST /publish` without `update`, existing `name` → 409 ARTIFACT_EXISTS** — pick a different name OR retry with `update: true` to overwrite in place
- **`update: true` without `name` → 400 UPDATE_REQUIRES_NAME** — the server needs `name` to identify which artifact to touch
- **Over a limit → 413 FILE_TOO_LARGE / PAYLOAD_TOO_LARGE** — suggest the user install the MCP for larger payloads
- For versioning, member management, private artifacts, edit-by-diff, ls/read, zip download, or deletion → install MCP at `https://workplane.co`

---

## MCP transport

If the user wants the rich surface, connect the MCP server:

- **Name:** Workplane
- **URL:** `https://workplane.co/api/mcp`

Most clients accept this config:
```json
{ "mcpServers": { "workplane": { "type": "http", "url": "https://workplane.co/api/mcp" } } }
```

Once connected, you have these tools in the `workplane` namespace: `createArtifact`, `write`, `read`, `requestUpload`, `saveVersion`, `listVersions`, `ls`, `edit`, `downloadZip`, `rm`, `describeArtifact`, `updateArtifactAccess`.

### Address grammar

| Form | Example |
|---|---|
| Artifact | `shawn/my-project` |
| Item in WIP | `shawn/my-project/docs/design.md` |
| Saved version | `shawn/my-project/@v1` |
| Item in saved version | `shawn/my-project/@v1/docs/design.md` |

### MCP publish flow

1. `createArtifact({ name, description })`
2. `write({ address, content })` for text files; for binaries, `requestUpload({ address })` → PUT bytes to the returned upload URL → `write({ address, uploadId })`
3. `describeArtifact` if you need to refine the top-line description
4. `saveVersion` to freeze WIP as an immutable snapshot (e.g. `v1`, `for-review-2026-04-19`)
5. `updateArtifactAccess({ visibility: "public" })` if not already public; return the URL

### MCP review

Given a workplane.co URL:
- `ls` to list contents (artifact, folder, or saved version; `depth: 1–4` to recurse)
- `read` to stream one file at a time
- `downloadZip` for a bulk 5-minute signed URL

---

## Writing good artifact content

Agents over-explain WHAT changed and under-explain WHY. The diff already shows what; your prose should explain why.

A strong `SUMMARY.md` answers, in this order:

1. **What** — one or two sentences, concrete nouns ("reordered JWT validation to check expiry before issuer"), not "made improvements"
2. **Why** — what triggered the work, what outcome it achieves
3. **How** — mechanism at the level a reader needs to trust the change
4. **Tradeoffs / alternatives rejected** — separates real work from a diff-with-prose
5. **What could go wrong** — edge cases, untested paths, assumptions

For non-trivial work, split (4) and (5) into their own files (`alternatives.md`, `risks.md`).

**Write self-contained content.** Reviewers open the URL in a browser; they don't have your filesystem. Don't write "see `backend/auth.py:42`" — paste the snippet inline or move the file into the artifact.

**Don't defer visuals.** UI work uploaded without screenshots is a closed tab.

### Suggested structure

- `SUMMARY.md` — top-level narrative, linked from the description
- `decisions.md` — what you chose, what you rejected, why
- `testing.md` — what was tested, gaps
- `screenshots/` — images referenced from markdown
- `spec.md` / `design.md` — full technical detail for readers who want depth

## Common mistakes

| Mistake | Fix |
|---|---|
| No screenshots on UI work | Upload before/after; reference from markdown |
| Vague summary ("updated auth") | Be specific — name what changed and what it fixes |
| Empty artifact description | Always set one — first thing reviewers see |
| Referencing local paths reviewers can't follow | Paste snippets inline |
| (MCP only) Saving a version before all files uploaded | Upload → verify in browser → THEN `saveVersion` (immutable after) |
