@wirecat/cli-base 0.63.0 → 0.64.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.
@@ -125,7 +125,11 @@ on the [CI](ci.md) page.
125
125
  - **Example:** `bin/release` starts `release.yml` and follows it. Only the `publish` job has the OIDC permission (the
126
126
  short-lived identity npm trusts), and it runs no project code: it only runs `npm publish` on the validated file.
127
127
  - **Exceptions:** npm trusts the workflow by file name: renaming `release.yml` stops publishing until npm's trusted
128
- publisher settings are updated.
128
+ publisher settings are updated. npm sets a trusted publisher on the package's settings page
129
+ ([npm docs](https://docs.npmjs.com/trusted-publishers)), which a package has only once it is published, so its
130
+ first version is published with `bin/release --local` by the owner, from a clean `main`. Right after it, the owner
131
+ adds the trusted publisher on npmjs.com (step 2 of [New CLI](new-cli.md#four-steps-that-need-a-person)), and every
132
+ later version goes through `release.yml`.
129
133
  - **Applies to:** all CLIs and shared libraries. **Since:** cli-base 0.41.0. **Rulings:** none.
130
134
 
131
135
  ### WC-REL-12 · Publish only after full validation and the release security checks pass
@@ -181,12 +185,18 @@ on the [CI](ci.md) page.
181
185
 
182
186
  ### WC-REL-16 · The package ships only the files it names
183
187
 
188
+ A CLI's `files` holds only what the installed CLI runs from or shows its user: `dist`, the agent skill (`skills`),
189
+ `README.md`, `LICENSE`, and files its code reads or runs after install, such as `scenarios` for `guide`, an `install`
190
+ script, third-party notices and licenses. `CHANGELOG.md` may ship too. It never holds `src/`, tests, fakes or
191
+ fixtures, `scripts/`, `.github/`, `bin/release`, `config/`, `lint/`, `contracts/`, `docs/dev/` or `template.json`.
192
+
184
193
  - **Why:** a stray file in the package can leak local data and grows every install.
185
194
  - **Enforced by:** `node-ci.yml:check` · `<app>: pnpm package:check` · `whatsapp-cli: pnpm release:check`.
186
195
  - **Example:** `package.json` `files` lists what ships. The CLI's `pnpm release:check` runs `packContents` from
187
196
  `@wirecat/cli-base/release` and fails on any other path in `npm pack --dry-run`.
188
- - **Exceptions:** none. Each CLI's `package:check` runs `packContents`; tg and max as
189
- `release-check.ts --package-only`.
197
+ - **Exceptions:** cli-template's own package ships the skeleton's sources and configs, since `new` copies them; the
198
+ `files` list `new` writes into a CLI follows this rule. Each CLI's `package:check` runs `packContents`; tg and max
199
+ as `release-check.ts --package-only`.
190
200
  - **Applies to:** all CLIs. **Since:** cli-base 0.41.0. **Rulings:** none.
191
201
 
192
202
  ## Sources
@@ -67,8 +67,9 @@ name. Any other top-level key is written as `[not allowed]`. A key that names co
67
67
  ### WC-SECR-4 · Secrets come from the environment, then the OS keyring, then a private file
68
68
 
69
69
  cli-base's `Credentials` reads the environment variable first (for CI), then the OS keyring, then a file with mode
70
- `0600`. The keyring service is the command's name. When the config directory comes from the environment, the service
71
- name is scoped to that directory (`isolated: true`).
70
+ `0600`. The keyring service is the CLI's app name, `appName` in its identity (`max-cli`, `gcal-cli`, `cli-memo`), not
71
+ the command word people type (`max`, `gcal`). When the config directory comes from the environment, the service name
72
+ is scoped to that directory (`isolated: true`).
72
73
 
73
74
  - **Why:** the keyring is the safest store on the computer, and a throwaway config directory must not overwrite the
74
75
  owner's real keyring entry.
@@ -274,7 +275,7 @@ general words.
274
275
  asks for it on that job only. The `zizmor` scan in `release-checks.yml` reports high findings at release, but does
275
276
  not fail on them.
276
277
  - **Exceptions:** none.
277
- - **Applies to:** the ten repositories: the six CLIs, cli-base, cli-core, cli-testing, cli-docs and community; and
278
+ - **Applies to:** the WireCat repositories: every CLI, cli-base, cli-core, cli-testing, cli-docs and community; and
278
279
  cli-template.
279
280
  **Since:** cli-base 0.41.0. **Rulings:** none.
280
281
 
@@ -30,7 +30,7 @@ Related pages: which account a read covers, and how a read across accounts is as
30
30
  `%LOCALAPPDATA%\WireCat\Data\` on Windows). Rows are keyed by provider and account. `storePath` is the only code
31
31
  that reads `MESSAGING_STORE` and `WIRECAT_STATE_DIR`.
32
32
  - **Exceptions:** none. Older documents that name `messages.db` describe a store that is no longer used.
33
- - **Applies to:** CLIs that keep local data through cli-core (tg, max, wa, memo, drive, zoom). **Since:** cli-base 0.41.0.
33
+ - **Applies to:** CLIs that keep local data through cli-core (tg, max, wa, memo, drive, zoom, gcal). **Since:** cli-base 0.41.0.
34
34
  **Rulings:** NEED-383.
35
35
 
36
36
  ### WC-STORE-2 · Reach the data through its area, and add a new kind of record as a new area
@@ -44,7 +44,7 @@ and which run after merge is in [CI](ci.md).
44
44
  file, listed after the shared one, adds only what is its own, such as a default profile.
45
45
  - **Exceptions:** keep coverage reports and debug traces outside the sandbox, with bounded retention. Never clean
46
46
  another session's scratch directory as test teardown.
47
- - **Applies to:** all CLIs and the shared packages. cli-base, cli-core, the six CLIs and cli-template load the shared
47
+ - **Applies to:** all CLIs and the shared packages. cli-base, cli-core, every CLI and cli-template load the shared
48
48
  setup first in `setupFiles`; cli-testing does not use it yet. **Since:** cli-base 0.41.0. **Rulings:** none.
49
49
 
50
50
  ### WC-TEST-2 · No test opens a real credential store
@@ -94,7 +94,9 @@ and which run after merge is in [CI](ci.md).
94
94
  - **Enforced by:** review only.
95
95
  - **Example:** waits go through an injected `SleepLike`, and `fakeClock()` from `@wirecat/cli-base/testing` records
96
96
  them without waiting. A test harness passes `sleep: async () => {}`. `pnpm test:slow` lists the 20 slowest tests
97
- and the 10 slowest files.
97
+ and the 10 slowest files. A test may wait for a local process or server it started, for example polling its
98
+ status with `vi.waitFor` and a timeout shorter than the test's own; that waits for an event, not for time. A
99
+ fixed sleep or `setTimeout` is still a wait for real time.
98
100
  - **Exceptions:** none. A new wait in the code gets a seam, never a longer test timeout.
99
101
  - **Applies to:** all CLIs and the shared packages. **Since:** cli-base 0.41.0. **Rulings:** dev-process:4.
100
102
 
@@ -171,7 +173,11 @@ and which run after merge is in [CI](ci.md).
171
173
  `coverage/argv.jsonl`. `pnpm test:matrix` turns that into `docs/dev/test-matrix.md` and fails on a command or
172
174
  option with neither a test nor a reason. A reason names the live scenario that covers it. A test that calls a
173
175
  function directly does not count.
174
- - **Exceptions:** none.
176
+ - **Exceptions:** commands generated from a service's API description, such as drive's and gcal's
177
+ `api <method>` from a Google Discovery snapshot, share one reason for the whole group (`api *` and its options).
178
+ It names two tests: one that checks every generated command's options against the snapshot, and one that drives a
179
+ generated command through `run()` into the executor every generated command shares. A hand-written command in the
180
+ same CLI still needs its own test or live scenario.
175
181
  - **Applies to:** all CLIs. memo's check fails only on a stale page, not yet on an option with no test.
176
182
  **Since:** cli-base 0.41.0. **Rulings:** NEED-359.
177
183
 
@@ -15,22 +15,23 @@ The [community standards](https://github.com/WireCatLabs/community/blob/main/sta
15
15
  one source of the presets. Each repository holds a copy of them in `config/wirecat/`, installed by
16
16
  `adopt-standards.py`.
17
17
 
18
- "The ten repositories" on this page means the six CLIs (tg, max, memo, drive, zoom, wa), cli-base, cli-core,
19
- cli-testing, cli-docs, plus community itself. cli-template follows every rule here as a CLI does
18
+ "The WireCat repositories" on this page means every WireCat CLI (today tg, max, memo, drive, zoom, wa and gcal; a
19
+ CLI made with `npx @wirecat/cli-template new` counts from its first commit), cli-base, cli-core, cli-testing, cli-docs,
20
+ plus community itself. cli-template follows every rule here as a CLI does
20
21
  ([New CLI](new-cli.md#the-template-repository-itself)).
21
22
 
22
23
  ## Rules
23
24
 
24
25
  ### WC-TOOL-1 · Install the shared presets with `adopt-standards.py`, and never edit the copies
25
26
 
26
- - **Why:** one reviewed set of presets keeps ten repositories alike; an edited copy drifts without anyone seeing it.
27
+ - **Why:** one reviewed set of presets keeps the repositories alike; an edited copy drifts without anyone seeing it.
27
28
  - **Enforced by:** `pnpm standards:check` · `standards.yml:standards`.
28
29
  - **Example:** `python3 scripts/adopt-standards.py /path/to/project` from a community checkout, then commit
29
30
  `config/wirecat/` and the lockfile. `standards:check` compares each file in `config/wirecat/` with the hash in
30
31
  `config/wirecat/manifest.json`.
31
32
  - **Exceptions:** none. A general improvement goes to community and comes back through a new adoption. A
32
33
  project-only setting goes in the root config (WC-TOOL-2).
33
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
34
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
34
35
 
35
36
  ### WC-TOOL-2 · Make each root config extend its copy in `config/wirecat/`
36
37
 
@@ -41,7 +42,7 @@ cli-testing, cli-docs, plus community itself. cli-template follows every rule he
41
42
  `lefthook.yml` extends `config/wirecat/lefthook.yml`.
42
43
  - **Exceptions:** do not extend `@wirecat/cli-base/biome` or `@wirecat/cli-base/lefthook.yml`. No repository uses
43
44
  them, and `standards:check` accepts only the paths above.
44
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
45
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
45
46
 
46
47
  ### WC-TOOL-3 · Pin the tool versions that `toolchain.json` names
47
48
 
@@ -50,7 +51,7 @@ cli-testing, cli-docs, plus community itself. cli-template follows every rule he
50
51
  - **Example:** `package.json` has `"packageManager": "pnpm@11.20.0"` and exact `devDependencies` for
51
52
  `@biomejs/biome`, `cspell` and its three dictionaries, `lefthook` and `markdownlint-cli2`, as in the manifest.
52
53
  - **Exceptions:** none.
53
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
54
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
54
55
 
55
56
  ### WC-TOOL-4 · Extend the shared TypeScript config, and do not loosen it
56
57
 
@@ -101,7 +102,7 @@ cli-testing, cli-docs, plus community itself. cli-template follows every rule he
101
102
  - **Example:** the shared preset sets 2 spaces, double quotes, semicolons only where needed, trailing commas, arrow
102
103
  parentheses always and 120 columns. Run `pnpm lint:fix` to apply them.
103
104
  - **Exceptions:** none.
104
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
105
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
105
106
 
106
107
  ### WC-TOOL-8 · Keep the shared Biome rules at error
107
108
 
@@ -111,7 +112,7 @@ cli-testing, cli-docs, plus community itself. cli-template follows every rule he
111
112
  noUnusedImports, noUnusedVariables and noExplicitAny.
112
113
  - **Exceptions:** a repository may add rules or raise a level. It may not turn a shared rule off (index, "Which rule
113
114
  wins").
114
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
115
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
115
116
 
116
117
  ### WC-TOOL-9 · Write to the console only with `console.error`, except in `scripts/`
117
118
 
@@ -122,7 +123,7 @@ cli-testing, cli-docs, plus community itself. cli-template follows every rule he
122
123
  - **Exceptions:** files under `scripts/` may print, because they are development tools. A shared package prints
123
124
  nothing at all, not even with `console.error`
124
125
  ([WC-ARCH-19](architecture.md#wc-arch-19--shared-packages-print-nothing-and-log-nothing-on-their-own)).
125
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
126
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
126
127
 
127
128
  ### WC-TOOL-10 · Keep the secret lint on, and suppress a finding only with its reason
128
129
 
@@ -132,7 +133,7 @@ cli-testing, cli-docs, plus community itself. cli-template follows every rule he
132
133
  `// biome-ignore lint/security/noSecrets: Crockford base32 alphabet, not a key`.
133
134
  - **Exceptions:** the rule is off in test files, `test/`, `tests/`, `__tests__/`, `fixtures/` and `generated/`,
134
135
  because those hold fake credentials or cannot keep a suppression comment.
135
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
136
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
136
137
 
137
138
  ### WC-TOOL-11 · Keep the three grit plugins that block unsafe calls
138
139
 
@@ -149,7 +150,7 @@ no-unbounded-spread ([WC-TOOL-12](#wc-tool-12--do-not-spread-a-list-of-user-data
149
150
  concatenation. no-new-function reports `new Function(...)` and `Function(...)`.
150
151
  - **Exceptions:** a reviewed site may keep a `biome-ignore` comment with the reason, for example a Windows `.cmd` shim
151
152
  with fixed arguments. The plugins read syntax, not data flow, so review and CodeQL at release cover the rest.
152
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
153
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
153
154
 
154
155
  ### WC-TOOL-12 · Do not spread a list of user data into call arguments
155
156
 
@@ -159,7 +160,7 @@ no-unbounded-spread ([WC-TOOL-12](#wc-tool-12--do-not-spread-a-list-of-user-data
159
160
  plugin reports `.push(...x)`, `Math.max(...x)` and `Math.min(...x)` as a warning.
160
161
  - **Exceptions:** a spread over a list that is small by construction may stay. The plugin skips tests, `testing/`,
161
162
  `scripts/`, `bench/` and `performance/`.
162
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
163
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
163
164
 
164
165
  ### WC-TOOL-13 · Cap every file at 1,000 lines with Biome
165
166
 
@@ -172,7 +173,7 @@ no-unbounded-spread ([WC-TOOL-12](#wc-tool-12--do-not-spread-a-list-of-user-data
172
173
  `src/telegram/adapter.ts`; four files in cli-core). A smaller cap is allowed: zoom uses 500. cli-docs turns it off for
173
174
  stylesheets. Biome reads only JavaScript and TypeScript, so the cap does not cover
174
175
  code in another language, such as wa's Go engine; the review signals of WC-LAY-7 still apply to it.
175
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
176
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
176
177
 
177
178
  ### WC-TOOL-14 · Turn on the import cycle rule
178
179
 
@@ -180,7 +181,7 @@ no-unbounded-spread ([WC-TOOL-12](#wc-tool-12--do-not-spread-a-list-of-user-data
180
181
  - **Enforced by:** `pnpm lint` · `standards.yml:standards` (the shared Biome base, like WC-TOOL-8).
181
182
  - **Example:** the shared Biome base sets the suspicious rule noImportCycles to error.
182
183
  - **Exceptions:** none.
183
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
184
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
184
185
 
185
186
  ### WC-TOOL-15 · Declare layer boundaries as restricted imports in `biome.json`
186
187
 
@@ -218,7 +219,7 @@ no-unbounded-spread ([WC-TOOL-12](#wc-tool-12--do-not-spread-a-list-of-user-data
218
219
  - **Exceptions:** a general word goes into the community word list, not into each project. cli-base checks
219
220
  `README.md` and `docs/standards/`; cli-docs its site pages in `content/docs/`; community every Markdown file it
220
221
  publishes. cli-core, zoom and cli-testing check only `README.md` yet.
221
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
222
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
222
223
 
223
224
  ### WC-TOOL-18 · Lint Markdown with `markdownlint-cli2` and the shared preset
224
225
 
@@ -227,7 +228,7 @@ no-unbounded-spread ([WC-TOOL-12](#wc-tool-12--do-not-spread-a-list-of-user-data
227
228
  - **Example:** the preset turns on only: no tabs (MD010), at most two blank lines in a row (MD012), a language on
228
229
  every fenced code block (MD040) and no empty links (MD042). `.markdownlint-cli2.jsonc` lists the files to check.
229
230
  - **Exceptions:** a repository may turn on more rules in its root config.
230
- - **Applies to:** the ten repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
231
+ - **Applies to:** the WireCat repositories. **Since:** cli-base 0.41.0. **Rulings:** none.
231
232
 
232
233
  ### WC-TOOL-19 · Check user pages with `rumdl` and the shared `rumdl.toml`
233
234
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-base",
3
- "version": "0.63.0",
3
+ "version": "0.64.0",
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",
@@ -135,6 +135,7 @@
135
135
  "@vitest/coverage-v8": "^5.0.5",
136
136
  "commander": "^15.0.0",
137
137
  "cspell": "10.4.0",
138
+ "esbuild": "0.28.2",
138
139
  "lefthook": "2.2.2",
139
140
  "markdownlint-cli2": "0.24.0",
140
141
  "typescript": "^7.0.2",
@@ -146,12 +147,16 @@
146
147
  },
147
148
  "peerDependencies": {
148
149
  "commander": ">=15",
150
+ "esbuild": "^0.28.0",
149
151
  "vitest": ">=5"
150
152
  },
151
153
  "peerDependenciesMeta": {
152
154
  "commander": {
153
155
  "optional": true
154
156
  },
157
+ "esbuild": {
158
+ "optional": true
159
+ },
155
160
  "vitest": {
156
161
  "optional": true
157
162
  }