mcpField
C
clockify-tracker

clockify-tracker

github.com/somnio-software生产力8112 次安装2 周前更新
代码仓库

关于 clockify-tracker

通过 HTTPS 调用 Clockify REST API 的时间追踪技能,支持手动填写工时,也可根据工作日志将仓库活动映射到项目。提交前会预览条目供确认。

主要功能

  1. 01列出工作区和项目
  2. 02通过 REST API 创建工时条目
  3. 03将本地时间转换为 UTC
  4. 04从环境或偏好文件读取 API 密钥
  5. 05根据工作日志生成条目
  6. 06提交前预览条目

适用场景

  1. 01记录手动描述的工作时段
  2. 02根据日期日志创建工时条目
  3. 03将仓库活动分配到 Clockify 项目

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/somnio-software/somnio-ai-tools --skill clockify-tracker

安装后在 Claude Code 中输入/clockify-tracker确认已加载。

详细介绍

Clockify 时间跟踪(REST API)

通过对 https://api.clockify.me/api/v1 发送 HTTPS 请求,与 Clockify 集成。不要假定本地存在 clockify_tracker 二进制文件。

API 密钥

按以下优先级顺序解析密钥:

  1. CLOCKIFY_API_KEY 环境变量 — 使用 echo $CLOCKIFY_API_KEY 检查
  2. CLOCKIFY_API_KEY_FILE 环境变量 — 指向仅包含密钥的文件;使用 cat "$CLOCKIFY_API_KEY_FILE" 2>/dev/null | tr -d '[:space:]' 读取
  3. Shell 配置文件 — 在常见的 rc 文件中搜索 CLOCKIFY_API_KEY 的导出或赋值语句:
    grep -h "CLOCKIFY_API_KEY" ~/.zshrc ~/.zprofile ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null \
      | grep -v '^\s*#' | head -1
    
    使用以下方式从类似 export CLOCKIFY_API_KEY=abc123 或 CLOCKIFY_API_KEY="abc123" 的行中提取值:
    sed 's/.*CLOCKIFY_API_KEY[[:space:]]*=[[:space:]]*//' | tr -d '"'"'"' '
    
    如果找到非空值,则静默使用(与该值存在于当前环境中时相同)。
  4. prefs 文件中的 api_key 字段(参见下方的 CLOCKIFY_PREFS_PATH)— 使用 cat <prefs-path> 2>/dev/null 读取
  5. 未找到 → 请用户粘贴其密钥(Clockify → Profile → API),然后询问是否保存:

    “要将此密钥保存到 ,以便下次无需再次输入吗?(yes/no)” 如果是,则将 "api_key": "<key>" 合并到 prefs 文件中。

切勿回显或记录密钥值。仅在 curl -H "X-Api-Key: $KEY" 命令中使用。

环境

变量用途
CLOCKIFY_API_KEY当前环境中的 API 密钥值。
CLOCKIFY_API_KEY_FILE密钥所在文件的路径(例如 ~/.secrets/clockify)。适用于密钥管理器或符号链接的保险库文件。
CLOCKIFY_PREFS_PATHprefs JSON 文件的自定义路径。未设置时默认为 ~/.clockify-prefs.json。解析 prefs 路径:${CLOCKIFY_PREFS_PATH:-~/.clockify-prefs.json}。
CLOCKIFY_TZ_OFFSET相对 UTC 的本地时差,单位为整小时(例如阿根廷使用 -3)。当 prefs 文件中没有时区时作为回退值。

要检查的 Shell 配置文件(上方第 3 步):~/.zshrc、~/.zprofile、~/.bashrc、~/.bash_profile、~/.profile。

身份验证

每个请求都需要:

  • 请求头:X-Api-Key: <resolved key>
  • 请求头:Content-Type: application/json(用于 POST 请求体)

端点(与先前 CLI 的行为一致)

列出工作区

GET /workspaces

返回工作区的 JSON 数组;每项包含 id 和 name。

列出工作区中的项目

GET /workspaces/{workspaceId}/projects?page-size=5000

返回项目的 JSON 数组;每项包含 id 和 name。

流程: 如果用户可能有多个工作区,先调用 GET /workspaces 并让用户选择(或使用唯一的工作区)。然后列出所选 workspaceId 中的项目。

创建时间条目

POST /workspaces/{workspaceId}/time-entries

JSON 请求体(字段与之前的 CLI 保持一致):

字段必填说明
start是ISO 8601 UTC 字符串,例如 2025-03-25T12:00:00.000Z
description是工作说明
billable否布尔值;省略时默认为 false
end否ISO 8601 UTC;省略则创建未结束的条目
projectId否Clockify 项目 ID
将用户本地时间 HH:mm 转换为 UTC start / end

当用户提供 HH:mm 格式的本地时间(并可选提供 YYYY-MM-DD,若未提供,则根据其所在地区的意图默认为今天)时:

  1. 解析日期 D(年、月、日)和时间部分 hour、minute。
  2. 将 tzOffset 设为该本地时区相对于 UTC 的偏移小时数:UTC+5 为 +5,UTC-3 为 -3。如果已设置 CLOCKIFY_TZ_OFFSET,则使用其值(整数小时);否则根据用户所在地区(例如阿根廷 → -3)或上下文推断。
  3. 构建 UTC 时间: utc_hour = hour - tzOffset 然后将其规范化为日期 D 上正确的 UTC DateTime(必要时跨日期进位),并使用 Z(ISO 8601 UTC)序列化。

示例:

  • 本地时间 09:00,日期为 2025-03-10,tzOffset = -3 → UTC 小时 9 - (-3) = 12 → 2025-03-10T12:00:00.000Z。
  • 如果用户已提供带 T 和时区/Z 的完整 ISO 字符串,则直接传递,不进行此转换。
多个日历日

对于日期范围(“March 2–6”)或离散日期列表(“March 23, 24, 25, 26 and 27”),每天都创建一个 POST 请求,使用相同的本地时间,并为每个 start(以及任何 end)设置对应日期。未提供年份时,假定为当前日历年。

操作流程

  1. 确认执行环境中有 CLOCKIFY_API_KEY。
  2. 如果工作区未知:调用 GET /workspaces;解析 workspaceId。
  3. 如果需要项目:调用 GET /workspaces/{workspaceId}/projects?page-size=5000;解析 projectId。
  4. 收集描述、开始时间(以及可选的结束时间)、必要时的日期,以及不明确时的时区偏移。
  5. 构建 JSON 并调用 POST /workspaces/{workspaceId}/time-entries。
  6. 显示 API JSON 响应或清晰的错误信息(状态码 + 响应正文)。

错误

如果状态码表示请求未成功,则读取响应正文并进行调整(ID 无效、权限不足、请求正文格式错误)。官方参考文档:Clockify API 文档。


基于日志的模式

当用户说 “use logs”、“from work logs”、“usa los logs”、“auto-fill from logs” 或类似表达时触发。现有的手动模式(明确提供描述/项目/日期/时间)保持不变。

偏好设置文件

路径:${CLOCKIFY_PREFS_PATH:-~/.clockify-prefs.json}。始终在运行时解析此路径——先检查环境变量,未设置时再使用 ~/.clockify-prefs.json。使用 cat "${CLOCKIFY_PREFS_PATH:-~/.clockify-prefs.json}" 2>/dev/null 读取;写入时用合并后的 JSON 覆盖文件。

{
  "api_key": "<clockify-api-key>",
  "timezone": { "name": "Buenos Aires, Argentina", "offset": -3 },
  "default_start": "09:00",
  "default_end": "17:00",
  "workspace_id": "<wid>",
  "repo_mappings": {
    "mini-meta-repo":  { "name": "Nubank",        "id": "<pid>" },
    "somnio-ai-tools": { "name": "Internal Tools", "id": "<pid>" }
  }
}

始终将新键合并到现有偏好设置中,绝不要替换整个文件。

分步流程

1. 加载偏好设置 — 读取 ~/.clockify-prefs.json。文件不存在表示没有已保存状态;继续进行首次设置。

2. 首次设置(没有偏好设置文件) — 在询问其他任何内容之前,先询问:

“我们来设置你的偏好。你目前正在使用哪些仓库/项目?每个仓库/项目对应的 Clockify 项目名称是什么? 示例:mini-meta-repo → Nubank,somnio-ai-tools → Internal Tools”

通过 GET /workspaces/{wid}/projects 将 Clockify 项目名称解析为 ID,并保存到偏好设置中。这是唯一一次完整列出项目范围的操作——之后遇到新仓库时,只需询问一次。

3. 询问时间范围 — 如果用户的消息中未提及:

“你希望我查看哪些日期?(例如:今天、本周、May 22–26)”

4. 读取日志文件 — 对时间范围内的每一天:

cat ~/.work-log/YYYY-MM-DD.md 2>/dev/null

文件不存在 → 跳过该日并告知用户。解析所有 ## HH:MM - … (branch) 标题,收集所选日期中不重复的仓库名称。

5. 确认时间范围 — 默认 09:00–17:00(8 h)。如果已有保存的偏好设置,则显示该设置。仅在没有偏好设置或用户明确提到不同时间段时询问是否更改。

6. 时区选择器 — 如果已保存时区,则将其作为默认值提供:

“使用 Buenos Aires(UTC-3)——按 Enter 保持不变,或选择一个数字 / 输入自定义值:”

如果没有已保存的偏好设置,则打印并等待用户输入数字、名称或自由文本:

1. Buenos Aires, Argentina  (UTC-3)
2. Montevideo, Uruguay      (UTC-3)
3. São Paulo, Brazil        (UTC-3)
4. Quito, Ecuador           (UTC-5)
5. Lima, Peru               (UTC-5)
6. Colombia                 (UTC-5)
7. Nicaragua                (UTC-6)
8. Other — type your city or UTC offset (e.g. "Madrid" or "UTC+1")

如果用户输入的城市或地区不在列表中,请根据你的知识推断其标准 UTC 时差(例如,“Madrid” → 冬季为 UTC+1/夏季为 UTC+2——使用今天日期对应的当前标准时差)。保存前请与用户确认:

“Madrid 的标准时间为 UTC+1——正确吗?”

7. 解析并确定仓库名称 — 日志标题有两种格式:

  • Worktree:## HH:MM - mini-meta-repo/refactor-flutter_http (branch) — 根仓库是 / 之前的部分
  • 主检出:## HH:MM - somnio-ai-tools (main) — 整个名称都是根仓库

按 / 拆分,提取根仓库名称(用于 Clockify 映射)和 worktree 名称(用于描述上下文)。然后:

  • 根仓库在 repo_mappings 中 → 静默使用。
  • 根仓库不在 repo_mappings 中 → 只询问一次:

    “我看到 mini-meta-repo 中有日志条目——这是哪个 Clockify 项目?”

创建任何条目之前,先汇总询问所有未知仓库。

8. 保存偏好设置 — 所有问题都得到答复后,将答案合并到 ~/.clockify-prefs.json。

9. 处理跨多个项目的工作日 — 对每一天,统计当天的仓库映射到的不同 Clockify 项目数:

  • 单个项目 → 为完整时间段创建一个条目。
  • 多个项目 → 请用户拆分工时:

    “5 月 26 日,你在 Nubank(mini-meta-repo)和 Internal Tools(somnio-ai-tools)上工作。8 小时该如何拆分?(例如:Nubank 7 小时/Internal Tools 1 小时)”

当天每个项目创建一个条目,并分别设置开始和结束时间。

10. 汇总每个条目的日志 — 对于每个(日期,Clockify 项目)组合,收集相关日志条目并生成一份两句话的执行摘要:

  • 第一句:主要成果——功能、决策,以及参与的具体 worktree/分支(请注明名称)
  • 第二句:关键发现、结果或下一步

目标是提供足够的上下文,让财务读者了解 8 小时的工作内容,同时避免长篇大论。

11. 预览并确认 — 发布任何内容之前,完整展示每个条目,让用户检查描述。格式为编号列表,每项对应一个条目:

Here's what I'll post to Clockify:

1. May 22 — Nubank — 09:00–17:00
   refactor-flutter_http: Completed Flutter HTTP migration by updating LogoutInterceptor
   to use IRouter and fixing the redirect_interceptor_test setup. Key finding: the
   interceptor correctly dispatches the logout deeplink on 403 responses.

2. May 26 — Nubank — 09:00–16:00
   refactor-flutter_http: Diagnosed the native catalyst HTTP bypass on both iOS and
   Android — authenticated calls go through URLSession/OkHttp, not Dart/Dio, making
   LogoutInterceptor.onError structurally unreachable. Proposed and planned Option A
   (synthetic DioException) as the only viable path to trigger the interceptor.

3. May 26 — Internal Tools — 16:00–17:00
   somnio-ai-tools: Planned and implemented the clockify-tracker log-based mode,
   including hook fix for root-repo logging and the repo-to-project mapping system.

Post these entries? (yes / edit / cancel)

请使用编号列表(不要使用表格),确保完整描述可读且不会被截断。如果用户说“编辑”,请询问要修改的条目编号和新的描述,然后重新展示完整预览,再发布。

12. 创建条目 — 每行调用一次 POST /workspaces/{workspaceId}/time-entries,使用现有的 UTC 转换逻辑。展示每个 API 响应。

13. 清理日志文件 — 所有条目均成功发布后,询问是否删除已处理的文件。

检查 ~/.clockify-prefs.json 中的 "auto_cleanup": true。如果已设置,则直接删除并告知用户删除了哪些文件。否则请询问:

“条目已发布。要删除已处理的日志文件吗?

  • ~/.work-log/2026-05-26.md
  • ~/.work-log/2026-05-27.md (yes / no / always——‘always’ 会保存此偏好设置,以后不再询问)”
  • yes — 使用 rm 删除这些文件,并逐一确认已删除
  • no — 保留文件,不做更改
  • always — 删除文件,然后将 "auto_cleanup": true 合并到解析后的偏好设置文件(${CLOCKIFY_PREFS_PATH:-~/.clockify-prefs.json})

只有当某个日期的所有条目都成功发布时,才删除该日期的文件。如果部分发布失败,则跳过删除任何包含失败条目的日期对应的文件,并告知用户保留了哪些文件。

评论

支持 Markdown