canai-yolo について
canai-yoloは、CanAI MCPツールを使ってFluentSnippets内のPHP、CSS、JSコードスニペットを管理するオプトイン型スキルです。スニペット操作とデプロイ時の保護策を扱い、明示的に依頼された作業に限って使用します。
主な機能
- 01スニペットの一覧表示と読み取り
- 02スニペットの作成と更新
- 03保護策を備えたスニペット公開
- 04ハッシュ確認付きのコード置換
- 05保存コードのハッシュとキャッシュ状態の確認
- 06CanAIの言語処理方法を説明
活用シーン
- 01サイト固有のスニペットを確認
- 02FluentSnippetsコードを作成または更新
- 03依頼されたPHPスニペットを公開
- 04スニペットの書き込みとキャッシュ状態を検証
MCP 対応
`{site}/wp-json/mcp/wpcanai`のCanAI MCPサーバーをAPIキーで利用します。FluentSnippetsを管理するツールを説明しており、プラグインが有効な場合にのみ登録されます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ usewp/ canai --skill canai-yoloインストール後、Claude Code で/canai-yoloを入力して読み込まれたか確認します。
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
CanAI YOLO — FluentSnippets MCP ツール
高リスクです。オプトインが必要です。 このスキルでは、WordPress サイトに PHP を永続的に公開できる MCP ツールについて説明します。インストールして呼び出すのは、ユーザーがスニペットの作業を明示的に希望している場合のみにしてください。
テンプレート、ページ、i18n、メディア、設定、Tailwind には、代わりに canai-mcp を使用してください。ユーザーがこのスキルを求めていない限り、通常の /canai-mcp コンテンツセッションに YOLO ワークフローを混在させないでください。
トランスポートは canai-mcp と同じ CanAI MCP サーバー({site}/wp-json/mcp/wpcanai)と API キーを使用します。機能 ID にはスラッシュを使用し、MCP ツール名にはハイフンを使用します。
重要 — このスキルを使う場合
canai-yolo は、次の場合にのみ使用してください。
- FluentSnippets(
easy-code-manager)— 専用の MCP ツールを使って、サイトの PHP、CSS、または JS スニペットを一覧表示、読み取り、作成、更新、公開します。
eval による回避策はありません。
wpcanai/eval機能はプラグイン v1.59.0 で削除されました — WP.org はeval()を全面的に禁止しています — そしてWPCANAI_ENABLE_EVALは読み取られなくなりました。すべての機能は実際の機能として提供されており、代替手段はありません。ワークフローで eval が必要に思える場合は、その場で即興の対応をするのではなく、不足している機能をリクエストしてください。オプトインのアドオンプラグインが計画されています(specs/2026-08-20-canai-eval-addon-design.md)。
FluentSnippets(PHP/CSS/JS スニペット)
サイト固有の PHP、CSS、JS は、プラグインコードではなく FluentSnippets に保存されていることがよくあります。ツール:wpcanai-list-snippets、wpcanai-get-snippet、wpcanai-create-snippet、wpcanai-update-snippet、wpcanai-replace-in-snippet、wpcanai-set-snippet-status。説明は [fluent-snippets] / [fluent-snippets, filesystem] で始まります(書き込み後にサイトがページキャッシュを消去する場合は cache も付きます)。canai-mcp の ツールラベル を参照してください。
スキーマだけでは分かりにくい重要なルール:
-
ツールが表示されるのは FluentSnippets が有効な場合のみです。
easy-code-managerが無効な場合、6 つのスニペットツールは登録されません。ツール一覧にも表示されません。 -
正規形式(プラグイン v1.80.0)。 PHP は
<?phpを付けずに本文として送信してください。先頭の<?phpと空行は、書き込み時(拒否されるのではなく)および読み取り時に削除されます。末尾の改行は保持され、末尾の?>は削除されます。sha256/bytes/linesは、コードをget-snippetが返すとおりの状態で計算するため、比較するときはローカルファイルではなく、その文字列のハッシュを計算してください。css/js は独自の<style>/<script>タグで囲まないでください。PHP は保存前に構文チェックされ、1 回テスト実行されます。すでに存在する関数やクラスを再宣言してはならず(function_exists/class_existsで保護してください)、出力を表示したり、トップレベルでreturnしたり、後から読み込まれるものを呼び出したりしてはなりません(フックを使用してください)。 -
作成時のステータスはデフォルトで下書きです。
wpcanai-create-snippetは、status: "published"(v1.80.0)を渡さない限り、下書きを作成します。この値を渡すと、まず PHP の構文チェックが行われ、構文エラーがある場合は何も書き込まれません。応答のstatusは読み戻された値です。Fluent Snippets 独自のauto_publishによって、下書きが公開状態に変更されることはあります。 -
書き込みが成功するのは、許可リストに登録されたグループのみです。 管理者は CanAI → AI Client → Guardrails → FluentSnippets group allowlist で、エージェントが書き込めるスニペットグループを指定します。許可リストが空(デフォルト)の場合、すべてのスニペット書き込みが拒否されます(
snippet_writes_disabled)。許可リストにないグループへの書き込みはsnippet_group_not_allowedを返します。ユーザーから別の指定がない限り、グループAIを優先してください。読み取り(list/get)は、許可リストに関係なく常に許可されます。 -
更新は差分のみを指定します。
wpcanai-update-snippetには変更したいフィールドだけを送信してください。サーバーは現在のスニペットを読み込み、すべてのメタデータに変更をマージしてから書き戻します。フィールドを省略すると現在の値が保持されます。codeのみを送信してgroup/priority/run_at/created_atを消去することはできません。 -
run_atは種類によって異なります。 PHP →all|backend|frontend;php_content→shortcode|wp_head|wp_body_open|wp_footer|before_content|after_content;css →wp_head|admin_head|everywhere;js →wp_head|wp_footer|admin_head|admin_footer。無効な組み合わせは FluentSnippets の呼び出し前に拒否されます(invalid_snippet_type/invalid_run_at)。 -
上流の既知の問題(ここでは修正されていません)。 CSS の
everywhereは管理画面では実際には読み込まれません(プラグインのタイプミスでeverywehere)。また、PHP のfrontendは適用されず、どこでも実行されます。どちらの値も FluentSnippets の UI で選択できるため、引き続き受け付けられます。判断に迷う場合はall/backend/wp_headを優先してください。 -
再有効化。 スニペットで致命的なエラーが発生すると、FluentSnippets によって自動的に無効化され、
has_errorが true になります。"reactivate": trueを渡さない限り、そのスニペットの更新は拒否されます(snippet_has_error)。この値を渡すと、エラーが解除されて更新が適用されます。そのため、通常の編集によって、既知の問題があるコードが意図せず再び有効になることはありません。 -
エラーには原因が示されます(v1.80.0)。 Fluent Snippets が拒否した保存は、
"{title} on line {line}: {reason} Fix: {fix}"という形式でエラーメッセージに返されます。再試行する前に原因と修正方法を確認してください。同じコードを再送信しないでください。
wpcanai-update-snippet の group を使ってスニペットを別のグループに移動するには、現在のグループと移動先のグループの両方が許可リストに登録されている必要があります。
デプロイループ(プラグイン v1.80.0)
スニペットを再送信せずにライブ編集し、ブラウザーを使わずに確認します。
- 置換 —
wpcanai-replace-in-snippet { "file_name", "replacements": [...], "require_all": true, "expected_sha256"?: "<sha256 from your last read>" }。require_allを指定すると、一致する箇所が見つからなかった場合は何も書き込まず、最も近い一致箇所を示します。expected_sha256を指定すると、最後に読み取ってから誰かがスニペットを変更していた場合、hash_mismatch(409)で書き込みを拒否します。アンカーに確信がない場合は、まずdry_run: trueを使用します。本文全体を書き換える場合は、引き続きwpcanai-update-snippet(同じexpected_sha256)を使用します。 - 確認 — レスポンスには、書き込み後に読み戻した、保存済みコードの
sha256、bytes、linesが含まれます。sha256を、想定するコードのハッシュ(上記の正規形式を使用)と比較します。後から、または別のセッションからwpcanai-get-snippet { "file_name", "fields": ["hash"] }を呼び出すと、コードを取得せずに同じフィールドを返します。 - キャッシュ — レスポンスの
purgedは、ページキャッシュのパージが保留中かどうかを示します。{ "scope": "all", "plugin": "…" }は、リクエストの終了時にサイト全体がパージされることを意味します(スニペットはすべてのページで実行されます)。nullは、何もキューに追加されていないことを意味します。purgedがnullで、キャッシュプラグインが有効な場合(書き込み後のパージがオフの場合)、または書き込み対象外の URL をパージする場合に限り、wpcanai-purge-cache(canai-mcp内)を呼び出します。
スニペットでのカスタム REST ルートの作成
エージェントは、FluentSnippets の PHP ルートと _canai_js の fetch を使って、ブラウザーから WordPress へのリレーを実装することがよくあります。スキーマだけでは分かりにくい点が 2 つあります。
-
カスタム nonce を
X-WP-Nonce(またはリクエストパラメーター_wpnonce)で送信しないでください。 WordPress コアのrest_cookie_check_errors()は、サイト全体のすべての REST リクエストで、この特定のヘッダー/パラメーターをインターセプトし、ルートのpermission_callbackが実行される前に、組み込みの'wp_rest'アクションに対して検証します。この名前で送信されたカスタムアクション用 nonce は必ずrest_cookie_invalid_nonceで拒否され、独自の権限チェックの内容が分からなくなります。カスタム nonce アクションには、別のヘッダー名(例:X-<Your-App>-Nonce)を使用してください。 -
ユーザー向けの文言を一般的なものにする場合でも、HTTP ステータス/エラーコードをクライアントに伝えてください(コンソールログ、またはページ上で区別できる状態として表示)。レート制限の
429、nonce の403、実際の500はそれぞれ異なる障害です。これらを 1 つのメッセージにまとめると、本番環境のインシデントをトリアージできなくなります。
wpcanai-list-snippets
- 引数:
{ "status"?: string, "type"?: string, "group"?: string, "include_hash"?: bool }— すべて省略可能なフィルターです(status:published|draft、type:PHP|php_content|css|js、group:グループ名)。(v1.80.0)include_hash: trueを指定すると、スニペットごとにsha256、bytes、linesが追加されます(すべてのファイルを読み取るため、明示的に指定してください)。FluentSnippets が有効な場合にのみ表示されます。 - 戻り値:
{ "snippets": [{ "file_name", "name", "type", "status", "run_at", "priority", "group", "tags", "description", "created_at", "updated_at", "has_error", "error_message", "writable" }], "groups": string[], "writable_groups": string[] }—writableはスニペットごとに示されます(そのグループが許可リストに含まれている場合)。writable_groupsは現在の許可リストで、書き込みを試みる前に変更可能な対象を確認できます。読み取りに制限はありません。
wpcanai-get-snippet
- 引数:
{ "file_name": string, "fields"?: ["meta"|"code"|"hash"] }— スニペットのファイル名(識別子。例:3-my-snippet.php)です。fieldsのデフォルトは 3 つすべてです。 - 戻り値: メタデータ全体、
code本文、エラー状態、writable(codeとconditionを加えたlist-snippetsの行と同じフィールド)、および (v1.80.0)sha256、bytes、lines。fields: ["hash"]を指定すると、file_name、status、group、updated_at、sha256、bytes、linesのみを返します。コードを取得せずに書き込みを確認する場合に使用します。不明なファイルの場合はsnippet_not_foundエラーが返されます。
wpcanai-create-snippet
- Args:
{ "name": string, "type": string, "run_at": string, "group": string, "code": string, "description"?: string, "tags"?: string, "priority"?: int, "status"?: "draft"|"published" }—name/type/run_at/group/codeはすべて必須です。PHP のcodeに<?phpは含めません(先頭にある場合は削除されます)。type/run_atはタイプテーブルに照らして検証されます。groupは書き込み可能な許可リストに含まれている必要があります。statusのデフォルトはdraftです。publishedの場合は、まず PHP の lint が実行されます。 - Returns:
{ "success": true, "file_name": string, "status": string, "group": string, "note": string, "sha256", "bytes", "lines", "purged" }— ファイル名は自動生成され(指定できません)、以降のすべての呼び出しでキーとして使われます。statusは読み戻されます。ドラフトは後からwpcanai-set-snippet-statusで公開できます。
wpcanai-update-snippet
- Args:
{ "file_name": string, "code"?: string, "name"?: string, "description"?: string, "tags"?: string, "group"?: string, "run_at"?: string, "priority"?: int, "reactivate"?: bool, "expected_sha256"?: string }—file_nameは必須です。変更するフィールドのみを送信してください(スパース — サーバーが現在のメタデータにマージします)。現在のgroupと、移動する場合は移動先のgroupも許可リストに含まれている必要があります。エラー状態のスニペットにはreactivate: trueが必要です。(v1.80.0)expected_sha256を指定すると、古い内容への書き込みをhash_mismatchで拒否します(409。メッセージには両方のハッシュが含まれ、何も書き込まれません)。 - Returns:
{ "success": true, "file_name": string, "changed_fields": string[], "sha256", "bytes", "lines", "purged" }— ハッシュフィールドは書き込み後に読み戻されます。 - 公開済み PHP コードの更新: 以前は、公開済み PHP スニペットの
codeを更新すると、Cannot redeclare functionで致命的なエラーが発生していました(FluentSnippets は、公開中のスニペットがすでに読み込まれている同じリクエスト内で検証を行います)。CanAI はこれを透過的に処理します。古いプラグインビルドでまだこのエラーが返る場合は、wpcanai-set-snippet-statusで非公開にしてから更新し、再公開してください。
wpcanai-replace-in-snippet(plugin v1.80.0)
- Args:
{ "file_name": string, "replacements": [{ "from": string, "to": string }], "require_all"?: bool, "ignore_whitespace"?: bool, "regex"?: bool, "scope"?: { "text": string, "occurrence"?: int }, "dry_run"?: bool, "expected_sha256"?: string }—canai-mcpのwpcanai-replace-in-metaの仕様をスニペットのコードに適用します。replace_no_matchメッセージには同じrequire_allの未一致診断が含まれ、ignore_whitespace/regex/scope/dry_runも同様に動作します。書き込みはupdate-snippetを通じて行われ(公開済み PHP は先に lint されます)、同じグループ許可リストが適用されます。 - Returns:
{ "success", "file_name", "total", "dry_run", "replacements": [{ "from", "to", "count", "suggestion"? }], "sha256", "bytes", "lines", "purged"? }—dry_runの場合、ハッシュは現在のコードのもので、purgedはありません。
wpcanai-set-snippet-status
- Args:
{ "file_name": string, "status": "published"|"draft" }— スニペットのgroupは許可リストに含まれている必要があります。 - Returns:
{ "success": true, "file_name": string, "status": string, "sha256", "bytes", "lines", "purged" }。FluentSnippets の両方のライフサイクルアクションを実行し、インデックスキャッシュを再構築して、公開済みスニペットを実際に実行します。
アクションルーター(簡易版)
| 目的 | ツール |
|---|---|
| FluentSnippets のスニペットを一覧表示/読み取る | wpcanai-list-snippets / wpcanai-get-snippet |
| スニペットを作成/更新する | wpcanai-create-snippet(status は任意) / wpcanai-update-snippet |
| スニペットの一部を編集する(デプロイループ) | wpcanai-replace-in-snippet → sha256 を確認 → purged |
| コードなしで保存内容を確認する | wpcanai-get-snippet { "fields": ["hash"] } / wpcanai-list-snippets { "include_hash": true } |
| スニペットを公開/非公開にする | wpcanai-set-snippet-status |
インストール
npx skills add usewp/canai --skill canai-yolo
同じ MCP エンドポイントでコンテンツを扱う場合は、canai-mcp と組み合わせてください。