Claude Code×WordPressで記事の投稿・更新を自動化|WP-CLIの手順

Claude Code×WordPressで記事公開を完全自動化|WP-CLI実践手順

公式ドキュメント・公式発表などの一次情報を確認したうえで、株式会社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本作成するコマンドを実行する

この記事の著者
株式会社Nexa 代表取締役川島 陸

一橋大学経済学部卒業後、フォーティエンスコンサルティング株式会社(旧 株式会社クニエ)にて法人向けAI導入支援等を経験。独立後、AI系メディア運営やDify/n8nの導入支援を経て、株式会社Nexaを創業。法人向けAI研修・AI導入支援・AI関連メディア運営を手掛ける。

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スクリプトで変換し、次の処理も同時に行っています。

  1. 要約ボックスの変換: Markdownの引用(blockquote)で書いた要約を、スタイル付きのdiv要素に変換
  2. 表のスタイルの追加: 表の罫線が出ないテーマに備えて、インラインスタイルを挿入
  3. 目次の生成: 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顧問がサポートします。「何から始めればいいか分からない」という段階からご相談いただけます。

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化できるか」「どのツールを選ぶべきか」を、無料相談で整理します。

AI顧問の無料相談はこちら →





この記事で参照した外部情報

  1. Claude Code公式: セットアップcode.claude.com
  2. WP-CLI公式: Installingmake.wordpress.org
  3. pandoc公式マニュアルpandoc.org
  4. WP-CLI公式: wp post createdeveloper.wordpress.org
  5. WordPress公式: kses_init()developer.wordpress.org
  6. WordPress公式: Roles and Capabilitieswordpress.org
  7. WP-CLIのソースコード: Runner.phpgithub.com
  8. WordPress公式: kses_remove_filters()developer.wordpress.org
  9. WordPress公式: wp_update_post()developer.wordpress.org
  10. WP-CLI公式: wp post term setdeveloper.wordpress.org
  11. WP-CLI公式: wp media importdeveloper.wordpress.org
  12. WP-CLI公式: WP_CLI::error()make.wordpress.org
  13. Claude Code公式: Skillscode.claude.com
  14. Claude Code公式: Run Claude Code programmaticallycode.claude.com
  15. WP-CLI公式: wp post updatedeveloper.wordpress.org

本文中でリンクしている外部ページの一覧です(自動生成)。最終確認日は本記事の最終更新日 2026-09-29 で、リンク先の内容はその後変わることがあります。

AI導入を検討中の方へ

無料ホワイトペーパー

この記事に関連する資料(PDF・無料)

公式一次情報を確認して作成した実務資料です。会社名・お名前・メール・電話番号の入力でダウンロードできます。

資料一覧(13冊)を見る

AIの力で、ビジネスを次のステージへ

まずはお気軽にご相談ください。貴社に最適なAI活用プランをご提案します。