# Rabetbase

> Use for Lovrabet development work through the rabetbase CLI: create or bind projects (including creating an AppCode project in the current folder), pull Dataset/API facts and maintain SDK clients, or manage datasets, Instant API access policies, database connections, pages, SQL, Backend Functions, menus, notifications, knowledge bases and kb search, Agent Context Rules, roles, files, OCR, deployment metadata, platform issues, and 钉钉沙箱账号绑定. Trigger when the user mentions rabetbase, Lovrabet development, AppCode, Dataset, Instant API allow/deny/route policy, project creation, api pull/codegen, dblink, page, SQL, BFF, menu, notification, knowledge base, kb search, Agent Context Rules, RULES.md, DATABASE.md, rule list/get/set, role, file/OCR, or related development workflows.

- Skill: `lovrabet/rabetbase` (Agent Skill, multi-file: 134 files)
- Install (CLI): `npx skillmds@latest add lovrabet/rabetbase`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lovrabet/rabetbase/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: lovrabet (https://skillmd.com/u/lovrabet)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/lovrabet/rabetbase

---


# Rabetbase CLI

> **前置条件：** 使用任何 API 命令前，需完成认证和配置（见下方）。
> **资料使用：** 先从意图索引定位能力，只读取当前任务直接相关的 reference。写操作、覆盖/恢复、复杂输出解析或命令契约不明确时，执行前读取对应 reference；简单只读操作可依据已确认的 CLI schema 直接完成。
> **命名约定：** 统一使用 `rabetbase <service> <command> [flags]` 格式。
> **输出格式：** AI Agent 需要结构化输出时，**优先 `--format compress`**（与 `json` 相同信封，单行紧凑、省 token）；需要人类可读缩进时用 **`--format json`**。可在 **`json` / `compress`** 上叠加 **`--jq '<expr>'`**（对最终打印的整条 JSON 做 jq；二进制查找顺序为 **`JQ_PATH` → CLI 内置 sidecar jq → `PATH` 上的 jq**，通常无需单独安装系统 jq）。不确定当前 CLI 有哪些子命令或 flags 时，先跑 **`rabetbase schema`**（与 `--help` 同源的机器可读契约，无需登录）。

## 前置条件

1. **连接配置与认证分离**：首次使用先执行 `rabetbase config init`。交互模式选择当前已开放国家/地区；非交互模式显式传 `--region`，未传时使用默认节点。企业独立部署优先导入 `lovrabet-routing/v1` 清单，也兼容旧扁平 Domain 文件和对应 `--*-domain` flags。`config init` 默认重建当前项目节点/Domain 配置，显式 `--global` 时写全局；保留 Cookie、AccessKey、format、locale 和应用绑定，但不登录、不绑定项目，随后再执行 `rabetbase auth login`
2. **AppCode**：确保 `.rabetbase.json` 中设置了 `apps`（单应用自动选中；多应用再配 `defaultApp`），或兼容读取的顶层 `appcode`，或通过 `--appcode <code>` / `--app <name>` 传入。旧 `.lovrabet.json` 不会自动读取
3. **配置文件**：`rabetbase config init` 默认写当前项目 `.rabetbase.json`，显式 `--global` 时写 `~/.rabetbase.json`；默认节点不落冗余 `region`。官方节点模式清理显式和遗留 Domain，独立部署模式清理旧 `region`/Domain 后写入路由配置。完整字段说明见 [`.rabetbase.json` 配置参考](references/rabetbase-config.md)。当前目录应用绑定使用下方 `workspace init`
4. **工作目录应用绑定**：当前目录要固定使用某个应用时，使用 `rabetbase workspace init --appcode <code>` 或 `rabetbase workspace use --app <name>`（选型见「app vs workspace 职责边界」）
5. **多应用场景**：一个项目有多个应用时，先 `rabetbase workspace add <name> --appcode …` 登记各应用，再用 `--app <name>` 临时切换，或 `workspace use --app <name>` 修改当前工作目录默认应用
6. **平台发现**：当你不知道当前登录账号能访问哪些应用时，先 `rabetbase app list --remote`；它查询平台目录，不修改本地配置
7. **本地配置视图**：当你要确认当前项目或全局已经登记了哪些应用、默认应用是谁时，用 `rabetbase app list`。`rabetbase app` 本身只显示帮助，不等价于 `app list`
8. **人员目录查询**：查询某租户的人员用 `rabetbase tenant members-list --tenant-code <code>`；查询某应用的人员及其角色归属用 `rabetbase app members-list --appcode <code>`。两者均为只读全量查询，不提供分页、模糊搜索或写入能力。
9. **本地 SQL / Backend Function 目录**：新建或长期维护的源文件应落在 CLI 与 `bff status` / `sql pull` 一致的路径，避免写在 `src/`、`queries/` 等随意目录后再迁移。
   - **SQL**：项目根 **`.rabetbase/sql/<appCode>/<dbName|db-<id>>/<sqlCode>_<sqlName>.sql|xml`**；草稿或人工兜底可放 `.draft.sql`。`sql create` / `sql pull` / `sql push` / `sql status` 默认围绕这套目录与 `.rabetbase/sql.lock.json` 工作。
   - **Backend Function**：**`.rabetbase/bff/<appCode>/...`**（由 `bff create` 创建或 `bff pull` 同步；与 `bff status` / `bff push` 扫描范围一致）。详见 [`guides/sql-creation-workflow.md`](guides/sql-creation-workflow.md)、[`guides/bff-creation-workflow.md`](guides/bff-creation-workflow.md)。
   - **Instant API Policy**：**`.rabetbase/instant-api-policy/<appCode>/policy.json`**。`instant-api-policy init/pull/validate/publish` 只读取或写入这一固定文件，不接受任意 `--file`。
10. **运行态查数显式交接** — `rabetbase` 只负责 Dataset 结构与研发发布。不需要真实行数据时，`lovrabet` CLI 可以不装。一旦要验证真实业务行数据，必须交接给 **`lovrabet data filter/getOne`**；不可用时报告阻断并提示安装 `lovrabet` Skill 与 CLI。不要调用已移除的 `rabetbase data filter/getOne`，也不要由本 Skill 静默安装或修复运行态 CLI。`rabetbase sql exec` 只验证已发布 SQL，不是行数据查询的通用替代。详见 [`guides/data-api-guidelines.md`](guides/data-api-guidelines.md)。

## Skill Freshness

- **本地 repo 与 CLI 契约优先** — 若已安装的全局 skill 描述与当前仓库 `skills/rabetbase/`、`rabetbase --help`、`rabetbase schema` 不一致，以**当前仓库内容和 CLI 实际输出**为准。
- **发现 skill 过期时应主动刷新** — CLI 安装和升级会自动安装同版本 Skill；若不一致已经影响当前任务判断，应执行 `rabetbase cli-skill install`，由最新版官方 Skills CLI 从当前 npm 包内本地源重装。
- **刷新后必须重新读取** — 刷新完成后，重新打开当前 `SKILL.md` 与所需 reference，再继续执行任务，避免沿用旧记忆。
- **刷新失败也不能回退到旧结论** — 若安装失败，明确告诉用户“本地全局 skill 可能过期”，并继续以仓库内 `skills/rabetbase/` 和 `rabetbase schema` 作为 source of truth。

## Agent 快速执行顺序

1. **判断需求类型**
   - Instant API 标准数据记录操作 → SDK filter/getOne/create/batchCreate/update/delete；批量更新使用 `update({ id: [...] })`，不存在 `batchUpdate()`
   - 简单聚合且数据集是 DB_TABLE → SDK aggregate；聚合列用 `aggregate[].column`，不要用旧别名 `field`
   - 复杂 JOIN / 数据库函数且数据集是 DB_TABLE → Custom SQL
   - 图表、统计卡片或数据大屏 → 自定义页面 + ECharts；数据层根据查询复杂度选择 Dataset 或 Custom SQL
   - 当前用户、角色、数据范围、外部系统、跨表事务或复杂业务编排 → Backend Function；Backend Function HOOK 可挂 DB_TABLE 或 METADATA，具体 operation 以后端返回为准
2. **先拿元数据，再写代码**
   - 至少先查 `rabetbase dataset detail --code xxx --format compress`（或 `json`）获取表结构
   - 跨表场景还需查目标表的结构
   - 写入前用 `data.fields[]` 确认真实字段、必填字段、枚举选项；枚举/选择字段写入 `options[].value`，不是展示 `label`
   - 需要了解数据集关联关系时用 `rabetbase dataset relations --format compress`（或 `json`）；需要审计关系事实错误和人工复核项时用 `rabetbase dataset relation-audit --format compress`
   - 需要从文本需求创建新的 `METADATA` 数据集时，先读 [`dataset generate-start/status`](references/rabetbase-dataset-generate.md)，执行 preview 写出 design 文件，审阅后用 `generate-start --apply --design-file` 提交任务，再用 `generate-status` 查询到成功
   - **管理物理库连接 / 测连 / 同步表结构分析**时用 `rabetbase db …`（先 [`db list`](references/rabetbase-db-list.md)，trace/plan id 见 [`database-connection-workflow.md`](guides/database-connection-workflow.md)）
   - 研发资源保存后的增量同步由服务端自动处理；仅在管理员明确要求首次初始化、历史回填或故障恢复时读 [`deployment sync-all`](references/rabetbase-deployment-sync-all.md)，在停止编辑的安静窗口执行；提交成功后按 jobId 查询状态，提交结果未知时用 `sync-jobs` 恢复任务事实
   - DBAgent 增量分析默认先执行一次异步差异刷新：调用 `db diff-refresh-start`，保存 traceId，并用 `db diff-refresh-status` 查询同一任务到终态；成功后按原始意图执行 `db diff --all`（差异表）或 `db tables`（全部表）。无论 `tableCount` 大小都执行刷新；只有用户明确表示“不需要分析”“不刷新”或“只看现有结果”时才跳过异步刷新，并说明结果可能不是最新事实
   - 需要查看全部表（含无差异表）或主动重新分析既有表时，用 `db tables`；它固定聚合全表分页。`db diff --all` 只聚合全部差异分页
   - DB 增量分析先对完整 `toAnalyzeTables` 执行 `db analyze-batch-plan`；它生成的是本地批次方案，不是服务端 `planId`，也不会创建任务。再严格按批次顺序启动；每批独立保存 `planId`（即 `analyze-start` 返回值），当前批次到达已知终态前不得启动下一批
   - 全部批次结束后再次执行异步差异刷新并重新获取完整差异；仍未收敛时，按 [`database-connection-workflow.md`](guides/database-connection-workflow.md) 对剩余 `toAnalyzeTables` 逐表串行重试且每表只恢复一次。仅当用户明确要求跳过分析/刷新时直接读取现有差异。状态查询失败继续使用原 `planId`，不得重复启动任务
   - 输出很大且只需子集时，在 `compress`/`json` 上加 `--jq '.data…'` 缩小结果
   - 需要真实业务行数据时必须交接给 `lovrabet data filter/getOne`；`lovrabet` 不可用时报告阻断并提示安装 Skill 与 CLI，不要静默安装或修复，也不要用 `rabetbase sql exec` 当行数据替代，见 [`guides/data-api-guidelines.md`](guides/data-api-guidelines.md)
   - 需要 `src/api/api.ts` / `client.ts` 时：先 `rabetbase api pull --format compress` 取 `data.models`、`data.files`、`data.needsAgentMerge`，再按 [`sdk-client-generation.md`](guides/sdk-client-generation.md) 更新 TypeScript。`api pull` 默认**不会覆盖已有** `api.ts`/`client.ts`；只有用户明确要求放弃本地定制并完整重建时才使用 `--force --yes`
   - 需要按 Dataset + API 配置 Instant API 的 `allow`、`deny` 或 `route` 时，先读取 [`rabetbase-instant-api-policy.md`](references/rabetbase-instant-api-policy.md)，只编辑固定 `policy.json`，随后依次执行 `validate`、`publish --dry-run`，经人工确认后再正式发布
3. **SQL 工作流严格分步**
   - 推荐路径：查现有(`sql list/detail`) 或新建(`sql create`) → 拉/落本地(`sql pull` / `sql create`) → 编辑同步目录文件 → 可选校验(`sql validate`) → 检查状态(`sql status`) → 先预览(`sql push --dry-run` / `sql delete --dry-run`) → 再 `sql push` / `sql delete` → `sql detail` / `sql exec` 验证
   - 先使用 `sql list/detail` 查找可复用的 Custom SQL；没有满足需求的资源时，按照 [`sql-creation-workflow.md`](guides/sql-creation-workflow.md) 与 [`sql-mybatis.md`](guides/sql-mybatis.md) 创建、校验、发布并验证
   - 页面执行已发布的 Custom SQL 时使用 `sqlCode` + `params`；Backend Function 默认使用 `context.client.sql.byName(sqlName).execute({ params })`，`sql.execute({ sqlCode, params })` 仅作兼容路径
4. **Backend Function 工作流严格分步**
   - 查现有 → 确认字段或通知配置 → 查公共函数 → 本地创建(`bff create`) → 检查状态(`bff status`) → 先预览(`--dry-run`) → 再拉取/推送/删除
   - 创建会发送消息通知的 Backend Function 时，先读取 [`backend-function.md`](guides/backend-function.md) 的“消息通知扩展”契约，再执行 [`rabetbase notification config-list --type EMAIL`](references/rabetbase-notification-config-list.md) 获取当前应用的 `configCode`；不得猜测渠道、收件人或把密钥写进脚本
   - 推送完成只代表脚本配置已同步到平台；若用户要确认最终运行效果，显式交接到运行验证（如可用的 `lovrabet bff exec`），不要把运行验证伪装成 `rabetbase` 已完成
5. **页面体系选择**
   - 数据列表页（Data List Page）是数据集驱动的结构化页面组，用于数据查看、维护和模型验证，不等同于最终业务工作台
   - 自定义页面（Custom Page）是完整代码文件驱动的独立页面，用于工作台、看板、门户和复杂业务交互；当前 React JSX 只是渲染实现，不是页面产品类型
   - 图表、统计卡片和数据大屏使用自定义页面与白名单内的 ECharts
   - 页面体系不明确时，先向用户确认；不要为同一目标同时创建数据列表页与自定义页面
6. **数据列表页（Data List Page，page）工作流**
   - 工作流判断先看 [`guides/page-development-workflow.md`](guides/page-development-workflow.md)
   - `page` 命令职责分离：[`page generate-start`](references/rabetbase-page-generate-start.md) 负责提交或复用任务，[`page generate-status`](references/rabetbase-page-generate-status.md) 负责查询任务状态，[`page data-list-status`](references/rabetbase-data-list-status.md) 负责查询数据列表页事实
   - 数据集字段变更后同步已有数据列表页：[`page sync`](references/rabetbase-page-sync.md)
   - 页面关系绑定审计：先读 [`rabetbase-page-relation-binding.md`](references/rabetbase-page-relation-binding.md)，再执行 [`page relation-audit`](references/rabetbase-page-relation-binding.md)
   - 遇到“关联数据带不出 / 数据列表页没有生成关联关系 / 页面关联绑定异常”类问题，固定顺序是：`dataset relations` 只读确认关系事实 → `dataset relation-audit` 审计关系事实风险 → `page data-list-status` 判断页面是否存在 → `page relation-audit` 审计页面绑定；若关系事实本身不对，先按 [`dataset relation-create/update/delete`](references/rabetbase-dataset-relation-mutations.md) 做 `--dry-run` 方案并等用户确认；已有页面再 `page sync --dry-run`，无页面走 `page generate-start --dry-run`
   - `page sync` 只负责同步已有数据列表页，不是数据集关系修复命令，也不能承诺自动修复所有 `wrong_code` / `wrong_label` / `missing`
   - 本地 schema 开发：[`page pull`](references/rabetbase-page-pull.md) → IDE 编辑 → [`page push`](references/rabetbase-page-push.md)
   - 恢复已删除页面：先读 [`page restore`](references/rabetbase-page-restore.md)，CLI 产品类型只使用 `DATA_LIST|CUSTOM`；默认按 ID 自动识别，存在跨类型同 ID 时显式传 `--page-type`
   - 需要理解 formal schema 组件语义时，再按需阅读 `knowledge/page-schema/` 下的 PageSchema 组件资料；不要把它与 `rabetbase page` 命令 reference 混淆
7. **自定义页面工作流**
   - 自定义页面与数据列表页是两类独立页面能力，不混用两类页面的命令
   - 创建、修改或发布前，必须先阅读 [`custom-page-workflow.md`](guides/custom-page-workflow.md)，再按其中的编排读取对应原子命令 reference
   - 编写 JSX、CSS 或词包前，必须阅读 [`generation-standards.md`](knowledge/custom-page/generation-standards.md)；选择 UI 组件时阅读 [`components.md`](knowledge/components.md)
8. **Legacy modernization / Application Blueprint 工作流**
   - 当用户要把无人交接老项目、外包接手项目或遗留系统翻新到 Lovrabet 体系时，先阅读 [`guides/legacy-application-blueprint-workflow.md`](guides/legacy-application-blueprint-workflow.md)
   - 主产物是 `.rabetbase/blueprint/<appCode>/application-blueprint.md`，不是直接生成或推送 SQL/Backend Function
   - 必须把老代码 Logic Graph 与 dbagent 已生成的 Dataset / Relations 绑定，再判断 Instant API、Custom SQL、Backend Function、Hook、COMMON 或 Java Service 落点

## 应用决议指引

1. **已明确 appcode**
   - 用户直接给了 `app-xxxx`
   - 或当前命令已经显式传了 `--appcode`
   - 直接执行目标命令，不需要先查 `rabetbase app list --remote`

2. **已明确本地应用名**
   - 当前项目 `.rabetbase.json` 已有唯一 app，或多 app 已配置 `defaultApp`
   - 或用户给了 `--app <name>`
   - 先用 `rabetbase app list` 验证本地配置，再执行目标命令

3. **只知道业务名称，不知道能访问哪个应用**
   - 先 `rabetbase app list --remote --format compress`
   - 从平台目录里确认当前登录账号可访问的应用
   - 再决定是否需要 `rabetbase workspace add` / `rabetbase workspace use`，或临时传 `--appcode`

4. **不要混淆两种视图**
   - `rabetbase app list`：本地配置视图，回答“当前项目/全局登记了哪些应用”
   - `rabetbase app list --remote`：平台目录视图，回答“当前登录账号能访问哪些应用”

5. **当两边不一致时**
   - 平台上有，本地没有：说明还没登记到本地配置，可用 `rabetbase workspace add`
   - 本地有，平台上查不到：说明当前账号可能无权限，或本地配置已过时，应先核对权限与 appcode

## 菜单异步重新分组（`menu regroup-start`）

执行前先阅读 [`menu regroup-start`](references/rabetbase-menu-regroup-start.md) 与 [`task status`](references/rabetbase-task-status.md)。该流程的完成口径不是“任务已提交”，而是异步重新分组任务到达明确终态：

1. 先用 `menu list` 取得精确的非 folder 叶子菜单 ID，再执行 `menu regroup-start --dry-run`。
2. 正式执行只提交一次并保存 `data.task.taskId`。首次回读时，`data.verification.groupingApplied` 可能是 `true` 或 `"unconfirmed"`；未回读确认不代表任务提交失败。
3. 若 `data.task.status` 为 `PENDING / PROCESSING`，执行返回的 `data.query.command`；后续仍为非终态时继续查询同一个 taskId，不得再次提交 `regroup-start`。
4. 保留初始响应的 `data.verification.lookupCommand`。无论初始响应已是 `SUCCESS`，还是后续 `task status` 到达 `SUCCESS`，都必须用该命令回读最终菜单事实；回读仍未确认时只重试只读查询，不得重提 `regroup-start`。
5. `FAILED` 时报告 `errorMessage` 且不自动重提；未知状态（`knownStatus=false`）进入人工复核，不推断成功或失败。

## 数据库连接（`db`）

与 **`dataset`（数据集模型）** 的分工：**`db *`** 管平台登记的 **物理库连接（dblink）**、**测连**、**schema 分析任务**、**物理表清单与差异**；表字段、枚举以 **`dataset detail`** 为准，数据集关联关系优先以 **`dataset relations`** 为准，关系事实风险用 **`dataset relation-audit`**。

- **入口**：先 [`db list`](references/rabetbase-db-list.md) 取 `id` 与 `latestAnalysisTraceId`（如有）。
- **只读常用**：[`db detail`](references/rabetbase-db-detail.md)、[`db test`](references/rabetbase-db-test.md)、[`db tables`](references/rabetbase-db-tables.md)、[`db diff`](references/rabetbase-db-diff.md)。`db tables` 固定聚合全部表及分析状态；`db diff` 只读差异结果，`--all` 只聚合全部差异分页。
- **差异刷新**：[`db diff-refresh-start/status`](references/rabetbase-db-diff-refresh.md)。CLI 发起 DBAgent 增量分析时，无论 `tableCount` 多少或是否缺失，默认先刷新再读取差异；只有用户明确要求跳过分析/刷新时才直接读取现有结果。刷新与 schema `analyze-*` 是两类任务，不得混用。
- **分析任务**：`db analyze-batch-plan` / `analyze-start` / `analyze-cancel` / `analyze-status`（服务端 plan/trace 来源见下）。
- **状态诊断边界**：`analyze-status` 的 `requestedAnalysis` 只还原原始提交范围；`hasMultipleAttempts=true` 只表示观察到多个执行尝试。不得据此推断尝试间连续性、实际执行范围或自动重启。
- **增量分批**：先用本地只读的 `db analyze-batch-plan --id <id> --tables <清单>` 得到确定性批次及 `planningEstimate`；这里生成的是本地批次方案，不是服务端 `planId`，不会创建或预留任务。再逐批调用一次 `analyze-start`，读取真实 `planId` 与当前任务的 `serverEstimate`；每批独立保存其返回的 `planId`，同一 dblink 严格串行。两类估算都不得驱动超时、取消、重试、自动重启或状态判断，`PENDING / RUNNING / RETRYING / CANCELING` 均不得推进下一批。
- **取消已有任务**：只使用正在跟踪的原 `planId` 执行 `analyze-cancel --plan <原 planId>`；取消分支不得调用 `analyze-start`，也不得用可能变化的 `latestAnalysisTraceId` 替换已知目标。
- **失败恢复**：全部批次结束后默认再次异步刷新，再读取完整 `db diff --all` 获取未收敛表；只有用户明确要求跳过分析/刷新时才直接读取。随后逐表串行执行 `analyze-start --tables <单表>`，每表只恢复一次；累计原因计数只作可能不完整的参考展示。Agent 可语义理解原始 `errorMsg` 辅助解释和建议，但两者都不驱动任务状态、重提任务或收敛判断。
- **ER 图引导**：`db analyze-status` 终态成功后，检查并转述 `data.links.erPage`；若没有 `data.links`，补 `--appcode` 或进入已配置 app 的项目上下文后重查。
- **写入**：[`db create`](references/rabetbase-db-create.md) / [`db update`](references/rabetbase-db-update.md) 默认先测试未保存配置，只有显式 `--skip-connection-test` 才跳过；[`db delete`](references/rabetbase-db-delete.md) 必须先 dry-run，执行前重新检查 DB_TABLE Dataset 依赖，有依赖即阻止且无 force。三者都支持 **`--dry-run`**。
- **横切流程与 trace/plan**：[`database-connection-workflow.md`](guides/database-connection-workflow.md)。**单命令细则**见 `references/rabetbase-db-*.md`（与仓库 `src/commands/db/` 一一对应）。

## 开发角色与协作者（`role`）

`rabetbase role` 只管理开发角色与开发协作者关系，输出明确包含 `scope: "dev"`。业务人员角色、用户组成员以及页面、菜单、数据集权限属于 `lovrabet`。若 `lovrabet` 当前 Help/Schema 尚未提供对应命令，应明确告知能力暂不可用，不得改用 rabetbase 代替，也不得跨端双写。

- **角色类型**：`ADMIN` / `DEV` / `OWNER`（内置）与已有 `CUSTOM`；`update` / `delete` 仅 `CUSTOM`。当前不提供 `role create`。
- **只读人员目录**：租户全员查询用 [`tenant members-list`](references/rabetbase-tenant-members-list.md)；应用成员及角色归属查询用 [`app members-list`](references/rabetbase-app-members-list.md)。只查看事实时不要调用 `role user-add`/`user-remove`。
- **加人/移人**：先 [`role user-resolve`](references/rabetbase-role-user-resolve.md) 拿 userId，再 [`role user-add`/`user-remove`](references/rabetbase-role-user-add.md)（`high-risk-write`，只改目标开发角色；OWNER 直接拒绝）。
- **查看/改/删已有组**：[`role list/detail/update/delete`](references/rabetbase-role-list.md)。
- **铁律**：写前先读取当前角色/成员事实 → `--dry-run` 看 `data.before/after` → 高风险写显式 `--yes`；不要用 rabetbase 修改运行态权限。

## 配置作用域原则（`--global`）

- **写操作默认当前项目**（包括 `config init`、`workspace add`、`config set`、`project create` 等），除非用户**显式**传 `--global`。
- **不要**在用户未要求时给命令加 `--global`** — 默认行为已是「项目优先」；只有用户明确要改全局配置或不在项目内且意图写全局时才使用。
- **`config set`**：在**没有**项目配置文件（当前目录未解析到 `.rabetbase.json`）且**未**传 `--global` 时，CLI **拒绝执行**并提示使用 `--global` 或先 `rabetbase workspace init --appcode <code>`，**不会**静默写入全局。
- **`project create`** 生成的新项目 `.rabetbase.json` **只继承**少量全局偏好（如 `cookie` / `locale` / `format` / `riskLevel` 等），**不会**把全局 `apps` / `defaultApp` 带入新项目文件；同时生成浏览器安全的 `src/api/sdk-config.ts` 与 `rabetbase.domain-routing.json`。每个官方节点直接声明自己的第三方库 CDN 与 Lovrabet 自有资源 Domain；项目文件始终包含解析后的完整地址，企业独立部署从共用清单读取显式 CDN。两个生成文件都不下发认证配置；`rabetbase run start|dev|build|preview` 会在执行脚本前刷新公开 Domain 快照，也可用 `project domain-routing-sync` 立即显式刷新；`api pull` 只刷新 SDK/API 文件。
- **`api pull` / `api list`**：默认仅针对**项目** `apps`；需要合并全局已登记应用时加 `--global`（见各命令 reference）。
- **`app list`**：默认展示**合并**后的全量；`--global` 仅全局、`--project` 仅项目（见 [`rabetbase app list`](references/rabetbase-app-list.md)）。

## app vs workspace 职责边界

划分轴 = **「这是关于 app 的客观事实，还是关于我当前工作环境的配置？」**

- **`app` = 应用的客观事实查询**：回答「我有/能访问哪些 app」和「某应用有哪些人员及角色归属」，与在哪写代码无关。**只读**，不承载增删。
  - `app list`（本地登记视图）/ `app list --remote`（平台可访问目录）/ [`app members-list`](references/rabetbase-app-members-list.md)（应用人员）。
- **`workspace` = 配置当前工作环境用哪些 app**：一切「改我的配置」的写操作都在这里。
  - `workspace init`（首次绑定当前目录）/ `workspace use --app <name>`（切换当前目录默认应用）。
  - `workspace add <name> --appcode <code>`（登记应用 profile）/ `workspace remove <name>`（移除本地 profile）。
  - 默认写当前项目 `.rabetbase.json`；`--global` 写全局（全局视作一个大工作空间）。`init`/`use` 不从全局复制 cookie/accessKey。

**三入口选型（不要混用）**：

| 场景 | 命令 |
|------|------|
| 首次安装后的全局引导 | `rabetbase config init` |
| 当前目录还没绑定 app | `rabetbase workspace init --appcode <code>`（单应用不写 `defaultApp`） |
| 目录已有配置，只再登记一个 profile | `rabetbase workspace add <name> --appcode <code>`（从单应用变为多应用时保留原应用为默认；`--global` 写全局） |
| 切换当前目录默认应用 | `rabetbase workspace use --app <name>` |

**入口判断**：
- 「看有哪些 app / 平台上能访问哪些」→ `app list`（`--remote` 查平台）。
- 「看某应用有哪些人员及其角色」→ `app members-list --appcode <code>`。
- 「看某租户有哪些人员」→ `tenant members-list --tenant-code <code>`。
- 「登记/删除应用 profile」→ `workspace add` / `workspace remove`（要动全局清单时加 `--global`）。
- 「让当前目录用某应用 / 切换默认应用」→ `workspace init` / `workspace use`。

## Agent 禁止行为

- **不要猜字段名** — 必须从 `dataset detail` 返回值获取真实字段名、类型、枚举值
- **不要跳过 validate 与 dry-run** — 修改已有 SQL 并准备 `sql push` 前，必须先跑 `sql validate`；创建 SQL 或执行高风险同步前至少确认过 `sql create --dry-run`、`sql push --dry-run` 或 `sql delete --dry-run` 的预览
- **不要手动拼 API URL** — 所有操作通过 CLI 命令完成，不要直接调 HTTP 接口
- **不要把 `sync-all` 当成日常发布或精确镜像** — 它只用于管理员首次初始化、历史回填或故障恢复，按源端现存记录 UPSERT，不删除目标端额外记录；在停止编辑的安静窗口执行，提交结果不确定时先用 `deployment sync-jobs` 恢复任务事实，不自动重提
- **不要向产品用户展开研发实现** — 回答角色权限操作时，不输出工程仓库、Controller、数据库表、接口路径、MR 排查或迁移过程；只说明 CLI 命令、角色边界、风险和可验证结果
- **不要臆测 sqlCode / id** — 从 `sql list` 或 `bff list` 获取真实标识
- **不要臆测 dblink id 或分析 trace/plan id** — 从 `db list` / `db detail` / `db analyze-start` 的返回字段获取（见 [database-connection-workflow.md](guides/database-connection-workflow.md)）
- **只使用可见命令** — 以本 skill、`rabetbase schema`、`rabetbase --help` 中出现的命令为准；不要凭训练记忆调用未出现的旧别名
- **不要含糊处理失败** — `sql create` / `sql push` / `sql delete` / `bff push` / `bff delete` 返回失败时，必须明确告知用户是哪条资源失败、为什么失败
- **不要在不确认表结构时就写 SQL** — 先 `dataset detail`，后写 SQL、Backend Function、页面……
- **不要把案例字段当通用规则** — 任何 Demo、历史项目、示例里的字段名、枚举值、表名都不能照搬；必须以当前 `dataset detail` 为准
- **不要循环单条查询** — 用 SDK `filter + $in` 批量查询，不要 N+1
- **不要依赖 CLI 输出文本片段判断写入结果** — 对 `dataset rename --dry-run` / 正式执行，只读取结构化 envelope 的 `data.*` 稳定字段
- **不要跳过 Dataset rename 最终线上回查** — 连续重命名后必须按 code 重新查询线上名称，不能只相信本地 plan 或 dry-run
- **不要把 MCP 工具名当 CLI 命令** — 使用 `rabetbase sql list`，不是 `list_sql_queries`
- **不要擅自加 `--global`** — 见上文「配置作用域原则」；默认写项目、读合并；仅在用户明确要求或文档说明的场景使用 `--global`。
- **不要为 Instant API Policy 传任意文件路径或写入 app-config** — 策略只使用 `.rabetbase/instant-api-policy/<appCode>/policy.json` 与独立策略接口；发布和回滚前必须校验并预览。

## 接口选型优先级

遇到新需求时按优先级选择实现方式：

1. **标准 SDK 接口**（filter/getOne/create 等）— 能用就不写 SQL
2. **aggregate 聚合接口** — DB_TABLE 的简单分组汇总；METADATA 不默认支持 aggregate；聚合定义使用 `column` 指定列，`field` 仅作为历史兼容别名
3. **自定义 SQL** — DB_TABLE 的复杂 JOIN、数据库函数、跨表统计；METADATA 不支持 SQL 路径
4. **Backend Function** — 外部系统调用、跨表事务、复杂业务编排

## SDK 核心规则

### 初始化

```typescript
import { createClient } from "@lovrabet/sdk";
const client = createClient({
  appCode: "your-app-code",
  authMode: "client-ak", // 传 accessKey 时必须显式声明；缺省 authMode 一律走 cookie 模式，accessKey 会被忽略
  accessKey: process.env.RABETBASE_ACCESS_KEY,
  models: [{ tableName: "users", datasetCode: "abc123", alias: "users" }],
});
```

> 认证模式必须显式声明：`accessKey`（仅 accessKey）用 `authMode: "client-ak"`；`accessKey + secretKey` 或 `token` 的签名场景用 `authMode: "openapi"`；浏览器 Cookie 环境省略 `authMode`（默认 cookie）。

### filter 查询（最常用）

```typescript
const result = await client.models.users.filter({
  where: { status: { $eq: "active" } },
  select: ["id", "name"],
  orderBy: [{ createTime: "desc" }],
  currentPage: 1,
  pageSize: 20,
});
```

参数名强制约束：`select`（非 fields）、`orderBy`（非 sort）、`currentPage`/`pageSize`（非 page/limit）

where 条件强制使用操作符：`$eq` `$ne` `$gt` `$lt` `$gte`（或别名 `$gteq`）`$lte`（或别名 `$lteq`）`$in` `$contain` `$startWith` `$endWith` `$notNull`（`$gteq`/`$lteq` 为后端兼容别名，映射同一 SQL，新代码推荐 `$gte`/`$lte`）

### SQL 调用

页面 SDK 通过已发布 Custom SQL 的 `sqlCode` + `params` 执行查询；Backend Function 默认通过当前应用内唯一 `sqlName` 的 `context.client.sql.byName(sqlName).execute({ params })` 执行查询，`sql.execute({ sqlCode, params })` 作为兼容调用方式。

```typescript
const data = await client.sql.execute<MyRow>({
  sqlCode: "xxx",
  params: { key: "val" },
});
if (data.execSuccess && data.execResult) {
  console.log(data.execResult);
}
```

自定义页面需要图表时，在其 React JSX 实现中使用 ECharts 呈现；只读查询且平台 `sqlCode` 权限已经满足时可以直接调用上面已发布的 Custom SQL。需要基于当前用户、角色、数据范围或业务规则做额外控制时，页面改调 Backend Function，由 Backend Function 完成校验后再执行该 Custom SQL。执行失败时保留并报告原始错误，根据 SQL 资源状态、参数与权限定位问题。

### Backend Function 调用

```typescript
const result = await client.bff.execute<DashboardData>({
  scriptName: "getUserDashboard",
  params: { userId: "123" },
});
```

### Personal Backend Function 调用

前端或 Node 服务通过 `client.personal.bff.execute({ scriptId, params })` 调用 Personal Backend Function。认证方式、兼容性检查、`undefined` 处理和返回值约定见 [`typescript-sdk.md`](guides/typescript-sdk.md#4-前端--node-调用-personal-backend-function-api)。

### 前端 vs Backend Function 关键差异

|                 | 前端 SDK                                     | Backend Function (context.client)                 |
| --------------- | -------------------------------------------- | ------------------------------------ |
| SQL 返回值      | `{ execSuccess, execResult }`                | 直接返回数组 `T[]`                   |
| 单条查询        | `getOne({ id })`                             | `getOne({ id })`                     |
| 数据集访问      | 可通过初始化/生成代码使用 alias              | `DB_TABLE` 默认使用 `models.byTable(tableName, { dblinkId? })`；`METADATA` 使用 `"dataset_" + 数据集 code`，`DB_TABLE` 也支持该兼容调用方式 |
| `filter()` 返回 | `tableData` 为列表数据                       | `tableData` 为列表数据，不是 `list`  |
| `create()` 返回 | 以 SDK 文档/类型为准                         | 新记录 ID，不是完整对象              |
| SDK 初始化能力  | `createClient` / `registerModels`            | 不可用；`context.client` 由平台注入  |
| 调 Backend Function          | `client.bff.execute({ scriptName, params })` | —                                    |
| 调 Personal Backend Function | `client.personal.bff.execute({ scriptId, params })` | —                              |

## 意图 → 命令索引

| 意图 | 推荐命令 | 备注 |
|------|---------|------|
| 初始化连接配置 | [`rabetbase config init`](references/rabetbase-init.md) | 选择官方节点或导入独立部署 Domain |
| 创建新项目 | [`rabetbase project create`](references/rabetbase-project-create.md) | 支持新目录或当前空目录创建；完成口径与安全边界见 reference |
| 刷新项目公开 Domain 路由 | [`rabetbase project domain-routing-sync`](references/rabetbase-project-domain-routing-sync.md) | 根据当前有效配置原子生成项目级 `rabetbase.domain-routing.json`；与前端页面路由无关 |
| 从 lovrabet-cli 迁移 | [`rabetbase project upgrade`](references/rabetbase-project-upgrade.md) | 6 步自动迁移，`--yes` 跳过确认 |
| 老项目翻新蓝图 / Legacy Application Blueprint | [`guides/legacy-application-blueprint-workflow.md`](guides/legacy-application-blueprint-workflow.md) | 先输出 `.rabetbase/blueprint/<appCode>/application-blueprint.md`，把老代码逻辑与 Dataset / Relations 绑定后再生成迁移 Backlog |
| 运行 package.json 脚本 | [`rabetbase run <script>`](references/rabetbase-run.md) | `write`；先审阅脚本命令体，嵌入式工具暂不开放 |
| 安装 / 重装 / 刷新 CLI Built-in Skill | [`rabetbase cli-skill install`](references/rabetbase-cli-skill-install.md) | 由最新版官方 Skills CLI 从当前 npm 包内本地源重装同版本 Skill；发现本地 skill 过期时优先执行 |
| 退出登录 | [`rabetbase auth logout`](references/rabetbase-auth-logout.md) | 删除本地认证 cookie |
| 绑定当前用户的钉钉沙箱账号 | [`rabetbase user-account dingding-sandbox-bind`](references/rabetbase-user-account.md) | `write`；先 `--dry-run` 核对 ID，正式执行不要求 `--yes`；不需要 appCode |
| 诊断配置问题 | [`rabetbase doctor`](references/rabetbase-doctor.md) | Built-in Skill 一致性、合并配置、各侧 JSON 语法、域名、认证状态 |
| 上报平台问题 | [`rabetbase issue report`](references/rabetbase-issue-report.md) | 由 Skill 组织完整客观事实，禁止代替平台侧做根因判断或方案设计 |
| 上传应用文件 | [`rabetbase file upload`](references/rabetbase-file.md) | 返回可持久保存的 `filePath` |
| 获取文件访问链接 | [`rabetbase file query-url`](references/rabetbase-file.md) | 默认短效；Markdown/HTML URL-only 内容显式加 `--long-term` |
| 提取票证类业务材料的文字与结构化字段 | [`rabetbase ocr recognize`](references/rabetbase-ocr.md) | 发票、票据、证照等；不用于通用图片理解 |
| 导出命令契约（flags/risk 等） | [`rabetbase schema`](references/rabetbase-schema.md) | 与 `--help` 同源；**无需登录**；大结果用 `--format compress` |
| 更新 CLI 版本 | [`rabetbase update`](references/rabetbase-update.md) | 自动检测最新版本，CLI 与 Built-in Skill 一体升级 |
| 初始化/切换当前工作目录应用 | [`rabetbase workspace`](references/rabetbase-workspace.md) | 写当前目录 `.rabetbase.json`；不从全局复制 cookie/accessKey |
| 修改配置文件 | [`rabetbase config set <key> <value>`](references/rabetbase-config.md) | 默认写项目；无项目配置且未 `--global` 会拒绝；`--global` 写 `~/.rabetbase.json` |
| 列出配置 | [`rabetbase config list`](references/rabetbase-config.md) | 查看当前生效的配置 |
| 管理运行态 app-config | [`rabetbase app-config list/get/set/delete`](references/rabetbase-app-config.md) | 运行态 app-config 管理面；默认不输出明文 value；`set` 为 `write`，`delete` 保持 `high-risk-write` |
| 管理 Instant API 数据集访问策略 | [`rabetbase instant-api-policy init/current/pull/validate/publish/revisions/revision/rollback`](references/rabetbase-instant-api-policy.md) | 固定文件 `.rabetbase/instant-api-policy/<appCode>/policy.json`；`version` 是 JSON 结构版本，`revision` 是发布历史版本；publish/rollback 为 high-risk-write |
| 管理和检索当前研发应用的企业知识库 | [`rabetbase kb list/detail/search/create/update/delete`](references/rabetbase-kb.md) | 管理仅 company scope；search 固定 Development 且仅 `public/company`；`create/update` 为 `write`，`delete` 保持 `high-risk-write` |
| 管理当前研发应用的 Agent context 规则 | [`rabetbase rule list/get/set`](references/rabetbase-rule.md) | `RULES.md` 供页面、API 等研发 Agent 使用且排除 DB Agent；`DATABASE.md` 仅供数据库分析时 DB Agent 使用；两者在各自流程全程参与 context；set 为 `write`，先 dry-run |
| 查询或管理应用级通知配置 | [`rabetbase notification config-list`](references/rabetbase-notification-config-list.md) / [`rabetbase notification config-create`](references/rabetbase-notification-config-mutations.md) / [`rabetbase notification config-update`](references/rabetbase-notification-config-mutations.md) / [`rabetbase notification config-delete`](references/rabetbase-notification-config-mutations.md) | list 获取 Backend Function 所需 `configCode`；写入只接收单一敏感 JSON 源，先 dry-run；update/delete 必须 `--yes` |
| 查看线上菜单事实 / 菜单异常审计 | [`rabetbase menu list`](references/rabetbase-menu-list.md) | 返回 DFS 事实、children/page、URL、最近更新人/时间和 snapshotHash；异常治理先读 [`menu-anomaly-manual-cleanup`](guides/menu-anomaly-manual-cleanup.md) |
| 批量显示或隐藏菜单 | [`rabetbase menu visibility-update`](references/rabetbase-menu-visibility-update.md) | 用精确 ID/path 选择目标；先 dry-run，使用 `--expect-visible` / `--expected-count` 防漂移，正式执行必须 `--yes` |
| 创建外部网站链接菜单 | [`rabetbase menu external-link-create`](references/rabetbase-menu-external-link-create.md) | `write`；显式选择 `embedded` 或 `new-window`，仅接受 HTTPS；建议先 dry-run，正式执行不要求 `--yes` |
| 原地更新既有外链 URL | [`rabetbase menu external-link-update`](references/rabetbase-menu-external-link-update.md) | `write`；精确单 ID、URL-only；必须带旧 URL 与父级断言，先 dry-run，再复用参数正式执行 |
| 修改任意类型菜单名称 | [`rabetbase menu rename`](references/rabetbase-menu-rename.md) | 精确单 ID、label-only；使用 `--expect-label` 防漂移，先 dry-run 并检查 before/after |
| 同步本地微前端路由到平台 | [`rabetbase menu sync`](references/rabetbase-menu-sync.md) | 扫描 `src/pages` 创建缺失的 `procode` 菜单；不上传构建产物；正式执行前先 `--dry-run` |
| 修改微前端菜单资源 URL | [`rabetbase menu asset-update`](references/rabetbase-menu-asset-update.md) | `write`；用 ID/path 精确选目标或显式 `--all`，默认 patch 且保留加载模式，先 dry-run 再复用参数正式执行 |
| 查看/管理开发角色 | [`rabetbase role list/detail/update/delete`](references/rabetbase-role-list.md) | 角色类型为 ADMIN/DEV/OWNER/CUSTOM；仅 CUSTOM 可改/删；当前不提供 create；输出 `scope: dev` |
| 解析昵称/用户名到 userId | [`rabetbase role user-resolve`](references/rabetbase-role-user-resolve.md) | 基于租户成员目录；重名时列出候选 ID，再把选中的 ID 传给 `role user-add/user-remove --user <id>` |
| 查询租户人员列表 | [`rabetbase tenant members-list --tenant-code <code>`](references/rabetbase-tenant-members-list.md) | 先校验当前账号所属租户，再返回全量人员；不分页、不输出邮箱/手机号/头像 |
| 查询应用人员及角色列表 | [`rabetbase app members-list --appcode <code>`](references/rabetbase-app-members-list.md) | 按 userId 去重并聚合 `roles[]`；角色归属输出 `roleCode`，同时保留 ACTIVE/PENDING 状态 |
| 把开发协作者加入/移出角色 | [`rabetbase role user-add / user-remove`](references/rabetbase-role-user-add.md) | 只改目标开发角色；OWNER 直接拒绝；`high-risk-write`，先 `--dry-run` |
| 按 ID 删除菜单或目录树 | [`rabetbase menu delete`](references/rabetbase-menu-delete.md) | 精确删除空 folder/非 folder 叶子；非空 folder 显式 `--recursive`，计划按叶子优先批量提交并回读 |
| 创建空菜单分组 | [`rabetbase menu group-create`](references/rabetbase-menu-group-create.md) | group 持久化为 `type=folder`，保留平台生成的非空 path；先 dry-run 并检查创建位置与排序 |
| 修改菜单分组排序 | [`rabetbase menu group-update`](references/rabetbase-menu-group-update.md) | 目标必须为 folder；修改任意菜单类型的名称统一使用 `menu rename`；先 dry-run 并检查 before/after |
| 移动已有叶子菜单 | [`rabetbase menu move`](references/rabetbase-menu-move.md) | 使用精确源 ID、目标父级 ID 和当前父级断言；逐项 dry-run 并检查写后回读 |
| 异步新建根分组 | [`rabetbase menu regroup-start`](references/rabetbase-menu-regroup-start.md) | `write`；只接收精确非 folder 叶子 ID；返回 taskId，非幂等请求不自动重提 |
| 查询通用异步任务 | [`rabetbase task status`](references/rabetbase-task-status.md) | 按 taskId + appCode 查询 `PENDING / PROCESSING / SUCCESS / FAILED`；只读，不重启业务操作 |
| 查找数据集 | [`rabetbase dataset list --name "xxx"`](references/rabetbase-dataset-list.md) | 默认返回支持的 `DB_TABLE` 和 `METADATA` 数据集；查指定来源用 `--source DB_TABLE` / `--source METADATA`；也可 `--code` 精确查 |
| 查看表结构和字段 | [`rabetbase dataset detail --code xxx`](references/rabetbase-dataset-detail.md) | 含字段定义和操作列表 |
| 废弃数据集 | [`rabetbase dataset delete`](references/rabetbase-dataset-delete.md) | high-risk-write；默认非级联，显式 `--cascade --confirm` 才删除关联页；必须先 `--dry-run`，批量推荐 `--expected-count` |
| 恢复已删除数据集 | [`rabetbase dataset restore`](references/rabetbase-dataset-restore.md) | high-risk-write；按唯一回收站日志只恢复 Dataset，页面用 `page restore` 明确恢复；必须先 `--dry-run` |
| 查询用户明确删除的字段 | [`rabetbase dataset user-deleted-field-list`](references/rabetbase-dataset-user-deleted-field-list.md) | read；只返回用户删除墓碑字段的安全投影，空列表正常成功 |
| 恢复一个用户删除字段 | [`rabetbase dataset field-restore`](references/rabetbase-dataset-field-restore.md) | write；先精确查询再 dry-run；只提交一个 column ID，并以恢复数量和双重回读确认；不自动同步页面 |
| 修改 Dataset 展示名 | [`rabetbase dataset rename`](references/rabetbase-dataset-rename.md) | 只更新 Dataset 展示名；必须先 `--dry-run`，用 `--expect-name` 防漂移；连续重命名先读对应章节 |
| 从文本生成新 METADATA 数据集 | [`rabetbase dataset generate-start`](references/rabetbase-dataset-generate.md) / [`generate-status`](references/rabetbase-dataset-generate.md) | 三步：preview；审阅后提交；随后执行 `data.query.command`，优先按同一个 taskId 查询。`PENDING/PROCESSING` 非终态，未知或响应丢失不得自动重提；只在返回 `createdDataset.code` 后使用 Dataset |
| 安全更新 Dataset 原始字段对象 | [`rabetbase dataset field-update`](references/rabetbase-dataset-field-update.md) | 使用 `--code` 定位 Dataset，只允许 patch 已知可变业务配置字段；必须先 `--dry-run`，用 `--expect-json` 防漂移 |
| Dataset 顶层 extend 更新命令 | [`rabetbase dataset extend-update`](references/rabetbase-dataset-extend-update.md) | 当前无可写字段；不得用于 `businessGroup`。业务场景分组只能使用 `rabetbase dataset business-group-update` |
| 发现已有业务分组 | [`rabetbase dataset business-groups`](references/rabetbase-dataset-business-groups.md) | read；按 `--dbid` 汇总 DB_TABLE Dataset，不含 METADATA；未分组桶统一显示为 `ungrouped` |
| 更新业务场景分组 | [`rabetbase dataset business-group-update`](references/rabetbase-dataset-business-group-update.md) | 使用 `--code` 定位 Dataset；DB_TABLE 与 METADATA 可设置非空分组，METADATA 可用 `ungrouped` 清空；必须先 `--dry-run`，推荐用 `--expect-business-group` 防漂移 |
| 查看 Dataset 操作定义 | [`rabetbase dataset operations --code xxx`](references/rabetbase-dataset-operations.md) | 获取 filter/getOne/create 等参数定义 |
| 查看数据集关联关系 | [`rabetbase dataset relations`](references/rabetbase-dataset-relations.md) | 标准只读入口，输出 `datasetCode + field` 关系事实；支持 `DB_TABLE -> DB_TABLE`、`DB_TABLE -> METADATA`、`METADATA -> METADATA` |
| 审计数据集关联关系 | [`rabetbase dataset relation-audit`](references/rabetbase-dataset-relation-audit.md) | 只读审计关系事实结构错误、风险和人工复核项 |
| 管理单条数据集关联关系 | [`rabetbase dataset relation-create/update/delete`](references/rabetbase-dataset-relation-mutations.md) | 单条关系写入；写入前用 `relations` 确认 `datasetCode + field` 关系事实，DB_TABLE 写入所需表名来自显式参数或物理表事实 |
| 首次生成数据列表页 | [`rabetbase page generate-start --datasetcode <code>`](references/rabetbase-page-generate-start.md) | 提交或复用服务端异步任务 |
| 创建自定义页面 | [`rabetbase page create --page-pattern BLANK --name "客户看板"`](references/rabetbase-page-create.md) | 综合操作页面优先使用 `ONEPAGE`，业务数据可视化使用 `DASHBOARD`，基础页面使用 `BLANK`；模板详情见 [`page-templates.md`](knowledge/custom-page/page-templates.md)，也可通过 `--page-dir` 创建完整页面；先 dry-run |
| 查询自定义页面 | [`rabetbase page custom-list`](references/rabetbase-page-custom-list.md) | 返回页面 ID、页面名称、`pageUrl`（查看最新保存内容）和 `editPageUrl`（打开编辑器） |
| 查看自定义页面详情 | [`rabetbase page custom-detail --id <pageId>`](references/rabetbase-page-custom-detail.md) | 查询页面详情，`codeContent` 包含可修改后整体提交的完整页面文件 |
| 更新自定义页面 | [`rabetbase page custom-update --id <pageId> --page-dir <dir>`](references/rabetbase-page-custom-update.md) | 以最新完整页面内容为基线更新，可参考 `BLANK`、`ONEPAGE` 或 `DASHBOARD` 的页面和交互模式；先 dry-run |
| 发布自定义页面 | [`rabetbase page custom-publish --id <pageId>`](references/rabetbase-page-custom-publish.md) | `write`；发布当前保存内容，先 dry-run 并审阅预览 |
| 查询数据列表页生成任务状态 | [`rabetbase page generate-status --datasetcode <code> --operation-id <id>`](references/rabetbase-page-generate-status.md) | 查询 job 状态，支持 `operationId` / `clientOperationId` |
| 查询数据列表页生成任务状态 | [`rabetbase page generate-status --datasetcode <code> --task-id <id>`](references/rabetbase-page-generate-status.md) | 查询 job 状态；taskId 首选，operationId/clientOperationId 兼容。成功后仍读取数据列表页事实，未知状态不得自动重提 |
| 查询数据列表页事实快照 | [`rabetbase page data-list-status --datasetcode <code>`](references/rabetbase-data-list-status.md) | 查询数据列表页四件套、残留页与菜单事实 |
| 审计数据列表页关系绑定 | [`rabetbase page relation-audit --datasetcode <code>`](references/rabetbase-page-relation-binding.md) | 只读检查数据列表页 options 绑定是否匹配 `dataset relations` |
| 同步已有数据列表页 | [`rabetbase page sync --datasetcode <code>`](references/rabetbase-page-sync.md) | 数据集字段变更后同步到关联数据列表页 |
| 拉取数据列表页 schema 到本地 | [`rabetbase page pull --id <pageId>`](references/rabetbase-page-pull.md) | 写入 `.rabetbase/page/<appCode>/`，进入本地编辑工作流 |
| 推送本地数据列表页 schema | [`rabetbase page push --id <pageId>`](references/rabetbase-page-push.md) | 推送后自动回拉 canonical schema 覆盖本地 |
| 恢复已删除页面 | [`rabetbase page restore --id <pageId>`](references/rabetbase-page-restore.md) | 支持 `DATA_LIST|CUSTOM` 自动识别；跨类型同 ID 时显式传 `--page-type` |
| 数据库连接（dblink）/ 测连 / 结构分析 | [`rabetbase db list`](references/rabetbase-db-list.md) 起 | **`id`**、**trace/plan id** 与“终态 + 复跑 diff”完成口径见 [database-connection-workflow.md](guides/database-connection-workflow.md)；各子命令见 `references/rabetbase-db-*.md` |
| 独立部署应用范围补偿同步 | [`rabetbase deployment sync-all`](references/rabetbase-deployment-sync-all.md) | 管理员首次初始化、历史回填或故障恢复时使用；`write`，只提交 appCode；在停止编辑的安静窗口执行，保存 jobId 后查询状态，结果未知时用 `sync-jobs` 恢复任务事实，不自动重提；不是精确镜像 |
| 生成 / 更新 API 客户端代码 | [`rabetbase api pull`](references/rabetbase-api-pull.md) → [`sdk-client-generation.md`](guides/sdk-client-generation.md) | `api pull` 拉 Dataset 事实并刷新 `sdk-config.ts`；已有 `api.ts`/`client.ts` 按 guide 合并更新 |
| 查看生成的 API 模型 | [`rabetbase api list`](references/rabetbase-api-list.md) | 列出已生成的数据模型 |
| 查看现有 SQL | [`rabetbase sql list --name "xxx"`](references/rabetbase-sql-list.md) | 分页，按名称过滤；默认查当前决议到的单个应用 |
| 查看 SQL 详情 | [`rabetbase sql detail --sqlcode xxx`](references/rabetbase-sql-detail.md) | 含完整 SQL 内容和参数定义 |
| 新建本地同步 SQL | [`rabetbase sql create --name xxx --db-id 10001 --mode sql`](references/rabetbase-sql-create.md) | 先在远端创建，再落本地文件与 `sql.lock.json` |
| 查看本地同步状态 | [`rabetbase sql status`](references/rabetbase-sql-status.md) | 检查 `added / modified / missing / unchanged / remoteOnly` |
| 拉取远端 SQL 到本地 | [`rabetbase sql pull`](references/rabetbase-sql-pull.md) | 写入 `.rabetbase/sql/<appCode>/<dbName|db-<id>>/`，含 `@lovrabet` 头注释 |
| 推送本地 SQL 到远端 | [`rabetbase sql push --sqlcode xxx`](references/rabetbase-sql-push.md) | `write`；以 `sql.lock.json` 为基准上传同步目录中的本地文件 |
| 删除 SQL | [`rabetbase sql delete --sqlcode xxx --yes`](references/rabetbase-sql-delete.md) | 删除远端并将本地文件移入 `.rabetbase/sql-trash/` |
| 校验 SQL 内容 | [`rabetbase sql validate --file xxx`](references/rabetbase-sql-validate.md) | 类型检测、危险语句检查、参数提取 |
| 执行 SQL 查询 | [`rabetbase sql exec --sqlcode xxx`](references/rabetbase-sql-exec.md) | 支持 `--params` JSON 参数 |
| 查看现有 Backend Function | [`rabetbase bff list`](references/rabetbase-bff-list.md) | 按类型和名称过滤，支持 `--app` 限定应用 |
| 查看 Backend Function 详情 | [`rabetbase bff detail --id n`](references/rabetbase-bff-detail.md) | 含完整脚本内容 |
| 创建本地 Backend Function | [`rabetbase bff create --type ENDPOINT --name xxx`](references/rabetbase-bff-create.md) | 在 `.rabetbase/bff/<appCode>/...` 下创建脚手架 |
| 查看 Backend Function 本地状态 | [`rabetbase bff status`](references/rabetbase-bff-status.md) | 检查 added / modified / unchanged / remoteOnly |
| 拉取远端 Backend Function | [`rabetbase bff pull`](references/rabetbase-bff-pull.md) | 从远端同步到本地 |
| 推送本地 Backend Function | [`rabetbase bff push`](references/rabetbase-bff-push.md) | `write`；建议先 dry-run，正式执行不要求 `--yes` |
| 删除 Backend Function | [`rabetbase bff delete --yes --target xxx`](references/rabetbase-bff-delete.md) | high-risk-write，删远端并清理本地 |
| 生成 SDK 代码 | [`rabetbase codegen sdk --code xxx`](references/rabetbase-codegen-sdk.md) | 按操作生成 TypeScript |
| 生成 SQL 调用代码 | [`rabetbase codegen sql --sqlcode xxx`](references/rabetbase-codegen-sql.md) | sdk/bff 两种 target |
| 列出已配置应用 | [`rabetbase app list`](references/rabetbase-app-list.md) | 默认合并视图；`--global` / `--project` 限定单层；`items[].named`、`meta` 见 reference |
| 发现平台可访问应用 | `rabetbase app list --remote` | 查询当前登录账号在平台上的应用目录，不修改本地配置 |
| 查询应用人员及角色归属 | [`rabetbase app members-list --appcode <code>`](references/rabetbase-app-members-list.md) | 全量只读；按 userId 去重，角色归属聚合到 `roles[]` |
| 查询租户人员 | [`rabetbase tenant members-list --tenant-code <code>`](references/rabetbase-tenant-members-list.md) | 全量只读；租户必须属于当前账号 |
| 查看 app 服务帮助 | `rabetbase app` | 只显示 `app` 子命令帮助，不等价于 `app list` |
| 绑定当前目录到应用 | [`rabetbase workspace init --appcode <code>`](references/rabetbase-workspace.md) | 首次绑定；单应用自动选中且不写 `defaultApp`；与只处理国家/地区及 Domain 的 `config init` 不同 |
| 切换当前工作目录默认应用 | [`rabetbase workspace use --app <name>`](references/rabetbase-workspace.md) | 持久修改当前目录 defaultApp |
| 登记应用 | [`rabetbase workspace add <name> --appcode <code>`](references/rabetbase-workspace.md) | 单应用不写 default；增加第二个应用时保留原应用为默认；`--global` 写全局 |
| 移除应用 | [`rabetbase workspace remove <name>`](references/rabetbase-workspace.md) | 只移除本地 profile，移除后自动切换 default |
| 临时切换应用执行 | 任何命令加 `--app <name>` 或 `--appcode <code>` | 不修改配置文件 |
| 查看配置文件格式 | [`.rabetbase.json` 配置参考](references/rabetbase-config.md) | 完整字段、优先级、环境变量 |

## 命令分组

> **执行前必做：** 从下表定位到命令后，务必先阅读对应命令的 reference 文档，再调用命令。

| 命令分组 | 说明 |
|----------|------|
| Quick Start | [`init`](references/rabetbase-init.md) |
| Project | [`create`](references/rabetbase-project-create.md) / [`domain-routing-sync`](references/rabetbase-project-domain-routing-sync.md) / [`upgrade`](references/rabetbase-project-upgrade.md) |
| Workspace | [`workspace init` / `workspace use` / `workspace add` / `workspace remove`](references/rabetbase-workspace.md) |
| Run Scripts | [`run`](references/rabetbase-run.md) |
| Authentication | [`auth login`](references/rabetbase-auth-login.md) / [`auth logout`](references/rabetbase-auth-logout.md) |
| User Accounts | [`dingding-sandbox-bind`](references/rabetbase-user-account.md) |
| Self Update | [`update`](references/rabetbase-update.md) |
| Schema | [`schema` / `schema export`](references/rabetbase-schema.md) |
| Diagnostics | [`doctor`](references/rabetbase-doctor.md) |
| Platform Issue | [`report`](references/rabetbase-issue-report.md) |
| File | [`upload` / `query-url`](references/rabetbase-file.md) |
| Configuration | [`config set/get/list/delete`](references/rabetbase-config.md) |
| Runtime App Config Management | [`app-config list/get/set/delete`](references/rabetbase-app-config.md) |
| Instant API Policy | [`instant-api-policy init/current/pull/validate/publish/revisions/revision/rollback`](references/rabetbase-instant-api-policy.md) |
| Company Knowledge Base | [`kb list/detail/search/create/update/delete`](references/rabetbase-kb.md) |
| Agent Conte

…(truncated)
