@fillu87gyc/nymph
v1.2.0
Published
Markdown review tool with hot reload and inline commenting
Readme
nymph
AI が生成した Markdown・Mermaid をレビューするための軽量ツール。
nymph output.mdブラウザが開き、ファイルを監視して自動再レンダリングします。
スタック: Bun · React 18 · TypeScript · Vite 7
要件
- Bun (
mise use -g bunまたは bun.sh)
インストール
bunx(インストール不要)
bunx @fillu87gyc/nymph *.mdグローバルインストール
bun install -g @fillu87gyc/nymph
nymph *.md単一バイナリ(Bun 不要で配布可)
bun build --compile src/cli.ts --outfile nymph
./nymph *.mdローカル開発
git clone https://github.com/fillu87gyc/nymph
cd nymph
bun install
bun run src/cli.ts output.mdクローンを指す nymph コマンドを常設するなら bun link を使います。以後は git pull && bun run build だけで最新(origin/main)に追従します。
bun run build # dist は .gitignore 済みなので必須
bun link # ~/.bun/bin/nymph → クローンの src/cli.tsbun install -g github:fillu87gyc/nymph は使わないでください。dist/ は git に入っていないため、サーバーは起動するのに画面が真っ白という状態になります。
使い方
nymph output.md
# nymph http://localhost:6276
# 監視中 /path/to/output.md
# Ctrl+C で停止複数ファイルや glob も指定できます:
nymph *.mdディレクトリを渡すと、VSCode のようにサイドバーへ階層ツリーを表示して .md を開けます:
nymph ./docs
nymph ./ # カレントディレクトリをツリー表示オプション
使い方: nymph [オプション] [ファイル|ディレクトリ ...]
引数:
ファイル ... 監視する .md ファイル(glob 対応)
ディレクトリ サイドバーにツリー表示して .md を開けるようにする
オプション:
-p, --port <番号> 使用するポート番号 (デフォルト: 6276)
--no-open ブラウザを自動的に開かない
--export <出力先> コメント埋め込みの静的 HTML を書き出して終了する
(サーバーは起動しない。ファイルを1つだけ指定する)
--export-mermaid エクスポートに Mermaid 描画エンジンを同梱する
(オフラインでも図が描画される。出力が約3MB増える)
--annotate <出力先> コメントを本文へ書き戻した Markdown を出力して終了する
(各ブロックの直後に「> [nymph] …」の引用を挿し込む。
元ファイルは書き換えない)
--annotate-open 書き戻すコメントを未解決・削除済のみに絞る
-v, --version バージョンを表示して終了
-h, --help このヘルプを表示して終了
サブコマンド:
nymph export <ファイル> [-o <出力先>] [--bom]
保存済みコメントを CSV にする(-o 省略で標準出力)
nymph dict build ユビキタス言語辞書をビルドする
nymph dict allow 辞書設定に書かれたコマンドを承認するnymph -p 8080 output.md # ポートを指定
nymph --no-open output.md # ブラウザを開かずに起動
nymph --version # バージョン確認
nymph report.md --export review.html # レビュー結果を静的 HTML に書き出す
nymph report.md --export review.html --export-mermaid # 図も描画できる形で
nymph report.md --annotate review.md # コメントを本文へ書き戻す
nymph export report.md -o review.csv # コメントを CSV にする指定したファイル / ディレクトリが存在しない場合は、サーバーを起動せずにそのパスを示して終了します(複数指定のうち一部だけ存在しない場合も、黙って無視せずエラーになります):
$ nymph README.md typo.md
エラー: 指定されたパスが存在しません: typo.md
nymph --help でヘルプを表示機能
ホットリロード
ファイルの変更を SSE で検知し、即座に再レンダリングします。
ディレクトリツリー(エクスプローラー)
nymph ./docs のようにディレクトリを渡すと、サイドバーに階層ツリーが表示されます(.md のみ、隠しディレクトリと node_modules は除外)。クリックしたファイルはタブに追加されます。ツールバーの フォルダを開く からパスを入力して、起動後にツリーのルートを切り替えることもできます。

ウィジェット配置
画面左右の枠に置くパネルは、⚙ 設定の 配置を編集 から開く専用の配置画面で決めます。「利用可能」の一覧と左右の枠のあいだをドラッグ&ドロップで移すだけで、1 つの枠に複数を縦に積めます(「左=タブ + アウトライン、右=コメント」のような並びも作れます)。枠の中の上下の順番もドラッグで入れ替えられます。
| ウィジェット | 内容 | 置ける場所 |
|---|---|---|
| タブ | 開いているファイルの一覧 | 左 / 右 / 横行(既定) |
| エクスプローラー | ルート配下のファイルツリー | 左(既定) / 右 |
| アウトライン | 見出しの一覧 | 左 / 右(既定) |
| コメント | レビューコメントの一覧 | 左 / 右 / 下ドック(既定) |
| 検索結果 | 常設の全文検索。結果から該当行へジャンプ | 左 / 右 |
| 最近 / ブックマーク | 履歴とブックマークの常設リスト | 左 / 右 |
| ミニマップ | 文書全体の俯瞰。コメント位置を点で重ね、クリックでジャンプ | 左 / 右 |
| 図の一覧 | 本文中の Mermaid 図へジャンプ | 左 / 右 |
| タスク | - [ ] チェックボックスの一覧(未完のみ絞り込み可) | 左 / 右 |
| リンク / 画像 | リンクと画像の一覧。相対パスは実在するかを判定 | 左 / 右 |
| 用語集 | 辞書の用語一覧と、本文中の出現箇所へのジャンプ | 左 / 右 |
| frontmatter | 先頭の YAML メタ情報 | 左 / 右 |
| 差分サマリ | チェックポイントからの変更箇所の一覧 | 左 / 右 |
| 文書統計 | 文字数・見出し数・推定読了時間など | 左 / 右 |
タブ・エクスプローラー・アウトライン・コメント以外は既定の置き場所を持たないため、枠に置いたときだけ画面に出ます(「利用可能」へ戻すと画面から消えます)。エクスプローラーとアウトラインは必ず左右どちらかの枠に入ります。
マウスを使わない場合は、チップにフォーカスして ← → で枠を移動、↑ ↓ で枠の中の並び替えができます。初期配置にリセット で初期状態(左=エクスプローラー / 右=アウトライン)に戻せます。配置に「保存」ボタンはありません — ドラッグした時点で画面に反映され、そのまま保存されます(✓ 完了 は画面を閉じるだけです)。
タブを左右の枠に置くと、VSCode の Open Editors のような縦リストになります(横行は 2 ファイル以上でのみ出ますが、縦置きは 1 ファイルでも表示します)。配置はブラウザに保存され、次回起動時も維持されます。
枠の幅は、枠と本文の境目をドラッグして左右それぞれ 140〜480px の範囲で変えられます(フォーカスして ← → でも 16px ずつ動かせます)。ダブルクリック(または Home キー)で既定の幅に戻ります。本文の左右端をドラッグする「本文幅の調整」とは別で、こちらはサイドバーの幅だけが変わります。幅もブラウザに保存されます。
最近開いたファイル
開いたファイルの履歴を ~/.local/share/nymph/recent.json に保存します(最大 20 件)。ツールバーの 最近 メニューと、引数なし起動時の画面から再オープンできます。

引数なしで起動すると、履歴とブックマークが起動画面に表示されます。

ブックマーク
ツールバーの ★ で、表示中のファイル(未選択時はツリーのルートディレクトリ)を登録できます。最近 メニューと起動画面に表示され、ファイルは開く・ディレクトリはツリーのルート切替になります。
Quick Open(Ctrl+P)
Ctrl+P / Cmd+P で検索パレットを開き、タブ・履歴・ブックマーク・ツリー内の全ファイルを横断して絞り込み、Enter で開けます。

キーボードショートカット
? でショートカット一覧が開きます(「⋯」メニューの ⌨ ショートカット一覧 からも同じものが出ます)。
| キー | 動作 |
|------|------|
| ? | ショートカット一覧を開く / 閉じる |
| Ctrl / Cmd + P | Quick Open(ファイル名と本文の検索) |
| C | コメントパネルを開く / 閉じる |
| T | テーマ(ダーク / ライト)を切り替える |
| Esc | モーダル・メニュー・一覧を閉じる |
修飾キーなしの 1 文字(? / C / T)は、コメント欄や検索欄に入力しているあいだと、モーダルが開いているあいだは反応しません。日本語入力の変換中にも横取りしません。Ctrl / Cmd と一緒に押したときも反応しないので、Ctrl+T(新しいタブ)や Cmd+C(コピー)はそのまま使えます。
コメントパネルをウィジェット枠に置いている場合は常時表示になるため、C では開閉しません。
Mermaid レンダリング + draw.io エクスポート
Mermaid コードブロックをインラインでレンダリングします。各ダイアグラムに → draw.io ボタンがあり、.drawio ファイルのダウンロードまたはコードのコピーができます。
画像の表示
 のような相対パスの画像は、md ファイルの場所を起点に解決して表示します(本文に直接書いた <img src="..."> も同じです)。ブラウザに任せると相対パスは画面の URL 基準で解決されてしまうため、nymph が起点を補って配信します。
読みに行く範囲はリンクの生死チェックと同じで、nymph ./docs のようにルートを渡していればルート配下、ファイル単体で開いていればそのファイルのディレクトリ配下です。範囲の外を指す画像は配信しません(../ でディレクトリの外へ出る画像を表示したい場合は、それを含むディレクトリをルートとして渡してください)。https:// などの外部 URL と data: の画像は、書かれたままブラウザが読み込みます。
インラインコメント
レンダリングされた各ブロックにホバーすると + ボタンが表示されます。テキスト選択でも範囲コメントが追加できます。コメントはレビュー対象ファイルを汚さないよう ~/.local/share/nymph/reviews/<key>/comments.json(<key> はファイルの絶対パスから決定論的に導出)に自動保存されます。
コメントのステータスとスナップショット
各コメントは 未解決 / 削除済 / 解決済 のいずれかの状態を持ちます。未解決のまま 対象の文章がファイルから消えたコメントは自動的に 削除済 になり、解決済みのコメントは 対象が消えても 解決済 のままです。コメントパネルのフィルタで状態ごとに絞り込めます。
コメントには作成時点の「もとの文章」(対象行 + 前後 5 行)が一緒に保存されます。削除済 / 解決済 のバッジをクリックすると、その文章を吹き出しで確認できます。
レビューのコピー
レビューをコピー ボタンで全コメントを JSON 形式でクリップボードにコピーします。
チェックポイント / Diff
📍 ボタンでチェックポイントを設定し、± diff ボタンで変更箇所をハイライト表示できます。チェックポイントはコメントと同じ ~/.local/share/nymph/reviews/<key>/checkpoint に保存されます。
HTML エクスポート
--export で、本文と保存済みコメントを 1 枚の静的 HTML に書き出せます。サーバーは起動せず、書き出したら終了します。
nymph report.md --export review.html生成物は単体で完結します。CSS も JavaScript も画像(ファイルと同じディレクトリ配下の相対パス)もすべてファイルの中に焼き込むので、ネットワークが無い環境でもそのまま開けます。メール添付や社内 Wiki への貼り付け、そのままの印刷 / PDF 化を想定しています。
- コメントは対象ブロックの直後に、状態(未解決 / 削除済 / 解決済)・行番号・ラウンド・「もとの文章」つきで並びます
- 対象が消えたコメントと差分への指摘は、末尾の「本文に紐づかないコメント」にまとめます
- ヘッダーの 解決済みを隠す で解決済みを畳め、ライト / ダーク でテーマを切り替えられます(初期値は OS の設定に従います)
Mermaid 図
既定ではソースを枠付きで見せるだけですが、--export-mermaid を付けると描画エンジンごと焼き込み、オフラインのまま図が描画されます。図が 1 つも無い文書では有効にしても同梱しません。
nymph report.md --export review.html --export-mermaid描画に失敗した図(構文エラーなど)はソース表示のまま残るので、1 つの図の不具合が他を巻き添えにしたり、枠だけが残ったりはしません。テーマを切り替えると図も描き直されます。
CDN から取得する案は採っていません。配布物が開かれるたび第三者へ接続する(=誰がいつ読んだかが漏れる)うえ、mermaid の ESM ビルドは図の種類ごとにチャンクを動的 import するため SRI で守りきれないためです。
アプリ本体と異なる点(意図的なもの)
- 本文中の生 HTML は実行せず、書かれたままエスケープして表示します(配布物に消毒し損ねた HTML を埋めないため)
- コードのシンタックスハイライトは付きません
印刷 / PDF
「⋯」メニューの 🖨 印刷 / PDF で、開いている文書をそのまま印刷・PDF 保存できます(Ctrl / Cmd + P は Quick Open に割り当てているため、印刷はこのメニューから開きます)。
- 紙に載るのは本文だけです。ツールバー・ウィジェット枠・コメントパネル・各ブロックの操作ボタンは出ません
- テーマがダークでも配色はライトに倒します。ブラウザは既定で背景色を印刷しないため、そのまま出すと薄い文字だけが紙に残ってしまうためです(画面のテーマ設定は変わりません)
- コードブロック・表・図はページの切れ目をまたがないようにし、長いコード行は折り返します(紙では横スクロールできないため)
- 見出しはその直後の本文と切り離されないようにします
コメントは紙に出ません。コメント入りで配りたいときは、印刷用 CSS 込みで書き出される HTML(下の「画面からのエクスポート」または --export)を開いて印刷してください。
画面からのエクスポート
「⋯」メニューの エクスポート から、CLI と同じ 3 形式をブラウザに直接ダウンロードできます。ターミナルへ戻らなくても、レビューしたその画面から結果を持ち出せます。
| 項目 | 中身 | 対応する CLI |
|------|------|-------------|
| 📄 HTML(コメント入り) | 単体で完結する静的 HTML | --export |
| 📝 Markdown(コメント入り) | 本文の隣に指摘が引用で入った .md | --annotate |
| 📊 CSV(コメント一覧) | 1 コメント 1 行の表 | nymph export |
- ファイル名は
<元の名前>-review.<拡張子>(report.md→report-review.md)です。元ファイルと同じ拡張子になる Markdown でも取り違えません - 生成物はサーバー側のディスクに残しません。書き出し先を決めるのはブラウザ(保存ダイアログ / ダウンロードフォルダ)です
- Mermaid を同梱 にチェックを入れると、HTML に描画エンジンを焼き込みます(
--export-mermaid相当)。既定は off です——生成物が約 3MB 大きくなるため - CSV だけは CLI と既定が逆で、BOM 付きで落とします。画面からのダウンロードは行き先がほぼ表計算ソフトなので、Excel での文字化けを防ぐ側に倒しています(パイプに繋ぐ用途は CLI の
nymph exportが引き続き BOM 無しです)
中身は CLI の出力とまったく同じです(組み立てを共有しているので、経路によって解釈が変わることはありません)。それぞれの詳細は下の各節を参照してください。
Markdown への書き戻し
--annotate で、保存済みコメントを本文に挿し込んだ Markdown を書き出せます。HTML エクスポートが「読ませる配布物」なのに対し、こちらはそのまま編集を続けられる形でレビューを返すためのものです(書き手が人でも AI でも、本文の隣に指摘がある Markdown を受け取ってそのまま直せます)。
nymph report.md --annotate review.md
nymph report.md --annotate review.md --annotate-open # 未解決・削除済だけコメントは対象ブロックの直後に引用として入ります:
これは本文の段落です。
> [nymph] 未解決 · L3 · ラウンド 2 · 2026-08-09 10:20
>
> 主語が曖昧です- 本文の行は書き換えません。足すのは引用と、それを区切るための空行だけです(引用の前後に空行が無いと、直後の本文が引用の続きとして読まれて元の文書の意味が変わるため)
- 行番号(
L3)は元ファイル基準です。引用を挿し込んだ時点で以降の行はずれるので、書き戻した Markdown 自身の行番号とは一致しません - 対象が消えた指摘と差分への指摘は、末尾の「本文に紐づかないコメント」にまとめます
- 出力の素性(日時・件数・ラウンド)は末尾の HTML コメントに残します。表示には出ないので、そのまま清書に回しても邪魔になりません
- 元ファイルへの上書きは拒否します。レビュー対象を書き換えないのがこのツールの前提なので、書き戻しは別ファイルへの出力に限っています
CSV エクスポート
nymph export で、保存済みコメントを 1 件 1 行の CSV にできます。表計算・課題管理・スクリプトへ流すための出力です。
nymph export report.md # 標準出力へ(そのままパイプできる)
nymph export report.md -o review.csv # ファイルへ
nymph export report.md --bom -o review.csv # Excel で開くなら BOM 付きで列は file, id, status, line_start, line_end, block_type, round, created_at, target, comment です。status は画面・HTML エクスポートと同じ規則(open / deleted / resolved)で決まります。RFC 4180(CRLF・" のエスケープ)に従うので、Excel / Numbers / LibreOffice や csv モジュールがそのまま読めます。
= + @ で始まる値は先頭に ' を足して無害化します(表計算ソフトが数式として評価してしまうため)。箇条書きの - は数式にならないのでそのままです。
ユビキタス言語辞書
プロジェクトルートの .nymph/config.yml を使って、docs/UBIQUITOUS_LANGUAGE.md から辞書ファイルを生成できます。
nymph dict build.nymph/dict.json に辞書ファイルが出力されます(.gitignore 対象のため生成ファイルは追跡しません)。
# デバッグ出力(ノード木とマッチ結果を .nymph/debug/ に保存)
nymph dict build --debug用語集のソースは docs/UBIQUITOUS_LANGUAGE.md です。新しいモジュールや概念を追加したときはこちらも更新してください。
開発
bun install
bun run dev # API サーバー(:6276) + Vite(:5173) を同時起動
bun run test # 単体 + コンポーネントテスト (Vitest 3)
bun run test:e2e # E2E テスト (Playwright)
bun run build # プロダクションビルド (Vite 7)
bun run smoke:pack # 公開物(npm pack)をインストールして CLI 入口を叩くsmoke:pack は package.json の files から実ファイルが漏れたまま publish される事故を止めるためのものです(bin が TypeScript ソースを直接指す構成なので、相対 import はすべて同梱されている必要があります)。作業ツリーで bun run src/cli.ts を叩いても漏れは再現しないため、npm pack の成果物を隔離ディレクトリへインストールして検証します。リリース時は CI(.github/workflows/publish.yml の verify job)が自動で実行します。
dev ではフロントのアセットを配っているのは Vite dev server(:5173)で、API サーバー(:6276)を開いてもビルド済みの古い dist/ が返るだけです。そのため CLI は「開くべき URL」としてフロント側を表示し、API のポートは補助的に添えます。
nymph http://localhost:5173
API http://localhost:6276この案内先は NYMPH_FRONTEND_URL で決まります(未指定なら API サーバー自身が dist/ を配る前提でそのポート)。dev では起動済みインスタンスが /version でこの値を公開するので、別の端末から nymph <file> を実行して既存インスタンスに委譲したときも、API のポートではなくフロントの URL が表示・オープンされます。
NYMPH_FRONTEND_URL を指定すると Vite はそのポートを strictPort で確保します(案内した URL と実際の待受がズレないようにするため。埋まっていれば黙って別ポートに逃げずに失敗します)。
ghq を使っている場合の開発用ショートカット(~/.zshrc)
nymphx() {
local nymph_dir origdir="$PWD"
if [[ -f package.json ]] && grep -q '"name": "@fillu87gyc/nymph"' package.json; then
nymph_dir="$PWD"
else
nymph_dir="$(ghq list --full-path nymph | grep '/nymph$' | head -1)"
fi
local -a a
for f in "$@"; do
case "$f" in
/*) a+=("$f") ;;
*) a+=("$origdir/$f") ;;
esac
done
local port=6276
while (: < /dev/tcp/127.0.0.1/$port) 2>/dev/null; do ((port++)); done
# API のポートをずらしたぶん Vite 側もずらす(strictPort で固定されるため)
local front=$((5173 + port - 6276))
(cd "$nymph_dir" && NYMPH_PORT="$port" NYMPH_FRONTEND_URL="http://localhost:$front" \
NYMPH_FILES="${a[*]}" bun run dev)
}nymphx *.md # HMR 有効な開発モードで起動リリース
入口は Actions タブの Run workflow だけです。package.json のバンプがまだなら、ワークフローがバンプ PR を作って止まります。それをマージしてもう一度 Run workflow すると、今度はリリースが最後まで走ります。
- Actions タブ → Release → Run workflow
versionにリリースするバージョンを入れる(例:1.2.3、プレリリースなら1.3.0-rc.1)tsc/ lint / unit test / build /smoke:packによる検証(verifyjob)package.jsonが指定バージョンかを見る(bumpjob)- 違う →
release/v1.2.3ブランチにバンプだけをコミットした PR を作り、ここで終わり。releasejob は skip され、ワークフロー自体は成功で終わります。PR をマージして 1 からやり直してください - 同じ → そのまま 5 へ
- 違う →
releasejob が走る- タグ
v1.2.3を作成して push - npm へ publish(provenance 付き。プレリリースは dist-tag
next) - リリースノート付きの GitHub Release を作成
- タグ
つまり新しいバージョンを出すときは Run workflow を 2 回叩くことになります(1 回目でバンプ PR ができ、マージ後の 2 回目で本番)。バンプを PR 経由にしているのは、main がブランチ保護されていてワークフローから直接 push できないためです。保護を緩める代わりにこの形にすることで、タグは必ずバンプ済みコミットを指します。
バンプ PR がまだ開いたままの状態で Run workflow をやり直した場合は、PR を作り直さずに既存の PR の URL を案内して終わります。
dry_run を有効にすると、タグ・publish・Release 作成を行わず検証と npm publish --dry-run だけを実行します。初回や不安なときの確認用です(バンプ PR も作りません)。
ローカルで git tag v1.2.3 && git push origin v1.2.3 した場合も同じワークフローが走ります(この経路ではタグ作成のステップだけスキップされます)。ただしタグは後から位置を動かせないため、未バンプのコミットにタグを付けた場合はバンプ PR を作らずエラーで止まります。その場合は git push --delete origin v1.2.3 でタグを消してから、Run workflow でやり直してください。
前提: バンプ PR の作成には、Settings → Actions → General → Workflow permissions の 「Allow GitHub Actions to create and approve pull requests」 が有効である必要があります。無効だと
bumpjob が「GitHub Actions is not permitted to create or approve pull requests」で落ちるので、その場合は設定を有効にするか、npm pkg set version=1.2.3だけの PR を手で作ってマージしてください。
publish が失敗して同じバージョンをやり直す場合、タグが同じコミットに残っていればそのまま再実行できます(タグ作成と publish 済みバージョンはスキップされる)。別のコミットに同名タグがある場合はエラーで止まるので、git push --delete origin v1.2.3 してから実行し直してください。
npm の認証: npmjs の Trusted Publishing(OIDC)を使っており、
NPM_TOKENなどの secret は不要です。ただし npmjs 側は リポジトリとワークフローのファイルパスの組み合わせ で照合するため、.github/workflows/publish.ymlをリネームするとnpm error code ENEEDAUTHで publish に失敗します。ファイル名を変えるときは npmjs の Trusted Publisher 設定も同時に更新してください。
Claude Code との連携
Claude Code のプロジェクトに nymph を追加すると、Edit ツールによるファイル編集時にコメントの行番号が自動追従します。
claude plugin install github:fillu87gyc/nymphClaude Code 上でフックをインストール:
/nymph:install仕組み:PostToolUse フックが Edit ツールの old_string / new_string を /edit-op エンドポイントに転送し、編集前後の行数差分でコメント位置を自動補正します。
ライセンス
MIT — 詳細は LICENSE。
dist/ に bundle 化して同梱しているサードパーティ・ソフトウェア(highlight.js /
diff / DOMPurify / marked / Mermaid / KaTeX / React / SWR ほか)の帰属表示・
ライセンス全文は THIRD_PARTY_NOTICES.md を参照して
ください。
