- name
- markdstage
- description
- Turn Markdown files into slides and present them in the MarkdStage canvas, or use the MarkdStage CLI to create, validate, inspect, capture, present, and export source-backed decks. Use for requests such as "present slides.md," "present this Markdown," "present @name.md," "use a Microsoft style," "turn this file into slides," "check whether my slides fit," "import an Archify SVG," or "export the deck to PDF or PowerPoint." When the source is prose-heavy, summarize and restructure each page as a heading with bullets. Generate the complete deck once at startup and pass every slide to the open input of canvas ID MarkdStage. Navigation then stays inside the canvas through buttons, arrow keys, the slide list, and Surface Pen on supported Windows systems.
# MarkdStage skill
Create all small Markdown slide fragments at presentation startup and pass them
together in the `slides` field of the canvas `open` input. The first slide is
therefore visible immediately, without a "deck not loaded" placeholder.
After registration, navigation is handled entirely by the canvas controls,
keyboard, and Surface Pen on supported systems. Do not run an `ask_user`
navigation loop. Call `load_deck` only when content or theme changes during a
presentation. Omit open input only to refocus an existing instance. Every
non-empty open input must contain `slides`; `sourceName` is metadata and never
reads or watches the named Markdown file.
## Distribution and installation
This file is an optional skill. The presentation runtime is the extension in
`.github/extensions/markdstage/`, which must be installed first. To install it
from the public repository at user scope, ask Copilot:
> Install the MarkdStage canvas Extension from
> `https://github.com/runceel/markdstage/tree/main/.github/extensions/markdstage`
> at user scope.
For reproducible installation, replace `main` with a release tag such as
`v1.0.0` or a verified commit SHA. The extension executes local code, so review
the diff and tag before installation. Put this skill at
`.github/skills/markdstage/SKILL.md` in a project or copy it to the user's skill
scope. See the repository README and `THIRD-PARTY-NOTICES.md` for ZIP
distribution, Gist single-file limits, and split Mermaid assets.
When only the extension is installed, its bundled `markdstage_guide` tool
provides equivalent slide-format, theme, and Architecture DSL guidance.
Retrieve the required topic before authoring Markdown for the MarkdStage canvas.
## Core principles ⚡
1. **Generate only a small Markdown fragment for each slide.** The extension
handles HTML, CSS, theme, layout, page numbers, and animation through
`marked`. Never generate a complete HTML document.
2. **Generate the full deck once, when presentation is requested,** and pass it
through the `slides` field of `open_canvas` input. Use `load_deck` only for
changes during the presentation. Do not regenerate Markdown on every page.
3. **Leave navigation to the canvas and input devices.** Users navigate with
**◀ / ▶**, arrow keys, the slide list (**☰**), and the Surface Pen tail
button on supported Windows systems. Do not use `ask_user` as a page loop.
A slide should be no larger than this:
```markdown
---
deck: Presentation title
kicker: Section name
page: 2
total: 6
---
## Slide heading
- Bullet **one**
- Bullet two
```
Build an array containing every fragment and pass it to `open_canvas`. The
first slide appears as soon as the canvas opens; canvas controls handle the rest.
### AI-generated decks versus canvas import
The extension also lets users import workspace Markdown directly with
**More controls > Open Markdown**. This deterministic split does not involve AI.
- **Use Open Markdown** when the source already uses slide syntax: pages separated
by `---` after a blank line, with any required front matter. Per-page Slidev
front matter is supported, and initial file front matter is inherited while
`layout: title` applies only to slide one. At import time, users choose
**Keep imported snapshot** (default) or **Update automatically on save**.
Source-backed decks can switch modes from the toolbar and retain the last
valid deck if watching fails.
- **Use this skill to build the deck** when source pages are prose-heavy and
require summarization into headings and bullets, when page division is
unsuitable, or when the requested theme and layout must be applied.
When a user asks AI to present a file, follow this skill and generate the deck.
Open Markdown is a separate user workflow, not an AI shortcut.
## CLI-assisted authoring workflow
For an immediate request to present Markdown in GitHub Copilot, keep using the
Canvas startup procedure below. Use the MarkdStage CLI when the task also needs
a persistent source-backed authoring loop, terminal or CI validation, fixed
16:9 diagnostics, targeted PNG review, or PDF/PowerPoint output. The CLI uses
the same parser, renderer, themes, Architecture DSL, and output pipeline as the
Canvas.
For the browser-based **npm CLI**, run `npx @markdstage/markdstage` or install
`@markdstage/markdstage` globally and use `markdstage`. It requires Node.js 24+
and an installed Chromium-based browser; its behavior is unchanged.
The **packaged Windows CLI** also exposes `markdstage`, without Node.js. Bare
invocation, direct Markdown, `preview`, and `present` activate the installed native
app through the package contract, reusing the window for the canonical workspace.
Bare invocation uses caller CWD with no file selected (an existing workspace shows
its file list, stops its audience window, and retains the deck behind the list).
Relative file and workspace arguments use caller CWD; both CLI and
app validate paths, containment, links, existence, and Markdown extensions.
Direct Markdown/preview open slide view; present opens presenter view and the
native audience window, idempotently on repeated requests. Native `present`
requires a file; only `present --no-open` retains file-less serving.
Native interaction needs WebView2, not external Chromium. `--watch` is accepted
and native Markdown watching is always enabled. `--theme` / `--theme-file` on
native handoff are usage errors: choose the theme in the app or use `--no-open`.
`--no-open` explicitly keeps the existing headless local server running until
Ctrl+C, preserving theme overrides and watch handling.
Packaged interactive commands return `0` only after app acceptance. `--json`
reports `{ok:true,accepted:true,workspace:<absolute>,file:<absolute or null>,mode:"preview"|"present"}`;
the response also includes the actual accepting native `processId` and `windowId`.
Rejection/timeout/activation
failure returns nonzero with `{ok:false,error:"activation_failed",message:...}`.
Do not interpret successful process launch alone as acceptance.
Help/version/guide/skill/validate/inspect/capture/export stay console-only;
inspect/capture/export still require external Chromium. Check which `markdstage`
is resolved when both distributions are installed; `npx` selects npm explicitly.
### Recommended create-review-deliver loop
1. **Establish the brief.** Identify the source material, audience, objective,
approximate slide count or duration, theme, required diagrams, and output
format. Preserve facts and required terminology from the source.
2. **Read only the relevant guidance.** Start with
`markdstage guide slide-format`, then retrieve `themes`, `custom-themes`, or
`architecture-dsl` only when the deck needs them.
3. **Create the complete Markdown deck.** Keep Markdown as the single source of
truth. Separate slides with `---`, use front matter for layouts and themes,
and never hand-write slide HTML or CSS.
4. **Validate before visual review.** Run
`markdstage validate slides.md --json` and fix deck, theme, and Architecture
DSL errors before judging layout.
5. **Use watch mode for live authoring.** Run
`markdstage preview slides.md --watch`, edit the Markdown, and review the
reloaded deck without losing the current slide. For npm or the UI served by
packaged `--no-open`, the browser begins on the
fixed 16:9 output surface in viewing mode; **Output preview** switches to the
retained responsive layout, and the pencil control switches to that layout
while enabling Architecture placement and detailed editing. Native handoff
opens the app in slide view; use its **More controls → Shape editing** for
Architecture editing.
6. **Inspect fixed 16:9 output.** Run
`markdstage inspect slides.md --json`. Use `--slide <n>` after a localized
change and `--fail-on-issues` in CI or other quality gates.
7. **Capture only what needs visual judgment.** Run
`markdstage capture slides.md` to capture clipped slides, or use
`--pages 2,4` for specific pages. Do not capture the whole deck by default;
structured diagnostics are faster and more precise for fit problems.
8. **Revise and repeat targeted checks.** Update Markdown, re-run validation
when structure, themes, or diagrams change, then inspect affected pages.
Repeat until the deck is valid, unclipped, concise, and visually balanced.
9. **Deliver from the same source.** Use
`markdstage present slides.md` for presenter view,
`markdstage export slides.md --output slides.pdf` for PDF, or
`markdstage export slides.md --output slides.pptx` for hybrid editable
PowerPoint.
Use screenshots to assess balance, spacing, or diagram appearance, not as the
primary way to discover structural or clipping errors. Review every final
export before distribution.
## Processing model
```text
Presentation startup (once)
AI -> generate an array of small Markdown fragments for all slides
| open_canvas("MarkdStage", { input: { slides: [...] } })
v
The extension stores the deck during open and displays slide one immediately
Navigation (entirely inside the canvas)
User -> ◀ / ▶, arrow keys, or ☰ slide list
| canvas posts the index to POST /navigate
v
Extension renders the stored fragment with marked, sanitizes it, and applies the theme
| SSE
v
Native canvas iframe updates without agent involvement
```
- Generate and register the complete deck only once; use `load_deck` for
mid-presentation replacement.
- The extension owns rendering, decoration, page numbers, Mermaid, emoji, and
navigation UI. No external server or manually started `localhost` port is
required.
- One deck is displayed at a time and is intended for a single presenter.
- The project-scoped extension lives at `.github/extensions/markdstage/`.
## Main actions
Start by opening the complete deck through `open_canvas` with
`canvasId: "MarkdStage"`. Pass `slides` and optional `index`, `theme`, and
`sourceName` in `input`. `sourceName` must be the source Markdown's
workspace-relative path; it anchors adjacent `assets/`, Markdown-relative
`theme-file` lookup, and the canvas Export PDF control's `<source-name>.pdf` output. It
does not read or watch that file. To refresh after editing Markdown, regenerate
and pass the complete `slides` array or call `load_deck`.
| Action | Purpose |
| --- | --- |
| `load_deck` | Replace or reload the registered deck. Pass `slides`, optional zero-based `index` (default `0`), optional deck theme (`dark`, `light`, `microsoft`, or `custom`; default `dark`), and optional metadata-only `sourceName`. Use only for content or theme changes after startup; `sourceName` never reads or watches Markdown. |
| `goto_slide` | Select a zero-based `index` in the registered deck. Out-of-range values are clamped. Normal navigation does not need this action; use it only for explicit chat requests such as "go to page 3." |
| `show_slide` | Temporarily replace one slide. Use for a one-off display or when no deck is registered, not for normal presentations. The override is included in output snapshots until navigation or deck replacement resumes the registered deck. |
| `get_architecture_errors` | Return Architecture DSL errors for the whole deck or one zero-based `index`. Each error includes `slideIndex`, one-based `page`, `blockIndex`, `architecture`, `code`, and `message`; temporary `show_slide` content is included. |
| `open_presenter` | Open the current deck in a synchronized, movable, resizable 1280×720 Edge / Chrome / Chromium app-mode window. Use browser or OS controls (`F11` on Windows) for full screen. Surface Pen never launches it. |
| `close_presenter` | Close the external presenter window. |
| `inspect_layout` | Check the registered in-memory PDF-equivalent fixed 1280×720 output snapshot before export, including any `show_slide` override. It never reads the source file on disk. It returns clipped pages and pages with Architecture measurements by default, including element bounds, effective font sizes, fitting flags, and diagram scale. Prefer one whole-deck call; serialize targeted calls because output jobs are exclusive. Prefer this action over image analysis. |
| `capture_slides` | Create 1280×720 PNG files only when visual inspection is required. Pass zero-based `indexes`, or omit them to capture only pages found by `inspect_layout`. Optional `outputDirectory` is workspace-relative. The result contains file paths rather than inline image data. |
| `export_pdf` | Export the current deck as a 16:9 PDF. Optional `outputPath` is a workspace-relative `.pdf` path; default is `markdstage.pdf`. Optional `theme` applies only to PDF. The canvas Export PDF control derives a name from `sourceName`. |
| `edit_architecture` | Toggle the lightweight Architecture placement mode for node dragging, keyboard movement, layout detachment, Undo, and Redo. Each operation is saved immediately under the stable placement contract. |
| `reset` | Clear slide and deck state and return to the waiting view. |
`load_deck` and `goto_slide` return `{ ok, version, index, total }`;
`goto_slide` also returns `changed`. For non-scrolling/PDF decks, call
one whole-deck `inspect_layout` after loading or revising slides. If targeted
inspections are necessary, run them serially. Use `capture_slides` only for
pages whose appearance cannot be judged from the layout diagnostics.
`export_pdf` returns `{ ok, path, total, theme, bytes }`. Before PDF export,
reload the complete deck if its source Markdown changed.
### Full Architecture editing
For a source-backed deck, **More controls > Shape editing** opens the separate
`architecture-editor` canvas directly. If a slide has multiple Architecture
blocks, select one from the accessible diagram picker first. Decks without a
source association retain the lightweight placement editor, and agents can
still use `edit_architecture` for that stable placement workflow.
- Users open it through **Shape editing** after importing Markdown with
**More controls > Open Markdown**.
- Agents open canvas ID `"architecture-editor"` with
`input: { sourcePath, blockIndex, theme? }`. `sourcePath` is
workspace-relative and `blockIndex` is zero-based across the Markdown file.
- Changes remain in a draft until the canvas **Save** control or `save` action.
- Context menus on diagram elements, empty space, and the tree support add,
connect, duplicate, delete, front/back ordering, Undo/Redo, and Save.
Group menus provide `none`, `row`, `column`, `grid`, and `layered` layouts.
A child never offers an action that detaches its parent group's layout.
Nodes, groups, and images added from empty space are centered at the context
menu position.
- A bounded shape palette adds rectangles, rounded rectangles, ellipses,
diamonds, triangles, hexagons, and parallelograms without overflowing the
toolbar.
- The primary toolbar keeps Undo, Redo, Shape, Save, and More visible while
secondary add, edit, arrange, view, grid, and reload commands stay under
**More**.
- Drag blank canvas space with the primary button to pan in both directions.
Middle-drag and Space-drag remain available. Move and resize gestures show
live feedback and respect reduced-motion preferences.
- **Elements** and **Properties** are collapsible. Medium windows use nonmodal
docks; narrow windows use nonblocking overlays. Opening a panel transfers
focus to its content, and each panel has a local close control.
- Empty blocks show **Add first shape**. Toolbar additions begin near the
visible canvas center and avoid occupied siblings.
- Keyboard users open the same menu with `Shift+F10` or the Context Menu key,
move with arrows, open a submenu with `ArrowRight`, return with `ArrowLeft`,
execute with Enter/Space, and close with Escape.
- Add a standalone image from the toolbar or an empty-space/group menu. The
inspector's **Select image from assets/** uses the same picker for node icons.
The picker searches Markdown-adjacent then workspace-root `assets/`.
Imported SVG / PNG / WebP / JPG / JPEG files of at most 10 MB are copied to
workspace-root `assets/`. Name collisions become `name-2.ext`. Removing or
undoing a diagram image never deletes the shared asset file.
- External-change conflicts never overwrite the source. To restart from the
file, call `reload` with `{ discard: true }`.
- The editor modifies only existing `architecture` blocks; it does not create
new blocks.
- The dedicated editor is disabled for non-source-backed decks created directly
by `open` / `load_deck`, because they have no safe write-back target.
These workflows do not alter the Architecture DSL v1 grammar or the stable save
contract of the placement editor.
## Markdown file syntax
A Markdown file represents the complete deck. At the top level, a line containing
only `---` after a blank line separates slides. A leading `---` block is file
front matter, and separators inside fenced code blocks are ignored.
Use only top-level `---` slide separators. Do not invent custom separators such
as `<!-- slide -->`.
Do not put a top-level HTML comment immediately before a separator. End the
comment, leave a blank line, and then write `---`; otherwise the line may not be
recognized as a slide boundary.
To have MarkdStage itself read and split a workspace Markdown file, use **More
controls > Open Markdown**. Do not use `sourceName` as a file-loading mechanism.
## Canvas API `slides` array
For `open_canvas` and `load_deck`, each `slides` array element is exactly one
slide. Read, split, or generate the deck before calling the Canvas API. Do not
pass a complete multi-slide Markdown file as one element and expect its `---`
lines to be split.
Each element contains optional YAML-like front matter delimited by `---`,
followed by GFM-compatible Markdown.
| Key | Role |
| --- | --- |
| `deck` | Deck name in the left footer |
| `kicker` | Small label above the heading |
| `page` | One-based current page; shown only together with `total` |
| `total` | Total page count |
| `title` | Browser-tab title; defaults to `deck` |
| `layout` | `title` for the cover, `section` for a section divider, `backcover` for the back cover, or `center` to vertically center heading and body together. Omit for top-aligned standard slides. |
| `size` | `auto` (default), `compact`, `normal`, `large`, or `xlarge`. `auto` safely enlarges only spacious standard slides; `compact` shrinks dense ones. |
| `theme` | Per-slide override: `dark`, `light`, `microsoft`, or `custom`. An explicit canvas theme has precedence. |
| `theme-file` | CSS custom-property file for `custom`, resolved first beside the source Markdown and then from the workspace root. A sibling `theme.json` loads automatically. |
| `background-image` | Per-slide decorative image, e.g. `/assets/background.png`, overriding all layouts and themes. Never inherited by later slides, including from initial front matter. |
| `logo` | Back-cover text at top left. Overrides the `theme.json` logo; empty hides it. |
| `copyright` | Back-cover copyright text at bottom left. Overrides `theme.json`; empty hides it. |
The `assets/background.png` alias without a leading slash is also accepted.
Background images use the normal lookup: Markdown-adjacent `assets/` before
workspace-root `assets/`, or workspace root only without `sourceName`.
Only `.svg`, `.png`, `.webp`, `.jpg`, and `.jpeg` files up to 2 MiB are accepted;
remote and `data:` URLs are forbidden. Use literal filenames (spaces and percent
signs allowed) with `/` separators. Source paths are not URL-decoded: `%20`
means literal filename text, not a space. Queries, fragments, backslashes, and
`.` / `..` path segments are rejected. Symlinks must stay inside
the assets folder and workspace. Images are centered cover behind content
and logos with existing colors underneath. For custom default/center layouts,
priority is per-slide `background-image` → `layouts.default.background` or
`layouts.center.background` → root `background` → existing background.
Theme entries use `{ image, alt? }` with theme-local `assets/` paths. Title
slides retain `cover.background`; section/back-cover layouts do not inherit the
common image. Only absent settings fall back; invalid values, missing files,
and oversized images are errors. Existing covers and logos are otherwise unchanged.
Use normal Markdown: headings, lists, emphasis, inline and fenced code, block
quotes, tables, links, images, `mermaid`, `architecture`, `archify`, and emoji. Write raw
Markdown; do not generate HTML or pre-escape it.
Put Slidev / Marp-style speaker notes in a top-level HTML comment at the end of
the slide. Notes support Markdown in the canvas and MarkdStage Desktop presenter
view, and PowerPoint export includes them as readable plain text notes. They do
not appear on standard slides, the external presenter, or PDF.
```markdown
## Demo
在 GitHub 查看