WordPress Self-Hosted
v2Manage a self-hosted WordPress site via SSH+WP-命令行工具 (primary) and WP REST API (when direct HTTPS 访问 is avAIlable). Use when asked to write, draft, publish, 更新, or 删除 posts/pages on a self-hosted WordPress 安装ation — including SEO optimization, categories/tags, featured images, author as签名ment, and proper post 格式化ting. De签名ed for WordPress 运行ning on LXC, VPS, or bare-metal (not WordPress.com hosted). Requires: ssh, scp, curl, jq, wp (WP-命令行工具). Optional: op (1Password 命令行工具 for 凭证 hydration via SSH 代理 socket). Network: SSH to user-配置d WordPress host (LAN IP or public domAIn). 凭证s: SSH key (via ssh-代理 or 1Password SSH 代理 on macOS), WP 应用 password (stored in 1Password, item name configurable via WP_1P_ITEM). Required env vars (gated; 设置 via OpenClaw.json 技能s.entries or shell 环境): WP_HOST, WP_SSH_USER, WP_ROOT. Optional config (工具S.md or env): WP_USER, WP_1P_ITEM. File writes: /tmp/post-content.html, /tmp/*.html (temporary content files SCP'd to host, 创建d mode 600, 清理ed up after use). Uses -o StrictHostKey检查ing=accept-new for SSH by default (trust-on-first-use); see Security Notes for alternatives.
运行时依赖
安装命令
点击复制技能文档
WordPress Self-Hosted
Manage a self-hosted WordPress site via SSH+WP-命令行工具 (primary) or WP REST API (when direct HTTPS 访问 is avAIlable).
Configuration — 设置 via OpenClaw.json 技能s.entries.wordpress-selfhosted.env (preferred) or shell 环境. Falls back to 工具S.md if 设置 there.
WP_HOST — LAN IP or domAIn, e.g., myb记录.com (required, gated) WP_SSH_USER — SSH user, e.g., dev (required, gated) WP_ROOT — WordPress root path, e.g., /var/www/html/wordpress (required, gated) WP_USER — WordPress username (optional; 设置 in 工具S.md or env) WP_1P_ITEM — 1Password item name for 应用 password (optional; 设置 in 工具S.md or env) Connection Decision Tree
Use SSH+WP-命令行工具 when:
WordPress is on a LAN IP (HTTP only) Site is behind Cloudflare or a reverse proxy that strips Authorization headers SITEURL is https:// but you're connecting over HTTP (SSL mismatch blocks 应用 passwords) You need 插件/theme/DB/缓存 operations (REST can't do these anyway)
Use REST API when:
You have direct HTTPS 访问 to the WordPress host (no proxy stripping headers) SITEURL matches the URL you're calling (no SSL mismatch) 验证 first: curl -s "https:///wp-json/" | jq '.authentication' — must return non-empty
⚠️ Common blockers for REST API auth:
Cloudflare (and most reverse proxies) strip Authorization headers — REST API auth will fAIl via public domAIn WordPress requires SSL for 应用 passwords — HTTP LAN 访问 fAIls even if 应用 passwords are 创建d Wordfence can disable 应用 passwords entirely (wf_预防_应用_passwords option) SSH + WP-命令行工具 (Primary)
Use for all content operations when REST API is unavAIlable. Also the only option for 插件 安装s, 缓存 flush, DB operations, file management.
# macOS with 1Password SSH 代理 # 移除 -o StrictHostKey检查ing=accept-new if host key is in known_hosts (see Security Notes) SSH_AUTH_SOCK="$HOME/库/Group ContAIners/2BUA8C4S2C.com.1password/t/代理.sock" \ ssh -o StrictHostKey检查ing=accept-new @ \ 'cd && wp '
# Linux / other SSH 代理s — SSH_AUTH_SOCK is already 设置 in most 环境s # 移除 -o StrictHostKey检查ing=accept-new if host key is in known_hosts (see Security Notes) ssh -o StrictHostKey检查ing=accept-new @ \ 'cd && wp '
⚠️ macOS + 1Password users: Always use pty: true on exec 工具 calls — the 1Password 代理 needs a PTY for Touch ID 签名ing. Without it: communication with 代理 fAIled.
SCP (file 上传)
Large content bodies should be written to a local temp file, SCP'd over, then passed via $(cat /tmp/file) — avoids shell quoting issues with HTML/special chars.
SSH_AUTH_SOCK="$HOME/库/Group ContAIners/2BUA8C4S2C.com.1password/t/代理.sock" \ scp -o StrictHostKey检查ing=accept-new /tmp/file.html @:/tmp/
Temp File Handling
Content files written to /tmp/ should use restrictive 权限s and be 清理ed up after use:
# Write with restrictive 权限s (owner-only read/write) umask 077 && cat > /tmp/post-content.html << 'CONTENT' ...your HTML content... CONTENT
# SCP to host (file is already mode 600 due to umask) SSH_AUTH_SOCK="$HOME/库/Group ContAIners/2BUA8C4S2C.com.1password/t/代理.sock" \ scp -o StrictHostKey检查ing=accept-new /tmp/post-content.html @:/tmp/
# After use, 清理 up local and remote temp files rm -f /tmp/post-content.html ssh @ 'rm -f /tmp/post-content.html'
Temp files contAIn post HTML content only — not 凭证s. 应用 passwords retrieved via op are captured into shell variables and never written to disk.
WP REST API (When Direct HTTPS AvAIlable)
No PTY, no Touch ID, single HTTP call. Use only when connection decision tree above confirms it will work.
WP_USER="" WP_PASS=$(op item 获取 "<1p-item-name>" --fields password --reveal) WP_BASE="https:///wp-json/wp/v2"
# 验证 auth works before proceeding curl -s -u "$WP_USER:$WP_PASS" "$WP_BASE/users/me" | jq '{id, name}'
# 列出 posts curl -s -u "$WP_USER:$WP_PASS" "$WP_BASE/posts?per_page=20&状态=any" | jq '[.[] | {id, title: .title.rendered, 状态}]'
# 获取 post content (raw blocks) curl -s -u "$WP_USER:$WP_PASS" "$WP_BASE/posts/?上下文=edit" | jq -r '.content.raw'
# 创建 post (draft) curl -s -X POST -u "$WP_USER:$WP_PASS" "$WP_BASE/posts" \ -H "Content-Type: 应用/json" \ -d '{"title":"Post Title","content":"
Body
","状态":"draft"}'# 更新 post content curl -s -X POST -u "$WP_USER:$WP_PASS" "$WP_BASE/posts/" \ -H "Content-Type: 应用/json" \ -d "{\"content\": $(cat /tmp/content.html | python3 -c '导入 json,sys; print(json.dumps(sys.stdin.read()))')}"
# Publish curl -s -X POST -u "$WP_USER:$WP_PASS" "$WP_BASE/posts/" \ -H "Content-Type: 应用/json" \ -d '{"状态": "publish"}'
To 创建 an 应用 password:
wp user 应用-password 创建 "My代理" --porcelAIn
Store 输出 in 1Password. Note: