$recipe['id'],
'title' => $recipe['title'],
'steps' => $recipe['steps'],
'tip' => $recipe['tip'] ?? '',
];
}
// ── Recipe definitions ────────────────────────────────────────────────────
private static function all(): array {
return [
// ── Core — available to any valid key ────────────────────────────
[
'id' => 'session_workflow',
'title' => 'How to start: open a session',
'task_keywords' => [ 'how to start', 'session', 'workflow', 'begin', 'get started' ],
'required_scope' => '',
'required_module' => '',
'steps' => [
[ 'tool' => 'tools/list', 'args' => '(no args) — discover what tools are available' ],
[ 'tool' => 'session.open', 'args' => 'name: "My task", description: "What I plan to do and why"' ],
[ 'tool' => '(your tool)', 'args' => 'run any write tool after the session is open' ],
[ 'tool' => 'session.close', 'args' => 'summary: "What was done"' ],
],
'tip' => 'Always close the session when done — AICOM analyzes it for reusable skill suggestions.',
],
[
'id' => 'create_post',
'title' => 'Create a blog post',
'task_keywords' => [ 'create post', 'blog post', 'new article', 'write post', 'new post', 'draft post' ],
'required_scope' => 'write.wp.posts',
'required_module' => '',
'steps' => [
[ 'tool' => 'session.open', 'args' => 'name: "Create post", description: "Draft and publish
"' ],
[ 'tool' => 'wp.posts.create', 'args' => 'title, content, status: "draft", post_type: "post"' ],
],
'tip' => 'Use status:"draft" first. Review the result, then call wp.posts.update(id, status:"publish") to go live.',
],
[
'id' => 'update_post',
'title' => 'Edit an existing post',
'task_keywords' => [ 'edit post', 'update post', 'modify post', 'change post', 'fix post' ],
'required_scope' => 'write.wp.posts',
'required_module' => '',
'steps' => [
[ 'tool' => 'wp.posts.list', 'args' => 'search: "", post_type: "post"' ],
[ 'tool' => 'wp.posts.get', 'args' => 'id: ' ],
[ 'tool' => 'session.open', 'args' => 'name: "Edit post", description: "Update "' ],
[ 'tool' => 'wp.posts.update', 'args' => 'id: , (fields to change)' ],
],
'tip' => 'Always read the post first (wp.posts.get) so you only change what is needed.',
],
[
'id' => 'upload_media',
'title' => 'Upload an image or file',
'task_keywords' => [ 'upload image', 'add media', 'upload file', 'upload photo', 'media library' ],
'required_scope' => 'manage.media',
'required_module' => '',
'steps' => [
[ 'tool' => 'session.open', 'args' => 'name: "Upload media", description: "Add to media library"' ],
[ 'tool' => 'media.upload', 'args' => 'url: "", title, alt_text' ],
],
'tip' => 'media.upload accepts a public URL and downloads it server-side. Returns attachment_id for use in wp.posts.update.',
],
[
'id' => 'attach_media_to_post',
'title' => 'Set a featured image on a post',
'task_keywords' => [ 'attach image', 'featured image', 'add image to post', 'post thumbnail', 'set thumbnail' ],
'required_scope' => 'manage.media',
'required_module' => '',
'steps' => [
[ 'tool' => 'session.open', 'args' => 'name: "Set featured image", description: "Attach image to post "' ],
[ 'tool' => 'media.upload', 'args' => 'url: "", alt_text: ""' ],
[ 'tool' => 'wp.posts.update', 'args' => 'id: , featured_media: ' ],
],
'tip' => 'featured_media accepts the attachment_id returned by media.upload.',
],
[
'id' => 'manage_menus',
'title' => 'Update a navigation menu',
'task_keywords' => [ 'menu', 'navigation', 'nav', 'add menu item', 'nav menu' ],
'required_scope' => 'manage.menus',
'required_module' => '',
'steps' => [
[ 'tool' => 'wp.menus.list', 'args' => '(no args)' ],
[ 'tool' => 'wp.menus.get', 'args' => 'id: ' ],
[ 'tool' => 'session.open', 'args' => 'name: "Update menu", description: "Add/remove items in "' ],
[ 'tool' => 'wp.menus.update', 'args' => 'id: , items: [...]' ],
],
],
// ── Backup ───────────────────────────────────────────────────────
[
'id' => 'backup_snapshot',
'title' => 'Create a backup snapshot before making changes',
'task_keywords' => [ 'backup', 'snapshot', 'before changes', 'safety', 'save state' ],
'required_scope' => 'manage.backups',
'required_module' => '',
'steps' => [
[ 'tool' => 'session.open', 'args' => 'name: "Backup", description: "Snapshot before "' ],
[ 'tool' => 'backup.create', 'args' => 'label: ""' ],
],
'tip' => 'backup.create snapshots all posts and meta. Use backup.restore to roll back if something goes wrong.',
],
// ── Users ─────────────────────────────────────────────────────────
[
'id' => 'list_users',
'title' => 'List site users',
'task_keywords' => [ 'list users', 'find user', 'user roles', 'who has access', 'site users' ],
'required_scope' => 'read.users',
'required_module' => '',
'steps' => [
[ 'tool' => 'wp.users.list', 'args' => 'role: "" (optional), search: "" (optional)' ],
],
],
[
'id' => 'create_user',
'title' => 'Create a new user',
'task_keywords' => [ 'create user', 'add user', 'new account', 'new user', 'register user' ],
'required_scope' => 'manage.users',
'required_module' => '',
'steps' => [
[ 'tool' => 'session.open', 'args' => 'name: "Create user", description: "Add as "' ],
[ 'tool' => 'wp.users.create', 'args' => 'username, email, role: "editor|author|contributor|subscriber"' ],
],
],
// ── A11y ─────────────────────────────────────────────────────────
[
'id' => 'audit_alt_text',
'title' => 'Audit and fix missing alt text on images',
'task_keywords' => [ 'alt text', 'accessibility', 'a11y', 'images seo', 'missing alt', 'image description' ],
'required_scope' => 'manage.a11y',
'required_module' => '',
'steps' => [
[ 'tool' => 'a11y.site_report', 'args' => '(no args) — find all images missing alt text' ],
[ 'tool' => 'session.open', 'args' => 'name: "Fix alt text", description: "Add alt text to top missing images"' ],
[ 'tool' => 'a11y.set_image_alt', 'args' => 'attachment_id: , alt_text: "" — repeat per image' ],
],
'tip' => 'Run a11y.site_report first (no session needed). Then open a session and fix in batches.',
],
[
'id' => 'audit_post_a11y',
'title' => 'Audit accessibility of a single post',
'task_keywords' => [ 'post accessibility', 'heading structure', 'a11y audit', 'check headings', 'accessibility report' ],
'required_scope' => 'manage.a11y',
'required_module' => '',
'steps' => [
[ 'tool' => 'a11y.audit_post', 'args' => 'post_id: ' ],
],
'tip' => 'a11y.audit_post is a read-only check — no session needed. Returns heading structure, image alt coverage, and contrast warnings.',
],
// ── Skills ───────────────────────────────────────────────────────
[
'id' => 'run_saved_skill',
'title' => 'Find and run a saved Skill',
'task_keywords' => [ 'run skill', 'execute skill', 'saved workflow', 'skill', 'automation' ],
'required_scope' => 'read.skills',
'required_module' => '',
'steps' => [
[ 'tool' => 'skills.list', 'args' => 'search: "", status: "active"' ],
[ 'tool' => 'skills.run', 'args' => 'id: , inputs: {}' ],
],
'tip' => 'skills.run returns the full instructions for the AI to follow — execute the steps it describes.',
],
[
'id' => 'create_skill',
'title' => 'Save a workflow as a reusable Skill',
'task_keywords' => [ 'create skill', 'save workflow', 'automate task', 'new skill', 'reusable' ],
'required_scope' => 'manage.skills',
'required_module' => '',
'steps' => [
[ 'tool' => 'skills.match', 'args' => 'name: "", description: "" — check for duplicates first' ],
[ 'tool' => 'session.open', 'args' => 'name: "Create skill", description: "Save workflow as "' ],
[ 'tool' => 'skills.create', 'args' => 'slug, name, description, steps: [...], type: "simple"' ],
[ 'tool' => 'skills.activate', 'args' => 'id: — only after user confirms' ],
],
'tip' => 'Always call skills.match first to avoid duplicates. New skills are saved as draft — ask the user before activating.',
],
// ── WooCommerce ───────────────────────────────────────────────────
[
'id' => 'woo_browse',
'title' => 'Browse WooCommerce products and categories',
'task_keywords' => [ 'list products', 'browse woocommerce', 'product catalog', 'woocommerce products', 'product list' ],
'required_scope' => 'read.woocommerce',
'required_module' => 'woocommerce',
'steps' => [
[ 'tool' => 'wc.categories.list', 'args' => '(no args)' ],
[ 'tool' => 'wc.products.list', 'args' => 'category: (optional), search: "" (optional), per_page: 20' ],
],
'tip' => 'These are read-only — no session needed. Use wc.products.get(id) to fetch a single product in full.',
],
[
'id' => 'woo_create_product',
'title' => 'Create a WooCommerce product',
'task_keywords' => [ 'create product', 'add product', 'new product', 'woocommerce product', 'add woocommerce' ],
'required_scope' => 'manage.woocommerce.products',
'required_module' => 'woocommerce',
'steps' => [
[ 'tool' => 'wc.categories.list', 'args' => '(no args) — find the right category id' ],
[ 'tool' => 'session.open', 'args' => 'name: "Create product", description: "Add to WooCommerce"' ],
[ 'tool' => 'wc.products.create', 'args' => 'name, regular_price, description, categories: [{id}], status: "draft"' ],
],
'tip' => 'Create as draft first. After reviewing, call wc.products.update(id, status:"publish") to go live.',
],
[
'id' => 'woo_update_stock',
'title' => 'Bulk update WooCommerce product stock',
'task_keywords' => [ 'stock', 'inventory', 'update stock', 'low stock', 'product inventory', 'woocommerce stock' ],
'required_scope' => 'manage.woocommerce.products',
'required_module' => 'woocommerce',
'steps' => [
[ 'tool' => 'wc.products.list', 'args' => 'per_page: 50, status: "publish"' ],
[ 'tool' => 'session.open', 'args' => 'name: "Update stock", description: "Adjust inventory levels"' ],
[ 'tool' => 'wc.products.update', 'args' => 'id: , stock_quantity: , manage_stock: true — repeat per product' ],
],
],
// ── Elementor ─────────────────────────────────────────────────────
[
'id' => 'elementor_read_page',
'title' => 'Read an Elementor page structure',
'task_keywords' => [ 'read elementor page', 'inspect page', 'page tree', 'elementor structure', 'page widgets' ],
'required_scope' => 'read.elementor',
'required_module' => 'elementor',
'steps' => [
[ 'tool' => 'wp.posts.list', 'args' => 'post_type: "page", search: ""' ],
[ 'tool' => 'elementor.page.get_tree', 'args' => 'post_id: ' ],
[ 'tool' => 'elementor.page.get_texts','args' => 'post_id: ' ],
],
'tip' => 'These are read-only — no session needed. get_texts returns all editable text blocks indexed by widget_id.',
],
[
'id' => 'elementor_edit_texts',
'title' => 'Edit text content on an Elementor page',
'task_keywords' => [ 'edit elementor texts', 'update page copy', 'landing page', 'elementor edit', 'change elementor text' ],
'required_scope' => 'manage.elementor',
'required_module' => 'elementor',
'steps' => [
[ 'tool' => 'elementor.page.get_texts', 'args' => 'post_id: — read all text blocks first' ],
[ 'tool' => 'elementor.page.validate', 'args' => 'post_id: , changes: [{widget_id, content}] — dry-run check' ],
[ 'tool' => 'session.open', 'args' => 'name: "Edit Elementor page", description: "Update copy on "' ],
[ 'tool' => 'elementor.page.set_texts', 'args' => 'post_id: , changes: [{widget_id, content}]' ],
],
'tip' => 'Always call get_texts first to get widget IDs. Use validate before set_texts to catch structural errors.',
],
// ── ECS (Elementor Color/Font Schemes) ────────────────────────────
[
'id' => 'ecs_apply_colors',
'title' => 'Apply a color scheme site-wide (ECS)',
'task_keywords' => [ 'color scheme', 'ecs colors', 'brand colors', 'apply theme', 'site colors', 'ecs' ],
'required_scope' => 'manage.elementor',
'required_module' => 'ecs',
'steps' => [
[ 'tool' => 'ecs.color_schemes.list', 'args' => '(no args)' ],
[ 'tool' => 'session.open', 'args' => 'name: "Apply color scheme", description: "Set as global theme"' ],
[ 'tool' => 'ecs.color_schemes.activate_global', 'args' => 'name: ""' ],
],
'tip' => 'activate_global creates an AICOM-managed Custom Look with a general condition (always on). The previous active look remains but is overridden.',
],
[
'id' => 'ecs_change_fonts',
'title' => 'Change the site font scheme (ECS)',
'task_keywords' => [ 'font scheme', 'ecs fonts', 'typography', 'change font', 'site fonts', 'font family' ],
'required_scope' => 'manage.elementor',
'required_module' => 'ecs',
'steps' => [
[ 'tool' => 'ecs.font_schemes.list', 'args' => '(no args)' ],
[ 'tool' => 'ecs.font_schemes.get', 'args' => 'name: "" — inspect current fonts' ],
[ 'tool' => 'session.open', 'args' => 'name: "Change fonts", description: "Update font scheme "' ],
[ 'tool' => 'ecs.font_schemes.save', 'args' => 'id: , fonts: [{id, family, weight, ...}]' ],
],
],
// ── Polylang ──────────────────────────────────────────────────────
[
'id' => 'pll_view_languages',
'title' => 'List configured Polylang languages',
'task_keywords' => [ 'languages', 'polylang languages', 'what languages', 'site languages', 'translations available' ],
'required_scope' => 'read.polylang',
'required_module' => 'polylang',
'steps' => [
[ 'tool' => 'pll.languages.list', 'args' => '(no args)' ],
],
'tip' => 'Read-only — no session needed. Returns locale, slug, and default_locale for each language.',
],
[
'id' => 'pll_translate_post',
'title' => 'Create a translated version of a post (Polylang)',
'task_keywords' => [ 'translate post', 'polylang', 'multilingual', 'translation', 'translated post', 'language version' ],
'required_scope' => 'manage.polylang',
'required_module' => 'polylang',
'steps' => [
[ 'tool' => 'pll.languages.list', 'args' => '(no args) — get language slugs' ],
[ 'tool' => 'wp.posts.get', 'args' => 'id: — read original content' ],
[ 'tool' => 'session.open', 'args' => 'name: "Translate post", description: "Create version of post "' ],
[ 'tool' => 'wp.posts.create', 'args' => 'title: "", content: "", status: "draft"' ],
[ 'tool' => 'pll.post.set_language', 'args' => 'post_id: , language: ""' ],
[ 'tool' => 'pll.post.link_translation', 'args' => 'original_id: , translation_id: ' ],
],
'tip' => 'Always link the translation — without pll.post.link_translation, Polylang treats it as a standalone post, not a translation.',
],
// ── Yoast SEO ─────────────────────────────────────────────────────
[
'id' => 'yoast_update_post_seo',
'title' => 'Update Yoast SEO title and meta description for a post',
'task_keywords' => [ 'yoast', 'seo title', 'meta description', 'seo post', 'update seo', 'yoast seo' ],
'required_scope' => 'manage.yoast',
'required_module' => 'yoast',
'steps' => [
[ 'tool' => 'wp.posts.get', 'args' => 'id: — read current content' ],
[ 'tool' => 'session.open', 'args' => 'name: "Update SEO", description: "Set Yoast meta for post "' ],
[ 'tool' => 'wp.meta.set', 'args' => 'post_id: , key: "_yoast_wpseo_title", value: ""' ],
[ 'tool' => 'wp.meta.set', 'args' => 'post_id: , key: "_yoast_wpseo_metadesc", value: ""' ],
],
'tip' => 'Yoast title variables like %%title%% %%sep%% %%sitename%% are supported in _yoast_wpseo_title. Keep meta description under 160 characters.',
],
[
'id' => 'yoast_bulk_seo',
'title' => 'Bulk update Yoast SEO fields for multiple posts',
'task_keywords' => [ 'bulk seo', 'yoast bulk', 'all posts seo', 'mass update seo', 'seo all pages' ],
'required_scope' => 'manage.yoast',
'required_module' => 'yoast',
'steps' => [
[ 'tool' => 'wp.posts.list', 'args' => 'post_type: "post", per_page: 20 (repeat with offset for pagination)' ],
[ 'tool' => 'session.open', 'args' => 'name: "Bulk SEO update", description: "Update Yoast meta for posts"' ],
[ 'tool' => 'wp.meta.set', 'args' => 'post_id: , key: "_yoast_wpseo_title", value: "" — repeat per post' ],
[ 'tool' => 'wp.meta.set', 'args' => 'post_id: , key: "_yoast_wpseo_metadesc", value: "" — repeat per post' ],
],
'tip' => 'Process in batches of 20 posts. Call wp.posts.list with offset to page through all posts.',
],
// ── SEOPress ──────────────────────────────────────────────────────
[
'id' => 'seopress_update_post_seo',
'title' => 'Update SEOPress SEO title and meta description for a post',
'task_keywords' => [ 'seopress', 'seo title', 'meta description', 'seo post', 'update seo', 'seopress seo' ],
'required_scope' => 'manage.seopress',
'required_module' => 'seopress',
'steps' => [
[ 'tool' => 'wp.posts.get', 'args' => 'id: — read current content' ],
[ 'tool' => 'session.open', 'args' => 'name: "Update SEO", description: "Set SEOPress meta for post "' ],
[ 'tool' => 'seopress.post.set', 'args' => 'post_id: , title: "", metadesc: ""' ],
],
'tip' => 'SEOPress title variables like %%post_title%% %%sep%% %%sitetitle%% are supported. Pass an empty string to clear a field back to the site-wide template.',
],
[
'id' => 'seopress_bulk_seo',
'title' => 'Bulk update SEOPress SEO fields for multiple posts',
'task_keywords' => [ 'bulk seo', 'seopress bulk', 'all posts seo', 'mass update seo', 'seo all pages' ],
'required_scope' => 'manage.seopress',
'required_module' => 'seopress',
'steps' => [
[ 'tool' => 'wp.posts.list', 'args' => 'post_type: "post", per_page: 20 (repeat with offset for pagination)' ],
[ 'tool' => 'session.open', 'args' => 'name: "Bulk SEO update", description: "Update SEOPress meta for posts"' ],
[ 'tool' => 'seopress.post.set', 'args' => 'post_id: , title: "", metadesc: "" — repeat per post' ],
],
'tip' => 'Process in batches of 20 posts. Call wp.posts.list with offset to page through all posts. Use seopress.posts.bulk_get first to see which posts are missing SEO fields.',
],
// ── Clautron ──────────────────────────────────────────────────────
[
'id' => 'clautron_install',
'title' => 'Install a Clautron component from the catalog',
'task_keywords' => [ 'clautron', 'install component', 'add capability', 'clautron catalog', 'install clautron' ],
'required_scope' => 'manage.clautron',
'required_module' => 'clautron',
'steps' => [
[ 'tool' => 'clautron.catalog.list', 'args' => '(no args) — see available components' ],
[ 'tool' => 'session.open', 'args' => 'name: "Install component", description: "Add "' ],
[ 'tool' => 'clautron.catalog.install', 'args' => 'component: ""' ],
],
'tip' => 'After install, call clautron.capability.meta.get to see the activated capability and its configuration options.',
],
[
'id' => 'clautron_blueprint',
'title' => 'Create a Clautron automation blueprint',
'task_keywords' => [ 'clautron blueprint', 'create blueprint', 'event automation', 'clautron automation', 'blueprint' ],
'required_scope' => 'manage.clautron',
'required_module' => 'clautron',
'steps' => [
[ 'tool' => 'clautron.primitives.list', 'args' => '(no args) — see available primitives' ],
[ 'tool' => 'clautron.blueprint.examples', 'args' => '(no args) — see example blueprints for reference' ],
[ 'tool' => 'clautron.blueprint.validate', 'args' => 'blueprint: {draft JSON} — check for errors before creating' ],
[ 'tool' => 'session.open', 'args' => 'name: "Create blueprint", description: ""' ],
[ 'tool' => 'clautron.blueprint.create', 'args' => 'blueprint: {validated JSON}' ],
[ 'tool' => 'clautron.blueprint.smoke_test','args' => 'blueprint_id: — verify the blueprint runs' ],
],
'tip' => 'Always call blueprint.examples first — it shows the structure Clautron expects. Validate before creating to catch schema errors early.',
],
];
}
}