Trellis (mindfold-ai) - 完整学习教程
Trellis (mindfold-ai) - 完整学习教程
教程级别: 从零到一 预计学习时间: 4-6 小时 前置知识: 命令行操作、Git 基础、至少一种 AI 编码助手(Claude Code 或 Cursor)的基本使用、Python 基础概念、JSON/YAML 配置文件格式
注意:本教程针对
mindfold-ai/Trellis——面向 AI 编码平台的框架和工具集。与微软的microsoft/TRELLIS(3D 资产生成模型)是完全不同的项目。
环境搭建指南
系统要求
| 项目 | 要求 |
|---|---|
| 操作系统 | macOS、Linux、Windows |
| Node.js | 18+(用于 npm 安装 Trellis CLI) |
| Python | 3.8+(Hook 脚本执行) |
| Git | 2.5+(并行会话需要 Git Worktree 支持) |
| AI 编码平台 | 至少安装一种:Claude Code、Cursor、OpenCode 等 |
安装步骤
# 第一步:全局安装 Trellis CLI
npm install -g @mindfoldhq/trellis@latest
# 第二步:验证安装
trellis --version
执行结果:
0.3.6
# 第三步:进入你的项目目录(如果还没有项目,先创建一个)
mkdir my-project && cd my-project
git init
# 第四步:初始化 Trellis(-u 指定你的用户名)
trellis init -u developer-name
# 如果团队使用多个 AI 编码平台,同时初始化多平台支持
trellis init --cursor --opencode --codex -u developer-name
执行结果:
✓ Trellis initialized for project: my-project
✓ Created .trellis/ directory structure
✓ Created .claude/ directory structure
✓ Generated Hook configurations
✓ Welcome, developer-name!
验证安装
# 验证 Trellis 目录结构是否正确生成
ls -la .trellis/
# 验证 Hook 配置是否正确生成
cat .claude/settings.json | python3 -m json.tool
执行结果:
# ls 输出
drwxr-xr-x workflow.md
drwxr-xr-x spec/
drwxr-xr-x workspace/
drwxr-xr-x tasks/
drwxr-xr-x scripts/
# settings.json 输出(简化)
{
"hooks": {
"SessionStart": [...],
"PreToolUse": [...],
"PostToolUse": [...],
"SubagentStop": [...]
}
}
注意事项:
- 确保项目已经初始化了 Git 仓库(git init),Trellis 依赖 Git 进行版本管理和并行会话。
- 如果 trellis 命令未找到,检查 npm 全局安装路径是否在 PATH 中。运行 npm config get prefix 查看全局安装路径。
- Python 环境需要可执行。Hook 脚本通过 python 或 python3 命令调用,确保系统中有可用的 Python 解释器。
第一部分:入门篇
1.1 理解 Trellis 的核心概念——为什么需要 Hook 注入
概念讲解:
使用 AI 编码助手(如 Claude Code)时,传统做法是在项目根目录创建 CLAUDE.md 或 .cursorrules 文件,写入编码规范和项目约定。问题是:AI 可能不读取或不遵守这些文件中的指令。
想象你在管理一个建筑工地。你把施工规范写在一本手册里放在工地上,希望每个工人都去读。但有些工人可能不读,或者读了一半就忘了。Trellis 的解决方案是:不依赖工人自觉阅读,而是在每个工人进场时,把规范直接"注入"到他们的工作指南中。
这就是 Hook 强制注入的核心思想:
- 传统方式:
CLAUDE.md/.cursorrules→ AI"可选"读取 → 可能忽略 - Trellis 方式:Hook 在特定事件触发时 → 自动执行脚本 → 将规范强制注入到 AI 上下文
代码示例: 查看 Hook 如何在会话启动时注入规范
# 查看项目初始化后生成的 Hook 配置
cat .claude/settings.json
{
"hooks": {
"SessionStart": [{
"command": "python .claude/hooks/session-start.py",
"timeout": 30
}],
"PreToolUse": [{
"command": "python .claude/hooks/inject-subagent-context.py",
"matcher": "Agent"
}],
"PostToolUse": [{
"command": "python .claude/hooks/sync-workspace.py"
}],
"SubagentStop": [{
"command": "python .claude/hooks/ralph-loop.py",
"matcher": "check"
}]
}
}
# 查看 session-start.py 脚本的内容(了解它做了什么)
head -30 .claude/hooks/session-start.py
执行结果:
# session-start.py 的核心逻辑:读取 workflow.md 和 workspace 上下文,
# 将它们作为 Hook 输出注入到当前 AI 会话中。
# 当你启动 Claude Code 时,这个脚本自动执行,
# workflow.md 中的规范就被加载到 AI 的上下文窗口中。
练习题:
1. 打开 .trellis/workflow.md 文件,查看其中包含的内容。思考:这些内容如果写在 CLAUDE.md 中,AI 是否一定会读取?Trellis 通过 Hook 注入后有什么不同?
2. 尝试修改 workflow.md 中的一段文字,然后在 Claude Code 中开启新会话,观察 AI 是否使用了你修改后的内容。
1.2 理解项目结构——Trellis 的文件系统
概念讲解:
Trellis 初始化后在项目中创建两个核心目录:
.trellis/:团队共享的项目配置,包含规范、任务和工作空间。这个目录应该提交到 Git,团队成员共享。.claude/:Claude Code 平台的配置,包含 Agent 定义、Hook 脚本和斜杠命令。部分内容需要提交到 Git。
.trellis/ ← 团队共享(提交到 Git)
├── workflow.md # 工作流指南——启动时自动注入
├── worktree.yaml # 多 Agent 并行配置
├── spec/ # 规范库——核心!
│ ├── frontend/ # 前端规范(React 组件模式、CSS 约定等)
│ ├── backend/ # 后端规范(API 设计、数据库模式等)
│ └── guides/ # 决策与分析框架
├── workspace/{your-name}/ # 个人工作日志(.gitignore)
├── tasks/ # 任务状态文件(task.json)
└── scripts/ # 工具脚本
.claude/ ← 平台配置
├── settings.json # Hook 注册配置
├── agents/ # Agent 角色定义
│ ├── dispatch.md # 调度 Agent——纯路由,不读规范
│ ├── implement.md # 实现 Agent——执行编码
│ ├── check.md # 检查 Agent——质量验证
│ └── research.md # 研究 Agent——调研分析
├── commands/ # 斜杠命令
│ └── trellis/ # Trellis 专用命令
└── hooks/ # Hook 脚本
├── session-start.py # 会话启动 → 注入上下文
├── inject-subagent-context.py # Agent 调用 → 注入规范
└── ralph-loop.py # Agent 停止 → 质量检查
代码示例: 查看目录结构
# 查看 Trellis 生成的完整目录结构
find .trellis -type f | head -20
find .claude -type f | head -20
执行结果:
# .trellis 目录
.trellis/workflow.md
.trellis/spec/frontend/.gitkeep
.trellis/spec/backend/.gitkeep
.trellis/spec/guides/.gitkeep
.trellis/workspace/developer-name/.gitkeep
.trellis/tasks/.gitkeep
# .claude 目录
.claude/settings.json
.claude/agents/dispatch.md
.claude/agents/implement.md
.claude/agents/check.md
.claude/agents/research.md
.claude/hooks/session-start.py
.claude/hooks/inject-subagent-context.py
.claude/hooks/ralph-loop.py
练习题:
1. 阅读 .claude/agents/dispatch.md 文件,理解 Dispatch Agent 的职责。为什么它是"纯路由"?
2. 阅读 .claude/agents/implement.md 文件,理解 Implement Agent 在执行编码任务时会遵循哪些规则。
1.3 第一次使用——编写你的第一个 Spec
概念讲解:
Spec(规范)是 Trellis 的核心。一个 Spec 是一个 Markdown 文件,描述了项目中某个方面的编码规范。例如:API 端点命名规范、错误处理模式、React 组件结构等。
Spec 写在 .trellis/spec/ 目录下,按类别组织:
- frontend/:前端相关规范
- backend/:后端相关规范
- shared/:前后端共享规范
- guides/:决策框架和分析指南
代码示例: 创建你的第一个 Spec
# 创建共享规范目录(如果不存在)
mkdir -p .trellis/spec/shared
# 创建一个错误处理规范
cat > .trellis/spec/shared/error-handling.md << 'EOF'
# 错误处理规范
## API 错误响应格式
所有 REST API 端点必须使用统一的错误响应格式:
```json
{
"code": "ERROR_CODE_NAME",
"message": "面向用户的错误描述",
"details": {}
}
错误码命名规范
- 使用大写蛇形命名法(UPPER_SNAKE_CASE)
- 格式:
{模块}_{错误类型},例如USER_NOT_FOUND、ORDER_INVALID_STATUS - 禁止使用模糊的错误码(如
ERROR、FAIL)
HTTP 状态码映射
- 400:请求参数错误(
PARAM_MISSING、PARAM_INVALID) - 401:未认证(
AUTH_REQUIRED) - 403:无权限(
PERMISSION_DENIED) - 404:资源不存在(
RESOURCE_NOT_FOUND) - 500:服务器内部错误(
INTERNAL_ERROR)
禁止事项
- 禁止直接抛出原始异常(raw exception)给前端
- 禁止在错误响应中暴露堆栈跟踪或内部实现细节
- 禁止使用 HTTP 200 返回错误信息(必须使用正确的错误状态码) EOF
echo "错误处理规范已创建"
**执行结果:**
错误处理规范已创建
**练习题:**
1. 再创建一个后端规范文件 `.trellis/spec/backend/api-design.md`,定义 REST API 的 URL 命名规范(如使用复数名词、嵌套资源表示等)。
2. 创建一个前端规范文件 `.trellis/spec/frontend/component-patterns.md`,定义 React 组件的文件结构和命名约定。
---
## 第二部分:进阶篇
### 2.1 JSONL 规范控制——让每种 Agent 只看它需要的规范
**详细讲解:**
上节我们创建了多个 Spec 文件。但问题是:如果项目有 50 个 Spec 文件,全部加载会占用大量上下文窗口。Trellis 的解决方案是 **JSONL 规范控制**——每种 Agent 角色有一个 `.jsonl` 文件,精确指定该 Agent 需要加载哪些 Spec。
这是一个 JSONL 文件(每行一个 JSON 对象),包含两个字段:
- `file`:Spec 文件的路径
- `reason`:为什么要注入这个 Spec(给 AI 提供上下文说明)
**代码示例:** 配置 Implement Agent 的规范注入
```bash
# 创建 Implement Agent 的 JSONL 控制文件
cat > .claude/agents/implement.jsonl << 'EOF'
{"file": ".trellis/spec/backend/api-design.md", "reason": "REST API URL 命名规范"}
{"file": ".trellis/spec/shared/error-handling.md", "reason": "错误处理和错误码规范"}
EOF
# 创建 Check Agent 的 JSONL 控制文件
# Check Agent 需要验证错误处理规范是否被正确遵循
cat > .claude/agents/check.jsonl << 'EOF'
{"file": ".trellis/spec/shared/error-handling.md", "reason": "验证错误处理规范是否被遵循"}
{"file": ".claude/commands/trellis/finish-work.md", "reason": "Lint 检查"}
{"file": ".claude/commands/trellis/finish-work.md", "reason": "TypeCheck 检查"}
EOF
echo "JSONL 控制文件已创建"
执行结果:
JSONL 控制文件已创建
验证 JSONL 文件格式:
# 验证 JSONL 格式是否正确(每行必须是合法 JSON)
python3 -c "
import json, sys
for i, line in enumerate(open('.claude/agents/implement.jsonl'), 1):
try:
obj = json.loads(line.strip())
print(f'第 {i} 行: ✓ file={obj[\"file\"]}, reason={obj[\"reason\"]}')
except json.JSONDecodeError as e:
print(f'第 {i} 行: ✗ JSON 格式错误: {e}')
sys.exit(1)
print('所有行格式正确!')
"
执行结果:
第 1 行: ✓ file=.trellis/spec/backend/api-design.md, reason=REST API URL 命名规范
第 2 行: ✓ file=.trellis/spec/shared/error-handling.md, reason=错误处理和错误码规范
所有行格式正确!
注意事项:
- JSONL 文件中每行必须是独立的合法 JSON 对象,不能有多余的逗号或换行。
- file 路径是相对于项目根目录的路径,确保文件确实存在。
- reason 字段帮助 AI 理解为什么这个规范被注入,写清楚原因有助于 AI 更好地遵从规范。
- 如果 Spec 文件路径不存在,Hook 脚本执行时会跳过该条目并输出警告日志。
练习题:
1. 为 Research Agent 创建 research.jsonl 文件,指定它需要加载的规范(如分析框架和决策指南)。
2. 故意在 implement.jsonl 中写入一个不存在的文件路径,观察 Hook 脚本执行时的行为。
2.2 规范渐进披露——根据任务类型过滤规范
详细讲解:
上一节我们配置了每种 Agent 应该加载哪些规范。但还有更精细的需求:同一个 Agent 执行不同类型的任务时,应该加载不同的规范子集。
例如,Implement Agent 执行前端任务时,不需要加载后端 Java 规范;执行后端任务时,不需要加载 React 组件规范。这就是规范渐进披露(Spec Progressive Disclosure)。
Trellis 通过 _SPEC_MAP 实现这个过滤。_SPEC_MAP 定义了任务类型与规范类别的映射关系:
# _SPEC_MAP 核心逻辑(概念代码)
_SPEC_MAP = {
"frontend": {"frontend", "shared", "guides"}, # 前端任务:只加载前端+共享+指南
"backend": {"backend-java", "shared", "cross-service", "guides"}, # 后端任务:只加载后端+共享+跨服务+指南
"fullstack": None, # 全栈任务:加载所有规范(None 表示不过滤)
}
工作原理:
1. Dispatch Agent 分析任务类型(frontend/backend/fullstack)
2. PreToolUse Hook 触发,读取任务类型
3. inject-subagent-context.py 根据 _SPEC_MAP 过滤 .jsonl 中的规范列表
4. 只有与任务类型匹配的规范被注入到 AI 上下文中
代码示例: 创建按类别组织的规范体系
# 创建前端规范
mkdir -p .trellis/spec/frontend
cat > .trellis/spec/frontend/component-patterns.md << 'EOF'
# React 组件规范
## 文件结构
每个 React 组件必须遵循以下文件结构:
components/ ├── Button/ │ ├── Button.tsx # 组件实现 │ ├── Button.test.tsx # 单元测试 │ ├── Button.module.css # 样式(使用 CSS Modules) │ └── index.ts # 导出
## 命名规范
- 组件文件名:PascalCase(如 `UserProfile.tsx`)
- 样式文件:`*.module.css`(必须使用 CSS Modules)
- 测试文件:`*.test.tsx`
## 禁止事项
- 禁止使用 inline styles
- 禁止在组件中直接调用 API(必须通过自定义 Hook)
EOF
# 创建后端规范(Java 示例)
mkdir -p .trellis/spec/backend
cat > .trellis/spec/backend/service-layer.md << 'EOF'
# Service 层规范
## 四层架构
所有后端接口必须遵循以下四层架构:
Controller → ServiceImpl → Manager → Dao
- **Controller**:只负责参数校验和响应封装,不含业务逻辑
- **ServiceImpl**:业务逻辑编排,事务管理
- **Manager**:通用业务封装,可被多个 ServiceImpl 复用
- **Dao**:数据访问层,只做数据库操作
## 禁止事项
- 禁止在 Controller 中编写业务逻辑
- 禁止在 ServiceImpl 中直接拼接 SQL
- 禁止跨层级调用(如 Controller 直接调用 Dao)
EOF
# 创建跨服务规范(微服务架构)
mkdir -p .trellis/spec/cross-service
cat > .trellis/spec/cross-service/api-contract.md << 'EOF'
# 跨服务 API 契约规范
## 接口变更原则
- 任何接口字段的修改(新增、删除、类型变更)必须通知下游服务
- 使用 Proto/GRPC 定义服务间契约
- 禁止直接修改已发布的 Proto 字段类型(必须新增字段)
## 影响分析
修改接口前,使用 GitNexus 分析下游服务影响范围。
EOF
echo "规范体系创建完成"
执行结果:
规范体系创建完成
验证规范类别划分:
# 查看当前规范目录结构,验证类别划分
find .trellis/spec -name "*.md" -type f | sort
执行结果:
.trellis/spec/backend/api-design.md
.trellis/spec/backend/service-layer.md
.trellis/spec/cross-service/api-contract.md
.trellis/spec/frontend/component-patterns.md
.trellis/spec/shared/error-handling.md
注意事项:
- 规范目录名称(如 frontend、backend、shared)需要与 _SPEC_MAP 中的类别名称对应。
- shared 目录下的规范会被前端和后端任务共同加载,放置两个领域都需要的通用规范。
- 如果项目没有微服务架构,可以不需要 cross-service 目录。
- fullstack 任务类型会加载所有规范,适用于涉及前后端同时修改的任务。
练习题:
1. 更新 implement.jsonl,添加新创建的前端和后端规范条目。然后思考:当任务类型为 frontend 时,哪些条目会被过滤掉?
2. 创建一个 guides/ 目录下的决策框架文件(如 api-versioning-guide.md),说明 API 版本迁移的决策流程。
2.3 四种 Agent 角色——理解分工协作
详细讲解:
Trellis 定义了四种专用 Agent,每种有明确的职责和规范注入策略。理解这四种角色的分工是使用 Trellis 的关键。
| Agent | 职责 | 规范注入 | 类比 |
|---|---|---|---|
| Dispatch | 接收任务,分析类型,调度子 Agent | 不注入任何规范(纯路由) | 项目经理 |
| Implement | 执行编码任务 | 通过 implement.jsonl 注入编码规范 |
开发工程师 |
| Check | 执行质量检查,输出完成标记 | 通过 check.jsonl 注入质量标准 |
质量工程师 |
| Research | 执行技术调研和代码分析 | 通过 research.jsonl 注入分析框架 |
技术顾问 |
关键设计:Dispatch Agent 是"纯路由"。它不读取任何规范,只负责分析任务类型并调度对应的子 Agent。所有上下文注入由 Hook 系统管理。这样设计的好处是:Dispatch Agent 的上下文窗口不被规范占用,全部用于任务分析和调度决策。
代码示例: 查看 Agent 定义文件
# 查看 Dispatch Agent 的定义
cat .claude/agents/dispatch.md
# Dispatch Agent
你是一个任务调度 Agent。你的职责是:
1. 接收用户的任务请求
2. 分析任务类型(frontend / backend / fullstack / research)
3. 调度对应的子 Agent 执行任务
## 调度规则
- 编码任务 → 调度 Implement Agent,完成后调度 Check Agent
- 调研任务 → 调度 Research Agent
- 不要自己执行任何编码或分析工作
- 不要读取任何规范文件(你的上下文由 Hook 管理)
## 任务状态更新
每次调度后,更新 `.trellis/tasks/task.json` 中的任务状态。
# 查看 Check Agent 的定义(关注完成标记机制)
cat .claude/agents/check.md
# Check Agent
你是一个质量检查 Agent。你的职责是:
1. 验证代码实现是否符合项目规范
2. 执行类型检查,完成后输出 `TYPECHECK_FINISH`
3. 执行代码检查(Lint),完成后输出 `LINT_FINISH`
4. 如果发现问题,修复后重新检查
## 完成标记
当你完成所有检查后,必须在输出中包含以下标记:
- `TYPECHECK_FINISH` — 类型检查通过
- `LINT_FINISH` — 代码检查通过
这些标记会被 Ralph Loop 验证。缺少标记将阻止你完成任务。
执行结果:
(显示上述 Markdown 文件内容)
练习题:
1. 阅读所有四种 Agent 的 .md 定义文件,对比它们的职责差异。思考:为什么 Dispatch 不注入任何规范?
2. 尝试修改 check.md,添加一个新的完成标记(如 TEST_FINISH),要求 Check Agent 在测试通过后输出该标记。
第三部分:高级篇
3.1 Ralph Loop 质量控制——确保 AI 不"偷懒"
详细讲解:
Ralph Loop 是 Trellis 最独特的质量保障机制。问题背景:AI 编码助手可能声称"已完成"任务,但实际未执行所有检查步骤。例如,Check Agent 说"代码检查通过",但没有真正运行 Lint。
Ralph Loop 的工作流程:
- Check Agent 执行检查任务,在输出中包含完成标记(如
TYPECHECK_FINISH、LINT_FINISH) - Check Agent 尝试停止(触发 SubagentStop Hook)
ralph-loop.py脚本执行,扫描 Agent 的输出是否包含所有要求的完成标记- 如果所有标记都存在 → 允许 Agent 停止
- 如果有标记缺失 → 阻止停止,返回缺失标记列表 → Agent 继续修复 → 重新触发检查
- 最多循环 N 次(防止无限循环)
代码示例: 配置 Ralph Loop 的完成标记
# 更新 check.jsonl,定义 Check Agent 需要验证的规范和对应标记
cat > .claude/agents/check.jsonl << 'EOF'
{"file": ".trellis/spec/shared/error-handling.md", "reason": "验证错误处理规范"}
{"file": ".trellis/spec/backend/service-layer.md", "reason": "验证四层架构规范"}
{"file": ".claude/commands/trellis/finish-work.md", "reason": "Lint"}
{"file": ".claude/commands/trellis/finish-work.md", "reason": "TypeCheck"}
EOF
echo "Ralph Loop 完成标记配置已更新"
执行结果:
Ralph Loop 完成标记配置已更新
Ralph Loop 验证逻辑(概念代码):
# ralph-loop.py 的核心验证逻辑(概念代码,理解工作原理)
import sys
def check_completion_markers(agent_output, required_markers):
"""检查 Agent 输出是否包含所有要求的完成标记"""
missing = []
for marker in required_markers:
if marker not in agent_output:
missing.append(marker)
if missing:
# 有标记缺失 → 阻止停止,返回缺失信息
print(f"BLOCK: 以下完成标记缺失: {', '.join(missing)}")
print("请继续执行相关检查并输出对应标记。")
sys.exit(2) # 非零退出码阻止 Agent 停止
else:
# 所有标记存在 → 允许停止
print("APPROVE: 所有完成标记验证通过。")
sys.exit(0)
# 要求的完成标记来自 check.jsonl 中的 reason 字段
required_markers = ["TYPECHECK_FINISH", "LINT_FINISH"]
注意事项:
- 完成标记的名称是在 check.jsonl 的 reason 字段中定义的,确保标记名称在 check.md 和 ralph-loop.py 之间一致。
- Ralph Loop 有最大迭代次数限制,防止 Check Agent 无法修复问题时的无限循环。如果达到最大次数仍有标记缺失,Agent 会被强制停止并报告未通过的检查。
- 完成标记应该是唯一的、不会在普通文本中意外出现的字符串(如 TYPECHECK_FINISH 而不是 done)。
练习题:
1. 在 check.jsonl 中添加一个新的条目,要求 Check Agent 验证 API 设计规范,并输出 API_CHECK_FINISH 标记。
2. 思考:如果 Check Agent 的输出中包含了 TYPECHECK_FINISH 字符串但实际没有运行类型检查,Ralph Loop 能检测到吗?这说明了什么?
3.2 Git Worktree 并行会话——让多个 Agent 同时工作
详细讲解:
当团队有多个独立任务需要同时处理时,单个 AI 会话串行执行效率太低。Trellis 基于 Git Worktree 实现多 Agent 并行执行。
Git Worktree 允许同一个仓库同时拥有多个工作目录,每个目录对应不同的分支。Trellis 为每个并行 Agent 创建一个独立的 worktree,Agent 在自己的 worktree 中工作,完成后合并回主分支。
代码示例: 配置并行会话
# 查看 worktree 配置文件
cat .trellis/worktree.yaml
# .trellis/worktree.yaml
# 定义并行会话配置
sessions:
- name: "feature-auth"
task: "实现用户认证模块"
branch: "feature/auth"
- name: "feature-order-api"
task: "实现订单 API 模块"
branch: "feature/order-api"
# 查看当前 Git Worktree 状态
git worktree list
执行结果:
/Users/developer/my-project abc1234 [main]
并行会话的工作流程(概念说明):
# 步骤 1:创建 worktree 用于并行 Agent
git worktree add .trellis/worktrees/feature-auth feature/auth
# 步骤 2:在独立 worktree 中启动 Agent(概念命令)
# Trellis 会自动管理这个过程
# 每个 Agent 在自己的 worktree 中独立工作
# 步骤 3:Agent 完成后合并
git checkout main
git merge feature/auth
git worktree remove .trellis/worktrees/feature-auth
注意事项:
- 并行任务之间不能有依赖关系。如果任务 B 依赖任务 A 的输出,它们必须串行执行。
- Worktree 目录在 .gitignore 中应被忽略,不要提交到版本控制。
- 合并时可能产生冲突,需要人工或 AI 辅助解决。
- 并行 Agent 数量受限于 AI 编码平台的并发会话能力和 GPU/API 配额。
练习题:
1. 使用 git worktree add 手动创建一个 worktree,在其中做一次代码修改,然后合并回主分支。这有助于理解 Trellis 并行会话的底层机制。
2. 思考:如果两个并行 Agent 修改了同一个文件的不同位置,合并时会发生什么?
3.3 任务生命周期管理——从创建到完成
详细讲解:
Trellis 将 AI 编码从"自由对话"转变为"任务驱动"。每个任务有明确的状态、类型和执行阶段,持久化在 .trellis/tasks/task.json 中。
任务状态流转:
pending → in_progress → completed
↓
in_progress (Check 阶段)
任务阶段(next_action):
[
{"phase": 1, "action": "implement"}, // 阶段 1:实现
{"phase": 2, "action": "check"}, // 阶段 2:检查
{"phase": 3, "action": "finish"} // 阶段 3:完成
]
代码示例: 查看和操作任务状态
# 查看当前任务列表
ls .trellis/tasks/
执行结果:
task.json
# 查看任务状态
cat .trellis/tasks/task.json
{
"title": "实现用户注册 API",
"status": "in_progress",
"dev_type": "backend",
"current_phase": 1,
"next_action": [
{"phase": 1, "action": "implement"},
{"phase": 2, "action": "check"},
{"phase": 3, "action": "finish"}
],
"created_at": "2026-04-04T10:00:00Z",
"updated_at": "2026-04-04T10:30:00Z"
}
注意事项:
- task.json 记录了任务的完整状态,支持跨会话恢复。如果 AI 会话意外中断,下次启动时可以从当前阶段继续。
- dev_type 字段决定了规范渐进披露的过滤规则(frontend/backend/fullstack),确保正确设置。
- current_phase 和 next_action 数组配合使用,Dispatch Agent 根据当前阶段调度对应的子 Agent。
练习题:
1. 手动创建一个 task.json 文件,定义一个前端任务(dev_type: "frontend")。思考:这个任务会加载哪些规范?不会加载哪些?
2. 思考跨会话恢复的场景:如果在 Implement 阶段会话中断,下次启动时 Trellis 如何知道应该继续实现而不是重新开始?
3.4 最佳实践
-
Spec 编写原则:每个 Spec 文件应该聚焦于一个主题(如"错误处理"、"API 设计"、"组件模式"),不要在一个文件中混合多个不相关的主题。文件名使用小写连字符命名(如
error-handling.md、api-design.md)。 -
JSONL 维护原则:每次新增或删除 Spec 文件时,同步更新对应的
.jsonl文件。可以编写简单的验证脚本确保.jsonl中引用的文件都存在。 -
完成标记设计原则:标记名称应该具有描述性(如
TYPECHECK_FINISH而非DONE1),避免在普通文本中意外出现。 -
团队协作原则:
.trellis/目录应提交到 Git,确保所有团队成员共享同一套规范。.trellis/workspace/目录应添加到.gitignore(个人工作日志不需要共享)。 -
版本管理原则:Trellis 当前处于 v0.x 版本,API 可能变化。在
.trellis/目录中添加版本标记文件,升级前在测试项目中验证兼容性。
第四部分:实战项目
项目需求
构建一个 Trellis 规范验证工具,实现以下功能:
- 扫描
.trellis/spec/目录下所有规范文件 - 验证 JSONL 控制文件中引用的规范是否存在
- 检查完成标记的一致性(check.jsonl 中的标记是否在 check.md 中定义)
- 生成验证报告
本项目的知识点覆盖: - 1.2 节:Trellis 目录结构和文件组织 - 2.1 节:JSONL 规范控制文件的格式和作用 - 3.1 节:Ralph Loop 完成标记机制
项目设计
trellis-validator/
├── validate.py # 主脚本:验证逻辑
├── README.md # 使用说明
└── .trellis/ # 测试用的 Trellis 配置
├── spec/ # 测试规范文件
└── ...
完整实现代码
# validate.py —— Trellis 规范验证工具
# 验证 Spec 文件完整性、JSONL 引用有效性和完成标记一致性
import json
import os
import sys
from pathlib import Path
def find_project_root():
"""查找项目根目录(包含 .trellis/ 的目录)"""
current = Path.cwd()
while current != current.parent:
if (current / ".trellis").exists():
return current
current = current.parent
return None
def scan_spec_files(project_root):
"""扫描 .trellis/spec/ 目录下所有规范文件"""
# 知识点 1.2:理解 Trellis 目录结构
spec_dir = project_root / ".trellis" / "spec"
if not spec_dir.exists():
print(f"错误:规范目录不存在: {spec_dir}")
return {}
# 按类别收集规范文件
spec_by_category = {}
for md_file in sorted(spec_dir.rglob("*.md")):
# 类别是 spec/ 下的第一级子目录名
relative = md_file.relative_to(spec_dir)
category = str(relative.parts[0]) if len(relative.parts) > 1 else "root"
if category not in spec_by_category:
spec_by_category[category] = []
spec_by_category[category].append(str(md_file.relative_to(project_root)))
return spec_by_category
def validate_jsonl_references(project_root):
"""验证 JSONL 文件中引用的规范文件是否存在"""
# 知识点 2.1:JSONL 规范控制文件的格式和作用
agents_dir = project_root / ".claude" / "agents"
results = {"valid": [], "missing": [], "parse_errors": []}
if not agents_dir.exists():
print("警告:.claude/agents/ 目录不存在")
return results
for jsonl_file in sorted(agents_dir.glob("*.jsonl")):
with open(jsonl_file, "r", encoding="utf-8") as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
if not line:
continue
try:
entry = json.loads(line)
spec_path = project_root / entry["file"]
if spec_path.exists():
results["valid"].append({
"jsonl": str(jsonl_file.name),
"line": line_num,
"file": entry["file"],
"reason": entry["reason"]
})
else:
results["missing"].append({
"jsonl": str(jsonl_file.name),
"line": line_num,
"file": entry["file"],
"reason": entry["reason"]
})
except json.JSONDecodeError as e:
results["parse_errors"].append({
"jsonl": str(jsonl_file.name),
"line": line_num,
"error": str(e)
})
return results
def check_completion_markers(project_root):
"""检查完成标记的一致性"""
# 知识点 3.1:Ralph Loop 完成标记机制
check_jsonl = project_root / ".claude" / "agents" / "check.jsonl"
check_md = project_root / ".claude" / "agents" / "check.md"
results = {"markers_in_jsonl": [], "markers_in_md": [], "inconsistent": []}
if not check_jsonl.exists():
print("警告:check.jsonl 不存在,跳过完成标记检查")
return results
# 从 check.jsonl 提取标记
markers_from_jsonl = set()
with open(check_jsonl, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
entry = json.loads(line)
reason = entry.get("reason", "").upper()
# 常见标记关键词
for keyword in ["LINT", "TYPECHECK", "TEST", "CHECK"]:
if keyword in reason:
marker = f"{keyword}_FINISH"
markers_from_jsonl.add(marker)
results["markers_in_jsonl"].append({
"marker": marker,
"source": entry["file"]
})
except json.JSONDecodeError:
pass
# 从 check.md 提取标记
markers_from_md = set()
if check_md.exists():
with open(check_md, "r", encoding="utf-8") as f:
content = f.read()
for keyword in ["LINT_FINISH", "TYPECHECK_FINISH", "TEST_FINISH", "CHECK_FINISH"]:
if keyword in content:
markers_from_md.add(keyword)
results["markers_in_md"].append({"marker": keyword})
# 检查一致性
jsonl_only = markers_from_jsonl - markers_from_md
md_only = markers_from_md - markers_from_jsonl
for marker in jsonl_only:
results["inconsistent"].append({
"marker": marker,
"issue": "标记在 check.jsonl 中引用,但未在 check.md 中定义"
})
for marker in md_only:
results["inconsistent"].append({
"marker": marker,
"issue": "标记在 check.md 中定义,但未在 check.jsonl 中引用"
})
return results
def generate_report(spec_results, jsonl_results, marker_results):
"""生成验证报告"""
print("=" * 60)
print("Trellis 规范验证报告")
print("=" * 60)
# 1. Spec 文件扫描结果
print("\n📋 Spec 文件扫描结果:")
total_specs = sum(len(files) for files in spec_results.values())
print(f" 共发现 {total_specs} 个规范文件,分布在 {len(spec_results)} 个类别中")
for category, files in spec_results.items():
print(f" - {category}/:{len(files)} 个文件")
for f in files:
print(f" {f}")
# 2. JSONL 引用验证结果
print(f"\n🔗 JSONL 引用验证结果:")
print(f" ✓ 有效引用:{len(jsonl_results['valid'])} 个")
print(f" ✗ 缺失文件:{len(jsonl_results['missing'])} 个")
print(f" ✗ 格式错误:{len(jsonl_results['parse_errors'])} 个")
for item in jsonl_results["missing"]:
print(f" ⚠ [{item['jsonl']}:L{item['line']}] 文件不存在: {item['file']} (原因: {item['reason']})")
for item in jsonl_results["parse_errors"]:
print(f" ⚠ [{item['jsonl']}:L{item['line']}] JSON 格式错误: {item['error']}")
# 3. 完成标记一致性检查
print(f"\n🏷 完成标记一致性检查:")
print(f" check.jsonl 中的标记:{[m['marker'] for m in marker_results['markers_in_jsonl']]}")
print(f" check.md 中的标记:{[m['marker'] for m in marker_results['markers_in_md']]}")
if marker_results["inconsistent"]:
print(f" ⚠ 发现 {len(marker_results['inconsistent'])} 个不一致:")
for item in marker_results["inconsistent"]:
print(f" - {item['marker']}: {item['issue']}")
else:
print(" ✓ 所有完成标记一致")
# 4. 总结
issues_count = (
len(jsonl_results["missing"])
+ len(jsonl_results["parse_errors"])
+ len(marker_results["inconsistent"])
)
print(f"\n{'=' * 60}")
if issues_count == 0:
print("✅ 验证通过!所有配置正确。")
else:
print(f"❌ 发现 {issues_count} 个问题,请修复后重新验证。")
print(f"{'=' * 60}")
def main():
"""主入口"""
# 知识点 1.2:定位项目根目录
project_root = find_project_root()
if project_root is None:
print("错误:未找到 .trellis/ 目录。请在 Trellis 项目根目录中运行此脚本。")
sys.exit(1)
print(f"项目根目录: {project_root}")
# 知识点 1.2:扫描规范文件
spec_results = scan_spec_files(project_root)
# 知识点 2.1:验证 JSONL 引用
jsonl_results = validate_jsonl_references(project_root)
# 知识点 3.1:检查完成标记一致性
marker_results = check_completion_markers(project_root)
# 生成报告
generate_report(spec_results, jsonl_results, marker_results)
if __name__ == "__main__":
main()
代码解析
-
扫描规范文件(知识点 1.2):
scan_spec_files函数递归扫描.trellis/spec/目录,按类别(frontend/backend/shared 等)收集所有 Markdown 规范文件。使用了Path.rglob("*.md")进行文件搜索。 -
验证 JSONL 引用(知识点 2.1):
validate_jsonl_references函数读取所有.jsonl文件,逐行解析 JSON,检查每个file路径是否存在。同时捕获 JSON 格式错误,帮助开发者快速定位配置问题。 -
完成标记一致性(知识点 3.1):
check_completion_markers函数分别从check.jsonl和check.md提取完成标记,交叉验证一致性。如果 JSONL 中引用的标记未在 MD 中定义(或反之),报告为不一致。
扩展挑战
-
添加 Spec 内容验证:检查每个 Spec 文件是否包含必要的章节(如"禁止事项"章节),确保规范的格式统一。提示:使用正则表达式或简单的字符串匹配。
-
添加
_SPEC_MAP验证:验证规范文件的目录分类是否与_SPEC_MAP中定义的类别名称匹配。提示:扫描spec/下的子目录名,与_SPEC_MAP中的集合取交集验证。 -
CI/CD 集成:将验证脚本集成到 GitHub Actions 或 GitLab CI 中,每次提交时自动验证 Trellis 配置的完整性。提示:在 CI 配置文件中添加
python validate.py步骤,非零退出码阻止合并。
第五部分:常见问题与排查指南
常见错误及解决方案
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
trellis: command not found |
npm 全局安装路径不在 PATH 中 | 运行 npm config get prefix 查看路径,将其添加到 PATH:export PATH="$(npm config get prefix)/bin:$PATH" |
Python not found 运行 Hook 时报错 |
系统中 python 命令不可用 |
安装 Python 3 或创建软链接:ln -s /usr/bin/python3 /usr/local/bin/python |
| Hook 脚本执行超时 | session-start.py 超过 30 秒超时 |
检查 workflow.md 文件大小,如果过大考虑拆分。或增大 .claude/settings.json 中的 timeout 值 |
| JSONL 解析错误 | .jsonl 文件中有非法 JSON 行 |
运行 python3 -c "import json; [json.loads(l) for l in open('.claude/agents/implement.jsonl') if l.strip()]" 验证格式 |
| Spec 文件未被注入 | .jsonl 文件中的路径错误或文件不存在 |
检查路径是否相对于项目根目录,确保文件确实存在 |
| Dispatch Agent 读取了规范 | Hook 配置中 matcher 字段缺失 |
确保 .claude/settings.json 中 PreToolUse Hook 的 matcher 设置为 "Agent" |
| Ralph Loop 无限循环 | Check Agent 无法满足检查条件 | 检查完成标记名称是否在 check.md 和 check.jsonl 之间一致。确认最大迭代次数设置合理 |
| Git Worktree 创建失败 | 分支名称冲突或 Git 状态不干净 | 先提交或暂存当前更改(git stash),然后重新创建 worktree |
| 任务状态不一致 | task.json 手动编辑导致格式错误 |
删除 task.json 让 Trellis 重新生成,或使用 JSON 验证工具检查格式 |
| 规范不生效(AI 仍忽略规范) | Hook 未正确注册或脚本无执行权限 | 检查 .claude/settings.json 中 Hook 配置是否正确,确认 .claude/hooks/ 下脚本有执行权限(chmod +x) |
调试技巧
- 手动执行 Hook 脚本排查问题:如果 Hook 不生效,手动运行脚本查看输出和错误信息:
# 手动执行 session-start Hook,查看注入内容
python3 .claude/hooks/session-start.py
# 检查脚本的退出码
echo "退出码: $?"
- 验证 JSONL 文件完整性:批量检查所有 JSONL 文件的格式和引用有效性:
# 一行命令验证所有 JSONL 文件
for f in .claude/agents/*.jsonl; do
echo "=== $f ==="
python3 -c "
import json, sys
errors = 0
for i, line in enumerate(open('$f'), 1):
line = line.strip()
if not line: continue
try:
json.loads(line)
except json.JSONDecodeError as e:
print(f' L{i}: {e}')
errors += 1
print(f' 共 {errors} 个错误' if errors else ' ✓ 格式正确')
"
done
- 查看 Trellis 工作日志:检查
.trellis/workspace/目录下的日志文件,了解 Hook 的执行历史和任务状态变化。
第六部分:学习路线推荐
官方文档推荐阅读顺序
-
Trellis README - 重点关注安装步骤和快速入门,理解 Trellis 的核心定位。GitHub 地址:mindfold-ai/Trellis
-
.trellis/workflow.md- Trellis 初始化后自动生成的工作流指南,在 Claude Code 启动时自动注入。理解 Trellis 的默认工作流设计。 -
.claude/agents/目录 - 逐个阅读四种 Agent 的定义文件(dispatch.md、implement.md、check.md、research.md),理解角色分工。 -
.claude/hooks/目录 - 阅读 Hook 脚本源码,理解 SessionStart、PreToolUse、SubagentStop 三种 Hook 的具体实现。 -
Trellis 官网 - trytrellis.app 查看最新功能介绍和更新日志。
推荐进阶资源
-
Claude Code Hooks 文档 - 深入理解 Claude Code 的原生 Hook API,这是 Trellis 的底层机制。理解 Hook 的事件类型、配置方式和执行模型。
-
Git Worktree 教程 - 掌握 Git Worktree 的基本操作,理解 Trellis 并行会话的底层原理。推荐阅读 Git 官方文档 - git-worktree。
-
MCP(Model Context Protocol) - 了解 Trellis 集成的 MCP 工具(ABCoder、GitNexus、Playwright 等)的工作原理,扩展 Trellis 的能力边界。
相关框架对比学习
-
Superpowers(obra/superpowers)- 对比理解"可选 Skill 加载"与"Hook 强制注入"的设计差异。Superpowers 的 14 个模块化 Skill 提供了另一种 AI 编码增强的思路。
-
BMAD Method(bmad-code-org/BMAD-METHOD)- 对比理解"文档驱动"与"Hook 驱动"的团队协作方式。BMAD 的四阶段敏捷循环提供了完整的方法论参考。
-
Claude Code 原生 Skills - 理解
CLAUDE.md、.claude/commands/等 Claude Code 原生配置机制,评估在哪些场景下原生机制已足够,哪些场景需要 Trellis 的增强能力。