![]()
Markdown を書くと、報告用の PowerPoint 資料になる。macOS のデスクトップアプリ(Electron)。

報告資料づくりで手間なのは中身ではなく体裁の手直しでした。並べ替えたら番号を振り直す、本文が溢れたらフォントを縮める、図を貼り直す。mdslide はその部分をツール側に引き取り、人は Markdown を書くことに集中します。
Cover / Agenda / Section / Body-Text / Body-2col と付けたマスター pptx を保管フォルダに置き、資料ごとに選ぶ。ツールは書式を持たない.md と同じフォルダの images/(貼り付けた画像)、notes/(下書き・素材)、out/(生成物)がひとまとまり。フォルダごと渡せるAGENTS.md と、それを読み込む CLAUDE.md(中身は @AGENTS.md の 1 行)がフォルダに自動で置かれるcurl -fsSL https://froggugugugu.github.io/mdslide/install.sh | bash を実行する(Apple silicon 向け)。mdslide が「アプリケーション」に入り、pptx の書き出しに使う python-pptx も専用の環境に入る。dmg から手で入れる方法は下の「インストール」deck.md が表紙・章・スライド 1 枚だけの空の枠でできる。題はフォルダ名(見本を触りたければ「サンプルを見る」)master: 名前.pptx として書かれる。見本でよければ、同じ画面の「見本を取り込む」で sample-master.pptx(リポジトリの examples/sample-master.pptx と同じもの)が保管フォルダに入る。手持ちのテンプレートから作る手順と AI 用のプロンプトは docs/master-guide.mdout/deck.pptx ができる。PowerPoint で開いて仕上げる2 回目からは前回の資料がそのまま開く。別の資料は、ツールバーのファイル名のボタン(Markdown ファイルを開く)から開く。前回のファイルが無ければ起動画面になり、「最近開いたもの」から選べる。使い方は ⌘/ で開く(初回の起動では自動で開く)。
notes/ に自動保存され、ファイルをドロップしても notes/ に入る![TODO 説明]() の仮置きが theme.json(マスターから抽出した配色)の PNG に置き換わる.mdslide/history/)フォルダには規約を書いた AGENTS.md(と、それを @AGENTS.md で読み込む CLAUDE.md)、theme.json、図の生成ヘルパー tools/mdslide_draw.py が自動で置かれる。
| 項目 | 要件 |
|---|---|
| OS | macOS(Electron)。配布版(Releases の dmg / zip とインストール用コマンド)は Apple silicon 向けで、Intel の Mac はソースから動かす。Linux / Windows は未検証 |
| Node.js | 24.15 以上(ソースから動かす場合。.node-version / .nvmrc を置いてあるので fnm / nvm / asdf はそのまま切り替わる) |
| Python | pptx の書き出しに Python 3.9 以上と python-pptx。図の生成を AI に任せるなら 3.12 と requirements.txt |
| AI エージェント | 任意。設定の「ツール」で選んだコマンドをコンソールのシェルで実行する。プリセットは claude codex gemini aider copilot cursor-agent opencode(既定は claude を自動起動)で、自分のコマンドも足せる。コマンドは PATH に入れておく |
ブラウザ版(npm run dev:web)は開発と E2E テストのためのもの。Chromium 限定で、pptx 生成とコンソールは使えない。
ターミナルで次を実行する(Apple silicon 向け)。
curl -fsSL https://froggugugugu.github.io/mdslide/install.sh | bash
scripts/install.sh が次を行う。オプションはスクリプト冒頭のコメントにある。
/Applications/mdslide.app に入れる(書き込めなければ ~/Applications)。入っていれば置き換える~/.config/mdslide/venv に入れる。版は固定し、ビルド済みの wheel だけを使う(Python 3.9 では Pillow の修正を含む版が入らないので、3.10 以上を勧める表示が出る)。アプリはこの場所を最初に探す。Python 3 が無ければ xcode-select --install を案内して飛ばすcurl でダウンロードしたファイルには、ブラウザと違って隔離属性(com.apple.quarantine)が付かない。Apple の公証を受けていない配布版でも、このコマンドで入れればそのまま開ける。
ブラウザで dmg をダウンロードして入れる場合は、開く前に隔離属性を外す。外さずに開くと、macOS は「“mdslide”は壊れているため開けません」と表示する(アプリは壊れていない。「ゴミ箱に入れる」は押さずに閉じる)。
ターミナルで次を実行する
xattr -dr com.apple.quarantine /Applications/mdslide.app
この場合、python-pptx は自分で入れる。アプリは起動時に確認し、見つからなければ案内を出す。
python3 -m venv ~/.config/mdslide/venv
~/.config/mdslide/venv/bin/python -m pip install python-pptx==1.0.2
Python 自体が無ければ、先に xcode-select --install を実行する(Command Line Tools に Python 3 が入っている)。Python の場所は設定の「書き出し」で指定することもできる。
ソースから動かす場合。Node は 24.15 以上(.npmrc の engine-strict により、古い Node では npm ci が最初に止まる)。node-pty のビルドに Xcode Command Line Tools(xcode-select --install)が要る。Python は 3.12(requirements.txt の matplotlib と pillow は、Command Line Tools の Python 3.9 には入らない)。Intel の Mac はこの方法で動かす。
npm ci # Electron と node-pty の再ビルドを含む
python3.12 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # 開発する場合は requirements-dev.txt
npm run dev
配布用のビルドは npm run dist:mac(アドホック署名の dmg / zip を release/ に出す)。GUI を使わずに出力だけ行うこともできる。
python3 tools/export_pptx.py deck.json --master master.pptx -o out.pptx --assets .
---
title: 資料タイトル
subtitle: 副題
agenda: once # once | per-section | none
numbering: chapter # chapter (1, 1.1) | flat | none
master: corporate.pptx # 保管フォルダのマスター。省略時はフォルダの master.pptx、無ければ設定の既定。none で使わない
---
# 章タイトル → 中表紙。アジェンダの項目にもなる
## 本文スライド
- 箇条書き(2 スペースで階層)
- **太字** と `コード`
## 構成図 {img=3/4 side=left} → 画像 3/4 幅・左。残りが本文

## 比較 {layout=2col} → 最初の空行で左右に分かれる
左の内容
右の内容
## 表とノート
| 指標 | 目標 |
| --- | --- |
| 稼働率 | 99.9% |
> note: スピーカーノート
| 記法 | 意味 |
|---|---|
# 見出し |
章(中表紙)。# より前の ## は通し番号になる |
## 見出し {属性} |
本文スライド。属性は Pandoc 形式 |
{img=1/1 \| 3/4 \| 1/2} {side=left \| right} |
画像スライド。画像はアスペクト比を保って枠に内接 |
{layout=2col} |
2 カラム。Body-2col レイアウトに流し込む |
{size=16} |
そのスライドの本文フォントサイズ(pt) |
![TODO 説明]() |
画像の仮置き。この行で貼り付けると置き換わる |
> note: |
スピーカーノート |
--- |
本文内の明示的なページ分割 |
開いた Markdown の親フォルダが作業の単位になる。Markdown を開いたときはその名前のまま使い、フォルダを開いたときと「新しく作る」では deck.md になる。
my-deck/
├── report.md # 唯一の正(開いた Markdown。名前は自由)
├── images/ # 貼り付けた画像(相対パスで参照)
├── master.pptx # このフォルダ専用のマスター(任意。通常は保管フォルダから frontmatter で選ぶ)
├── deck.json # 書き出しの中間形式(契約 v2)
├── out/deck.pptx # 生成結果
├── notes/ # 下書き・素材
├── theme.json # マスターから抽出した配色とフォント(アプリが書き直す。手で編集しない)
├── tools/mdslide_draw.py # 図の生成ヘルパー(アプリの版で上書きされる)
├── AGENTS.md # エージェント向けの規約(無いときだけ生成、編集可)
├── CLAUDE.md # @AGENTS.md の 1 行。Claude Code は同じ規約を読む
└── .mdslide/history/ # AI に指示を送る直前の Markdown のスナップショット(「前の版に戻す」で戻る)
設定は 1 ファイル ~/.config/mdslide/settings.json(XDG_CONFIG_HOME 準拠、MDSLIDE_CONFIG で場所を変更できる)に置く。手で編集した内容はウィンドウにフォーカスが戻ったときに反映される。マスターの保管フォルダ(masters.dir)、既定のマスター(masters.default)、Vim キーバインド(editor.vim)、エディタ幅(editor.width)、書き出しに使う Python の場所(export.python)もここにある。保管フォルダの既定は設定ファイルと同じフォルダの masters/、アプリが最初に探す Python は同じフォルダの venv/。
| 環境変数 | 用途 |
|---|---|
MDSLIDE_CONFIG |
設定ファイルのパス |
MDSLIDE_WORKSPACE |
起動時に開くフォルダか Markdown ファイル(起動引数でも渡せる) |
MDSLIDE_PYTHON |
pptx の書き出しに使う Python。指定するとそれだけを使い、自動では探さない |
MDSLIDE_NODE |
node-pty を読み込めない環境で端末を中継する Node(既定 node) |
npm run dev # Electron(electron-vite dev)
npm run dev:web # ブラウザ版 http://localhost:5173
npm run typecheck # tsc(src+tests / electron)
npm test # vitest(単体 + 内部結合)
npm run test:coverage # 閾値 lines 80% / branches 70%
npm run test:py # pytest(deck.json → pptx、図生成、インストール用スクリプト)
npm run test:e2e # Web E2E(headless Chromium)
npm run test:e2e:electron # Electron E2E(実アプリを起動。要ディスプレイ)
npm run test:all # typecheck / test:coverage / test:py / test:e2e。PR の条件(Electron E2E は CI の macOS ジョブで回る)
| 層 | 場所 | 保証すること |
|---|---|---|
| 単体 | tests/unit/ |
parser / render / fit / geometry / importMaster / workspace / 各コンポーネント |
| 内部結合 | tests/integration/ |
store を通した Markdown → スライド → 保存、フォルダ監視と競合 |
| Python | tests/python/ |
deck.json → pptx(レイアウト解決、画像内接、表、ノート、警告)、図の生成ヘルパー、scripts/install.sh(macOS のみ) |
| E2E | tests/e2e/ |
ユーザーが実際に行う一連の操作。Web は OPFS、Electron は CDP |
リリースは package.json の version を上げ、同じ版のタグを push する(タグと version が違えば release.yml が止まる)。release.yml の build ジョブが macOS ランナーで dmg / zip をビルドし、署名、インストール用コマンドでの入れ方、ライセンス表示、Electron fuses を確かめる。publish ジョブが下書きのリリースに添付してから公開する(Immutable releases のため、公開後は添付ファイルもタグも変えられない。ADR-0027)。使い方ページ(GitHub Pages)とインストール用コマンドは、main への push で pages.yml が更新する。
v="v$(node -p "require('./package.json').version")" && git tag "$v" && git push origin "$v"
設計の要点は次のとおり。詳細は CLAUDE.md と docs/adr/。
src/model/ は純粋関数。React にも Electron にも依存しないsrc/store/ は Zustand。markdown 以外はすべて派生値electron/preload.ts だけdeck.json の geometry)と同じ表示行モデルを共有するサプライチェーン攻撃への備えとして、依存はすべて完全一致で固定し、更新は PR 経由でのみ取り込む。
package.json は完全一致のバージョン(.npmrc の save-exact)。package-lock.json をコミットし、セットアップも CI も npm ci。CI とリリースでは依存の install スクリプトを走らせず(--ignore-scripts)、node-pty だけを npm run rebuild で作るrequirements.txt(実行時)と requirements-dev.txt(テスト)で == 固定。インストール用コマンドは python-pptx と依存を版で固定し、wheel だけを入れるrelease.yml の publish ジョブ(contents)と pages.yml の deploy ジョブ(pages / id-token)だけで、どちらもリポジトリのコードも依存も実行しない@electron/get が SHASUMS256.txt で検証するこのプロジェクトは project-blueprints を利用して開発している。Claude Code のルール・スキル・エージェント・品質ゲートといった開発の枠組みはそこから来ており、このリポジトリには mdslide 固有の規約(CLAUDE.md)だけを含めている。
MIT。同梱するサードパーティのソフトウェアと素材のライセンス、商標については THIRD_PARTY_NOTICES.md。脆弱性は公開の Issue ではなく、SECURITY.md の方法で知らせてください。