Clockwerk

A local work history engine. Hooks into your AI tools, timestamps every interaction, and groups activity into sessions based on idle gaps. Everything stays in local SQLite. No accounts, no cloud, no telemetry.

MIT licensed·GitHub·Claude Code · Cursor · Copilot

Getting Started

Get started with Clockwerk

A local work history engine for developers. Reconstructs work sessions from tool activity, stored on your machine.

Clockwerk is a local work history engine. It reconstructs developer work sessions from activity signals - every prompt, edit, and command in your tools already has a timestamp. Clockwerk turns those into sessions.

Warning

Clockwerk is in early access and evolving rapidly. Features, commands, and APIs may change between releases. For the best experience, always run the latest version. The CLI will warn you when a new version is available.

How it works

The pipeline is: activity signals (hooks in your tools) produce raw events, which are stored in local SQLite. A session detection algorithm groups events into sessions based on activity gaps. The result is a complete work history.

Everything runs locally. Events are stored on your machine, sessions are computed on your machine, and corrections happen on your machine. Nothing ever leaves your machine.

Install

cli
$ bun add -g @getclockwerk/cli
✓ Installed clockwerk

Supports Linux and macOS (x64 and ARM). Also available via npm: npm install -g @getclockwerk/cli.

Initialize a project

cli
$ clockwerk init
Project name (my-project):
Detected: Claude Code, Cursor
Install hooks? (Y/n)
✓ Created .clockwerk config

Run this in any project directory. It creates a local config, auto-detects your AI tools, and offers to install hooks for automatic tracking.

Start tracking

cli
$ clockwerk up
✓ Daemon started

The daemon runs in the background and picks up activity from your hooks automatically. Use clockwerk status to see your tracked time.

Check your status

cli
$ clockwerk status
Daemon: running (pid 12345)
Project: my-project
Today: 2h 30m (3 sessions)

That's it. Sessions are being computed from your tool activity. Use clockwerk list today to inspect sessions from the CLI, open Studio for a visual overview, or export to CSV for billing.

Local-first architecture

Raw activity data never leaves your machine. Events are stored in local SQLite and sessions are computed locally. Clockwerk never captures your source code, prompts, credentials, or keystrokes.

Open source

Clockwerk is open source on GitHub. MIT licensed. You can audit what gets tracked and how sessions are computed.

Getting Started

Installation

Install Clockwerk on Linux or macOS via npm or bun.

Quick install

cli
$ bun add -g @getclockwerk/cli

Or with npm:

cli
$ npm install -g @getclockwerk/cli

The package includes pre-compiled binaries for your platform. No build step needed.

Supported platforms

Linuxx64 and ARM64
macOSx64 (Intel) and ARM64 (Apple Silicon)

Note

Windows is not currently supported. Use WSL2 for Windows development.

Verify installation

cli
$ clockwerk help
clockwerk vX.X.X - local work history engine
 
Usage: clockwerk <command> [options]

Uninstall

cli
$ clockwerk down
$ bun remove -g @getclockwerk/cli
$ rm -rf ~/.clockwerk

Warning

Removing ~/.clockwerk deletes your local event history and session data. To keep a backup, copy the directory before uninstalling: cp -r ~/.clockwerk ~/.clockwerk-backup

Stop the daemon, remove the package, and delete the config directory. Project-level .clockwerk files can be removed individually.

Getting Started

Open Source

Clockwerk's core packages are open source. Audit, extend, and contribute.

Why open source

Time tracking tools have access to sensitive data about your work patterns, projects, and workflow. We believe you should be able to verify exactly what data is collected and where it goes. That's why Clockwerk's CLI and core packages are open source.

What's open source

@clockwerk/coreEvent schema, SQLite database layer, session computation, materialization, and config management. This is the engine that computes sessions from raw events.
@clockwerk/cliThe full CLI and background daemon. Commands, hook parsers, plugin system, Studio, and file watcher. Everything that runs on your machine.
@clockwerk/hooksHook adapter configurations for Claude Code, Cursor, Copilot, and other AI tools.

Note

Browse the source at github.com/getclockwerk/clockwerk.

What you can verify

With the source available, you can audit:

Data collectionSee exactly which events are captured by each hook and plugin, and what context they carry
Session computationReview the gap-based algorithm that groups events into sessions, including the 5-minute gap and 1-minute minimum
Export outputVerify exactly what fields are included in CSV and JSON exports
Local storageCheck the SQLite schema and see exactly what's stored in ~/.clockwerk/clockwerk.db

Architecture

Clockwerk is built with Bun and TypeScript. The CLI compiles to a single standalone binary with no runtime dependencies. Events are stored in a local SQLite database and sessions are computed on-device.

RuntimeBun (compiled to standalone binary)
Local storageSQLite via bun:sqlite
IPCUnix domain socket for daemon communication
StudioLocal web UI via Hono, served from the CLI on localhost

Contributing

Contributions are welcome. File issues, submit pull requests, or build your own integrations. Check the GitHub repository for setup instructions and contribution guidelines.

Tracking

Init

Initialize Clockwerk in a project directory.

Interactive mode

Run clockwerk init in any project directory. It prompts for a project name, detects installed AI tools, and offers to install hooks.

cli
$ clockwerk init
Project name (my-project):
Detected: Claude Code, Cursor
Install hook for Claude Code? (Y/n)
Install hook for Cursor? (Y/n)
✓ Created .clockwerk config
✓ Installed 2 hooks

Non-interactive mode

Pass the project name as an argument to skip the prompt:

cli
$ clockwerk init my-project
✓ Created .clockwerk config
✓ Installed hooks for Claude Code

The .clockwerk file

Init creates a .clockwerk JSON file in your project root:

.clockwerk
{
  "version": 1,
  "project_name": "my-project",
  "project_token": "local_my-project",
  "harnesses": {
    "claude-code": true,
    "cursor": true
  }
}

Tip

Add .clockwerk to your .gitignore. The init command does this automatically if a .gitignore exists.

Hook auto-detection

During init, Clockwerk checks for the presence of AI tool config directories:

Claude CodeDetected via ~/.claude/
CursorDetected via ~/.cursor/
CopilotDetected via ~/.copilot/

Tracking

Daemon

Start and stop the Clockwerk background daemon.

Start the daemon

cli
$ clockwerk up
✓ Daemon started

The daemon runs in the background, listens for events from hooks and plugins, and computes sessions from activity gaps.

clockwerk up

Start the background daemon.

FlagDescriptionDefault
-f, --foregroundRun in foreground with log output to stdout-

Stop the daemon

cli
$ clockwerk down
✓ Daemon stopped

Sends SIGTERM for a graceful shutdown. If the daemon doesn't stop within 2 seconds, it's force-killed.

Foreground mode

Useful for debugging. Logs are printed to stdout instead of the log file:

cli
$ clockwerk up --foreground
[INFO] Daemon started on /home/you/.clockwerk/daemon.sock
[INFO] Loaded 2 plugins
[INFO] Event received: tool_call from claude-code

How it works

The daemon communicates over a Unix socket using a simple RPC protocol. Hooks and plugins send events to the socket, and the daemon stores them in a local SQLite database.

Socket~/.clockwerk/daemon.sock
PID file~/.clockwerk/daemon.pid
Log file~/.clockwerk/daemon.log
Database~/.clockwerk/clockwerk.db (SQLite)

Note

The daemon must be running for hooks and plugins to work. Use clockwerk status to check if it's running.

Tracking

Status

Check the current tracking status and today's progress.

Usage

cli
$ clockwerk status
Daemon: running (pid 12345)
Project: my-project
Today: 2h 30m (3 sessions)
 
Plugins:
docker-logs 12 events last: 2m ago
git-activity 5 events last: 8m ago

Output breakdown

DaemonWhether the daemon is running and its process ID
ProjectThe project name from your .clockwerk config
TodayTotal tracked time and session count for today
PluginsActive plugins with event counts and last event timestamp

When the daemon is stopped

cli
$ clockwerk status
Daemon: stopped
Project: my-project

When the daemon is not running, today's time and plugin info are not available. Run clockwerk up to start tracking.

Tracking

Manual logging

Manually log time for meetings, calls, or offline work.

Usage

clockwerk log <duration> [description]

Manually log time with an optional description.

Duration formats

2h2 hours
45m45 minutes
1h30m1 hour 30 minutes
3030 minutes (plain number)

Examples

cli
$ clockwerk log 2h "client meeting"
✓ Logged 2h 0m
cli
$ clockwerk log 45m "code review"
✓ Logged 45m
cli
$ clockwerk log 1h30m
✓ Logged 1h 30m

How it works

Manual log entries create events at 4-minute intervals, which is under the 5-minute session gap threshold. This means the logged time appears as a single continuous session.

Note

The daemon must be running to log time. Manual entries use the source "manual" and event type "manual".

Tracking

Daemon logs

View and follow the daemon log output.

Usage

clockwerk logs

Display daemon log output.

FlagDescriptionDefault
-f, --followStream logs in real-time-
-n, --lines <n>Number of lines to show50
-l, --level <level>Filter by level (DEBUG, INFO, WARN, ERROR)-

Examples

cli
$ clockwerk logs -f
[INFO] Event received: tool_call from claude-code
[INFO] Session computed: 45m (12 events)
[INFO] Session materialized: 1h 25m from claude-code
cli
$ clockwerk logs --level ERROR -n 20

Log levels

DEBUGVerbose output for troubleshooting
INFONormal operation events
WARNNon-critical issues
ERRORFailures that need attention

Log file location

Logs are written to ~/.clockwerk/daemon.log. The logs command reads this file directly.

Integrations

Hooks

Automatic time tracking via AI tool integrations.

How hooks work

Hooks are post-tool-use callbacks that fire whenever your AI tool executes an action (editing a file, running a command, etc.). Each hook invocation sends an event to the Clockwerk daemon with context about what happened.

Hooks capture: tool name, file paths, session IDs, working directory, and timestamps. All hooks have a 5-second timeout to avoid slowing down your tools.

Auto-install

cli
$ clockwerk hook install
Detected: Claude Code, Cursor
✓ Installed hook for Claude Code
✓ Installed hook for Cursor

Auto-detect checks for tool config directories in your home folder and installs the appropriate hook configuration.

Install a specific hook

cli
$ clockwerk hook install claude-code

Available hook IDs: claude-code, cursor, copilot.

Claude Code

Installs a PostToolUse hook in ~/.claude/settings.json that fires on all tool calls.

~/.claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "clockwerk hook claude-code",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

Captured data: tool name (Edit, Write, Bash, Read, etc.), session ID, file paths from tool input, and working directory.

Cursor

Installs a postToolUse hook in ~/.cursor/hooks.json.

~/.cursor/hooks.json
{
  "hooks": [
    {
      "event": "postToolUse",
      "command": "clockwerk hook cursor",
      "timeout": 5000
    }
  ]
}

Captured data: tool name, conversation ID, tool arguments, working directory.

GitHub Copilot

Installs a postToolUse hook in .github/hooks/clockwerk.json within your project.

.github/hooks/clockwerk.json
{
  "hooks": [
    {
      "event": "postToolUse",
      "command": "clockwerk hook copilot",
      "timeout": 5000
    }
  ]
}

Event data

Each hook invocation extracts the following from the tool's JSON input:

tool_nameThe tool that was called (Edit, Write, Bash, Read, Grep, etc.)
file_pathThe file being operated on, made relative to the project root
descriptionTruncated to 200 characters
branchCurrent git branch, if available
issue_idAuto-extracted from branch names matching ISSUE-123 pattern

Source override

By default, each hook sets the event source based on the tool that triggered it. You can override this for all events in a process by setting the CLOCKWERK_SOURCE environment variable before running your agent.

This is useful for autonomous agent loops and headless runs where no human is interacting with the tool directly. Setting the source to autonomous signals that the session was machine-driven rather than human-driven.

# Run a headless agent loop with autonomous tracking
export CLOCKWERK_SOURCE=autonomous
claude -p "Run the test suite and fix any failures"

Note

Autonomous sessions appear in Studio and CLI output but are excluded from time totals by default. Use the source filter to include or inspect them.

Integrations

PluginsBeta

Track time from custom tools with the plugin system.

Overview

Plugins let you track time from any tool or process. A plugin is a shell command that outputs events. Clockwerk runs it on an interval and records the output as tracking events.

Plugins can be installed from the registry with a single command, or defined inline for custom tooling. The plugin registry is hosted on GitHub and community contributions are welcome.

Install from registry

Install a plugin by name. Clockwerk fetches the plugin manifest and script from the registry and installs it to ~/.clockwerk/plugins/.

cli
$ clockwerk plugin add git-activity
✓ Plugin 'git-activity' installed (v1.0.0)

Browse available plugins at getclockwerk.com/plugins.

Install inline

Define a plugin inline without a registry entry by passing --command directly:

cli
$ clockwerk plugin add my-tool --command "my-tool status --json" --event-type tool_call --interval 30
✓ Plugin 'my-tool' added
FlagDescriptionDefault
--command <cmd>Shell command to execute-
--template <name>Use a built-in template-
--event-type <type>Event type to recordmanual
--source <source>Source identifierplugin:<name>
--interval <secs>Minimum seconds between events1

Templates

Built-in templates for common tools:

docker-logsTrack Docker container activity
figma-activityTrack Figma file edits via REST API
git-activityTrack git commits and operations
ci-statusTrack CI/CD pipeline runs
cli
$ clockwerk plugin add docker --template docker-logs
✓ Plugin 'docker' added

Plugin manifest format

Registry plugins are defined by a plugin.json manifest file. This file describes the plugin and how Clockwerk should run it:

plugin.json
{
  "name": "my-plugin",
  "version": "1.0.0",
  "display_name": "My Plugin",
  "description": "A short description of what this plugin tracks.",
  "author": "Your Name",
  "event_type": "manual",
  "source": "plugin:my-plugin",
  "command": "./plugin.sh",
  "interval": 5,
  "tags": ["example"]
}
nameUnique identifier, 2-64 chars, lowercase alphanumeric with hyphens
versionSemver version string (e.g. 1.0.0)
display_nameHuman-readable name shown in the registry
descriptionShort description of what the plugin tracks
authorPlugin author name
event_typeEvent type emitted by the plugin
sourceSource identifier, 2-64 chars, alphanumeric with hyphens and colons
commandShell command to execute (relative paths resolved from plugin dir)
intervalMinimum seconds between executions (optional, default: 1)
tagsArray of tags for registry filtering (optional)

Manage plugins

cli
$ clockwerk plugin list
docker-logs interval: 30s source: plugin:docker-logs
git-activity interval: 60s source: plugin:git-activity
cli
$ clockwerk plugin test docker-logs
Running plugin...
Event: tool_call from plugin:docker-logs
✓ Plugin output valid
cli
$ clockwerk plugin remove docker-logs
✓ Plugin 'docker-logs' removed

Update plugins

Check all installed registry plugins for newer versions and apply updates interactively:

cli
$ clockwerk plugin update
git-activity 1.0.0 -> 1.1.0 available
Update git-activity? (y/N)
✓ git-activity updated to 1.1.0

Create a plugin

Scaffold a new plugin from the official template. This generates a plugin.json and plugin.sh in a new directory under plugins/:

cli
$ clockwerk plugin create my-plugin
✓ Plugin scaffolded at plugins/my-plugin/
Edit plugin.json to describe your plugin
Edit plugin.sh to implement event output
Run: clockwerk plugin test my-plugin

Contribute a plugin

Anyone can publish a plugin to the Clockwerk registry. To contribute:

ForkFork the clockwerk repository on GitHub
CreateRun clockwerk plugin create <name> to scaffold from the template, then implement plugin.sh
Open a PRSubmit a pull request adding your plugin directory under plugins/ - include a complete plugin.json and a working plugin.sh

Once merged, the plugin becomes available via clockwerk plugin add <name> for all users.

Valid event types

tool_callA tool or command was executed
file_editA file was modified
file_readA file was read
chat_messageA chat message was sent
completion_acceptA code completion was accepted
git_commitA git commit was made
manualManual or custom event
heartbeatPeriodic presence signal

Source naming

Plugin sources must be 2-64 characters, lowercase alphanumeric with hyphens and colons allowed. By default, the source is plugin:<name>.

Integrations

Studio

A local web UI for browsing, editing, and managing your tracked sessions.

Clockwerk Studio is a local web interface for your time data. It reads directly from your SQLite database - no cloud, no daemon dependency for reads, no latency.

Launch

cli
$ clockwerk studio
Clockwerk Studio running at http://localhost:3111

Opens a local web server and your browser. The daemon must be running for write operations (editing descriptions, deleting sessions), but reads work independently.

Custom port

cli
$ clockwerk studio --port=4000
Clockwerk Studio running at http://localhost:4000

Dashboard

The landing page shows your day at a glance: total time tracked today and this week, average daily hours, and a list of today's sessions. Click any session to see its full detail.

Session browser

The sessions page lists all tracked sessions grouped by date. Filter by period - today, yesterday, this week, or this month. Each row shows the time range, duration, source, branch, and description if one exists.

Session detail

Drill into any session to see the full metadata: source, branch, issue ID, event count, topics, file areas, individual files changed, git commits, and tools used. Edit the description inline or delete the session entirely.

How it reads data

Studio opens your local SQLite database in read-only mode for every page load. No socket connections, no daemon queries, no timeouts. Writes (description edits, deletes) go through the daemon.

Tip

Studio reads directly from SQLite in read-only mode. Edits and deletes go through the daemon to ensure data consistency.

Data

Sessions & Events

How Clockwerk computes sessions from raw events.

Events

Everything Clockwerk tracks starts as an event: a timestamped record of something that happened. Events are generated by hooks, plugins, manual logging, and file watching.

Event types

tool_callAn AI tool executed a command (Edit, Write, Bash, etc.)
file_editA file was modified
file_readA file was read or opened
chat_messageA chat message was sent in an AI tool
completion_acceptA code completion suggestion was accepted
git_commitA git commit was created
manualManually logged time or custom plugin events
heartbeatPeriodic signal from file watcher or plugin

Sources

claude-codeEvents from Claude Code hooks
cursorEvents from Cursor hooks
copilotEvents from GitHub Copilot hooks
manualEvents from clockwerk log
file-watchEvents from the file watcher
plugin:*Events from custom plugins
autonomousEvents from headless/autonomous AI agent runs

Session computation

Clockwerk groups events into sessions using a gap-based algorithm. Sessions are computed incrementally on your machine - each new event either extends an existing session or starts a new one.

5-minute gapIf more than 5 minutes pass between events, a new session starts
1-minute minimumSessions shorter than 60 seconds are padded to 1 minute
Branch partitioningEvents on different branches create separate sessions
IncrementalSessions are materialized as events arrive, not recomputed from scratch

Session data

Each session aggregates data from its events:

DurationWall-clock time from first to last event (min 60 seconds)
SourceMost common source across events
BranchGit branch from the first event with branch context
Issue IDAuto-extracted from branch names (e.g. PROJ-123)
TopicsDeduplicated topic tags from events
File areasTop-level directories from touched files
Tools usedUnique tool names from tool_call events
Event countTotal number of events in the session

Event context

Each event can carry optional context fields:

tool_nameName of the tool (max 64 chars)
descriptionWhat happened (max 200 chars)
file_pathRelative file path (max 512 chars)
branchGit branch (max 256 chars)
issue_idIssue tracker ID (max 64 chars)
topicTopic or category (max 200 chars)

Note

All events and sessions live in a local SQLite database on your machine. Raw events never leave your device. Use clockwerk export to extract session data as CSV or JSON.

Data

File Watching

Track activity from file system changes.

Overview

The file watcher monitors your project directory for changes and generates heartbeat events. This tracks development activity even when you're not using an AI tool, for example manual editing in VS Code or Vim.

Enable file watching

cli
$ clockwerk config set watch.enabled true
✓ Updated watch.enabled = true

Configuration

.clockwerk
{
  "watch": {
    "enabled": true,
    "interval": 30,
    "exclude": ["node_modules", ".git", "dist", "build"]
  }
}
enabledWhether file watching is active
intervalHeartbeat window in seconds (how often to emit events)
excludeGlob patterns for directories and files to ignore

How it works

The file watcher uses inotify (Linux) or FSEvents (macOS) to detect changes. When a file is modified, it generates a heartbeat event with the file path. Events are throttled by the interval setting to avoid noise.

Tip

File watching works well alongside hooks. Hook events capture AI tool usage, while file watching captures manual editing. Together they give a complete picture of your development time.

Default exclusions

Temporary and generated files are automatically excluded from session data:

.tmp, .tempTemporary files
.swp, .swoVim swap files
.bak, .origBackup files
~ (tilde suffix)Editor backup files

Data

Config

View and modify Clockwerk project configuration.

View config

cli
$ clockwerk config
Project: my-project
Token: local_my-project
Harnesses:
claude-code: enabled
cursor: enabled

Subcommands

clockwerk config

Show all project settings.

clockwerk config name <name>

Set the project name.

clockwerk config set <key> <value>

Set a specific config value.

Available config keys

FlagDescriptionDefault
watch.enabledEnable file system watchingfalse
watch.intervalHeartbeat interval in seconds30

Examples

cli
$ clockwerk config set watch.enabled true
✓ Set watch.enabled = true
cli
$ clockwerk config set watch.interval 60
✓ Updated watch.interval = 60
cli
$ clockwerk config name "My SaaS App"
✓ Project name set to "My SaaS App"

The .clockwerk file

All project configuration is stored in the .clockwerk file at your project root. This is a JSON file that can be edited directly or managed via the config command.

.clockwerk
{
  "version": 1,
  "project_name": "my-project",
  "project_token": "local_my-project",
  "harnesses": {
    "claude-code": true,
    "cursor": true
  },
  "watch": {
    "enabled": false,
    "interval": 30,
    "exclude": ["node_modules", ".git"]
  },
  "plugins": []
}

Data

Export

Export session data as CSV or JSON.

Usage

clockwerk export

Export tracked sessions.

FlagDescriptionDefault
--format <csv|json>Output formatcsv
--since <YYYY-MM-DD>Start date filter-
--allExport all history-
-o, --output <path>Write to file instead of stdout-

Examples

cli
$ clockwerk export
Date,Start,End,Duration,Project,Source,Branch,Topics,File Areas,Events
2025-01-15,09:00,11:30,2h 30m,my-project,claude-code,main,...
cli
$ clockwerk export --format json --since 2025-01-01
cli
$ clockwerk export --all -o timesheet.csv
✓ Exported 142 sessions to timesheet.csv

CSV format

The CSV output includes the following columns:

DateSession date (YYYY-MM-DD)
StartSession start time
EndSession end time
DurationFormatted duration (e.g. 2h 30m)
ProjectProject name
SourcePrimary event source
BranchGit branch
TopicsComma-separated topic tags
File AreasTop-level directories
EventsEvent count

Invoicing workflow

Export your tracked time for client invoicing:

cli
$ clockwerk export --since 2025-01-01 -o january.csv
✓ Exported 47 sessions to january.csv

Tip

The default export covers the last 7 days. Use --since for longer periods or --all for the complete history.

Data

Privacy

Your data stays on your machine. No cloud, no accounts, no telemetry.

Local-only by design

Clockwerk is built on a simple principle: your development data belongs to you. Everything is stored locally on your machine in a SQLite database. There is no cloud, no accounts, no telemetry. The CLI and core packages are open source so you can verify this yourself.

What Clockwerk stores

Clockwerk stores timestamped activity events and computed sessions in ~/.clockwerk/clockwerk.db:

TimestampsWhen tool interactions occurred
DurationComputed session length from activity gaps
SourceWhich tool generated the events (e.g. claude-code, cursor)
ContextOptional metadata like branch name, tool name, and file paths

What Clockwerk never stores

Clockwerk never captures or stores:

Source codeNo file contents, diffs, or code snippets
Prompts & conversationsYour AI tool conversations stay between you and your AI
CredentialsNo API keys, tokens, passwords, or secrets
Keystroke dataNo key logging or input monitoring
IDE configurationNo editor settings, extensions, or preferences
Network trafficNo request/response data from your applications

No network access

Clockwerk makes zero network requests. There is no cloud sync, no analytics, no update checks, no phone-home behavior. The daemon communicates exclusively over a local Unix socket.

Export is explicit

The only way data leaves your machine is through the clockwerk export command, which you run manually. Exports include session metadata (timestamps, duration, source) and are saved to a local file.

Audit it yourself

Clockwerk is open source. MIT licensed. You can read the implementation and inspect your local database directly with any SQLite client.