publish-substack-article について
publish-substack-articleは、Markdown記事をリッチテキストに変換し、確認用のSubstack下書きとして保存するSkillです。Playwright MCPまたはChrome DevTools MCPでブラウザーを操作し、表は画像として扱います。公開前の確認と操作はユーザーが行います。
主な機能
- 01Markdownからタイトルと本文を抽出
- 02HTMLに変換して書式付きで貼り付け
- 03表を画像にして挿入
- 04下書き保存状態の確認
- 05Playwright MCPとChrome DevTools MCPに対応
活用シーン
- 01Markdown記事をSubstackの下書きとして保存
- 02見出し、コード、リンクなどの書式を保持
- 03記事内の表を画像で掲載
- 04下書きを確認して手動で公開
MCP 対応
Playwright MCP、または利用できない場合はChrome DevTools MCPで、ブラウザーの移動、エディターへの入力、画像のアップロードを操作します。下書きを保存し、公開フローは開始しません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sugarforever/ 01coder-agent-skills --skill publish-substack-articleインストール後、Claude Code で/publish-substack-articleを入力して読み込まれたか確認します。
詳細
Substack 記事を公開する
Markdown コンテンツを Substack の投稿エディターに公開します。Markdown を HTML に変換し、リッチテキストとして貼り付けます。公開前にユーザーが確認できるよう、下書きとして保存します。
前提条件
- ブラウザー自動化 MCP(次のいずれか):
- Chrome DevTools MCP(
mcp__chrome-devtools__*) - Playwright MCP(
mcp__playwright__*)
- Chrome DevTools MCP(
- ユーザーが Substack にログインしていること
markdownパッケージをインストールした Python 3(pip install markdown)copy_to_clipboard.pyスクリプト(publish-zsxq-article スキルで共有)
ブラウザー MCP ツールの対応表
このスキルは Chrome DevTools MCP と Playwright MCP の両方に対応しています。
| 操作 | Chrome DevTools MCP | Playwright MCP |
|---|---|---|
| 移動 | navigate_page | browser_navigate |
| スナップショットを取得 | take_snapshot | browser_snapshot |
| スクリーンショットを撮影 | take_screenshot | browser_take_screenshot |
| 要素をクリック | click | browser_click |
| テキストを入力 | fill | browser_type |
| ファイルをアップロード | upload_file | browser_file_upload |
| キーを押す | press_key | browser_press_key |
| JS を評価 | evaluate_script | browser_evaluate |
優先順位:デフォルトでは Playwright MCP を使用します。Playwright MCP が利用できない場合に限り、Chrome DevTools MCP を使用します。
検出:実行時には、mcp__playwright__browser_navigate を優先してください。Playwright ツールが利用できない場合に限り、mcp__chrome-devtools__navigate_page にフォールバックします。
主な URL
- Substack ダッシュボード:
https://{publication}.substack.com/publish - 投稿エディター:
https://{publication}.substack.com/publish/post/{postId}
Publication の解決
ダッシュボードに移動するには、Substack の publication サブドメイン(例:verysmallwoods.substack.com の verysmallwoods)が必要です。デフォルト値をハードコードしないでください。
移動を始める前に、次の順序で publication を解決してください。
- スキルの引数 — ユーザーが publication サブドメインを指定してスキルを実行した場合は、それを使用します。
- 環境変数 —
SUBSTACK_PUBLICATIONを確認します(任意。同じ publication に繰り返し公開するユーザー向け)。 - どちらも利用できない場合は、ユーザーに確認します:
Substack の publication サブドメイン(例:verysmallwoods.substack.com の
verysmallwoods)を指定してください。
publication サブドメインを解決せずに、ステップ 3(移動)に進まないでください。
エディターのインターフェース
Substack の投稿エディターは Tiptap(ProseMirror ベースの WYSIWYG エディター)を使用しています。
主な要素
- タイトル入力欄:
textbox "title"(プレースホルダー:「Title」) - サブタイトル入力欄:
textbox "Add a subtitle…" - コンテンツ領域:
.ProseMirror(Tiptap エディター、「Start writing...」) - 保存ステータス:
button "Saved"(自動保存) - プレビューボタン:
button "Preview" - 続行ボタン:
button "Continue"(公開フロー — 使用しないでください) - 設定サイドバー:
button "Settings"(タイトル、説明、サムネイル)
設定サイドバー(左パネル)
「Settings」または「File Settings」を開いたとき:
- タイトル:
textbox "Add a title..." - 説明:
textbox "Add a description..." - サムネイル:アップロードボタン(アスペクト比 3:2)
ツールバー
太字、斜体、取り消し線、コード、リンク、画像、音声、動画、引用、リスト(箇条書き/番号付き)、ボタン、その他(コードブロック、区切り線、脚注、LaTeX など)
コンテンツの挿入方法
重要:HTML コンテンツをクリップボード経由で貼り付けてください。 直接入力やプレーンな Markdown の貼り付けは使用しないでください。
Tiptap エディターは HTML の貼り付けをネイティブに処理し、リッチコンテンツとして表示します。手順は次のとおりです。
- Python の
markdownライブラリを使って Markdown を HTML に変換します copy_to_clipboard.py htmlを使って HTML をシステムクリップボードにコピーします- エディターのコンテンツ領域にフォーカスします
- Cmd+V(macOS)または Ctrl+V(Windows/Linux)を押して貼り付けます
HTML の貼り付けを使う理由
fillツール → コンテンツがプレーンテキストとして扱われ、書式が適用されません- プレーンな Markdown の貼り付け → Tiptap は貼り付け時に Markdown を解析しません
- HTML の貼り付け → Tiptap が HTML をリッチコンテンツとして表示します(見出し、コードブロック、リンク、太字など)
既知の制限:Substack のエディターは HTML テーブルに対応していません。テーブルはプレーンテキストにまとめられます。テーブルを画像に変換する方法については、ステップ 0:事前処理を参照してください。
主なワークフロー
ステップ 0:前処理 — 表を画像に変換する
Substack は HTML の表をレンダリングしません。表はプレーンテキストに変換されます。Markdown の表はすべて PNG 画像に変換し、個別にアップロードする必要があります。
ワークフロー:
-
Markdown ファイル内の表を検出します(
|で表の構造を形成している行) -
図から画像への変換スキルを使って、各表を PNG に変換します:
# Extract table to temp file
cat > /tmp/table1.md << 'TABLE_EOF'
| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Data 1 | Data 2 | Data 3 |
TABLE_EOF
# Convert via diagramless.xyz API (auto-detects as table)
node ~/.claude/skills/diagram-to-image/scripts/diagram-to-image.mjs /tmp/table1.md -o /tmp/table1.png
-
後で挿入できるように、記事内で各表がある位置(どの見出し/段落の後か)を記録します
-
HTML 変換前に、コンテンツから Markdown の表を削除します(貼り付けたコンテンツにプレーンテキストとして表示されないようにします)
画像のアップロードは、本文を貼り付けた後に行います。ステップ 7 を参照してください。
ステップ 1:コンテンツを準備する
Markdown ファイルを読み込み、次の項目を抽出します:
- タイトル:YAML フロントマターの
titleフィールド、H1 見出し# Title、またはファイル名から取得します - サブタイトル:YAML フロントマターの
excerptまたはdescriptionフィールドから取得します - コンテンツ:Markdown 本文全体(YAML フロントマターと相互参照リンクを除去します)
ステップ 2:Markdown を HTML に変換する
Python の markdown ライブラリを tables と fenced_code 拡張機能付きで使用します:
import markdown
import re
with open('/path/to/article.md', 'r') as f:
content = f.read()
# Strip YAML frontmatter
content = re.sub(r'^---\n.*?\n---\n', '', content, flags=re.DOTALL)
# Strip cross-reference links (e.g., English version link)
# Adjust pattern as needed for your articles
content = re.sub(r'^> .* available at.*\n\n?', '', content, flags=re.MULTILINE)
# Convert to HTML
html = markdown.markdown(content, extensions=['tables', 'fenced_code'])
# Write to temp file
with open('/tmp/substack_article.html', 'w') as f:
f.write(html)
重要:nl2br 拡張機能は使用しないでください。単一の改行が <br> タグに変換され、エディターで余分な改行が発生します。
ステップ 3:Substack に移動する
Substack ダッシュボードに移動し、新しい投稿を作成します:
# Navigate to Substack dashboard
navigate to: https://{publication}.substack.com/publish
ログインしていない場合は、ユーザーにログインを促します:
请先登录 Substack,登录完成后告诉我。
Please log in to Substack first, then let me know.
ステップ 4:新しい投稿を作成する
ダッシュボードから、新しいテキスト投稿を作成します:
- サイドバーの「Create new」をクリックします
- 「Text post」を選択します(または新しい投稿の URL に直接移動します)
または、エディターが空の投稿を開いた状態であれば、そのまま進めます。
ステップ 5:タイトルとサブタイトルを入力する
- タイトルのテキストボックス(
textbox "title")をクリックします - 記事のタイトルを入力します
- サブタイトルのテキストボックス(
textbox "Add a subtitle…")をクリックします - サブタイトル/抜粋を入力します
click: title textbox
fill/type: article title
click: subtitle textbox
fill/type: article subtitle
ステップ 6:HTML コンテンツを挿入する(クリップボードから貼り付け)
重要:fill ツールは使用しないでください。書式なしのプレーンテキストが挿入されます。
- HTML をシステムクリップボードにコピーします:
python3 /path/to/copy_to_clipboard.py html --file /tmp/substack_article.html
-
エディターのコンテンツ領域(
.ProseMirrorまたはその内部の段落要素)をクリックします -
Cmd+V を押して貼り付けます:
press_key: Meta+v (macOS)
press_key: Control+v (Windows/Linux)
これにより Tiptap の HTML 貼り付けハンドラーが実行され、適切な書式を保ったリッチテキストとしてコンテンツがレンダリングされます。
ステップ 7:表の画像を挿入する
ステップ 0 で記事内の表を画像に変換した場合は、ここで挿入します:
-
エディター内で正しい位置に移動します — 表を挿入する箇所(該当する見出し/テキストの後)の段落または空行をクリックします
-
画像ツールバーのボタン(
button "Image")をクリックします — 「Image」「Gallery」「Stock photos」「Generate image」のオプションがあるドロップダウンメニューが表示されます -
ドロップダウンから「Image」メニュー項目をクリックします — ファイル選択ダイアログが開きます
-
ファイル選択ダイアログから画像をアップロードします:
- Playwright MCP:画像パスを指定して
browser_file_uploadを使用します - Chrome DevTools MCP:画像パスを指定して
upload_fileを使用します
- Playwright MCP:画像パスを指定して
重要な注意事項:
- ファイルパスの制限:Playwright MCP では、許可されたルート(プロジェクトディレクトリ)内からのみファイルをアップロードできます。画像が
/tmp/にある場合は、先にプロジェクトディレクトリにコピーしてください - 各表について繰り返す:カーソルを正しい位置に置いてから、各表の画像をアップロードします
- 残ったテキストを削除する:前処理で表を削除しなかったために表の内容がプレーンテキストとして貼り付けられている場合は、選択して(トリプルクリックで段落を選択できます)、画像を挿入する前に削除します
ステップ 8:下書きを確認する
貼り付けた後:
- 「Saved」ステータスインジケーター(緑色の点と「Saved」のテキスト)を確認します
- スナップショットを取得してコンテンツの構造を確認します
- 必要に応じてスクリーンショットを取得し、表示を確認します
エディターは自動保存されるため、明示的な保存操作は必要ありません。
ステップ 9:完了を報告する
草稿已保存到 Substack。请在 Substack 中预览并手动发布。
Draft saved to Substack. Please preview and publish manually.
Post URL: https://{publication}.substack.com/publish/post/{postId}
完全な実行例
ユーザー:「/path/to/my-article.md を Substack に公開して」
0. Pre-process tables (if any)
- Detect Markdown tables
- Create styled HTML for each table
- Render to screenshots (open in browser, screenshot, close tab)
- Remove table Markdown from content
- Note insertion positions
1. Read /path/to/my-article.md
- Extract title from frontmatter or H1
- Extract subtitle from frontmatter excerpt
- Get full Markdown content (with tables removed)
2. Convert Markdown to HTML
- Strip frontmatter
- Use markdown.markdown() with ['tables', 'fenced_code']
- Write to /tmp/substack_article.html
3. Navigate to Substack dashboard or new post
4. Check if logged in
- If not, prompt user to login
5. Fill title and subtitle
6. Copy HTML to clipboard + Paste
- python3 copy_to_clipboard.py html --file /tmp/substack_article.html
- Click editor content area
- Press Cmd+V
7. Insert table images at correct positions
- For each table: click position → Image button → Image menuitem → file upload
8. Verify draft saved
- Check "Saved" status
9. Report success
- "草稿已保存,请手动预览并发布"
重要なルール
- 「Continue」は絶対にクリックしないでください - 公開フローが開始されます。下書きとしてのみ保存してください(自動保存されます)
- 必ず最初に HTML に変換してください - プレーンな Markdown は Tiptap エディターで解析されません
- クリップボードから貼り付けてください - 書式付きコンテンツを挿入する唯一の確実な方法です
- ログイン状態を確認してください - 必要に応じてユーザーにログインを促してください
- 元のファイルを保持してください - ソースの Markdown ファイルは変更しないでください
- 完了を報告してください - 下書きが保存され、手動での確認が必要であることをユーザーに伝えてください
nl2br拡張機能は使用しないでください - 二重の改行が発生します- テーブル → 画像 - コンテンツを貼り付ける前にテーブルを前処理してください。貼り付け後に画像をアップロードしてください
- Playwright のファイルパス - Playwright MCP ではファイルのアップロード先が許可されたルートに制限されています。アップロード前に一時ファイルをプロジェクトディレクトリにコピーしてください
- 先に公開先を解決してください - 公開先のサブドメインをハードコードしないでください。ナビゲーションを開始する前に、スキルの引数、
SUBSTACK_PUBLICATION環境変数、またはユーザーへの確認を通じて解決してください(「公開先の解決」を参照) - Playwright MCP を優先してください - デフォルトでは Playwright MCP を使用し、利用できない場合に限り Chrome DevTools MCP を使用してください
トラブルシューティング
コンテンツがプレーンテキストとして表示される(書式なし)
生の HTML タグや書式のないテキストが表示される場合:
- 原因:クリップボードから貼り付けずに、
fillツールを使ってコンテンツを挿入しました - 解決策:
copy_to_clipboard.py+ Cmd+V の方法を使用してください(ステップ 6 を参照)
テーブルが表示されない(プレーンテキストとして表示される)
Substack の Tiptap エディターは HTML テーブルに対応していません。テーブルはインラインのプレーンテキストにまとめられます。
- 解決策:diagram-to-image スキルを使ってテーブルを PNG に変換し、画像としてアップロードしてください(ステップ 0 とステップ 7 を参照)
- 代替策:シンプルなテーブルは、書式付きリストに再構成してください
- プレーンテキストをすでに貼り付けている場合:プレーンテキストの段落をトリプルクリックして選択し、Backspace を押して削除してから、その位置にテーブル画像を挿入してください
ログインが必要
ページにログインを促すメッセージが表示された場合:
请先登录 Substack: https://{publication}.substack.com
登录完成后告诉我。
エディターが読み込まれない
エディターの要素が表示されない場合:
- ページが完全に読み込まれるまで待ちます
- 新しいスナップショットを取得します
- それでも読み込まれない場合は、ページを再読み込みします
クリップボードへのコピーに失敗する
copy_to_clipboard.py が失敗する場合:
- 依存関係がインストールされていることを確認してください:
pip install pyobjc-framework-Cocoa(macOS) - HTML ファイルが存在し、読み取り可能であることを確認してください
- まず小さなテスト文字列のコピーを試してください
要素リファレンス
| 要素 | セレクター/識別子 | 説明 |
|---|---|---|
| タイトル入力欄 | textbox "title" | 投稿タイトル |
| サブタイトル入力欄 | textbox "Add a subtitle…" | 投稿のサブタイトル |
| コンテンツ領域 | .ProseMirror(Tiptap エディター) | 投稿コンテンツ |
| 保存状態 | button "Saved" | 自動保存インジケーター |
| プレビューボタン | button "Preview" | 投稿をプレビュー |
| Continue ボタン | button "Continue" | 使用禁止 - 公開フローが開始されます |
| 設定ボタン | button "Settings" | 設定サイドバーを開く |
| 終了ボタン | button "Exit" | エディターを終了 |
| 画像ボタン | button "Image" | 画像アップロードのドロップダウンを開く |
| 画像メニュー項目 | menuitem "Image" | 画像アップロード用のファイル選択画面を開く |
| 作成者ボタン | button "{PublicationName}" | 作成者/公開先の選択メニュー |
技術的な詳細
エディターの技術スタック
- Tiptap:ProseMirror を基盤とする、ヘッドレスでフレームワークに依存しないリッチテキストエディター
- ProseMirror:基盤となるリッチテキスト編集フレームワーク
- 貼り付け処理:Tiptap はクリップボードの HTML をネイティブに解析し、内部ドキュメントモデルに変換します
コンテンツ変換パイプライン
Markdown file
↓ (Python markdown library)
HTML string
↓ (copy_to_clipboard.py)
System clipboard (text/html + text/plain)
↓ (Cmd+V keyboard shortcut)
Tiptap ProseMirror editor
↓ (auto-save)
Substack draft
対応している書式
以下の Markdown 要素は、HTML に変換して貼り付けた後、正しく表示されます。
| Markdown 要素 | Substack の対応状況 | 備考 |
|---|---|---|
| 見出し(H2〜H6) | 対応 | H1 は非推奨です(タイトルは別に設定します) |
| 太字/斜体 | 対応 | |
| インラインコード | 対応 | |
| コードブロック | 対応 | 構文のハイライト表示は異なる場合があります |
| リンク | 対応 | |
| 引用 | 対応 | |
| 箇条書き | 対応 | |
| 番号付きリスト | 対応 | |
| 水平線 | 対応 | |
| 表 | 非対応 → 画像 | 図から画像への変換スキルで変換し、画像としてアップロードします |
| 画像 | 手動 | 画像ツールバーボタン → ファイル選択からアップロードします |