@plotio/cli 0.0.0-stage → 0.2.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -2
  3. package/dist/plot.js +1854 -0
  4. package/package.json +37 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Plot
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,194 @@
1
- # Temporary Holding Version
1
+ # @plotio/cli
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `plot`: read Plot pages, follow a meeting while it happens, and post back, from
4
+ any agent with a shell (Claude Code, Codex CLI, Amp, OpenCode) or a script.
5
+
6
+ Design and reasoning: `plans/agent-cli-and-mcp.md` at the repo root.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npx @plotio/cli help agents # no install
12
+ npm install -g @plotio/cli # or install the `plot` binary
13
+ ```
14
+
15
+ Node 22 or later (the repo pins 24 in `.nvmrc`). In this repo,
16
+ `pnpm --filter @plotio/cli start <command>` runs the TypeScript directly (no
17
+ `--` before the command: pnpm passes it through, and `plot` would read it as
18
+ the command).
19
+
20
+ ## Getting access
21
+
22
+ Two kinds of credential, both `plot_agent_sk_…` tokens that Plot stores only
23
+ as a hash:
24
+
25
+ - **A page.** Someone picks "Copy agent instructions" on a page, which gives
26
+ a one-time `temp_code_…` (ten minutes, single use).
27
+ `plot open temp_code_… --agent "Claude Code"` redeems it for a token that
28
+ reads that one page (24 hours from the last read, a week at most).
29
+ - **A workspace.** `plot login --agent "Claude Code"` signs in the way Claude
30
+ Code does: OAuth authorization code with PKCE (S256), client id `plot-cli`,
31
+ against the authorization server the API names in
32
+ `/.well-known/oauth-authorization-server`. So `--api` at a local or preview
33
+ deployment signs in on that deployment's own web app, never production's.
34
+ The code is exchanged at the token endpoint, `/v1/me` names the workspace,
35
+ and the token is stored as that API's workspace grant.
36
+
37
+ One verifier and state make two authorize URLs that differ only in
38
+ `redirect_uri`, and the server binds a code to the one it was approved with:
39
+ a loopback one (`http://127.0.0.1:<port>/callback`) and the out-of-band
40
+ `urn:ietf:wg:oauth:2.0:oob`, for which the consent page shows the code
41
+ instead of redirecting. The loopback URL is only ever opened, never printed,
42
+ because a browser on any other machine would be redirected into a dead port.
43
+
44
+ - **On your own machine.** The browser opens on the loopback URL; approve
45
+ and it calls the terminal back by itself. Nothing to paste.
46
+ - **Browser elsewhere (SSH, another computer).** The terminal prints the
47
+ out-of-band URL under "A browser tab should have opened. If it did not, or
48
+ it is on another machine, open this URL:". Approve there, and paste the
49
+ code the page shows at `Paste code here if prompted:`. Whichever arrives
50
+ first wins, within ten minutes. `--no-browser` prints only that URL and
51
+ does not listen at all.
52
+ - **An agent or a sandbox (no TTY).** Nothing listens and nothing waits.
53
+ `plot login` prints the out-of-band URL and
54
+ `After approving, run: plot login --code <code>`, saves a pending login
55
+ (API base, verifier, state, agent name, time) in
56
+ `$XDG_CONFIG_HOME/plot/pending-login.json` at `0600`, and exits 0. The agent
57
+ hands the URL to its person, who approves and sends the code back;
58
+ `plot login --code <code>` exchanges it, stores the grant, deletes the
59
+ pending file and prints `Connected to <workspace>`. A pending login lasts
60
+ ten minutes, and `--code` works at a terminal too.
61
+
62
+ ## Commands
63
+
64
+ | Command | Does |
65
+ | ------------------------------------------------- | ----------------------------------------------------------------------------- |
66
+ | `plot open <temp_code_…> [--agent <name>]` | Redeem a handoff code and store the page token |
67
+ | `plot login [--agent] [--no-browser]` | Connect a workspace: sign in and approve in the browser |
68
+ | `plot login --code <code>` | Finish a login started without a terminal, with the code the browser showed |
69
+ | `plot logout [<page>] [--all]` | Revoke a credential on the server, then forget it |
70
+ | `plot whoami [<page>] [--json]` | What the credential acts for, its scope and expiry |
71
+ | `plot pages [--limit <n>] [--next <c>] [--json]` | Pages the workspace grant can read, newest first |
72
+ | `plot read <page> [--json]` | The page as Markdown (topics included), or as JSON; stores the updates cursor |
73
+ | `plot watch <page> [--level …] [options]` | Wait for the next update, print it, store the cursor |
74
+ | `plot topics <page>` | Topics as JSON, with the quotes behind each point |
75
+ | `plot search <query> [--limit] [--next] [--json]` | Search every page the workspace grant can read |
76
+ | `plot post <page> [--branch <id>] [--body <t>]` | Post a message (body from `--body`, else stdin), idempotent per run |
77
+ | `plot mcp-config [--host <h>] [--write] [<page>]` | The MCP server block for a host, pointing at `<api>/mcp` |
78
+ | `plot help agents` | The guide for an AI agent |
79
+
80
+ `<page>` is a page id or a page URL (`https://www.plot.io/p/<id>`).
81
+
82
+ Every command takes `--api <url>`, `--token <token>` and `-h`/`--help`.
83
+ `plot help <command>` lists a command's options.
84
+
85
+ ### `watch`
86
+
87
+ One command is one turn: it blocks until something qualifies, prints only
88
+ what is new since the last `watch` of that page, stores the new cursor and
89
+ exits. Levels: `substantial` (default, when Plot's topic model completed a
90
+ run), `every` (any new words), `topics` (a topic changed). Each request asks
91
+ the server to hold it for up to 240 seconds (`wait=240`, kept under the 300
92
+ seconds Node's fetch waits for response headers); where the server
93
+ answers at once instead (Convex reached directly, in local dev and previews),
94
+ `watch` pauses `--interval` seconds (default 3) and asks again.
95
+ `--timeout <seconds>` gives up, cursor unchanged; keep it under your shell
96
+ tool's own timeout. `--from-start` and `--cursor` override the stored cursor,
97
+ and `--partial` includes words still being spoken (marked `interim`).
98
+
99
+ An update is `{notice, page, level, lines, topics, room, lastRunAt, cursor}`:
100
+ `lines` carry `authorName`, `text` and the flags `continues`, `revised`,
101
+ `removed`, `interim`; `topics` carry their `points` with source quotes;
102
+ `room` is who is present. `plot read` also stores the cursor (from its
103
+ `X-Plot-Updates-Cursor` header), so a `watch` after a `read` brings only what
104
+ was said after it. A stored cursor the server refuses (`bad_cursor`,
105
+ `wrong_cursor_page`) is dropped and the watch starts over once.
106
+
107
+ ### `pages` and `search`
108
+
109
+ Both page with an opaque `next`; keep passing `--next` until the output has
110
+ no "More:" line, since a short batch does not mean the end. A page token on
111
+ either is refused (`wrong_scope`): they need `plot login`.
112
+
113
+ ### `post`
114
+
115
+ Each run generates one idempotency `id` and reuses it if the connection drops
116
+ or a gateway answers 502 to 504, so the message lands once. A refusal is never
117
+ retried: `read_only` means the person who granted access cannot post there.
118
+
119
+ ### `mcp-config`
120
+
121
+ Hosts: `claude-code` (default, `.mcp.json`), `cursor` (`~/.cursor/mcp.json`),
122
+ `vscode` (`.vscode/mcp.json`), `zed` (its `settings.json`) and
123
+ `claude-desktop` (a connector added in its settings, OAuth only). The
124
+ `Authorization` header names the `PLOT_TOKEN` environment variable in the
125
+ host's own syntax (`${PLOT_TOKEN}` for Claude Code, `${env:PLOT_TOKEN}` for
126
+ Cursor and VS Code) rather than holding the token, because `.mcp.json` and
127
+ `.vscode/mcp.json` are usually committed. The token itself (the stored
128
+ workspace one, or `<page>`'s) is printed to stderr as an `export` line to run
129
+ where the host starts. `--inline-token` puts the token in the header instead
130
+ (and makes a file it writes `0600`); Zed cannot read a variable there, so its
131
+ block always holds the token. `--no-token` leaves the header out so the host
132
+ signs in with OAuth. `--write` merges the block into the host's file, keeping
133
+ every other server, and refuses a file whose top level is not a JSON object.
134
+
135
+ ## Environment
136
+
137
+ | Variable | Meaning |
138
+ | ----------------- | ------------------------------------------------------------------------- |
139
+ | `PLOT_API_URL` | API base. Default `https://agents.plot.io`; a deployment's `.convex.site` |
140
+ | | host for local dev and previews. `--api` wins over it. |
141
+ | `PLOT_TOKEN` | Use this token instead of the store (a sandbox or CI job). |
142
+ | `PLOT_AGENT_NAME` | Default `--agent`. Inside Claude Code the default is "Claude Code". |
143
+ | `XDG_CONFIG_HOME` | Where the credential store lives (below). |
144
+
145
+ Token resolution for a page command: `--token`, then `PLOT_TOKEN`, then the
146
+ page's stored grant, then the stored workspace grant. A stored token the
147
+ server calls expired or revoked is removed and the next one tried.
148
+
149
+ ## Where credentials live
150
+
151
+ `$XDG_CONFIG_HOME/plot/credentials.json`, by default
152
+ `~/.config/plot/credentials.json`, mode `0600` in a `0700` directory. Keyed by
153
+ API base, so production's and a preview's tokens never collide:
154
+
155
+ ```json
156
+ {
157
+ "https://agents.plot.io": {
158
+ "workspace": {
159
+ "token": "plot_agent_sk_…",
160
+ "workspace": "Acme",
161
+ "expiresAt": "…"
162
+ },
163
+ "pages": {
164
+ "<pageId>": {
165
+ "token": "plot_agent_sk_…",
166
+ "expiresAt": "…",
167
+ "title": "…",
168
+ "cursor": "…"
169
+ }
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ A page entry can hold just a `cursor` when that page is watched through the
176
+ workspace grant. `plot logout --all` revokes and removes everything for the
177
+ current API base.
178
+
179
+ ## Development
180
+
181
+ ```bash
182
+ pnpm --filter @plotio/cli test # node --test, no network
183
+ pnpm --filter @plotio/cli type-check
184
+ pnpm --filter @plotio/cli lint
185
+ pnpm --filter @plotio/cli build # dist/plot.js, one bundled file
186
+ ```
187
+
188
+ `dist/` is not committed; `prepack` runs the build, so `pnpm pack` and
189
+ `pnpm publish` from a clean tree still ship `dist/plot.js`.
190
+
191
+ All HTTP lives in `src/api.ts`. The build bundles with esbuild rather than
192
+ emitting with `tsc`, because `@plot/shared` (token shapes) is a private
193
+ workspace package: the bundle inlines it, so the
194
+ published package has no dependencies at all.