Local-first / CLI + TUI + Web + MCP
一个 SQLite 文件,没有服务器、没有账号、没有云。 人看终端界面或网页,Agent 走 CLI 或 MCP,四个入口读写同一块板子。 核心是一把数据库层的原子锁:两个 Agent 抢同一个任务,第二个会被直接拒绝。
它不是又一个 todo 工具。四个设计决定都是冲着"AI Agent 干活不靠自觉"来的。
关键区分:in_review 和 done 不是一回事。
in_review = 做完了但没验证,done = 跑过测试证明了。
这条专门为 Agent 设的 —— 防止 Agent 自己宣布"我做完了"就算结案。
规则写死在项目的 SKILL.md 里:只有真跑过代码/测试/命令,才能标 done,而且要把跑了什么记进证据流水。
认领任务不是"改个字段",而是一条带条件的 UPDATE: 只有当任务无主、或者本来就是你的,这条语句才会命中一行。 第二个 Agent 抢同一个任务,数据库直接让它落空。 并发安全不靠 Agent 讲礼貌,靠 SQLite 的 WAL 事务。
每个任务有个 evidence 字段,用来记动手之前的分析:
读了哪些文件、选了什么方案、发现什么约束。
它是带时间戳的追加流水,不是可以随手覆盖的文本框 ——
想把任务推进 in_progress,先把想清楚的东西留下来。
ready = 在 backlog/todo + 没人占 + 没外部阻塞 + 所有依赖都 done。
blocked = 没完成 + 有未完成依赖或开放阻塞。
没人需要手工维护这两个状态。所以 ls --ready 一条命令就回答"现在该干什么",P0 排最前。
下面是真实终端输出。claude-a 先认领,claude-b 随后来抢。
$ atx claim 1 --owner claude-a SmokeTest-1 claimed by claude-a (status -> in_progress) $ atx claim 1 --owner claude-b error: SmokeTest-1 already claimed by 'claude-a' (since 2026-09-14T03:29:55+00:00); use --force to take it 退出码 1
拒绝发生在数据库这一层,就这一条语句:
UPDATE tasks SET owner=?, claimed_at=?, status='in_progress', updated_at=? WHERE project=? AND id=? AND (owner='' OR owner=? OR ?) 无主 或本来就是你的 或 --force
命中 0 行就回滚、抛错、告诉你现在的持有者是谁、占了多久。
配套还有 release(还回去)、handoff(交给别人)、
claims --stale 12(谁占着超过 12 小时没动,该去问了)。
任务 2 依赖任务 1。1 没做完,2 就进不了 ready 列表 —— 也是真实输出。
$ atx ls --blocked #2 backlog 出漫画 [feature deps:#1] $ atx done 1 $ atx ls --ready #2 backlog 出漫画 [feature ready] ← 自动解锁了
同一个 SQLite 文件。CLI 改的东西,终端界面 0.5 秒内就刷新出来。
| 入口 | 命令 | 谁用 | 说明 |
|---|---|---|---|
| CLI | atx |
Agent + 人 | 短别名,和 agenttasker 等价 |
| TUI | atx board |
人 | 终端里的六列看板,监听数据库变化自动刷新 |
| Web | atx serve |
人 | 本地网页,纯标准库,默认只绑 127.0.0.1 |
| MCP | atx mcp |
Agent | stdio 服务器,13 个工具 |
Python 3.10+。核心零依赖,[mcp] 只在需要 MCP 服务器时装。
$ git clone https://github.com/BadbotAI/Agent-Tasker.git $ cd Agent-Tasker $ python3 -m venv .venv && .venv/bin/pip install -e '.[mcp]'
# 建任务,带描述、前置分析、优先级、标签 $ atx add "修登录跳转" -d "302 时 cookie 丢了" \ -e "已定位到 SameSite=None" --status todo --priority P1 --tag web # 建一个依赖前者的任务 $ atx add "补回归测试" --dep 1 # 现在能干什么(P0 排最前) $ atx ls --ready # 原子认领,顺带推进 in_progress $ atx claim 1 --owner agent-7 # 边干边追加发现 $ atx update 1 --append-evidence "复现确认,见 tests/e2e" # 验证通过,收工 $ atx done 1 # 人类看板 $ atx board
任务按项目分命名空间,默认取 git 仓库名,可以用 -p 或
$AGENTTASKER_PROJECT 覆盖。引用写 12 或 项目名-12 都行。
数据库默认落在 ~/.local/share/agenttasker/tasks.db,
用 $AGENTTASKER_DB 换地方。附件按 sha256 内容寻址存在数据库旁边。
标准 stdio MCP 服务器,Claude Desktop、Claude Code、任何 MCP 客户端都能接。
服务器从工作目录的 git 仓库名推断项目,每个工具也都接受显式的 project 参数。
{
"mcpServers": {
"agenttasker": {
"command": "/path/to/Agent-Tasker/.venv/bin/agenttasker",
"args": ["mcp"],
"env": { "AGENTTASKER_DB": "/Users/you/.local/share/agenttasker/tasks.db" }
}
}
}
list_tasks 支持 ready / blocked /
priority / tag / stale_hours / all_projects 过滤。
附件走 base64 进出,Agent 可以直接挂截图和日志。
完整的 Agent 工作纪律写在仓库的
SKILL.md。
模块划得干净:领域逻辑、存储、四个入口各自独立。
存储层带完整的就地迁移:老版本的全局自增 id 会迁成
(project, id) 复合主键且保留原 id,老版本的 evidence 文本块会被解析成带时间戳的行再删列。
还能 export 成版本化 JSON(附件 base64 内嵌)搬到另一台机器 import --merge ——
这是它不要云服务也能跨机器的解法。
实话部分。装之前值得知道。
atx serve 起的 Python 服务器,读你本机的 SQLite。
GitHub Pages 只托管静态文件,跑不了。要在线共享看板,得找能跑 Python 的地方。
--host 参数,但千万别设成
0.0.0.0 —— 那等于把任务板裸奔在局域网上。而且是 2 秒轮询,不是 WebSocket。