
Lark Base
- 7 installs
- 60 repo stars
- Updated April 13, 2026
- liangdabiao/lark-workflow-feishu-cli
Helps with ai & agent building tasks.
About
lark-base is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- lark-base
- AI & Agent Building
- AI-coding skill
Lark Base by the numbers
- 7 all-time installs (skills.sh)
- Ranked #12,545 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/liangdabiao/lark-workflow-feishu-cli --skill lark-baseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 7 |
|---|---|
| repo stars | ★ 60 |
| Last updated | April 13, 2026 |
| Repository | liangdabiao/lark-workflow-feishu-cli ↗ |
What it does
Helps with ai & agent building tasks.
Files
base
前置条件: 先阅读 `../lark-shared/SKILL.md`。
执行前必做: 执行任何 base 命令前,必须先阅读对应命令的 reference 文档,再调用命令。命名约定: 仅使用 lark-cli base +... 形式的命令。Agent 快速执行顺序
1. 先判断任务类型
- 临时统计 / 聚合分析 →
+data-query - 要把结果长期显示在表里 → formula 字段
- 用户明确要 lookup,或确实更适合
from/select/where/aggregate→ lookup 字段 - 明细读取 / 导出 →
+record-list / +record-get
2. 先拿结构,再写命令
- 至少先拿当前表结构:
+field-list或+table-get - 跨表场景必须再查目标表的结构
3. formula / lookup 有硬门槛
- 先读对应 guide
- 读完 guide 后,再创建对应字段
4. 写记录前先判断字段可写性
- 只写存储字段
- 系统字段 / formula / lookup 默认只读
Agent 禁止行为
- 不要把
+record-list当聚合分析引擎 - 不要没读 guide 就直接创建 formula / lookup 字段
- 不要凭自然语言猜表名、字段名、公式表达式里的字段引用
- 不要把系统字段、formula 字段、lookup 字段当成
+record-upsert的写入目标 - 不要在 Base 场景改走
lark-cli api GET /open-apis/bitable/v1/... - 不要因为 wiki 解析结果里的
obj_type=bitable就去找bitable.*;在本 CLI 里应继续使用lark-cli base +...
Base 基本心智模型
1. Base 字段分三类
- 存储字段:真实存用户输入的数据,通常适合
+record-upsert写入,例如文本、数字、日期、单选、多选、人员、关联。附件字段例外:对 agent 而言,文件上传必须走+record-upload-attachment。 - 系统字段:平台自动维护,只读,典型包括创建时间、最后更新时间、创建人、修改人、自动编号。
- 计算字段:通过表达式或跨表规则推导,只读,典型包括 公式字段(formula) 和 查找引用字段(lookup)。
2. 写记录前先判断字段类别 — 只有存储字段可直接写;公式 / lookup / 创建时间 / 更新时间 / 创建人 / 修改人 / 自动编号都应视为只读输出字段,不能拿来做 +record-upsert 入参。 3. Base 不只是存表数据,也能内建计算 — 用户提出“统计、比较、排名、文本拼接、日期差、跨表汇总、状态判断”等需求时,不能默认导出数据后手算;要先判断是否应通过 +data-query 或公式字段在 Base 内完成。
分析路径决策
1. 一次性分析 / 临时查询 → 优先 +data-query
- 适合:分组统计、SUM / AVG / COUNT / MAX / MIN、条件筛选后聚合。
- 特征:要的是“这次算出来的结果”,不是把结果沉淀成表内字段。
2. 长期复用的派生指标 / 行级计算结果 → 优先公式字段
- 适合:利润率、是否延期、剩余天数、分档标签、跨表汇总后的派生结果。
- 特征:要把结果长期显示在 Base 里,跟随记录自动更新。
3. 显式要求 Lookup,或确实要按 source/select/where/aggregate 建模 → 用 lookup 字段
- 默认仍优先考虑 formula。lookup 只在用户明确要求、或更符合固定查找配置时使用。
4. 原始记录读取 / 明细导出 → +record-list / +record-get
- 不要把
+record-list当分析引擎;它负责取明细,不负责聚合计算。
公式 / Lookup 专项规则
1. 涉及 formula / lookup 时,先读 guide,再出命令
- formula:`formula-field-guide.md`
- lookup:`lookup-field-guide.md`
2. guide 先于创建命令
- 没读对应 guide 前,不要直接创建 formula / lookup 字段
- 读完 guide 后,再补齐对应 JSON 并创建字段
type=formula必须提供expressiontype=lookup必须提供from / select / where,必要时补aggregate
3. 公式字段优先于 lookup 字段
- 只要用户的诉求是“计算 / 条件判断 / 文本处理 / 日期差 / 跨表聚合 / 跨表筛选后取值”,默认优先尝试 formula。
- 只有用户明确说要 lookup,或配置天然更适合 lookup 四元组时,再走 lookup。
4. 表名 / 字段名必须精确匹配
- 公式、lookup、data-query 中出现的表名 / 字段名,必须来自
+table-list/+table-get/+field-list的真实返回,禁止凭语义猜测改写。
5. 先拿结构再写表达式
- 公式或 lookup 一律先获取相关表结构,再生成表达式 / 配置;不要直接凭用户口述拼字段名。
Workflow 专项规则
1. 执行任何 workflow 命令前,必须先读两份文档:对应的命令文档 + [lark-base-workflow-schema.md](references/lark-base-workflow-schema.md)
+workflow-create→ 先读 lark-base-workflow-create.md + schema+workflow-update→ 先读 lark-base-workflow-update.md + schema+workflow-list→ 先读 lark-base-workflow-list.md + schema+workflow-get→ 先读 lark-base-workflow-get.md + schema+workflow-enable→ 先读 lark-base-workflow-enable.md + schema+workflow-disable→ 先读 lark-base-workflow-disable.md + schema- schema 中定义了所有 StepType 枚举、步骤结构、Trigger/Action/Branch/Loop 的 data 格式、值引用语法等
- 禁止凭自然语言猜测
type值(如把"新增记录"猜成CreateTrigger),必须从 schema 的 StepType 枚举中复制准确的类型名称
2. 创建前确认依赖信息
- 先通过
+table-list/+field-list获取真实的表名、字段名 - 禁止凭自然语言猜测表名/字段名填入 workflow 配置
核心规则
1. 只使用原子命令 — 使用 +table-list / +table-get / +field-create / +record-upsert / +view-set-filter / +record-history-list / +base-get 这类一命令一动作的写法,不使用旧聚合式 +table / +field / +record / +view / +history / +workspace 2. 写记录前先读字段结构 — 先调用 +field-list 获取字段结构,再读 lark-base-shortcut-record-value.md 确认各字段类型的写入值格式 3. 写字段前先看字段属性规范 — 先读 lark-base-shortcut-field-properties.md 确认 +field-create/+field-update 的 JSON 结构 4. 筛选查询按视图能力执行 — 先读 lark-base-view-set-filter.md 和 lark-base-record-list.md,通过 +view-set-filter + +record-list 组合完成筛选读取 5. 对记录进行分析(涉及"最高/最低/总计/平均/排名/比较/数量"等分析意图) — 先读 lark-base-data-query.md,通过 +data-query 进行数据筛选聚合的服务端计算 6. 聚合分析与取数互斥 — 需要分组统计 / SUM / MAX / AVG / COUNT 时,必须使用 +data-query(服务端计算),禁止用 +record-list 拉全量记录再手动计算;反之,+data-query 不返回原始记录,取数场景仍走 +record-list / +record-get 7. 所有 `+xxx-list` 禁止并发调用 — +table-list / +field-list / +record-list / +view-list / +record-history-list / +role-list 只能串行执行 8. 批量上限 500 条/次 — 同一表建议串行写入,并在批次间延迟 0.5–1 秒 9. 统一参数名 — 一律使用 --base-token,不使用旧 --app-token 10. 遇到“公式 / 查找引用 / 派生指标 / 跨表计算”需求,优先走字段方案判断 — 先判断应建 formula / lookup 字段,还是只做一次性 +data-query 11. 公式、lookup、系统字段默认视为只读 — 除 +field-create / +field-update 维护字段定义外,不要把这些字段作为记录写入目标 12. 改名和删除按明确意图执行 — +view-rename 在目标视图和新名称都明确时可直接执行;+record-delete / +field-delete / +table-delete 在用户已经明确要求删除且目标明确时也可直接执行,不需要再补一次确认,并且执行删除命令时要主动补上 --yes;只有目标不明确时才继续追问
问卷 / 表单提示
- 获取问卷列表:使用
+form-list(先拿form-id) - 获取单个问卷:使用
+form-get - 获取表单 / 问卷问题:使用
+form-questions-list - 删除问卷 / 表单问题:使用
+form-questions-delete - 创建 / 更新问题:使用
+form-questions-create / +form-questions-update
意图 → 命令索引
| 意图 | 推荐命令 | 备注 |
|---|---|---|
| 列表 / 获取数据表 | lark-cli base +table-list / +table-get | 原子命令 |
| 创建 / 更新 / 删除数据表 | lark-cli base +table-create / +table-update / +table-delete | 一命令一动作 |
| 列表 / 获取字段 | lark-cli base +field-list / +field-get | 原子命令 |
| 创建 / 更新字段 | lark-cli base +field-create / +field-update | 使用 --json |
| 创建 / 更新公式字段 | lark-cli base +field-create / +field-update | type=formula;先读 formula guide,再创建 / 更新 |
| 创建 / 更新 lookup 字段 | lark-cli base +field-create / +field-update | type=lookup;先读 lookup guide,再创建 / 更新,默认先判断 formula 是否更合适 |
| 列表 / 获取记录 | lark-cli base +record-list / +record-get | 原子命令,如果需要聚合计算,分组统计 推荐走 +data-query |
| 创建 / 更新记录 | lark-cli base +record-upsert | --table-id [--record-id] --json |
| 聚合分析 / 比较排序 / 求最值 / 筛选统计 | lark-cli base +data-query | 不要用 +record-list 拉全量数据再手动计算,需使用 +data-query 走服务端计算 |
| 配置 / 查询视图 | lark-cli base +view-* | list/get/create/delete/get-*/set-*/rename |
| 查看记录历史 | lark-cli base +record-history-list | 按表和记录查询变更历史 |
| 按视图筛选查询 | lark-cli base +view-set-filter + lark-cli base +record-list | 组合调用 |
| 创建 / 获取 / 复制 Base | lark-cli base +base-create / +base-get / +base-copy | 原子命令 |
| 列表 / 获取工作流 | lark-cli base +workflow-list / +workflow-get | 原子命令 |
| 创建 / 更新工作流 | lark-cli base +workflow-create / +workflow-update | 使用 --json,必须阅读 schema |
| 启用 / 停用工作流 | lark-cli base +workflow-enable / +workflow-disable | 一命令一动作 |
| 启用 / 停用高级权限 | lark-cli base +advperm-enable / +advperm-disable | 启用后才能使用自定义角色;停用会使已有角色失效 |
| 列表 / 获取角色 | lark-cli base +role-list / +role-get | 查看角色摘要或完整配置 |
| 创建 / 更新 / 删除角色 | lark-cli base +role-create / +role-update / +role-delete | 管理自定义角色权限 |
| 列表 / 获取表单 | lark-cli base +form-list / +form-get | 原子命令 |
| 创建 / 更新 / 删除表单 | lark-cli base +form-create / +form-update / +form-delete | 一命令一动作 |
| 列表 / 创建 / 更新 / 删除表单问题 | lark-cli base +form-questions-list / +form-questions-create / +form-questions-update / +form-questions-delete | 一命令一动作 |
| 列表 / 获取仪表盘 | lark-cli base +dashboard-list / +dashboard-get | 原子命令 |
| 创建 / 更新 / 删除仪表盘 | lark-cli base +dashboard-create / +dashboard-update / +dashboard-delete | 一命令一动作 |
| 列表 / 获取仪表盘 Block | lark-cli base +dashboard-block-list / +dashboard-block-get | 原子命令 |
| 创建 / 更新 / 删除仪表盘 Block | lark-cli base +dashboard-block-create / +dashboard-block-update / +dashboard-block-delete | 一命令一动作 |
操作注意事项
- Base token 口径统一:统一使用
--base-token - `+xxx-list` 调用纪律:
+table-list / +field-list / +record-list / +view-list / +record-history-list / +role-list / +dashboard-list / +dashboard-block-list / +workflow-list禁止并发调用;批量执行时只能串行 - `+record-list` limit 上限:
--limit最大200。需要更多数据时必须用分页(offset递增)分批拉取,禁止单次传超过200 - 字段可写性先判断:存储字段才可写;公式 / lookup / 系统字段默认只读,写记录时应跳过
- 公式能力要主动想到:用户说“算一下”“生成标签”“判断是否异常”“跨表汇总”“按日期差预警”时,要先判断是否应该建公式字段,而不是只返回手工分析方案
- lookup 不是默认首选:lookup 只在用户明确要求或确实更适合固定查找模型时使用;常规计算、跨表聚合和条件判断优先 formula
- 附件字段:如果用户要“上传附件 / 给记录加文件”,只能走
+record-upload-attachment这条链路(读字段 → 读记录 → 上传素材 → 回写记录) - 人员字段 / 用户字段:调试时注意
user_id_type与执行身份(user / bot)差异 - history 使用方式:
+record-history-list按table-id + record-id查询记录历史,不支持整表历史扫描 - workspace 状态:已接入
+base-create / +base-get / +base-copy - `+base-create / +base-copy` 结果返回规范:创建或复制成功后,回复中必须主动返回新 Base 的标识信息。若返回结果里带可访问链接(如
base.url),要一并返回 - `+base-create / +base-copy` 友好性规则:
--folder-token、--time-zone、复制时的--name都是可选项。用户没有特别要求时,不要为了这些可选参数额外打断;能直接创建/复制就直接执行 - `+base-create / +base-copy` 权限处理(bot 创建):若 Base 由应用身份(bot)创建,创建或复制成功后默认继续使用 bot 身份为当前可用 user(指当前 CLI 中 auth 模块已登录且可用的用户身份)添加
full_access(管理员)权限,并在回复中明确授权结果(成功 / 无可用 user / 授权失败及原因)。若授权未完成,要继续给出后续引导(稍后重试授权或继续用 bot);owner 转移必须单独确认,禁止擅自执行 - dashboard 使用方式:
+dashboard-create创建后返回dashboard_id;Block 的data_config通过 JSON 字符串传入,支持@file.json读取文件 - advperm 使用方式:
+advperm-enable启用高级权限后才能管理角色(+role-*);+advperm-disable是高风险操作,停用后已有自定义角色全部失效;操作用户必须为 Base 管理员;先读 lark-base-advperm-enable.md / lark-base-advperm-disable.md - role 使用方式:
+role-create仅支持custom_role;+role-update采用 Delta Merge(role_name和role_type必须始终提供);+role-delete不可逆且仅支持自定义角色;角色配置支持base_rule_map(Base 级复制/下载)、table_rule_map(表级权限含记录/字段粒度)、dashboard_rule_map(仪表盘权限)、docx_rule_map(文档权限);写角色前先读 role-config.md - 表单 form-id:通过
+form-list获取;+form-create返回的id即form-id,可用于+form-questions-*操作 - workflow 使用方式:在创建或更新 workflow 前,必须仔细阅读 lark-base-workflow-schema.md 了解各触发器和节点组件的结构;同时
+workflow-list返回的不是完整树状结构,若需读取完整结构请使用+workflow-get。 - data-query 使用方式:使用
+data-query前必须先阅读 lark-base-data-query.md 了解 DSL 结构、支持的字段类型、聚合函数和限制条件;DSL 中的field_name必须与表字段名精确匹配,构造前先用+field-list获取真实字段名 - 公式 / lookup 使用方式:构造表达式或 where 条件前,至少先拿当前表结构;跨表时要查找目标表的结构,不允许凭自然语言猜字段名
- 视图重命名确认规则:用户已经明确“把哪个视图改成什么名字”时,
+view-rename直接执行即可,不需要再补一句确认 - 删除确认规则(记录 / 字段 / 表):如果用户已经明确说要删除,并且目标也明确,
+record-delete / +field-delete / +table-delete可直接执行,不需要再补一次确认;执行时直接带--yes通过 CLI 的高风险写入校验。只有目标仍有歧义时,再先用+record-get / +field-get / +table-get或 list 命令确认
Wiki 链接特殊处理(特别关键!)
知识库链接(/wiki/TOKEN)背后可能是云文档、电子表格、多维表格等不同类型的文档。不能直接假设 URL 中的 token 就是 file_token,必须先查询实际类型和真实 token。
处理流程
1. 使用 `wiki.spaces.get_node` 查询节点信息
lark-cli wiki spaces get_node --params '{"token":"<wiki_token>"}'2. 从返回结果中提取关键信息
node.obj_type:文档类型(docx/doc/sheet/bitable/slides/file/mindnote)node.obj_token:真实的文档 token(用于后续操作)node.title:文档标题
3. 根据 `obj_type` 选择后续命令
| obj_type | 说明 | 后续命令 |
|---|---|---|
docx | 新版云文档 | drive file.comments.*、docx.* |
doc | 旧版云文档 | drive file.comments.* |
sheet | 电子表格 | sheets.* |
bitable | 多维表格 | lark-cli base +...(优先);如果 shortcut 不覆盖,再用 lark-cli base <resource> <method>;不要改走 lark-cli api /open-apis/bitable/v1/... |
slides | 幻灯片 | drive.* |
file | 文件 | drive.* |
mindnote | 思维导图 | drive.* |
4. 把 wiki 解析出的 `obj_token` 当成 Base token 使用
- 当
obj_type=bitable时,node.obj_token就是后续base命令应使用的真实 token。 - 也就是说:如果原始输入是
/wiki/...链接,不要把wiki_token直接塞给--base-token。
5. 如果已经报了 token 错,再回退检查 wiki
- 如果命令返回
param baseToken is invalid、base_token invalid、not found,并且用户最初给的是/wiki/...链接或wiki_token,优先怀疑“把 wiki token 当成了 base token”。 - 这时不要改走
bitable/v1API;应立即重新执行lark-cli wiki spaces get_node,确认obj_type=bitable后,改用node.obj_token重新执行lark-cli base +...。
查询示例
# 查询 wiki 节点
lark-cli wiki spaces get_node --params '{"token":"Pgrr***************UnRb"}'返回结果示例:
{
"node": {
"obj_type": "docx",
"obj_token": "UAJ***************E9nic",
"title": "ai friendly 测试 - 1 副本",
"node_type": "origin",
"space_id": "6946843325487906839"
}
}Base 链接解析规则
| 链接类型 | 格式 | 处理方式 |
|---|---|---|
| 直接 Base 链接 | /base/{token} | 直接提取作为 --base-token |
| Wiki 知识库链接 | /wiki/{token} | 先调用 wiki.spaces.get_node,取 node.obj_token |
URL 参数提取
https://{domain}/base/{base-token}?table={table-id}&view={view-id}/base/{token}→--base-token?table={id}→--table-id?view={id}→--view-id
禁止事项
- 禁止将完整 URL 直接作为
--base-token参数传入 - 禁止将 wiki_token 直接作为
--base-token
常见错误速查
| 错误码 | 含义 | 解决方案 |
|---|---|---|
| 1254064 | 日期格式错误 | 用毫秒时间戳,非字符串 / 秒级 |
| 1254068 | 超链接格式错误 | 用 {text, link} 对象 |
| 1254066 | 人员字段错误 | 用 [{id:"ou_xxx"}],并确认 user_id_type |
| 1254045 | 字段名不存在 | 检查字段名(含空格、大小写) |
| 1254015 | 字段值类型不匹配 | 先 +field-list,再按类型构造 |
param baseToken is invalid / base_token invalid | 把 wiki token、workspace token 或其他 token 当成了 base_token | 如果输入来自 /wiki/...,先用 lark-cli wiki spaces get_node 取真实 obj_token;当 obj_type=bitable 时,用 node.obj_token 作为 --base-token 重试,不要改走 bitable/v1 |
| formula / lookup 创建失败 | 指南未读或结构不合法 | 先读 formula-field-guide.md / lookup-field-guide.md,再按 guide 重建请求 |
| 系统字段 / 公式字段写入失败 | 只读字段被当成可写字段 | 改为写存储字段,计算结果交给 formula / lookup / 系统字段自动产出 |
| 1254104 | 批量超 500 条 | 分批调用 |
| 1254291 | 并发写冲突 | 串行写入 + 批次间延迟 |
参考文档
- lark-base-shortcut-field-properties.md —
+field-create/+field-updateJSON 规范(推荐) - role-config.md — 角色权限配置详解
- lark-base-shortcut-record-value.md —
+record-upsert值格式规范(推荐) - formula-field-guide.md — formula 字段写法、函数约束、CurrentValue 规则、跨表计算模式(强烈推荐)
- lookup-field-guide.md — lookup 字段配置规则、where/aggregate 约束、与 formula 的取舍
- lark-base-view-set-filter.md — 视图筛选配置
- lark-base-record-list.md — 记录列表读取与分页
- lark-base-advperm-enable.md —
+advperm-enable启用高级权限 - lark-base-advperm-disable.md —
+advperm-disable停用高级权限 - lark-base-role-list.md —
+role-list列出角色 - lark-base-role-get.md —
+role-get获取角色详情 - lark-base-role-create.md —
+role-create创建角色 - lark-base-role-update.md —
+role-update更新角色 - lark-base-role-delete.md —
+role-delete删除角色 - lark-base-dashboard.md — dashboard 命令索引(每个命令已拆到独立文档)
- lark-base-dashboard-block.md — dashboard block 命令索引(每个命令已拆到独立文档)
- dashboard-block-data-config.md — Block data_config 结构、图表类型、filter 规则
- lark-base-workflow.md — workflow 命令索引
- lark-base-workflow-schema.md —
+workflow-create/+workflow-updateJSON body 数据结构详解,包含触发器及各类节点的配置规则(强烈推荐) - lark-base-data-query.md —
+data-query聚合分析(DSL 结构、支持字段类型、聚合函数) - examples.md — 完整操作示例(建表、导入、筛选、更新)
命令分组
执行前必做: 从下表定位到命令后,务必先阅读对应命令的 reference 文档,再调用命令。
| 命令分组 | 说明 |
|---|---|
| `table commands` | +table-list / +table-get / +table-create / +table-update / +table-delete |
| `field commands` | +field-list / +field-get / +field-create / +field-update / +field-delete / +field-search-options |
| `record commands` | +record-list / +record-get / +record-upsert / +record-upload-attachment / +record-delete |
| `view commands` | +view-list / +view-get / +view-create / +view-delete / +view-get-* / +view-set-* / +view-rename |
| `data-query commands` | +data-query |
| `history commands` | +record-history-list |
| `base / workspace commands` | +base-create / +base-get / +base-copy |
| `advperm commands` | +advperm-enable / +advperm-disable |
| `role commands` | +role-list / +role-get / +role-create / +role-update / +role-delete |
| `form commands` | +form-list / +form-get / +form-create / +form-update / +form-delete |
| `form questions commands` | +form-questions-list / +form-questions-create / +form-questions-update / +form-questions-delete |
| `workflow commands` | +workflow-list / +workflow-get / +workflow-create / +workflow-update / +workflow-enable / +workflow-disable |
| `dashboard commands` | +dashboard-list / +dashboard-get / +dashboard-create / +dashboard-update / +dashboard-delete |
| `dashboard block commands` | +dashboard-block-list / +dashboard-block-get / +dashboard-block-create / +dashboard-block-update / +dashboard-block-delete |
dashboard block data_config 参考
Block 的 data_config 字段因 type 不同而变化。本文档描述所有共享结构。
支持的组件类型(type 枚举)
| type 值 | 说明 |
|---|---|
column | 柱状图 |
bar | 条形图 |
line | 折线图 |
pie | 饼图 |
ring | 环形图 |
area | 面积图 |
combo | 组合图 |
scatter | 散点图 |
funnel | 漏斗图 |
wordCloud | 词云 |
radar | 雷达图 |
statistics | 指标卡 |
data_config 通用结构
| 字段 | 类型 | 说明 |
|---|---|---|
table_name | string | 关联数据表名称 |
series | [{ "field_name": "xxx", "rollup": "SUM" }] | 指标/Y 轴(与 count_all 二选一)。rollup 支持 SUM / MAX / MIN / AVERAGE |
count_all | boolean | COUNTA 聚合,统计所有记录数(与 series 二选一) |
group_by | [{ "field_name": "xxx", "mode": "integrated" }] | X 轴分组维度 |
filter | object | 筛选条件 |
filter.conjunction | "and" / "or" | 筛选逻辑 |
filter.conditions | [{ "field_name", "operator", "value" }] | 筛选条件数组,value 类型因字段类型而异(见下方 filter 格式规则) |
filter 格式规则
基本结构:
{
"filter": {
"conjunction": "and",
"conditions": [
{ "field_name": "字段名", "operator": "操作符", "value": "值" }
]
}
}操作符:
| 操作符 | 含义 | 是否需要 value |
|---|---|---|
is | 等于 | 是 |
isNot | 不等于 | 是 |
contains | 包含 | 是 |
doesNotContain | 不包含 | 是 |
isEmpty | 为空 | 否 |
isNotEmpty | 不为空 | 否 |
isGreater | 大于 | 是 |
isGreaterEqual | 大于等于 | 是 |
isLess | 小于 | 是 |
isLessEqual | 小于等于 | 是 |
各字段类型的 value 格式:
| 字段类型 | value 类型 | 适用操作符 | 示例 |
|---|---|---|---|
| 文本 / 电话 / URL | string | is, isNot, contains, doesNotContain, isEmpty, isNotEmpty | {"field_name":"姓名","operator":"contains","value":"张"} |
| 数字 | number | is, isNot, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty | {"field_name":"金额","operator":"isGreater","value":0} |
| 单选 | string(选项名) | is, isNot, isEmpty, isNotEmpty | {"field_name":"状态","operator":"is","value":"已完成"} |
| 多选 | string 或 string[] | is, isNot, contains, doesNotContain, isEmpty, isNotEmpty | {"field_name":"标签","operator":"contains","value":["紧急","重要"]} |
| 日期时间 / 创建时间 / 修改时间 | number(毫秒时间戳) | is, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty | {"field_name":"创建日期","operator":"isGreater","value":1711209600000} |
| 复选框 | boolean | is | {"field_name":"已审核","operator":"is","value":true} |
| 人员 / 创建人 / 修改人 | string 或 string[](用户 ID) | is, isNot, isEmpty, isNotEmpty | {"field_name":"负责人","operator":"is","value":"user_id_xxx"} |
| 所有类型(为空/不为空) | 不需要 value | isEmpty, isNotEmpty | {"field_name":"备注","operator":"isEmpty"} |
value类型为string | number | boolean | string[],需根据字段类型匹配正确格式
约束与本地校验
- 必填与互斥
- 必填:
table_name - 互斥:
series与count_all二选一,且至少提供其一 - 长度/结构
group_by最多 2 个;每项field_name必填group_by[].sort.type取值group|value|view;order取值asc|desc- 规范化(CLI 自动处理)
series[].rollup自动转成大写(如sum→SUM)group_by[].sort.type/order自动转成小写- 本地校验(可通过
--no-validate跳过) +dashboard-block-create/update默认对data_config做轻量校验;失败会聚合错误并给出修复建议- 仅需传入合法 JSON;CLI 不会擅自改写你的业务含义
可复制模板
最小柱状图:
{
"table_name": "表名",
"series": [{ "field_name": "数值字段", "rollup": "SUM" }],
"group_by": [{ "field_name": "分组字段", "mode": "integrated" }]
}最小饼/环图(按分类计数):
{
"table_name": "表名",
"count_all": true,
"group_by": [{ "field_name": "分类字段", "mode": "integrated" }]
}折线图(按月趋势):
{
"table_name": "表名",
"series": [{ "field_name": "金额", "rollup": "SUM" }],
"group_by": [{ "field_name": "月份", "mode": "integrated", "sort": {"type":"group","order":"asc"} }]
}常见错误与修复
- 同时存在
series与count_all - 现象:后端/本地校验报互斥错误
- 修复:仅保留其一;统计字段用
series,统计条数用count_all:true - 缺少
table_name - 现象:本地校验缺少必填字段
- 修复:指定数据源表名(使用表名,非表 ID)
series[].rollup大小写/取值不合法- 现象:本地校验提示枚举不支持
- 修复:改为
SUM|MAX|MIN|AVERAGE中之一(不区分大小写,CLI 会统一为大写;计数请使用count_all:true) group_by超出 2 个或字段名为空- 修复:保留前 2 个,或补齐
field_name - 排序枚举不合法
- 修复:
group_by.sort.type仅能为group|value|view;order为asc|desc - filter 写法不规范
- 修复:
conjunction取and|or;conditions[].operator必须在本页表格列举的范围内;除isEmpty/isNotEmpty外需提供value
指标卡(statistics)data_config 示例
统计数字字段求和:
{
"table_name": "数据表",
"series": [{ "field_name": "数字", "rollup": "SUM" }]
}统计记录行数:
{
"table_name": "数据表",
"count_all": true
}series与count_all二选一,不能同时使用。
坑点
- `count_all` 与 `series` 二选一 — 两者不能同时使用
- filter `value` 类型因字段而异 — 文本/单选为 string,数字为 number,日期为毫秒时间戳,多选/人员可为 string[],复选框为 boolean;
isEmpty/isNotEmpty不需要 value - `data_config` 结构随 `type` 变化 — 不同组件类型的字段不同,创建前务必确认类型对应的字段
飞书多维表格使用场景完整示例(base)
本文档提供基于 lark-cli base ... 的完整示例,覆盖 unified Shortcut 与当前 base/v3 原生 API 的常见组合方式。
返回: SKILL.md | 参考: shortcut 字段 JSON 规范 · shortcut 记录值规范
---
场景 1:用 unified Shortcut 快速建表
适合已经明确字段结构、希望一次性完成建表的场景。
lark-cli base +table-create \
--base-token bascnXXXXXXXX \
--name "客户管理表" \
--fields '[
{"name":"客户名称","type":"text"},
{"name":"负责人","type":"user","property":{"multiple":false}},
{"name":"签约日期","type":"datetime"},
{"name":"状态","type":"single_select","property":{"options":["进行中","已完成"]}}
]'---
场景 2:使用原生 API 创建数据表并查看字段
适合需要精确观察 base/v3 请求参数和响应结构的场景。原生 API 直接使用 base service。
步骤 1:在已有 Base 中创建数据表
lark-cli base tables create \
--params '{"base_token":"bascnXXXXXXXX"}' \
--data '{"name":"客户管理表"}'步骤 2:列出字段
lark-cli base table.fields list \
--params '{"base_token":"bascnXXXXXXXX","table_id":"tblXXXXXXXX","limit":100}'提示:当前base/v3不再使用旧的app_token/app.table.*路径,统一改为base_token+tables/table.fields/table.records。
---
场景 3:创建、读取、更新单条记录
新增记录
lark-cli base table.records create \
--params '{"base_token":"bascnXXXXXXXX","table_id":"tblXXXXXXXX"}' \
--data '{
"客户名称":"字节跳动",
"负责人":[{"id":"ou_xxx"}],
"状态":"进行中"
}'列出记录
lark-cli base table.records list \
--params '{"base_token":"bascnXXXXXXXX","table_id":"tblXXXXXXXX","limit":100}'更新记录
lark-cli base table.records patch \
--params '{"base_token":"bascnXXXXXXXX","table_id":"tblXXXXXXXX","record_id":"recXXXXXXXX"}' \
--data '{
"状态":"已完成"
}'删除记录
lark-cli base table.records delete \
--params '{"base_token":"bascnXXXXXXXX","table_id":"tblXXXXXXXX","record_id":"recXXXXXXXX"}'---
场景 4:配置视图筛选后按视图读取记录
当前 base/v3 原生 spec 没有独立 search 方法。需要筛选查询时,推荐先写视图筛选,再通过 view_id 读取记录。
更新视图筛选条件
lark-cli base view.filter update \
--params '{"base_token":"bascnXXXXXXXX","table_id":"tblXXXXXXXX","view_id":"vewXXXXXXXX"}' \
--data '{
"logic":"and",
"conditions":[
{
"field_name":"状态",
"operator":"is",
"value":["进行中"]
}
]
}'按视图读取记录
lark-cli base table.records list \
--params '{"base_token":"bascnXXXXXXXX","table_id":"tblXXXXXXXX","view_id":"vewXXXXXXXX","limit":100}'---
场景 5:什么时候优先用 Shortcut
- 需要一次性建表并附带字段、视图时,优先
lark-cli base +table-create - 需要按业务字段名做 upsert 时,优先
lark-cli base +record-upsert - 需要配置筛选视图时,优先
lark-cli base +view-set-filter - 需要记录历史时,优先
lark-cli base +record-history-list
原生 API 更适合两类场景:
- 需要逐步核对
schema base.<resource>.<method>的请求参数 - 需要精确控制单次表 / 字段 / 记录 / 视图操作
Bitable Formula Writing Guide
Mandatory Read Acknowledgement
When creating or updating a formula field with lark-cli base +field-create/+field-update --json ... and type is formula, you should read this guide first and only then add --i-have-read-guide to the command.
Do not proactively add --i-have-read-guide before reading this guide. Without it, the CLI will fail fast and direct you back to this guide.
Default strategy
All cross-table references, aggregations, and computed fields should use Formula fields by default. Do NOT use Lookup fields unless the user explicitly requests it. Formula is a strict superset of Lookup — anything Lookup can do, Formula can do with a single expression.
Usage
When creating a formula field, the Agent should:
1. Get all table names: lark-cli base +table-list --base-token <base> — returns items[].table_name 2. Get table structure: lark-cli base +table-get --base-token <base> --table-id <table> — returns fields[] 3. If the formula references other tables, also get those tables' structures 4. Write the formula expression following this guide 5. Construct the Formula field JSON and submit it to create or update the field
Key constraints:
- The JSON must include
"type": "formula"— this field is required - Table names and field names in the formula must exactly match those returned by
+table-list/+table-get - The
expressionvalue is a string containing the formula expression; double quotes inside the expression must be properly escaped in JSON (e.g.\"text\")
---
Section 1: Core Concepts — Scalar vs List
This is the foundation of formula logic. You must determine this before writing any formula.
| Syntax | Meaning | Return type | Example |
|---|---|---|---|
[Field] | Value of this field in the current row | Scalar (single value) | [Name] → "Alice" |
[TableName].[Field] | All values of this field in the target table | List (multiple values) | [Employees].[Name] → ["Alice","Bob",...] |
[TableName] | The target table (entire table) | Table reference | Used as data range for FILTER/COUNTIF etc. |
Rules:
- Scalars can be used directly in operations:
[Price] * [Quantity] - Lists cannot be used as scalars — they must be processed first: use
SUM()for sum,ARRAYJOIN(",")for joining,FIRST()/LAST()/NTH()for single value extraction - Link field access
[LinkField].[TargetField]returns a list (values of the target field for all linked records) - LISTCOMBINE flattening rule: When a FILTER's result column is itself a multi-value field (MultiSelect, Link, etc.), it produces a 2D array and must be flattened with
.LISTCOMBINE(); for single-value fields (Number, Text, etc.) it can be omitted, but adding it is never wrong:
[Table].FILTER(CurrentValue.[Field] = [Value]).[MultiSelectCol].LISTCOMBINE() ← required for multi-value columns
[Table].FILTER(CurrentValue.[Field] = [Value]).[NumberCol].LISTCOMBINE() ← optional for single-value columns---
Section 2: Data Types and Type Conversion
Field storage types
| Type | Description | Supported operations |
|---|---|---|
| Number | Stored as numeric value | Math operations, comparisons, auto-converts to string for concatenation |
| Text | Stored as string | String operations; can participate in math if content is numeric, otherwise errors |
| Date | Date object | Date functions, add/subtract with numbers; auto-converts to default format string when using & — use TEXT to format first for controlled output |
| MultiSelect | Data list | List functions, CONTAIN checks |
| Link | Links to other table records | Chained access [LinkField].[Field], result is a list |
| Boolean | TRUE/FALSE | Logical operations; auto-converts to number when compared with numbers |
Implicit type conversion
| Scenario | Conversion rule |
|---|---|
| Number + Float | → Float |
| Date + Number | → Date (adds/subtracts days). Use +/- for whole days, use DURATION() for hour/minute/second precision |
| Date - Date | → Duration |
| Boolean compared with Number | Boolean auto-converts to number (TRUE=1, FALSE=0) |
& concatenation | Both sides auto-convert to string |
Type consistency in comparisons
When using comparison operators (>, >=, <, <=, =, !=), both sides should be the same type to avoid semantic errors or unexpected results.
Principle: When types differ, explicitly convert one side rather than relying on implicit conversion:
- Number vs Text → use
VALUE()to convert text to number - Date vs Text → use
TEXT()to convert date to text - Date vs Date equality → Dates include time components, so direct
=comparison may fail due to different hours/minutes/seconds. For day-level equality, convert to text first:TEXT([DateA], "YYYY/MM/DD") = TEXT([DateB], "YYYY/MM/DD") - Select and User fields can be compared with both same-type values and text
- Text fields in numeric aggregation (SUM/AVERAGE/MIN/MAX etc.) → convert to number with
VALUE()first. For FILTER results, use.MAP(VALUE(CurrentValue)).SUM()
---
Section 3: CurrentValue
CurrentValue is the iteration variable in FILTER/MAP/COUNTIF/SUMIF functions, representing the "current item" being processed in the data range.
CurrentValue meaning in different contexts
| Data range type | CurrentValue represents | Access pattern | Example |
|---|---|---|---|
Entire table [TableName] | A row in the table | CurrentValue.[FieldName] | [Orders].FILTER(CurrentValue.[Amount] > 100).[Customer] |
Column [TableName].[Field] | A single field value | Use CurrentValue directly | [Orders].[Amount].FILTER(CurrentValue > 100) |
MultiSelect field [Tags] | One option | Use CurrentValue directly | [Tags].FILTER(CurrentValue = "Important") |
| LIST-generated list | One element | Use CurrentValue directly | LIST(1,2,3).MAP(CurrentValue * 2) |
Key rules
1. When data range is a table, use CurrentValue.[FieldName] to access row fields 2. When data range is a column/list, use CurrentValue directly for the element value — cannot use CurrentValue.[FieldName] 3. CurrentValue can only appear inside the condition/mapping parameters of FILTER/MAP/COUNTIF/SUMIF functions 4. To reference the current table's field value in a condition, write [FieldName] directly — it refers to the formula row's value, not a property of CurrentValue
Anti-patterns
| Wrong | Reason | Correct |
|---|---|---|
[Table].[Col].FILTER(CurrentValue.[Col] > 0) | Data range is a column; CurrentValue is a scalar, cannot use . to access fields | [Table].[Col].FILTER(CurrentValue > 0) |
[Table].FILTER(CurrentValue > 100) | Data range is a table; CurrentValue is a row, cannot compare directly | [Table].FILTER(CurrentValue.[Amount] > 100).[Amount] |
CurrentValue + 1 (at top level) | CurrentValue can only be used inside iteration functions | Use inside MAP/FILTER etc. |
---
Section 4: Operators
Bitable formulas only allow the following operators. like, in, <>, **, ^ etc. are prohibited.
| Category | Operators | Description |
|---|---|---|
| Arithmetic | + - * / % | Add, subtract, multiply, divide, modulo (% is equivalent to MOD()) |
| Comparison | > >= < <= = != | Greater than, greater or equal, less than, less or equal, equal, not equal |
| Logical | && `\ | \ |
| Concatenation | & | Text concatenation; non-text values auto-convert to string |
Important:
- Equality uses
=(single equals), not== - Not-equal uses
!=, not<> - String concatenation uses
&, not+ - Both
&&/||and AND()/OR() functions are supported
---
Section 5: Link Fields and Cross-Table References
Link field description
When a field type is described as FieldName: Link [target table: X, foreign key: Y], it links to target table X using field Y as the join key.
Chained cross-table access
[LinkField].[TargetField]Retrieves the target field values for all linked records as a list. Supports continued chaining: [LinkA].[LinkB].[Field].
Equivalent expanded form
- Multi-value link:
[TargetTableX].FILTER([LinkField].CONTAIN(CurrentValue.[Y])).[TargetField].LISTCOMBINE() - Single-value link:
[TargetTableX].FILTER(CurrentValue.[Y] = [LinkField]).[TargetField].LISTCOMBINE()
(.LISTCOMBINE() is required when [TargetField] is a multi-value field; optional for single-value fields)
Notes
- Link fields typically return lists (possibly empty)
- To output a single value, use aggregation (SUM/MAX), joining (ARRAYJOIN), or extraction (FIRST/LAST/NTH)
- Do not nest FILTER inside FILTER for cross-table queries — prefer link field chained access
---
Section 6: Function Call Conventions
Two calling styles
| Style | Format | Description |
|---|---|---|
| Functional | FUNC(arg1, arg2) | Works for all functions |
| Chained | arg1.FUNC(arg2) | Moves the first argument before . |
Rules:
- Zero-argument functions cannot be chained:
NOW(),TODAY(),PI(),TRUE(),FALSE() - SORTBY can only be chained:
[Table].SORTBY([Table].[SortCol]).[OutputCol]. The sort column always uses the original table's column name ([TableName].[Field]format); the engine aligns rows internally, even when the data range is a FILTER result - FILTER is recommended to be chained:
[Table].FILTER(condition).[OutputCol]
FILTER / SORTBY result column rules
- When data range is a table
[TableName], FILTER / SORTBY returns a table reference. The chain must end with.[Field]to specify the result column, otherwise the formula fails:
Correct: [Sales].FILTER(CurrentValue.[Amount] > 100).[Customer]
Correct: [Sales].FILTER(condition).SORTBY([Sales].[SortCol]).[Customer] ← result column at end of chain
Wrong: [Sales].FILTER(CurrentValue.[Amount] > 100) ← missing result column- When data range is a column
[TableName].[Field]or a list, FILTER returns the filtered list directly — no result column needed:
Correct: [Sales].[Amount].FILTER(CurrentValue > 100)After the result column, it's recommended to flatten with .LISTCOMBINE() first (especially when the result column is a multi-value field), then chain aggregation functions:
[Sales].FILTER(CurrentValue.[Amount] > 100).[Amount].LISTCOMBINE().SUM()---
Section 7: Hard Constraints
1. Nesting prohibition: FILTER / SUMIF / COUNTIF / MAP must not be nested inside each other's condition/mapping expressions. None of these functions can appear inside the condition or mapping parameter of another.
- Prohibited:
[Table1].FILTER(CurrentValue.[Col] = [Table2].FILTER(...).[Col])← FILTER inside FILTER condition - Prohibited:
[Table].MAP([Table2].MAP(...))← MAP inside MAP mapping - Allowed:
[Table].FILTER(cond1).[Col].FILTER(cond2)← chained call; the first FILTER's output is the second's data range, not nesting
2. Function whitelist: Only use functions listed in Section 8. No unlisted functions.
3. Exact name matching: Table names and field names in formulas must exactly match those returned by +table-get — no renaming or adding spaces.
4. Operator whitelist: Only use operators listed in Section 4.
5. Strings use double quotes: Strings must be wrapped in double quotes ", single quotes are not supported.
6. Do not use LOOKUP: FILTER is a superset of LOOKUP. All LOOKUP formulas can be rewritten with FILTER. Use FILTER exclusively to reduce complexity.
---
Section 8: Complete Function Reference
8.1 Logic functions
| Function | Signature | Return type | Description |
|---|---|---|---|
| IF | IF(condition, true_val, [false_val]) | Matches branch type | Returns true_val when TRUE, false_val otherwise; omitting false_val returns false (not null) |
| IFS | IFS(cond1, val1, cond2, val2, ...) | Matches branch type | Multi-condition branching; returns value for the first TRUE condition |
| SWITCH | SWITCH(expr, match1, result1, [match2, result2, ...], [default]) | Matches branch type | Matches expression value and returns corresponding result |
| IFERROR | IFERROR(expr, fallback) | Matches branch type | Returns fallback when expression errors |
| IFBLANK | IFBLANK(expr, fallback) | Matches branch type | Returns fallback when expression is blank (blank = NULL/empty string/empty list) |
| AND | AND(cond1, cond2, ...) | Boolean | TRUE when all conditions are TRUE |
| OR | OR(cond1, cond2, ...) | Boolean | TRUE when any condition is TRUE |
| NOT | NOT(condition) | Boolean | Logical negation |
| ISBLANK | ISBLANK(value) | Boolean | Tests if blank (NULL/empty string/empty list are blank; 0 and FALSE are not) |
| ISNULL | ISNULL(value) | Boolean | Tests if NULL (only NULL is true; empty string is not) |
| ISERROR | ISERROR(expr) | Boolean | Tests if expression errors |
| ISNUMBER | ISNUMBER(value) | Boolean | Tests if value is a number |
| CONTAIN | CONTAIN(search_range, value, ...) | Boolean | Tests if list/MultiSelect contains the value; does NOT do text substring matching |
| CONTAINSALL | CONTAINSALL(search_range, value, ...) | Boolean | Tests if list/MultiSelect contains all specified values |
| CONTAINSONLY | CONTAINSONLY(search_range, value, ...) | Boolean | Tests if list/MultiSelect contains only the specified values |
| TRUE | TRUE() | Boolean | Returns TRUE |
| FALSE | FALSE() | Boolean | Returns FALSE |
| RECORD_ID | RECORD_ID() | Text | Returns the current row's record ID |
| RANDOMBETWEEN | RANDOMBETWEEN(min_int, max_int, [keep_updating]) | Number | Random integer in the specified range |
| RANDOMITEM | RANDOMITEM(list, [keep_updating]) | Matches element type | Randomly picks one element from a list |
8.2 Numeric functions
| Function | Signature | Return type | Description |
|---|---|---|---|
| SUM | SUM(val1, val2, ...) | Number | Sum; accepts multiple values or a list |
| AVERAGE | AVERAGE(val1, val2, ...) | Number | Average |
| MAX | MAX(val1, val2, ...) | Number | Maximum |
| MIN | MIN(val1, val2, ...) | Number | Minimum |
| MEDIAN | MEDIAN(val1, val2, ...) | Number | Median |
| COUNTA | COUNTA(val1, val2, ...) | Number | Count of non-blank values |
| COUNTIF | COUNTIF(data_range, condition) | Number | Count matching items. Data range can be a table (CurrentValue is a row, use CurrentValue.[Field]) or a column (CurrentValue is a scalar value) |
| SUMIF | SUMIF(data_range, condition) | Number | Sum matching values. Data range must be a numeric column (e.g. [Table].[NumField]); CurrentValue is each value in that column (scalar), cannot use CurrentValue.[Field] to access other fields. For cross-field conditions, use FILTER+SUM instead |
| ROUND | ROUND(number, digits) | Number | Round. digits: 1=one decimal, 0=integer, -1=tens place |
| ROUNDUP | ROUNDUP(number, digits) | Number | Round away from zero. Same digits semantics as ROUND |
| ROUNDDOWN | ROUNDDOWN(number, digits) | Number | Round toward zero. Same digits semantics as ROUND |
| FLOOR | FLOOR(number, [base]) | Number | Round down to nearest multiple of base (default 1) |
| CEILING | CEILING(number, [base]) | Number | Round up to nearest multiple of base (default 1) |
| ABS | ABS(number) | Number | Absolute value |
| INT | INT(number) | Integer | Truncate to integer |
| MOD | MOD(dividend, divisor) | Number | Modulo |
| POWER | POWER(base, exponent) | Number | Exponentiation |
| QUOTIENT | QUOTIENT(dividend, divisor) | Number | Integer division |
| VALUE | VALUE(text) | Number | Convert text to number |
| ISODD | ISODD(number) | Boolean | Tests if number is odd |
| RANK | RANK(value, search_range, [ascending]) | Number | Rank of value in range; default descending |
| SEQUENCE | SEQUENCE(start, end, [step]) | List | Generate number sequence |
| PI | PI() | Number | Pi constant |
| SIN/COS/TAN/ASIN/ACOS/ATAN/ATAN2/SINH/COSH/TANH/ASINH/ACOSH/ATANH | func(radians_or_value) | Number | Trigonometric and hyperbolic functions; arguments in radians |
8.3 Text functions
| Function | Signature | Return type | Description |
|---|---|---|---|
| CONCATENATE | CONCATENATE(text1, text2, ...) | Text | Concatenate multiple texts; supports lists as input |
| LEN | LEN(text) | Number | Character count |
| LEFT | LEFT(text, [count]) | Text | Extract from left; default 1 |
| RIGHT | RIGHT(text, [count]) | Text | Extract from right; default 1 |
| MID | MID(text, start, count) | Text | Extract from middle |
| FIND | FIND(search_val, search_range, [start]) | Number | Find substring position (case-sensitive); returns -1 if not found |
| REPLACE | REPLACE(text, start, count, new_text) | Text | Replace by position |
| SUBSTITUTE | SUBSTITUTE(text, old_text, new_text, [occurrence]) | Text | Replace by content; can specify which occurrence |
| UPPER | UPPER(text) | Text | Convert to uppercase |
| LOWER | LOWER(text) | Text | Convert to lowercase |
| TRIM | TRIM(text) | Text | Remove leading/trailing spaces |
| TEXT | TEXT(value, format) | Text | Format output. Date formats: "YYYY-MM-DD", "YYYY/MM/DD hh:mm:ss"; number formats: "00", "000.00" |
| CONTAINTEXT | CONTAINTEXT(text, search_text) | Boolean | Tests if text contains substring (text substring matching) |
| SPLIT | SPLIT(text, delimiter) | List | Split text by delimiter |
| TODATE | TODATE(value) | Date | Convert date string to date type |
| CHAR | CHAR(number) | Text | ASCII code to character |
| FORMAT | FORMAT(template, [val1, val2, ...]) | Text | Template string formatting; use {1}, {2} as placeholders |
| HYPERLINK | HYPERLINK(url, [display_text]) | Hyperlink | Create a hyperlink |
| ENCODEURL | ENCODEURL(text) | Text | URL encode |
| REGEXMATCH | REGEXMATCH(text, regex) | Boolean | Regex match test |
| REGEXEXTRACT | REGEXEXTRACT(text, regex) | List | Extract first match's capture groups |
| REGEXEXTRACTALL | REGEXEXTRACTALL(text, regex) | 2D List | Extract all matches |
| REGEXREPLACE | REGEXREPLACE(text, regex, replacement) | Text | Regex replace |
8.4 Date functions
| Function | Signature | Return type | Description |
|---|---|---|---|
| NOW | NOW() | Date | Current date and time |
| TODAY | TODAY() | Date | Current date (midnight) |
| DATE | DATE(year, month, day) | Date | Construct a date |
| YEAR | YEAR(date) | Number | Extract year |
| MONTH | MONTH(date) | Number | Extract month |
| DAY | DAY(date) | Number | Extract day |
| HOUR | HOUR(date) | Number | Extract hour |
| MINUTE | MINUTE(date) | Number | Extract minute |
| SECOND | SECOND(date) | Number | Extract second |
| WEEKDAY | WEEKDAY(date, [type]) | Number | Day of week |
| WEEKNUM | WEEKNUM(date, [type]) | Number | Week number |
| DAYS | DAYS(end_date, start_date) | Number | Days between two dates (end - start), includes decimals. Note parameter order: end date comes first |
| DATEDIF | DATEDIF(start_date, end_date, [unit]) | Number | Whole days/months/years between dates. Unit: "D"(default)/"M"/"Y". Start must be before end |
| DURATION | DURATION(days, [hours], [minutes], [seconds]) | Duration | Create a duration for date arithmetic |
| EDATE | EDATE(date, months) | Date | Date N months later |
| EOMONTH | EOMONTH(date, [months]) | Date | End of month N months later; months default 0 |
| WORKDAY | WORKDAY(start_date, days, [holidays]) | Date | Date N workdays later (skips weekends and holidays) |
| NETWORKDAYS | NETWORKDAYS(start_date, end_date, [holidays]) | Number | Workdays between dates (inclusive) |
8.5 List functions
| Function | Signature | Return type | Description |
|---|---|---|---|
| LIST | LIST(val1, val2, ...) | List | Create a list |
| FIRST | FIRST(list) | Scalar | First element |
| LAST | LAST(list) | Scalar | Last element |
| NTH | NTH(list, index) | Scalar | Nth element (1-based) |
| FILTER | [Table].FILTER(condition).[ResultCol] or [Table].[Col].FILTER(condition) | List | Filter by condition. When data range is a table, result column is required; when it's a column/list, it's not needed. Use CurrentValue in conditions. Add .LISTCOMBINE() when result column is multi-value |
| MAP | data_range.MAP(mapping_expr) | List | Apply mapping to each element. Use CurrentValue in mapping |
| SORT | SORT(list, [ascending]) | List | Sort; default ascending (TRUE) |
| SORTBY | [Table].SORTBY([Table].[SortCol], [ascending]).[OutputCol] | List | Sort by column then extract output column. Chain-only, must include output column |
| UNIQUE | UNIQUE(list) | List | Deduplicate |
| ARRAYJOIN | ARRAYJOIN(list, [delimiter]) | Text | Join list elements as text; default comma-separated |
| LISTCOMBINE | LISTCOMBINE(val1, [val2, ...]) or list.LISTCOMBINE() | List | Two uses: (1) merge values/lists into one list; (2) chained call to flatten 2D array (commonly used when FILTER result column is a multi-value field) |
| DISTANCE | DISTANCE(location1, location2) | Number | Distance between two geographic locations (km) |
---
Section 9: Commonly Confused Functions
CONTAIN vs CONTAINTEXT
| CONTAIN | CONTAINTEXT | |
|---|---|---|
| Purpose | Tests if list/MultiSelect contains a value | Tests if text contains a substring |
| Example | [Tags].CONTAIN("Urgent") | [Notes].CONTAINTEXT("completed") |
| Wrong usage | CONTAIN([Notes], "completed") — cannot do substring matching | CONTAINTEXT([Tags], "Urgent") — Tags is a list, not text |
ISBLANK vs ISNULL
| ISBLANK | ISNULL | |
|---|---|---|
| NULL | TRUE | TRUE |
"" empty string | TRUE | FALSE |
Empty list [] | TRUE | FALSE |
0 | FALSE | FALSE |
FALSE | FALSE | FALSE |
DAYS vs DATEDIF
| DAYS | DATEDIF | |
|---|---|---|
| Parameter order | DAYS(end, start) — end first | DATEDIF(start, end, unit) — start first |
| Precision | Includes decimals (hours/minutes/seconds as fractional days) | Integer only (whole days/months/years) |
| Negative values | Returns negative when start is after end | Errors when start is after end |
SUM vs SUMIF
| SUM | SUMIF | |
|---|---|---|
| Purpose | Sum all values | Sum values matching a condition |
| Arguments | SUM(val1, val2, ...) or SUM([Table].[Col]) | SUMIF(data_range, condition) with CurrentValue in condition |
| Example | SUM([Orders].[Amount]) — sum all | SUMIF([Orders].[Amount], CurrentValue > 100) — sum only >100 |
FILTER+aggregation vs COUNTIF/SUMIF
| FILTER+aggregation | COUNTIF/SUMIF | |
|---|---|---|
| Nature | Filter then aggregate (two steps) | One-step (syntactic sugar) |
| Equivalence | [Table].FILTER(cond).[Col].LISTCOMBINE().SUM() | SUMIF([Table].[Col], cond) (only when condition involves only column values) |
| When to use | Conditions span multiple fields, or multi-step needed | Conditions only involve column values (e.g. CurrentValue > 100) |
---
Section 10: Decision Trees
Cross-table queries: which approach?
Need data from another table?
├─ Current table has a link field to the target table?
│ ├─ Yes → Use chained access: [LinkField].[TargetField]
│ │ Need aggregation? → .SUM() / .ARRAYJOIN(",") / .FIRST()
│ └─ No → Need to match by field value?
│ ├─ Field matching or complex filtering → [TargetTable].FILTER(CurrentValue.[MatchField] = [Value]).[OutputCol]
│ └─ Only counting or summing → COUNTIF([TargetTable], condition) / FILTER+SUMConditional logic: IF vs IFS vs SWITCH?
Need conditional logic?
├─ Single condition → IF(condition, true_val, false_val)
├─ Multiple mutually exclusive conditions (if-elseif-else) → IFS(cond1, val1, cond2, val2, ...)
├─ Matching a value against fixed options → SWITCH(expr, option1, result1, option2, result2, ..., default)
└─ Need error handling?
├─ Catch errors → IFERROR(expr, fallback)
└─ Catch blanks → IFBLANK(expr, fallback)Aggregation: which function?
Need to aggregate data?
├─ Sum/average/max/min for entire column → SUM/AVERAGE/MAX/MIN([Table].[Col])
├─ Count non-blank → COUNTA([Table].[Col])
├─ Conditional count → COUNTIF([Table], CurrentValue.[Field] = [Value])
├─ Conditional sum (column-only condition) → SUMIF([Table].[Col], CurrentValue > threshold)
├─ Conditional sum (cross-field condition) → [Table].FILTER(CurrentValue.[Field]=value).[NumCol].LISTCOMBINE().SUM()
├─ Count unique → [Table].[Col].UNIQUE().COUNTA()
└─ Ranking → RANK([Value], [Table].[Col])---
Section 11: Common Formula Patterns
Pattern 1: Cross-table conditional count
Count rows in target table matching a condition:
[TargetTable].COUNTIF(CurrentValue.[MatchField] = [CurrentTableField])Pattern 2: Cross-table conditional sum
Filter target table by current row's value, then sum:
[TargetTable].FILTER(CurrentValue.[MatchField] = [CurrentTableField]).[NumCol].LISTCOMBINE().SUM()SUMIF works when data range is a column and conditions only involve column values:
SUMIF([TargetTable].[NumCol], CurrentValue > 100)Note: COUNTIF can use a table as data range (only counting, no specific column needed), but SUMIF's data range must be a numeric column (needs values to sum), so CurrentValue is each value in that column (scalar) — cannot use CurrentValue.[OtherField] to access other fields. For cross-field conditions, use FILTER with a table as data range.
Pattern 3: Cross-table lookup
[TargetTable].FILTER(CurrentValue.[MatchCol] = [CurrentTableField]).[ReturnCol]Pattern 4: Link field values + aggregation
SUM([LinkField].[NumField])
[LinkField].[TextField].UNIQUE().ARRAYJOIN(",")Pattern 5: Conditional text concatenation
IF([Condition], "prefix" & [Field] & "suffix", "default text")Pattern 6: Date difference
DATEDIF([StartDate], [EndDate], "D") & " days"
DAYS([EndDate], [StartDate])Pattern 7: List element mapping
[MultiSelectField].MAP(CurrentValue & " tag")
SPLIT([TextField], ",").MAP(TRIM(CurrentValue))Pattern 8: Cross-table with sorting
[TargetTable].SORTBY([TargetTable].[SortCol], FALSE).[OutputCol]
[TargetTable].FILTER(CurrentValue.[Field] = [Value]).SORTBY([TargetTable].[SortCol]).[OutputCol]---
Section 12: Anti-Pattern Collection
Mistake 1: Extra argument in MAP
Wrong: [Table].[Col].MAP([Table2].[Col], CurrentValue + 1)
Correct: [Table].[Col].MAP(CurrentValue + 1)Reason: MAP takes only two arguments (data range + mapping expression), no "lookup range".
Mistake 2: Inverted FILTER syntax
Wrong: condition.[Table].FILTER()
Correct: [Table].FILTER(condition).[ResultCol] (result column required when data range is a table)Reason: FILTER's data range comes first, condition is passed as the argument.
Mistake 3: Using CurrentValue.[Field] on a column range
Wrong: SUMIF([Sales].[Revenue], CurrentValue.[Salesperson] = [Name])
Correct: [Sales].FILTER(CurrentValue.[Salesperson] = [Name]).[Revenue].LISTCOMBINE().SUM()Reason: SUMIF([Sales].[Revenue], ...) uses "Revenue" column as data range. CurrentValue is each revenue value (scalar), not a row — cannot use . to access other fields. Use FILTER with the table as data range for cross-field conditions.
Mistake 4: Missing result column after FILTER
Wrong: [Sales].FILTER(CurrentValue.[Amount] > 100)
Correct: [Sales].FILTER(CurrentValue.[Amount] > 100).[Customer]Reason: FILTER on a table returns a table reference; must specify result column with .[Field] at the end.
Mistake 5: Nested FILTER
Wrong: [Table1].FILTER(CurrentValue.[ID] = [Table2].FILTER(CurrentValue.[Status]="Done").[ID])
Correct: [Table1].FILTER(CurrentValue.[ID] = [CurrentRowField]).[OutputCol]Reason: FILTER/MAP/SUMIF/COUNTIF cannot be nested inside each other's conditions. Split into multiple steps or use link fields.
Mistake 6: SORTBY without output column
Wrong: [Table].SORTBY([Table].[Col])
Correct: [Table].SORTBY([Table].[Col]).[OutputCol]Reason: SORTBY must have an output column at the end; otherwise the result cannot be represented as an array.
Mistake 7: SORTBY sort column without table name
Wrong: [Table].SORTBY([Col]).[OutputCol]
Correct: [Table].SORTBY([Table].[Col]).[OutputCol]Reason: SORTBY's sort column must use [TableName].[FieldName] format.
Mistake 8: Using CONTAIN for text substring matching
Wrong: CONTAIN([Notes], "urgent")
Correct: CONTAINTEXT([Notes], "urgent")Reason: CONTAIN checks if a list/MultiSelect contains a whole value, not substring matching. Use CONTAINTEXT for text substrings.
Mistake 9: Date concatenation without formatting
Not recommended: "Deadline: " & [DateField] ← output format is uncontrolled
Recommended: "Deadline: " & TEXT([DateField], "YYYY-MM-DD")Reason: Concatenating a date with & won't error, but uses the default format. Use TEXT to specify the format explicitly.
Mistake 10: Reversed DAYS parameter order
Wrong: DAYS([StartDate], [EndDate]) → returns negative
Correct: DAYS([EndDate], [StartDate]) → returns positiveReason: DAYS parameter order is end date first, start date second.
Mistake 11: Chaining zero-argument functions
Wrong: TODAY.DAYS([Date])
Correct: TODAY().DAYS([Date])Reason: NOW, TODAY, PI and other zero-argument functions must include parentheses.
---
Section 13: Complete Examples
Example 1: Employee sales summary
Table structure (from +table-get):
- Employees: EmployeeID (Text), Name (Text), Department (Text)
- Sales: ContractID (Number), SalespersonID (Text), Quantity (Number), Total (Number)
Current table: Employees
Requirement: For each employee, output "Sold XX orders" if they have sales records, otherwise "No sales records".
Formula:
IF(
[Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) >= 1,
"Sold " & [Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) & " orders",
"No sales records"
)Field JSON:
{
"type": "formula",
"name": "Sales Summary",
"expression": "IF([Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) >= 1, \"Sold \" & [Sales].COUNTIF(CurrentValue.[SalespersonID] = [EmployeeID]) & \" orders\", \"No sales records\")"
}Explanation: [Sales].COUNTIF(...) uses the entire Sales table as data range. CurrentValue represents each row in Sales, accessing CurrentValue.[SalespersonID] for that row's salesperson. [EmployeeID] refers to the current row in the Employees table (where the formula lives).
Example 2: Chained cross-table access via link fields
Table structure:
- Orders: ID (AutoNumber), OrderItems (Link [target: OrderItems, foreign key: ID])
- OrderItems: ID (AutoNumber), Product (Link [target: Products, foreign key: ID])
- Products: ID (AutoNumber), ProductName (Text)
Current table: Orders
Requirement: Deduplicate and comma-join all product names from linked order items.
Formula:
[OrderItems].[Product].[ProductName].UNIQUE().ARRAYJOIN(",")Field JSON:
{
"type": "formula",
"name": "Product List",
"expression": "[OrderItems].[Product].[ProductName].UNIQUE().ARRAYJOIN(\",\")"
}Explanation: [OrderItems] gets linked order item records, .[Product] expands to each item's linked product, .[ProductName] gets all product names, .UNIQUE() deduplicates, .ARRAYJOIN(",") joins with commas.
Example 3: Cross-table filter + sort
Table structure:
- Projects: ProjectName (Text), Status (Text), Owner (Text)
- Tasks: TaskName (Text), Project (Text), Priority (Number), DueDate (Date)
Current table: Projects
Requirement: Find the highest-priority (lowest number) task name for the current project.
Formula:
FIRST(
[Tasks].FILTER(CurrentValue.[Project] = [ProjectName]).SORTBY([Tasks].[Priority], TRUE).[TaskName]
)Field JSON:
{
"type": "formula",
"name": "Top Priority Task",
"expression": "FIRST([Tasks].FILTER(CurrentValue.[Project] = [ProjectName]).SORTBY([Tasks].[Priority], TRUE).[TaskName])"
}Explanation: [Tasks].FILTER(CurrentValue.[Project] = [ProjectName]) filters tasks belonging to the current project. .SORTBY([Tasks].[Priority], TRUE) sorts by priority ascending. .[TaskName] extracts task names. FIRST(...) gets the first one (highest priority).
---
Section 14: Translating User Requirements to Formulas
When the user describes their formula need in natural language, follow these rules to convert it into a precise expression:
1. Numbers must use precise values: "less than 80%" → field value less than 0.8. "above 1000" → >= 1000. 2. Interval boundaries: "above/below/within" = closed (inclusive); "less than/more than/outside" = open (exclusive). 3. Branching logic must be organized as an ordered list with a fallback branch. Each branch has a condition and output.
- Example: "return risk level for 1-3" →
IFS([Value] = 1, "low", [Value] = 2, "medium", [Value] = 3, "high")with anIFERRORor trailing empty-string fallback.
4. Multi-level branches must be flattened to a single level. Nested if-else chains → flat IFS. 5. Branch conditions must be mutually exclusive. If the user's conditions overlap, rewrite to eliminate ambiguity. 6. Reorder branches by logical priority if the user's order is illogical (e.g., check specific conditions before catch-all).
---
Section 15: Constraint Summary
- Request body must include
"type": "formula"— this field is required - Only use functions and operators listed in this document
- FILTER/SUMIF/COUNTIF/MAP must not be nested inside each other's conditions (chained calls are not nesting)
- Do not use LOOKUP — use FILTER exclusively
- Table and field names must exactly match
+table-getoutput - Strings must use double quotes
" - Format dates with TEXT before concatenating, to control output format
- SORTBY can only be chained and must include an output column
- Link fields return lists — aggregate or extract single values before output
base +advperm-disable
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
停用指定 Base 的高级权限。停用后自定义角色等高级权限功能将不可用。
推荐命令
# 停用高级权限
lark-cli base +advperm-disable \
--base-token VwGhbYCXQaYGMzsWlEZcBbfMnod参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token,27 位字母数字字符串 |
API 入参详情
HTTP 方法和路径:
PUT /open-apis/base/v3/bases/:base_token/advperm/enable?enable=falsePath 参数:
| 参数 | 必填 | 说明 |
|---|---|---|
base_token | 是 | Base 的唯一标识,27 位字母数字字符串 |
Query 参数:
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
enable | 是 | bool | 固定为 false,表示停用高级权限 |
API 出参详情
Response:
| 字段 | 类型 | 说明 |
|---|---|---|
code | int32 | 错误码,0 表示成功 |
message | string | 错误信息 |
data | string | 成功时为空 |
返回值
命令成功后输出 JSON:
{
"ok": true,
"data": {
"success": true
}
}工作流
[!CAUTION]
这是高风险写入操作 — 停用高级权限会影响所有已配置的自定义角色,执行前必须向用户确认。
1. 向用户确认 --base-token,并提醒停用会影响已有角色配置 2. 执行命令 3. 确认返回 code: 0 表示停用成功
坑点
- ⚠️ 操作用户必须为 Base 管理员:非管理员调用会返回权限错误
- ⚠️ 停用影响已有角色:停用高级权限后,已创建的自定义角色将失效
- ⚠️ API 路径版本:本接口使用
base/v3,路径必须从原始文档提取,不要用 WebSearch 补全 - ⚠️ data 字段是 JSON 字符串:响应中
data是 string 类型(非 object),需要双重解析
参考
- lark-base — 多维表格全部命令
- lark-shared — 认证和全局参数
base +advperm-enable
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
启用指定 Base 的高级权限。启用后可使用自定义角色等高级权限功能。
推荐命令
# 启用高级权限
lark-cli base +advperm-enable \
--base-token VwGh**************Mnod参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token,27 位字母数字字符串 |
API 入参详情
HTTP 方法和路径:
PUT /open-apis/base/v3/bases/:base_token/advperm/enable?enable=truePath 参数:
| 参数 | 必填 | 说明 |
|---|---|---|
base_token | 是 | Base 的唯一标识,27 位字母数字字符串 |
Query 参数:
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
enable | 是 | bool | 固定为 true,表示启用高级权限 |
API 出参详情
Response:
| 字段 | 类型 | 说明 |
|---|---|---|
code | int32 | 错误码,0 表示成功 |
message | string | 错误信息 |
data | string | 成功时为空 |
返回值
命令成功后输出 JSON:
{
"ok": true,
"data": {
"success": true
}
}工作流
1. 向用户确认 --base-token 2. 执行命令 3. 确认返回 code: 0 表示启用成功
坑点
- ⚠️ 操作用户必须为 Base 管理员:非管理员调用会返回权限错误
- ⚠️ API 路径版本:本接口使用
base/v3,路径必须从原始文档提取,不要用 WebSearch 补全 - ⚠️ data 字段是 JSON 字符串:响应中
data是 string 类型(非 object),需要双重解析 - ⚠️ 启用后才能管理角色:
+role-create / +role-update / +role-delete等角色操作需要先启用高级权限
参考
- lark-base — 多维表格全部命令
- lark-shared — 认证和全局参数
base +base-copy
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
复制一个已有 Base;可选只复制结构,不复制内容。
推荐命令
lark-cli base +base-copy \
--base-token app_xxx \
--name "Copied Base"
lark-cli base +base-copy \
--base-token app_xxx \
--name "Copied Base" \
--folder-token fld_xxx \
--time-zone Asia/Shanghai \
--without-content参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | 源 Base Token |
--name <name> | 否 | 新 Base 名称 |
--folder-token <token> | 否 | 目标文件夹 token |
--time-zone <tz> | 否 | 时区,如 Asia/Shanghai |
--without-content | 否 | 只复制结构,不复制内容 |
API 入参详情
HTTP 方法和路径:
POST /open-apis/base/v3/bases/:base_token/copy返回重点
- 返回
base。 - CLI 会额外标记
copied: true。 - 回复结果时,必须主动返回新 Base 的可访问链接:
- 优先使用返回结果中的
base.url - 同时返回新 Base 的 token;字段名以实际返回为准,常见为
base_token或app_token - 如果本次返回没有
url,至少返回新 Base 的名称和 token
[!IMPORTANT]
如果 Base 是以应用身份(bot)复制出来的,agent 在复制成功后应默认继续使用 bot 身份,为当前可用的 user 身份添加该 Base 的 full_access(管理员)权限。推荐流程:
1. 先用lark-cli contact +get-user获取当前用户信息,并从返回结果中读取该用户的open_id
2. 再切回 bot 身份,使用这个open_id给该用户授权该 Base 的full_access(管理员)权限
>
如果lark-cli contact +get-user无法执行,或者本地没有可用的 user 身份、拿不到当前用户的open_id,则应视为“本地没有可用的 user 身份”,明确说明因此未完成授权。
>
回复复制结果时,除 base token 和可访问链接外,还必须明确告知用户授权结果:- 如果授权成功:直接说明当前 user 已获得该 Base 的管理员权限
- 如果本地没有可用的 user 身份:明确说明因此未完成授权
- 如果授权失败:明确说明 Base 已复制成功,但授权失败,并透出失败原因;同时提示用户可以稍后重试授权,或继续使用应用身份(bot)处理该 Base
>
如果授权未完成,应继续给出后续引导:用户可以稍后重试授权,也可以继续使用应用身份(bot)处理该 Base;如果希望后续改由自己管理,也可将 Base owner 转移给该用户。
>
仍然不要擅自执行 owner 转移。 如果用户需要把 owner 转给自己,必须单独确认。
工作流
[!CAUTION]
这是写入操作 — 执行前必须向用户确认。
1. 先确认源 Base Token。 2. --name、--folder-token、--time-zone 都是可选项;用户没要求时不要为这些可选参数额外追问。 3. 只要结构时,显式传 --without-content。 4. 复制成功后,整理并返回:新 Base 名称、token,以及响应中已有的可访问链接。
参考
- lark-base-workspace.md — base / workspace 索引页
- lark-base-base-create.md — 创建全新 Base
base +base-create
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
创建一个新的 Base;可选指定父文件夹和时区。
推荐命令
lark-cli base +base-create \
--name "New Base"
lark-cli base +base-create \
--name "项目管理" \
--folder-token fld_xxx \
--time-zone Asia/Shanghai参数
| 参数 | 必填 | 说明 |
|---|---|---|
--name <name> | 是 | 新 Base 名称 |
--folder-token <token> | 否 | 目标文件夹 token |
--time-zone <tz> | 否 | 时区,如 Asia/Shanghai |
API 入参详情
HTTP 方法和路径:
POST /open-apis/base/v3/bases返回重点
- 返回
base。 - CLI 会额外标记
created: true。 - 回复结果时,必须主动返回新 Base 的可访问链接:
- 优先使用返回结果中的
base.url - 同时返回新 Base 的 token;字段名以实际返回为准,常见为
base_token或app_token - 如果本次返回没有
url,至少返回新 Base 的名称和 token
[!IMPORTANT]
如果 Base 是以应用身份(bot)创建的,agent 在创建成功后应默认继续使用 bot 身份,为当前可用的 user 身份添加该 Base 的 full_access(管理员)权限。推荐流程:
1. 先用lark-cli contact +get-user获取当前用户信息,并从返回结果中读取该用户的open_id
2. 再切回 bot 身份,使用这个open_id给该用户授权该 Base 的full_access(管理员)权限
>
如果lark-cli contact +get-user无法执行,或者本地没有可用的 user 身份、拿不到当前用户的open_id,则应视为“本地没有可用的 user 身份”,明确说明因此未完成授权。
>
回复创建结果时,除 base token 和可访问链接外,还必须明确告知用户授权结果:- 如果授权成功:直接说明当前 user 已获得该 Base 的管理员权限
- 如果本地没有可用的 user 身份:明确说明因此未完成授权
- 如果授权失败:明确说明 Base 已创建成功,但授权失败,并透出失败原因;同时提示用户可以稍后重试授权,或继续使用应用身份(bot)处理该 Base
>
如果授权未完成,应继续给出后续引导:用户可以稍后重试授权,也可以继续使用应用身份(bot)处理该 Base;如果希望后续改由自己管理,也可将 Base owner 转移给该用户。
>
仍然不要擅自执行 owner 转移。 如果用户需要把 owner 转给自己,必须单独确认。
工作流
[!CAUTION]
这是写入操作 — 执行前必须向用户确认。
1. 先确认 Base 名称。 2. --folder-token、--time-zone 都是可选项;用户没要求时不要为此额外追问。 3. 创建成功后,整理并返回:Base 名称、token,以及响应中已有的可访问链接。
参考
- lark-base-workspace.md — base / workspace 索引页
- lark-base-base-copy.md — 复制 Base
base +base-get
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
读取一个 Base 的详情。
推荐命令
lark-cli base +base-get \
--base-token app_xxx参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
API 入参详情
HTTP 方法和路径:
GET /open-apis/base/v3/bases/:base_token返回重点
- 返回
base,通常包含base_token / name / url等信息。
坑点
- ⚠️ 先确认传入的是
base_token,不是workspace_token。 - ⚠️ 如果最初输入来自
/wiki/...,不要直接把wiki_token当--base-token;若报param baseToken is invalid/base_token invalid,先用lark-cli wiki spaces get_node取node.obj_token,再重试+base-get。
参考
- lark-base-workspace.md — base 索引页
base +dashboard-block-create
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
data_config 结构: 参见 dashboard-block-data-config.md 了解图表类型、通用字段和 filter 规则。
在仪表盘中创建一个 Block(图表组件)。
推荐命令
# 创建柱状图 block
lark-cli base +dashboard-block-create \
--base-token bascn***************CtadY \
--dashboard-id blkxxx \
--name "订单趋势" \
--type column \
--data-config '{"table_name":"订单表","count_all":true,"group_by":[{"field_name":"金额","mode":"integrated"}],"filter":{"conjunction":"and","conditions":[{"field_name":"金额","operator":"isGreater","value":0},{"field_name":"状态","operator":"is","value":"已完成"},{"field_name":"负责人","operator":"isNotEmpty"},{"field_name":"创建日期","operator":"isGreaterEqual","value":1711209600000}]}}'
# 创建指标卡(统计数字字段求和)
lark-cli base +dashboard-block-create \
--base-token bascn***************CtadY \
--dashboard-id blkxxx \
--name "销售总额" \
--type statistics \
--data-config '{"table_name":"数据表","series":[{"field_name":"数字","rollup":"SUM"}]}'
# 创建指标卡(统计记录行数)
lark-cli base +dashboard-block-create \
--base-token bascn***************CtadY \
--dashboard-id blkxxx \
--name "记录总数" \
--type statistics \
--data-config '{"table_name":"数据表","count_all":true}'
# 使用文件传入复杂 data_config
lark-cli base +dashboard-block-create \
--base-token bascn***************CtadY \
--dashboard-id blkxxx \
--name "销售漏斗" \
--type funnel \
--data-config @config.json参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--name <name> | 是 | Block 名称(允许重名) |
--type <type> | 是 | Block 类型(见 dashboard-block-data-config.md 类型枚举表) |
--data-config <json> | 否 | 数据配置 JSON 对象(支持 @file.json) |
--user-id-type <type> | 否 | 用户 ID 类型 |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
POST /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_id/blocksRequest Body:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | Block 名称(允许重名) |
type | string | 是 | Block 类型枚举 |
data_config | object | 否 | 数据配置(数据源、维度、指标、筛选等) |
Create 不支持 layout(layout 由后端自动计算)返回重点
| 字段 | 类型 | 说明 |
|---|---|---|
block_id | string | Block ID |
name | string | Block 名称 |
type | string | Block 类型 |
layout | object | 布局信息(只读,后端自动计算) |
data_config | object | 数据配置 |
工作流
[!CAUTION]
这是写入操作 — 执行前必须向用户确认。
1. 先确定图表类型(参见 dashboard-block-data-config.md)。 2. JSON 较大时优先用 @file.json。
[!TIP]
CLI 会对data_config做轻量校验与规范化:series[].rollup大写、group_by[].sort.*小写;若需要跳过,使用--no-validate。可直接参考文档尾部的“可复制模板”。
坑点
- `name` 和 `type` 必填 — name 允许重名,type 不可在创建后修改。
- `layout` 只读 — 由后端自动计算,Create 不支持指定布局。
- `data_config` 结构随 `type` 变化 — 不同组件类型的字段不同,创建前务必确认类型对应的字段。
- `count_all` 与 `series` 二选一 — 两者不能同时使用。
- `user_id_type` 仅在 filter 涉及人员字段时有意义。
参考
- lark-base-dashboard-block.md — block 索引页
- dashboard-block-data-config.md — data_config 结构、图表类型、filter 规则
base +dashboard-block-delete
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
删除仪表盘中的一个 Block。
推荐命令
lark-cli base +dashboard-block-delete \
--base-token bascn***************CtadY \
--dashboard-id blkxxx \
--block-id 9v7g********idcd参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--block-id <id> | 是 | Block ID |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
DELETE /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_id/blocks/:block_id工作流
[!CAUTION]
这是写入操作且不可逆 — 执行前必须向用户确认。
参考
- lark-base-dashboard-block.md — block 索引页
base +dashboard-block-get
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
获取仪表盘中单个 Block 的详情。
推荐命令
lark-cli base +dashboard-block-get \
--base-token bascn***************CtadY \
--dashboard-id blkxxx \
--block-id 9v7g********idcd参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--block-id <id> | 是 | Block ID |
--user-id-type <type> | 否 | 用户 ID 类型:open_id / union_id / user_id |
--format <fmt> | 否 | 输出格式 |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
GET /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_id/blocks/:block_idQuery 参数:
| 参数 | 必填 | 说明 |
|---|---|---|
user_id_type | 否 | 用户 ID 类型,默认 open_id(仅在 filter 涉及人员字段时使用) |
返回重点
| 字段 | 类型 | 说明 |
|---|---|---|
block_id | string | Block ID |
name | string | Block 名称 |
type | string | Block 类型 |
layout | object | 布局信息(只读) |
layout.x | int | X 坐标 |
layout.y | int | Y 坐标 |
layout.w | int | 宽度 |
layout.h | int | 高度 |
data_config | object | 数据配置 |
参考
- lark-base-dashboard-block.md — block 索引页
- dashboard-block-data-config.md — data_config 结构详解
base +dashboard-block-list
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
分页列出仪表盘中的所有 Block(图表组件)。
推荐命令
lark-cli base +dashboard-block-list \
--base-token bascn***************CtadY \
--dashboard-id blkxxx参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--page-size <n> | 否 | 每页数量,默认 20,最大 100 |
--page-token <token> | 否 | 分页标记 |
--format <fmt> | 否 | 输出格式:json / pretty / table / csv / ndjson |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
GET /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_id/blocks返回重点
| 字段 | 类型 | 说明 |
|---|---|---|
items | []Block | Block 列表 |
total | int | Block 总数 |
has_more | bool | 是否还有更多 |
page_token | string | 下一页分页标记(has_more=true 时返回) |
坑点
+dashboard-block-list禁止并发调用;批量执行时只能串行。
参考
- lark-base-dashboard-block.md — block 索引页
base +dashboard-block-update
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
data_config 结构: 参见 dashboard-block-data-config.md 了解图表类型、通用字段和 filter 规则。
更新仪表盘中 Block 的名称或数据配置。
推荐命令
lark-cli base +dashboard-block-update \
--base-token bascn***************CtadY \
--dashboard-id blkxxx \
--block-id 9v7g********cd \
--name "订单趋势v2" \
--data-config '{"table_name":"订单表2","count_all":true,"group_by":[{"field_name":"金额2","mode":"integrated"}]}'参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--block-id <id> | 是 | Block ID |
--name <name> | 否 | 新名称 |
--data-config <json> | 否 | 数据配置 JSON 对象 |
--user-id-type <type> | 否 | 用户 ID 类型 |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
PATCH /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_id/blocks/:block_idRequest Body:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 否 | Block 名称 |
data_config | object | 否 | 数据配置 |
Update 不支持修改type和layout
工作流
[!CAUTION]
这是写入操作 — 执行前必须向用户确认。
[!TIP]
CLI 默认会对data_config做轻量校验与规范化(见 dashboard-block-data-config.md 的“约束与本地校验”);如需兼容特殊场景,可加--no-validate跳过。
坑点
- 不可修改 `type` 和 `layout` — 只能更新
name和data_config。 - `user_id_type` 仅在 filter 涉及人员字段时有意义。
参考
- lark-base-dashboard-block.md — block 索引页
- dashboard-block-data-config.md — data_config 结构详解
base dashboard block shortcuts
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
dashboard block(图表组件)相关命令索引。
命令导航
| 文档 | 命令 | 说明 |
|---|---|---|
| lark-base-dashboard-block-list.md | +dashboard-block-list | 分页列出仪表盘 Block |
| lark-base-dashboard-block-get.md | +dashboard-block-get | 获取 Block 详情 |
| lark-base-dashboard-block-create.md | +dashboard-block-create | 创建 Block |
| lark-base-dashboard-block-update.md | +dashboard-block-update | 更新 Block |
| lark-base-dashboard-block-delete.md | +dashboard-block-delete | 删除 Block |
相关
- lark-base-dashboard.md — 仪表盘管理
- dashboard-block-data-config.md — Block data_config 结构、图表类型、filter 规则
说明
- 聚合页只保留目录职责;每个命令的详细说明请进入对应单命令文档。
- 所有
+xxx-list调用都必须串行执行;若要批量跑多个 list 请求,只能串行执行。
base +dashboard-create
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
创建仪表盘。
推荐命令
# 创建仪表盘
lark-cli base +dashboard-create \
--base-token VwGhb**************fMnod \
--name "销售报表"
# 创建仪表盘(指定主题)
lark-cli base +dashboard-create \
--base-token VwGhb**************fMnod \
--name "销售报表" \
--theme-style default参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--name <name> | 是 | 仪表盘名称 |
--theme-style <style> | 否 | 主题风格(见下方枚举) |
--dry-run | 否 | 预览 API 调用,不执行 |
theme-style 枚举
| 值 | 说明 |
|---|---|
default | 默认主题 |
SimpleBlue | 简约蓝 |
DarkGreen | 深绿 |
summerBreeze | 夏日微风 |
simplistic | 简洁 |
energetic | 活力 |
deepDark | 深色 |
futuristic | 未来感 |
API 入参详情
HTTP 方法和路径:
POST /open-apis/base/v3/bases/:base_token/dashboardsRequest Body:
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 仪表盘名称 |
theme | object | 主题配置 |
theme.theme_style | string | 主题风格 |
返回重点
- 返回创建后的仪表盘对象,包含
dashboard_id。
工作流
[!CAUTION]
这是写入操作 — 执行前必须向用户确认。
坑点
- dashboard_id 在 create 返回中取得,后续 get/update/delete 使用。
- theme_style 是嵌套在
theme对象下的字段,shortcut 自动包装为{"theme": {"theme_style": "..."}}。
参考
- lark-base-dashboard.md — dashboard 索引页
base +dashboard-delete
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
删除仪表盘。
推荐命令
lark-cli base +dashboard-delete \
--base-token VwGhb**************fMnod \
--dashboard-id dshxxxxxxx参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
DELETE /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_id工作流
[!CAUTION]
这是写入操作且不可逆 — 执行前必须向用户确认。
坑点
- 删除仪表盘会同时删除其下所有 Block,不可恢复。
参考
- lark-base-dashboard.md — dashboard 索引页
base +dashboard-get
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
获取仪表盘详情,包括主题和组件列表。
推荐命令
lark-cli base +dashboard-get \
--base-token VwGhb**************fMnod \
--dashboard-id dshxxxxxxx参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--format <fmt> | 否 | 输出格式 |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
GET /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_id返回重点
| 字段 | 类型 | 说明 |
|---|---|---|
dashboard_id | string | 仪表盘 ID |
name | string | 仪表盘名称 |
theme | object | 主题配置 |
theme.theme_style | string | 主题风格:default / SimpleBlue / DarkGreen / summerBreeze / simplistic / energetic / deepDark / futuristic |
blocks | []object | 组件列表 |
blocks[].block_id | string | 组件 ID |
blocks[].block_name | string | 组件名称 |
blocks[].block_type | string | 组件类型 |
参考
- lark-base-dashboard.md — dashboard 索引页
- lark-base-dashboard-block.md — Block 管理
base +dashboard-list
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
分页列出一个 Base 下的仪表盘。
推荐命令
lark-cli base +dashboard-list \
--base-token VwGhb**************fMnod参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--page-size <n> | 否 | 每页数量 |
--page-token <token> | 否 | 分页标记 |
--format <fmt> | 否 | 输出格式:json / pretty / table / csv / ndjson |
--dry-run | 否 | 预览 API 调用,不执行 |
API 入参详情
HTTP 方法和路径:
GET /open-apis/base/v3/bases/:base_token/dashboards返回重点
- 返回
items / total / page_token / has_more。 items仅含dashboard_id和name。
坑点
+dashboard-list禁止并发调用;批量列多个 Base 时必须串行。
参考
- lark-base-dashboard.md — dashboard 索引页
base +dashboard-update
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
更新仪表盘名称或主题。
推荐命令
lark-cli base +dashboard-update \
--base-token VwGhb**************fMnod \
--dashboard-id dshxxxxxxx \
--name "新名称" \
--theme-style default参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--dashboard-id <id> | 是 | 仪表盘 ID |
--name <name> | 否 | 新名称 |
--theme-style <style> | 否 | 主题风格(见下方枚举) |
--dry-run | 否 | 预览 API 调用,不执行 |
theme-style 枚举
| 值 | 说明 |
|---|---|
default | 默认主题 |
SimpleBlue | 简约蓝 |
DarkGreen | 深绿 |
summerBreeze | 夏日微风 |
simplistic | 简洁 |
energetic | 活力 |
deepDark | 深色 |
futuristic | 未来感 |
API 入参详情
HTTP 方法和路径:
PATCH /open-apis/base/v3/bases/:base_token/dashboards/:dashboard_idRequest Body:
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 仪表盘名称 |
theme | object | 主题配置 |
theme.theme_style | string | 主题风格 |
工作流
[!CAUTION]
这是写入操作 — 执行前必须向用户确认。
坑点
- theme_style 是嵌套在
theme对象下的字段,shortcut 自动包装为{"theme": {"theme_style": "..."}}。
参考
- lark-base-dashboard.md — dashboard 索引页
base dashboard shortcuts
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
dashboard 相关命令索引。
命令导航
| 文档 | 命令 | 说明 |
|---|---|---|
| lark-base-dashboard-list.md | +dashboard-list | 分页列出仪表盘 |
| lark-base-dashboard-get.md | +dashboard-get | 获取仪表盘详情 |
| lark-base-dashboard-create.md | +dashboard-create | 创建仪表盘 |
| lark-base-dashboard-update.md | +dashboard-update | 更新仪表盘 |
| lark-base-dashboard-delete.md | +dashboard-delete | 删除仪表盘 |
相关
- lark-base-dashboard-block.md — 仪表盘 Block(图表组件)管理
说明
- 聚合页只保留目录职责;每个命令的详细说明请进入对应单命令文档。
- 所有
+xxx-list调用都必须串行执行;若要批量跑多个 list 请求,只能串行执行。
base +field-create
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
创建一个字段。
Agent 最小工作流
1. 先判断是不是 formula / lookup。 2. 如果是:先读对应 guide。 3. 没读 guide 前,不要直接创建 formula / lookup 字段。 4. 读完 guide 后,再构造 --json 并创建字段。 5. 如果是跨表 formula / lookup,再补查目标表的结构。
推荐命令
lark-cli base +field-create \
--base-token app_xxx \
--table-id tbl_xxx \
--json '{"name":"预算","type":"number","precision":2}'
lark-cli base +field-create \
--base-token app_xxx \
--table-id tbl_xxx \
--json '{"name":"状态","type":"select","multiple":false,"options":[{"name":"Todo","hue":"Blue","lightness":"Lighter"},{"name":"Done","hue":"Green","lightness":"Light"}]}'参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--table-id <id_or_name> | 是 | 表 ID 或表名 |
--json <body> | 是 | 字段属性 JSON 对象 |
API 入参详情
HTTP 方法和路径:
POST /open-apis/base/v3/bases/:base_token/tables/:table_id/fieldsJSON 值规范
--json必须是 JSON 对象,顶层直接传字段定义,不要再套一层。- 顶层最少包含:
name、type。 type不同,必填子字段不同:select:用multiple+options(options里只传name/hue/lightness,不要传id)。link:必须有link_table,可选bidirectional、bidirectional_link_field_name。formula:必须有expression;先读 formula guide,再创建。lookup:必须有from、select、where;先读 lookup guide,再创建。
正确(base +field-create)
{
"name": "状态",
"type": "select",
"multiple": false,
"options": [
{ "name": "Todo", "hue": "Blue", "lightness": "Lighter" },
{ "name": "Done", "hue": "Green", "lightness": "Light" }
]
}返回重点
- 返回
field和created: true。
工作流
1. formula / lookup 字段必须先阅读对应指南;没读之前不要直接创建。
坑点
- ⚠️ 这是写入操作,执行前必须确认。
- ⚠️ 当
--json.type是formula或lookup时,先读对应 guide,再创建。
参考
- lark-base-field.md — field 索引页
- lark-base-shortcut-field-properties.md — shortcut 字段 JSON 规范(推荐)
- formula-field-guide.md — formula 指南(创建公式必读)
- lookup-field-guide.md — lookup 指南(创建查找引用必读)
base +field-delete
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
删除一个字段。
推荐命令
lark-cli base +field-delete \
--base-token app_xxx \
--table-id tbl_xxx \
--field-id fld_xxx \
--yes参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--table-id <id_or_name> | 是 | 表 ID 或表名 |
--field-id <id_or_name> | 是 | 字段 ID 或字段名 |
API 入参详情
HTTP 方法和路径:
DELETE /open-apis/base/v3/bases/:base_token/tables/:table_id/fields/:field_id返回重点
- 返回
deleted: true和目标字段标识。
工作流
这是高风险写入操作。CLI 层要求显式传--yes;如果用户已经明确要求删除且目标明确,直接执行并带上--yes,不要再补一次确认。
1. 建议先用 +field-get 或 +field-list 确认目标字段。 2. 只有当字段目标仍不明确时,才继续追问;如果删除意图和目标都明确,直接执行。
坑点
- ⚠️ 高风险写操作,删除后不可恢复。
- ⚠️ 忘记带
--yes会被 CLI 拦截。
参考
- lark-base-field.md — field 索引页
base +field-get
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
获取一个字段的完整配置。
推荐命令
lark-cli base +field-get \
--base-token app_xxx \
--table-id tbl_xxx \
--field-id fld_xxx参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--table-id <id_or_name> | 是 | 表 ID 或表名 |
--field-id <id_or_name> | 是 | 字段 ID 或字段名 |
API 入参详情
HTTP 方法和路径:
GET /open-apis/base/v3/bases/:base_token/tables/:table_id/fields/:field_id返回重点
- 返回完整字段配置,适合做更新前的基线。
坑点
- ⚠️ 重名字段场景下,建议优先传
fld_xxx。
参考
- lark-base-field.md — field 索引页
base history shortcuts
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
history 相关命令索引。
命令导航
| 文档 | 命令 | 说明 |
|---|---|---|
| lark-base-record-history-list.md | +record-history-list | 按 table-id + record-id 查询记录变更历史 |
说明
- 聚合页只保留目录职责;每个命令的详细说明请进入对应单命令文档。
- 所有
+xxx-list调用都必须串行执行;若要批量跑多个 list 请求,只能串行执行。