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 +94 -0
- package/CLAUDE.md +1 -0
- package/README.md +127 -0
- package/dist/cli.js +129 -0
- package/package.json +50 -0
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
|