wpops 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![license](https://img.shields.io/npm/l/wpops.svg)](LICENSE)
6
6
  [![node](https://img.shields.io/node/v/wpops.svg)](package.json)
7
7
 
8
- > WordPress REST operations toolkit — a zero-dependency CLI (plus agent skill) to manage posts, pages, media, comments, users and plugins across one or many sites.
8
+ > WordPress REST operations toolkit — a zero-dependency CLI (plus agent skill) to manage posts, pages, media, comments, users, navigation menus and plugins across one or many sites.
9
9
 
10
10
  WordPress REST 操作工具。只依赖 Node 内置能力(无第三方包),用应用密码通过
11
11
  `/wp-json/` 管理站点内容与插件。
@@ -64,6 +64,14 @@ npm publish
64
64
  > 白名单不含 `sites/`。每台机器各自 `wpops setup`,工具与 skill 都不携带密钥。
65
65
  > `WPOPS_SKIP_SKILL=1 npm i -g wpops` 可跳过自动装 skill;`wpops install-skill` 可手动补装。
66
66
 
67
+ ### 本机(开发) vs 其他机器(使用)
68
+
69
+ - **本机开发**:`pnpm add -g .` 会在 pnpm 全局建一个**指向本仓库的 Junction**,
70
+ 于是命令行的 `wpops` 就是**源码实时版** —— 改代码立即生效,无需重装。
71
+ 验证:`where.exe wpops`(应指向 `...\pnpm\bin`)。
72
+ - **其他机器使用**:`npm i -g wpops`,装的是 **npm 上发布的版本**;升级用 `npm i -g wpops@latest`。
73
+ - `npx wpops ...` 只在临时缓存里跑一次,不落 PATH。
74
+
67
75
  ## 1. 配置
68
76
 
69
77
  给每个站点建一个档案。**推荐用向导**:`wpops setup`(问 URL/用户名/应用密码,自动写入并体检)。
@@ -101,16 +109,25 @@ node bin/wpops.js doctor
101
109
 
102
110
  ## 3. 命令
103
111
 
112
+ > **现查现用**:`wpops help <组>` 或 `wpops <组> --help` 看某组动作与参数;`wpops commands --json` 拿机器可读清单(全部组/动作/是否写操作)。
113
+ > 帮助与清单都由 `lib/spec.js` 单一事实来源生成,不会和实现漂移。
114
+ >
115
+ > **退出码**:`0` 成功;`2` 用法/参数错误(stderr 打印错误 + 精简用法 + `--help` 提示);`1` 运行期错误(HTTP/网络/配置)。`--help` 始终走 stdout 且为 `0`。
116
+
104
117
  ```
105
- # 内容
118
+ # 内容(默认存草稿,发布是独立动作——见下方"发布安全")
106
119
  wpops posts list [--per-page 10] [--page 2] [--status draft] [--search 关键词]
107
120
  [--orderby date] [--order desc] [--categories 1,2] [--tags 3]
108
121
  [--author 1] [--after 2026-01-01] [--before 2026-12-31] [--json]
109
122
  wpops posts get <id>
110
- wpops posts create --title "标题" --content "正文" [--status draft] [--categories 1,2] [--tags 3] [--featured-media 44]
123
+ wpops posts create --title "标题" --content "正文" [--categories 1,2] [--tags 3] # 未给 --status 即草稿
111
124
  wpops posts create --title "标题" --from-file ./post.md --status draft
112
- wpops posts update <id> --title "新标题" [--status publish] [--featured-media 0]
113
- wpops posts delete <id> [--force] # 默认进回收站
125
+ wpops posts export <id> --file post.html # 导出正文,本地改排版
126
+ wpops posts update <id> --from-file post.html --dry-run # 先预览,再真正应用(下面这行)
127
+ wpops posts update <id> --from-file post.html
128
+ wpops posts publish <id> # 显式发布
129
+ wpops posts unpublish <id> # 下线为草稿
130
+ wpops posts delete <id> [--force] # 默认进回收站
114
131
  wpops pages ... # 同样的子命令
115
132
  wpops me
116
133
 
@@ -118,6 +135,8 @@ wpops me
118
135
  wpops media list [--per-page 20] [--media-type image]
119
136
  wpops media get <id>
120
137
  wpops media upload ./pic.jpg [--title "标题"] [--alt "替代文本"]
138
+ wpops media sideload --url https://example.com/pic.jpg [--title "标题"] # 从 URL 导入
139
+ wpops media edit-image <id> --rotation 90 [--crop] [--dest-width 800] # 裁剪/旋转(缺 --src 自动取当前图)
121
140
  wpops media update <id> [--alt "替代文本"] [--caption "说明"] [--post 123]
122
141
  wpops media delete <id>
123
142
 
@@ -138,6 +157,68 @@ wpops users update <id> --role editor
138
157
  wpops users delete <id> --force [--reassign 1] # 有内容的用户需指定内容转交人
139
158
  wpops users me
140
159
 
160
+ # 导航菜单(接口由插件提供;核心 REST 没有)
161
+ wpops menus list [--per-page 100] # 列出菜单(id / name / slug / locations)
162
+ wpops menus get <id>
163
+ wpops menu-items list [--menus 190] [--search 词] [--per-page 100] [--page 1]
164
+ wpops menu-items get <id>
165
+ wpops menu-items create --title "Projects" --url https://example.com/projects --menus 190 --menu-order 6
166
+ wpops menu-items create --title "Projects" --menus 190 --type post_type --object page --object-id 4976
167
+ wpops menu-items update <id> --menu-order 3 [--parent 4979] [--target _blank]
168
+ wpops menu-items delete <id> --dry-run # 预览不需要 --force
169
+ wpops menu-items delete <id> --force # 真正删除才必须 --force(不可撤销)
170
+ wpops menus create --name Header --locations header,mobile
171
+ wpops menus update 190 --locations header,mobile # 位置分配靠更新菜单的 locations
172
+ wpops menus delete 190 --force
173
+
174
+ # 搜索 / 站点设置 / 自省
175
+ wpops search 关键词 [--type post] [--subtype post] [--per-page 10]
176
+ wpops settings # 查看站点设置
177
+ wpops settings update --title "新标题" [--description "..."] [--timezone Asia/Shanghai] [--posts-per-page 10]
178
+ wpops settings update --data '{"show_on_front":"page"}'
179
+ wpops types list|get <type> # 已注册文章类型(含 rest_base)
180
+ wpops taxonomies list|get <tax> # 已注册分类法
181
+ wpops statuses # 文章状态
182
+
183
+ # 任意自定义类型(show_in_rest 的 CPT / 自定义分类)
184
+ wpops content list books [--per-page 10] # rest_base 直接当 type
185
+ wpops content get books 12
186
+ wpops content create books --title "..." [--status draft]
187
+ wpops content update books 12 --title "..."
188
+ wpops content delete books 12 --force
189
+ wpops terms list genres # 自定义分类法同理
190
+
191
+ # 修订 / 区块 / 区块主题结构
192
+ wpops revisions list <id> [--type posts|pages]
193
+ wpops revisions get <id> <rev>
194
+ wpops revisions restore <id> <rev> # 用旧修订覆盖正文
195
+ wpops revisions delete <id> <rev> --force
196
+ wpops blocks list|get|create|update|delete ... # 可复用区块
197
+ wpops navigation list|get|create|update|delete ... # 区块主题导航
198
+ wpops templates list|get|update ... # 模板(update --content/--from-file)
199
+ wpops template-parts list|get|update ...
200
+ wpops global-styles get <id> · global-styles update <id> --styles '{"...":...}'
201
+
202
+ # 小工具 / 应用密码 / 插件能力
203
+ wpops widgets list|get|create|update|delete ... # --id --sidebar --instance JSON
204
+ wpops sidebars list|get|update ... # update --widgets a,b,c
205
+ wpops app-passwords list [--user me] # 列出应用密码(不含明文)
206
+ wpops app-passwords create --name ci-token [--user me] # 明文密码只打印这一次
207
+ wpops app-passwords delete <uuid> --force
208
+ wpops abilities list|get|run <name> [--input JSON] # Abilities API(需插件)
209
+ wpops health list · health <test> # 站点健康测试(需插件)
210
+ wpops batch --requests '[{"method":"DELETE","path":"/wp/v2/menu-items/123"}]' # 仅 POST/PUT/PATCH/DELETE
211
+
212
+ # 输出与批量
213
+ wpops posts list --all-pages # 自动翻完所有页
214
+ wpops posts list --fields id,title,status --csv # 字段投影 / CSV(--table 表格)
215
+ wpops menus list --quiet # 只出错时输出
216
+ wpops menus list --output menus.txt # 写入文件
217
+ wpops sites show qnnp.me # 查看站点配置(密码打码)
218
+ wpops sites rm qnnp.me · sites rename 旧 新 # 管理站点档案(确认后再用)
219
+ wpops completion bash # 输出补全脚本
220
+ wpops help menus # 某组用法
221
+
141
222
  # 插件 / 主题(见下方能力说明)
142
223
  wpops plugins list [--status active] [--search 关键词]
143
224
  wpops plugins install <wordpress.org 别名> [--activate]
@@ -152,11 +233,20 @@ wpops raw POST /wp-json/wp/v2/comments --data '{"post":1,"content":"hi"}'
152
233
 
153
234
  # 安全开关
154
235
  wpops posts delete 12 --dry-run # 只预览,不执行(所有写命令都支持)
236
+ wpops posts update 12 --from-file post.html --dry-run
155
237
  wpops --all posts delete 12 --dry-run # 跨站预览
156
238
  wpops --all plugins list # 读操作无需确认
157
239
  wpops --all plugins activate akismet/akismet --yes # 写操作必须 --yes
158
240
  ```
159
241
 
242
+ ### 发布安全(两步走)
243
+
244
+ - **创建默认草稿**,不会直接上线;发布是独立动作 `wpops posts publish <id>`(页面/CPT 同理),下线用 `unpublish <id>`。
245
+ - 修改**已发布**内容的正文时,会先在 stderr 提示并给出修订回滚命令(加 `--yes` 可静默);`settings` / 菜单位置等 live 变更同样会提示。
246
+ - 改版式/长文的安全流程:`export` 导出正文 → 本地编辑 → 建**草稿副本**预览(回显后台编辑链接)→ `update --from-file` 应用到原页 → 不满意用 `revisions restore` 回滚。
247
+ - **页面构建器注意**:Elementor / SiteOrigin / Divi 等把布局存在插件 meta 里,直接改 REST 的 `post_content` 会**弄坏页面**;这类页面请在构建器 UI 里改,wpops 只用于体检/备份/回滚。
248
+ - WP 的**前端草稿预览**依赖登录态,应用密码在浏览器里用不了;可靠入口是回显的**后台编辑/预览链接**。
249
+
160
250
  ## 4. 多站点
161
251
 
162
252
  所有站点都放在 `sites/`,一个站点一个文件:
@@ -193,10 +283,17 @@ wpops --all plugins list # 巡检所有站的插件
193
283
  | 事项 | 核心 REST 能做到吗 |
194
284
  |---|---|
195
285
  | 文章 / 页面 / 媒体 / 分类 / 标签 / 评论 / 用户的增删改查 | ✅ 完整 |
286
+ | 搜索、站点设置(site title/时区/…)、类型/分类/状态自省 | ✅ |
287
+ | 自定义类型 / 自定义分类(`show_in_rest` 的 CPT) | ✅(`content` / `terms` 通用命令) |
288
+ | 修订历史(列/看/删/恢复)、可复用区块、区块主题导航/模板/全局样式 | ✅ |
289
+ | 小工具 / 边栏、用户应用密码 | ✅ |
290
+ | 导航菜单 / 菜单项(列表、增删改) | ⚠️ 需站点装有暴露 `/menus`、`/menu-items` 的插件 |
196
291
  | 插件:列出、**安装**(按 wp.org 别名)、启用/停用、删除 | ✅ |
197
292
  | 插件:**更新已装插件代码** | ❌ 核心 REST 没有该端点 |
198
293
  | 主题:列出、切换 | ✅ |
199
294
  | 主题:安装 / 更新 | ❌ |
295
+ | Abilities API(`abilities list/run`)、站点健康测试(`health`) | ⚠️ 需对应插件 |
296
+ | 批量请求(`batch`) | ✅(仅 POST/PUT/PATCH/DELETE,核心限制) |
200
297
  | WordPress 核心更新 | ❌ |
201
298
  | 备份 / 数据库优化 / 缓存清理 | ❌(需服务器侧) |
202
299
 
@@ -209,16 +306,18 @@ wpops --all plugins list # 巡检所有站的插件
209
306
 
210
307
  - `sites/*.env` 存放应用密码,等同于该账号登录凭据;专用账号 + 可随时在后台吊销。
211
308
  - 应用密码要求 HTTPS。
212
- - **写操作前先 `--dry-run` 预览**;破坏性操作(`delete --force`、分类/用户删除)另需 `--force`。
309
+ - **写操作前先 `--dry-run` 预览**(`delete` 的预览不需要 `--force`);真正执行破坏性删除(`delete --force`、分类/用户/菜单项删除)才必须加 `--force`。
213
310
  - **`--all` 的写操作必须加 `--yes`**,否则直接拒绝,避免手滑波及全线。
214
311
  - 网络抖动/429/5xx 会自动重试(默认 2 次,幂等方法才重试网络错误)。
215
312
  - 这是本地脚本,不对外开端口。
216
313
 
217
- ## 7. 与 WordPress skills 的关系
314
+ ## 7. 自洽执行器
315
+
316
+ 本项目是**执行器**(真正发请求),内置 agent skill(`skills/wpops/SKILL.md`)自洽、不依赖其他 skill:
317
+ 它只讲清**何时用、安全流程、能力索引、如何现查现用**(`wpops help` / `wpops commands --json` / `wpops raw`),
318
+ 精确的字段与枚举一律在运行时向 CLI 或站点查询,因此不会随文档过时。
218
319
 
219
- 本项目是**执行器**(真正发请求);已安装的官方 skills
220
- (`wp-rest-api`、`wp-wpcli-and-ops`、`wp-performance`、`wordpress-router`)
221
- 是**知识/规范**,指导"该怎么安全地做"。
320
+ 更广义的 WordPress 知识(主题/插件开发、WP-CLI 运维、性能等)属于其他领域,与本工具正交,按需另取即可。
222
321
 
223
322
  ## 8. 全局命令(可选)
224
323