@wirecat/cli-base 0.50.2 → 0.50.4
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/CHANGELOG.md +32 -0
- package/README.md +6 -4
- package/dist/standards/flags-what.js +28 -0
- package/dist/standards/vocabulary.js +12 -1
- package/docs/standards/README.md +1 -0
- package/docs/standards/accounts.md +1 -2
- package/docs/standards/ci.md +5 -4
- package/docs/standards/commands.md +2 -2
- package/docs/standards/comparisons.md +118 -0
- package/docs/standards/mcp.md +27 -29
- package/docs/standards/permissions.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,38 @@ Versions before 0.8.0 are in the [git tags](https://github.com/WireCatLabs/cli-b
|
|
|
8
8
|
Every entry says what changed as a caller sees it, why, and what to watch for — the rules are
|
|
9
9
|
[`docs/dev/CONVENTIONS.md`](docs/dev/CONVENTIONS.md#the-changelog).
|
|
10
10
|
|
|
11
|
+
## 0.50.4 — 24.10.2026
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **The shared vocabulary covers knowledge-work resources and receipt delivery.** Registers agents,
|
|
16
|
+
reminders, key documents, evidence answers and the mail archive, with distinct assignment, decision reversal,
|
|
17
|
+
evidence invalidation and receipt acknowledgement actions. Registers the four missing stored meeting
|
|
18
|
+
selector ID flags with target roles. Existing canonical verbs still replace overlapping Memo spellings;
|
|
19
|
+
forum `--topic <id>` keeps its existing meaning, while meeting tags/topics use native query terms.
|
|
20
|
+
|
|
21
|
+
- **A standard for comparison pages** ([Comparisons](docs/standards/comparisons.md), `WC-CMP-1` to `WC-CMP-10`). A CLI's `docs/compare.md` compares it with the tools a reader would pick for the same job, lists user tasks rather than implementation details, always has an "Agents and safety" group and says where another tool is better (owner, 2026-10-24). Nothing changes in code.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **Denied commands remain discoverable.** The MCP and permission standards require current availability metadata instead of hiding denied commands. CLI help retains the same capabilities; execution still enforces the permission. This records the owner's discovery rule for every CLI.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
- **`sync` covers a two-way mirror.** The vocabulary's meaning of `sync` now says a mirror syncs both ways, so drive's `mirrors sync`, which also writes changes back to Google, uses the verb as defined (owner, 2026-10-24). Nothing changes for one-way syncs.
|
|
29
|
+
|
|
30
|
+
- **Release checks reject high production dependency findings and audit a fresh npm resolution.** The lockfile-only
|
|
31
|
+
critical gate missed high findings and newer transitive resolutions. Update the reusable workflow pin to adopt
|
|
32
|
+
the checks; fix high findings before releasing. Package packing and resolution disable lifecycle scripts.
|
|
33
|
+
|
|
34
|
+
## 0.50.3 — 23.10.2026
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **The vocabulary has `press` and `app` for a messenger's bot buttons.** Verb `press` (press a button under a bot's
|
|
39
|
+
message; the bot sees who pressed it), the owner's word for it (2026-10-23), and view `app` (a bot's mini app: the
|
|
40
|
+
address that opens it). tg and max mount `messages press` and `chats app`, so `unknown-verb` stops reporting them;
|
|
41
|
+
a CLI whose baseline lists them sees "stale baseline entry" and removes the lines.
|
|
42
|
+
|
|
11
43
|
## 0.50.2 — 23.10.2026
|
|
12
44
|
|
|
13
45
|
### Added
|
package/README.md
CHANGED
|
@@ -24,8 +24,9 @@ the command tree as data — the parts every CLI needs and nobody should write t
|
|
|
24
24
|
| [Shared tooling](docs/TOOLING.md) | The TypeScript, Biome, lefthook, docs and CI setup a CLI takes from here, and `cli-dev` |
|
|
25
25
|
| [Testing](docs/dev/TESTING.md) | The checks, and what each one is for |
|
|
26
26
|
| [Conventions](docs/dev/CONVENTIONS.md) | How code here is written |
|
|
27
|
-
| [Standards handbook](docs/standards/README.md) | The rules every WireCat CLI follows, one page per area
|
|
28
|
-
| [CLI standard](https://github.com/WireCatLabs/cli-core/blob/main/docs/dev/STANDARD.md) | The rules
|
|
27
|
+
| [Standards handbook](docs/standards/README.md) | The rules every WireCat CLI follows, one page per area and a new-CLI checklist |
|
|
28
|
+
| [CLI standard](https://github.com/WireCatLabs/cli-core/blob/main/docs/dev/STANDARD.md) | The messenger-specific rules for tg, max and wa |
|
|
29
|
+
| [Roadmap](docs/roadmap.md) | What is being built next for developers on this package |
|
|
29
30
|
| [Changelog](CHANGELOG.md) | What each version changed, and what may break callers |
|
|
30
31
|
|
|
31
32
|
## What it is
|
|
@@ -112,12 +113,13 @@ record — live in `/standards` as Valibot schemas that also emit JSON Schema 20
|
|
|
112
113
|
|
|
113
114
|
- **The whole command tree as data.** `describeProgram` walks the live Commander tree, like `rails routes`: every
|
|
114
115
|
command, option, default, conflict and whether it writes. `commands --json` gives it to an agent instead of `--help`.
|
|
115
|
-
- **A linter for command trees.** `cli-dev lint` checks a CLI's tree against
|
|
116
|
+
- **A linter for command trees.** `cli-dev lint` checks a CLI's tree against 19 rules — unknown verbs, filter flags
|
|
116
117
|
that should be query fields, examples that do not run, key casing and more. Known violations live in a baseline
|
|
117
118
|
that may only shrink.
|
|
118
119
|
- **An audit across CLIs.** `cli-dev audit` reads several CLIs' command trees and checks them against each other:
|
|
119
120
|
the commands every CLI must have, the same options and output where two CLIs share a path, the same meaning for the
|
|
120
|
-
same flag
|
|
121
|
+
same flag. Entity-schema and error-reason comparisons require additional inputs; the weekly published-CLI
|
|
122
|
+
run does not supply them and reports `n/a` for those checks.
|
|
121
123
|
|
|
122
124
|
### One query language for every list
|
|
123
125
|
|
|
@@ -323,6 +323,34 @@ export const WHAT_FLAGS = [
|
|
|
323
323
|
meaning: "look again at this many recent days, for what arrived late",
|
|
324
324
|
unit: "days",
|
|
325
325
|
},
|
|
326
|
+
{
|
|
327
|
+
name: "--meeting-id",
|
|
328
|
+
value: "<id>",
|
|
329
|
+
role: "target",
|
|
330
|
+
type: "id",
|
|
331
|
+
meaning: "one stored meeting selected for transcript search",
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
name: "--identity-id",
|
|
335
|
+
value: "<id>",
|
|
336
|
+
role: "target",
|
|
337
|
+
type: "id",
|
|
338
|
+
meaning: "a stored participant identity whose meetings are selected; does not identify the speaker of a hit",
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
name: "--person-id",
|
|
342
|
+
value: "<id>",
|
|
343
|
+
role: "target",
|
|
344
|
+
type: "id",
|
|
345
|
+
meaning: "a stored person whose linked participant identities select meetings",
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
name: "--series-id",
|
|
349
|
+
value: "<id>",
|
|
350
|
+
role: "target",
|
|
351
|
+
type: "id",
|
|
352
|
+
meaning: "one stored recurring series selected for meeting search",
|
|
353
|
+
},
|
|
326
354
|
{ name: "--meeting", value: "<id>", role: "target", type: "id", meaning: "a meeting, by its store id" },
|
|
327
355
|
{
|
|
328
356
|
name: "--message",
|
|
@@ -120,7 +120,7 @@ const verbs = [
|
|
|
120
120
|
["cancel", "stop a job or a pending thing"],
|
|
121
121
|
[
|
|
122
122
|
"sync",
|
|
123
|
-
"bring the local store up to date from the source: only what changed, or the whole list where the source cannot say",
|
|
123
|
+
"bring the local store up to date from the source: only what changed, or the whole list where the source cannot say; a mirror syncs both ways",
|
|
124
124
|
],
|
|
125
125
|
["fetch", "one bounded pull of one named thing into the store, not a catch-up"],
|
|
126
126
|
["export", "write from the store to a file"],
|
|
@@ -153,6 +153,7 @@ const verbs = [
|
|
|
153
153
|
["unstar", "take the owner's star off a message"],
|
|
154
154
|
["vote", "answer a poll"],
|
|
155
155
|
["answer", "reply to a button someone pressed under a bot's message"],
|
|
156
|
+
["press", "press a button under a bot's message; the bot sees who pressed it"],
|
|
156
157
|
["action", "show what a bot is doing in a chat, such as typing, for a few seconds"],
|
|
157
158
|
["watch", "follow new events as they come, and keep them"],
|
|
158
159
|
["close", "close a thing that stays: a poll, a task"],
|
|
@@ -168,6 +169,10 @@ const verbs = [
|
|
|
168
169
|
["unarchive", "bring an archived chat back to the main chat list"],
|
|
169
170
|
["reset", "replace a thing; the old one stops working"],
|
|
170
171
|
["moderate", "apply a chat's rules: delete what breaks them, act on who broke them"],
|
|
172
|
+
["assign", "name the person responsible for work, with their task role"],
|
|
173
|
+
["reverse", "record that an accepted decision no longer holds, without replacing it"],
|
|
174
|
+
["invalidate", "mark a derived record whose supporting evidence no longer holds"],
|
|
175
|
+
["acknowledge", "record successful delivery using the exact receipt issued when the item was claimed"],
|
|
171
176
|
["confirm", "the owner accepts what an agent proposed"],
|
|
172
177
|
["reject", "the owner refuses what an agent proposed"],
|
|
173
178
|
["move", "move a file in the source"],
|
|
@@ -238,6 +243,10 @@ const collections = [
|
|
|
238
243
|
["recordings", "the files a provider recorded of a meeting"],
|
|
239
244
|
["jobs", "work this tool runs in the background or on a timer"],
|
|
240
245
|
["actions", "what an agent proposes to do; the owner confirms or rejects each"],
|
|
246
|
+
["agents", "the agents whose actions are recorded in the shared store"],
|
|
247
|
+
["reminders", "scheduled notices about stored work, claimed and acknowledged with delivery receipts"],
|
|
248
|
+
["key-documents", "selected source documents that a project keeps as its starting references"],
|
|
249
|
+
["answers", "evidence-grounded answers assembled from selected stored sources"],
|
|
241
250
|
["aliases", "other names of one thing"],
|
|
242
251
|
["mentions", "phones, e-mail addresses, links and documents found in stored text, each where it was written"],
|
|
243
252
|
["images", "pictures in stored messages, searched by what they show"],
|
|
@@ -263,6 +272,7 @@ const collections = [
|
|
|
263
272
|
const singulars = [
|
|
264
273
|
["session", "this tool's login"],
|
|
265
274
|
["account", "the messenger or mail account behind a profile"],
|
|
275
|
+
["mail", "the local email archive and its mailbox import, rules and cleanup operations"],
|
|
266
276
|
["config", "a profile's settings"],
|
|
267
277
|
["server", "the long-running process of a profile"],
|
|
268
278
|
["store", "the local SQLite database the tools share"],
|
|
@@ -305,6 +315,7 @@ const views = [
|
|
|
305
315
|
["unanswered", "questions without an observed qualifying answer"],
|
|
306
316
|
["me", "the account a profile's token belongs to"],
|
|
307
317
|
["between", "the messages between two given messages of one chat"],
|
|
318
|
+
["app", "a bot's mini app: the address that opens it, signed in as the owner"],
|
|
308
319
|
];
|
|
309
320
|
const roots = [
|
|
310
321
|
["batch", "run bounded explicitly registered reads with independent correlated answers"],
|
package/docs/standards/README.md
CHANGED
|
@@ -38,6 +38,7 @@ rules it keeps. A new CLI is ready for its first release when every check under
|
|
|
38
38
|
| [Testing](testing.md) | `TEST` | 17 | Sandbox, no network, no real waits, leak tests, coverage, contracts, test matrix, parity |
|
|
39
39
|
| [Security](security.md) | `SECR` | 20 | Secrets, logs, keyring, argv, error text, untrusted text, scanners, workflow hardening, reporting |
|
|
40
40
|
| [Documents](docs.md) | `DOC` | 20 | User pages and developer pages, generated pages, current facts, changelog |
|
|
41
|
+
| [Comparisons](comparisons.md) | `CMP` | 10 | Which tools a comparison page lists, rows as user tasks, agents and safety, where others are better, proof of marks |
|
|
41
42
|
| [Releases](releases.md) | `REL` | 16 | `bin/release`, the release lock, versions, release reports, trusted publishing |
|
|
42
43
|
| [CI](ci.md) | `CI` | 12 | Hooks, the pull request budget, full validation, monthly runs |
|
|
43
44
|
| [Time](time.md) | `TIME` | 6 | UTC in the store and in answers, the zone at input and display edges, date-only filters, tests in another zone |
|
|
@@ -13,8 +13,7 @@ Rule ids on this page are `WC-ACCT-<n>`. How to read a rule, how ids work and wh
|
|
|
13
13
|
|
|
14
14
|
### Who follows these rules today
|
|
15
15
|
|
|
16
|
-
cli-core resolves the profile for tg, max and wa. WC-ACCT-1 needs cli-core 0.319.0 or newer, and
|
|
17
|
-
0.321.0. memo has no messenger profile: its shared commands run without one, and they pick accounts with `--provider`
|
|
16
|
+
cli-core resolves the profile for tg, max and wa. WC-ACCT-1 needs cli-core 0.319.0 or newer. memo has no messenger profile: its shared commands run without one, and they pick accounts with `--provider`
|
|
18
17
|
and `--account` (WC-ACCT-7). zoom resolves its own profile word by the same rules (`zm <profile> …`, `ZM_PROFILE`,
|
|
19
18
|
`ZM_PROFILE_LOCK`) from zoom-cli 0.35.0, with cli-core's `liftProfile` and `usableProfileName`. drive still has its own
|
|
20
19
|
profile code: it registers its own profiles. That is a known gap, not an exception.
|
package/docs/standards/ci.md
CHANGED
|
@@ -96,7 +96,7 @@ cli-testing, cli-docs, plus community itself.
|
|
|
96
96
|
cli-docs validates its site before each deployment instead, and community has no build. Third-party security apps
|
|
97
97
|
may post their own checks.
|
|
98
98
|
- **Applies to:** the CLIs, cli-base, cli-core and cli-testing. cli-base, whatsapp-cli, tg-cli, max-cli, cli-core
|
|
99
|
-
cli-memo and
|
|
99
|
+
cli-memo, zoom-cli and drive-cli have `pr.yml`; cli-testing does not have it yet. **Since:**
|
|
100
100
|
cli-base 0.41.0 (pull request validation since cli-base 0.44.6). **Rulings:** none.
|
|
101
101
|
|
|
102
102
|
### WC-CI-6 · Run the changelog guard on every pull request
|
|
@@ -168,9 +168,10 @@ cli-testing, cli-docs, plus community itself.
|
|
|
168
168
|
- **Why:** a red merge breaks `main` for every parallel branch, and an admin merge skips the only gate there is.
|
|
169
169
|
- **Enforced by:** `whatsapp-cli: main ruleset required checks` · `cli-core: main ruleset required checks` ·
|
|
170
170
|
`tg-cli: main ruleset required checks` · `max-cli: main ruleset required checks` ·
|
|
171
|
-
`cli-memo: main ruleset required checks
|
|
172
|
-
the ruleset requires the pull request validation jobs besides the
|
|
173
|
-
have no pr.yml, so their rulesets require only the standards job, and
|
|
171
|
+
`cli-memo: main ruleset required checks` · `drive-cli: main ruleset required checks`, plus the main ruleset of
|
|
172
|
+
cli-base itself. In each repository with pr.yml, the ruleset requires the pull request validation jobs besides the
|
|
173
|
+
standards job. cli-testing and cli-docs have no pr.yml, so their rulesets require only the standards job, and
|
|
174
|
+
review covers the rest. zoom-cli has pr.yml,
|
|
174
175
|
but its ruleset still requires only the standards job.
|
|
175
176
|
- **Example:** `gh pr checks <number>` shows every line as pass before `gh pr merge`. Never merge with `--admin`. A
|
|
176
177
|
release changes `main` the same way
|
|
@@ -287,10 +287,10 @@ Each of these is set with `annotate(command, { … })` from `@wirecat/cli-base/c
|
|
|
287
287
|
### WC-CMD-27 · Refuse a command path that arrived as one word
|
|
288
288
|
|
|
289
289
|
- **Why:** a shell loop that quotes `"projects add"` would otherwise get the root help and no reason.
|
|
290
|
-
- **Enforced by:** `src/commands/commands.test.ts` · `cli-memo: src/program.test.ts`.
|
|
290
|
+
- **Enforced by:** `src/commands/commands.test.ts` · `cli-memo: src/program.test.ts` · `cli-core: src/cli/program.ts`.
|
|
291
291
|
- **Example:** call `refuseJoinedPath(program, args)` before `parseAsync`. It throws a `validation_error` that names
|
|
292
292
|
the words to type.
|
|
293
|
-
- **Exceptions:** none.
|
|
293
|
+
- **Exceptions:** none. memo and cli-core call `refuseJoinedPath` before parsing.
|
|
294
294
|
- **Applies to:** all CLIs. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
295
295
|
|
|
296
296
|
## External references
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Comparisons
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
How a CLI's comparison page (`docs/compare.md`) is written: which tools it compares, which rows it has, how a mark is
|
|
6
|
+
proven, and what it says about the places where another tool is better. The page is read by someone choosing a tool
|
|
7
|
+
for a job, not by someone reviewing our code.
|
|
8
|
+
|
|
9
|
+
Rule ids on this page are `WC-CMP-<n>`. How to read a rule, how ids work and which rule wins are in the
|
|
10
|
+
[index](README.md). The general rules for user pages are in [Documents](docs.md).
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
### WC-CMP-1 · Compare with the tools a reader would pick instead, for the same job
|
|
15
|
+
|
|
16
|
+
- **Why:** a table against products in another category answers a question nobody asked and makes us look either
|
|
17
|
+
better or worse than we are.
|
|
18
|
+
- **Enforced by:** review only.
|
|
19
|
+
- **Example:** zm is compared with other command lines and MCP servers for a Zoom account. Meeting assistants that
|
|
20
|
+
join calls (Otter, Fireflies) are a different job; that comparison stays private until zm does that job too.
|
|
21
|
+
- **Exceptions:** one column may be the official app or the official API, when readers would otherwise use it.
|
|
22
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
23
|
+
|
|
24
|
+
### WC-CMP-2 · A row is a task the user wants done, grouped by how people use the tool
|
|
25
|
+
|
|
26
|
+
- **Why:** people choose a tool by what they can do with it: read and send messages, send photos, find a chat, find a
|
|
27
|
+
file, keep a draft, see who is active in a group. How login works or where data is stored is rarely the reason.
|
|
28
|
+
- **Enforced by:** review only.
|
|
29
|
+
- **Example:** groups such as "Catch up", "Reply and send", "Find", "Files and media", "Organise", "Overview and
|
|
30
|
+
analytics", "Agents and safety", "Setup". Rows such as "Send several photos as one album", "Find a file someone sent
|
|
31
|
+
in any chat". Not rows such as "QR login and two-step password" or "Works without a local copy".
|
|
32
|
+
- **Exceptions:** an implementation detail gets a row only when it changes what the user can do, such as "Search
|
|
33
|
+
without internet".
|
|
34
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
35
|
+
|
|
36
|
+
### WC-CMP-3 · A missing feature gets a row only if users would choose a tool by it
|
|
37
|
+
|
|
38
|
+
- **Why:** a row we fail reads as a gap to fix. A rare account setting listed as missing makes the product look
|
|
39
|
+
incomplete for no reason.
|
|
40
|
+
- **Enforced by:** review only.
|
|
41
|
+
- **Example:** "Set or remove the cloud password" is not a row on max's page. "Drafts" is.
|
|
42
|
+
- **Exceptions:** none.
|
|
43
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
44
|
+
|
|
45
|
+
### WC-CMP-4 · Write each row so that ❌ cannot be misread
|
|
46
|
+
|
|
47
|
+
- **Why:** a short noun can name a bigger thing than the row means; with ❌ beside it the reader concludes the tool
|
|
48
|
+
cannot do the bigger thing.
|
|
49
|
+
- **Enforced by:** review only.
|
|
50
|
+
- **Example:** "Show the other person that you are typing", not "Typing". ❌ beside "Typing" reads as "cannot send
|
|
51
|
+
messages".
|
|
52
|
+
- **Exceptions:** none.
|
|
53
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
54
|
+
|
|
55
|
+
### WC-CMP-5 · Every page has an "Agents and safety" group, and it may be the largest
|
|
56
|
+
|
|
57
|
+
- **Why:** it is what the WireCat tools are built for, and what a reader cannot learn from a feature list: what an
|
|
58
|
+
agent may do without asking, how a wrong send is stopped, what the agent sees.
|
|
59
|
+
- **Enforced by:** review only.
|
|
60
|
+
- **Example:** rows such as "An agent can read but not send unless you allow it", "Ask before each send", "Limit sends
|
|
61
|
+
to a list of chats", "A send is never made twice after a retry", "Every command reachable through MCP", "Works with
|
|
62
|
+
an agent without a browser".
|
|
63
|
+
- **Exceptions:** none.
|
|
64
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
65
|
+
|
|
66
|
+
### WC-CMP-6 · Keep technical rows few, and only where they help a choice
|
|
67
|
+
|
|
68
|
+
- **Why:** a reader who wants protocol details reads the docs; a comparison full of them hides the answer.
|
|
69
|
+
- **Enforced by:** review only.
|
|
70
|
+
- **Example:** one "Setup" group: install command, platforms, licence, price, MCP over stdio or HTTP, and how the tool
|
|
71
|
+
compares with a browser agent driving the web app (speed, cost, reliability).
|
|
72
|
+
- **Exceptions:** none.
|
|
73
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
74
|
+
|
|
75
|
+
### WC-CMP-7 · Say plainly where another tool is better
|
|
76
|
+
|
|
77
|
+
- **Why:** a table that only shows our wins is not believed, and a reader who finds the gap later stops trusting the
|
|
78
|
+
rest.
|
|
79
|
+
- **Enforced by:** review only.
|
|
80
|
+
- **Example:** a section "Where another tool fits better" with two to four scenarios, each one sentence: the job, the
|
|
81
|
+
tool that does it better, why. Only gaps a reader would care about (WC-CMP-3).
|
|
82
|
+
- **Exceptions:** none.
|
|
83
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
84
|
+
|
|
85
|
+
### WC-CMP-8 · No "better" or "faster" without a published measurement
|
|
86
|
+
|
|
87
|
+
- **Why:** a quality claim against another tool is the claim a reader is most likely to test.
|
|
88
|
+
- **Enforced by:** review only.
|
|
89
|
+
- **Example:** "memo finds better answers than Hindsight" needs a result in cli-testing `performance/` and a link to
|
|
90
|
+
it. Without one, the row says what each tool does ("search by words and by meaning"), not which does it better.
|
|
91
|
+
- **Exceptions:** none.
|
|
92
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** none.
|
|
93
|
+
|
|
94
|
+
### WC-CMP-9 · Every mark is proven, and the page says when it was checked
|
|
95
|
+
|
|
96
|
+
- **Why:** a comparison goes stale faster than any other page, and a wrong mark about another project is unfair to
|
|
97
|
+
it.
|
|
98
|
+
- **Enforced by:** review only.
|
|
99
|
+
- **Example:** our marks are checked against the code on `main` or by running the tool. A competitor mark links to
|
|
100
|
+
its own documentation or source. A mark that cannot be proven is ➖ ("not in its documentation"). The intro names the
|
|
101
|
+
check date. The legend is ✅ yes · 🟡 partly · ❌ no · ➖ not in its documentation, plus "n/a" where
|
|
102
|
+
a row cannot apply to a tool (an MCP row for a connector that is itself the agent).
|
|
103
|
+
- **Exceptions:** none.
|
|
104
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** none.
|
|
105
|
+
|
|
106
|
+
### WC-CMP-10 · Keep the table short enough to read
|
|
107
|
+
|
|
108
|
+
- **Why:** past about 25 rows the reader stops scanning, and the rows that matter are lost.
|
|
109
|
+
- **Enforced by:** review only.
|
|
110
|
+
- **Example:** one feature table, with each group as a bold row inside it; 15 to 25 rows and 3 to 6 tools. A row
|
|
111
|
+
where every tool has the same mark is dropped.
|
|
112
|
+
- **Exceptions:** none.
|
|
113
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.50.4. **Rulings:** owner, 2026-10-24.
|
|
114
|
+
|
|
115
|
+
## Sources
|
|
116
|
+
|
|
117
|
+
- Owner review of the max, zm and memo comparison pages, 2026-10-24.
|
|
118
|
+
- The tg comparison page, `tg-cli/docs/compare.md`, the first page written this way.
|
package/docs/standards/mcp.md
CHANGED
|
@@ -2,17 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Scope
|
|
4
4
|
|
|
5
|
-
How a CLI serves agents over MCP: the tools it exposes, how they are built from the command tree, and
|
|
6
|
-
permission level makes visible.
|
|
5
|
+
How a CLI serves agents over MCP: the tools it exposes, how they are built from the command tree, and how permission levels control availability and execution.
|
|
7
6
|
|
|
8
7
|
**MCP** (Model Context Protocol) is how an AI agent asks a program what it can do (`tools/list`) and then calls it. A
|
|
9
8
|
**tool** is a name, a description, an input schema and the code that runs when it is called.
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
1. **Rules** — what is true on cli-core 0.321.0, the version these rules were checked against. Each has a `WC-MCP` id.
|
|
14
|
-
2. **[Planned — not built yet](#planned--not-built-yet)** — the approved design that replaces hand-written tools. It
|
|
15
|
-
has no ids, because it is not true yet. Do not write code that expects it.
|
|
10
|
+
The rules below define the MCP contract. [Tools generated from commands](#tools-generated-from-commands)
|
|
11
|
+
explains how cli-core builds and filters the catalogue.
|
|
16
12
|
|
|
17
13
|
Rule ids on this page are `WC-MCP-<n>`. How to read a rule, how ids work and which rule wins are in the
|
|
18
14
|
[index](README.md).
|
|
@@ -86,18 +82,25 @@ Both declare the answer envelope (a list `{ items, page, … }` or one thing `{
|
|
|
86
82
|
- **Exceptions:** none.
|
|
87
83
|
- **Applies to:** all CLIs. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
88
84
|
|
|
89
|
-
|
|
85
|
+
<a id="wc-mcp-6--the-profiles-permissions-decide-what-is-offered-and-what-runs"></a>
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
not offered when a key it reads, such as `messages`, is `deny`. The list is built when the server starts. The personal
|
|
93
|
-
server reads the permissions again on every call, so a stricter level refuses the next call at once; a command allowed
|
|
94
|
-
after start-up appears only after a restart.
|
|
87
|
+
### WC-MCP-6 · Permissions change availability, not command existence
|
|
95
88
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
CLI help and discovery retain commands regardless of profile permissions. MCP listings and searches also
|
|
90
|
+
retain commands whose own permission, a required read permission or a process read-only lock prevents execution.
|
|
91
|
+
They report current `availability`: `available: false`, a reason and the permission key where applicable.
|
|
92
|
+
Permitted commands report `available: true`. Arguments and answer schemas remain discoverable either way.
|
|
93
|
+
|
|
94
|
+
Availability is permission information, not an execution grant. Every call rechecks the current rules before
|
|
95
|
+
performing work. Changes to profile levels update discovery availability without erasing commands or requiring
|
|
96
|
+
agents to conclude that a capability does not exist. With a named profile, CLI help and discovery annotate the
|
|
97
|
+
same local permission decision; discovery without a profile remains independent of account configuration.
|
|
98
|
+
|
|
99
|
+
- **Why:** an agent must distinguish a supported capability that is currently blocked from an unknown command.
|
|
100
|
+
- **Enforced by:** `cli-core: src/mcp/mcp.test.ts`; custom servers need the same contract.
|
|
101
|
+
- **Example:** `{ "messages.send": "deny" }` leaves `messages send` searchable with `availability: { available: false, reason: "the profile denies messages.send", permission: "messages.send" }`; calling it returns `permission_error`.
|
|
102
|
+
- **Exceptions:** transport exclusions, such as an interactive login or an unbounded process, are independent of permissions and remain documented.
|
|
103
|
+
- **Applies to:** all CLIs. **Since:** cli-core 0.408.0. **Rulings:** owner, 2026-10-24.
|
|
101
104
|
|
|
102
105
|
### WC-MCP-7 · Over MCP, `ask` counts as `allow`, and no server shows a form
|
|
103
106
|
|
|
@@ -187,26 +190,22 @@ and every write goes through the write guard ([WC-PERM-13](permissions.md#wc-per
|
|
|
187
190
|
- **Exceptions:** none.
|
|
188
191
|
- **Applies to:** all CLIs. **Since:** cli-base 0.44.0. **Rulings:** none.
|
|
189
192
|
|
|
190
|
-
|
|
193
|
+
<a id="planned--not-built-yet"></a>
|
|
191
194
|
|
|
192
|
-
|
|
193
|
-
release says it is done, the rules above describe what runs.
|
|
195
|
+
## Tools generated from commands
|
|
194
196
|
|
|
195
|
-
|
|
197
|
+
cli-core builds its personal and bot MCP catalogues from the command tree with `toolsFromCommands`
|
|
198
|
+
(`src/mcp/agent.ts`). Permission keys limit what each profile can call, including writes.
|
|
196
199
|
|
|
197
200
|
- **Tools come from commands.** The catalogue is generated from the command tree, the same data as `commands --json`.
|
|
198
201
|
A call runs the command itself, in-process, and hands back the answer object. Permissions, `ask`, effects, answers
|
|
199
|
-
and errors are
|
|
202
|
+
and errors are the CLI's own, because they are the same code. Calls share the CLI execution path.
|
|
200
203
|
- **`mcp: false` hides a command from MCP servers.** It is set on a command or a group and covers everything below it.
|
|
201
204
|
Agents that use the CLI directly are not affected.
|
|
202
|
-
|
|
203
|
-
`mcp: false` on each command it reaches.
|
|
204
|
-
- **Not built today:** no MCP server reads it yet, so setting it hides nothing.
|
|
205
|
+
`commands --json` shows `mcp: false` on each command it reaches, and cli-core omits it from the catalogue.
|
|
205
206
|
- **`mcp: false` on an option** leaves that option out of the tool's input. The first use is
|
|
206
207
|
`messages delete --for-everyone`, because an agent never deletes for everyone ([WC-PERM-11](permissions.md)).
|
|
207
|
-
|
|
208
|
-
`mcp: false` on that option alone.
|
|
209
|
-
- **Not built today:** no MCP server reads it yet, so setting it hides nothing.
|
|
208
|
+
cli-base's `annotateOption(option, { mcp: false })` sets it; cli-core omits that option from the tool input.
|
|
210
209
|
- **Never offered, by rule:** a command with a `lifetime` (`persistent`, such as `serve` and `watch`, or `interactive`,
|
|
211
210
|
such as `session start`). An agent call must return.
|
|
212
211
|
- **One server per subtree.** The personal server is built from the program without its `bot` group; the bot server
|
|
@@ -214,7 +213,6 @@ What will change:
|
|
|
214
213
|
- **The profile still decides at run time** what is listed (WC-MCP-6).
|
|
215
214
|
- **The whole catalogue is pinned** in each CLI's `contracts/mcp-tools.json`, so a command that becomes visible to
|
|
216
215
|
agents shows up as a diff in its pull request.
|
|
217
|
-
- **Every surface moves**, in this order: drive, the bot servers, memo, zoom, then the tg and max personal servers.
|
|
218
216
|
|
|
219
217
|
## Sources
|
|
220
218
|
|
|
@@ -47,7 +47,7 @@ way for a command the owner types and for an agent over MCP. A config file that
|
|
|
47
47
|
### WC-PERM-2 · There are four levels: `deny`, `readonly`, `ask`, `allow`
|
|
48
48
|
|
|
49
49
|
- `deny` — nothing, not even a read. The command answers `permission_error` (exit 5) before it connects, and an agent
|
|
50
|
-
|
|
50
|
+
still discovers the command, marked unavailable with its permission reason ([WC-MCP-6](mcp.md)).
|
|
51
51
|
- `readonly` — reads work, writes answer `permission_error`. On a key that only writes, such as `messages.delete`, it
|
|
52
52
|
is the same as `deny`.
|
|
53
53
|
- `ask` — a write asks first. See WC-PERM-9 for a terminal and [WC-MCP-7](mcp.md) for an agent.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-base",
|
|
3
|
-
"version": "0.50.
|
|
3
|
+
"version": "0.50.4",
|
|
4
4
|
"description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|