Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

24 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

βš™οΈ Clockwork

Automated Git-Based Time Tracking

Go Version License MCP Protocol Built with tview

Track your work time automatically through git commits with both a powerful MCP server and an interactive terminal UI

Features β€’ Installation β€’ Quick Start β€’ Usage β€’ Documentation


🎯 Overview

Clockwork is a dual-mode time tracking system that transforms your git commits into actionable worklog entries. Whether you prefer working through AI assistants (MCP mode) or an interactive terminal interface (TUI mode), Clockwork has you covered.

🎭 Two Modes, One Database

πŸ€– MCP Server Mode - Integrate with Claude and other LLM applications

  • Expose time tracking as MCP tools
  • Natural language interactions: "track the last 2 hours of work"
  • Seamless integration with your AI workflow

πŸ’» TUI Mode - Interactive terminal interface

  • Full-featured terminal UI for direct interaction
  • Browse projects and entries with keyboard shortcuts
  • Real-time statistics and filtering
  • Perfect for quick reviews and manual entries

✨ Features

πŸ“Š Smart Time Tracking

  • Automatic Commit Aggregation - Collects commits since your last entry
  • Intelligent Duration Calculation - Estimates work time from commit timestamps
  • Custom Overrides - Manually adjust duration and messages when needed
  • Flexible Entry Creation - Git-based or manual entry modes

🎨 Rich Terminal UI

  • Projects Dashboard - Visual overview of all your projects
  • Entries Browser - Sortable, filterable entry list with summaries
  • Statistics View - Time breakdowns by project and invoice status
  • Keyboard-Driven - Efficient navigation without touching the mouse
  • Color-Coded - Invoiced/uninvoiced status at a glance

πŸ”§ Project Management

  • Multi-Project Support - Track time across unlimited projects
  • Flexible Commit Sources - Each project chooses how its commits are found: none, a local git repo, or supplied by an MCP client
  • Invoice Tracking - Mark entries as invoiced for billing
  • Advanced Filtering - By project, date range, or invoice status

πŸ’Ύ Database & Integration

  • Embedded Database - bbolt key-value store, no external dependencies
  • Single File Storage - ~/.local/clockwork/default.db
  • MCP Protocol - Works with Claude Desktop, Claude Code, and other MCP clients
  • Data Persistence - All data safely stored between sessions

πŸš€ Installation

Prerequisites

Build from Source

# 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

Verify Installation

# 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

⚑ Quick Start

πŸ€– MCP Server Mode

1. Configure Your MCP Client

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

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

Claude Code CLI (~/.claude/config.json):

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

πŸ’‘ Tip: Use $(go env GOPATH)/bin/clockwork if you ran go install

2. Restart Your MCP Client

The Clockwork tools will now be available in your Claude sessions.

3. Start Tracking

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 Mode

1. Launch the TUI

./bin/clockwork

2. Create Your First Project

  • Press n to create a new project
  • Enter project name and git repository path
  • Press Tab to navigate, Enter to save

3. Create Your First Entry

  • Press Enter on a project to view its entries
  • Press n to create a new entry
  • Choose Git mode (auto-aggregates commits) or Manual mode
  • Fill in the details and save

4. Explore Statistics

  • From the entries view, press s to see statistics
  • View time breakdowns by project and invoice status
  • Use f to apply filters

πŸ“– Usage

πŸ’» TUI Mode Reference

Global Shortcuts

  • Ctrl+C or Ctrl+Q - Quit application
  • Tab - Navigate form fields
  • Esc - Close modal/cancel

Projects View

  • n - New project
  • e - Edit selected project
  • d - Delete selected project (with confirmation)
  • Enter - View project entries
  • q - Quit application
  • ↑/↓ - Navigate list

Entries View

  • n - New entry (choose git or manual mode)
  • e - Edit selected entry
  • d - Delete selected entry
  • i - Toggle invoiced status
  • f - Configure filters
  • s - View statistics
  • q - Back to projects
  • ↑/↓ - Navigate list

Statistics View

  • f - Configure filters
  • r - Refresh statistics
  • q - Back to entries

Entry Creation Modes

Git Mode (Automatic):

  1. Select project
  2. Clockwork fetches commits since last entry
  3. Auto-calculates duration from timestamps
  4. Auto-generates message from commit summaries
  5. Optional: Override duration or message

Manual Mode:

  1. Select project
  2. Enter duration (formats: 1h 30m, 90m, 1.5h)
  3. Enter message/description
  4. Mark as invoiced (optional)

Filtering

Apply filters in entries or statistics views:

  • Project - Select specific project or "All Projects"
  • Date Range - Start/end dates (format: YYYY-MM-DD)
  • Invoice Status - All, Invoiced Only, or Uninvoiced Only

πŸ€– MCP Mode Reference

Available Tools

Tool Description Example
create_project Create a new project Create project "API Server" at /code/api
get_commit_baseline Show a project's source and last commit hash What commit should I start from?
update_project Update project details Rename project to "API v2"
delete_project Delete project and all entries Delete the API project
list_projects List all projects Show all my projects
create_entry Create worklog from commits or manually Track 2 hours on the API project
update_entry Update entry details Mark last entry as invoiced
delete_entry Delete an entry Delete yesterday's entry
list_entries List entries with filters, search, ordering, pagination Show uninvoiced entries from last month
new_project_form / edit_project_form Open the interactive project form Show me a form to add a project
new_entry_form / edit_entry_form Open the interactive entry form Let me fill in an entry by hand

Interactive widgets (MCP Apps)

Hosts that support the MCP Apps extension (io.modelcontextprotocol/ui) render the project and entry tools as interactive tables and forms. The widgets are registered as ui://clockwork/... resources and linked from the tool definitions, so tables repaint after every create, update or delete, rows carry Edit and Delete actions, and form submissions call the same tools the model uses. Hosts without the extension see the normal tool results.

Natural Language Examples

"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"

Programmatic 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
})

πŸ”§ How It Works

Commit Aggregation Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Last Entry     β”‚
β”‚  commit_hash    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  git log <hash>..HEAD       β”‚
β”‚  Fetch new commits          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Aggregate commit messages  β”‚
β”‚  Calculate duration         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Create worklog entry       β”‚
β”‚  Store latest commit hash   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Duration Calculation Logic

  • Single commit β†’ Default 30 minutes
  • Multiple commits β†’ (last_commit_time - first_commit_time) + 30 minutes

Example: Commits at 9:00 AM and 11:30 AM

  • Time span: 2.5 hours
  • Buffer: 0.5 hours
  • Total duration: 3 hours (180 minutes)

Database Schema

~/.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}

πŸ“Š Data Models

Project

{
  "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"
}

Entry

{
  "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"
}

Statistics

{
  "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"
}

πŸ› οΈ Development

Running Tests

# 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

Project Structure

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

Building for Production

# 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

⚠️ Important Notes

Database Locking

The TUI and the MCP server can run at the same time. Clockwork opens the bbolt file per operation β€” read-only for reads, read-write for writes β€” and closes it again, so an idle process holds no lock. A collision between the two is retried with backoff (75ms attempts, 3s budget) before it is reported.

  • βœ… TUI and MCP server side by side on one database
  • ⚠️ Writes still serialize: the second writer waits for the first to finish its (short) operation
  • ⚠️ The TUI reloads on navigation; it does not auto-refresh when the MCP server writes

Error: open bbolt at "...": timeout β€” something held the lock for more than 3 seconds. Check for a stuck process on the same file.

Details and trade-offs: docs/bbolt-concurrent-access-strategy.md.

Database Location

Resolved in one place (db.DefaultPath()), highest precedence first:

Source Value
--db <path> flag used verbatim; accepted by both modes (clockwork --db ..., clockwork mcp --db ...)
CLOCKWORK_DB env var used verbatim (an empty value counts as unset)
default ~/.local/clockwork/default.db

Paths are used exactly as given β€” the shell expands ~, clockwork does not.

Commit Sources

A repository is optional. Each project declares a source_type:

source_type Locator field Where commits come from
none β€” Nowhere. Only manual entries are possible.
local git_repo_path A git repository on this machine, read by clockwork with the git CLI.
mcp repository Clockwork does not look them up. The calling client β€” typically an AI with access to a repository MCP server or API β€” fetches them and passes them to create_entry in the commits array.

Projects created before source_type existed are read as local when they have a repository path and none when they do not, so no migration is needed.

For source_type: "local":

  • The path must be a valid git repository
  • The repository must have at least one commit
  • Git must be accessible in the system PATH

For source_type: "mcp":

  • Call get_commit_baseline to learn the last recorded commit hash
  • Fetch the commits made after it using your own tooling
  • Pass them to create_entry; each commit needs a message, and a timestamp unless you also pass an explicit duration
  • The TUI cannot create git-mode entries for these projects, since no client is present to supply the commits β€” use manual entries there

πŸ› Troubleshooting

"No new commits found"

Cause: No commits exist between the last entry and HEAD

Solution: Make new commits, then create an entry

"Failed to get git author"

Cause: Git not configured properly

Solution:

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

"Project not found"

Cause: Invalid project ID or project was deleted

Solution: List projects to verify:

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

"Invalid duration format"

Cause: Duration not in recognized format

Solution: Use one of these formats:

  • 1h 30m - Hours and minutes
  • 90m - Minutes only
  • 1.5h - Decimal hours
  • 90 - Plain number (treated as minutes)

Database Corruption

Rare but possible. If the database becomes corrupted:

# 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

🀝 Contributing

Contributions are welcome! Here's how:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass (go test ./...)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Code Style

  • Follow standard Go formatting (gofmt)
  • Add comments for exported functions
  • Keep functions focused and testable
  • Update tests for any changes

πŸ“ License

MIT License - see LICENSE for details

πŸ™ Acknowledgments

Built with these excellent open-source projects:

  • mcp-go - Model Context Protocol implementation by Mark3 Labs
  • bbolt - Pure Go embedded key-value database
  • tview - Rich terminal UI library
  • tcell - Terminal cell-based view library

πŸ”— Links


Made with βš™οΈ and ❀️ by the Techthos team

Automate your time tracking. Focus on building great things.

Built and maintained by Techthos.

About

Clockwork-MCP is a local executable MCP-Server that gives Agents the ability to simple track project worklogs.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages