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.
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
$ bun add -g @getclockwerk/cli✓ Installed clockwerkSupports Linux and macOS (x64 and ARM). Also available via npm: npm install -g @getclockwerk/cli.
Initialize a project
$ clockwerk initProject name (my-project):Detected: Claude Code, CursorInstall hooks? (Y/n)✓ Created .clockwerk configRun 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
$ clockwerk up✓ Daemon startedThe daemon runs in the background and picks up activity from your hooks automatically. Use clockwerk status to see your tracked time.
Check your status
$ clockwerk statusDaemon: running (pid 12345)Project: my-projectToday: 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
$ bun add -g @getclockwerk/cliOr with npm:
$ npm install -g @getclockwerk/cliThe package includes pre-compiled binaries for your platform. No build step needed.
Supported platforms
Note
Windows is not currently supported. Use WSL2 for Windows development.
Verify installation
$ clockwerk helpclockwerk vX.X.X - local work history engine Usage: clockwerk <command> [options]Uninstall
$ clockwerk down$ bun remove -g @getclockwerk/cli$ rm -rf ~/.clockwerkWarning
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
Note
Browse the source at github.com/getclockwerk/clockwerk.
What you can verify
With the source available, you can audit:
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.
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.
$ clockwerk initProject name (my-project): Detected: Claude Code, CursorInstall hook for Claude Code? (Y/n)Install hook for Cursor? (Y/n)✓ Created .clockwerk config✓ Installed 2 hooksNon-interactive mode
Pass the project name as an argument to skip the prompt:
$ clockwerk init my-project✓ Created .clockwerk config✓ Installed hooks for Claude CodeThe .clockwerk file
Init creates a .clockwerk JSON file in your project root:
{
"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:
Tracking
Daemon
Start and stop the Clockwerk background daemon.
Start the daemon
$ clockwerk up✓ Daemon startedThe daemon runs in the background, listens for events from hooks and plugins, and computes sessions from activity gaps.
clockwerk upStart the background daemon.
| Flag | Description | Default |
|---|---|---|
| -f, --foreground | Run in foreground with log output to stdout | - |
Stop the daemon
$ clockwerk down✓ Daemon stoppedSends 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:
$ clockwerk up --foreground[INFO] Daemon started on /home/you/.clockwerk/daemon.sock[INFO] Loaded 2 plugins[INFO] Event received: tool_call from claude-codeHow 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.
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
$ clockwerk statusDaemon: running (pid 12345)Project: my-projectToday: 2h 30m (3 sessions) Plugins: docker-logs 12 events last: 2m ago git-activity 5 events last: 8m agoOutput breakdown
When the daemon is stopped
$ clockwerk statusDaemon: stoppedProject: my-projectWhen 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
Examples
$ clockwerk log 2h "client meeting"✓ Logged 2h 0m$ clockwerk log 45m "code review"✓ Logged 45m$ clockwerk log 1h30m✓ Logged 1h 30mHow 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 logsDisplay daemon log output.
| Flag | Description | Default |
|---|---|---|
| -f, --follow | Stream logs in real-time | - |
| -n, --lines <n> | Number of lines to show | 50 |
| -l, --level <level> | Filter by level (DEBUG, INFO, WARN, ERROR) | - |
Examples
$ 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$ clockwerk logs --level ERROR -n 20Log levels
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
$ clockwerk hook installDetected: Claude Code, Cursor✓ Installed hook for Claude Code✓ Installed hook for CursorAuto-detect checks for tool config directories in your home folder and installs the appropriate hook configuration.
Install a specific hook
$ clockwerk hook install claude-codeAvailable hook IDs: claude-code, cursor, copilot.
Claude Code
Installs a PostToolUse hook in ~/.claude/settings.json that fires on all tool calls.
{
"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.
{
"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.
{
"hooks": [
{
"event": "postToolUse",
"command": "clockwerk hook copilot",
"timeout": 5000
}
]
}Event data
Each hook invocation extracts the following from the tool's JSON input:
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/.
$ 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:
$ clockwerk plugin add my-tool --command "my-tool status --json" --event-type tool_call --interval 30✓ Plugin 'my-tool' added| Flag | Description | Default |
|---|---|---|
| --command <cmd> | Shell command to execute | - |
| --template <name> | Use a built-in template | - |
| --event-type <type> | Event type to record | manual |
| --source <source> | Source identifier | plugin:<name> |
| --interval <secs> | Minimum seconds between events | 1 |
Templates
Built-in templates for common tools:
$ clockwerk plugin add docker --template docker-logs✓ Plugin 'docker' addedPlugin manifest format
Registry plugins are defined by a plugin.json manifest file. This file describes the plugin and how Clockwerk should run it:
{
"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"]
}Manage plugins
$ clockwerk plugin listdocker-logs interval: 30s source: plugin:docker-logsgit-activity interval: 60s source: plugin:git-activity$ clockwerk plugin test docker-logsRunning plugin...Event: tool_call from plugin:docker-logs✓ Plugin output valid$ clockwerk plugin remove docker-logs✓ Plugin 'docker-logs' removedUpdate plugins
Check all installed registry plugins for newer versions and apply updates interactively:
$ clockwerk plugin updategit-activity 1.0.0 -> 1.1.0 availableUpdate git-activity? (y/N)✓ git-activity updated to 1.1.0Create a plugin
Scaffold a new plugin from the official template. This generates a plugin.json and plugin.sh in a new directory under plugins/:
$ 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-pluginContribute a plugin
Anyone can publish a plugin to the Clockwerk registry. To contribute:
Once merged, the plugin becomes available via clockwerk plugin add <name> for all users.
Valid event types
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
$ clockwerk studioClockwerk Studio running at http://localhost:3111Opens 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
$ clockwerk studio --port=4000Clockwerk Studio running at http://localhost:4000Dashboard
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
Sources
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.
Session data
Each session aggregates data from its events:
Event context
Each event can carry optional context fields:
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
$ clockwerk config set watch.enabled true✓ Updated watch.enabled = trueConfiguration
{
"watch": {
"enabled": true,
"interval": 30,
"exclude": ["node_modules", ".git", "dist", "build"]
}
}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:
Data
Config
View and modify Clockwerk project configuration.
View config
$ clockwerk configProject: my-projectToken: local_my-projectHarnesses: claude-code: enabled cursor: enabledSubcommands
clockwerk configShow all project settings.
clockwerk config name <name>Set the project name.
clockwerk config set <key> <value>Set a specific config value.
Available config keys
| Flag | Description | Default |
|---|---|---|
| watch.enabled | Enable file system watching | false |
| watch.interval | Heartbeat interval in seconds | 30 |
Examples
$ clockwerk config set watch.enabled true✓ Set watch.enabled = true$ clockwerk config set watch.interval 60✓ Updated watch.interval = 60$ 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.
{
"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 exportExport tracked sessions.
| Flag | Description | Default |
|---|---|---|
| --format <csv|json> | Output format | csv |
| --since <YYYY-MM-DD> | Start date filter | - |
| --all | Export all history | - |
| -o, --output <path> | Write to file instead of stdout | - |
Examples
$ clockwerk exportDate,Start,End,Duration,Project,Source,Branch,Topics,File Areas,Events2025-01-15,09:00,11:30,2h 30m,my-project,claude-code,main,...$ clockwerk export --format json --since 2025-01-01$ clockwerk export --all -o timesheet.csv✓ Exported 142 sessions to timesheet.csvCSV format
The CSV output includes the following columns:
Invoicing workflow
Export your tracked time for client invoicing:
$ clockwerk export --since 2025-01-01 -o january.csv✓ Exported 47 sessions to january.csvTip
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:
What Clockwerk never stores
Clockwerk never captures or stores:
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.