Problem
issue-graph reads GitHub and Linear, but teams that track work in Plane can't map blockers, epics, and linked PRs before they start work.
Changes
issue-graph plane <PROJ-123|url|uuid>reads a work item neighborhood, and--project UUID|IDENTIFIERcaptures a whole project. Both use the existing work graph, Markdown and JSON output, dashboard,--cluster/--clusters, and--github.- Relations come from Plane's v1 relations endpoint, because the blocking and ordering types are only available there.
blocking/blocked_by,start_before/start_after, andfinish_before/finish_aftereach become one directed edge, with the same evidence ID from either side.duplicateandrelates_toare undirected, and unknown types keep their native name. - The reader pages the workspace work item list (v2, 100 per page) before crawling. That list gives each item's project, parent, and state, so children, parents, and items in other projects resolve without extra requests, and each crawled item costs two requests (relations and links). Plane's v2 list ignores
idandid__infilters, so items can't be fetched in batches by ID. When the workspace is larger than--max-pages, the reader falls back to per-item lookups and records that in the report'sindexcoverage. - Plane Cloud allows 60 requests per minute per key. The REST reader keeps a client-side budget of 50 per minute (
PLANE_REQUESTS_PER_MINUTE), honorsRetry-Afteron 429, and prints one note when it starts pacing. - Auth is
PLANE_API_KEYsent in theX-API-Keyheader. Self-hosted Plane works throughPLANE_API_URLandPLANE_WEB_URL, which must use https except on localhost. Only GET requests are sent. - Plane's
cancelledstate group is stored ascanceled, so the dashboard's existing state colors apply. resolveGithubAttachmentsnow accepts any report with the fields it reads (GithubResolvableReport), so Plane reports can use it. Linear behavior is unchanged.- New export
issue-graph/transport/plane. Docs page/docs/plane, plus README, bundled skill,schema, and an Unreleased changelog section above the release markers.
Not included: browser login (Plane OAuth needs a registered app), Plane's v2-only implements relations, and text mentions.
Visual proof
Fixture output:
$ issue-graph plane ENG-12 --depth 0
# Plane graph · fixture / Engine
Coverage: complete within requested scope · 1 nodes · depth 0
## ENG-12 · Mount the engine behind the staff check
Status: In Progress
https://app.plane.so/fixture/browse/ENG-12/
- ← parent: ENG-10
- ← blocks: ENG-11
- → blocks: ENG-13
- → finishes before: ENG-13
- Link: feat: mount the engine · https://github.com/acme/app/pull/412Live test against a private Plane Cloud workspace of 170 work items:
-
One neighborhood at depth 1 read 8 items in 5.5 s.
-
A project capture of 80 of 155 items took 193 s at the default budget, with no failed or partial reads. It found 168
blocks, 57 parent, and 3relates_toedges, plus 19 links. The open count (98) matched Plane's own filtered total. -
Help, README, docs, and the bundled skill agree
-
Generated content was refreshed from its source
-
Packaging changes were checked against the installed archive (
pnpm test:package) -
A release PR changes the
package.jsonversion and the matchingCHANGELOG.mdnotes (not a release PR)
Checks: pnpm lint, pnpm typecheck, pnpm test (956 passed, 58 new), pnpm build, pnpm check:docs, pnpm test:package.
🤖 Generated with Claude Code
@amitav13 is attempting to deploy a commit to the Vercel Labs Team on Vercel.
A member of the Team first needs to authorize it.