[FEATURE] /insights --project <path>: scope the report to a single project directory

发布时间 2026-09-19 11 天前
来源 Claude Code(GitHub Issues · RSSHub)
字数 3,295 字
查看原文

补充自 2026年09月19日

AI智能总结

一名用户提交功能请求,希望给 /insights 命令加上 --project <path> 参数,把报告范围限定到单个项目目录。

[功能] /insights --project:将报告范围限定到单个项目目录

预检清单

  • [x] 我已搜索现有请求,该功能尚未被请求过
  • [x] 这是一个单一的功能请求(不是多个功能的组合)

问题陈述

/insights 会分析本机上的每一次会话,但没有提供将报告范围限定到某一个项目的方式。对于在多个代码仓库上使用 Claude Code 的用户来说,这份报告反映的其实是他们使用最多的那个项目,根本无法回答"我在这个项目上的进展如何?"。

在我本机上的实测数据(~/.claude/usage-data/session-meta/,v2.1.278,2026-09-19 重新测量):

  • 4,294 条 session-meta 记录,分布在 634 个不同的 project_path 值上
  • 在这 634 个中:50 个真实项目目录、其下 158 个 git worktree,以及 426 个来自 hook 隔离测试的临时 /tmp/… 目录
  • 我今天想要查看洞察的那个项目:53 次会话 — 仅占总量的 1.23%
  • 使用量排名前三的项目:占总会话数的 45.2%

该语料库的两个特性使得真实占比比 1.23% 看起来还要更低。

76.9% 的记录是零信号的。 4,294 条中有 3,301 条恰好只有 2 条"消息"、零助手轮次、零工具调用、零 token、零时长,并且 first_prompt: "No prompt"。它们的转录文件清楚说明了本质——一个只跑了一次本地斜杠命令、在任何模型轮次之前就退出的会话:

7f020908-….jsonl  10 lines  {'queue-operation': 2, 'attachment': 4, 'user': 2, 'system': 1, 'last-prompt': 1}
    | <command-name>/usage</command-name>

只有 945 条记录(22.0%) 包含任何助手轮次或任何工具调用。一次 /usage 调用被计为一次会话,分母中有它,采样池中也有它,与一个长达六小时的构建会话并列。在有实质内容的记录中,我的项目只占 8/945 — 0.85%。

会话数本身就不是正确的统计单位。 在那 53 次会话中,中位数是 2 条消息;53 次中有 45 次会话消息数 ≤5,合计只有 90 条消息 — 占该项目总量的 7.6% — 而单单一次会话就占 37.3%,前五次会话合计占 80.3%。整台机器上也呈现同样的形态:每次会话的中位数为 2 条消息,前 10% 的记录承载了 81.8% 的全部消息。因此,对会话做均匀采样,其实是在对空壳做采样,而真正蕴含设计决策和痛点的少数会话恰好被这种采样所遗漏。

叙述段落、痛点模式、工具使用画像与建议,全部是基于整个语料库生成的,因此没有项目专属的内容可供单独阅读——这份分析自始至终就与我的项目无关。

实际情况比占比所暗示的还要更糟,因为报告本身是采样的。我最近一次报告的头部是这样的:

4,956 sessions total · 490 analyzed · 6,764 messages · 2026-07-15 to 2026-09-19

4,956 个会话中分析了 490 个。如果该样本在记录上是均匀分布的,那么其中属于我项目的会话数的期望值为 5,再按上面 8/53 的实质内容比率折算,其中真正含有任何内容的期望值不到 1 个。关于那个项目的任何一句话都毫无依据地漂浮在那里,没有标签地与其他 489 条混合在一起,并且头部信息既没有说明包含了哪些项目,也没有说明各自有多少。读者根本看不出这是一份跨 50 个代码仓库的汇总报告。

这不是什么特殊的使用场景。它就是一台工作机器的常态:少数大型的、长期运行的项目,加上长长的、由小型项目组成的尾巴。洞察最有价值的恰恰是在这条长尾上——一个新项目、一个不熟悉的技术栈、一个出问题的代码仓库——而全局汇总恰恰把这条长尾淹没了。426 个 /tmp 临时目录则是第二个原因:没有人愿意在工作流分析里看到 hook 隔离的测试运行结果,而目前没有任何办法将它们排除。

数据其实已经被采集了。每一条 session-meta 记录都把 project_path 作为一等顶层字段:

{
  "session_id": "…",
  "project_path": "/home/me/projects/auxiliary/kanjin",
  "start_time": "2026-09-02T09:48:20.173Z"
}

不需要再去采集、存储或计算任何新数据。语料库本来就是按项目为键组织的。缺少的只是一个过滤器。

提议方案

为 /insights 增加一个可选的项目范围限定。之前提出过该诉求的多个用户不约而同地几乎给出了同样的设计,因此作为方案来说已经得到了充分的验证:

/insights                          # 保持不变 —— 所有项目,沿用当前行为
/insights --project .              # project_path 位于当前工作目录下的会话
/insights --project <path>         # 对 project_path 进行前缀匹配
/insights --exclude <path>         # 可选的反向排除 —— 例如 --exclude /tmp

默认行为必须保持不变。 不带任何参数的 /insights 依然分析全部会话。严格意义上的增量、可选功能:不需要迁移、不需要废弃,对不传该参数的任何人都毫无影响。

采用前缀匹配,而非完全相等。 在 git worktree 中启动的会话会把 /.claude/worktrees/ 记录为项目路径——在我本机上,覆盖 158 个 worktree 路径、共 331 次会话。对代码仓库根目录进行前缀匹配,会把这些会话归并到它们的父项目中,这正是用户说"这个项目"时的真实含义。如果采用相等匹配,这些会话就会被静悄悄地丢掉。

如果觉得上面这一组参数过多,最小可用版本是采用一个可选的位置参数路径,正如 #29844 所提议的:

/insights /home/me/projects/thing

实现上只需要在加载阶段、采样与 facet 生成之前增加一个谓词:

sessions.filter(s => s.project_path.startsWith(resolvedScope))

下游的所有环节——采样、facet 抽取、叙述生成、图表、HTML 报告——在过滤后的集合上照常运行,无需任何改动。

两处花不了多少成本的额外增强,能让效果显著改善:

  1. 在报告头部显式说明范围。 现在的头部只打印消息数、会话数与日期范围。还应该打印所包含的项目、范围之内的会话数,以及其中有实质内容(非零信号)的会话数。这样一份限定范围的报告就不会被误读为全局报告——而一份全局报告也应该如实说明它是一个跨 N 个项目的汇总。

  2. 在生成之前先打印范围内的会话数。 如果一次限定范围的运行只覆盖 4 个会话,应该明确告知用户,而不是默默地产出一份空洞的叙述。这也有助于解决一长串"报告为空"的问题(#64275、#83849、#83695、#81679 等等)——在这些 issue 中,输入量不足都会导致 AI 部分为空且没有任何解释。

备选方案

尝试过、或经过考虑后被否决的方案:

  • 删除或移动其他项目的 session-meta 文件。 这是 #56334 提交者最终采取的做法。它为了获得一份限定范围的报告,必须销毁全局历史,而且每次都要重做一遍。

  • 运行 /insights,然后绕过噪声自行阅读。 在面对一份 490 个会话的样本、信号占比仅 0.85% 的情况下,这是不可行的。叙述是基于完整语料库生成的,里面没有任何项目专属的内容可供单独阅读。

  • *自己解析 `session-meta/.json。** 我做过这件事,才得到了上面那些数字。但这样做只能得到计数。/insights` 的价值在于定性的 facet 分析与叙述,而目前没有受支持的方式可以在一个子集上调用这些能力。

  • 每个项目使用独立的机器或操作系统账户。 #41199 的提交者真的这样做了——后端跑在虚拟机上,UI 在另一台桌面上——并且报告说即便如此,当同一桌面有两个项目时仍然会失败。对于 51 个项目,这显然不现实。

  • 用日期过滤(--since/--until)作为替代。 对于一次只做一个项目的人来说,这能部分缓解。该功能也已被请求过九次,却至今仍未发布,因此整个过滤系列的需求都还没有得到响应。

没有任何一种变通方案能够保留该功能真正的价值。

优先级

高 - 对生产力有显著影响

功能分类

CLI 命令与参数