标签
标签配置
标签是可以应用于会话的附加标记。与状态(互斥——每个会话只能有一个)不同,标签是多选的(每个会话可以有多个)。它们支持通过嵌套 JSON 树进行层次化组织。
存储位置
- 配置文件:
~/.tentarc/workspaces/{id}/labels/config.json
无默认值(常规标签)
与状态不同,常规标签一开始是空的。用户可以创建他们需要的任何标签。没有内置或必需的常规标签。
视觉表示
标签仅有颜色——在 UI 中渲染为彩色圆圈。不支持图标或表情符号。
层次化标签(嵌套树)
标签形成嵌套的 JSON 树。层次结构就是结构本身——父/子关系通过 children 数组表示。数组位置决定显示顺序(不需要 order 字段)。
示例:
{
"version": 1,
"labels": [
{
"id": "eng",
"name": "Engineering",
"color": "info",
"children": [
{
"id": "frontend",
"name": "Frontend",
"children": [
{ "id": "react", "name": "React", "color": { "light": "#3B82F6", "dark": "#60A5FA" } }
]
},
{ "id": "backend", "name": "Backend" }
]
},
{ "id": "bug", "name": "Bug", "color": "destructive" }
]
}
这会在侧边栏中渲染为树形结构:
Engineering
├─ Frontend
│ └─ React
└─ Backend
Bug
规则:
- ID 是简单的 slug(小写字母数字 + 连字符)
- ID 必须在整个树中全局唯一
- 最大嵌套深度:5 层
- 数组位置 = 显示顺序(无
order字段) - 按父标签筛选会包含所有子孙标签
config.json 结构
{
"version": 1,
"labels": [
{
"id": "bug",
"name": "Bug",
"color": "destructive"
},
{
"id": "feature",
"name": "Feature",
"color": "accent",
"children": [
{ "id": "ui", "name": "UI", "color": { "light": "#6366F1", "dark": "#818CF8" } },
{ "id": "api", "name": "API", "color": { "light": "#10B981", "dark": "#34D399" } }
]
}
]
}
标签属性
| 属性 | 类型 | 描述 |
|---|---|---|
id | string | 唯一 slug,在整个树中全局唯一(例如 "bug"、"frontend")。小写字母数字 + 连字符。 |
name | string | 显示名称 |
color | EntityColor? | 可选颜色。系统颜色字符串(例如 "accent"、"info/80")或自定义对象({ "light": "#hex", "dark": "#hex" })。在 UI 中渲染为彩色圆圈。 |
valueType | 'string' | 'number' | 'date'? | 可选的值类型提示。告诉 UI 显示什么输入控件,以及代理应该写入什么格式。布尔(仅存在)标签可省略。 |
children | LabelConfig[]? | 可选的嵌套子标签。数组位置 = 显示顺序。 |
颜色格式
与状态相同——参见状态文档了解支持的格式和常见错误的完整详情。
系统颜色: "accent"、"info"、"success"、"destructive"、"foreground"(可选 /opacity 0–100)
自定义颜色: { "light": "#EF4444", "dark": "#F87171" } — 支持 hex、OKLCH、RGB、HSL 格式
会话标签
会话将标签存储为字符串数组。布尔标签是纯 ID;带值标签使用 :: 分隔符:
{
"labels": ["bug", "priority::3", "due::2026-01-30", "linear::https://linear.app/issue/ENG-456"]
}
- 标签是累加的(会话可以有零个或多个标签)
- 布尔标签:
"bug"— 仅存在,无值 - 带值标签:
"priority::3"— ID + 值用::分隔 ::分割仅在第一次出现时进行(值可以包含::)- 无效的标签 ID 在读取时会被静默过滤掉
- 删除标签会自动从所有会话中移除它(子标签也会被移除)
- 层次化筛选:点击父标签会显示标记了它或任何子孙的会话
值类型
值在解析时从原始字符串推断:
| 类型 | 格式 | 示例 |
|---|---|---|
number | 有限数字 | "priority::3"、"effort::0.5" |
date | ISO 日期 (YYYY-MM-DD) | "due::2026-01-30" |
string | 其他任何内容 | "link::https://example.com" |
推断顺序: ISO 日期检查 → 数字检查 → 字符串后备。
配置中的可选 valueType 仅是提示——解析器始终从原始值推断,不管配置如何。
添加标签
编辑工作区的 labels/config.json:
{
"version": 1,
"labels": [
{
"id": "bug",
"name": "Bug",
"color": "destructive"
},
{
"id": "priority",
"name": "Priority",
"color": "accent",
"valueType": "number"
},
{
"id": "due",
"name": "Due Date",
"color": "info",
"valueType": "date"
},
{
"id": "project",
"name": "Project",
"color": "foreground/60",
"children": [
{ "id": "alpha", "name": "Alpha", "color": "info" },
{ "id": "beta", "name": "Beta", "color": "success" }
]
}
]
}
颜色约定
创建或修改标签时,除非用户明确要求,否则请遵循以下约定:
-
始终添加颜色。 每个标签都应该有
color用于视觉识别(渲染为彩色圆圈)。 -
在类别内使用互补色。 同级标签(同一父级的子标签)应使用相同色系或色调范围的颜色,创建视觉上协调的组。例如,"Backend" 组可能为其子标签(API、Database)使用绿色/青色,而 "Frontend" 使用靛蓝/蓝色(React、CSS)。
-
对语义含义使用语义颜色:
- Bug/错误 →
"destructive"或红色调 - 功能/增强 →
"accent"或蓝色/靛蓝色调 - 成功/完成 →
"success"或绿色调 - 信息/元数据 →
"info"或天蓝/青色调 - 中性/杂项 →
"foreground/60"或灰色调
- Bug/错误 →
颜色格式提醒: 对子标签使用自定义 { "light": "#hex", "dark": "#hex" } 对象以获得精确的颜色控制。为顶级父类别保留系统颜色("accent"、"info"、"destructive" 等)。
验证
重要:创建或编辑标签后务必验证:
config_validate({ target: "labels" })
验证内容:
- 有效的 JSON 和递归 schema 结构
- 整个树中全局唯一的 ID
- 有效的 slug 格式(小写字母数字加连字符)
- 最大嵌套深度(5 层)
自动标签规则
自动标签规则自动扫描用户消息并应用带有提取值的标签。在任何标签上配置正则表达式模式以触发自动标记。
配置
在 config.json 中的任何标签上添加 autoRules:
{
"id": "linear-issue",
"name": "Linear Issue",
"color": "purple",
"valueType": "string",
"autoRules": [
{
"pattern": "linear\\.app/[\\w-]+/issue/([A-Z]+-\\d+)",
"valueTemplate": "$1",
"description": "Matches Linear issue URLs"
},
{
"pattern": "\\b([A-Z]{2,5}-\\d+)\\b",
"valueTemplate": "$1",
"description": "Matches bare issue keys like CRA-123"
}
]
}
AutoLabelRule 属性
| 属性 | 类型 | 描述 |
|---|---|---|
pattern | string | 必需。 带捕获组的正则表达式。使用 flags(默认:gi)。 |
flags | string | 正则表达式标志(默认:gi — 全局、不区分大小写)。g 始终强制执行。 |
valueTemplate | string | 使用 $1、$2 进行捕获组替换的模板。如果省略,使用第一个捕获组。 |
description | string | 人类可读的此规则匹配内容的描述。 |
正则表达式模式
规则使用带捕获组的 JavaScript 正则表达式:
{
"pattern": "github\\.com/([\\w-]+/[\\w-]+)/pull/(\\d+)",
"valueTemplate": "$1#$2",
"description": "Matches GitHub PR URLs"
}
- 全局匹配:
g标志始终强制执行,因此会找到消息中的所有出现 - 捕获组:
$1、$2等在valueTemplate中被匹配的组替换 - 多个匹配:"CRA-1 and CRA-2" 在同一标签上产生两个标签条目
- 代码块剥离:围栏代码块和内联代码中的内容被忽略
值标准化
提取的值根据标签的 valueType 进行标准化:
| valueType | 原始捕获 | 标准化后 |
|---|---|---|
string | CRA-123 | CRA-123(直接传递) |
number | $45,000 | 45000(去除符号 + 逗号) |
number | 1.5M | 1500000(展开后缀) |
number | 50k | 50000(展开后缀) |
date | 2026-01-30 | 2026-01-30(直接传递) |
评估行为
- 时机:当用户消息发送时评估规则(新消息和排队消息)
- 仅用户消息:不扫描助手输出和工具结果
- 代码剥离:评估前剥离围栏代码块和内联代码
- 去重:相同的标签+值不会被添加到会话两次
- 匹配限制:每条消息最多 10 个匹配(防止粘贴数据导致标签爆炸)
- 持久性:自动应用的标签存储在会话上
- 多个规则:标签上的所有规则都会被评估;收集所有匹配
- 验证:在配置保存时验证模式(无效的正则表达式和 ReDoS 模式被拒绝)
- 错误处理:无效的正则表达式模式在运行时被跳过(记录为警告)
完整示例
一个自动标记 Linear 问题、截止日期、联系人和预算的工作区:
{
"version": 1,
"labels": [
{
"id": "linear-issue",
"name": "Linear Issue",
"color": "purple",
"valueType": "string",
"autoRules": [
{ "pattern": "linear\\.app/[\\w-]+/issue/([A-Z]+-\\d+)", "valueTemplate": "$1", "description": "Linear URLs" },
{ "pattern": "\\b([A-Z]{2,5}-\\d+)\\b", "valueTemplate": "$1", "description": "Bare issue keys" }
]
},
{
"id": "deadline",
"name": "Deadline",
"color": "orange",
"valueType": "date",
"autoRules": [
{ "pattern": "(\\d{4}-\\d{2}-\\d{2}(?:T\\d{2}:\\d{2})?)", "valueTemplate": "$1", "description": "ISO dates" }
]
},
{
"id": "contact",
"name": "Contact",
"color": "blue",
"valueType": "string",
"autoRules": [
{ "pattern": "([\\w.+-]+@[\\w.-]+\\.[a-zA-Z]{2,})", "valueTemplate": "$1", "description": "Email addresses" }
]
},
{
"id": "budget",
"name": "Budget",
"color": "green",
"valueType": "number",
"autoRules": [
{ "pattern": "\\$([\\d,.]+[kKmMbB]?)", "valueTemplate": "$1", "description": "Dollar amounts" }
]
}
]
}
侧边栏行为
标签在左侧边栏中显示为多级可展开部分:
All Chats (平铺,总数)
Flagged (平铺,标记数)
States (可展开 → 状态子项)
Labels (可展开)
├─ Views (可展开 → 视图子项)
├─ Engineering (标签)
└─ Bug (标签)
────────────
Sources (可展开 → API/MCP/Local)
Skills (平铺)
────────────
Settings (平铺)
点击标签会筛选会话列表。点击父标签会包含标记了任何子孙的会话。
设计决策
- 嵌套 JSON 树:层次结构就是结构本身——无需学习约定
- 数组位置 = 顺序:无需
order字段,数组位置决定显示顺序 - 全局唯一 ID:简单的 slug,在整个树中唯一
- 仅颜色的视觉效果:标签使用彩色圆圈——无图标,保持 UI 简洁一致
- 无类别:标签不影响收件箱/归档筛选(那是状态的用途)
- 无默认值:工作区从零个标签开始
- 无固定标签:所有标签完全由用户控制(可删除、可重命名)
- 多选:会话存储
labels: string[],而非单个值 - 删除级联:删除标签会从会话中移除它和所有子孙
- 最大深度 5:防止过深的层次结构
- 层次化筛选:父标签点击包含所有子孙会话
- 通过
::分隔符的值:简单、扁平的字符串存储——无需更改会话格式的 schema - 解析时的类型推断:解析器始终推断(日期 → 数字 → 字符串),
valueType只是 UI 提示 - 仅日期格式:ISO
YYYY-MM-DD— 无时间组件,避免时区复杂性