slidemind 0.2.2 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slidemind",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Connect Claude Code to the slidemind PowerPoint add-in — build and edit native, on-brand PowerPoint decks against the active corporate design, from the terminal.",
5
5
  "author": {
6
6
  "name": "statworx",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slidemind",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Connect Codex to the slidemind PowerPoint add-in — build and edit native, on-brand PowerPoint decks against the active corporate design. Requires the slidemind CLI (npm install -g slidemind); the skills explain the install when it is missing.",
5
5
  "author": {
6
6
  "name": "statworx",
@@ -25,6 +25,13 @@
25
25
  "category": "Productivity",
26
26
  "capabilities": [
27
27
  "Skills"
28
+ ],
29
+ "websiteURL": "https://www.statworx.com",
30
+ "brandColor": "#E07D44",
31
+ "logo": "./assets/app-icon.png",
32
+ "screenshots": [],
33
+ "defaultPrompt": [
34
+ "Turn this into an on-brand slide deck"
28
35
  ]
29
36
  }
30
37
  }
package/AGENTS.md CHANGED
@@ -17,13 +17,58 @@ Both drive the same add-in bridge, so an agent and a human end up producing the
17
17
 
18
18
  The package is published to **public npm** as `slidemind` (`publishConfig.access: public`; license `UNLICENSED` — publicly installable, proprietary). The source lives in a private GitHub repo (`STATWORX/intern-slidemind-cli`); the npm tarball is the install artifact. The CLI is a thin client — the corporate design and the OOXML render live in the slidemind add-in and require an open host — so there is nothing secret in the tarball.
19
19
 
20
- Install + register with a harness:
20
+ **Onboarding is one pasted command.** The add-in's Settings → General → Connect
21
+ CLI → *Set up CLI* mints a claim and prints the whole line:
21
22
 
22
23
  ```bash
23
- npm install -g slidemind
24
- slidemind init --for all # claude | codex | opencode | all | none
24
+ npx --yes slidemind@latest setup smc1_<claim>
25
25
  ```
26
26
 
27
+ npx runs the package from its cache but never installs it, so `cmdSetup` does
28
+ the persistent work itself: decode the claim → redeem it → save the session →
29
+ `npm install -g slidemind@latest` → deploy the skills → run `ready`. The user
30
+ needs nothing but Node beforehand, and **there is no `init` step**: `--for auto`
31
+ (the default) resolves through each installer's `detect()` to the coding agents
32
+ actually present, minus any whose slidemind plugin already supplies the skills.
33
+ `init` stays for the manual-install path and for adding a harness later.
34
+
35
+ `detect()` reads **two** signals and treats either as present: the harness config
36
+ dir (`~/.claude`, `$CODEX_HOME`/`~/.codex`, `~/.config/opencode`) and the harness
37
+ binary on `PATH`. Neither alone is sufficient — those dirs are created the first
38
+ time an agent RUNS, so a just-installed, never-launched agent has none, while a
39
+ desktop-app-only install has no binary. A machine where BOTH miss (e.g. only a
40
+ never-opened desktop app) still ends up connected but skill-less; the remedy is
41
+ `slidemind init --for auto` once the agent has been opened, which is what the
42
+ "none detected" line tells the user.
43
+
44
+ **Why the claim carries a URL, and why onboarding must start in PowerPoint.**
45
+ Every customer runs its own deployment, so a fresh CLI cannot know which backend
46
+ its user belongs to — there is no address to start an approval at and nothing to
47
+ discover it from. The authenticated add-in knows, so the claim (`smc1_` +
48
+ base64url `{v,u,s}`) carries this deployment's origin next to a one-time secret.
49
+ That is the same property the retired `pair <blob>` flow had; `setup` keeps it
50
+ and removes the steps. **Do not "simplify" this into a CLI-first flow** (a device
51
+ code the CLI mints, a browser PKCE page it opens): both need the backend URL
52
+ *before* they can start, which is the one thing the CLI does not have. The
53
+ backend builds `u` from the configured `FRONTEND_URL`, never from a request
54
+ header — a spoofable header must not end up in a credential the CLI then trusts.
55
+
56
+ Installation, skill distribution, and CLI authorization stay independent
57
+ underneath. This matters for admin-distributed Codex plugins: the plugin already
58
+ supplies the skills, so those users must **not** plant a second copy — which
59
+ `--for auto` handles by itself, and `setup --for none --no-install` reduces to
60
+ the connection alone.
61
+
62
+ **mint → redeem is the ONLY way a CLI gets a session.** There is no device code
63
+ and no `slidemind connect`: both were removed because each needs the backend URL
64
+ *before* it can start, which is the one thing the CLI does not have. `ready` on an
65
+ unconnected CLI therefore does not attempt a handshake — it emits a
66
+ `not_connected` blocker naming the add-in button and exits. Consequently the CLI
67
+ hardcodes **no backend URL at all**; `SLIDEMIND_CONNECT_URL` is gone, and
68
+ `--backend`/`SLIDEMIND_BACKEND` only ever *scope* an existing session. The
69
+ retired `slidemind pair <blob>` had the same carries-its-own-address property;
70
+ `setup` keeps it and removes the steps.
71
+
27
72
  `npx slidemind <command>` runs it without a global install. `slidemind update` is a thin wrapper over `npm install -g slidemind@latest` (`--ref <version>` to pin, `--for <target>` to control the redeploy). The `files` whitelist in `package.json` controls what ships (`bin/ src/ skills/ .claude-plugin/ .codex-plugin/ .agents/plugins/ AGENTS.md README.md`); `archive/`, `docs/`, `scripts/`, and `test/` are excluded. Two traps live in that list:
28
73
 
29
74
  - `.agents/plugins/`, **not** `.agents/` — `files` globs the filesystem rather than git, and `.agents/` also holds gitignored per-developer harness scratch that a bare entry would publish.
@@ -38,7 +83,7 @@ Both agent harnesses can also install slidemind as a **plugin** — this private
38
83
 
39
84
  > The Codex **admin console** validates harder than the CLI does: it rejects an import when any `interface` block lacks a non-blank `longDescription`, which `codex plugin add` never complains about. `test/plugin-manifests.test.mjs` guards it.
40
85
 
41
- `slidemind init --for <target>` remains the universal fallback on all three harnesses; the Claude installer prints a dedup hint when it detects the plugin is also installed.
86
+ `slidemind init --for <target>` remains the universal fallback on all three harnesses; the Claude and Codex installers each print a dedup hint when they detect the plugin is also installed (`~/.claude/plugins/cache/<marketplace>/slidemind/`, `$CODEX_HOME/plugins/cache/<marketplace>/slidemind/<version>/`). Plugin users only ever need `npm install -g slidemind` for the binary — never `init`, which would plant a second copy of the skills that drifts on the next plugin update. Both skills' *CLI missing* remediation says so, keyed off whether the running `SKILL.md` sits under a plugin cache.
42
87
 
43
88
  **Updating a plugin-installed CLI is `/plugin`, not `slidemind update`.** The Claude plugin ships its own copy of the CLI on the session's PATH, so `npm install -g slidemind@latest` drops a second, unrelated global and the session keeps running the old binary — a user following that advice would watch the update succeed and stay blocked on the add-in's version floor. `src/install-channel.mjs` detects the channel from the running code's path (plus `CLAUDE_PLUGIN_ROOT`) and every too-old-CLI remediation ends with `updateCliInstruction()`, so the message names the updater that actually replaces this binary; the `cli_update_required` rung of the readiness ladder also flips `actor` to `user` there, because the agent cannot drive `/plugin`.
44
89
 
@@ -89,7 +134,7 @@ slidemind/
89
134
  ├── .agents/
90
135
  │ └── plugins/marketplace.json Codex marketplace — serves this repo (git clone) as the plugin; NOT in the npm tarball
91
136
  ├── bin/
92
- │ ├── slidemind.mjs CLI dispatcher (ready, doctor, presentations, read, download-bundle, new, init, build, build-pptx, view-draft, push, ls engines, search, insert-slide, add-slide, install, pair/whoami/use/logout)
137
+ │ ├── slidemind.mjs CLI dispatcher (setup, connect, ready, doctor, presentations, read, download-bundle, new, init, build, build-pptx, view-draft, push, ls engines, search, insert-slide, add-slide, install, whoami/use/logout)
93
138
  │ └── slidemind + slidemind.cmd PATH shims for Claude Code plugin sessions (npm links slidemind.mjs itself)
94
139
  ├── skills/ canonical, installable skill payload — thin CLI workflow glue only
95
140
  │ ├── create-slides/
@@ -99,11 +144,13 @@ slidemind/
99
144
  │ │ composition/layouts/authoring/build-export) are READ from the materialized
100
145
  │ │ bundle — owned by the add-in.
101
146
  │ └── search/
102
- │ └── SKILL.md engine-search + slide-reuse skill (installs as slidemind-search): host gate +
103
- │ discover → search → pick → reuse loop + vocabulary→CLI command map. The craft is
147
+ │ └── SKILL.md engine-search + slide-reuse skill (installs as slidemind-search): host gate
148
+ │ (insert-slide + reading an open deck only) + discover → search → pick → reuse
149
+ │ loop + vocabulary→CLI command map. The craft is
104
150
  │ READ from the bundle's workflow/search.md — owned by the add-in.
105
151
  ├── src/ implementation of the slidemind CLI
106
- │ ├── bridge/ add-in local-bridge: client.mjs, bundle.mjs (materialize), build-and-push.mjs (server render; native-slide splicing), engine-download.mjs + recolor.mjs (image/icon fetch + recolour)
152
+ │ ├── bridge/ add-in local-bridge: client.mjs, bundle.mjs (materialize), build-and-push.mjs (server render; native-slide splicing), engine-download.mjs + recolor.mjs (image/icon fetch + recolour),
153
+ │ │ setup-claim.mjs (decode/redeem the add-in's one-command claim — the only connect path) + http-json.mjs + config.mjs (per-backend sessions)
107
154
  │ ├── builders/ build.mjs (HTML preview), review.mjs (spatial preview-review gate + local server; stable per-deck port, graceful fallback, tab reuse across rounds), plan.mjs (plan sign-off gate) + plan-overlay.js + plan-md.mjs (markdown→HTML) + gate-server.mjs (shared gate primitives), resolve-skill.mjs (→ bundle), lint.mjs (runs the add-in's engine)
108
155
  │ ├── pptx/ host-free local-.pptx support (fflate-based): read-local.mjs (read a file's slides — output-identical to the host read), slide-swap.mjs (fold a picked slide into a deck as native .pptx — swaps it into the lowest slot the splicer reads, then prunes the package to that slide's dependency closure so a slice carries only what it needs), zip.mjs + ooxml.mjs (shared unzip/order helpers)
109
156
  │ └── installers/ per-harness installers: claude.mjs, codex.mjs, opencode.mjs, lib.mjs
@@ -120,8 +167,8 @@ We **do not** ship separate slash commands. Earlier versions had a top-level `co
120
167
  ## CLI surface
121
168
 
122
169
  ```bash
123
- slidemind ready [deck] # one-shot session start: connection ladder + design resolution + bundle download + deck bind; --to/--force/--connect-only/--json (HOST REQUIRED)
124
- slidemind doctor # read-only connection diagnostics (ordered next-action ladder; does NOT materialize or bind — `ready` is the preflight)
170
+ slidemind ready [deck] # one-shot session start: connection ladder + design resolution + bundle download + deck bind; --to/--brand/--force/--connect-only/--json (a BOUND deck, an explicit --brand, or a single listed design readies with PowerPoint closed)
171
+ slidemind doctor # read-only diagnostics on TWO independent ladders — backend authoring (session/backend/version/engines) and live PowerPoint (windows/pane); does NOT materialize or bind — `ready` is the preflight
125
172
  slidemind presentations # list PowerPoint windows registered with the add-in
126
173
  slidemind read [presId|file.pptx] # pull an open presentation's content (presId; HOST REQUIRED) OR read a local .pptx on disk (file path; host-free) — same per-slide output (--mode summary|raw)
127
174
  slidemind download-bundle [deck] # materialize the active corporate design's bundle locally
@@ -129,27 +176,36 @@ slidemind new <name> # scaffold ./decks/<name>/ (auto-binds to the
129
176
  slidemind plan <deck> # plan sign-off gate on <deck>/plan.md; markdown editor + live preview + overall feedback, blocks for approve/comments (host-free)
130
177
  slidemind build <deck> # build self-contained HTML preview
131
178
  slidemind review <deck> # spatial preview-review gate; blocks for approve/comments (host-free)
132
- slidemind build-pptx <deck> # render native .pptx via the add-in (HOST REQUIRED)
179
+ slidemind build-pptx <deck> # compose: add-in; template pack: host-free with --pack <dir>
180
+ slidemind inspect-template-deck <deck> # normalized pack model for pack-owned validation; --pack <dir> --json
133
181
  slidemind view-draft <deck> # render the deck's slides to per-slide PNGs so the agent can look before review; no push, no .pptx (host-free once the bundle is materialized)
134
182
  slidemind push <deck> # render + push slides into a running PowerPoint (HOST REQUIRED)
135
- slidemind ls engines # list the live engine catalog (image + slide; --type/--subtype) (HOST REQUIRED)
136
- slidemind search "<query>" # search an engine for imagery or slides (--engine/--intent/--top) (HOST REQUIRED)
183
+ slidemind ls engines # list the live engine catalog (image + slide; --type/--subtype) (pane-free on add-ins with engineRoutes; HOST REQUIRED on older ones)
184
+ slidemind search "<query>" # search an engine for imagery or slides (--engine/--intent/--top/--deck) (pane-free on add-ins with engineRoutes; HOST REQUIRED on older ones)
137
185
  slidemind insert-slide [opts] # reuse found slide(s) live into a window (--search/--pick/--to/--at) (HOST REQUIRED)
138
- slidemind imagen "<prompt>" [opts] # generate ONE image via the add-in's image model into <deck>/assets/ (--deck/--out/--size/--quality/--brand-style; paired backend, pane-free)
139
- slidemind add-slide [opts] # fold slide(s) into a deck as native .pptx — from an engine (--search/--pick/--deck/--to/--at; HOST REQUIRED) or a local file (--from <file.pptx>/--pick/--deck/--at; host-free, mutually exclusive with --search)
140
- slidemind pair <code> # pair with an add-in environment (copy from its "Connect CLI")
141
- slidemind whoami # list every paired environment (* = default)
186
+ slidemind imagen "<prompt>" [opts] # generate ONE image via the add-in's image model into <deck>/assets/ (--deck/--out/--size/--quality/--brand-style; connected backend, pane-free)
187
+ slidemind setup <claim> # one-command onboarding from the add-in's Connect CLI button: redeem the claim + npm install -g + skills + ready (--for/--no-install/--no-ready/--json)
188
+ slidemind add-slide [opts] # fold slide(s) into a deck as native .pptx — from an engine (--search/--pick/--deck/--to/--at/--json; pane-free on add-ins with engineRoutes) or a local file (--from <file.pptx>/--pick/--deck/--at; host-free, mutually exclusive with --search)
189
+ slidemind whoami # list every connected environment (* = default)
142
190
  slidemind use <url|env> # set the default environment
143
191
  slidemind logout [url|env] # unpair one environment (--all unpairs every one)
144
- slidemind init --for <target> # install skill into claude | codex | opencode | all (also clears the bundle cache)
192
+ slidemind init --for <target> # install skill into claude | codex | opencode | all | auto (also clears the bundle cache); `setup` already does this
145
193
  slidemind uninstall --for <target> # remove the skill (also clears the bundle cache)
146
194
  ```
147
195
 
148
196
  `<deck>` resolves as: absolute path → `./<arg>` if it exists → `./decks/<arg>`. The decks directory is `./decks/` by default; override with `SLIDEMIND_DECKS=/abs/path`.
149
197
 
150
- **Multi-environment pairing.** The CLI stores one session **per backend** (`~/.config/slidemind/session.json`, v2 `{version, sessions[], default}`; the legacy single-record v1 shape is migrated on read). Pair once per environment (local / dev / prod) and every command **fans out** across all paired backends, tags each open window with its `env`, and **routes by the presentation's origin backend** automatically — no manual switching. Scope a command to one backend with `--backend <url|env>` (or `SLIDEMIND_BACKEND`). This is a developer convenience; a normal user pairs exactly one. See the memory note *CLI↔add-in: cloud relay + pairing*.
198
+ **Multi-environment sessions.** The CLI stores one session **per backend** (`~/.config/slidemind/session.json`, v2 `{version, sessions[], default}`; the legacy single-record v1 shape is migrated on read). Connect once per environment (local / dev / prod) and every command **fans out** across all connected backends, tags each open window with its `env`, and **routes by the presentation's origin backend** automatically — no manual switching. Adding an environment is easiest with `slidemind setup <claim> --no-install --for none` — the claim carries its own backend, so nothing has to be typed or configured. There is no other way in: without a claim the CLI has no backend to talk to. Later commands may scope an existing session with `--backend <url|env>` / `SLIDEMIND_BACKEND`. A normal user connects exactly one backend.
199
+
200
+ **The design truth lives in the add-in, not the CLI.** The `.pptx` is rendered server-side over the local bridge (no local exporter), the corporate design is fetched as a bundle, brand imagery comes from the add-in's engine, and slide reuse (extract / insert / splice) executes in the add-in too. So `create`/`build-pptx`/`push`/`ls engines`/`search`/`insert-slide`/`add-slide` all need the **slidemind add-in with an active corporate design** behind them. The engine-search + slide-reuse wire contract is in `docs/slidemind-cli-connect/11-engine-search-slide-reuse.md`; see `docs/slidemind-cli-connect/` for the rest.
201
+
202
+ **Engine ops are moving off the task pane.** An add-in that advertises `engineRoutes` in `/api/cli/capabilities` answers discovery, search, download and slide extraction on the CLI session itself (`GET /api/cli/engines`, `POST /api/cli/searches`, `GET /api/cli/searches/:id/results/:sel/{image,thumbnail,slide,source-presentation}`), so those commands need **no PowerPoint window at all** — the searchId is server-owned, `--to` becomes a no-op, and multi-environment routing goes by the deck's bound design (`.bundle-ref.json`), never by an open window's origin. Older add-ins keep relaying every one of them through the pane (`client.resolveEngineBackend()` returns null → `requirePaneHost()`), so **never remove the pane path and never raise `minCliVersion` for this**. Live `insert-slide` and reading an unsaved open deck stay pane-bound — that is Office.js physics, but even there the *extraction* backend is the one that **minted the searchId** (`client.resolveSearchBackend()`), never the target window's origin: with two environments connected those differ, and spending a server-owned id on the wrong one 404s as an "expired search" no re-search can clear.
203
+
204
+ When the backend's permission snapshot ages out, corpus search (only) answers `403 permissions_stale`, rendered through `client.permissionsStaleBlocker(err)` as one user-actionable line — but the snapshot backs the **pane-free path only**, since a live pane signs every request with a browser token that is strictly fresher. So when a pane-ready window is open, `search` **relays through it** instead of blocking (one stderr note; the searchId is then the pane's, and every next step names that window), and the ops that cannot be replayed pane-side — anything bound to an opaque `searchId` — name that open pane as the route to a fresh search rather than telling the user to open an add-in that is already open. `slidemind ls engines` is the exception: `GET /api/cli/engines` is the catalog route on both add-in generations, so there is no second route to retry on and only the message widens. Plan: `docs/slidemind-cli-connect/13-pane-free-authoring.md`.
205
+
206
+ **The two ops that stay pane-bound self-heal a presId churn.** Every pane reconnect mints a NEW presId for the same window, so `push`'s insert and `insert-slide` re-list the registry and re-match the window before giving up: `waitForPaneReady` matches the same presId, then `fileName`+`brandId`, then — when a Save-As renamed the window mid-run — the **design fingerprint alone** (`presFP == brandId`), and only when exactly one connected window carries it (two windows on one design are indistinguishable, and pushing into the wrong one is worse than waiting). `engineOpWithPaneWait` takes that window identity plus an opt-in `retargetOnMissing`, which **only the live insert sets**: for an idempotent engine read a 404 is the search record talking, not the window, so waiting on the registry would just stall the agent (`isMissingPresentationError` keeps a coded 404 like `unknown_search` out of it). Both retries re-send the SAME `operationId`, so the pane-side dedup makes them safe; both retry exactly ONCE and then surface the wake-PowerPoint blocker — `push` by saving the rendered `.pptx` next to the deck rather than throwing the bytes away, `insert-slide` by naming the click and the window-free `add-slide` alternative.
151
207
 
152
- **The design truth lives in the add-in, not the CLI.** The `.pptx` is rendered server-side over the local bridge (no local exporter), the corporate design is fetched as a bundle, brand imagery comes from the add-in's engine, and slide reuse (extract / insert / splice) executes in the add-in too. So `create`/`build-pptx`/`push`/`ls engines`/`search`/`insert-slide`/`add-slide` all hard-require an **open PowerPoint host with the slidemind add-in and an active corporate design**. The engine-search + slide-reuse wire contract is in `docs/slidemind-cli-connect/11-engine-search-slide-reuse.md`; see `docs/slidemind-cli-connect/` for the rest.
208
+ **The readiness ladder is two ladders.** `bin/slidemind.mjs` authors them once: `backendBlocker(pub)` (paired → every backend unreachable → CLI below the floor) is what render, bundle and the pane-free engine routes ride on, and `paneBlocker(pub)` (no window → not render-ready → pane suspended) governs only push's insert, `insert-slide` and reading an open presentation. `connectionBlocker = backendBlocker ?? paneBlocker` keeps every pre-existing message byte-identical, `doctor` reports the two separately (`authoring` / `host` in `--json`) so an agent stops reading "pane gone" as "cannot work", and `permissions_stale` is reported as a **degradation** next to the authoring ladder — never a rung, because it must not gate render or bundle. `doctor`'s engine-search line reads the same `capabilities.permissionsStale` flag off `/api/cli/readiness`, so `doctor`, `ls engines` and `search` name ONE cause for that one condition instead of three. `ready`'s ladder for a **bound** deck is session → bundle freshness → (informational) engine + pane reachability: with an empty registry it materializes straight over the brand route instead of sitting out the hydration wait, and when a window IS registered the open add-in stays the design source of truth. An unbound deck with no window resolves through `GET /api/cli/brands` (capability `brandsList`, `client.listBrands()`): one design binds automatically, several stop with `ambiguous_brand` naming `--brand <presFP>`. `client.engineReachability({ backends })` is the engine half of both reports — env labels only, never a URL.
153
209
 
154
210
  ## External skill packs (this repo ships none)
155
211
 
@@ -165,7 +221,18 @@ Some decks build from a **template pack** (`mode: "fill-template"` in the pack's
165
221
 
166
222
  A pack that declares no `components.canonical` fails loudly in `layoutNumber()` — returning null instead would silently demote every master-backed slide to freeform and build a deck that quietly lost its template.
167
223
 
168
- Packs resolve through `locateSkillDir()` (`src/builders/resolve-skill.mjs`): `$SLIDEMIND_SKILLS_DIR/<name>` → `~/.config/slidemind/skills/<name>` → `<package>/skills/<name>` → the **harness** skill and plugin dirs (`~/.claude`, `~/.codex`, opencode; both `<name>` and `slidemind-<name>`). That last tier is what makes every distribution channel work — a plugin or admin upload lands the pack in a harness directory, never in ours — and it ranks *after* the package so this CLI's own skills are never shadowed by a stale copy.
224
+ The preferred integration is explicit: `slidemind build-pptx <deck> --pack <exact-directory>`.
225
+ The pack directory is resolved by its owning plugin, so the CLI does not need to
226
+ know the plugin name or any harness cache layout. Pack-owned validation can use
227
+ `slidemind inspect-template-deck <deck> --pack <exact-directory> --json`, which
228
+ returns a normalized sequence without running domain-specific rules.
229
+
230
+ For compatibility, direct builds still resolve through `locateSkillDir()`
231
+ (`src/builders/resolve-skill.mjs`): `$SLIDEMIND_SKILLS_DIR/<name>` →
232
+ `~/.config/slidemind/skills/<name>` → `<package>/skills/<name>` → the **harness**
233
+ skill and plugin dirs (`~/.claude`, `~/.codex`, opencode; both `<name>` and
234
+ `slidemind-<name>`). This fallback remains until external packs migrate to
235
+ explicit paths.
169
236
 
170
237
  Pack-dependent integration tests belong in the pack's own repo, not here.
171
238
 
package/README.md CHANGED
@@ -21,6 +21,8 @@ Both drive the same add-in bridge, so an agent and a human end up producing the
21
21
 
22
22
  - [Requirements](#requirements)
23
23
  - [Install](#install)
24
+ - [One command (recommended)](#one-command-recommended)
25
+ - [Manual install](#manual-install)
24
26
  - [Windows](#windows)
25
27
  - [macOS](#macos)
26
28
  - [Linux](#linux)
@@ -47,19 +49,45 @@ Both drive the same add-in bridge, so an agent and a human end up producing the
47
49
  | **PowerPoint** | Microsoft 365, PowerPoint 2021/2019/2016, or PowerPoint on the web — anything that loads Office Add-ins. |
48
50
  | **OS** | Windows, macOS, or Linux. See per-OS notes below. |
49
51
 
50
- The CLI reaches PowerPoint through the add-in's **cloud relay** (no localhost, no certificates). Because of that, the machine running the CLI **does not have to be the same machine running PowerPoint** — pair once and commands route to wherever your add-in is registered.
52
+ The CLI reaches PowerPoint through the add-in's **cloud relay** (no localhost, no certificates). Because of that, the machine running the CLI **does not have to be the same machine running PowerPoint** — connect it once and commands route to wherever your add-in is registered.
51
53
 
52
- Commands that read the design, render, push, or reach an engine (`ready`, `download-bundle`, `build-pptx`, `push`, `ls engines`, `search`, `insert-slide`, `add-slide`) **require an open PowerPoint host with the add-in and an active corporate design.** `build`, `review`, and `view-draft` work fully offline against a previously materialized bundle. Reading a local PowerPoint file (`read <file.pptx>`) or folding a slide from one into a deck (`add-slide --from <file.pptx>`) is host-free too — no PowerPoint, no pairing, no bundle needed. `new` scaffolds offline too; when you're paired and a design is open it also best-effort binds the new deck (otherwise it just scaffolds and hints to run `slidemind ready <slug>`).
54
+ Commands that read the design, render, push, or reach an engine (`ready`, `download-bundle`, `build-pptx`, `push`, `ls engines`, `search`, `insert-slide`, `add-slide`) **require an open PowerPoint host with the add-in and an active corporate design.** `build`, `review`, and `view-draft` work fully offline against a previously materialized bundle. Reading a local PowerPoint file (`read <file.pptx>`) or folding a slide from one into a deck (`add-slide --from <file.pptx>`) is host-free too — no PowerPoint, connection, or bundle needed. `new` scaffolds offline too; when you're connected and a design is open it also best-effort binds the new deck (otherwise it just scaffolds and hints to run `slidemind ready <slug>`).
53
55
 
54
56
  ---
55
57
 
56
58
  ## Install
57
59
 
58
- The package is published to **public npm** as [`slidemind`](https://www.npmjs.com/package/slidemind). The same two commands work on every platform:
60
+ ### One command (recommended)
61
+
62
+ In PowerPoint, open the **slidemind add-in** → **Settings → General → Connect CLI** → **Set up CLI**, and copy the command it shows. Paste it into your terminal:
63
+
64
+ ```bash
65
+ npx --yes slidemind@latest setup smc1_…
66
+ ```
67
+
68
+ That single command installs slidemind globally, connects it to your account, deploys the skills into every coding agent it finds on this machine, and runs the first readiness check. **There is no `slidemind init` step** — setup detects Claude Code, Codex, and opencode itself (by their config directory *or* their command on your `PATH`, so a freshly installed agent you have not opened yet still counts), and skips any harness whose slidemind plugin already supplies the skills. The only prerequisite is **Node 18+**; you never type a backend address.
69
+
70
+ If it reports *no coding agent found* — or you install one later — run `slidemind init --for auto` to deploy the skills then.
71
+
72
+ The copied command carries a one-time claim that works once and expires after about 10 minutes. Copy a fresh one if it lapses.
73
+
74
+ Flags, if you need them: `--for <claude|codex|opencode|all|auto|none>` overrides harness detection (`auto` is the default; `none` skips skills entirely), `--no-install` skips the global npm install, `--no-ready` skips the closing readiness check.
75
+
76
+ ### Manual install
77
+
78
+ If your organization distributes the Codex plugin through the admin console, the skills are already present and you only install the CLI binary:
59
79
 
60
80
  ```bash
61
81
  npm install -g slidemind
62
- slidemind init --for all # deploy the skill into Claude Code / Codex / opencode
82
+ ```
83
+
84
+ Do not run `slidemind init` for an admin- or plugin-installed skill; that would create a second copy. The package is published to **public npm** as [`slidemind`](https://www.npmjs.com/package/slidemind).
85
+
86
+ For a standalone/manual install, add the skills after installing the CLI:
87
+
88
+ ```bash
89
+ npm install -g slidemind
90
+ slidemind init --for auto # deploy the skill into every coding agent found here
63
91
  ```
64
92
 
65
93
  Then confirm it's on your `PATH`:
@@ -68,7 +96,7 @@ Then confirm it's on your `PATH`:
68
96
  slidemind --version
69
97
  ```
70
98
 
71
- `slidemind init --for <claude|codex|opencode|all|none>` scopes the harness deployment. Use `none` to install the CLI only.
99
+ `slidemind init --for <claude|codex|opencode|all|auto>` scopes the harness deployment; `auto` picks every coding agent found on this machine. You only need `init` if you installed the CLI by hand or added a new coding agent later — the one-command setup above already does it.
72
100
 
73
101
  > **Heads-up — first install downloads a headless Chrome.** slidemind renders decks by capturing slides with a local headless browser (then assembling the `.pptx` server-side), so `npm install -g slidemind` pulls a pinned Chromium (~150–300 MB) via `puppeteer`'s postinstall. Behind a corporate proxy/firewall this download can fail; set `HTTPS_PROXY` (and, if needed, `PUPPETEER_DOWNLOAD_BASE_URL`) so npm can reach it, or point `PUPPETEER_EXECUTABLE_PATH` at an existing Chrome/Edge. The browser lives in puppeteer's own cache, not the slidemind package.
74
102
 
@@ -81,7 +109,7 @@ slidemind runs on native Windows (PowerShell, Windows Terminal, or cmd) — no W
81
109
 
82
110
  ```powershell
83
111
  npm install -g slidemind
84
- slidemind init --for all
112
+ slidemind init --for auto
85
113
  slidemind --version
86
114
  ```
87
115
 
@@ -96,7 +124,7 @@ The global install lands in `%APPDATA%\npm`, which the Node installer puts on yo
96
124
 
97
125
  ```bash
98
126
  npm install -g slidemind
99
- slidemind init --for all
127
+ slidemind init --for auto
100
128
  slidemind --version
101
129
  ```
102
130
 
@@ -108,7 +136,7 @@ npm config set prefix ~/.npm-global
108
136
  echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc
109
137
  source ~/.zshrc
110
138
  npm install -g slidemind
111
- slidemind init --for all
139
+ slidemind init --for auto
112
140
  ```
113
141
 
114
142
  Credentials are stored under `~/.config/slidemind/`.
@@ -119,7 +147,7 @@ The CLI runs fine on Linux. There's no PowerPoint desktop on Linux, so you'll co
119
147
 
120
148
  ```bash
121
149
  npm install -g slidemind
122
- slidemind init --for all
150
+ slidemind init --for auto
123
151
  slidemind --version
124
152
  ```
125
153
 
@@ -133,6 +161,8 @@ Run any command without installing globally:
133
161
  npx slidemind <command>
134
162
  ```
135
163
 
164
+ Note that npx only *runs* the package from its cache — it never installs it. That is why the one-command setup above goes through `npx --yes slidemind@latest setup …`: the bootstrap runs from the cache and then performs the persistent `npm install -g` itself.
165
+
136
166
  ### Install as a plugin (Claude Code / Codex)
137
167
 
138
168
  Both harnesses can install slidemind as a **plugin** instead of the two-command npm flow.
@@ -165,25 +195,34 @@ Codex plugins carry the skills only — the CLI still comes from `npm install -g
165
195
 
166
196
  ## Connect to PowerPoint
167
197
 
168
- The CLI talks to PowerPoint through the add-in's cloud relay, so you pair once per machine.
198
+ Connecting starts **in PowerPoint**, because that is where slidemind already knows both who you are and which slidemind deployment you belong to. A freshly installed CLI knows neither — every organization runs its own backend, so there is no address it could guess.
169
199
 
170
- 1. In PowerPoint, open the **slidemind add-in** task pane → **Settings → General → Connect CLI**, and press **Pair**.
171
- 2. It shows a one-time command (it expires in ~10 min — press **Pair** again for a fresh one). Copy and run it:
200
+ ### Copy one command (recommended)
172
201
 
173
- ```bash
174
- slidemind pair <code>
175
- ```
202
+ 1. In PowerPoint, open the **slidemind add-in** task pane → **Settings → General → Connect CLI** → **Set up CLI**.
203
+ 2. Press **Copy command** and paste it into your terminal.
204
+ 3. Done. The add-in flips to *Connected* on its own, and the CLI continues into its readiness check — no add-in restart, no backend URL, nothing else to confirm.
176
205
 
177
- 3. **Restart the add-in once.** Pairing turns CLI integration on, but the task pane that's already running may not pick up the connection — so close the slidemind task pane and reopen it from the ribbon (if needed, reopen the presentation). The wizard doesn't prompt for this, but a freshly-booted pane is what registers your window with the CLI.
206
+ This is the same command shown under [Install](#one-command-recommended): it works whether or not slidemind is already installed, and re-running it later connects an additional machine.
178
207
 
179
- 4. Verify the link:
208
+ ### Already installed?
180
209
 
181
- ```bash
182
- slidemind whoami # lists the paired environment(s)
183
- slidemind presentations # lists open PowerPoint windows the add-in sees
184
- ```
210
+ Same panel, same claim — press **CLI already installed?** and it swaps the copied line to the short form, skipping the npx bootstrap:
211
+
212
+ ```bash
213
+ slidemind setup smc1_…
214
+ ```
215
+
216
+ It does exactly the same work: connect, refresh the skills, run `ready`. Add `--no-install --for none` if you want the connection alone and nothing touched.
217
+
218
+ Either way, verify with:
219
+
220
+ ```bash
221
+ slidemind whoami # lists connected environment(s)
222
+ slidemind presentations # lists open PowerPoint windows the add-in sees
223
+ ```
185
224
 
186
- If `slidemind presentations` is empty even though PowerPoint is open with the add-in and an active corporate design, restart the add-in (step 3) and retry.
225
+ A setup command works once and expires after about 10 minutes; copy a fresh one from the add-in if that happens.
187
226
 
188
227
  ```bash
189
228
  slidemind logout # unpair this machine
@@ -199,6 +238,7 @@ slidemind new my-deck # scaffold ./decks/my-deck/ (auto-binds to the
199
238
  slidemind build my-deck # build a self-contained HTML preview (offline)
200
239
  slidemind review my-deck # spatial preview review: leave comments / approve in the browser (offline)
201
240
  slidemind build-pptx my-deck # render a native .pptx via the add-in (host required)
241
+ # template packs may pass --pack <exact-pack-directory>
202
242
  slidemind push my-deck # stream slides straight into an open PowerPoint (host required)
203
243
  slidemind read <presId|file.pptx> # read an open presentation (host required) or a local .pptx on disk (host-free)
204
244
  slidemind ls engines # list the active design's image + slide engines (host required)
@@ -240,6 +280,9 @@ slidemind plan <deck> Plan sign-off gate on <deck>/plan.md; blocks fo
240
280
  slidemind build <deck> Build a self-contained HTML preview (offline)
241
281
  slidemind review <deck> Spatial preview review; blocks for approve/comments (offline)
242
282
  slidemind build-pptx <deck> Render a native .pptx via the add-in (host required)
283
+ --pack <dir> for an explicit fill-template pack
284
+ slidemind inspect-template-deck <deck> Emit a normalized template-deck model for pack validation
285
+ --pack <dir> --json [--allow-unrendered-freeform]
243
286
  slidemind view-draft <deck> Render slides to per-slide PNGs, no push — look before review (offline once cached)
244
287
  --to <presId> --out <dir> --open
245
288
  slidemind push <deck> Build + push slides into an open PowerPoint (host required)
@@ -259,11 +302,14 @@ slidemind download-bundle [deck] Materialize the active corporate design locally
259
302
  slidemind presentations List PowerPoint windows registered with the add-in
260
303
  slidemind read [presId|file.pptx] Read an open presentation (presId; host required) or a local .pptx on disk (file path; host-free)
261
304
  --mode summary|raw (default raw) [--to <presId>] [--json]
262
- slidemind pair <code> Pair with an add-in (copy the code from "Connect CLI")
263
- slidemind whoami Show paired environment(s)
305
+ slidemind setup <claim> One-command onboarding: connect + global install + skills + ready
306
+ --for <target> --no-install --no-ready --json
307
+ slidemind whoami Show connected environment(s)
264
308
  slidemind use <url|env> Set the default environment
265
309
  slidemind logout [url|env] Unpair an environment (--all unpairs every one)
266
310
  slidemind init --for <target> Install the skill into a harness (clears the bundle cache)
311
+ <target> = claude | codex | opencode | all | auto (every harness found here)
312
+ Not needed after `setup` — only when adding a coding agent later
267
313
  slidemind uninstall --for <t> Remove a previously-installed skill (clears the bundle cache)
268
314
  slidemind update [--for <t>] Fetch the latest release and redeploy
269
315
  slidemind --help Full usage
@@ -309,20 +355,20 @@ slidemind push my-deck --slides 02,05,07 # push only a subset of source slides
309
355
 
310
356
  ## Multiple environments (for slidemind developers)
311
357
 
312
- If you run the add-in against more than one backend (local / dev / prod), the CLI is **multi-environment**: pair once per backend and every command automatically discovers your open PowerPoint across all of them, tags each window with its environment, and routes to the right one — no manual switching.
358
+ If you run the add-in against more than one backend (local / dev / prod), the CLI is **multi-environment**: connect once per backend and every command automatically discovers your open PowerPoint across all of them, tags each window with its environment, and routes to the right one — no manual switching.
313
359
 
314
360
  ```bash
315
- slidemind pair <local-code> --label local
316
- slidemind pair <dev-code> --label dev
317
- slidemind whoami # lists every paired environment (* = default)
361
+ slidemind setup <claim-from-local-add-in> --no-install --for none # each claim carries its own backend
362
+ slidemind setup <claim-from-dev-add-in> --no-install --for none
363
+ slidemind whoami # lists every connected environment (* = default)
318
364
  slidemind presentations # windows from all environments, each tagged [env]
319
365
  slidemind push my-deck --to <presId> # routed to whichever environment owns that window
320
366
  slidemind use dev # set the default environment
321
- slidemind logout dev # unpair one (or --all to unpair every one)
367
+ slidemind logout dev # disconnect one (or --all to disconnect every one)
322
368
  slidemind --backend local presentations # scope a single command to one environment
323
369
  ```
324
370
 
325
- Each "Connect CLI" code carries its own backend and session token, so pairing is per-environment and routing is automatic. A normal user just pairs one.
371
+ `setup` is the easiest way to add an environment because the claim carries its backend — that is exactly the fact the CLI cannot otherwise know. `--no-install --for none` keeps it to the connection alone, leaving your existing binary and skills untouched. Because the claim carries the backend, there is no environment to select and no URL to configure — the CLI hardcodes no backend at all. Once connected, sessions stay per-environment and routing is automatic. A normal user connects one environment.
326
372
 
327
373
  ---
328
374
 
@@ -334,7 +380,7 @@ slidemind update --ref 0.1.0 # pin a specific version
334
380
  slidemind update --for codex # redeploy into one harness (--for none to skip)
335
381
  ```
336
382
 
337
- Equivalently: `npm install -g slidemind@latest && slidemind init --for all`.
383
+ Equivalently: `npm install -g slidemind@latest && slidemind init --for auto`.
338
384
 
339
385
  ---
340
386
 
@@ -344,9 +390,11 @@ Equivalently: `npm install -g slidemind@latest && slidemind init --for all`.
344
390
  |---|---|
345
391
  | `slidemind: command not found` (or not recognized) | The npm global bin isn't on your `PATH`. Run `npm prefix -g` and add its `bin` (Windows: `%APPDATA%\npm`) to `PATH`, or use `npx slidemind`. |
346
392
  | PowerShell: *running scripts is disabled* | npm's `.ps1` shim hit the execution policy. Use `slidemind.cmd <command>`, or `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`. |
347
- | A command can't reach PowerPoint (empty `presentations`, "no host", nothing seems connected) | Run **`slidemind ready`** — it checks pairing, the connection, the CLI version, and open windows in one shot and prints the single next step to take (open PowerPoint / click the pane / pair / update). |
348
- | `slidemind presentations` is empty right after pairing (PowerPoint + add-in already open) | The just-paired task pane never registered. **Restart the add-in** — close the slidemind task pane and reopen it from the ribbon (or reopen the presentation). The pairing wizard doesn't prompt for this. |
349
- | `Not paired` | In the add-in, open **Settings → General → Connect CLI**, press **Pair**, and run the shown `slidemind pair <code>`. Codes are one-time and expire — generate a fresh one if it's stale. |
393
+ | A command can't reach PowerPoint (empty `presentations`, "no host", nothing seems connected) | Run **`slidemind ready`** — it checks the secure connection, backend, CLI version, and open windows in one shot and prints the single next step to take. |
394
+ | `slidemind presentations` is empty immediately after approval | Bring PowerPoint forward and click the slidemind pane once; its authenticated relay reconnects and registers automatically. Reopen the pane only if the Office webview itself is suspended. |
395
+ | `Not connected` / `not_connected` | In **PowerPoint → slidemind → Settings → General → Connect CLI**, press the link button and run the command it shows. |
396
+ | `this setup command has already been used or has expired` | A setup claim works exactly once and lasts ~10 minutes. Copy a fresh one from **Connect CLI → Set up CLI**. |
397
+ | `this slidemind add-in is too old for one-command setup` | That deployment predates the setup route and must be updated before this CLI can connect to it. |
350
398
  | `build-pptx` / `push` / `search` error about no host | These require an open PowerPoint host with an active corporate design. `slidemind build` (HTML) is the only fully-offline preview. |
351
399
  | `EACCES` on `npm install -g` (macOS/Linux) | Don't `sudo npm`. Use a user-owned Node via [nvm](https://github.com/nvm-sh/nvm) or Homebrew, or run `mkdir -p ~/.npm-global && npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to `PATH`, then retry. |
352
400
 
Binary file