项目目标
创建一个名为 agentdev 的命令行工具,旨在帮助开发者对多个不同的命令行 AI Agent(如 Claude Code, Codex 等)在同一个任务上的表现进行并排的、直观的“体感对比 (vibe eval)”。
核心工作流
- 配置 (Configure): 用户在一个全局配置文件
~/.config/agentdev/config.toml中定义一个“Agent 池”,为每个 Agent 指定一个别名和其完整的启动命令。 - 启动 (Start): 用户通过
agentdev start "<prompt>"来启动一次评测。 - 自动化准备 (Automate): 工具在后台自动为每个已配置的 Agent 执行以下操作:
- 基于一个随机生成的任务名(如
electric-purple-donkey),创建一个独立的git worktree(如electric-purple-donkey-claude)。 - 在该 worktree 内,启动一个分离的
tmux会话,并运行对应的 Agent 命令。 - 通过
tmux send-keys将初始任务指令发送给 Agent,让其开始工作。
- 基于一个随机生成的任务名(如
注:早期版本的终端仪表盘已废弃,现统一使用 Web UI。
- 评估 (Evaluate): 用户运行
agentdev ui,进入一个基于浏览器的仪表盘。- 任务分组: 仪表盘左侧以“任务”为单位对所有 worktree 进行分组展示,形成一个可折叠的树状列表。
- 分层 Diff 预览: 仪表盘右侧的预览窗格会根据用户的选择动态变化:
- 宏观对比: 当用户选中一个任务节点(如
electric-purple-donkey)时,预览区会显示一个合并后的git diff视图,将该任务下所有 Agent 产生的代码变更并排展示,方便快速横向比较。 - 微观审查: 当用户展开任务并选中一个具体的 Agent 节点(如
claude)时,预览区仅显示这一个 Agent 的git diff,方便深入审查其具体方案。
- 宏观对比: 当用户选中一个任务节点(如
- 深入 (Engage): 在仪表盘中,用户可以选中任何一个满意的 Agent,按
Enter键即可无缝附着(attach)到其tmux会话中,继续进行交互式开发。 - 清理 (Clean Up): 任务完成后,用户可运行
agentdev delete-task <task_name>,一键式地、安全地删除与该任务相关的所有 worktree、tmux会话及状态记录。也可以在 dashboard 上用快捷键d删除 task / worktree
技术基础
该项目将作为现有 Rust 项目 xlaude 的一个新功能分支进行开发,以最大化复用其在 git worktree 管理、tmux 交互和 TUI 框架上的成熟能力。
为了实现上述需求,我们将项目分解为以下六个核心任务:
- Task 1: Agent 配置管理: 建立从
config.toml文件加载 Agent 定义的机制。 - Task 2: 状态管理扩展: 改造
xlaude的状态文件结构,引入“任务 (task_id)”概念,以关联多个 worktree。 - Task 3: 实现
agentdev start命令: 构建核心的评测任务启动逻辑,包括批量创建 worktree 和tmux会话。 - Task 4: Dashboard UI 改造: 将
xlaude的扁平列表重构为按任务分组的树状视图。 - Task 5: Dashboard "分层 Diff" 预览功能: 实现仪表盘右侧窗格根据选择层级(任务 vs. Agent)动态显示不同
diff的核心逻辑。 - Task 6: 实现
agentdev delete-task命令: 提供一个便捷的命令来完成整个任务的资源清理。
环境设置
- 创建分支: 从
xlaude项目main分支创建一个新分支feature/agentdev-poc。 - 重命名项目: 在
Cargo.toml中将包名修改为agentdev,确保编译产物为agentdev。
编码步骤
-
Step 1: Agent 配置管理 (Task 1)
- 在
src/config.rs中定义Config和AgentProfile结构体,使用serde和toml进行解析。 - 实现
load_config()函数,该函数会尝试从~/.config/agentdev/config.toml加载配置;若文件不存在,则返回一个包含claude和codex的硬编码默认配置。 - 在项目文档中提供
config.toml的配置示例。
- 在
-
Step 2: 状态管理扩展 (Task 2)
- 修改
src/state.rs中的WorktreeDetails结构体,增加一个task_id: String字段,并使用#[serde(default)]确保向后兼容。 - 在状态加载逻辑中,对旧数据进行迁移:遍历所有 worktree 详情,如果其
task_id为空,则用其自身的名称作为task_id的默认值。
- 修改
-
Step 3: 实现
agentdev start命令 (Task 3)- 使用
clap定义start子命令,包含prompt、可选的--agents和--name参数。 - 实现命令逻辑:加载配置,确定任务名(用户指定或随机生成),然后循环遍历所有目标 Agent,为每个 Agent 执行
git worktree add和tmux new-session -d/tmux send-keys,最后将所有新创建的 worktree 信息(包含正确的task_id)写入状态文件。
- 使用
-
Step 4 & 5: Dashboard 改造与分层 Diff (Task 4 & 5)
- 数据结构: 定义一个
enum ListItem,包含Task(TaskGroup)和Worktree(&WorktreeDetails)两个变体,用于表示 TUI 列表中的不同层级。 - 数据准备: 在渲染前,将扁平的状态数据按
task_id重组为Vec<TaskGroup>。 - UI 渲染: 修改
ratatui的渲染循环,以树状结构绘制列表。根据任务节点的is_expanded状态决定是否渲染其下的 Agent 子节点。 - 核心预览逻辑: 在 TUI 的事件处理循环中:
- 获取当前高亮的
ListItem。 - 如果选中的是
Task: 遍历其下的所有 worktree,分别执行git diff,然后将所有diff输出(每个都带有 Agent 头部标识)合并成一个字符串,显示在预览窗格。 - 如果选中的是
Worktree: 只对这一个 worktree 执行git diff,并将其输出显示在预览窗格。
- 获取当前高亮的
- 数据结构: 定义一个
-
Step 6: 实现
agentdev delete-task命令 (Task 6)- 使用
clap定义delete-task子命令,接受一个task_name参数。 - 实现命令逻辑:根据
task_name从状态文件中筛选出所有相关的 worktree,向用户展示并请求确认,然后依次执行tmux kill-session和git worktree remove,最后清理状态文件。
- 使用
测试计划
- 单元测试: 覆盖配置加载和状态迁移的边缘情况。
- 集成测试: 编写脚本测试
agentdev start->agentdev delete-task的完整生命周期,验证文件系统和tmux状态的正确性。 - 手动测试: 重点测试 Dashboard 的交互,包括任务折叠/展开、分层
diff视图的正确切换,以及Enter键附着tmux会话的功能。