# Plane CLI — Feature Spec

## Problem

The Plane MCP servers expose one-operation-per-tool. Common workflows (bulk updates, state transitions with side effects, filtered queries) require 10-20 separate tool calls with no composition. A dedicated CLI can batch, compose, and pipeline these into single commands.

## Core Commands

### Work Items
- `plane ls` — list items with rich filtering (state, assignee, label, date range, priority, type). Supports `--project`, `--cycle`, `--module`. Supports `--fields id,title,state` to select specific fields (reduces API payload ~90% on large lists, makes output scannable).
- `plane show <ID>` — full detail view of a work item including AC, comments, links, relations, activity. With no `<ID>` and inside a git repo, infers the work item from the current branch name (e.g. `feat/PROJ-123-add-auth` → `PROJ-123`).
- `plane create <title>` — create with inline flags: `--state`, `--priority`, `--label`, `--assignee`, `--ac "criteria 1" --ac "criteria 2"`. When called without required flags, walks through fields interactively via `dialoguer` prompts instead of erroring.
- `plane update <ID>` — batch update fields in one call.
- `plane done <ID>` — transition to done + check all AC + optional comment. One command. With no `<ID>`, infers from current git branch.
- `plane mv <ID> --cycle <name>` — move between cycles/modules.
- `plane bulk <IDs...> --state <state>` — bulk state transitions. Supports `--dry-run` to print exactly what would change (item IDs, current state → new state, AC status) without executing.
- `plane watch <ID>` — live-tail a work item or cycle. Polls and refreshes the terminal view on state changes. Use case: kicked off a review, want to know when it moves to done without refreshing the web UI.

### Cycles & Modules
- `plane cycles` — list cycles with progress bars.
- `plane modules` — list modules with item counts.
- `plane cycle <name> ls` — list items in a cycle.

### Dashboard
- `plane dashboard` — overview: items by state, overdue, in-progress, AC completion rates. Colored table output.
- `plane mine` — my assigned items across all projects.

### Acceptance Criteria
- `plane ac <ID>` — show AC with checkboxes.
- `plane ac <ID> check <index>` — check off an AC item.
- `plane ac <ID> add "new criteria"` — append AC.

### Sync & Config
- `plane sync` — pull latest state from Plane API, cache locally for fast reads.
- `plane config` — set API key, default workspace, default project.
- `plane workspace <name>` — switch active workspace.

## Git-Aware Context

When inside a git repo, plane-cli-requiem reads the current branch name and extracts a work item ID if present (e.g. `feat/PROJ-123-add-auth` → `PROJ-123`). This makes `plane show`, `plane done`, and `plane ac` zero-arg commands for the common case of "whatever I'm working on right now." The branch pattern is configurable in `config.toml`.

## Interactive Prompts

Commands that require multiple fields (`plane create`, `plane update`) support two modes:
1. **Flag mode** — pass everything inline for scripting: `plane create "Fix auth" --priority high --ac "Unit tests pass"`
2. **Interactive mode** — omit flags and get walked through each field via `dialoguer`. Title → priority → state → assignee → AC, with validation at each step. This makes `plane create` the fastest path to a well-formed ticket.

## Field Selection

`plane ls --fields id,title,state` tells the API to only return those fields. Reduces payload size and terminal noise. JSON output respects field selection for predictable scripting.

## Dry Run

`--dry-run` is supported on all destructive/bulk operations (`bulk`, `done`, `update`). Prints exactly what would change without executing:

```
DRY RUN — no changes made:
  PROJ-123: state todo → done, 3/3 AC checked
  PROJ-124: state in-progress → done, 2/2 AC checked
  PROJ-125: state in-review → done, 1/3 AC incomplete ⚠
Total: 3 items would be updated
```

This is the difference between people scripting plane-cli-requiem in CI vs being afraid to.

## Multi-Workspace Support

User has multiple Plane workspaces (jakutainc, ourhomii, personal-projects-zee, venoble). The CLI should support workspace switching and cross-workspace queries (`plane mine` across all).

## Output Formats

All commands support multiple output formats via `--format`:
- `table` (default for TTY) — colored, aligned, human-readable
- `json` — structured, complete, schema-stable for scripting
- `csv` — for spreadsheet import and simple piping

Auto-detects TTY vs pipe: `plane ls` shows a table, `plane ls | jq` outputs JSON. Explicit `--format` overrides detection.

## Caching

SQLite-backed local cache for offline reads and fast repeat queries.

### Architecture
- **Write-through on reads** — every `plane ls` or `plane show` caches the API response
- **Optimistic updates on mutations** — `plane done` updates cache immediately, API call runs in parallel
- **Graceful offline degradation** — show cached data with a staleness indicator (`⚡ cached 12m ago`), queue mutations for sync when connectivity returns

### Configuration (`config.toml`)

```toml
[cache]
enabled = true
ttl_seconds = 3600          # cached items expire after 1 hour
max_size_mb = 100            # limit cache to 100 MB
offline_mode = false         # if true, never hit API — cache only
```

### Why SQLite over flat JSON
With hundreds of work items, filtering/querying JSON files gets expensive. SQLite handles indexed lookups natively. Schema: `items(id, workspace_id, project_id, data_json, updated_at)` with indexes on filtered columns.

## Credential Storage

API keys stored in the system keychain (Windows Credential Manager / macOS Keychain / Linux secret-tool) via the `keyring` crate. Prevents accidental key leaks when sharing config or dotfiles. Fallback to `config.toml` and `PLANE_API_KEY` env var for CI/headless environments.

## Shell Completion

Shell completions generated via `clap_complete` for bash, zsh, fish, and PowerShell. Completions for workspace names, project names, cycle names, and recent item IDs are cached locally — target <100ms response. Completions that hit the API on every keystroke are unusable; the cache prevents this.

## Retry & Rate Limiting

Plane's API will 429 on bulk operations. plane-cli-requiem implements:
- Exponential backoff: 1s → 2s → 4s, max 5 attempts
- `Retry-After` header respect (if present, wait that long instead of backoff)
- Per-item failure reporting on bulk ops: "12/15 succeeded, 3 failed (rate limited)" with the option to retry failures

## Tech Decisions

- **Language:** Rust (single binary, fast startup, consistent with reportal)
- **Distribution:** crates.io + cargo-dist (same pipeline as reportal)
- **Config:** TOML at `~/.plane-cli-requiem/config.toml` (workspaces, defaults, cache settings)
- **Credentials:** System keychain via `keyring` crate, fallback to config/env
- **Output:** Colored tables via comfy-table, same styling approach as reportal
- **Cache:** SQLite via `rusqlite`
- **Interactive prompts:** `dialoguer`
- **Shell completions:** `clap_complete`
- **API:** Plane REST API at `developers.plane.so`

## Semver Contract

Once people script against `plane ls --json`, the JSON schema is a public API. Rules:
- Adding new fields to JSON output is non-breaking (minor version)
- Removing or renaming fields is breaking (major version)
- Changing command behavior or flag semantics is breaking (major version)
- Adding new commands or optional flags is non-breaking (minor version)

Lock the schema at 1.0 and only add, never remove or reorder.

## Implementation Checklist

### Done
- [x] CLI routing — all 14 subcommands registered and routable via clap
- [x] Config system — TOML loading/saving, workspace registry, validation
- [x] Type-safe identifiers — WorkspaceSlug, ProjectSlug, ApiToken, all API UUIDs
- [x] Session resolution — active workspace + PLANE_API_KEY env override
- [x] API client — authenticated HTTP with x-api-key, project resolution
- [x] `plane config` — register workspaces, set active workspace/project, show config
- [x] `plane workspace` — switch active workspace
- [x] `plane ls` — list work items with table/json/csv output, state/priority coloring
- [x] `plane show <ID>` — full detail view by identifier (NRO-123)
- [x] `plane show project <slug>` — project summary with state distribution counts
- [x] `plane show cycle <name>` — cycle detail with start/end dates
- [x] `plane show module <name>` — module detail with description
- [x] `plane ac <ID>` — display acceptance criteria from description
- [x] Output format auto-detection — table for TTY, JSON when piped

### Write Endpoints
- [x] PATCH method on API client for updating work items
- [x] POST method on API client for creating work items
- [x] POST method for creating comments (via WorkItemScopedClient::post_comment)
- [x] DELETE method on API client for deleting work items
- [x] Wire `plane create` to POST endpoint
- [x] Wire `plane update` to PATCH endpoint
- [x] Wire `plane delete <ID>` — delete with confirmation prompt (--yes to skip)
- [x] Wire `plane done` — composed: transition state (AC check + comment pending)
- [x] Wire `plane bulk` — batch PATCH across multiple items with per-item reporting
- [x] Wire `plane mv` — add work item to cycle (--cycle) or module (--module)

### Filtering & Pagination
- [x] `plane ls --state`, `--priority` filter flags (--assignee, --label pending)
- [ ] `plane ls --fields` to select specific API fields (reduces payload)
- [ ] Cursor-based pagination — loop until `next_page_results` is false
- [ ] `expand` query param support for inline state/assignee resolution

### Git-Aware Context & VCS Integration
- [x] Infer work item ID from current branch name (e.g. `feat/NRO-123-add-auth`)
- [x] Zero-arg `plane show`, `plane done`, `plane ac`, `plane open` when branch contains an ID
- [ ] Configurable branch pattern in `config.toml`
- [x] `plane start <ID>` — create feature branch (feat/ID-slugified-title) + transition to In Progress
- [x] `plane pr` — open PR via `gh` with title `[ID] title` and body with Plane link
- [ ] Auto-comment back to Plane when a PR is created or merged

### Missing Commands
- [x] `plane cycles` — list cycles with date ranges (table/json/csv)
- [x] `plane cycles <name>` — list items in a specific cycle (table/json/csv)
- [x] `plane modules` — list modules with descriptions (table/json/csv)
- [x] `plane modules <name>` — list items in a specific module (table/json/csv)
- [x] `plane dashboard` — terminal overview: items by state group, overdue counts, completion %
- [x] `plane mine` — my assigned items in the active project (table/json/csv)
- [ ] `plane watch` — live-tail a work item, poll for state changes
- [x] `plane open <ID>` — open work item, project, workspace, cycle, or module in browser
- [x] `plane me` — show current user, workspace, project, auth status
- [ ] `plane info <url>` — parse a Plane URL and print summary/state/assignee

### Scripting Helpers
- [x] `plane id` — print current branch's work item ID (for scripts/statuslines)
- [x] `plane url` — print current branch's work item URL
- [ ] `--web` flag on show/cycles/modules to open in browser instead of printing
- [ ] `$EDITOR` support for long descriptions and comments on create/update
- [ ] Command aliases — short forms like `plane i` for `plane issue`

### Module & Cycle Management
- [ ] Create cycles — `plane cycle create <name> --start <date> --end <date>`
- [ ] Create modules — `plane module create <name>`
- [ ] Delete cycles and modules
- [ ] Add/remove work items from cycles and modules
- [ ] Archive/unarchive cycles and modules

### Infrastructure
- [ ] `--dry-run` flag on bulk, done, update
- [ ] Interactive prompts via `dialoguer` when flags are omitted on create/update
- [ ] SQLite cache for offline reads and fast repeat queries
- [ ] System keychain credentials via `keyring` crate
- [ ] Shell completions via `clap_complete` (bash, zsh, fish, PowerShell)
- [ ] Retry with exponential backoff + `Retry-After` header respect (60 req/min limit)
- [ ] CI pipeline + cargo-dist for releases
- [ ] Per-directory config profiles — auto-select workspace/project based on git repo
- [ ] Plugin/extension hooks — `plane-foo` on `$PATH` becomes `plane foo` (gh-style)

### Future / Stretch
- [ ] TUI mode — ratatui interactive board with vim navigation and quick state transitions
- [ ] Rich search query syntax — cohesive filter language reusable across commands

## Open Questions

- Should it integrate with reportal (e.g. `rj nro` auto-sets plane project context)?
