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)

RecipeSageRecipeSageDockerPostgreSQL运维2026/11/02

RecipeSage 4.1.1 常用 CLI 命令与工具详解

目标:系统梳理 RecipeSage 4.1.1 selfhost 形态的四组命令行工具——api 容器内的 recipesage CLI(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 / Compose29.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 CLIapi 容器 /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 做用户级异步任务。

三、前置条件

  1. 六服务栈在线:docker compose -p recipesage ps 六行 Up(部署见 B2 篇)。
  2. CLI 依赖 api 容器内的运行时环境(Node 24、/app 工作目录、注入的 DATABASE_URL 等环境变量)——必须在容器内执行,宿主无 node/凭据。
  3. 下文示例统一用单行形态: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-interval1000 / 1(秒)
recomputeDiscoverRankScores-b/--batch-size1000
remoderateStuckDiscoverRecipes-a/--min-age-minutes / -b/--batch-size / --dry-run30 / 100 / false
activateBonusFeatures--subscription-nameforever(枚举 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/registerPOSTname/email/password,直接返回 token(无邮箱验证)
users/validateSessionGET返回 "Valid"
users/getMe / getMyStats / getMyFriendsGETgetMyStats 用 POST 实测 404
users/createFriendshipPOSTfriendId;协作需双向各调一次
recipes/createRecipePOST全字段必填;folder 枚举 main/inbox
recipes/getRecipesPOSTbody:folder/orderBy/orderDirection/offset/limit;GET 实测 404
recipes/getRecipeGET?id=
shoppingLists/createShoppingListPOSTcollaboratorUserIds 必填(可空数组)
shoppingLists/createShoppingListItemPOSTshoppingListId/title/quantity/recipeId/completed/categoryTitle
shoppingLists/updateShoppingListPOST共享协作改这里(带全 title+collaboratorUserIds)
jobs/startExportJobPOSTformat 枚举 txt/pdf/jsonld,返回 jobId
jobs/getJob / getJobDownloadUrlByIdGET参数名是 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)。

八、注意事项

  1. CLI 只在 api 容器内有意义:依赖容器工作目录 /app 与注入的 DATABASE_URL;宿主直接跑 node dist/apps/cli/main.cjs 会因找不到模块/连不上库失败。
  2. restore-db.sh / migrate.sh 是开发环境脚本(库名、服务名、备份源均非 selfhost 形态),恢复请走 6.3 手工流程。
  3. dropdb 前先停 api:否则连接池重连会报库不存在;恢复完 up -d api 自动跑迁移对齐 schema。
  4. indexRecipes/seed 已内嵌启动序列,重复执行幂等;remoderate 类命令未配 AI key 时只会产生失败 job。
  5. 备份只覆盖 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 帮助与参数默认值、compose/psql/备份恢复、openapi 统计均为 2026-11-02 在 v4.1.1 实测栈逐条执行回显;恢复闭环采用异名测试库验证后清理,未影响主库数据。

RecipeSage 4.1.1 常用 CLI 命令与工具详解 - Quzuo