Skip
All writing

2026-08-11 · 10 min read · plane-cli

plane-cli: a Plane client that prints the next command for you

Bun, one binary, write confirmations for AI agents, and why UUIDs in help text matter.

I use Plane for project tracking. The web UI is fine. The API is fine. What was not fine was living in the browser for “list urgent bugs, comment, move state” while I already lived in the terminal with agents.

So I wrote plane-cli — a self-contained plane binary. Bun compile, no Node runtime on the target. Cloud or self-hosted. MIT. Solo.

The UX bet

Most CLIs dump JSON or a pretty table and leave you alone.

This one prints Next (copy-paste ready) blocks with real UUIDs filled in:

plane project=1111-… items show aaaa-…
plane project=1111-… items update aaaa-… --state="In Progress"

That’s not decoration. It’s how you teach both humans and agents the grammar of the tool without opening docs.

Claude Code loved this once it existed — it would chain show → update → comment without inventing flags. Before that, it hallucinated flags that felt “REST-ish.” So the CLI became the docs.

Architecture (keep it boring)

Layers, top depends on bottom only:

LayerJob
index.tssettings, dispatch, errors
cli/parse args, walk command tree, generate help
commands/one module per resource, commands as data
api/typed client scoped like api.project(id).item(id)
render/everything printed — commands never format themselves
config.ts / state.ts / history.ts.planerc, .plane/, local log

Help is generated from the command tree. If help can drift from reality, it will. I made drift hard.

Claude Code is good at adding a command module when the pattern is obvious. It’s bad at inventing a second way to parse args mid-project. I kept smacking “use the tree.”

Config resolution

Independently per key:

env → nearest `.planerc` walking up → `~/.planerc`

Repo can pin project= without secrets. Home holds the API key (mode 0600, never overwrite existing). Classic 12-factor-ish, but files win when you’re jumping between checkouts.

Write confirmation (the agent feature)

First write against a project in a directory stops and shows exactly what would happen, then exits. Re-run with --yes (or answer the prompt). Once per project per directory.

Also: the notice tells AI assistants to restate the change in plain words and wait. Plane has no undo. An agent with a half-heard “close the billing bugs” can torch a board in seconds.

PLANE_ASSUME_YES=1 for pipelines. Local history redacts anything that looks like a credential.

This was not in v0. It landed after I watched an agent get enthusiastic. Claude Code helped implement the confirm gate; the policy was mine.

Screenshot-only tickets

Plane stores pasted images as <image-component src="<uuid>">. Invisible to dumb HTTP clients. items show reports image count; items images --download pulls them with your key. Half of QA tickets are “see screenshot” with zero text. A CLI that ignores that is cosplay.

Shipping

bun build --compile → one binary. installers for dmg / msi / deb / AppImage / tar.gz. Tag a version, CI attaches release artifacts.

I used Claude Code heavily for packaging scripts and the command modules. I did not let it “simplify” the confirm flow or merge render into commands. Layering is the product’s future-proofing.

Open source

github.com/mubashirjamali101/plane-cli

export PLANE_API_KEY=...
export PLANE_WORKSPACE=...
export PLANE_BASE_URL=https://api.plane.so/api/v1
plane projects list
plane about

If you build CLIs for agent-heavy workflows: print the next command, confirm writes, generate help from data. Claude Code will use what you give it. Give it sharp tools, not a bag of flags.