Skip to content

Latest commit

 

History

History
357 lines (252 loc) · 17.1 KB

File metadata and controls

357 lines (252 loc) · 17.1 KB

PRD v0.1 — Agent 状态 + 个人 To-do 桌面便签条

状态:待对齐。本文档只覆盖 v1 范围,token/额度模块单列为 v1.1。


1. 一句话定义

一个常驻桌面、可折叠的极简任务条:左边管所有 AI Agent 的活,右边管自己的活。

2. 要解决的问题

同时跑多个 Agent(Claude Code / Codex)时:

  • 不知道哪个在跑、哪个跑完了、哪个卡住在等你授权 —— 只能挨个切窗口看
  • 定时任务什么时候会触发,完全没有可视化
  • 自己的 to-do 在另一个 app 里,和"Agent 在替我干的活"割裂成两个世界

3. 差异点(为什么不是又一个 monitor)

维度 现有竞品 本产品
审美 开发者审美,信息塞满,系统控件原样用 极简高级感,第一性卖点
形态 菜单栏(要点开才看得到) 桌面常驻可折叠条(余光可扫)
定时任务 基本无人展示 一等公民
个人 to-do 无(最多是 quick notes) 独立 tab,三分类

数据源(本地 JSONL)人人可得,壁垒只能建立在形态 + 审美 + 整合体验上,不在解析能力上。

4. 非目标(v1 明确不做)

  • ❌ 派活 / 编排 Agent(那是 Vibe Kanban、AgentGrid 的活)
  • ❌ 代码 review、diff 展示、git worktree 管理
  • ❌ 网页版 dashboard、团队协作、多端同步
  • ❌ 手机端

保持"只读 + 极简",是这个产品能好看的前提。



4.5 Agent 覆盖范围

v1 必须做接入抽象层,不能把 Claude Code / Codex 的解析逻辑写死。

阶段 Agent
v1 Claude Code、Codex、Cursor、Antigravity
二期 Kimi、WorkBuddy、DSH 等

⚠️ 这比原计划(仅 Claude Code + Codex)扩了范围。抽象层本身成本不高,但每接一个 Agent 都要单独摸它的数据源、状态语义和落盘格式,这部分是线性增加的工作量。若 v1 要控周期,可先只实现 Claude Code + Codex 两个 adapter,但接口按四个 Agent 的形态设计。

Adapter 需要抽象的能力:

  • 发现会话(路径/进程/接口)
  • 解析状态 → 映射到统一的四态(等你介入 / 进行中 / 已完成 / 空闲)
  • 读取定时任务(可选,非每个 Agent 都有)
  • 读取限额窗口(可选,v1.1)
  • 跳转/聚焦到该会话

4.6 各 Agent 实际能读到什么(实测)

Agent 会话状态 等你介入 定时任务 额度 数据源
Claude Code ✅ 接口 ~/.claude/projects/**/*.jsonlscheduled-tasks//api/oauth/usage
Codex ✅ 显式事件 ✅ 日志内 ~/.codex/sessions/automations/token_count.rate_limits
Cursor ✅ 推断 ❌ 无 ❌ 本地无 ~/.cursor/projects/<slug>/agent-transcripts/*.jsonl。格式同 Claude 但没有 tool_result 和逐行时间戳,全靠 mtime 推断。目录名是 cwd 把 / 和空格都换成 -,需逐段对磁盘还原
Antigravity(已下线,roadmap ⚠️ 无法判断 会话正文 conversations/*.pb 加密不可读;只能读 brain/<id>/task.md 明文清单 + metadata.jsonupdatedAt。能知道做到哪、不知道是否卡着等人,故永不产出 needsYou。且本机两个月未用,未经活数据验证

5. 形态与交互

5.1 两种状态

折叠态(默认)

  • 一条窄条,常驻桌面,置顶
  • 只显示一个信号:最需要你介入的那件事
    • 优先级:等你授权 > 已完成待查看 > 进行中 > 全部空闲
    • 例:⏸ 1 个等你授权 / ▶ 3 个进行中 / ✓ 全部完成
  • 有 to-do 高优未完成时,附加一个极轻的标记
  • 单击展开

设计原则:折叠态能显示的信息量约等于 1 行。克制到只剩一个信号,是这个产品气质的分水岭。宁可少,不可满。

展开态

  • 面板,两个 tab:Agents / To-do
  • 失焦或再次单击 → 收回折叠态

5.2 窗口行为(已知难点)

  • 置顶层级:需要能盖在全屏应用之上(Noticky 把这当卖点,说明不 trivial)
  • 多显示器:记住所在屏幕与位置
  • 可拖动,位置持久化
  • 全局快捷键唤起/收起

6. 功能 A:Agents tab

6.1 状态定义

状态 含义 优先级
等你介入 Agent 停下来等授权/等输入 最高
进行中 正在跑
已完成 本轮结束,未被你查看过
定时任务 已配置、尚未触发,显示下次触发时间 常驻
空闲/已查看 折叠或弱化显示 最低

已确认采纳。 在你原本的「已完成 / 定时任务 / 进行中」之外,新增**「等你介入」**作为独立状态并置于最高优先级。

依据:竞品 claude-status-bar 专门实现了这个优先级冒泡——一个等授权的会话永远不该被"思考中"的会话盖住。多 Agent 并行时,最高频的真实痛点不是"跑完了没",而是"哪个卡住在等我"。

这条直接决定折叠态那一行显示什么,是整个产品的核心信号。

6.2 每条会话展示

  • 项目名 / 工作目录(短名)
  • 来源标识(Claude Code / Codex)
  • 状态 + 状态持续时长
  • 最后一条动作摘要(一行,截断)
  • 点击 → 跳转/聚焦到对应会话窗口

6.3 数据来源(已实测)

会话状态

  • Claude Code:~/.claude/projects/**/*.jsonl,FSEvents 监听
  • Codex:~/.codex/sessions/

定时任务

路径 / 来源 可得字段 风险
Codex ~/.codex/automations/<id>/automation.toml id name status rrule target_thread_id created_at updated_at 已实测,零风险。明文 TOML,rrule 为标准 iCalendar 格式,用现成库算下次触发时间
Claude Code ~/.claude/scheduled-tasks/<taskId>/SKILL.md ✅ 已确认 taskId description schedule cronExpression fireAt enabled nextRunAt lastRunAt 路径与字段形状均已确认,nextRunAt 现成、无需自算。⚠️ 但本机当前 0 条任务、目录尚未生成,解析代码未经真实数据验证,等有真实任务后需复核字段名

⚠️ 已知陷阱:~/.claude/tasks/ 不是定时任务。 它是会话内的子任务清单(结构为 subject / status / blockedBy),命名极具误导性,不要接错。

范围决策:不覆盖 Claude 云端 routines。 Claude 另有一套跑在云端的 routines 机制,不落本地磁盘。v1 只覆盖本地定时任务。

全部只读,不写入任何 Agent 的数据目录。

7. 功能 B:To-do tab

7.1 三个分类

分类 行为
高优 置顶,视觉上唯一允许"重"的元素;未完成时会向折叠态冒泡
普通 常规列表,手动增删
每日重复 每天 0 点自动重置为未完成;保留完成历史(用于连续天数)

7.2 操作

  • 快速新增(键盘优先,一个输入框 + 回车)
  • 勾选完成 / 取消
  • 拖拽排序、跨分类拖拽
  • 完成后的项:淡出并折叠到"今日已完成",不占视觉

7.3 存储

纯本地,单一文件(SQLite 或 JSON)。无账号,无云。


8. 用量模块(已实现)

8.1 结论:三个 Agent 的数据可得性完全不同

能拿到什么 来源
Codex 真实额度used_percent、窗口长度、resets_atplan_type 会话日志 event_msg.payload.type == "token_count"rate_limits
Claude Code · 套餐等级 ✅ 如 Max 5x ~/.claude.jsonoauthAccount.organizationRateLimitTier(普通配置文件,不涉凭据)
Claude Code · 额度百分比 本地拿不到 见下

Claude Code 的 5 小时 / 整周百分比不落在任何可持续读取的本地文件里。 已排查:

  • 日志里的 error.rateLimits —— 仅撞限额报错时出现,实测为 null
  • local-agent-mode-sessions/*/audit.jsonl 里有 rate_limit_event (结构 {status, resetsAt, rateLimitType: five_hour|seven_day, utilization, isUsingOverage}, 正是需要的形状)—— 但它只在接近限额时才写,且这批文件最新的也是三周前的,不能当持续数据源
  • ~/.claude.json、各类 cache —— 只有套餐等级,没有用量

唯一的持续来源是接口 GET /api/oauth/usage(地址取自 Claude Code 自身安装包, 它的 /usage 界面就是这么来的)。已实现,见 ClaudeUsageAPI

  • token 从 Keychain 项 Claude Code-credentials 读取,只在内存中存在,绝不落盘、绝不写日志
  • 只发往 api.anthropic.com,即该 token 本来的归属方
  • 拿不到就自动退回本地 token 累计,界面上区分得开

已跑通,实测返回结构: 顶层有 five_hour / seven_day 等字段,但要用 limits 数组—— 它才是 Claude 自己 /usage 界面用的那份,kind + group + scope 三个字段足以还原分组标签:

kind 界面标签
session 5 小时
weekly_all 本周 · 全部模型
weekly_scoped + scope.model.display_name 本周 · Fable

顶层字段留作兜底,且只认白名单——返回体里混有 nimbus_quilltangelo 等内部代号, 递归抓 utilization 会把它们当额度显示出来。

套餐等级(Max 5x)从 Keychain 那份凭据的 rateLimitTier 读,比 ~/.claude.json 可靠: 后者在重新登录后会被清空,要等 profile 重新拉取才回填。

⚠️ 前提:claude CLI 的凭据必须是有效的。 若日常只在桌面端使用 Claude Code, CLI 那份 Keychain 凭据可能早已过期(本机实测 expiresAt 停在 2026-06-30、 refreshToken 为空,接口返回 401)。跑一次 claude auth login 即可刷新。

⚠️ 接口未公开,Claude 改版时可能失效,届时需跟进。

8.2 呈现原则

界面上必须把「官方额度」和「本地统计」明确区分,不能让人误以为本地累加值 就是剩余额度。实现见 AgentQuota.isLocalEstimate,每个 Agent 区块右上角标注来源, 底部另有一句说明。

  • Codex:本周窗口进度条 + 百分比 + 重置倒计时
  • Claude Code:套餐等级 + 近 5 小时 / 近 7 天的 token 累计(含缓存读取)+ 输出量
  • 拿不到百分比的项一律不画进度条——画一条没有分母的进度条是在骗人

8.3 已知取舍

Claude 的累计值包含缓存读取 token,而缓存读取通常占绝大多数, 所以数字会显得很大。保持包含是为了和 Codex 的 total_tokens 口径一致 (Codex 的官方统计同样含缓存)。若认为误导,可改为剔除缓存读取。

8.4 性能

算「近 7 天」要看全量日志(几十 MB),每次刷新全读不可接受。 ClaudeUsageIndex 记住每个文件已消费到的字节偏移,只解析新增部分; 文件变小(轮转)时该文件重来。额度整体走 15 秒慢节拍。

9. 视觉方向(已选定:C 玻璃)

9.1 方向

C「玻璃」 —— macOS 原生质感:磨砂通透、大圆角、系统字体。 视觉稿见 visual-directions.html(三方向对比:A 墨迹 / B 仪表 / C 玻璃)。

选它的代价是辨识度最低,需要靠 9.3 的手段补回来。

9.2 设计 token(来自选定稿)

token 浅色 深色
面板底 rgba(252,252,253,.70) rgba(30,32,36,.66)
正文 #111214 #F1F2F4
次级文字 #5B6066 #A6ACB3
弱化文字 #8A9098 #767C84
分隔线 rgba(20,22,28,.10) rgba(255,255,255,.115)
选中底 rgba(20,22,28,.055) rgba(255,255,255,.075)
信号色(等你介入) 由皮肤定义,默认 #E2542B 由皮肤定义,默认 #FF7A52
进行中 #3E9E74 #5FC79A
  • 圆角:15px
  • 磨砂:backdrop-filter: blur(30px) saturate(1.7)
  • 描边:0.5px 同分隔线色
  • 字体:系统字体栈(SF Pro / PingFang SC),不引外部字体

9.3 辨识度补救(必做)

C 的风险是"用户以为这是系统自带功能"。三条补救手段,按性价比排序:

  1. 换掉信号色已解决 —— 由 9.5 皮肤系统承接。系统蓝是 macOS 上最泛滥的强调色,比磨砂和圆角更容易让人觉得这是系统组件;每款皮肤自带信号色,默认「素」皮肤已换为灼橙 #E2542B
  2. 分组标题保持句式而非大写标签 已在稿中体现(用「等你介入」而不是 等你介入 全大写字距标签)。这是 C 区别于 A/B 的语气特征,保留。
  3. 折叠态的形状可以不守规矩 面板守 macOS 规范,但折叠态那一条是产品自己的东西,可以在尺寸比例和内部节奏上做出特征。

9.5 皮肤系统

毛玻璃是不变的基底,皮肤在其上换材质与颜色。 视觉稿见 skins.html

基底中性正是它能当基底的原因:玻璃不表达立场,所以能承载任何风格而不打架。辨识度由皮肤提供,不由基底提供——这同时解决了 9.3 提出的 C 方向辨识度问题。

皮肤权限契约(必须严格执行)

皮肤可以 皮肤不能
信号色与进行中色 布局与间距(所有皮肤共用一套栅格)
材质层:网点 / 颗粒 / 网格 / 色斑 信息层级与分组顺序
玻璃底色与透明度 四态语义(等你介入永远最高优先级)
中性灰阶的色相偏移(偏暖 / 偏冷) 圆角与磨砂参数——这是产品的形,不是风格
信号点形状:圆 / 方 / 微圆角 字体——统一系统字体栈
一处角落装饰图形 「折叠态只显示一个信号」这条铁律

契约存在的意义:若皮肤什么都能改,每装一个皮肤就是一个不同的 app,产品统一气质荡然无存。

v1 内置皮肤

皮肤 来源 信号色 材质
Plain(默认) #E2542B 灼橙 无纹理,纯玻璃
网点 Riso 参考图一 #EE7A16 / 群青 #4A6FD4 半调网点双色错位叠印
线谱 Plot 参考图二 #D6386E 品红 / 青 #2E9AA8 13px 细网格 + 角落放射线
拓印 Relief 参考图三 #BF4B33 砖红 / 雾蓝 #7396C4 纸纹颗粒 + 有机色斑

每款皮肤深浅两套齐全。

⚠️ 材质层强度上限(硬性)

组件仅 296px 宽、正文 12.5px,纹理压到文字底下就会打架,网点与颗粒这类高频纹理尤甚。

  • 浅色下材质层不透明度 ≤ 20%
  • 深色下 ≤ 30%
  • 不允许任何皮肤单独调高此上限

纹理本就该只在余光里存在。若觉得"不够明显",那是正确的。

二期

开放自定义皮肤(用户可导入自己的配色与材质),受同一份契约约束。

9.4 硬约束(跨方向通用,保留)

  • 不用系统默认控件的原始样式
  • 单一强调色,其余全部中性灰阶
  • 信息密度低于竞品一个量级——留白是功能,不是浪费
  • 状态用极细微的差异表达(一个点、一段颜色),不用大色块和 badge 轰炸
  • 深色/浅色跟随系统,两套都要设计,不做简单反色

10. 技术选型(待定)

方案 优点 缺点
SwiftUI 原生 性能好、窗口层级可控、体积小 仅 macOS
Tauri 跨平台、前端可控审美 窗口置顶/全屏覆盖需额外处理
Electron 生态成熟 体积大,和"极简"气质冲突

选定 SwiftUI:v1 确定 macOS only(已拍板)。窗口层级是本产品的核心难点,原生控制力比跨平台更重要。


11. 已决议事项

议题 结论
定时任务指什么 Claude Code 与 Codex 各自的 scheduled tasks,数据源见 6.3
额度模块要什么 限额窗口剩余量(5 小时 + 整周),非会话消耗,见 8.1
「等你介入」第四态 采纳,且为最高优先级,见 6.1
平台 v1 仅 macOS
Agent 抽象层 需要。v1 四个 adapter 已全部接入(Claude Code / Codex / Cursor / Antigravity),各自的数据可得性见 4.6;Kimi、WorkBuddy、DSH 等二期
To-do 与 Agent 任务打通 二期。v1 两个 tab 彻底独立,互不关联
视觉方向 C 玻璃,并在其上增加皮肤系统,见 9

12. 下一步行动

优先级 动作 阻塞什么
P0 定位 Claude Code 定时任务落盘路径已确认~/.claude/scheduled-tasks/<taskId>/SKILL.md
P1 建一条真实 Claude 定时任务,复核字段解析 该分组的正确性
P1 FSEvents 监听(现为 2 秒轮询,够用但可更跟手) 响应速度
P2 点击会话跳回对应 Agent 窗口(现为在 Finder 中定位日志) 跳转体验
P1 出视觉方向稿已完成,选定 C 玻璃
P1 信号色探索已完成,收进皮肤系统(9.5)
P2 spike 限额窗口数据来源已完成并实现,见第 8 节