RecipeSage 4.1.1 常用 CLI 命令与工具详解
RecipeSage 4.1.1 selfhost 命令行工具面全解:api 容器内 recipesage CLI 七子命令逐条 --help 实测(含 batch-size 1000/100、min-age-minutes 30、subscription-name forever 等真实默认值与无 --version 纠偏)、compose 运维命令组、/app/scripts 四脚本原文(restore-db.sh 写死 recipesage_dev+db3 的 selfhost 陷阱、pg_dump→异库恢复→40 表验证实测闭环)、REST 兼容层 144 paths 方法速查与 18 导入适配器、FAQ(实测日期 2026-11-02)
RecipeSage 4.1.1 常用 CLI 命令与工具详解
目标:系统梳理 RecipeSage 4.1.1 selfhost 形态的四组命令行工具——api 容器内的
recipesageCLI(7 个子命令,参数默认值逐条--help实测)、compose 运维命令组、容器内/app/scripts/运维脚本(含 restore-db.sh 的 selfhost 陷阱与异库恢复实测闭环),以及 REST 兼容层 API 工具面(144 paths 方法速查)。全部命令与回显来自 2026-11-02 实测环境(Ubuntu 24.04.5 / Docker 29.9.2 / v4.1.1,宿主端口 8162)。配置参数见站内文章 《RecipeSage 4.1.1 配置参数详解》,部署见 《RecipeSage Docker Compose 部署指南》。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 24.04.5 LTS(x86_64) |
| Docker / Compose | 29.9.2 / v5.6.1 |
| 组件版本 | RecipeSage v4.1.1 |
| CLI 入口 | api 容器内 node dist/apps/cli/main.cjs(工作目录 /app,Commander 程序名 recipesage) |
| 容器进入方式 | docker exec -it recipesage_api sh(或单行 docker exec recipesage_api <命令>) |
| 数据库 | postgres:16,库/用户均 recipesage_selfhost(40 表) |
| 备份产物 | rs_backup2.sql.gz(pg_dump+gzip,20890 字节) |
二、工具概览
| 工具组 | 位置 | 用途 |
|---|---|---|
recipesage CLI | api 容器 /app/dist/apps/cli/main.cjs | 搜索索引回填、清单分类、discover 排序/审核、seed、调试解密(7 命令) |
| compose 命令组 | 宿主 docker compose -p recipesage … | 栈生命周期:ps/logs/up/down/pull |
| 运维脚本 | api 容器 /app/scripts/(8 个) | selfhost-startup.sh(启动主线)、restore-db.sh、migrate.sh、decrypt-debug-dump.sh 等 |
| REST 兼容层 | http://127.0.0.1:8162/api/compat/v2/* | 脚本化业务操作(tRPC 自动生成,144 paths) |
💡 技术拓展:RecipeSage CLI 是 Commander 风格的"进程内一次性任务"工具;同类形态对比——
形态 特点 代表 一次性 CLI 任务(本文) 跑完即退,靠 cron/手动触发 recipesage CLI、mobilizon_ctl 常驻 worker 进程持续消费队列 RecipeSage 的 queue-worker 包(selfhost 由 api 内联消费) 管理 UI 图形化 前端管理页 selfhost 场景主要用第一、三种;CLI 与队列 job(导出等)分工:CLI 做全表批处理,job 做用户级异步任务。
三、前置条件
- 六服务栈在线:
docker compose -p recipesage ps六行 Up(部署见 B2 篇)。 - CLI 依赖 api 容器内的运行时环境(Node 24、
/app工作目录、注入的DATABASE_URL等环境变量)——必须在容器内执行,宿主无 node/凭据。 - 下文示例统一用单行形态:
docker exec recipesage_api node dist/apps/cli/main.cjs <子命令>。
四、recipesage CLI 七命令详解
4.1 帮助总览(无参调用)
docker exec recipesage_api node dist/apps/cli/main.cjs
实测回显(全文):
Usage: recipesage [options] [command]
RecipeSage CLI
Options:
-h, --help display help for command
Commands:
indexRecipes [options] Backfill the Postgres full-text search tsv columns.
categorizeShoppingListItems Categorize uncategorized shopping list items.
recomputeDiscoverRankScores [options] Recompute the smart-ranking and rating scores for every discover recipe. Intended to be scheduled (for example, as a Kubernetes CronJob).
remoderateStuckDiscoverRecipes [options] Re-queue moderation for discover recipes stuck in PENDING.
activateBonusFeatures [options] Activate bonus features (a subscription) for a user by email address.
seed Seed baseline database records (the assistant user and the shared example recipe images).
decryptDebugStore [options] Decrypt an encrypted debug store dump.
help [command] display help for command
⚠️ 实测纠偏:Commander 帮助只有 -h/--help,没有 --version 选项;selfhost 版本以镜像 tag 为准(docker inspect recipesage_api --format '{{.Config.Image}}' 回显 julianpoy/recipesage-selfhost:api-v4.1.1)。
4.2 indexRecipes(搜索索引回填)
回填 PostgreSQL 全文检索 tsv 列(搜索功能依赖)。参数实测(--help 回显):-b, --batch-size <size> 默认 1000;-i, --batch-interval <interval> 默认 1(秒)。
docker exec recipesage_api node dist/apps/cli/main.cjs indexRecipes
实测回显:
Postgres FTS backfill complete!
该命令已包含在 api 启动序列里(见 6.1),常规无需手跑;导入大批旧食谱后搜索不中、或改过Recipes表后可手动补一次。幂等,可放心重复执行。
4.3 categorizeShoppingListItems(清单条目自动分类)
对未分类的购物清单条目调用分类器(默认走 GROCERY_CATEGORIZER_URL 公有 API,本地化见配置篇 5.6)。无额外参数。
docker exec recipesage_api node dist/apps/cli/main.cjs categorizeShoppingListItems
实测回显:
Categorization complete!
4.4 recomputeDiscoverRankScores(discover 智能排序重算)
重算 discover 分享池全部食谱的排序与评分分,官方描述适合定时调度(如 CronJob)。参数实测:-b, --batch-size <size> 默认 1000。selfhost 私有实例未开启 discover 分享时基本空跑,按需调度:
docker exec recipesage_api node dist/apps/cli/main.cjs recomputeDiscoverRankScores --batch-size 500
4.5 remoderateStuckDiscoverRecipes(卡审重入队)
把卡在 PENDING 的 discover 食谱重新排入 AI 审核队列(依赖 AI_MODEL_MODERATION 配置)。参数实测(--help 回显):-a, --min-age-minutes <minutes> 默认 30;-b, --batch-size <size> 默认 100;--dry-run 默认 false(只列出不入队)。未配 AI key 时入队任务会失败,先用 dry-run 观察:
docker exec recipesage_api node dist/apps/cli/main.cjs remoderateStuckDiscoverRecipes --dry-run
4.6 activateBonusFeatures(订阅特权开通)
按邮箱给用户开通 bonus features(订阅模型)。参数实测:--email <email>;--subscription-name <name> 默认 forever,枚举 forever|pyo-monthly|pyo-yearly|pyo-single。这是托管 SaaS 的运营口子——selfhost 未配 Stripe(注入层 STRIPE_SK 置空),对私有实例意义有限,列出防误用。
4.7 seed(基线数据初始化)
写入基线记录(assistant 用户与共享示例食谱图片),无参数。api 启动脚本已自动执行(幂等),手工场景仅用于全新库补种:
docker exec recipesage_api node dist/apps/cli/main.cjs seed
4.8 decryptDebugStore(调试转储解密)
解密加密的 debug store 转储。参数实测:--input <input>、--output <output>(输入/输出文件名)。与 /app/scripts/decrypt-debug-dump.sh 配套,排障向作者提交诊断包时使用。
4.9 参数默认值速查(全部 --help 实测)
| 命令 | 参数 | 实测默认值 |
|---|---|---|
| indexRecipes | -b/--batch-size / -i/--batch-interval | 1000 / 1(秒) |
| recomputeDiscoverRankScores | -b/--batch-size | 1000 |
| remoderateStuckDiscoverRecipes | -a/--min-age-minutes / -b/--batch-size / --dry-run | 30 / 100 / false |
| activateBonusFeatures | --subscription-name | forever(枚举 forever/pyo-monthly/pyo-yearly/pyo-single) |
| decryptDebugStore | --input / --output | 无默认,必传 |
| seed / categorizeShoppingListItems | — | 无参数 |
五、compose 运维命令组
docker compose -p recipesage ps --format '{{.Name}} {{.Status}}'
实测回显:
recipesage_api Up 14 minutes
recipesage_postgres Up 14 minutes (healthy)
recipesage_proxy Up 14 minutes
recipesage_pushpin Up 14 minutes
recipesage_static Up 14 minutes
recipesage_valkey Up 14 minutes
其余高频动作(完整语境见部署篇第十节):
docker compose -p recipesage logs -f api # 排障主入口:迁移/请求/job 日志都在这里
docker compose -p recipesage restart api # 不改配置的纯重启
docker compose -p recipesage up -d api # 改 compose 配置后的重建生效(配置篇 3.3)
docker compose -p recipesage pull api static # 升级:api/static 必须成对拉新 tag
docker compose -p recipesage down # 停栈(卷保留,数据不丢)
六、容器内运维脚本(/app/scripts/)
docker exec recipesage_api ls /app/scripts/
实测回显:
decrypt-debug-dump.sh
dev-setup.sh
migrate.sh
prepare-for-capacitor-build.sh
prepare-for-electron-build.sh
restore-db.sh
selfhost-startup.sh
watchandrun.sh
6.1 selfhost-startup.sh(启动主线,原文实测)
api 容器 command 即此脚本,四步串行(cat 原文节选):
echo "==== Running migrations, please wait. ===="
pnpm exec prisma migrate deploy
echo "==== Running database seeders, please wait. ===="
node dist/apps/cli/main.cjs seed
echo "==== Rebuilding search index, please wait. ===="
node dist/apps/cli/main.cjs indexRecipes
echo "==== Starting API ===="
node dist/apps/backend/main.cjs
解读:迁移(69 个 Prisma migration 自动应用)→ seed → FTS 回填 → 起服务,全部幂等;升级新镜像后 up -d api 即自动完成库表迁移,无需手工 migrate。
6.2 restore-db.sh(⚠️ selfhost 不可直接用)
脚本原文(cat 实测节选):
POSTGRES_USER=recipesage_dev
POSTGRES_DB=recipesage_dev
...
server=root@db3.recipesage.com
scp -r $server:/pg-backup/$(ssh $server 'ls -t /pg-backup | head -1') restore.sql.gz
...
docker compose exec postgres dropdb -U $POSTGRES_USER $POSTGRES_DB
docker compose exec postgres createdb -U $POSTGRES_USER $POSTGRES_DB
gunzip -c restore.sql.gz | docker exec -i "$(docker compose ps -q postgres)" psql -U $POSTGRES_USER -d $POSTGRES_DB
纠偏(重要):该脚本面向开发环境——库/用户写死 recipesage_dev(selfhost 是 recipesage_selfhost),默认备份源是 RecipeSage 生产备份机 db3.recipesage.com(自托管机器不可能有权限),且先 pg_terminate_backend 踢掉全部连接再 dropdb(直接对 selfhost 跑等于清库)。不要原样执行;恢复请照 6.3 的手工流程(等价脚本逻辑,实测闭环)。带参数 $1 时用本地文件替代 scp 拉取,但库名硬编码问题仍在。
6.3 备份与恢复实测闭环(推荐做法)
备份(pg_dump + gzip,实测 20890 字节):
docker exec recipesage_postgres pg_dump -U recipesage_selfhost recipesage_selfhost | gzip > rs_backup2.sql.gz
ls -la rs_backup2.sql.gz
实测回显:
-rw-r--r-- 1 root root 20890 Nov 2 04:56 rs_backup2.sql.gz
恢复验证——为不破坏主库,恢复到异名测试库做全链路校验:
docker exec recipesage_postgres createdb -U recipesage_selfhost rs_restore_test
gunzip -c rs_backup2.sql.gz | docker exec -i recipesage_postgres psql -U recipesage_selfhost -d rs_restore_test -q
echo "psql rc=$?"
实测回显:psql rc=0。校验表数与数据:
docker exec recipesage_postgres psql -U recipesage_selfhost -d rs_restore_test \
-tAc "select count(*) from pg_tables where schemaname='public'"
docker exec recipesage_postgres psql -U recipesage_selfhost -d rs_restore_test -tAc 'select title from "Recipes" limit 3'
实测回显:
40
G25 Test Pasta Aglio e Olio
Pasta Aglio e Olio
40 表、两条食谱(含历史批次数据)完整恢复,备份可用性证实。清理测试库:
docker exec recipesage_postgres dropdb -U recipesage_selfhost rs_restore_test
实测回显:命令无输出、退出码 0(随后 psql -l 中 rs_restore_test 消失)。真要恢复主库时,把 6.2 脚本的 dropdb/createdb 目标换成 recipesage_selfhost 并先停 api(docker compose -p recipesage stop api),再执行同样的 gunzip -c … | docker exec -i … psql -d recipesage_selfhost。
6.4 migrate.sh 与 decrypt-debug-dump.sh
migrate.sh 原文只有一行:docker compose exec backend pnpm exec tsx packages/backend/src/migrate.js——目标服务名是开发编排的 backend,selfhost 栈里不存在(api 服务迁移走 6.1 的 prisma migrate deploy),同样不可照搬。decrypt-debug-dump.sh 是 4.8 CLI 命令的 shell 包装。
七、REST 兼容层 API 工具面
tRPC 路由自动生成 REST 兼容层,权威清单自取:
curl -s http://127.0.0.1:8162/api/openapi.json -o rs_openapi.json && wc -c rs_openapi.json
python3 -c "import json;d=json.load(open('rs_openapi.json'));print('paths:',len(d['paths']))"
实测回显:
403081 rs_openapi.json
paths: 144
高频端点速查(方法/参数为 2026-11-02 实测,认证统一 Authorization: Bearer <token>):
| 端点(/compat/v2/ 前缀) | 方法 | 实测要点 |
|---|---|---|
users/register | POST | name/email/password,直接返回 token(无邮箱验证) |
users/validateSession | GET | 返回 "Valid" |
users/getMe / getMyStats / getMyFriends | GET | getMyStats 用 POST 实测 404 |
users/createFriendship | POST | friendId;协作需双向各调一次 |
recipes/createRecipe | POST | 全字段必填;folder 枚举 main/inbox |
recipes/getRecipes | POST | body:folder/orderBy/orderDirection/offset/limit;GET 实测 404 |
recipes/getRecipe | GET | ?id= |
shoppingLists/createShoppingList | POST | collaboratorUserIds 必填(可空数组) |
shoppingLists/createShoppingListItem | POST | shoppingListId/title/quantity/recipeId/completed/categoryTitle |
shoppingLists/updateShoppingList | POST | 共享协作改这里(带全 title+collaboratorUserIds) |
jobs/startExportJob | POST | format 枚举 txt/pdf/jsonld,返回 jobId |
jobs/getJob / getJobDownloadUrlById | GET | 参数名是 id 不是 jobId |
clip(/api/clip) | POST | 未配 AI key 实测 400 |
导入方向:jobs 子路由内置 18 种外部服务适配器(copymethat、crouton、csv、enex、jsonld 等,openapi.json 内搜 startImport 可见全表);/api/ml/getRecipeFromOCR|getRecipeFromPDF|getRecipeFromText 依赖 AI 组配置(见配置篇 5.5)。⚠️ v4 已无旧 /api/groups 群组端点(实测 GET/POST 均 404)。
八、注意事项
- CLI 只在 api 容器内有意义:依赖容器工作目录
/app与注入的DATABASE_URL;宿主直接跑node dist/apps/cli/main.cjs会因找不到模块/连不上库失败。 - restore-db.sh / migrate.sh 是开发环境脚本(库名、服务名、备份源均非 selfhost 形态),恢复请走 6.3 手工流程。
- dropdb 前先停 api:否则连接池重连会报库不存在;恢复完
up -d api自动跑迁移对齐 schema。 - indexRecipes/seed 已内嵌启动序列,重复执行幂等;remoderate 类命令未配 AI key 时只会产生失败 job。
- 备份只覆盖 PG;图片/导出产物在 apimedia 卷(
/rs-media),完整备份 =pg_dump+ 卷打包(见部署篇第七节)。
九、常见问题(FAQ)
Q1: docker exec recipesage_api node dist/apps/cli/main.cjs 报 Cannot find module?
A: 检查是否在 api 容器(镜像名 api-v4.1.1 那个)且未改工作目录;CLI 路径相对 /app。
Q2: 搜索搜不到刚导入的食谱?
A: 跑一次 indexRecipes(4.2),FTS tsv 回填后立即可搜。
Q3: 清单条目一直不分类?
A: categorizeShoppingListItems 依赖外部分类器 API(默认公有服务),网络不通时先验证 GROCERY_CATEGORIZER_URL 可达(配置篇 5.6)。
Q4: 恢复备份后 Web 端 500?
A: 多半是备份来自旧版本 schema——恢复后 up -d api 让启动脚本自动 prisma migrate deploy 对齐(6.1)。
Q5: getJob 用 ?jobId= 查不到?
A: 参数名是 id(实测 getJob?id=<uuid> 200)。
Q6: CLI 能列出版本号吗?
A: 不能(无 --version,见 4.1 纠偏);用 docker inspect recipesage_api --format '{{.Config.Image}}' 看镜像 tag。
十、参考链接
- 源码仓库(CLI 实现 packages/cli):https://github.com/julianpoy/RecipeSage
- 部署仓库与 compose:https://github.com/julianpoy/RecipeSage-selfhost
- API 文档:https://docs.recipesage.com/api/ (本机自描述
/api/openapi.json) - 同专栏:配置见 《RecipeSage 4.1.1 配置参数详解》,部署见 《RecipeSage Docker Compose 部署指南》,选型见 《RecipeSage 介绍与选型指南》
取证说明:本文 CLI 帮助与参数默认值、compose/psql/备份恢复、openapi 统计均为 2026-11-02 在 v4.1.1 实测栈逐条执行回显;恢复闭环采用异名测试库验证后清理,未影响主库数据。