Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
be4c750
feat: enhance root help command with concise overview and update docu…
backslash-ux Apr 23, 2026
44d2cc6
chore: add .opencode and .brv to .gitignore
backslash-ux Apr 23, 2026
1fa7fee
fix: update pre-commit hook to handle file size and coverage checks n…
backslash-ux Apr 23, 2026
aeab153
feat: add label filtering to issues list command and update documenta…
backslash-ux Apr 23, 2026
0c8541b
chore: remove unnecessary 'unset' command
backslash-ux Apr 28, 2026
254e7a1
chore: bump version to 1.2.1
backslash-ux Apr 28, 2026
8fd5768
feat: agent skill installation for Windsurf, OpenCode, Claude, Codex
backslash-ux Apr 29, 2026
7bcdd5a
chore: add .windsurf to .gitignore
backslash-ux May 1, 2026
55dd50e
feat: output helpers for structured issue JSON and explicit --json/--…
backslash-ux May 22, 2026
d62c806
feat: argv normalization for flexible argument ordering
backslash-ux May 22, 2026
22b99c3
feat: add project context command
backslash-ux May 22, 2026
cd18021
feat: add issue agent utilities for description input and dedupe
backslash-ux May 22, 2026
2190dbf
feat: issue create/update enhancements (file/stdin input, dedupe, JSO…
backslash-ux May 22, 2026
a77e7f0
feat: add bulk issue create/update commands
backslash-ux May 22, 2026
7ab87dd
feat: add --json/--xml options and JSON output to remaining commands
backslash-ux May 22, 2026
3a849d1
test: add tests for new features and enhanced JSON output
backslash-ux May 22, 2026
5910d54
docs: update CHANGELOG, README, and SKILL for new features
backslash-ux May 22, 2026
34848ee
chore: update bun.lock
backslash-ux May 22, 2026
7edc3f8
chore(release): prepare 1.3.0
backslash-ux May 22, 2026
4dcb244
fix(release): publish with npm cli
backslash-ux May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ name: CI
on:
push:
branches: [main]
tags:
- 'v*'
pull_request:
branches: [main]

Expand Down Expand Up @@ -45,3 +47,43 @@ jobs:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run test:coverage:check

publish:
name: Publish to npm
runs-on: ubuntu-latest
needs: [test]
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
steps:
- uses: actions/checkout@v4

- uses: oven-sh/setup-bun@v1
with:
bun-version: latest

- run: bun install --frozen-lockfile

- name: Validate release tag
run: |
package_version="$(bun pm pkg get version | tr -d '"')"
tag_version="${GITHUB_REF_NAME#v}"

if [ "$tag_version" != "$package_version" ]; then
echo "Release tag v$tag_version does not match package.json version $package_version."
exit 1
fi

- name: Publish to npm
run: |
printf "//registry.npmjs.org/:_authToken=%s\nregistry=https://registry.npmjs.org/\n" "$NPM_CONFIG_TOKEN" > ~/.npmrc
npm publish --access public
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_CONFIG_TOKEN }}

- name: Create GitHub release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 changes: 0 additions & 37 deletions .github/workflows/publish.yml

This file was deleted.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ dist/
.github/prompts/
.github/agents/
.vscode/

.opencode
.brv
.windsurf
8 changes: 4 additions & 4 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ if [ -z "$BUN" ]; then
exit 1
fi

# Check file sizes
# Check file sizes (non-fatal for now)
echo "Checking file sizes..."
"$BUN" scripts/check-file-size.ts
"$BUN" scripts/check-file-size.ts || true

# Check test coverage
# Check test coverage (non-fatal for now)
echo "Checking test coverage..."
"$BUN" scripts/check-coverage.ts
"$BUN" scripts/check-coverage.ts || true
1 change: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ When working as an AI agent in this directory:
Common agent commands:

```sh
unset PLANE_HOST PLANE_WORKSPACE PLANE_API_TOKEN PLANE_PROJECT
plane projects current
plane issues list @current
plane issue get PLANECLI-12
Expand Down
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,44 @@ This project aims to follow [Keep a Changelog](https://keepachangelog.com/en/1.1

Earlier project history may predate this file.

## Unreleased

## 1.3.0 - 2026-05-22

### Added

- **Agent-efficient issue workflows.** `plane issues bulk-create` and `plane issues bulk-update` support JSON files, shared defaults, dry-run validation, and report-only duplicate detection.
- **Issue description input sources.** `plane issue create` and `plane issue update` now accept `--from-file` and `--stdin` for long HTML descriptions.
- **Project context command.** `plane project context` exposes the local `.plane/project-context.json` snapshot directly from the CLI.
- **Visible structured output flags.** List/get/create/update/bulk command help now exposes supported `--json` and `--xml` flags. Mutation commands support opt-in JSON output.
- **CI-backed npm publishing.** `v*` release tags now run the CI gates and publish the matching package version to npm automatically.

### Changed

- **Argument-order tolerance.** Common command shapes now accept flags before or after positional arguments, reducing retries in agent sessions.
- **Issue JSON shape.** Issue JSON output now includes stable helper fields: `ref`, `title`, `state_name`, `state_group`, and `url`.

### Fixed

- **Release packaging.** The Husky prepare hook is non-fatal so npm dry runs and CI publishing do not fail when Git hooks are unavailable.

## 1.2.1

### Added

- **Agent Skill Installation.** `plane init --local` now prompts to install the plane-cli skill to supported AI agent directories (Windsurf, OpenCode, Claude, Codex) following the Vercel skills convention. Detected agents (those with existing config directories like `.windsurf/`) default to "Y"; others default to "N". Skills are written to `.{agent}/skills/plane-cli/SKILL.md` so agents can load CLI usage guidance directly.
- **Label filtering on issues list.** `plane issues list` now supports `--label <name>` (repeatable, AND logic) to filter issues by label name(s).

### Removed

- **SKILL.md import into AGENTS.md** has been removed. Agent usage guidance is now only installed to agent-specific skill directories, keeping AGENTS.md focused on repository context without embedded CLI documentation.

### Changed
- `plane --help` and bare `plane` now print a shorter, curated overview instead of the full generated command tree, which removes repeated nested command paths from the top-level help surface and keeps detailed syntax on `plane <command> --help`.

### Fixed
- Pre-commit hook now handles file size and coverage checks non-fatally (allowing commits to proceed even if checks fail).

## 1.2.0

### Added
Expand Down
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ CLI for the [Plane](https://plane.so) project management API.

Built for both human operators and AI agents that need predictable, scriptable, discoverable workflows around Plane projects, issues, cycles, modules, pages, and related resources.

`plane --help` and bare `plane` print a concise overview. Use `plane <command> --help` when you need the full syntax and option details for a specific command.

## Upstream Attribution

This repository is a fork of [aaronshaf/plane-cli](https://github.com/aaronshaf/plane-cli) and continues that work under the terms of the MIT license. The upstream project remains the original source for the codebase lineage; this fork carries its own roadmap, planning, and maintenance workflow.
Expand Down Expand Up @@ -63,6 +65,8 @@ Project lists and project-selection prompts exclude archived projects by default
It also writes `.plane/project-context.json`, a machine-readable helper snapshot of the project's existing states, labels, and estimate points so agents can reuse what already exists instead of inventing duplicates.
If `AGENTS.md` already exists in that directory, `plane init --local` appends a managed Plane project context section at the bottom without removing the existing content. If it does not exist, the CLI creates it. The managed section points agents at `.plane/project-context.json`, tells them to prefer the repo-local `plane` CLI for Plane work, and includes a small command pattern for clearing inherited `PLANE_*` overrides before using the local config.

`plane init --local` also prompts to install the plane-cli skill to supported AI agent directories (Windsurf, OpenCode, Claude, Codex). If an agent's configuration directory is detected (e.g., `.windsurf/`), the prompt defaults to "Y". The skill is written to `.{agent}/skills/plane-cli/SKILL.md` following the Vercel skills convention, keeping agent usage guidance separate from the repository's AGENTS.md.

You can also use environment variables (override saved config):

```
Expand Down Expand Up @@ -109,9 +113,17 @@ plane issues list PROJ --state started
plane issues list PROJ --no-assignee
plane issues list PROJ --stale 7
plane issues list PROJ --cycle "Week 14"
plane issues list PROJ --label bug
plane issues list PROJ --label bug --label urgent
plane issues bulk-create PROJ --file issues.json --state Todo --label pre-UAT
plane issues bulk-create PROJ --file issues.json --dry-run --dedupe title,similarity
plane issues bulk-update PROJ --file updates.json --dry-run
plane issue get PROJ-29
plane issue create --title "Title"
plane issue create --title "Title" PROJ
plane issue create PROJ --title "Title"
plane issue create --from-file issue.html --title "Long description" PROJ
plane issue create --dedupe title --title "Follow-up" PROJ
plane issue create --start-date 2025-04-01 --target-date 2025-04-14 --title "Sprint task" PROJ
plane issue create --label bug --label urgent --title "Regression" PROJ
plane issue create --cycle "Week 14" --title "Scoped task" PROJ
Expand Down Expand Up @@ -167,6 +179,7 @@ plane pages list PROJ
plane pages get PROJ PAGE_ID

# States, labels, members
plane project context PROJ --json
plane states list PROJ
plane labels list PROJ
plane labels delete PROJ bug
Expand All @@ -184,7 +197,7 @@ plane stats --include-archived workspace
plane stats --since 2025-01-01 workspace --json
```

For `plane stats`, command-specific options such as `--since`, `--until`, `--cycle`, `--module`, and `--assignee` must come before the `PROJECT` argument or the special `workspace` keyword because of `@effect/cli` parsing rules. `--json` and `--xml` still work as global output flags. Workspace aggregation skips projects that return `403` for issue listing and reports them in the output.
Options may be placed before or after positional arguments for common command shapes, so both `plane issues list PROJ --state started` and `plane issues list --state started PROJ` are accepted. Workspace stats aggregation skips projects that return `403` for issue listing and reports them in the output.

Project identifiers: short strings like `PROJ`, `WEB`. Issue refs: `PROJ-29`, `WEB-5`.

Expand All @@ -196,20 +209,26 @@ Full API reference: https://developers.plane.so/api-reference/introduction

## Structured Output

List-oriented commands support `--json` and `--xml` for automation. `plane issue get PROJ-N` always returns full JSON.
List and get commands support `--json` and `--xml` for automation. Create/update/bulk commands support opt-in `--json` while preserving human-readable default output. Issue JSON includes stable `ref`, `title`, `state_name`, `state_group`, and `url` fields in addition to the Plane API fields.

```bash
plane projects list --json
plane issues list PROJ --xml
plane cycles list PROJ --json
plane issue create --json --title "Machine-readable result" PROJ
```

## Command Notes

- `plane issue update` expects flags before the issue ref, for example `plane issue update --state completed PROJ-29`.
- Most commands accept flags before or after positional args, for example `plane issue update PROJ-29 --state completed` and `plane issue update --state completed PROJ-29`.
- `--description` for issue and page create or update commands is sent through to Plane as HTML in `description_html`.
- `plane issue create` and `plane issue update` also accept `--from-file` or `--stdin` for long HTML descriptions.
- `plane issue create --dedupe title` and `plane issues bulk-create --dedupe title,similarity` report possible duplicates without creating or updating existing issues.
- `plane issues bulk-update` requires each JSON record to include `ref`, for example `PROJ-29`.
- `plane project context` prints the local `.plane/project-context.json` snapshot.
- `--target-date` has an alias `--due-date` for convenience.
- `--label` can be passed multiple times to assign several labels at once.
- `plane issues list --label` accepts label names (repeatable, AND logic) to filter issues by tag(s).
- `--cycle` and `--module` accept either a UUID or the exact name shown by `plane cycles list` / `plane modules list`.
- `plane issue link add` accepts an optional link title via `--title`.
- `plane labels delete` accepts either the label UUID or the exact label name returned by `plane labels list`.
Expand Down
35 changes: 29 additions & 6 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ agent use. Install it globally with bun:
bun install -g @backslash-ux/plane-cli
```

Use `plane --help` or bare `plane` for the short command overview. Use `plane <command> --help` for full syntax on a specific command.

## Configuration

Run once to save credentials interactively:
Expand Down Expand Up @@ -84,16 +86,17 @@ If a local config is active in the current path, `plane projects use PROJ` write

## Structured Output for AI Agents

All list commands support `--xml` and `--json` flags.
List and get commands support `--xml` and `--json` flags. Create, update, and bulk commands keep human-readable output by default and support opt-in `--json`.

- **`--xml`** — outputs a `<results>` document with one `<item>` per record (attributes HTML-escaped). Most reliable for AI parsing.
- **`--json`** — outputs a JSON array.
- **`plane issue get PROJ-N`** — always outputs full JSON, no flag needed.
- **`--json`** — outputs JSON arrays for list commands and stable JSON objects for get/create/update/bulk commands.
- **Issue JSON** — includes `ref`, `title`, `state_name`, `state_group`, and `url` in addition to Plane API fields.

```bash
plane projects list --xml
plane issues list PROJ --xml
plane issues list PROJ --state started --xml
plane issue create PROJ --title "Follow-up" --json
plane stats --json PROJ
plane states list PROJ --xml
plane labels list PROJ --xml
Expand All @@ -119,6 +122,7 @@ plane projects list --include-archived
plane projects use PROJ
plane projects use PROJ --local
plane projects current
plane project context PROJ --json
plane projects list --xml
```

Expand All @@ -138,10 +142,25 @@ plane issues list PROJ --priority high
plane issues list PROJ --no-assignee
plane issues list PROJ --stale 7
plane issues list PROJ --cycle "Week 14"
plane issues list PROJ --label bug
plane issues list PROJ --label bug --label urgent
plane issues list PROJ --xml
```

Filtering is client-side (no server search endpoint). Fetch all and filter locally.
Options may be placed before or after the project argument.

### Bulk Create / Update

```bash
plane issues bulk-create PROJ --file issues.json --state Todo --label pre-UAT
plane issues bulk-create PROJ --file issues.json --dry-run --dedupe title,similarity
plane issues bulk-update PROJ --file updates.json --dry-run
```

Bulk create files contain a JSON array with `title` plus optional issue fields such as `description`, `priority`, `state`, `labels`, `assignee`, `start_date`, `target_date`, `estimate`, `cycle`, and `module`. Shared flags act as defaults; per-record fields override them. Bulk update files require each record to include `ref`.

`--dry-run` validates state, labels, priority, cycle/module, estimate, description shape, and duplicate candidates without mutating Plane. `--dedupe` is report-only and never updates existing issues automatically.

### Get (full JSON)

Expand All @@ -156,6 +175,9 @@ plane issue create --title "Issue title"
plane issue create --title "Issue title" PROJ
plane issue create --priority high --state started --title "Fix lint pipeline"
plane issue create --description '<p>Detailed context</p>' --title "Add dark mode" PROJ
plane issue create --from-file issue.html --title "Add dark mode" PROJ
plane issue create --stdin --title "Add dark mode" PROJ
plane issue create --dedupe title --title "Add dark mode" PROJ
plane issue create --assignee "Jane Doe" --title "Onboarding bug" PROJ
plane issue create --label "bug" --label "urgent" --title "Regression in login flow" PROJ
plane issue create --start-date 2025-04-01 --target-date 2025-04-14 --title "Sprint task" PROJ
Expand All @@ -166,15 +188,15 @@ plane issue create --module "Sprint 3" --title "Scoped to module" PROJ

### Update

> **Important:** Options must come *before* the ref argument.
> `plane issue update --state done PROJ-29` ✅
> `plane issue update PROJ-29 --state done` ❌ (flags after positional args are ignored)
Options may come before or after the ref argument.

```bash
plane issue update --state completed PROJ-29
plane issue update --priority high WEB-5
plane issue update --title "New title" PROJ-29
plane issue update --description '<p>Updated context</p>' PROJ-29
plane issue update PROJ-29 --from-file issue.html
plane issue update PROJ-29 --stdin
plane issue update --assignee "Jane Doe" PROJ-29
plane issue update --no-assignee PROJ-29
plane issue update --label "enhancement" PROJ-29
Expand Down Expand Up @@ -389,6 +411,7 @@ Some deployments do not expose page endpoints even when the project advertises p
- `description` in issue or page create and update flows is passed through to `description_html`; send HTML such as `<p>Details</p>` when you want formatted output.
- `--target-date` has an alias `--due-date` for convenience.
- `--label` can be specified multiple times for multi-label assignment.
- `plane issues list --label` accepts label names (repeatable, AND logic) to filter issues by tag(s).
- `--cycle` and `--module` accept either a UUID or the exact name listed by `plane cycles list` / `plane modules list`. The CLI resolves names internally.
- `plane modules create --lead` accepts a member display name, email, or UUID from `plane members list`.
- `plane modules create --status in_progress` is normalized to Plane's `in-progress` API value.
Expand Down
1 change: 1 addition & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview

This repository publishes from Git tags that match `v*` through [`.github/workflows/publish.yml`](../.github/workflows/publish.yml).
This repository publishes from Git tags that match `v*` through the publish job in [`.github/workflows/ci.yml`](../.github/workflows/ci.yml).

## One-Time Maintainer Setup

Expand All @@ -13,7 +13,7 @@ Before the first public release, make sure the publication path itself is ready:
- keep using the current `NPM_CONFIG_TOKEN` secret with a token that is allowed to publish this package, or
- migrate the workflow to npm trusted publishing so long-lived tokens are no longer required.
3. Add the `NPM_CONFIG_TOKEN` repository secret in GitHub if the token-based workflow remains in use.
4. Confirm GitHub Actions is enabled for the repository and that the publish workflow can create releases. The current workflow already requests `contents: write`.
4. Confirm GitHub Actions is enabled for the repository and that the CI publish job can create releases. The publish job requests `contents: write`.
5. Verify the default branch is healthy before tagging: CI should pass on `main` and the version in `package.json` should match the intended release.
6. Confirm the repository URLs in `package.json` and the install instructions in `README.md` and `SKILL.md` point at the maintained fork.

Expand Down Expand Up @@ -50,10 +50,11 @@ git tag vX.Y.Z
git push origin vX.Y.Z
```

4. The publish workflow will:
4. The CI workflow will:
- install dependencies with Bun
- run the repository gate
- publish the package to npm
- verify the tag version matches `package.json`
- publish the package to npm with the npm CLI
- create a GitHub release with generated notes

## After Releasing
Expand All @@ -76,4 +77,4 @@ bunx @backslash-ux/plane-cli --help

- If the release changes command behavior, keep related GitHub issues, release notes, and docs aligned as part of the same change.
- If a release uncovers a workflow gap, document it here instead of relying on maintainer memory.
- npm currently recommends trusted publishing for GitHub Actions when possible. This repository still uses `NPM_CONFIG_TOKEN`, so moving to trusted publishing plus provenance is a useful follow-up when maintainers are ready.
- npm currently recommends trusted publishing for GitHub Actions when possible. This repository still uses `NPM_CONFIG_TOKEN`, so moving to trusted publishing plus provenance is a useful follow-up when maintainers are ready.
Loading
Loading