Git时间追踪工具

Clockwork是一款基于Git提交的自动化时间追踪系统,提供MCP服务器模式和交互式终端界面,适用于开发者的工作时间管理和项目跟踪。

  • by Techthos
  • Go
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 Techthos/clockwork

使用说明

⚙️ 发条装置

基于Git的自动时间跟踪

通过强大的MCP服务器和交互式终端UI,通过git提交自动跟踪您的工作时间

特性 • 安装 • 快速开始 • 用法 • 文档


🎯 概述

发条装置 是一个双模时间跟踪系统,可以将git提交转换为可操作的工作日志条目。无论您喜欢通过人工智能助手(MCP模式)还是交互式终端界面(TUI模式)工作,Clockwork都能满足您的需求。

🎭 两种模式,一个数据库

🤖 MCP服务器模式 -与Claude和其他LLM应用程序集成

  • 将时间跟踪作为MCP工具公开
  • 自然语言交互:“追踪最后2小时的工作”
  • 与您的AI工作流程无缝集成

💻 TUI模式 -交互式终端界面

  • 功能齐全的终端用户界面,可直接交互
  • 使用键盘快捷键浏览项目和条目
  • 实时统计和过滤
  • 非常适合快速评论和手动输入

✨ 特性

📊 智能时间追踪

  • 自动提交聚合 -收集自上次输入以来的提交
  • 智能工期计算 -根据提交时间戳估算工作时间
  • 自定义覆盖 -需要时手动调整持续时间和消息
  • 灵活的条目创建 -基于Git或手动输入模式

🎨 丰富的终端用户界面

  • 项目仪表板 -所有项目的可视化概述
  • 条目浏览器 -可排序、可过滤的条目列表及其摘要
  • 统计视图 -按项目和发票状态分列的时间明细
  • 键盘驱动 -无需触摸鼠标即可高效导航
  • 颜色编码 -发票/未开票状态一目了然

🔧 项目管理

  • 多项目支持 -跨无限项目跟踪时间
  • 灵活的提交来源 -每个项目选择如何找到其提交:无、本地git仓库或由MCP客户端提供
  • 发票跟踪 -将条目标记为已开票
  • 高级过滤 -按项目、日期范围或发票状态

💾 数据库与集成

  • 嵌入式数据库 -bbolt键值存储,无外部依赖
  • 单文件存储 - ~/.local/clockwork/default.db
  • MCP协议 -适用于Claude Desktop、Claude Code和其他MCP客户端
  • 数据持久层 -会话之间安全存储的所有数据

🚀 安装

先决条件

从源代码构建

# Clone the repository
git clone https://github.com/techthos/clockwork.git
cd clockwork

# Build the static binary to ./bin/clockwork
make build

# Or install to $GOPATH/bin
make install

验证安装

# The binary supports two modes
./bin/clockwork      # Starts terminal UI (default)
./bin/clockwork mcp      # Starts MCP server

# Either mode can point at a specific database file
./bin/clockwork --db /path/to/clockwork.db

⚡ 快速开始

🤖 MCP服务器模式

1.配置您的MCP客户端

Claude 桌面版 (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "clockwork": {
      "command": "/absolute/path/to/clockwork",
      "args": ["mcp"]
    }
  }
}

克劳德代码命令行界面 (~/.claude/config.json):

{
  "mcpServers": {
    "clockwork": {
      "command": "/absolute/path/to/clockwork",
      "args": ["mcp"]
    }
  }
}

💡 小贴士:使用 $(go env GOPATH)/bin/clockwork 如果你跑了 go install

2.重新启动MCP客户端

时钟工具现在将在您的Claude会话中可用。

3.开始跟踪

You: "Create a new project called 'Website Redesign' in /home/user/projects/website"

You: "Track the work I did today on the website project"

💻 TUI模式

1.推出TUI

./bin/clockwork

2.创建你的第一个项目

  • 按 n 创建新项目
  • 输入项目名称和git存储库路径
  • 按Tab键导航,按Enter键保存

3.创建您的第一个条目

  • 按项目上的Enter键查看其条目
  • 按 n 创建新条目
  • 选择Git模式(自动聚合提交)或手动模式
  • 填写详细信息并保存

4.探索统计

  • 在条目视图中,按 s 查看统计数据
  • 按项目和发票状态查看时间细分
  • 使用 f 应用筛选器

📖 用法

💻 TUI模式参考

全局快捷方式

  • Ctrl+C 或 Ctrl+Q -退出应用程序
  • Tab -浏览表单字段
  • Esc -关闭模式/取消

项目视图

  • n -新项目
  • e -编辑所选项目
  • d -删除所选项目(确认后)
  • Enter -查看项目条目
  • q -退出应用程序
  • ↑/↓ -导航列表

条目视图

  • n -新条目(选择git或手动模式)
  • e -编辑所选条目
  • d -删除所选条目
  • i -切换发票状态
  • f -配置筛选器
  • s -查看统计数据
  • q -返回项目
  • ↑/↓ -导航列表

统计视图

  • f -配置筛选器
  • r -刷新统计信息
  • q -返回条目

条目创建模式

Git模式 (自动):

  1. 选择项目
  2. Clockwork获取自上次输入以来的提交
  3. 根据时间戳自动计算持续时间
  4. 根据提交摘要自动生成消息
  5. 可选:覆盖持续时间或消息

手动模式:

  1. 选择项目
  2. 输入持续时间(格式: 1h 30m, 90m, 1.5h)
  3. 输入消息/描述
  4. 标记为已开票(可选)

过滤

在条目或统计视图中应用筛选器:

  • 项目 -选择特定项目或“所有项目”
  • 日期范围 -开始/结束日期(格式:YYYY-MM-DD)
  • 发票状态 -全部、仅开票或仅未开票

🤖 MCP模式参考

可用工具

工具 说明 示例
create_project 新建项目 在创建项目“API服务器” /code/api
get_commit_baseline 显示项目的源代码和上次提交哈希 我应该从哪个提交开始?
update_project 更新项目详细信息 将项目重命名为“API v2”
delete_project 删除项目和所有条目 删除API项目
list_projects 列出所有项目 显示我的所有项目
create_entry 通过提交或手动创建工作日志 跟踪API项目上的2小时
update_entry 更新条目详细信息 将上次条目标记为已开票
delete_entry 删除条目 删除昨天的条目
list_entries 列出带有过滤器、搜索、排序、分页的条目 显示上个月未发音的条目
new_project_form / edit_project_form 打开交互式项目窗体 显示一个窗体以添加项目
new_entry_form / edit_entry_form 打开互动报名表 让我手工填写

交互式小部件(MCP应用程序)

支持MCP Apps扩展的主机(io.modelcontextprotocol/ui)渲染 项目和条目工具,如交互式表格和表单。小部件注册为 ui://clockwork/... 资源并从工具定义链接,因此表会重新绘制 每次创建、更新或删除后,行都会执行编辑和删除操作,并形成表单 提交调用的工具与模型使用的工具相同。没有扩展名的主机请参阅 正常工具结果。

自然语言示例

"Create a new project called 'Mobile App' at /Users/me/code/mobile"

"Track my work today on the mobile app project"

"Show me all uninvoiced time entries"

"Mark the last 3 entries as invoiced"

"How much time did I spend on the API project this week?"

"Create a manual entry for 2 hours of meeting time on the mobile project"

程序化API

// Create a project backed by a local git repository
create_project({
  name: "My Project",
  source_type: "local",
  git_repo_path: "/absolute/path/to/repo"
})

// Create a project with no repository at all (manual entries only)
create_project({
  name: "Consulting",
  source_type: "none"
})

// Create a project whose commits you look up yourself
create_project({
  name: "Remote App",
  source_type: "mcp",
  repository: "owner/remote-app"
})

// Create entry from git commits (source_type "local", automatic)
create_entry({
  project_id: "project-uuid",
  invoiced: false
})

// Create entry from commits you fetched yourself (source_type "mcp")
get_commit_baseline({ project_id: "project-uuid" })
// → { source_type: "mcp", repository: "owner/remote-app", last_commit_hash: "abc123..." }

create_entry({
  project_id: "project-uuid",
  commits: [
    { hash: "3f2a91c...", author: "Alex", message: "feat: add widget",
      timestamp: "2026-07-20T09:00:00Z" }
  ]
})

// Create manual entry (no git aggregation)
create_entry({
  project_id: "project-uuid",
  duration: 120,  // minutes
  message: "Client meeting and planning",
  invoiced: false
})

// List entries with filters, search, ordering and pagination
list_entries({
  project_id: "project-uuid",  // optional, empty = all projects
  start_date: "2025-01-01",    // optional
  end_date: "2025-01-31",      // optional
  invoiced: false,             // optional, null = all entries
  search: "invoice",           // optional, matches message, commit hash, project name
  sort_by: "created_at",       // optional: created_at | updated_at | duration | message
  order: "desc",               // optional: desc (default) | asc
  page: 1,                     // optional, 1-based
  page_size: 50                // optional, clamped to 50
})
// → rows plus page, page_size, total, total_pages, has_more

// Update entry
update_entry({
  id: "entry-uuid",
  duration: 180,      // optional
  message: "Updated", // optional
  invoiced: true      // optional
})

🔧 运作原理

提交聚合流

┌─────────────────┐
│  Last Entry     │
│  commit_hash    │
└────────┬────────┘
         │
         ▼
┌─────────────────────────────┐
│  git log <hash>..HEAD       │
│  Fetch new commits          │
└────────┬────────────────────┘
         │
         ▼
┌─────────────────────────────┐
│  Aggregate commit messages  │
│  Calculate duration         │
└────────┬────────────────────┘
         │
         ▼
┌─────────────────────────────┐
│  Create worklog entry       │
│  Store latest commit hash   │
└─────────────────────────────┘

持续时间计算逻辑

  • 单次提交 → 默认30分钟
  • 多次提交 → (last_commit_time - first_commit_time) + 30 minutes

示例:上午9:00和11:30提交

  • 时间跨度:2.5小时
  • 缓冲时间:0.5小时
  • 总时长:3小时(180分钟)

数据库模式

~/.local/clockwork/default.db (bbolt)
├── projects/
│   └── <uuid> → {id, name, source_type, git_repo_path?, repository?, created_at, updated_at}
└── entries/
    └── <uuid> → {id, project_id, duration, message, commit_hash, invoiced, created_at, updated_at}

📊 数据模型

项目

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Website Redesign",
  "source_type": "local",
  "git_repo_path": "/home/user/projects/website",
  "created_at": "2025-01-27T10:00:00Z",
  "updated_at": "2025-01-27T10:00:00Z"
}

进入

{
  "id": "660e8400-e29b-41d4-a716-446655440001",
  "project_id": "550e8400-e29b-41d4-a716-446655440000",
  "duration": 180,
  "message": "Aggregated 3 commits:\n1. [abc123d] Implement login form\n2. [def456e] Add form validation\n3. [ghi789f] Update styles",
  "commit_hash": "ghi789f...",
  "invoiced": false,
  "created_at": "2025-01-27T14:30:00Z",
  "updated_at": "2025-01-27T14:30:00Z"
}

统计

{
  "total_minutes": 540,
  "total_hours": 9.0,
  "entry_count": 3,
  "invoiced_minutes": 180,
  "uninvoiced_minutes": 360,
  "project_breakdown": {
    "project-uuid-1": 300,
    "project-uuid-2": 240
  },
  "earliest_entry": "2025-01-20T09:00:00Z",
  "latest_entry": "2025-01-27T14:30:00Z"
}

🛠️ 发展

运行测试

# All tests
go test ./...

# With coverage
go test -cover ./...

# Verbose output
go test ./... -v

# Specific package
go test ./internal/db -v
go test ./internal/git -v

项目结构

clockwork/
├── cmd/
│   └── clockwork/          # Main entry point
├── internal/
│   ├── db/                 # Database operations (bbolt)
│   ├── models/             # Data structures
│   ├── git/                # Git integration
│   ├── server/             # MCP server implementation
│   ├── tui/                # Terminal UI components
│   │   ├── app.go          # Main TUI app structure
│   │   ├── projects.go     # Projects view
│   │   ├── entries.go      # Entries view
│   │   ├── stats.go        # Statistics view
│   │   ├── modals.go       # Dialog boxes
│   │   ├── theme.go        # Color scheme
│   │   └── helpers.go      # Utilities
│   └── utils/              # Shared utilities
├── go.mod
├── go.sum
├── CLAUDE.md               # AI assistant context
└── README.md

生产大楼

# Build with optimizations (static, like release assets)
CGO_ENABLED=0 go build -ldflags="-s -w" -o bin/clockwork ./cmd/clockwork

# Build for specific platform
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/clockwork-linux ./cmd/clockwork
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o bin/clockwork-macos ./cmd/clockwork
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o bin/clockwork.exe ./cmd/clockwork

⚠️ 重要说明

数据库锁定

TUI和MCP服务器可以同时运行。 Clockwork打开bbolt文件 操作--只读用于读取,读写用于写入--并再次关闭它,因此是一个空闲进程 没有锁。两者之间的冲突将以回退方式重试(75毫秒尝试,3秒预算) 在报道之前。

  • ✅ TUI和MCP服务器并排在一个数据库上
  • ⚠️ Writes仍然序列化:第二个writer等待第一个writer完成其(短)操作
  • ⚠️ TUI在导航时重新加载;MCP服务器写入时,它不会自动刷新

错误: open bbolt at "...": timeout --有什么东西锁住了锁3秒钟多。检查 对于同一文件上的卡住进程。

细节和权衡: docs/bbolt-concurrent-access-strategy.md.

数据库位置

在一个地方解决(db.DefaultPath()),最高优先级优先:

来源 价值
--db <path> 旗帜 逐字使用;两种模式都接受(clockwork --db ..., clockwork mcp --db ...)
CLOCKWORK_DB env-var 逐字使用(空值计为未设置)
默认值 ~/.local/clockwork/default.db

路径完全按照给定的方式使用——shell会扩展 ~,发条不会。

提交来源

存储库是可选的。每个项目都声明一个 source_type:

source_type 定位器字段 提交来自哪里
none --无处可去。只能手动输入。
local git_repo_path 这台机器上的git存储库,由git CLI的发条读取。
mcp repository 时钟不会查找它们。调用客户端(通常是可以访问存储库MCP服务器或API的AI)获取它们并将其传递给 create_entry 在 commits 阵列。

之前创建的项目 source_type 存在被读取为 local 当他们 具有存储库路径,并且 none 如果没有,则不需要迁移。

对于 source_type: "local":

  • 路径必须是有效的git存储库
  • 存储库必须至少有一个提交
  • Git必须在系统PATH中可访问

对于 source_type: "mcp":

  • 叫 get_commit_baseline 学习上次记录的提交哈希
  • 使用您自己的工具获取提交后的提交
  • 将它们传递给 create_entry;每次提交都需要一个 message和a timestamp 除非你也通过一个明确的 duration
  • TUI无法为这些项目创建git模式条目,因为没有客户端 提供提交——在那里使用手动条目

🐛 故障排除

“未找到新提交”

原因:最后一个条目和HEAD之间不存在提交

解决方案:进行新的提交,然后创建一个条目

“获取git作者失败”

原因:Git配置不正确

解决方案:

git config user.name "Your Name"
git config user.email "your@email.com"

“未找到项目”

原因:项目ID无效或项目已删除

解决方案:列出要验证的项目:

# In TUI: View projects screen
# In MCP: Use list_projects tool

“工期格式无效”

原因:持续时间格式不可识别

解决方案:使用以下格式之一:

  • 1h 30m -小时和分钟
  • 90m -仅分钟
  • 1.5h -十进制小时数
  • 90 -普通数字(以分钟计)

数据库损坏

罕见但可能如果数据库损坏:

# Backup current database
cp ~/.local/clockwork/default.db ~/.local/clockwork/backup.db

# Remove corrupted database
rm ~/.local/clockwork/default.db

# Clockwork will create a new database on next run

🤝 贡献

欢迎投稿!方法如下:

  1. 分叉存储库
  2. 创建要素分支(git checkout -b feature/amazing-feature)
  3. 进行更改
  4. 添加新功能的测试
  5. 确保所有测试通过(go test ./...)
  6. 提交您的更改(git commit -m 'Add amazing feature')
  7. 推到分支(git push origin feature/amazing-feature)
  8. 打开拉取请求

代码风格

  • 遵循标准Go格式(gofmt)
  • 为导出的函数添加注释
  • 保持功能的专注性和可测试性
  • 更新测试以了解任何更改

📝 许可证

MIT许可证-请参阅 许可证 详情

🙏 致谢

基于这些优秀的开源项目构建:

  • mcp走 -Mark3 Labs的模型上下文协议实现
  • bbolt -Pure Go嵌入式键值数据库
  • tview -丰富的终端UI库
  • T细胞 -基于终端单元的视图库

🔗 链接


由以下材料制成⚙️ 和❤️ 由Techthos团队

自动化您的时间跟踪。专注于创造伟大的事物。

由以下人员建造和维护 Techthos.