公開日: 最終更新:
公式ドキュメント・公式発表などの一次情報を確認したうえで、株式会社Nexaが執筆・更新しています。AIツールの仕様や料金は変わることがあるため、導入判断の前に各公式サイトの最新情報もご確認ください。運営会社について
Claude CodeにWP-CLIのコマンドを実行させると、WordPressの記事の作成、カテゴリ・SEOメタ・アイキャッチの設定、公開、公開後の更新までをターミナルから自動化できます(2026年9月29日時点)。
- 要点1: 本文はHTMLファイルのまま
wp post createに渡し、下書きで作成して表示を確認してから公開する - 要点2: JSON-LDのscriptタグが保存時に消えるのは、
--userで指定したユーザーに unfiltered_html の権限がない場合。--userを付けないWP-CLIは、無害化のフィルターを外して保存する - 要点3:
wp post term setに数字を渡すと、その数字が名前のカテゴリが作られる。IDで指定するときは--by=idを付ける
対象: WordPressで運営するメディアやブログの投稿作業を、Claude Codeで自動化したいWeb担当者・DX推進担当者
今日やること: テスト用のWordPressで、下書きを1本作成するコマンドを実行する
Claude CodeでWordPressの記事投稿を自動化するときは、サーバーにSSHで接続し、WordPress公式のコマンドラインツール「WP-CLI」を実行させる方法が扱いやすいです。管理画面で行っていた本文の入力、カテゴリの選択、SEOメタの入力、アイキャッチの設定、公開、公開後の修正を、コマンドで順に実行できます。
「記事を書いたあと、毎回管理画面でカテゴリを選んで、SEOメタを入力して、アイキャッチを設定して……」こうした定型的な作業に時間を取られているケースは少なくありません。
この記事では、あるメディアサイトで実際に構築した自動化フローをもとに、記事を投稿・更新する手順を、実行できるコマンドで解説します。コマンドと引数はWP-CLIとWordPressの公式ドキュメントで確認し、WordPress 7.1.2とWP-CLI 2.12.0の検証環境で動作を確かめました(確認日: 2026年9月29日)。
接続方法(ファイルの直接編集・WP-CLI・REST API・MCP)の違いと選び方は、「Claude Code×WordPress連携|4つの接続方法と選び方」で解説しています。この記事は、記事の投稿と更新の手順に絞ります。
Claude Code × WP-CLIで実現できること
まず、何が自動化されるのかの全体像を確認しておきます。
記事の投稿・更新で自動化できる6つの操作
| # | 操作 | 管理画面での作業 | 使うコマンド |
|---|---|---|---|
| 1 | 記事の作成(下書き) | エディターに本文を入力 | wp post create |
| 2 | カテゴリ・タグの設定 | 一覧から選択 | --post_category、wp post term set |
| 3 | SEOメタの設定 | SEOプラグインの入力欄に入力 | wp post meta update |
| 4 | アイキャッチ画像の設定 | 画像をアップロードして選択 | scp + wp media import |
| 5 | 公開・予約投稿 | 公開ボタンをクリック | wp post update |
| 6 | 公開済み記事の更新 | エディターで本文を修正 | wp post get、wp post update |
作業の流れは、原稿をHTMLに変換する、下書きを作成する、カテゴリ・SEOメタ・アイキャッチを設定する、表示を確認して公開する、の順です。公開後に内容を直すときは、バックアップを取ってから本文を更新します。
これらをClaude Codeのスキルとして定義しておくと、「このMarkdownファイルをWordPressに下書きで入れて」と指示するだけで、一連の操作が実行されます。
管理画面操作との比較
あるメディアサイトの運用チームでは、この自動化を導入する前後で以下の変化がありました。
| 指標 | 導入前 | 導入後 |
|---|---|---|
| 記事1本の公開作業時間 | 約30〜45分 | 約5分(確認含む) |
| SEOメタの設定漏れ | 月に数件発生 | ゼロ(必ず自動設定) |
| カテゴリ設定ミス | 月に1〜2件 | ゼロ(スラッグで動的設定) |
| アイキャッチ未設定 | 月に2〜3件 | ゼロ(ファイル存在を自動検知) |
特に効果が大きかったのは「設定漏れがなくなった」点です。設定する項目をコマンドに固定したことで、入力のし忘れが起きなくなりました。これは1つのサイトでの例で、効果は記事の本数や体制によって変わります。
前提条件と環境セットアップ
必要な前提条件
この自動化フローを実行するために、以下が必要です。
- WordPressが動いているサーバーへのSSH接続(鍵認証)
- サーバー上のWP-CLI(PHP 7.2.24以降が必要)
- 手元のパソコンのClaude Code
- MarkdownをHTMLに変換する手段(pandocなど)
Claude Codeをまだ導入していない場合は、公式ドキュメントが推奨しているネイティブインストールを使います。
# macOS / Linux / WSL
curl -fsSL https://claude.ai/install.sh | bash
claude --version
npm(npm install -g @anthropic-ai/claude-code)でも導入できます。v2.1.198以降のnpmパッケージは、Node.js 22以上を必要とします(Claude Code公式: セットアップ)。導入の流れは「Claude Code 始め方ガイド」にまとめています。
WP-CLIのインストール
レンタルサーバーによっては、最初からWP-CLIが入っています。SSHで接続して wp --info を実行し、バージョン情報が表示されれば、インストールは不要です。入っていない場合は、公式の手順でダウンロードします(WP-CLI公式: Installing)。
# サーバーのホームディレクトリで実行する
cd ~
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
# 管理者権限がある場合は、wp という名前で実行できるようにする
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
管理者権限(sudo)が使えない共用サーバーでは、最後の2行を実行せず、ホームディレクトリに置いたまま php ~/wp-cli.phar として実行します。この記事のコマンドは、この書き方で統一しています。wp として実行できる環境では、読み替えてください。
SSH設定ファイルの書き方
手元のパソコンの ~/.ssh/config に接続先を書いておくと、コマンドが短くなります。次の例の mysite、example.com、deploy は例示用の値です。自分の環境の値に置き換えてください。
Host mysite
HostName example.com
User deploy
IdentityFile ~/.ssh/id_ed25519
この設定があると、ssh mysite だけで接続できます。
WP-CLIの動作確認
手元のパソコンから、次の2つを実行します。
# WP-CLIが動くかを確認する
ssh mysite 'php ~/wp-cli.phar --info'
# WordPressを読み込めるかを確認する(バージョンが表示されれば成功)
ssh mysite 'php ~/wp-cli.phar --path=$HOME/public_html/example.com core version'
--path には、WordPressを設置したディレクトリを指定します。パスが違うと「Error: This does not seem to be a WordPress installation.」と表示されます。php が見つからない場合は、サーバー上で which php を実行してパスを確認してください。
この記事のコマンドの読み方
STEP 2以降のコマンドは、サーバーにSSHでログインした状態で実行する書き方にしています。最初に、WP-CLIの呼び出しを wp という名前の関数にまとめておきます。
# 手元のパソコンから、サーバーにログインする
ssh mysite
# サーバー上で、WP-CLIの呼び出しを関数にまとめる(パスは自分の環境に合わせる)
wp() { php "$HOME/wp-cli.phar" --path="$HOME/public_html/example.com" "$@"; }
wp core version
関数にしておくと、bashでもzshでも同じ書き方で動き、空白を含むタイトルもそのまま渡せます。wp というコマンドが最初から使えるサーバーでは、この定義は不要です。
SSH越しに1行ずつ実行すると、引用符が二重になり、タイトルに含まれる空白や記号が崩れやすくなります。手元のパソコンからまとめて実行する方法は、「自動化フロー全体をスキルとして組み込む方法」で説明します。
ポイント最初は、本番ではなくテスト用のWordPress(ステージングやローカル環境)で一連の手順を試してください。コマンドは確認なしで記事を作成・変更します。
STEP 1 — 記事本文のMarkdown → HTML変換
frontmatterの書き方と必要なフィールド
記事はMarkdown形式で管理します。先頭にfrontmatterを記述し、メタ情報をまとめておきます。
---
title: 記事タイトル
description: メタディスクリプション(120文字以内)
category: カテゴリのスラッグ(例: claude-code)
target_kw: ターゲットキーワード
slug: パーマリンク用スラッグ(英語)
---
タイトル、説明文、カテゴリ、スラッグをこのfrontmatterから読み取ってコマンドに渡すと、設定値がMarkdownファイル1つにまとまります。
MarkdownをHTMLに変換する
変換に使う道具は問いません。pandocを使う場合は、次の1行で変換できます。
# 手元のパソコンで実行する
pandoc -f markdown -t html article.md -o article.html
pandocは、既定では <head> や <body> を含まない本文だけのHTMLを出力します。ファイル先頭のfrontmatterはメタデータとして読み取られ、本文には出力されません(pandoc公式マニュアル)。
あるメディアサイトでは、自作のPythonスクリプトで変換し、次の処理も同時に行っています。
- 要約ボックスの変換: Markdownの引用(blockquote)で書いた要約を、スタイル付きのdiv要素に変換
- 表のスタイルの追加: 表の罫線が出ないテーマに備えて、インラインスタイルを挿入
- 目次の生成: h2見出しからアンカー付きの目次を作り、記事の冒頭に挿入
こうした変換スクリプトも、仕様を伝えればClaude Codeに作成させられます。
構造化データ(JSON-LD)を本文に入れる場合
記事の構造化データをテーマやSEOプラグインが出力していないサイトでは、本文HTMLの末尾にJSON-LDを加える方法があります。Googleは、構造化データの形式としてJSON-LDを推奨しています(Google検索セントラル: 構造化データの仕組み)。
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "記事タイトル",
"datePublished": "2026-09-29T10:00:00+09:00",
"dateModified": "2026-09-29T10:00:00+09:00"
}
</script>
ポイントGoogleのAIによる概要(AI Overview)やAIモードに表示されるために、特別な構造化データを追加する必要はありません(Google検索セントラル: AI機能とウェブサイト)。構造化データは、ページの内容をGoogleに正確に伝えるためのものです。画面に表示されている本文と、内容を一致させてください。
STEP 2 — WP-CLIで記事を作成・公開する
本文をファイルで渡して下書きを作成する
変換したHTMLとアイキャッチ画像を、サーバーの作業用フォルダに転送します。
# 手元のパソコンから実行する
ssh mysite 'mkdir -p ~/wp-publish'
scp article.html thumbnail.png mysite:~/wp-publish/
続いて、サーバー上で下書きを作成します。wp post create は、最初の引数にファイルを指定すると、その内容を本文として読み込みます(WP-CLI公式: wp post create)。
# 投稿者にするユーザーのIDを調べる
wp user list --fields=ID,user_login,roles
# 本文をファイルで渡して、下書きを作成する(AUTHOR_ID は上で調べたIDに置き換える)
AUTHOR_ID=2
POST_ID=$(wp post create "$HOME/wp-publish/article.html" \
--post_title='記事タイトル' \
--post_name='sample-post' \
--post_status=draft \
--post_author=$AUTHOR_ID \
--porcelain)
echo "投稿ID: $POST_ID"
- ファイルの指定: ファイルを指定すると
--post_contentは無視される。ファイル名の代わりに-を渡すと、標準入力から本文を読み込む --post_status: 省略した場合も下書き(draft)になる。最初から公開(publish)を指定するのは避ける--post_author:--userを付けずに実行すると、WordPress上の「現在のユーザー」がいない状態になる。検証環境では、この指定を省くと投稿者が未設定(ID 0)の記事になった--porcelain: 作成された投稿のIDだけを出力する。変数に入れて、以降のコマンドで使う
長いHTMLを --post_content= に直接書く方法は、引用符や改行の扱いで壊れやすいため、ファイルで渡す方法をおすすめします。
scriptタグ(JSON-LD)が保存時に消える条件
「JSON-LDを含むHTMLを保存したら、<script> タグが消えていた」という現象は、保存を実行したユーザーの権限で決まります。WordPressは、unfiltered_html という権限を持たないユーザーが保存する内容に、KSESと呼ばれる無害化のフィルターを適用します(WordPress公式: kses_init())。このフィルターは、scriptタグなど、許可されていないHTMLを取り除きます。
unfiltered_html の権限を持つのは、通常のサイト(単一サイト)では管理者と編集者です。投稿者と寄稿者は持ちません。マルチサイトでは、特権管理者だけが持ちます(WordPress公式: Roles and Capabilities)。
WP-CLIで記事を保存したときの結果は、次のとおりです(WordPress 7.1.2とWP-CLI 2.12.0の単一サイトで、4つの権限それぞれを確認)。
| 実行の仕方 | scriptタグ | 補足 |
|---|---|---|
--user を付けない |
残る | WP-CLIが無害化のフィルターを外して保存する。投稿者は --post_author で指定する |
--user に管理者・編集者を指定 |
残る | 指定したユーザーが投稿者になる。マルチサイトでは、特権管理者でなければ消える |
--user に投稿者・寄稿者を指定 |
消える | タグだけが除かれ、JSON-LDの中身が文字として本文に残る |
--user を付けない場合にscriptタグが残るのは、WP-CLI自身が、WordPressの読み込み時に kses_remove_filters() を呼び出しているためです(WP-CLIのソースコード: Runner.php)。
フィルターの解除で外れるものと、守ること
kses_remove_filters() は、scriptタグを削除する関数ではありません。無害化のフィルターを解除する関数です。公式リファレンスによると、解除されるのは、投稿のタイトル、本文、抜粋、コメント本文を保存するときのフィルターです(WordPress公式: kses_remove_filters())。
フィルターが外れている間は、JSON-LDに限らず、どのscriptタグも、iframeも、イベント属性(onclickなど)も、書かれたとおりに保存されます。悪意のあるコードが混ざったHTMLを渡すと、そのまま公開ページに出力されます。次の3点を守ってください。
- 渡すHTMLは、自分たちで作成して内容を確認したものに限る: 外部サイトから取得した文章、フォームの入力、第三者から受け取ったHTMLを、そのまま流し込まない
- 保存の前に、機械的に点検する: 意図したJSON-LD以外のscriptタグなどが含まれていないかを確認する
- 実行できる人と場所を絞る: WP-CLIを実行できるSSHユーザーを限定し、鍵を共有しない
# scriptタグ、iframe、イベント属性、javascript: を含む行を表示する
grep -n -i -E '<script|<iframe|[[:space:]]on[a-z]+=|javascript:' article.html
意図して入れたJSON-LDの行だけが表示されれば問題ありません。Claude Codeに生成させたHTMLも、同じように点検します。
なお、$wpdb->update() でデータベースを直接書き換える方法でも、scriptタグは残ります。ただし、WordPressの保存処理を通らないため、リビジョンが作られず、更新日時も変わりません。wp post create と wp post update は保存処理を通るので、この記事ではこちらを使います。
表示を確認してから公開する
下書きの状態で、管理画面のプレビューを人が確認します。問題がなければ、公開に切り替えます。
# 状態を確認する
wp post list --post__in=$POST_ID --post_status=any --fields=ID,post_title,post_status,post_name
# 公開する
wp post update $POST_ID --post_status=publish
# 予約投稿にする場合(日時はサイトのタイムゾーン。--edit_date=true を必ず付ける)
wp post update $POST_ID --post_status=future --post_date='2026-10-01 10:00:00' --edit_date=true
# 状態が future になったことを確認する
wp post get $POST_ID --fields=ID,post_status,post_date
下書きを予約投稿に切り替えるときは、--edit_date=true を付けます。検証環境では、これを付けずに実行すると、指定した日時が無視されて、その場で公開されました。WordPressは、下書きの日付を、明示的な指定がない限り現在の日時に置き換えるためです(WordPress公式: wp_update_post())。
STEP 3 — カテゴリ・タグの動的設定
数字をそのまま渡すと、数字の名前のカテゴリが作られる
カテゴリの設定でよくある間違いが、カテゴリのID(term_id)を、そのままコマンドに渡すことです。
# NG: 5 は「IDが5のカテゴリ」ではなく「スラッグが5のカテゴリ」として扱われる
wp post term set $POST_ID category 5
wp post term set は、渡された値を、既定ではスラッグとして扱います(WP-CLI公式: wp post term set)。スラッグが「5」のカテゴリが無ければ、「5」という名前のカテゴリが新しく作られ、記事はそのカテゴリに入ります。検証環境でも、同じ結果になりました。
あるメディアサイトで実際に発生したトラブルとして、term_idの固定値指定を使った結果、「2」「14」「5」といった数値そのものがカテゴリ名として登録されてしまい、記事が誤ったカテゴリに分類されるという問題が起きました。修正のために15本以上の記事のカテゴリを一括で直すことになりました。
記事の作成時にスラッグで指定する
安全なのは、記事を作成するときに --post_category で指定する方法です。カテゴリの名前、スラッグ、IDのいずれでも指定でき、該当するカテゴリが無い場合はエラーで止まります。意図しないカテゴリが作られません。
# 作成時に指定する(STEP 2のコマンドに1行加える)
POST_ID=$(wp post create "$HOME/wp-publish/article.html" \
--post_title='記事タイトル' \
--post_name='sample-post' \
--post_status=draft \
--post_author=$AUTHOR_ID \
--post_category=claude-code \
--porcelain)
# タグは、カンマ区切りの名前で指定する(無いタグは作成される)
wp post update $POST_ID --tags_input='WP-CLI,自動化'
作成済みの記事のカテゴリを変更する
カテゴリが無ければ作成し、そのうえで設定する場合は、次のように書きます。
# スラッグからカテゴリのIDを調べる(無ければ空になる)
TERM_ID=$(wp term list category --slug=claude-code --field=term_id)
# 無ければ作成する
if [ -z "$TERM_ID" ]; then
TERM_ID=$(wp term create category 'Claude Code' --slug=claude-code --porcelain)
fi
# IDで指定するときは --by=id を付ける
wp post term set $POST_ID category $TERM_ID --by=id
スラッグが分かっていれば、wp post term set $POST_ID category claude-code と書いても同じ結果になります。IDで指定する場合は、必ず --by=id を付けます。
setは、記事のカテゴリを、指定したものに置き換える。今のカテゴリを残して追加するときはwp post term addを使う--by=idに存在しないIDを渡すと、検証環境ではエラーにならず、記事のカテゴリがすべて外れた。IDが空でないことを確認してから実行する
AI導入に関するお困りごとは、株式会社NexaのAI顧問がサポートします。「何から始めればいいか分からない」という段階からご相談いただけます。
STEP 4 — SEOメタ情報の設定
SEOプラグインのタイトルと説明文は、多くの場合、投稿のカスタムフィールド(メタ情報)に保存されています。wp post meta update で設定できます。SEO SIMPLE PACKの場合は、次のキーを使います。
# SEOタイトル
wp post meta update $POST_ID ssp_meta_title '記事タイトル|サイト名'
# メタディスクリプション
wp post meta update $POST_ID ssp_meta_description 'メタディスクリプション(120文字以内)'
# 設定した値を確認する
wp post meta get $POST_ID ssp_meta_title
主なプラグインのキーは、次のとおりです。各プラグインの配布ファイルで確認しました(2026年9月29日時点の最新版)。
| プラグイン | SEOタイトル | メタディスクリプション |
|---|---|---|
| SEO SIMPLE PACK(3.7.0) | ssp_meta_title |
ssp_meta_description |
| Yoast SEO(28.6) | _yoast_wpseo_title |
_yoast_wpseo_metadesc |
| Rank Math(1.0.279) | rank_math_title |
rank_math_description |
- SEO SIMPLE PACKのキーは、先頭にアンダースコアが付かない。
_ssp_meta_titleと書くと、別のキーとして保存され、検索結果用のタイトルには反映されない - All in One SEO(5.0.2)は、タイトルと説明文を専用のテーブル(aioseo_posts)で管理している。
wp post meta updateで書き込んでも、出力には反映されない
キーの名前はプラグインの更新で変わることがあります。管理画面で1件だけ手入力し、次のコマンドで実際のキーを確認してから自動化してください。
# その記事に保存されているメタ情報を一覧で表示する
wp post meta list $POST_ID
\ AI活用の「次の一手」を一緒に考えませんか /
AI顧問の無料相談はこちらSTEP 5 — アイキャッチ画像のアップロードと設定
media importコマンドで取り込みと設定を同時に行う
アイキャッチ画像は、wp media import でメディアライブラリに取り込みます。--post_id と --featured_image を付けると、取り込みと同時に、その記事のアイキャッチに設定されます(WP-CLI公式: wp media import)。
# 画像を取り込み、記事のアイキャッチに設定する
ATTACHMENT_ID=$(wp media import "$HOME/wp-publish/thumbnail.png" \
--post_id=$POST_ID \
--title='記事タイトル' \
--alt='画像の内容を説明する文' \
--featured_image \
--porcelain)
echo "画像ID: $ATTACHMENT_ID"
# 設定されたことを確認する(画像IDが表示される)
wp post meta get $POST_ID _thumbnail_id
--porcelain を付けると、取り込んだ画像のIDだけが出力されます。--alt には、キーワードの羅列ではなく、画像の内容を説明する文を入れます。
画像ファイルの有無を自動判定する
画像が無い記事でも処理が止まらないように、ファイルがあるときだけ取り込みます。
THUMBNAIL="$HOME/wp-publish/thumbnail.png"
if [ -f "$THUMBNAIL" ]; then
wp media import "$THUMBNAIL" --post_id=$POST_ID --featured_image --porcelain
else
echo "thumbnail.pngが存在しません。アイキャッチはスキップします"
fi
自動化フロー全体をスキルとして組み込む方法
STEP 2〜5を1つのスクリプトにまとめる
ここまでのコマンドを、サーバー上で実行するスクリプト publish.sh にまとめます。記事ごとに変える値は、先頭にまとめてあります。
#!/bin/bash
# publish.sh — サーバー上で実行し、下書きを1本作成する
set -eu
# WP-CLIの呼び出し(パスは自分の環境に合わせる)
wp() { php "$HOME/wp-cli.phar" --path="$HOME/public_html/example.com" "$@"; }
DIR="$HOME/wp-publish"
# 記事ごとに変える値(frontmatterから転記する)
TITLE='記事タイトル'
SLUG='sample-post'
CATEGORY='claude-code'
DESCRIPTION='メタディスクリプション'
AUTHOR_ID=2
# 同じスラッグの記事があれば中止する(二重投稿の防止)
EXISTING=$(wp post list --name="$SLUG" --post_type=post \
--post_status=publish,draft,pending,future,private --format=ids)
if [ -n "$EXISTING" ]; then
echo "同じスラッグの記事があります(ID: ${EXISTING})。中止します。"
exit 1
fi
# 下書きを作成する(カテゴリが無い場合はエラーで止まる)
POST_ID=$(wp post create "$DIR/article.html" \
--post_title="$TITLE" --post_name="$SLUG" \
--post_status=draft --post_author="$AUTHOR_ID" \
--post_category="$CATEGORY" --porcelain)
# SEOメタを設定する(SEO SIMPLE PACKの場合)
wp post meta update "$POST_ID" ssp_meta_title "$TITLE"
wp post meta update "$POST_ID" ssp_meta_description "$DESCRIPTION"
# アイキャッチ画像があれば設定する
if [ -f "$DIR/thumbnail.png" ]; then
wp media import "$DIR/thumbnail.png" --post_id="$POST_ID" \
--title="$TITLE" --alt="$TITLE" --featured_image --porcelain
fi
echo "下書きを作成しました(ID: ${POST_ID})"
手元のパソコンからは、ファイルを転送して、スクリプトを実行します。
# 手元のパソコンから実行する
ssh mysite 'mkdir -p ~/wp-publish'
scp article.html thumbnail.png publish.sh mysite:~/wp-publish/
ssh mysite 'bash ~/wp-publish/publish.sh'
set -euを指定しているので、途中のコマンドが失敗すると、その時点で止まる。WP-CLIは、エラー時に終了コード1を返す(WP-CLI公式: WP_CLI::error())- 日本語の全角文字の直前に変数を書くときは、
${POST_ID}のように波かっこで囲む。囲まないと、古いbashでは変数名の一部として読まれ、エラーになる - スラッグで記事を探すときは、状態を
publish,draft,pending,future,privateのように並べる。検証環境では、--post_status=anyと--nameの組み合わせでは、下書きが見つからなかった
スキルとして定義するメリット
Claude Codeでは、繰り返し実行する手順を「スキル」(SKILL.md)として定義できます。プロジェクト用は .claude/skills/<スキル名>/SKILL.md、個人用は ~/.claude/skills/<スキル名>/SKILL.md に置きます(Claude Code公式: Skills)。スキルとして定義しておくと、以下のメリットがあります。
- 再現性の向上: コマンドの順序や引数が固定されるため、実行ミスが減る
- チーム展開: スキルファイルを共有するだけで、他のメンバーも同じ自動化フローを使える
- エラー対応の標準化: エラーが発生した場合の対処手順もスキルに含めておける
---
name: wp-publish
description: MarkdownをHTMLに変換し、WordPressに下書きとして投稿する
disable-model-invocation: true
---
# WordPressに下書きを投稿する
対象のMarkdownファイル: $ARGUMENTS
次の順に処理する。
1. frontmatterから title、slug、category、description を読み取る
2. pandocでHTMLに変換し、article.html として保存する
3. article.html を点検する。意図したJSON-LD以外の script、iframe、イベント属性があれば中止して報告する
4. publish.sh の先頭の値を、1で読み取った値に書き換える
5. article.html、thumbnail.png、publish.sh を scp でサーバーの ~/wp-publish/ に転送する
6. ssh mysite 'bash ~/wp-publish/publish.sh' を実行する
7. 作成された投稿IDを報告する。公開はしない
Claude Codeで /wp-publish drafts/article.md と入力すると、この手順が実行されます。disable-model-invocation: true は、Claudeが自分の判断でこのスキルを起動しないようにする設定です。投稿のように外部へ影響する手順は、人が起動したときだけ動くようにします。スキルの作り方は「Claude Code Skillsの作り方」で解説しています。
cronジョブとの組み合わせ
Claude Codeは、claude -p で、対話画面を開かずに実行できます。スキルは、指示文の中に /スキル名 を書いて呼び出します(Claude Code公式: Run Claude Code programmatically)。これをcronジョブに組み込むと、決まった時刻に投稿の処理を動かせます。
# 対話画面を開かずに実行する。使ってよい道具を --allowedTools で指定する
claude -p "/wp-publish drafts/article.md" \
--allowedTools "Read,Edit,Bash(pandoc *),Bash(grep *),Bash(scp *),Bash(ssh mysite *)"
あるメディアサイトでは、以下のようなスケジュールで記事を自動公開しています。
- 平日 10:00: 前日までに準備完了した記事を1本自動公開
- 平日 13:00: キーワードリストから次の記事のリサーチ〜執筆を自動開始
- 平日 22:00: 当日公開した記事のインデックス申請を自動実行
このフローにより、週5本のペースでの記事公開を、担当者の直接操作なしで継続できています。
これから始める場合は、自動化する範囲を下書きの作成までにして、公開は人が内容を確認してから行う運用をおすすめします。無人で公開まで進めるのは、点検の仕組みが整ってからにしてください。
公開済みの記事を更新する手順
公開済みの記事の本文を直すときは、今の本文をファイルに保存してから、wp post update で更新します。wp post update も、投稿IDのあとにファイルを指定すると、その内容を本文として読み込みます(WP-CLI公式: wp post update)。
# スラッグから投稿IDを調べる
POST_ID=$(wp post list --name=sample-post --post_type=post \
--post_status=publish,draft,pending,future,private --format=ids)
echo "投稿ID: $POST_ID"
# 今の本文をバックアップする
wp post get $POST_ID --field=post_content > "$HOME/wp-publish/backup-$POST_ID-$(date +%Y%m%d).html"
# 新しい本文で更新する
wp post update $POST_ID "$HOME/wp-publish/article.html"
# 更新されたことを確認する
wp post get $POST_ID --fields=ID,post_title,post_status,post_modified
- リビジョンが残る: 検証環境では、更新のたびにリビジョンが作られた。管理画面の編集画面から、以前の本文に戻せる
- タイトルや説明文も同じ形で更新できる: タイトルは
--post_title=、SEOメタはwp post meta updateを使う - スラッグは変えない:
--post_name=を変えるとURLが変わる。検索結果や他の記事からのリンクに影響する - 投稿IDが空のまま実行しない: スラッグが違っていると、投稿IDが空になる。IDが表示されたことを確認してから、次のコマンドに進む
scriptタグが残る条件は、作成のときと同じです。--user に投稿者や寄稿者を指定して更新すると、本文に入っていたJSON-LDのタグが除かれます。
SSHが使えない場合はREST APIで投稿・更新する
SSHが使えないサーバーでは、REST APIとアプリケーションパスワードで、同じ流れを組めます。アプリケーションパスワードの発行方法と下書きを作成するコマンドは、「4つの接続方法と選び方」で解説しています。ここでは、更新の要点だけを示します。
記事の更新は、POST /wp/v2/posts/<id> に、変更する項目だけを送ります(WordPress公式: REST API Posts)。本文をファイルから送る場合は、jqでJSONに変換します。
# 手元のパソコンから実行する。POST_ID は更新する記事のID
# WP_USER と WP_APP_PASSWORD は環境変数で渡す
jq -Rs '{content: .}' article.html | curl --user "$WP_USER:$WP_APP_PASSWORD" \
-X POST "https://example.com/wp-json/wp/v2/posts/$POST_ID" \
-H "Content-Type: application/json" \
--data-binary @-
WP-CLIとの違いは、次の3点です。
- 権限は、アプリケーションパスワードを発行したユーザーのものになる: 投稿者や寄稿者のユーザーで保存すると、本文のscriptタグは無害化のフィルターで除かれる。JSON-LDを本文に入れないサイトなら、投稿者の権限で足りる
- SEOプラグインのメタ情報は、設定できない場合がある: REST APIの
metaで読み書きできるのは、REST APIに公開する設定(show_in_rest)で登録されたキーに限られる - アイキャッチは、画像のIDで指定する: 画像をメディアとして登録し、そのIDを
featured_mediaに指定する
アプリケーションパスワードは、指示文やCLAUDE.mdに書かず、環境変数で渡します。仕様は「REST API Handbook: Authentication」に記載されています。
本番で動かす前の5つの確認点
自動化のコマンドは、確認の画面を挟まずに記事を作成・変更します。本番のサイトで動かす前に、次の5点を確認してください。
| 確認点 | 内容 |
|---|---|
| 1. テスト環境で先に試す | ステージングやローカル環境で、作成から更新までを一通り実行する |
| 2. 最初は下書きで作成する | 公開は、人がプレビューを確認してから切り替える |
| 3. 渡すHTMLを点検する | 自分たちで作成したHTMLに限り、意図しないscriptタグが無いことを確認する |
| 4. 更新の前にバックアップを取る | 今の本文をファイルに保存してから更新する |
| 5. 実行できる人と操作を絞る | SSHの鍵を共有せず、Claude Codeに許可するコマンドを限定する |
Claude Codeに許可するコマンドの絞り方は「Claude Code セキュリティガイド」で解説しています。本番に接続する設定を作る前に、確認してください。
よくある質問
Q. Claude CodeでWordPressの記事投稿は、どこまで自動化できますか?
記事の作成、カテゴリとタグの設定、SEOメタの設定、アイキャッチ画像の設定、公開、公開後の本文の更新まで自動化できます。WP-CLIのコマンドをClaude Codeに実行させる方法です。最初は下書きの作成までを自動化し、公開は人が確認してから行う運用をおすすめします。
Q. wp post createで–post_contentに直接HTMLを渡せないの?
渡せます。ただし、長いHTMLは引用符や改行の扱いで壊れやすいため、ファイルで渡す方法をおすすめします。wp post create は、最初の引数にファイルを指定すると、その内容を本文として読み込みます。
Q. JSON-LDのscriptタグが、保存したときに消えてしまうのはなぜ?
保存を実行したユーザーに unfiltered_html の権限が無いためです。WordPressは、この権限を持たないユーザーが保存する内容からscriptタグを取り除きます。WP-CLIでは、--user に投稿者や寄稿者を指定した場合に起こります。--user を付けない場合と、管理者・編集者を指定した場合(単一サイト)は、scriptタグが残ります。
Q. kses_remove_filtersは、scriptタグを削除する関数ですか?
いいえ。無害化のフィルター(KSES)を解除する関数です。解除されている間は、scriptタグやiframeも、書かれたとおりに保存されます。--user を付けないWP-CLIはこの状態で保存するので、渡すHTMLは、自分たちで作成して内容を確認したものに限ってください。
Q. カテゴリが「2」「14」という名前になってしまう問題の原因は?
wp post term set に数字を渡したためです。このコマンドは、渡された値を既定ではスラッグとして扱い、該当するカテゴリが無ければ、その名前で新しく作ります。IDで指定するときは --by=id を付けます。記事の作成時に --post_category で指定する方法なら、カテゴリが無い場合にエラーで止まります。
Q. SSH接続先でWP-CLIが見つからないというエラーが出る場合は?
サーバー上で which wp を実行し、WP-CLIの場所を確認してください。見つからない場合は、php ~/wp-cli.phar のように、ファイルの場所を直接指定して実行します。php の場所がサーバーによって違うこともあるため、which php でも確認します。
Q. SEO SIMPLE PACK以外のSEOプラグインにも同じ方法が使える?
Yoast SEOとRank Mathは、キーの名前が違うだけで、同じく wp post meta update で設定できます。All in One SEOは、タイトルと説明文を専用のテーブルで管理しているため、この方法では反映されません。キーの名前はSTEP 4の表を参照してください。
Q. SSHが使えないレンタルサーバーでも自動化できますか?
できます。REST APIとアプリケーションパスワードを使い、記事の作成と更新を行います。ただし、保存はアプリケーションパスワードを発行したユーザーの権限で行われ、SEOプラグインのメタ情報は設定できない場合があります。
まとめ
Claude Code × WP-CLIで、記事の投稿・更新を自動化するときのポイントをまとめます。
- STEP 1: MarkdownをHTMLに変換する。メタ情報はfrontmatterにまとめる
- STEP 2: HTMLファイルを
wp post createに渡し、下書きで作成する。確認してから公開する - STEP 3: カテゴリは
--post_categoryにスラッグで指定する。IDを渡すときは--by=idを付ける - STEP 4: SEOメタは、プラグインのキーを確認して
wp post meta updateで設定する - STEP 5: アイキャッチは
wp media importに--featured_imageを付けて設定する - 更新: 今の本文をバックアップしてから、ファイルで上書きする
scriptタグが残るかどうかは、保存を実行するユーザーの権限で決まります。--user を付けないWP-CLIは、無害化のフィルターを外して保存するため、渡すHTMLは内容を確認したものに限ってください。
管理画面での手作業に時間を取られているチームほど、導入効果を感じやすいでしょう。まずはテスト環境で、下書きを1本作成するところから試してみることをおすすめします。
法人向けAI導入・活用の月額伴走サービス
AI導入の疑問を、週1回のMTGで相談できる「AI顧問」
株式会社Nexaでは、ChatGPT・Claude・Claude CodeなどのAI導入に関する質問や、社内活用・業務自動化の進め方を週1回相談できる 月額7万円(毎月3社限定で月額5万円)のAI顧問サービス を提供しています。
「自社では何から始めるべきか」「この業務はAI化できるか」「どのツールを選ぶべきか」を、無料相談で整理します。
この記事で参照した外部情報
- Claude Code公式: セットアップcode.claude.com
- WP-CLI公式: Installingmake.wordpress.org
- pandoc公式マニュアルpandoc.org
- WP-CLI公式: wp post createdeveloper.wordpress.org
- WordPress公式: kses_init()developer.wordpress.org
- WordPress公式: Roles and Capabilitieswordpress.org
- WP-CLIのソースコード: Runner.phpgithub.com
- WordPress公式: kses_remove_filters()developer.wordpress.org
- WordPress公式: wp_update_post()developer.wordpress.org
- WP-CLI公式: wp post term setdeveloper.wordpress.org
- WP-CLI公式: wp media importdeveloper.wordpress.org
- WP-CLI公式: WP_CLI::error()make.wordpress.org
- Claude Code公式: Skillscode.claude.com
- Claude Code公式: Run Claude Code programmaticallycode.claude.com
- WP-CLI公式: wp post updatedeveloper.wordpress.org
本文中でリンクしている外部ページの一覧です(自動生成)。最終確認日は本記事の最終更新日 2026-09-29 で、リンク先の内容はその後変わることがあります。
AI導入を検討中の方へ








