@wirecat/zoom-cli 0.5.1 → 0.7.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 (81) hide show
  1. package/README.md +306 -370
  2. package/dist/api.d.ts +2 -2
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +1 -1
  5. package/dist/api.js.map +1 -1
  6. package/dist/archive-commands.js +1 -1
  7. package/dist/archive-commands.js.map +1 -1
  8. package/dist/archive-import.d.ts +1 -1
  9. package/dist/archive-import.d.ts.map +1 -1
  10. package/dist/archive-import.js.map +1 -1
  11. package/dist/archive-transcripts.d.ts +1 -1
  12. package/dist/archive-transcripts.d.ts.map +1 -1
  13. package/dist/archive-transcripts.js +1 -1
  14. package/dist/archive-transcripts.js.map +1 -1
  15. package/dist/bin/zm.js +4 -3
  16. package/dist/bin/zm.js.map +1 -1
  17. package/dist/files.d.ts +2 -2
  18. package/dist/files.d.ts.map +1 -1
  19. package/dist/files.js +1 -1
  20. package/dist/files.js.map +1 -1
  21. package/dist/folders.d.ts +9 -0
  22. package/dist/folders.d.ts.map +1 -0
  23. package/dist/folders.js +37 -0
  24. package/dist/folders.js.map +1 -0
  25. package/dist/local-transcription.d.ts +1 -1
  26. package/dist/local-transcription.d.ts.map +1 -1
  27. package/dist/local-transcription.js +1 -1
  28. package/dist/local-transcription.js.map +1 -1
  29. package/dist/mcp-server.js +1 -1
  30. package/dist/mcp-server.js.map +1 -1
  31. package/dist/meeting-integration-commands.js +1 -1
  32. package/dist/meeting-integration-commands.js.map +1 -1
  33. package/dist/meeting-integration.d.ts +1 -1
  34. package/dist/meeting-integration.d.ts.map +1 -1
  35. package/dist/meeting-integration.js.map +1 -1
  36. package/dist/meeting-search-commands.d.ts +1 -1
  37. package/dist/meeting-search-commands.d.ts.map +1 -1
  38. package/dist/program.d.ts +1 -1
  39. package/dist/program.d.ts.map +1 -1
  40. package/dist/program.js +2 -2
  41. package/dist/program.js.map +1 -1
  42. package/dist/recording-archive.d.ts.map +1 -1
  43. package/dist/recording-archive.js +1 -1
  44. package/dist/recording-archive.js.map +1 -1
  45. package/dist/recording-partial-store.d.ts +1 -1
  46. package/dist/recording-partial-store.d.ts.map +1 -1
  47. package/dist/recording-promotion-store.d.ts +1 -1
  48. package/dist/recording-promotion-store.d.ts.map +1 -1
  49. package/dist/recording-promotion-store.js +1 -1
  50. package/dist/recording-promotion-store.js.map +1 -1
  51. package/dist/recording-schedule-commands.js +1 -1
  52. package/dist/recording-schedule-commands.js.map +1 -1
  53. package/dist/recording-schedule.d.ts +1 -1
  54. package/dist/recording-schedule.d.ts.map +1 -1
  55. package/dist/recording-schedule.js +1 -1
  56. package/dist/recording-schedule.js.map +1 -1
  57. package/dist/recording-sync-store.d.ts +1 -1
  58. package/dist/recording-sync-store.d.ts.map +1 -1
  59. package/dist/recording-sync-store.js +1 -1
  60. package/dist/recording-sync-store.js.map +1 -1
  61. package/dist/recording-sync.d.ts +1 -1
  62. package/dist/recording-sync.d.ts.map +1 -1
  63. package/dist/recording-sync.js +1 -1
  64. package/dist/recording-sync.js.map +1 -1
  65. package/dist/recordings.d.ts +1 -1
  66. package/dist/recordings.d.ts.map +1 -1
  67. package/dist/recordings.js.map +1 -1
  68. package/dist/remote-meetings.d.ts +8 -8
  69. package/dist/remote-meetings.d.ts.map +1 -1
  70. package/dist/remote-meetings.js +1 -1
  71. package/dist/remote-meetings.js.map +1 -1
  72. package/dist/store-connection.d.ts +1 -1
  73. package/dist/store-connection.d.ts.map +1 -1
  74. package/dist/store-connection.js +1 -1
  75. package/dist/store-connection.js.map +1 -1
  76. package/dist/watch-commands.d.ts +1 -1
  77. package/dist/watch-commands.d.ts.map +1 -1
  78. package/dist/watch-commands.js +1 -1
  79. package/dist/watch-commands.js.map +1 -1
  80. package/package.json +3 -4
  81. package/skills/zoom-cli/SKILL.md +1 -1
package/README.md CHANGED
@@ -1,448 +1,356 @@
1
- # @wirecat/zoom-cli
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/WireCatLabs/zoom-cli/main/docs/images/social-preview.png" alt="Zoom meetings and transcripts for your AI agent" width="100%">
3
+ </p>
2
4
 
3
- `zm` logs in to Zoom with your own public OAuth app and reads hosted meetings, participants,
4
- transcripts and AI summaries. It archives available cloud recording video, audio, transcripts and
5
- chat files. Downloaded WebVTT files can also be imported, including transcripts
6
- from meetings you attended. The shared meeting model, ingestion and commands come from
7
- `@wirecat/cli-meetings`.
5
+ # zoom-cli
8
6
 
9
- ## Current availability
7
+ **Zoom meetings and transcripts for your AI agent.** Know the context before the call. Remember the
8
+ commitments after it.
10
9
 
11
- Login, cloud recording downloads and remote meeting commands work independently of the meeting
12
- database. Import, pull, folder watching and meeting reads use the published shared SQLite adapter.
13
- Store connections open lazily and close before successful results are emitted. Meeting data persists
14
- in the shared WireCat database; `MESSAGING_STORE` selects an explicit database path. The shared model,
15
- exports and ingestion loop come from `@wirecat/cli-meetings`.
10
+ `zm` keeps your Zoom meetings, transcripts and AI summaries in a local database and gives them to
11
+ Claude Code, Codex, Gemini CLI or any MCP client. Ask what you discussed with someone last time, or
12
+ what you promised in yesterday's call, and get the answer with a reference to the exact passage.
16
13
 
17
- ## Set up your Zoom app
14
+ [Documentation][docs/index.md] ·
15
+ [Commands][docs/commands.md] ·
16
+ [WireCat](https://wirecat.dev)
18
17
 
19
- Follow [the app guide](docs/zoom-app.md). Use Public Client OAuth and redirect to
20
- `https://wirecat.dev/zoom-callback`. Configure the Public Client ID, then log in:
18
+ [![npm](https://img.shields.io/npm/v/@wirecat/zoom-cli)](https://www.npmjs.com/package/@wirecat/zoom-cli)
19
+ [![Node](https://img.shields.io/node/v/@wirecat/zoom-cli)](https://nodejs.org/)
20
+ [![License: Apache 2.0](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/WireCatLabs/zoom-cli/blob/main/LICENSE)
21
+
22
+ <!-- Demo slot: a 30–45 s recording of the exchange below goes here, as an absolute
23
+ raw.githubusercontent.com URL so it also renders on npmjs.com. -->
24
+
25
+ **Example** — invented people, illustrative output:
26
+
27
+ > **You:** I have a call with Bob Sample at three. What did we agree last time, and what do I owe him?
21
28
 
22
29
  ```sh
23
- zm config set zoom.clientId <public-client-id>
24
- zm login --browser firefox
30
+ zm remote-meetings list --json # your upcoming meetings
31
+ zm meetings people "Bob Sample" --json # him among past participants
32
+ zm meetings search "quote" --since 2026-09-01 --json
33
+ zm meetings evidence meeting:1/42/57/118 --json # the exact passage
25
34
  ```
26
35
 
27
- The callback returns to a listener on your machine. If it cannot, paste the `code=…&state=…`
28
- parameters shown on the callback page. Login checks the state and PKCE verifier, stores tokens
29
- only in the system keyring, and returns login status and actual granted scopes. A missing keyring
30
- is an error; tokens are never written to a config file.
36
+ > **Agent:** You last spoke on 2 October in "Pricing review". You promised Bob a revised quote by
37
+ > Friday (`meeting:1/42/57/118`), and he asked whether the annual plan includes onboarding
38
+ > (`meeting:1/42/57/131`). Neither comes up in a later meeting.
31
39
 
32
- ## Commands
40
+ ## Quick start
33
41
 
34
- | Command | Purpose |
35
- |---|---|
36
- | `config show` | show local configuration |
37
- | `config set <key> <value>` | configure the public client or file source |
38
- | `login [--browser <program>]` | approve access through your browser |
39
- | `commands --json` | discover command arguments, flags and examples |
40
- | `complete -- <words...>` | answer shell completion requests |
41
- | `doctor` | inspect local runtime and public config without login or database access |
42
- | `session status` | inspect saved OAuth state separately from local data profiles |
43
- | `import <folder>` | import downloaded transcripts into the selected local profile |
44
- | `pull [--since <date>]` | fetch occurrences from the configured source |
45
- | `meetings list`, `meetings show <meeting>` | read stored meetings |
46
- | `meetings transcript <meeting>` | read current transcripts |
47
- | `meetings summary <meeting>` | read stored summaries |
48
- | `meetings export <meeting> --format markdown\|vtt` | export stored meeting content |
49
- | `meetings search <query>`, `meetings people <query>` | find stored text or participants |
50
- | `meetings search-page <query>`, `meetings search-index` | bounded hit continuation and explicit keyword indexing |
51
- | `meetings link-event <reference>`, `meetings link-person <reference>` | preview or apply owner-selected stored links |
52
- | `meetings transcribe <meeting> <file> --model <model>` | preview or locally recognize a WAV file into an independent transcript |
53
- | `meetings evidence <reference>`, `meetings context <person>` | read bounded evidence or identity-linked person context |
54
- | `meetings task-proposal <reference> --kind <kind>` | preview a task with meeting provenance |
55
- | `meetings semantic <query> --model <id>` | rank scanned stored vectors with an explicit query model |
56
- | `meetings embeddings --model <id>` | preview local vector generation; `--yes` applies one bounded batch |
57
- | `search all <query>` | search meetings by default, or explicitly selected shared resources |
58
- | `events list` | read stored events |
59
- | `watch [folder] --source api\|files --jsonl` | repeatedly ingest the configured source in the foreground |
60
- | `recordings list`, `recordings show <meeting>` | discover cloud recordings and asset metadata |
61
- | `recordings download <meeting> --destination <directory>` | archive available recording files |
62
- | `recordings sync --from <date> --to <date> --destination <directory> --jsonl` | archive recording history across calendar months |
63
- | `recordings schedule create\|list\|show\|run\|disable` | plan and manage local daily archive jobs |
64
- | `recordings archive inspect\|verify\|locks <directory>` | inspect local manifests, checksums or locks |
65
- | `recordings archive recover <directory>` | preview recovery of stale local locks |
66
- | `recordings archive transcript <directory>` | read verified archived WebVTT cues without a database |
67
- | `recordings archive search <directory> <query>` | search verified archived cue text without a database |
68
- | `recordings archive import <directory>` | verify archived VTT assets and append them to stored occurrences |
69
- | `remote-meetings list\|show\|invitation` | read upcoming Zoom meetings and invitations |
70
- | `remote-meetings create\|update\|cancel` | preview or apply a simple Zoom meeting change |
71
- | `serve --mcp` | serve read-only stored meeting tools over MCP stdio |
72
- | `skill show`, `skill install --for agents` | print or explicitly install the packaged agent guide |
73
-
74
- Use `--json` for one JSON value or `--jsonl` for one item per line. Errors go to stderr. `--no-input`
75
- refuses browser login. `--help` and `--version` work without a configured app or login.
76
- Use `--quiet` to suppress non-error diagnostics. Piped output defaults to JSON; terminal output
77
- uses the shared human-readable renderer. Completion emits its shell protocol unless JSON is requested.
78
-
79
- Browser login requires an input terminal. Piped or JSON login also requires
80
- `--interactive`; CI and terminals without interactive input do not launch a browser. `session status` reads
81
- cached login state without refreshing credentials. Remote verification through `session status
82
- --check` explicitly contacts Zoom and requires the corresponding user-read scope.
83
-
84
- Use `--fields id,title` to select result fields. `--offline` refuses network requests. Finite commands
85
- buffer successful output until resource cleanup completes, with a default output limit of 4 MiB;
86
- `--max-output-bytes 0` removes that limit. `--timeout <milliseconds>` sets a positive whole-command
87
- deadline. Durations also accept units such as `30s`, `5m` and `1h`. Defaults are 30 seconds for reads,
88
- five minutes for login and one hour for recording downloads, sync and archive verification.
89
- Foreground watching and MCP serving have no default deadline. Cancellation waits for active operations
90
- and cleanup; an injected operation that ignores its signal can delay shutdown.
91
-
92
- Config keys: `zoom.clientId`, `account.profile`, `source` (`api` or `files`), `files.folder`,
93
- and `files.timezone`.
94
- Directories follow the platform convention; `ZM_CONFIG_DIR` overrides the configuration directory.
95
- Changing that directory also changes the keyring service used for login.
96
-
97
- ## Select a local profile
98
-
99
- Choose a label for the stored meetings:
42
+ You need Node 22.16+ (22.x) or 24+, a system keyring and **your own Zoom app** — Zoom lets a program
43
+ read your meetings only through an app you register. [Creating it][docs/zoom-app.md]
44
+ takes a few minutes and needs no client secret.
100
45
 
101
46
  ```sh
102
- zm config set account.profile personal
47
+ npm install -g @wirecat/zoom-cli
48
+ zm config set zoom.clientId <public-client-id>
49
+ zm login # approve in your browser; the token goes to the keyring
50
+ zm config set account.profile personal # a label for your stored meetings
51
+ zm pull --lookback-days 7
52
+ zm meetings list
103
53
  ```
104
54
 
105
- Labels contain 1–64 letters, digits, dots, underscores or hyphens and start with a letter or digit.
106
- The label groups local meeting data; OAuth login uses the configured client and keyring entry. Use
107
- separate labels for data you want kept in separate accounts. File import and API pull share the
108
- selected profile. Folder import leaves its pull cursor unchanged; switching pull sources may need
109
- an older explicit `--since` to revisit earlier occurrences.
55
+ Turn on **Allow hosts to retain transcripts** in Zoom's settings first: Zoom returns transcripts only
56
+ for meetings you hosted, and only when they were kept. For meetings you only attended, download the
57
+ transcripts from Zoom and run `zm import <folder>`. Full guide:
58
+ [installation][docs/installation.md].
110
59
 
111
- Import and pull register the selected profile when ingestion begins. Read commands look up an
112
- existing profile and never register an account; import transcripts or pull first if no stored
113
- meetings exist. `MESSAGING_STORE` overrides the shared database path for all these commands and MCP
114
- reads. Metadata, help, configuration and login commands do not open the database.
60
+ More: [installation][docs/installation.md] · [your Zoom app][docs/zoom-app.md] ·
61
+ [Zoom on wirecat.dev][wirecat/en/docs/zoom]
115
62
 
116
- The shared store uses `wirecat.db`. Opening its default path deletes the legacy unencrypted
117
- `messages.db` and its `-wal` and `-shm` sidecars, without migrating them. The legacy files are kept
118
- when `MESSAGING_STORE` is set, an explicit store path is supplied, or another process holds the
119
- legacy database open. A later default-path open retries deletion after that process closes.
63
+ ## What you can do
120
64
 
121
- ## Recover from errors
65
+ **Prepare for a call.** *"I meet Bob Sample tomorrow. What did we talk about last time?"*
66
+ `remote-meetings list` shows upcoming meetings; `meetings people`, `meetings search-page` (word
67
+ search that also matches English, Spanish and Russian word forms) and `meetings context person:<id>`
68
+ bring back past meetings with the same people.
122
69
 
123
- If the browser cannot start, select an installed browser with `--browser firefox`. In an interactive
124
- terminal, you can also paste the callback parameters. Without paste input, a launch failure exits
125
- promptly. A malformed config still allows `--help` and `--version`; config commands report the error.
70
+ **Follow up after it.** *"What did I promise in today's call?"* The agent reads
71
+ `meetings transcript` and `meetings summary`, cites passages with `meetings evidence`, and
72
+ `meetings task-proposal --kind promise` previews a follow-up task tied to that passage.
126
73
 
127
- Missing-scope errors name the required scope. Add it in your Zoom app, then log in again. A network
128
- failure reports a provider error; malformed provider replies report an invalid response. Diagnostic
129
- messages exclude raw provider error text.
74
+ **Keep the whole history.** *"Back up every recording since January."*
75
+ `recordings sync --from 2026-01-01 --to 2026-10-10 --destination ./zoom-archive --jsonl` downloads
76
+ video, audio, transcripts and chat with SHA-256 manifests; `recordings schedule` runs it daily.
130
77
 
131
- Once persistence is connected, use `pull --lookback-days 7` to revisit the last seven days, or an
132
- older explicit `pull --since 2026-10-01` for earlier occurrences whose transcript appeared later. The cursor alone does not guarantee
133
- that late transcripts are revisited. Serialize pulls for the same account to avoid concurrent event
134
- creation. A failed occurrence leaves the cursor unchanged so the next pull can retry it.
78
+ More: [the local archive][docs/archive.md] · [search and evidence][docs/search.md] ·
79
+ [Zoom on wirecat.dev][wirecat/en/docs/zoom]
135
80
 
136
- ## Downloaded transcripts
81
+ ## Built for AI agents
137
82
 
138
- The files source reads ordinary `.vtt` files directly inside a folder. Names follow the existing
139
- exporter's `YYYY-MM-DD_HHMM_topic-slug.vtt` format. Occurrence ids derive from the timestamp and
140
- normalized topic; files carry no Zoom occurrence UUID. Participants remain unknown, and speaker
141
- names are kept without guessing an identity.
83
+ - **Command line + skill.** `zm skill install` adds the packaged guide for Claude Code, Codex and
84
+ Gemini CLI. Every command speaks `--json` or `--jsonl`, and `zm commands --json` describes them all.
85
+ - **MCP.** `zm serve --mcp` is a read-only stdio server for Claude Desktop, Cursor and other MCP
86
+ clients: meetings, transcripts, summaries, exports and search.
87
+ [Connecting a client][docs/mcp.md].
142
88
 
143
- Cloud archive assets use hashed filenames and retain their identity in manifests. Use a separate
144
- command to import these assets into the selected local profile:
89
+ Your agent. Your meetings. Your rules.
145
90
 
146
- ```sh
147
- zm recordings archive import ./zoom-archive --offline --jsonl
148
- ```
91
+ More: [MCP and skills][docs/mcp.md] · [connect your AI agent][wirecat/en/docs/agents]
149
92
 
150
- Import verifies every selected VTT asset before opening the store. The default limits are 8 MiB
151
- per file and 64 MiB in total; use `--max-bytes` and `--max-total-bytes` to change them. Select an
152
- occurrence with `--uuid`, or assets with comma-separated `--file-ids`. Each occurrence is appended
153
- atomically by its raw Zoom UUID, preserving other transcripts, summaries, participants and the
154
- pull cursor. Corrected content retains earlier revisions; identical asset hashes are idempotent.
155
- An occurrence with no known start time can receive transcripts only if it already exists. Receipts
156
- report acknowledged or unavailable occurrences. When the exact receipt capability is available,
157
- they also report meeting creation and inserted, replayed and superseded transcript counts from the
158
- same transaction. Older adapters keep the acknowledgement without guessed counts.
159
- Earlier acknowledged occurrences can remain committed if a later append fails.
93
+ ## Why zm
160
94
 
161
- Read or search archived transcripts directly:
95
+ - **Context, not one transcript.** Every meeting you hosted, transcripts you imported and recordings
96
+ you archived, searchable together.
97
+ - **Local-first.** Meetings live in a SQLite database on your machine. Archived transcripts can be read
98
+ and searched offline, without login.
99
+ - **Every answer has a source.** References such as `meeting:1/42/57/118` point to one passage of one
100
+ transcript revision, and corrected transcripts keep their history.
101
+ - **Made for agents.** JSON output, bounded reads with explicit completeness, a skill and an MCP server.
102
+ - **Safe by default.** Your own Zoom app, tokens only in the keyring, a read-only MCP server, and every
103
+ change to Zoom previewed until you add `--yes`.
162
104
 
163
- ```sh
164
- zm recordings archive transcript ./zoom-archive --offline --json
165
- zm recordings archive search ./zoom-archive "example plan" --limit 100 --offline --json
166
- ```
105
+ More: [security][docs/security.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
167
106
 
168
- Both commands verify each WebVTT file they read against manifest sizes and SHA-256 digests before
169
- returning parsed cues. Search stops after finding one match beyond its limit; later files remain
170
- unread. They need no login, configuration or database. Use `--uuid` or comma-separated
171
- `--file-ids` to select assets, and `--max-bytes` to change the default 8 MiB per-file read limit.
172
- Search matches literal cue text after Unicode normalization and lowercasing; speaker names are
173
- not searched. Its default limit is 100, with a maximum of 1000. `hasMore` means another matching cue
174
- exists; increase the limit or narrow the occurrence, file or query selection to read more.
175
- Results have no continuation cursor. Finite output remains
176
- bounded by `--max-output-bytes`, and a failed verification emits no successful result.
177
-
178
- For repeated API ingestion, use `zm watch --source api --lookback-days 7 --jsonl`. A folder argument
179
- selects file watching; otherwise the configured source applies. File watching can use `files.folder`.
180
- API watching accepts `--since` and revisits zero through 31 days, and requires online access.
181
- `--since` sets the initial lower bound; after a successful cursor write, later cycles use the cursor
182
- with the selected overlap. Failed cycles retain the initial bound until a cursor write succeeds.
183
- The overlap also subtracts from the initial `--since` bound.
184
- `--interval` controls the delay between completed cycles. Profile, source and file settings are
185
- captured, along with the OAuth client, before watching begins; changing configuration requires restarting the watch. Cycles never
186
- overlap and close their store connection before emitting a receipt. Stop with Ctrl-C.
187
-
188
- File times default to UTC. Set `files.timezone` to the IANA zone used when the filenames were
189
- created, for example `Europe/Madrid`. Ambiguous or nonexistent daylight-saving times are refused. Conflicting contents for the same
190
- normalized filename key are an error; correct the conflicting files before retrying. File discovery
191
- fails explicitly on invalid names rather than silently importing a partial folder.
107
+ ## What works today, and what does not yet
192
108
 
193
- ## Archive cloud recordings
109
+ `zm` is at version 0.x; commands may still change. Today it reads hosted meetings, participants,
110
+ transcripts and AI summaries (Pro plan or higher) through Zoom's official API, imports downloaded
111
+ WebVTT files, archives cloud recordings, transcribes local audio with an installed speech model,
112
+ links meetings to events and people, and creates, changes or cancels simple meetings.
194
113
 
195
- Find an occurrence and download its available files to an explicit destination:
114
+ - **It does not find commitments on its own.** Your agent finds them in transcripts;
115
+ `task-proposal` only previews a task and creates nothing.
116
+ - **People are linked by hand.** `zm` never guesses a person from a speaker name; person context
117
+ covers participants already linked to a person, for example with `meetings link-person`.
118
+ - **Local transcription takes PCM16 WAV only** (16 or 48 kHz) and an already installed speech model;
119
+ video files are not decoded, and speakers stay unknown.
120
+ - **Attended meetings need a manual download** from your Zoom portal, then `zm import`.
121
+ - **A company-managed Zoom account** may need an admin to approve your app.
122
+ - **Daily archive jobs install only on Linux.** Other platforms can preview them.
123
+ - **Zoom only, for now.** Google Meet and Microsoft Teams are
124
+ [on the roadmap][gh/cli-meetings/blob/main/docs/dev/roadmap.md].
196
125
 
197
- ```sh
198
- zm recordings list --from 2026-10-01 --to 2026-10-10 --json
199
- zm recordings show example-occurrence --json
200
- zm recordings download example-occurrence --destination ./zoom-archive --json
201
- zm recordings archive verify ./zoom-archive --offline --json
202
- ```
126
+ More: [what is planned][gh/cli-meetings/blob/main/docs/dev/roadmap.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
203
127
 
204
- For recording history across months, use:
128
+ ## Commands by task
205
129
 
206
- ```sh
207
- zm recordings sync --from 2026-01-01 --to 2026-10-10 --destination ./zoom-archive --jsonl
208
- ```
130
+ | Task | Commands |
131
+ |---|---|
132
+ | Set up and log in | `config show`, `config set <key> <value>`, `login [--browser <program>]`, `session status [--check]`, `doctor` |
133
+ | Bring meetings in | `pull [--since <date>] [--lookback-days <days>]`, `import <folder>`, `watch [folder] --source api\|files --jsonl` |
134
+ | Read stored meetings | `meetings list`, `meetings show <meeting>`, `meetings transcript <meeting>`, `meetings summary <meeting>`, `meetings export <meeting> --format markdown\|vtt`, `events list` |
135
+ | Search | `meetings search-page <query>`, `meetings search-index`, `meetings search <query>`, `meetings people <query>`, `search all <query>` |
136
+ | Evidence and people | `meetings evidence <reference>`, `meetings context <person>`, `meetings link-person <reference>`, `meetings link-event <reference>`, `meetings task-proposal <reference> --kind <kind>` |
137
+ | Search by meaning | `meetings embeddings --model <id>`, `meetings semantic <query> --model <id>` |
138
+ | Local transcription | `meetings transcribe <meeting> <file> --model <model>` |
139
+ | Cloud recordings | `recordings list`, `recordings show <meeting>`, `recordings download <meeting> --destination <directory>`, `recordings sync --from <date> --to <date> --destination <directory> --jsonl`, `recordings schedule create\|list\|show\|run\|disable` |
140
+ | Local archive | `recordings archive inspect\|verify\|locks\|recover <directory>`, `recordings archive transcript\|search\|import <directory>` |
141
+ | Zoom meetings | `remote-meetings list\|show\|invitation`, `remote-meetings create\|update\|cancel` |
142
+ | Agents | `serve --mcp`, `skill show`, `skill install [--for claude\|agents\|all]`, `commands --json`, `complete -- <words...>` |
209
143
 
210
- Sync accepts explicit ordered dates spanning at most ten calendar years. It splits them into monthly
211
- requests, deduplicates occurrence UUIDs and downloads serially. Each JSONL receipt describes one
212
- completed occurrence; earlier receipts and completed files remain if a later request fails. Repeat the
213
- same range or an overlapping recent range to discover new assets. With a selected local profile,
214
- sync saves durable progress and retains pending recordings. Use `--recheck-from YYYY-MM-DD` to
215
- rediscover recent dates for late or changed assets, and `--checkpoint` to select its checkpoint file.
216
- `--max-pages` and `--max-entries` bound discovery. Headless sync requires `--jsonl`.
217
-
218
- Checkpoints acknowledge earlier successful archives; they do not check current disk integrity or
219
- prove that all provider recordings were available. Run `recordings archive verify` to check local
220
- files. Use `--no-resume` to rescan the full requested range without durable progress.
221
-
222
- Recording lists accept an ordered date range of at most 31 days. Downloads stream to disk rather
223
- than loading a video into memory. The default per-file limit is 20 GiB; change it with `--max-bytes`.
224
- Use `--file-ids` to select comma-separated asset ids. Only completed, downloadable assets are saved;
225
- the receipt reports unavailable assets separately. Zoom permissions, recording retention and account
226
- features determine what can be downloaded. Assets from a meeting you attended are not necessarily
227
- available through your cloud recording API.
228
-
229
- Each occurrence has a manifest containing metadata, file sizes and SHA-256 checksums. Signed
230
- download URLs and OAuth tokens are excluded. Repeating a download verifies existing manifest files
231
- and skips matching assets. Existing files are never overwritten; a mismatch requires a new destination.
232
- With a selected local profile, interrupted downloads retain verified partial bytes and resume only
233
- when a strong validator and the returned range agree. Changed representations restart safely.
234
- Explicit `--resume` requires a profile; `--no-resume` and downloads without a profile use ephemeral
235
- partials. Completed manifest entries remain available if a later transfer fails.
236
-
237
- Archive commands inspect and verify local data without logging in or opening a database. Concurrent
238
- writers to the same destination are refused. After a process crash, inspect `recordings archive locks`
239
- and preview `recordings archive recover`. Add `--yes` to remove recognized locks owned by a dead process
240
- on this machine; active, foreign and unrecognized locks are preserved. Recovery removes stale lock
241
- markers only. Download continuation can recover a completed promotion only when its owned journal,
242
- verified partial and final file all match; unrelated untracked files remain protected.
243
-
244
- To plan a daily backup, choose an absolute destination and timer timezone:
144
+ Zoom meeting changes, links, search indexing, transcription, schedules, embeddings and lock recovery
145
+ preview by default and run once with `--yes`; `--dry-run` always keeps the preview.
245
146
 
246
- ```sh
247
- zm recordings schedule create --name daily --destination /home/AliceExample/zoom-archive --from 2026-01-01 --at 03:15 --timezone Europe/Madrid --json
248
- zm recordings schedule list --offline --json
249
- zm recordings schedule run <schedule-id> --jsonl
250
- zm recordings schedule disable <schedule-id> --yes --json
251
- ```
147
+ More: [usage][docs/usage.md] · [every command and option][docs/commands.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
252
148
 
253
- Creation previews by default. Add `--yes` to install a Linux systemd user timer; `--dry-run`
254
- overrides it. Automatic installation currently supports Linux only. The timer follows its IANA
255
- timezone, while recording discovery uses UTC dates and defaults to seven days of recent rechecks.
256
- Systemd user services must be available for the job to run; previews also work on other platforms.
257
- Jobs capture the local profile, public client ID, destination and runtime/config paths, without
258
- credentials. Running a saved job requires its captured profile and client to remain selected.
259
- Saved status describes the last acknowledged operation; list/show do not query live timer state.
260
- Disabling stops the timer and preserves job definitions and archived files.
149
+ ## Your Zoom app and login
261
150
 
262
- ## Link meetings to shared context
151
+ `zm` reads your meetings through Zoom's official API, as you, so it uses **your own Zoom app** with
152
+ Public Client OAuth. Create it once from the supplied manifest: it asks for read-only access to
153
+ meetings, participants, transcripts and AI summaries. Recording archives and meeting management need
154
+ extra scopes, which you add only if you want those features. The app has no client secret.
263
155
 
264
- Create an independent local transcript from an audio file for an existing stored meeting:
156
+ `zm login` opens Zoom's consent page. Zoom redirects to the static page
157
+ `https://wirecat.dev/zoom-callback`, which passes the answer to a listener on your machine; if it
158
+ cannot, paste the `code=…&state=…` parameters it shows. Login checks the state and PKCE verifier and
159
+ stores tokens only in the system keyring. Browser login needs an interactive terminal; piped or JSON
160
+ login also needs `--interactive`. `zm session status` reads the cached state without refreshing it;
161
+ `--check` asks Zoom.
265
162
 
266
- ```sh
267
- zm meetings transcribe 1 ./AliceExample.wav --model parakeet-v3 --json
268
- zm meetings transcribe 1 ./AliceExample.wav --model parakeet-v3 --yes --json
269
- ```
163
+ More: [your Zoom app][docs/zoom-app.md] · [login and sessions][docs/sessions.md] ·
164
+ [Zoom on wirecat.dev][wirecat/en/docs/zoom]
270
165
 
271
- Preview verifies the input and describes the chosen model without loading it. `--yes` recognizes
272
- with an already installed local model and atomically appends the completed transcript; `--dry-run`
273
- overrides it. No model is automatically installed. Input currently accepts PCM16 WAV, mono or stereo,
274
- at 16 or 48 kHz. `--models-dir` selects an absolute installed model directory. Media, duration,
275
- segment count and transcript text have explicit bounds through `--max-bytes`, `--max-duration`,
276
- `--max-segments` and `--max-text-bytes`. Recognition uses fixed windows of up to 30 seconds, so
277
- timestamps describe those windows. Speakers remain unknown. Provider transcripts and historical
278
- revisions are preserved; the applied receipt gives transaction counts and provenance.
166
+ ## Profiles and the local store
279
167
 
280
- Stored meeting references use `meeting:<accountId>/<meetingId>`. A retained transcript appends its
281
- revision id, and a cue appends its position. Event and person linking accept root references:
168
+ `account.profile` is a label (1–64 letters, digits, dots, underscores or hyphens) that groups the
169
+ meetings you store; use separate labels for data you want kept apart. Import and pull register the
170
+ profile; read commands never do, so pull or import first.
282
171
 
283
- ```sh
284
- zm meetings link-event meeting:1/1 --event-id 1 --expected-event-id none --json
285
- zm meetings link-event meeting:1/1 --event-id 1 --expected-event-id none --yes --json
286
- zm meetings link-person meeting:1/1 --participant-id 1 --person 1 --expected-person none --yes --json
287
- ```
172
+ Meetings live in the shared WireCat database `wirecat.db`, next to data from other WireCat tools.
173
+ `MESSAGING_STORE` selects another path. Opening the default path deletes the legacy unencrypted
174
+ `messages.db` and its sidecars without migrating them, unless another path is set or another process
175
+ holds it open. Metadata, help, configuration and login never open the database.
288
176
 
289
- These local changes preview by default; `--yes` applies once and `--dry-run` overrides it. Expected
290
- link options reject a stale decision. Use `--event-id none` to unlink an event. Person linking moves
291
- only the selected participant's identity; it never guesses a person from a speaker name. Target
292
- people must have authorized account observations. Explicit `--target-accounts <ids>` adds account
293
- ids for that lookup. Profile labels group local data and do not authenticate a remote identity.
177
+ More: [profiles][docs/sessions.md#select-a-local-profile] ·
178
+ [where meetings are stored][docs/archive.md#where-meetings-are-stored] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
294
179
 
295
- Use [memo](https://github.com/WireCatLabs/cli-memo) for the existing shared notes, tags and memories
296
- interface. Both tools use the same store; point `MESSAGING_STORE` at the same file if it is overridden.
297
- For a Zoom profile named `AliceExample`, its provider account key is `zm-profile:AliceExample`:
180
+ ## Pull, import and watch
298
181
 
299
182
  ```sh
300
- memo tags add planning --meeting 1 --provider zoom --account zm-profile:AliceExample --json
301
- memo tags remove planning --meeting 1 --provider zoom --account zm-profile:AliceExample --json
302
- memo notes add --text "Alice Example follow-up" --about meeting:1/1 --json
303
- memo notes list --about meeting:1/1 --json
304
- memo memories add "Alice Example will review" --kind fact --scope work --subject meeting:1/1 --evidence meeting:1/1/1/0 --json
305
- memo memories list --subject meeting:1/1 --scope work --json
183
+ zm pull --lookback-days 7 # hosted meetings, revisiting late transcripts
184
+ zm import ./downloaded-transcripts # .vtt files from your Zoom portal
185
+ zm watch --source api --lookback-days 7 --jsonl # keep pulling in the foreground
306
186
  ```
307
187
 
308
- Memo's add/remove commands write directly to the local store. Owner-authored memories are confirmed;
309
- agent-authored memories stay proposed until confirmed. Meeting revision and cue evidence remains
310
- addressable after corrections. The references and ids above are invented examples; use ids from
311
- your stored meetings and selected account.
188
+ The cursor alone does not revisit transcripts that appear late; use `--lookback-days` or an older
189
+ `--since`. A failed occurrence leaves the cursor unchanged for the next pull. Imported files follow
190
+ the exporter's `YYYY-MM-DD_HHMM_topic-slug.vtt` names; set `files.timezone` to the zone they were
191
+ written in (UTC by default). Participants of imported files stay unknown, and speaker names are
192
+ never turned into identities.
312
193
 
313
- ## Search and read evidence
194
+ More: [the local archive][docs/archive.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
314
195
 
315
- For bounded text search, first index queued meeting records explicitly, then page through hits:
196
+ ## Archive cloud recordings
316
197
 
317
198
  ```sh
318
- zm meetings search-index --limit 100 --max-read-bytes 4194304 --json
319
- zm meetings search-index --limit 100 --yes --json
320
- zm meetings search-page "example plan" --limit 20 --json
321
- zm meetings search-page "example plan" --limit 20 --after <nextCursor> --json
199
+ zm recordings sync --from 2026-01-01 --to 2026-10-10 --destination ./zoom-archive --jsonl
200
+ zm recordings archive verify ./zoom-archive --offline --json
201
+ zm recordings archive search ./zoom-archive "example plan" --offline --json
322
202
  ```
323
203
 
324
- Indexing previews by default; `--yes` applies one bounded batch and `--dry-run` overrides it.
325
- Repeat until the applied receipt reports `remaining: 0`. A search read never processes indexing
326
- work. Its coverage reports pending indexing and unknown index/archive completeness. All normalized
327
- query words must match, through literal prefixes or the stored stemming configuration. The default
328
- configuration adds English, Russian and Spanish word stems; a store can disable or customize it.
329
- This is keyword search, with no semantic model or query operators. `--meeting-id`, `--since` and `--until`
330
- narrow the selected account. The opaque cursor belongs to that account, query and filters; it can
331
- continue inside a large transcript. JSONL preserves the complete page, including `nextCursor`.
204
+ Sync covers up to ten years in monthly requests and downloads serially, streaming to disk. Each
205
+ occurrence gets a manifest with sizes and SHA-256 checksums, never signed URLs or tokens. Existing
206
+ files are never overwritten; repeated runs skip verified files. With a profile, interrupted downloads
207
+ resume safely. `recordings archive transcript|search` read verified WebVTT offline without a
208
+ database; `recordings archive import` appends them to your stored meetings. `recordings schedule
209
+ create --yes` installs a daily systemd user timer (Linux only).
210
+
211
+ What you can download depends on Zoom permissions, retention and your plan. Recordings of meetings
212
+ you only attended are not necessarily available through your API.
332
213
 
333
- `meetings search` keeps its existing literal prefix transcript search. `search all` uses the shared search
334
- service and searches only meetings by default:
214
+ More: [archive cloud recordings][docs/archive.md#archive-cloud-recordings] ·
215
+ [daily backups][docs/archive.md#daily-backups] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
216
+
217
+ ## Search and evidence
335
218
 
336
219
  ```sh
337
- zm search all "example plan" --limit 100 --max-meetings 100 --json
338
- zm meetings evidence meeting:3/15/20/0 --cues 100 --bytes 65536 --json
339
- zm meetings context person:7 --meetings 10 --scan-limit 1000 --json
340
- zm meetings task-proposal meeting:3/15/20/0 --kind promise --json
220
+ zm meetings search-index --limit 100 --yes --json # index queued meetings, one batch
221
+ zm meetings search-page "example plan" --limit 20 --json # word search with continuation
222
+ zm meetings evidence meeting:3/15/20/0 --cues 100 --json # the exact passage
223
+ zm meetings context person:7 --meetings 10 --json # meetings linked to a person
341
224
  ```
342
225
 
343
- Meeting references have the form `meeting:<account>/<meeting>[/<transcript>[/<cue-position>]]`.
344
- They are restricted to the selected local account. Transcript references retain historical revision
345
- identity. Evidence bounds both returned content and database reads; resume with its returned cue
346
- reference using `--after`, or its revision cursor using `--after-transcript-id`. These continuation
347
- options are mutually exclusive. `--max-read-bytes` defaults to 4 MiB per page and
348
- `--max-transcript-pages` bounds revision scanning, including empty revisions. Follow the returned
349
- continuation and completeness fields rather than assuming a bounded response is exhaustive.
226
+ `search-page` matches every word by prefix or by stored English, Spanish and Russian word forms, and
227
+ pages with an opaque `--after` cursor. References have the form
228
+ `meeting:<account>/<meeting>[/<transcript>[/<cue-position>]]`, stay inside the selected account and
229
+ keep pointing at the same revision after a correction. Every bounded read reports whether it is
230
+ complete. `search all --only meetings,notes` adds store-wide notes. `meetings embeddings` and
231
+ `meetings semantic` search by meaning with a model you name; nothing is downloaded for you.
350
232
 
351
- Person context uses stored identity links and account presence, without matching speaker names.
352
- A person linked to a meeting is not necessarily a speaker. Pending derived indexes or bounded scans
353
- can leave context incomplete. Task proposals support question, request, mention and promise;
354
- `applied: false` and `persistence: "proposal-only"` mean no task was created.
233
+ More: [search and evidence][docs/search.md] · [topic search][docs/topic-search.md] ·
234
+ [Zoom on wirecat.dev][wirecat/en/docs/zoom]
355
235
 
356
- Broader search requires explicit `--only messages,mail,notes,meetings`. Message reads use the
357
- selected local account; mail reads include stored email accounts; notes are global to the shared
358
- store. Meeting matching uses word
359
- prefixes; unsupported meeting syntax or exact queries are reported as skipped. A meetings-only
360
- continuation uses the returned `meetings.nextCursor` as `--meeting-cursor '<json>'`, bound to its
361
- account and query. JSONL emits one complete report, retaining skips, coverage and cursors.
236
+ ## Local transcription
362
237
 
363
- ## Explicit meeting vectors
238
+ No Zoom transcript? `zm meetings transcribe 1 ./call.wav --model <model> --yes` recognizes a PCM16 WAV
239
+ file (mono or stereo, 16 or 48 kHz) with an already installed local speech model and appends it as a
240
+ separate transcript. The preview checks the file without loading the model. Timestamps cover windows
241
+ of up to 30 seconds and speakers stay unknown.
364
242
 
365
- Choose an already installed local model, or explicitly select a remote endpoint and dimensions:
243
+ More: [transcribe local audio][docs/archive.md#transcribe-local-audio] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
366
244
 
367
- ```sh
368
- zm meetings embeddings --model e5-small --json
369
- zm meetings embeddings --model e5-small --yes --limit 100 --json
370
- zm meetings semantic "example plan" --model e5-small --max-chunks 1000 --json
371
- zm meetings semantic "example plan" --model example-model --base-url http://127.0.0.1:8080/v1 --dims 384 --json
372
- ```
245
+ ## MCP and agent setup
373
246
 
374
- The first embedding command previews existing chunk status without opening a model, downloading
375
- files or generating vectors. `--yes` validates and opens the selected model before rebuilding chunks
376
- and embedding one bounded batch. Local models must already be installed; this command never downloads
377
- them. Remote endpoints are explicit; OpenAI endpoints use `OPENAI_API_KEY`. Remote models cannot be
378
- used with `--offline`.
247
+ `zm skill install` writes the packaged guide to `~/.claude/skills/zoom-cli/` (Claude Code) and
248
+ `~/.agents/skills/zoom-cli/` (Codex, Gemini CLI); `--for` picks one. MCP clients start the server
249
+ with `["serve", "--mcp"]`:
379
250
 
380
- Generation uses current transcript revisions and rechecks their hashes before saving results.
381
- `--after-transcript-id` continues rebuilding chunks; `--after-hash` continues missing-vector work.
382
- These are separate cursors. Shared cached vectors remain available to other resources.
383
- A completed generation can emit its acknowledged receipt during a bounded cancellation grace period,
384
- then exit 130. Failed generation and cancelled queries emit no such receipt; a blocked output pipe
385
- can prevent delivery.
251
+ ```json
252
+ { "mcpServers": { "zoom": { "command": "zm", "args": ["serve", "--mcp"] } } }
253
+ ```
254
+
255
+ The server has seven read-only tools: meeting list and show, transcripts, summaries, exports, text
256
+ search and participant search. `--meeting-context`, `--unified-search` and `--semantic --model <id>`
257
+ add evidence, shared search and meaning search. It reads only the selected profile, and never exposes
258
+ file exports, Zoom changes, embedding generation or task creation. A desktop app may need the full
259
+ path from `which zm`, and the same `ZM_CONFIG_DIR` or `MESSAGING_STORE` in the entry's `env`.
386
260
 
387
- Semantic search embeds only the query and reads existing vectors; it never rebuilds or generates
388
- stored vectors. Results rank scanned candidates for the selected account and model. Use
389
- `--after-chunk-id` to continue candidate scanning, not to page through globally ranked results.
390
- The report states candidate scan coverage; index completeness and archive completeness are unknown.
391
- `--max-rows` and `--max-text-bytes` bound transcript reads for generation and search.
261
+ More: [MCP and skills][docs/mcp.md] · [MCP and skills on wirecat.dev][wirecat/en/docs/mcp] ·
262
+ [connect your AI agent][wirecat/en/docs/agents]
392
263
 
393
- ## Watch a transcript folder
264
+ ## Manage Zoom meetings
394
265
 
395
266
  ```sh
396
- zm watch ./downloaded-transcripts --interval 10s --jsonl
267
+ zm remote-meetings create --topic "Example planning" --start-time 2026-10-20T10:00:00Z --duration-minutes 30 --json
268
+ zm remote-meetings cancel 123456789 --dry-run --json
397
269
  ```
398
270
 
399
- Watching rescans the folder for each cycle, so corrected older files are revisited. It imports serially,
400
- closes the cycle's store connection before emitting its receipt and waits for output to drain before
401
- starting another cycle. Intervals range from one second to one day. This is a foreground process;
402
- stop it with Ctrl-C. Headless watching requires `--jsonl`; a stream cannot use `--json`.
403
- Select a local profile before watching, just as for a one-time import.
271
+ Creation, updates and cancellation preview until you add `--yes`, and are never retried
272
+ automatically. An uncertain outcome exits with code 14: check Zoom before repeating. Remote ids are
273
+ Zoom's numeric ids; stored `meetings` commands use local ids.
404
274
 
405
- Cancellation allows up to one second to flush a fully completed receipt if it arrives during
406
- store close. A blocked output pipe stops that flush; no later cycle starts.
275
+ More: [managing Zoom meetings][docs/remote-meetings.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
407
276
 
408
- ## Read meeting tools through MCP
277
+ ## Output, limits and deadlines
409
278
 
410
- `zm serve --mcp` uses MCP's stdio protocol and serves seven read-only tools: meeting list/show,
411
- transcripts, summaries, exports, text search and participant search. Tool discovery does not open a
412
- database. Each read uses the selected local account and closes its connection before the response;
413
- a caller cannot override the account. File exports and remote mutations are not exposed as tools.
279
+ `--json` prints one value and `--jsonl` one item per line; piped output defaults to JSON and errors
280
+ go to stderr. `--fields id,title` trims results, `--offline` refuses the network, and output is
281
+ capped at 4 MiB unless `--max-output-bytes` says otherwise. Default deadlines are 30 seconds for
282
+ reads, five minutes for login and one hour for downloads, sync and verification; `--timeout 5m`
283
+ changes them. Watching and MCP serving run until stopped.
414
284
 
415
- Optional flags add tools without changing the defaults: `--meeting-context` adds evidence, person
416
- context and task proposals; `--unified-search` adds meetings-only shared search;
417
- `--semantic --model <id>` adds one read-only vector query tool. Remote semantic models additionally
418
- require `--base-url` and `--dims`. The server fixes the model at startup and the profile on its first
419
- read; restart it to change either. Clients cannot override either selection. Embedding generation
420
- and task creation are never MCP tools.
285
+ More: [usage][docs/usage.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
421
286
 
422
- MCP clients can launch `zm` with arguments `["serve", "--mcp"]`. Keep stdout for protocol messages;
423
- omit `--json`, `--jsonl` and `--fields`. `--max-output-bytes` bounds each tool result, with zero meaning
424
- unlimited. Select a profile and import or pull its data before reading tools; discovery is available
425
- without stored data.
287
+ ## Configuration
426
288
 
427
- `zm skill show` prints the packaged instructions for an agent. `zm skill install --for agents` writes
428
- a version-stamped copy to the agent skills directory; `--for claude` selects Claude Code instead.
429
- Installation is explicit and does not run when a command starts.
289
+ | Setting | Meaning |
290
+ |---|---|
291
+ | `zoom.clientId` | your Zoom app's Public Client ID |
292
+ | `account.profile` | the local profile label |
293
+ | `source` | `api` or `files` for `pull` and `watch` |
294
+ | `files.folder`, `files.timezone` | the transcript folder and the zone of its filenames |
295
+ | `ZM_CONFIG_DIR` | another configuration directory (also changes the keyring entry) |
296
+ | `MESSAGING_STORE` | another shared database path |
297
+ | `OPENAI_API_KEY` | only for an OpenAI embedding endpoint you select |
430
298
 
431
- ## Manage a Zoom meeting
299
+ More: [configuration][docs/configuration.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
432
300
 
433
- Remote meeting ids are Zoom's numeric ids; stored `meetings` commands use local database ids.
434
- Create, update and cancel show the proposed request by default. Add `--yes` to apply it once;
435
- `--dry-run` always keeps the preview, including when `--yes` is present.
301
+ ## Security model
436
302
 
437
- ```sh
438
- zm remote-meetings create --topic "Example planning" --start-time 2026-10-20T10:00:00Z --duration-minutes 30 --json
439
- zm remote-meetings update 123456789 --topic "Example review" --yes --json
440
- zm remote-meetings cancel 123456789 --dry-run --json
441
- ```
303
+ - Your own Zoom app with PKCE; no client secret exists.
304
+ - Tokens only in the system keyring, never in a config file; a missing keyring is an error.
305
+ - Network: Zoom's API, plus an embedding endpoint only when you name one. `--offline` refuses both.
306
+ - Manifests and saved jobs never hold signed URLs, tokens or credentials; diagnostics omit raw
307
+ provider error text.
308
+ - The MCP server is read-only and fixed to the selected profile; changes to Zoom preview until `--yes`.
309
+
310
+ More: [security][docs/security.md] · [security on wirecat.dev][wirecat/en/docs/security]
311
+
312
+ ## Troubleshooting
313
+
314
+ - **"Invalid redirect" from Zoom:** the manifest import left the redirect URL or Public Client OAuth
315
+ unset; fill them in by hand.
316
+ - **No transcripts:** turn on **Allow hosts to retain transcripts**; attended meetings need `zm import`.
317
+ - **Missing-scope error:** add the named scope in your app, then `zm login` again.
318
+ - **Browser does not start:** `zm login --browser firefox`, or paste the callback parameters.
319
+ - **Lock left after a crash:** `zm recordings archive locks`, then `recover` with `--yes`.
442
320
 
443
- Only instant and scheduled creation and basic changes are supported. Remote writes are never
444
- automatically retried. If a write was dispatched and its result is uncertain, inspect Zoom before
445
- repeating it; the CLI reports an uncertain outcome with exit code 14.
321
+ More: [troubleshooting][docs/troubleshooting.md] · [Zoom on wirecat.dev][wirecat/en/docs/zoom]
322
+
323
+ ## Part of WireCat
324
+
325
+ `zm` is part of [WireCat](https://wirecat.dev), an open-source, local-first context layer for AI
326
+ agents. Meetings land in the same local store as your Telegram, MAX and memo data, and
327
+ `zm search all "<query>" --only meetings,notes` searches them together with your memo notes.
328
+ Start with Zoom. Add more context when you need it. Your context. Any agent.
329
+
330
+ More: [wirecat.dev](https://wirecat.dev) · [connect your AI agent][wirecat/en/docs/agents]
331
+
332
+ ## Technical docs
333
+
334
+ | Page | What it covers |
335
+ |---|---|
336
+ | [Overview][docs/index.md] | what `zm` is and the one-minute start |
337
+ | [Installation][docs/installation.md] | requirements, first run, where files go, completion |
338
+ | [Your Zoom app][docs/zoom-app.md] | creating the app, scopes, company accounts |
339
+ | [Login, sessions and profiles][docs/sessions.md] | OAuth login, keyring, local profiles |
340
+ | [Usage][docs/usage.md] | every command group, output, deadlines |
341
+ | [The local archive][docs/archive.md] | pull, import, watch, recordings, backups, transcription |
342
+ | [Search and evidence][docs/search.md] | word search, evidence, people, links, memo |
343
+ | [Topic search][docs/topic-search.md] | search by meaning with a model you choose |
344
+ | [MCP and skills][docs/mcp.md] | the skill, the MCP server, optional tools |
345
+ | [Managing Zoom meetings][docs/remote-meetings.md] | upcoming meetings, create, update, cancel |
346
+ | [Commands][docs/commands.md] | every command, option and exit code (generated) |
347
+ | [Configuration][docs/configuration.md] | settings and environment variables |
348
+ | [Troubleshooting][docs/troubleshooting.md] | by symptom |
349
+ | [Security][docs/security.md] | what reaches the disk and the network |
350
+ | [Architecture][docs/dev/architecture.md] · [Testing][docs/dev/testing.md] · [Releasing][docs/dev/releasing.md] | for contributors |
351
+
352
+ The WireCat portal at [wirecat.dev/en/docs/zoom][wirecat/en/docs/zoom] is being prepared; until then these pages
353
+ are the reference.
446
354
 
447
355
  ## Development
448
356
 
@@ -454,15 +362,43 @@ pnpm lint && pnpm typecheck && pnpm test:coverage && pnpm docs:check
454
362
  pnpm build && pnpm smoke:bun
455
363
  ```
456
364
 
457
- [Commands](docs/commands.md), [architecture](docs/dev/ARCHITECTURE.md), [testing](docs/dev/TESTING.md) and
458
- [development setup](docs/dev/DEVELOPMENT.md) describe the local setup.
459
- [Releasing](docs/dev/RELEASING.md) covers package checks and trusted publishing. Fixtures use invented
460
- people and meetings. Tests use an injected keyring, scripted HTTP responses, temporary config
461
- folders and the memory meeting store.
365
+ Fixtures use invented people and meetings. Tests use an injected keyring, scripted HTTP responses,
366
+ temporary config folders and the memory meeting store. `pnpm generate:check` checks the generated
367
+ command reference; `pnpm test:matrix` measures command and option coverage.
462
368
 
463
- `pnpm generate:check` checks the generated command reference. `pnpm test:matrix` measures CLI
464
- command and option coverage; its [matrix](docs/dev/test-matrix.md) records explicit exceptions.
369
+ More: [development setup][docs/dev/development.md] · [test matrix][docs/dev/test-matrix.md]
465
370
 
466
371
  ## Licence
467
372
 
468
- [Apache License 2.0](LICENSE).
373
+ [Apache License 2.0][license].
374
+
375
+ [docs/archive.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/archive.md
376
+ [docs/archive.md#archive-cloud-recordings]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/archive.md#archive-cloud-recordings
377
+ [docs/archive.md#daily-backups]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/archive.md#daily-backups
378
+ [docs/archive.md#transcribe-local-audio]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/archive.md#transcribe-local-audio
379
+ [docs/archive.md#where-meetings-are-stored]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/archive.md#where-meetings-are-stored
380
+ [docs/commands.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/commands.md
381
+ [docs/configuration.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/configuration.md
382
+ [docs/dev/architecture.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/dev/ARCHITECTURE.md
383
+ [docs/dev/development.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/dev/DEVELOPMENT.md
384
+ [docs/dev/releasing.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/dev/RELEASING.md
385
+ [docs/dev/test-matrix.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/dev/test-matrix.md
386
+ [docs/dev/testing.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/dev/TESTING.md
387
+ [docs/index.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/index.md
388
+ [docs/installation.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/installation.md
389
+ [docs/mcp.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/mcp.md
390
+ [docs/remote-meetings.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/remote-meetings.md
391
+ [docs/search.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/search.md
392
+ [docs/security.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/security.md
393
+ [docs/sessions.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/sessions.md
394
+ [docs/sessions.md#select-a-local-profile]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/sessions.md#select-a-local-profile
395
+ [docs/topic-search.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/topic-search.md
396
+ [docs/troubleshooting.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/troubleshooting.md
397
+ [docs/usage.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/usage.md
398
+ [docs/zoom-app.md]: https://github.com/WireCatLabs/zoom-cli/blob/main/docs/zoom-app.md
399
+ [gh/cli-meetings/blob/main/docs/dev/roadmap.md]: https://github.com/WireCatLabs/cli-meetings/blob/main/docs/dev/ROADMAP.md
400
+ [license]: https://github.com/WireCatLabs/zoom-cli/blob/main/LICENSE
401
+ [wirecat/en/docs/agents]: https://wirecat.dev/en/docs/agents
402
+ [wirecat/en/docs/mcp]: https://wirecat.dev/en/docs/mcp
403
+ [wirecat/en/docs/security]: https://wirecat.dev/en/docs/security
404
+ [wirecat/en/docs/zoom]: https://wirecat.dev/en/docs/zoom