i-plane 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md ADDED
@@ -0,0 +1,94 @@
1
+ # Working on this repository
2
+
3
+ Read this before changing anything here. It is not documentation of what the tool
4
+ does — that is `README.md` — it is what breaks when the rules below are ignored.
5
+
6
+ ## What this is
7
+
8
+ A CLI for [Plane](https://plane.so) whose caller is a coding agent, not a person
9
+ at a terminal. Plane's REST answer for seven work items is ~6,500 tokens of JSON;
10
+ this prints ~145 tokens of lines. Every rule below follows from that one fact.
11
+
12
+ ## Authorship
13
+
14
+ Written by Claude (Anthropic) with the repository owner. The owner decides what
15
+ gets built and what ships; the model writes the code, runs the checks, and
16
+ reports what it finds — including when the finding is its own bug.
17
+
18
+ ## Invariants
19
+
20
+ Breaking one of these is a bug even when tests pass.
21
+
22
+ **Nothing prompts, ever.** A CLI that waits for input hangs an agent forever. A
23
+ missing argument is a `UsageError` naming what was expected; `src/commands/guide.ts`
24
+ turns it into a hint with that command's real examples.
25
+
26
+ **Exit codes are a contract.** `2` the call was wrong, `1` Plane refused or was
27
+ unreachable. Callers branch on the code instead of parsing text, so a
28
+ misclassified error is worse than a vague message.
29
+
30
+ **`--json` is never optional.** Commands build a model and hand it to a formatter;
31
+ `printValue` in `src/output.ts` decides between them. Print directly and you have
32
+ silently dropped `--json` for that command.
33
+
34
+ **`src/registry.ts` is the single source for commands.** It feeds the guide, every
35
+ `<command> --help`, and the hint on a failed call — and it is what rejects unknown
36
+ flags. Add a flag to a command without adding it there and the CLI will refuse it.
37
+
38
+ **Never trust a server-side filter.** The list endpoint honours `fields` and
39
+ `expand` (11 KB → 737 bytes on the wire) but accepts `state_group`, `priority` and
40
+ `order_by` with a 200 and ignores them. Narrowing happens in `src/commands/issues.ts`.
41
+
42
+ **Never let the token reach text.** `redact` in `src/client.ts` guards every error
43
+ path; `maskToken` guards `config`. Node puts an offending header value into its
44
+ own error message, and a server can echo a key back in an error body.
45
+
46
+ **Pin versions exactly.** A range once meant the tree tested here and the tree a
47
+ user installs were different — undici, `^7.16.0` against 8.10.2 installed.
48
+
49
+ ## Ground already lost once
50
+
51
+ Twenty-one findings came out of one review. These are the ones worth remembering:
52
+
53
+ | What happened | Why |
54
+ |---|---|
55
+ | ` ```c++ ` hung the process forever | a fence pattern that refused a line without consuming it |
56
+ | `--yes=false` deleted a work item | a switch tested for presence, not value |
57
+ | a misspelled `--priority` returned an unfiltered list, exit 0 | no flag validation |
58
+ | the API token appeared in an error message | masking guarded one command, not the error paths |
59
+ | a description lost `<div>` inside inline code | entity decoding followed by tag stripping |
60
+
61
+ The Markdown conversion was hand-written and lost five ways at once. It now uses
62
+ `markdown-it` and `turndown`. `markdown-it` rather than `marked` for one reason:
63
+ with `html:false` it escapes raw HTML instead of passing `<img src=x onerror=…>`
64
+ into other people's browsers.
65
+
66
+ ## Checks
67
+
68
+ ```bash
69
+ bun test # every case is a bug that shipped once
70
+ ./node_modules/.bin/tsc --noEmit # src and types; tests are checked by bun
71
+ ./node_modules/.bin/biome check .
72
+ node scripts/release.mjs # the full gate, without publishing
73
+ ```
74
+
75
+ Tests are deliberately not in `tsc`'s `include`: pulling `bun-types` in collides
76
+ with `@types/node` inside the library's own declarations, and a type error in
77
+ someone else's file says nothing about this code.
78
+
79
+ ## Testing against a live instance
80
+
81
+ Credentials are at `~/.config/plane/credentials` and the CLI reads them itself, so
82
+ `node dist/cli.js list CLOUD` works with no arguments. Delete anything you create:
83
+
84
+ ```bash
85
+ node dist/cli.js delete CLOUD-42 --yes
86
+ ```
87
+
88
+ ## Releasing
89
+
90
+ Publishing is irreversible — a version cannot be reused, and a tarball that
91
+ shipped too much stays in every mirror. `node scripts/release.mjs` does
92
+ everything except publish; `--publish` is the only path to `npm publish`. The gate
93
+ empties `dist`, runs the checks, smoke-tests the built command, enforces package
94
+ contents and size, and refuses when the registry cannot be reached.
package/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md
package/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # i-plane
2
+
3
+ A command-line client for [Plane](https://plane.so) that prints lines instead of
4
+ JSON dumps.
5
+
6
+ Ask Plane's API for seven work items and it answers with twenty-nine fields
7
+ each — about 6,500 tokens. The same seven through `i-plane` are 145. If you are
8
+ piping work items into a coding agent, that difference is the entire point.
9
+
10
+ ```
11
+ $ i-plane list CLOUD --state started
12
+ CLOUD-4 Create and assign work items [high] (In Progress)
13
+ CLOUD-5 Visualize your work (In Progress)
14
+ ```
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install -g i-plane
20
+ ```
21
+
22
+ Node 20 or newer.
23
+
24
+ ## Set it up
25
+
26
+ You need three things: the address of your Plane, an API key, and a workspace.
27
+ The key comes from **Workspace settings → API tokens**.
28
+
29
+ Supply them however suits you — flags win over environment, environment wins over
30
+ the file:
31
+
32
+ ```bash
33
+ # once, in a file
34
+ mkdir -p ~/.config/plane && chmod 700 ~/.config/plane
35
+ cat > ~/.config/plane/credentials <<'EOF'
36
+ PLANE_URL=https://plane.example.com
37
+ PLANE_API_KEY=plane_api_…
38
+ PLANE_WORKSPACE=my-workspace
39
+ EOF
40
+ chmod 600 ~/.config/plane/credentials
41
+
42
+ # or per call
43
+ i-plane list CLOUD --url https://plane.example.com --token … --workspace my-workspace
44
+ ```
45
+
46
+ Not sure what is in effect:
47
+
48
+ ```
49
+ $ i-plane config
50
+ url https://plane.example.com (file)
51
+ workspace my-workspace (env)
52
+ token plane_…856f (file)
53
+ file /home/you/.config/plane/credentials
54
+ ```
55
+
56
+ ## Use it
57
+
58
+ Run `i-plane` with no arguments and it shows the command map, the usual order of
59
+ work, and how it behaves. `i-plane <command> --help` gives one command's flags
60
+ and real examples.
61
+
62
+ ```
63
+ summary projects and how much is in each
64
+ list [project] work items, one line each --state --priority --limit
65
+ show <ID> one work item, description included
66
+ search <text> across the whole workspace
67
+ create <title> --project --priority --state --description
68
+ update <ID> --state --priority --name --description
69
+ done <ID> move to the first completed state
70
+ comment <ID> <text> add a comment
71
+ delete <ID> --yes delete; refuses without --yes
72
+ projects states labels members whoami config guide
73
+ ```
74
+
75
+ Short forms for what fingers type: `ls`, `new`, `set`, `rm`, `find`.
76
+
77
+ Work items go by the name people say — `CLOUD-8`. Projects take an identifier
78
+ (`CLOUD`), a full name, or a unique prefix of one.
79
+
80
+ Every command accepts `--json` and then prints the whole model, for when you need
81
+ ids and timestamps rather than a readable line.
82
+
83
+ ## Descriptions are Markdown
84
+
85
+ Write them as Markdown; read them back as Markdown. Plane stores HTML, and the
86
+ translation happens here.
87
+
88
+ ````bash
89
+ i-plane create --project CLOUD "Fix the resolver" --description '## Steps
90
+
91
+ ```bash
92
+ dig +short example.com @127.0.0.1
93
+ ```
94
+
95
+ | Node | Role | Status |
96
+ | ---- | ---- | ------ |
97
+ | pi5 | DNS | broken |
98
+
99
+ 1. check the cache
100
+ 2. check the routes'
101
+ ````
102
+
103
+ Code fences keep their language, tables stay tables, ordered lists stay numbered.
104
+ Raw HTML in a description is escaped rather than passed through, so nothing you
105
+ write can execute in someone else's browser.
106
+
107
+ ## Good to know
108
+
109
+ **A list is complete unless it says so.** `list` returns every work item in the
110
+ project. `--limit` exists, but when it cuts the list the last line tells you how
111
+ many rows it hid.
112
+
113
+ **Exit codes mean something.** `2` — the command was wrong. `1` — Plane refused or
114
+ could not be reached. Useful in scripts.
115
+
116
+ **Proxies work without configuration.** If `HTTPS_PROXY` applies to your Plane
117
+ address, it is used; `NO_PROXY` is honoured the way curl honours it, including
118
+ CIDR ranges. On a network without a proxy none of this runs.
119
+
120
+ ## Contributing
121
+
122
+ `AGENTS.md` has the working rules: the invariants, the checks to run, and the
123
+ bugs that already shipped once.
124
+
125
+ ## License
126
+
127
+ MIT