ToolsEnabled Slides
Officialby ToolsEnabled
README.md
# ToolsEnabled Slides
Build and edit real PowerPoint presentations from an MCP host while you watch in a local browser. Slides keeps one editable deck model, a live studio, object history, slide locks, and human pause, resume, undo and redo controls.
The MCP host supplies the agent. Slides makes no model calls and has no account, API key, or online service requirement.
New decks use a clean white theme with Arial headings and body text, a blue accent, generous margins and explicit bullet glyphs. Per-element font, color and position settings override the defaults. Imported slides retain their original design.
## Install and start
**Linux tested; native Windows not yet supported.** This release is scoped to Linux. Native Windows qualification found that normal shutdown leaves the workspace lease behind, preventing a second session. Windows renderer/setup fixes and native macOS/Desktop qualification are pending.
Requirements: Node.js 22 or newer, Python 3.10 or newer, and the Python packages in `requirements.txt`. PDF and PNG on Linux also require LibreOffice Impress. PNG conversion through LibreOffice uses the pinned pypdfium2 wheel.
Works with Claude Code on Linux through the `toolsenabled-slides` plugin; the repository is its own plugin marketplace for Claude Code (`.claude-plugin/marketplace.json`) and Codex (`.agents/plugins/marketplace.json`). See [plugin installation](docs/CLAUDE-INSTALL.md) for the install commands and the explicit offline setup of an external CPython 3.12 venv from the Linux wheel bundle, which was published with 0.1.0 and is unchanged for 0.1.9: [toolsenabled-slides-0.1.0-cp312-linux-x86_64-wheels.zip](https://github.com/ToolsEnabled/toolsenabled-slides/releases/download/v0.1.0/toolsenabled-slides-0.1.0-cp312-linux-x86_64-wheels.zip), SHA-256 `a29454931420b8d9547eeb8d17c389a005cf0343a927d7a275f15eb3cab25fec`. No Claude Desktop bundle (`.mcpb`) is distributed with this release; `manifest.json` is an MCPB manifest kept for future Desktop qualification. The source ZIP contains no wheels or copied venv. ToolsEnabled is not affiliated with or endorsed by Anthropic. [Privacy](https://toolsenabled.ai/privacy/) · [Support](mailto:support@toolsenabled.ai).
Download the source ZIP and its `.sha256` file from the [v0.1.9 release](https://github.com/ToolsEnabled/toolsenabled-slides/releases/tag/v0.1.9), verify the ZIP, and extract it (it unpacks to `slides/`) into a directory you own. On Linux:
```sh
curl -LO https://github.com/ToolsEnabled/toolsenabled-slides/releases/download/v0.1.9/toolsenabled-slides-0.1.9.zip
curl -LO https://github.com/ToolsEnabled/toolsenabled-slides/releases/download/v0.1.9/toolsenabled-slides-0.1.9.zip.sha256
sha256sum -c toolsenabled-slides-0.1.9.zip.sha256
unzip toolsenabled-slides-0.1.9.zip && cd slides
python3 -m venv .venv
.venv/bin/python -m pip install --require-hashes -r requirements.txt
node src/cli/doctor.js
```
Install LibreOffice with `sudo apt-get install libreoffice-impress` on Ubuntu. Set `SLIDES_SOFFICE` to the executable if it is outside PATH. Doctor reports the selected renderer and missing prerequisites, and prints install commands only for what is missing. Nothing installs itself at startup. Helper executables are resolved to absolute paths outside the workspace, with an explicit install-directory working directory. Python prerequisite probes use isolated mode.
Plugin route, which needs the external runtime from [docs/CLAUDE-INSTALL.md](docs/CLAUDE-INSTALL.md) and Node.js 22 or newer on the PATH that Claude Code runs with: in Claude Code, `claude plugin marketplace add ToolsEnabled/toolsenabled-slides`, then install it with the four settings it requires (the paths are examples): `claude plugin install -s local toolsenabled-slides@toolsenabled-slides --config python_executable="/absolute/private/Slides Runtime/bin/python" --config node_executable=/absolute/node --config workspace_directory="/absolute/decks/Project Update" --config port=4599`. Claude Code starts the MCP server as `node ${CLAUDE_PLUGIN_ROOT}/slides-mcp.js` and passes the settings to it as environment variables; `node_executable` is the Node.js that the `/slides` panes run. Without the Python and workspace settings the plugin installs but starts no server. The install then prints "2 userConfig options not yet set — run /plugin configure … or pass --config KEY=VALUE." This is expected: the two are the optional `renderer` (default `auto`) and `libreoffice_executable` (default empty, which finds LibreOffice on the PATH). Claude Code counts every option you have not saved a value for, even one with a default, and starts the server with the defaults; nothing else is needed. In Codex, run `codex plugin marketplace add ToolsEnabled/toolsenabled-slides`, then install ToolsEnabled Slides from the toolsenabled-slides marketplace in Codex's `/plugins` browser.
Start the stdio MCP server with one command:
```sh
node slides-mcp.js
```
The server creates a private workspace at `.slides-workspace` in the current directory, starts the local suite, and prints its studio address to stderr. MCP messages alone use stdout. Open the one-time dashboard URL printed at startup to watch and control editing. A bare `/studio` page can display the deck, but does not authorize human controls. In Claude Code, the human finds startup stderr at `~/.cache/claude-cli-nodejs/<cwd-slug>/mcp-logs-plugin-toolsenabled-slides-slides/<timestamp>.jsonl` (XDG settings may change the base), or in a private absolute `--debug-file` they select. The log's mode depends on the host and your umask (Claude Code 2.1.296 wrote it as mode 644 under umask 022, readable by every local account), and same-user agent file tools can read an unused link whatever its mode: open the link promptly, before assigning agent work, and never ask the agent to retrieve it.
For a persistent studio that outlives individual MCP sessions, set `SLIDES_WORKSPACE` and run `node src/cli/studio.js`. MCP clients with the same workspace and port attach to it. Clients that attach leave the server running on exit. On Linux, a suite started by an MCP client exits with that owning client, including abrupt termination, through a private lifetime pipe; attached clients then need to reconnect. If a launch link expires or a dashboard tab loses its session, stop and restart the owning client or persistent studio to receive a fresh launch URL. Saved workspace edits remain.
## Try it
No account or API key is needed: Slides runs on your computer and makes no model calls. You need Node.js 22 or newer on the PATH, CPython 3.12 and the verified 0.1.0 wheel bundle extracted to `/absolute/downloads/cp312-linux-x86_64` (see [plugin installation](docs/CLAUDE-INSTALL.md)). From the folder where you will start `claude`, prepare the runtime from the extracted release ZIP at `/absolute/slides`, make a workspace folder and install the plugin with its four settings:
```sh
mkdir -p /absolute/private "/absolute/decks/Project Update"
python3.12 /absolute/slides/tools/setup-runtime.py --runtime "/absolute/private/Slides Runtime" --wheels "/absolute/downloads/cp312-linux-x86_64" --pip-wheel "/absolute/downloads/cp312-linux-x86_64/pip-24.3.1-py3-none-any.whl"
claude plugin marketplace add ToolsEnabled/toolsenabled-slides
claude plugin install -s local toolsenabled-slides@toolsenabled-slides --config python_executable="/absolute/private/Slides Runtime/bin/python" --config node_executable=/absolute/node --config workspace_directory="/absolute/decks/Project Update" --config port=4599
```
Start `claude` there, open the one-time studio link from its MCP log to watch the deck (see above), approve each Slides tool call when asked, and try these three prompts:
1. `Show me the deck.` Claude calls `ppt_show`: "Untitled Presentation" at revision 0, with one title slide, `s1`.
2. `Add a slide titled "Quarterly results" with the bullets "Revenue up 12%", "Two new customers" and "Next: hiring".` Claude locks `s1` (adding a slide changes the whole deck), adds the slide, locks it and sets the three bullets: two slides at revision 2, and the studio shows the new slide.
3. `Export the deck as quarterly-results.pptx.` `ppt_export` writes `quarterly-results.pptx`, a two-slide PowerPoint file, in the workspace folder. PDF and PNG export also need LibreOffice.
## What this plugin runs, sends and reads
This covers the Claude Code plugin in this repository: the MCP server that `.mcp.json` starts and the mod in `hooks/register.tsx` that adds the `/slides` panes. Slides has no account, telemetry or update check. It opens no network connection except to its own server on 127.0.0.1, and it sends nothing to ToolsEnabled.
### MCP server
- **Command.** Claude Code runs `node ${CLAUDE_PLUGIN_ROOT}/slides-mcp.js` with no other arguments. `node` comes from the PATH that Claude Code runs with and must be Node.js 22 or newer. The settings arrive as environment variables: `SLIDES_PLUGIN_MODE=1`, `SLIDES_WORKSPACE` (`workspace_directory`), `SUITE_PYTHON` (`python_executable`), `SUITE_PORT` (`port`), `SLIDES_RENDERER` (`renderer`), `SLIDES_SOFFICE` (`libreoffice_executable`), and fixed values for the allowed origins and the HTTP timeouts.
- **Checks before anything is created.** The workspace must be an absolute path outside the plugin cache. The configured Python runs `src/python/runtime_contract.py`, which requires a CPython 3.12 venv outside the plugin and the workspace, a `slides-runtime.json` receipt that matches this release's `requirements.txt`, the locked package versions, and a Node.js 22 or newer that is outside the workspace and the plugin cache. If a check fails, the server prints the reason to stderr and exits.
- **Programs it starts.** The local suite, `node src/server.js`, which listens on 127.0.0.1 at the configured port and serves the studio. The configured Python, running the plugin's own scripts in `src/python/` to build the PPTX, import a deck and read shape details from it, check fonts, prepare render copies and turn PDF pages into PNG. LibreOffice `soffice` (the configured path, or `soffice` on PATH): `soffice --version` to detect it, and a headless conversion to PDF with a new private profile in a temporary folder inside the workspace, for PDF and PNG exports and for the studio thumbnails that are rendered at startup and after edits. Nothing is downloaded or installed at launch. The install commands that `src/cli/doctor.js` and some error messages print are advice for you; Slides never runs them.
- **What it reads and writes.** It reads the workspace (deck files, the images and videos you put in `assets/`, and its own state in `.slides-state/`), the plugin's files, the runtime receipt and the variables above, and it writes only in the workspace. LibreOffice and the system libraries it loads also keep their usual caches in your home directory, such as fontconfig and dconf under `~/.cache`.
- **What it sends, and where.** Tool results (slide text, IDs, lint findings, export paths) go to Claude Code over stdio, and Claude Code may send them to its model provider under its own terms. The studio and its data go only to a browser on this machine, at the path `/studio` on 127.0.0.1 and the configured port, and human controls need the one-time launch link. Startup messages, including that link, go to stderr, which Claude Code keeps in its MCP log file. Decks with external links are refused before import and rendering, so rendering fetches nothing.
- **Tool annotations.** Every one of the 37 MCP tools declares a title and the `readOnlyHint`, `destructiveHint`, `idempotentHint` and `openWorldHint` annotations: 8 tools only read, the other 29 change the deck, board, locks, tasks or workspace files and are marked destructive (conservatively for the additive ones, see docs/MCP.md), and none reaches beyond this computer.
- **Environment.** The server passes its environment on to the programs it starts. Slides itself reads only its own `SLIDES_*` and `SUITE_*` variables, PATH (to find programs), NO_COLOR and, on Windows, SystemRoot, and it sends none of them anywhere.
### The `/slides` mod
`hooks/register.tsx` adds one command, `/slides`, which opens a read-only pane. It changes no permission, setting, agent or other command. It handles five events:
| Event | What the handler does |
| --- | --- |
| `session.start` | Clears the pane's state, registers the `/slides` command with `$.command.register`, then passes the event on unchanged with `return next(e)`. |
| `session.end` | Clears the pane's state and passes the event on unchanged. |
| `ui.close`, for its own pane `slides-view` only | Clears the pane's state and passes the event on unchanged. `ui.close` is also the name of a call: the mod calls `$.ui.close` on its own pane when you press `q` or Close. |
| `command.run`, for the `slides` command only | Opens the pane and loads the requested view. As that command's handler it returns its own empty result, so nothing from the workspace enters the transcript or the model's context. |
| `ui.render`, for its own pane only | Draws the pane. |
**Programs it starts.** The mod runs two programs, both with the Node.js you configured: `src/cli/view.js`, to read the view you open, and `src/cli/doctor.js`, to probe the renderer, only when you press `v` in the status view. Each view load (opening `/slides`, paging, reload, home, help and the view filters) runs this through `$.process.run`, with the plugin folder as the working directory and a 7-second limit:
```
/usr/bin/env -i -- PATH=… HOME=… LANG=… SLIDES_WORKSPACE=… SUITE_PYTHON=… SUITE_PORT=… SLIDES_RENDERER=… SLIDES_SOFFICE=… <node_executable> --max-old-space-size=384 <plugin>/src/cli/view.js <view> [<selector>] --json --offset <n> --limit <n> [--all] [--revision <hash>]
```
Pressing `v` in the status view, and nothing else, runs the renderer probe with a 45-second limit:
```
/usr/bin/env -i -- PATH=… HOME=… LANG=… SLIDES_PLUGIN_MODE=1 SLIDES_WORKSPACE=… SUITE_PYTHON=… SLIDES_RENDERER=… SLIDES_SOFFICE=… <node_executable> <plugin>/src/cli/doctor.js
```
The pane's data comes from the same reader as the command-line views, `src/cli/view.js`, run as a separate Node process with a 384 MB memory cap and a time limit. The mod assembles the command when it runs, because it contains your configured paths and the view you asked for. `env -i` starts the child with an empty environment, so the child receives only the variables written after it: PATH, HOME and LANG, which the mod reads from Claude Code with `$.env.get`, and the plugin settings. `node_executable` must be an absolute path without `=`, and the pane never falls back to `node` on PATH. The probe's `doctor.js` runs the configured Python (the runtime check and the pypdfium2 version) and `soffice --version`.
**What it reads and sends.** `view.js` reads the workspace's saved state: outline, board, tasks, history, export receipts and asset metadata. For the home, slide, status, studio, history and lint views it also asks the running Slides server on `127.0.0.1:<port>` for live state (`GET /api/health`, `/api/state`, `/api/history`, `/api/lint?cached=1`). The pane shows the result in the terminal only. What the mod reads (PATH, HOME, LANG and your plugin settings) goes only to the reader it starts on this computer, and what the reader prints goes only to the pane: the mod sends nothing over the network.
### Tests and the credential checks
The `test/` folder is the repository's test suite; the plugin never runs it. Tests use placeholder hosts such as `evil.example` and `example.invalid` as hostile `Origin` and `Host` values, to prove the local server refuses cross-origin requests, and decks in tests and in `src/python/` contain XML namespace names such as `schemas.openxmlformats.org`, which are part of the PowerPoint file format, not addresses. Names such as `t.test(…)` and `pkg.scripts.test` are JavaScript calls and properties, not hosts. The tests that start the server, the CLI or the MCP launcher in files that name such hosts give the child only the operating-system basics and the suite's own `SUITE_*` and `SLIDES_*` settings (`test/helpers/child-env.js`); the MCP test client, `test/helpers/mcp-client.js`, does the same for every test, and `test/js/test-client-env.test.js` checks it. `test/js/pane-environment.test.js` and `hooks/views.test.ts` deliberately set synthetic values for `ANTHROPIC_API_KEY`, `CLAUDE_CODE_MESSAGING_TOKEN`, `GITHUB_TOKEN` and similar names, to prove that the pane's children never receive them. `src/python/render_pptx.py` reads one variable, `SLIDES_WORKSPACE`. Nothing in this repository reads a real credential or sends one anywhere. The only secrets Slides handles are the dashboard launch link and session token that it creates for its own local dashboard.
The directory's credential check reads a file that spells a remote-looking address beside environment variables, a cookie or a key as a credential that may leave the machine. The local studio's origin (plain HTTP on a loopback address) is therefore built by one helper, `src/lib/origins.js`, so the server, the dashboard session and the `ppt` CLI, which read their own settings and handle the dashboard cookie, spell no address of their own except the fixed loopback origins `http://127.0.0.1:<port>` and `http://localhost:<port>`, the loopback host names 127.0.0.1, localhost and ::1, and `http://localhost` as the base the server parses request paths against; in the tests, the hostile `Host` and `Origin` values of `test/js/security.test.js` are in `test/fixtures/foreign-requests.json`, and the pattern that finds the one-time link in test output is `launchLink` in `test/helpers/dashboard.js`. `test/js/directory-pairs.test.js` pins that layout.
The directory's credential check still pairs two parts of this plugin that have nothing to do with each other: the mod reads PATH, HOME and LANG to pass them to its own reader (above), and the skill lists Codex commands, such as `!node "<plugin>/src/cli/view.js" home --workspace "<ws>" --port <port>`, that you fill in and run yourself and that read only this computer's workspace and its server on 127.0.0.1, so no credential leaves the machine in either part.
The tests start this repository's own programs and talk to them on 127.0.0.1; `tools/generate-release.py` reads its own published release file from GitHub (through `tools/release_fetch.py`) only to compare it with the signed file, and the other tools work offline or on 127.0.0.1: nothing in `test/` or `tools/` downloads a program or runs anything it fetched.
The directory's name check compares the publisher "ToolsEnabled, Inc." and its GitHub organization "ToolsEnabled" with an existing listing called "nabled": this plugin is published by ToolsEnabled, Inc. and is not related to that listing.
## Connect your host
Set `SUITE_PYTHON` to the absolute Python executable in your prepared runtime, then generate the command or configuration for your client:
```sh
node tools/mcp-config.mjs --client claude
node tools/mcp-config.mjs --client codex
node tools/mcp-config.mjs --client cursor
node tools/mcp-config.mjs --client claude-desktop
node tools/mcp-config.mjs --client deepseek
```
The helper prints configuration and does not change host settings. It names Node.js by the PATH entry that runs the current `node` (for example `/usr/local/bin/node`), not the file a version manager links it to, so the entry survives a Node.js upgrade behind that link; the path stays absolute because desktop clients do not start servers with your shell's PATH. Run the helper with the `node` you want the client to use. `SLIDES_WORKSPACE` overrides its default `slides-workspace` directory. Claude Code and Codex output is a registration command; Cursor and Claude Desktop output is an `mcpServers` JSON entry; DeepSeek Harness output is an extension configuration. Restart the host after adding the configuration. Plugin installation for Claude Code and Codex is described in [docs/CLAUDE-INSTALL.md](docs/CLAUDE-INSTALL.md); the registration helper also works independently of plugin support.
Try: “Use Slides to make a three-slide project update. Read the board and outline, lock the slides, then export update.pptx and update.pdf.”
## Work with your deck
Place an existing `.pptx` in the workspace, lock the current slides with `ppt_lock`, and call `ppt_import` with its relative path. Give it any name except `presentation.pptx`: Slides keeps the current deck rendered under that name in the workspace and replaces it after edits. If it finds a `presentation.pptx` it did not write (your own deck with that name, or changes saved over the render in PowerPoint), it first keeps that file as `presentation.user-<time>.pptx` and says so in its log. Import preserves the source file and creates an editable overlay over a private copy. Human undo restores the previous model. External relationships, macro content types, VBA/OLE/ActiveX relationships and elements, and OLE compound-file signatures are refused before import and rendering. Rendered packages are checked again before publication. Embedded workbooks are unsupported, including ordinary Excel-backed charts. Replace those charts with PNG, JPEG or GIF images before import; existing chart image snapshots remain supported. Imported images must be PNG, JPEG or GIF by decoded content and retain their original bytes, quality, metadata and animation after first-frame decoding and GIF/APNG header/frame-metadata checks within the import budgets. Later animation frames stay encoded in the original media and PPTX exports. PNG msOG embedded animation is refused. For PDF and PNG, a private render copy replaces each animated GIF with a PNG of its first frame at the same dimensions and removes APNG animation chunks; the model and original media stay unchanged. SVG, WMF/EMF, PDF images and imported video are refused. Native video can be added from workspace assets. LibreOffice uses a fresh private profile for each conversion.
Use `ppt_show` for IDs and `ppt_board` for pinned presentation guidance. Lock each affected slide before editing; deck-wide changes require every current slide. The studio can protect slides and individual objects. Pause, resume, undo, redo, explicit dashboard lock overrides and dashboard downloads are not available as MCP tools and require the dashboard session. MCP callers can release only their own locks. Raw HTTP clients running as the same user are outside that identity boundary; locks do not isolate processes that already have local filesystem access. Open the one-time launch URL printed at startup; its fragment secret expires after ten minutes. The page exchanges it by POST for an origin-scoped token in sessionStorage and an HttpOnly cookie. Every human control requires the session header as well as the cookie; a cookie alone is refused. Pause refuses editing and explicit plugin exports; board messages and reads remain available. Board prose is workspace guidance and does not override the user or host; deterministic lint checks provide additional feedback.
`ppt_export` creates a new workspace-relative destination:
- `{"path":"update.pptx","format":"pptx"}` produces a PowerPoint file.
- `{"path":"update.pdf","format":"pdf"}` produces a PDF.
- `{"path":"update-pages","format":"png"}` produces one PNG per slide.
Replies include the captured model revision, renderer and output paths. Existing destinations are refused. Create parent directories first. Filesystem roots, traversal, symlinks and private state paths are not accepted. Images and videos added to the deck must already exist in the workspace's `assets/` directory. Files are processed locally.
## Configuration
| Variable | Purpose |
| --- | --- |
| `SLIDES_WORKSPACE` | Absolute workspace directory. Use one per deck. |
| `SUITE_PORT` | Loopback port, default 4599. Use a different port for each simultaneously open workspace. |
| `SUITE_PYTHON` | Absolute prepared external Python executable required in plugin mode; manual direct mode may use the installation's `.venv`. |
| `SLIDES_RENDERER` | Use `auto` or `libreoffice` on Linux. The experimental `powerpoint` path is not supported by this release. |
| `SLIDES_SOFFICE` | Path to LibreOffice's `soffice` executable. |
State and imported originals live in `.slides-state` inside the workspace. Keep that directory with the workspace. Only one suite process may own a workspace; a second process refuses startup before reading its model. After a crash, verify the PID in `.slides-state/server.lock` is gone before removing that file. Slides never steals a lease automatically.
## Limits
- Native object animations and embedded MP4 playback require the experimental PowerPoint COM/pywin32 path, which is outside this Linux release's supported scope. The studio's motion preview approximates those builds. Static decks, transitions, imports and PPTX/PDF/PNG exports use the Linux path. Export reports an error when a deck requires an unavailable renderer capability.
- PDF and PNG are static. Fonts, effects, media and complex imported formatting can differ between LibreOffice and PowerPoint. Inspect exported pages before sharing.
- Import accepts up to 32 MiB, 5,000 ZIP members and 128 MiB of expanded data. Both imported and newly edited decks are limited to 200 slides and a 2 MiB model. MCP requests are limited to 1 MiB, queued work to 64 requests / 4 MiB, and text replies to 60,000 characters.
- If pypdfium2 is missing, PNG thumbnails report why they are unavailable; PPTX and PDF remain usable. Without LibreOffice on Linux, only PPTX export works.
- Human undo/redo and slide claims are in memory. Object history, model, board, pause state and protections are durable. Imported originals are retained so history can refer to them; old originals may consume disk space.
- This is a local, single-user application, not a server for untrusted network clients. Host/Origin checks and path confinement protect its APIs; they do not sandbox a host or user that already has filesystem access. Do not expose the port through a tunnel or proxy.
See [all MCP tools](docs/MCP.md), [test instructions](docs/TESTING.md) and [experimental Windows renderer review](docs/COM-REVIEW.md). Licensed under the [MIT License](LICENSE).
## User commands
Claude Code provides the read-only `/slides` panes (tested with 2.1.296); the bare command opens `home`. They use the configured Node runtime and external workspace without MCP calls, model turns, editor registration, server startup or permission prompts. Use `1` to `8` for details, `n`/`p` to page, `b` to return, `r` to reload, `h` for home, `k` for help, and Esc or `q` to close. Help shows two commands per page with their descriptions and Codex equivalents. Other views show eight records per page. A changed snapshot requires an explicit reload. Detail text is bounded and marks truncation. Status offers a renderer probe only when you press `v`; opening the pane never runs it.
Native action commands start ordinary model work with the usual tool permissions. Type the full `/toolsenabled-slides:slides-…` name: unprefixed action names did not resolve when last checked (2.1.287). Panes never put workspace content into model context. Codex has no plugin slash-command registration; its equivalents below are CLI views and the `$toolsenabled-slides:toolsenabled-slides` skill. A Codex command typed after an exclamation mark runs in a shell, and its output enters the next model turn, so the CLI quotes workspace data and applies the same secret/control filters. This mapping is not native slash-command parity.
In CLI examples, replace `<plugin>` with the absolute installed plugin directory (the parent of `src/`: a version folder under `~/.codex/plugins/cache/toolsenabled-slides/toolsenabled-slides/`), `<ws>` with the configured workspace, and `<port>` with its port. Node and workspace settings are literal arguments. `ppt` is not automatically placed on PATH by plugin installation. Optional selectors in brackets are notation, not literal arguments. For object history, pass three words: `history s1 element e1` or `history s1 decor d1`.
| Claude command | Kind | Result | Codex equivalent |
|---|---|---|---|
| `/slides home` | Pane | Deck outline, revision, pause state, task count and studio guidance. | `!node "<plugin>/src/cli/view.js" home --workspace "<ws>" --port <port>` |
| `/slides slide <number-or-id>` | Pane | Full slide text, media, builds, notes, locks and protections. | `!node "<plugin>/src/cli/view.js" slide <number-or-id> --workspace "<ws>" --port <port>` |
| `/slides notes [number-or-id]` | Pane | Speaker notes in slide order, or one selected slide. | `!node "<plugin>/src/cli/view.js" notes [number-or-id] --workspace "<ws>" --port <port>` |
| `/slides search <text>` | Pane | Literal search across visible text, bullets and speaker notes. | `!node "<plugin>/src/cli/view.js" search <text> --workspace "<ws>" --port <port>` |
| `/slides board` | Pane | Pinned notes and messages with recorded provenance. | `!node "<plugin>/src/cli/view.js" board --workspace "<ws>" --port <port>` |
| `/slides tasks [loops]` | Pane | Open/all task records and grant scope; Loops shows cadence and last run. | `!node "<plugin>/src/cli/view.js" tasks [loops] --workspace "<ws>" --port <port>` |
| `/slides history [undo\|redo\|slide-id element\|decor object-id]` | Pane | Saved activity, live undo/redo history or selected object versions; dashboard-only restore. | `!node "<plugin>/src/cli/view.js" history [undo\|redo\|slide-id element\|decor object-id] --workspace "<ws>" --port <port>` |
| `/slides lint` | Pane | Local quality findings plus existing full lint only when cached for this revision. | `!node "<plugin>/src/cli/view.js" lint --workspace "<ws>" --port <port>` |
| `/slides timing` | Pane | Speaking estimate, total target/budget, transitions and playback. | `!node "<plugin>/src/cli/view.js" timing --workspace "<ws>" --port <port>` |
| `/slides status` | Pane | Configured runtime, live locks/editors, render receipt and explicit renderer probe. | `!node "<plugin>/src/cli/view.js" status --workspace "<ws>" --port <port>` |
| `/slides protections` | Pane | Protected content, exceptions, decision history and task grants. | `!node "<plugin>/src/cli/view.js" protections --workspace "<ws>" --port <port>` |
| `/slides assets` | Pane | Local assets metadata and slide usage; never follows symbolic links. | `!node "<plugin>/src/cli/view.js" assets --workspace "<ws>" --port <port>` |
| `/slides layouts` | Pane | Native and observed layouts, element types, effects and theme accent. | `!node "<plugin>/src/cli/view.js" layouts --workspace "<ws>" --port <port>` |
| `/slides exports` | Pane | Past successful exports with revision, renderer and file receipts. | `!node "<plugin>/src/cli/view.js" exports --workspace "<ws>" --port <port>` |
| `/slides studio` | Pane | Clean studio URL and human-only launch-link instructions; never reads secrets. | `!node "<plugin>/src/cli/view.js" studio --workspace "<ws>" --port <port>` |
| `/slides help` | Pane | Every view and action with its Codex equivalent. | `!node "<plugin>/src/cli/view.js" help` |
| `/toolsenabled-slides:slides-new <brief>` | Action | Build a first presentation from a brief. | `$toolsenabled-slides:toolsenabled-slides new <brief>` |
| `/toolsenabled-slides:slides-add <brief>` | Action | Add requested slides in the current deck style. | `$toolsenabled-slides:toolsenabled-slides add <brief>` |
| `/toolsenabled-slides:slides-edit <slide> <change>` | Action | Make a focused presentation edit and verify it. | `$toolsenabled-slides:toolsenabled-slides edit <slide> <change>` |
| `/toolsenabled-slides:slides-style <instructions>` | Action | Apply requested styles to selected slides. | `$toolsenabled-slides:toolsenabled-slides style <instructions>` |
| `/toolsenabled-slides:slides-import <file.pptx>` | Action | Import a workspace PowerPoint file as the current deck. | `$toolsenabled-slides:toolsenabled-slides import <file.pptx>` |
| `/toolsenabled-slides:slides-preview [slide-or-all]` | Action | Export PNG previews and report the selected pages. | `$toolsenabled-slides:toolsenabled-slides preview [slide-or-all]` |
| `/toolsenabled-slides:slides-export <pptx\|pdf\|png> [path]` | Action | Export a fresh presentation copy. | `$toolsenabled-slides:toolsenabled-slides export <pptx\|pdf\|png> [path]` |
| `/toolsenabled-slides:slides-write-notes <slide\|all> [guidance]` | Action | Write or revise speaker notes. | `$toolsenabled-slides:toolsenabled-slides write-notes <slide\|all> [guidance]` |
| `/toolsenabled-slides:slides-media <slide> <assets/file> [placement]` | Action | Place or update local images and video. | `$toolsenabled-slides:toolsenabled-slides media <slide> <assets/file> [placement]` |
| `/toolsenabled-slides:slides-animate <slide> <instructions>` | Action | Set slide builds and transitions. | `$toolsenabled-slides:toolsenabled-slides animate <slide> <instructions>` |
| `/toolsenabled-slides:slides-fix-lint [slides]` | Action | Resolve relevant quality findings. | `$toolsenabled-slides:toolsenabled-slides fix-lint [slides]` |
| `/toolsenabled-slides:slides-fit <minutes>` | Action | Adjust visible text toward a speaking-time target. | `$toolsenabled-slides:toolsenabled-slides fit <minutes>` |
| `/toolsenabled-slides:slides-task <task-id>` | Action | Carry out a dashboard-assigned task. | `$toolsenabled-slides:toolsenabled-slides task <task-id>` |
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues