Effortless, accurate time tracking that works passively in the background. Built for freelance developers who use Claude Code, VS Code, Cursor, or the terminal.
$ tt now
> client-project 1h 23m (today: 4h 15m) [goal: 71%]
No browser tabs. No manual timers. No context switching. Open your terminal, start coding, and tt handles the rest.
flowchart LR
A["Open Claude Code"] -->|SessionStart hook| B["tt pulse"]
B --> C["Session auto-starts"]
C --> D["You code..."]
D -->|PostToolUse hook| E["Activity heartbeat"]
E -->|Every 60s| D
D -->|20min idle| F["Auto-pause"]
F -->|Resume activity| D
D -->|Close terminal| G["tt stop"]
tt hooks into Claude Code's lifecycle events. When you open a terminal in a project directory, tracking starts. As you work, activity pulses keep the session alive. Step away for 20 minutes? Time pauses automatically. Come back? It resumes. Close the terminal? Session stops.
The VS Code extension adds passive tracking on file save and editor focus -- no hooks required.
Your time data lives in a local SQLite database at ~/.tt/tt.db -- no cloud, no accounts, no sync complexity.
# Clone and build
git clone https://github.com/aiwithabidi/time-tracker.git
cd time-tracker
bun install && bun run build
# Install globally + set up Claude Code hooks
./dist/tt setupThe setup command:
- Copies the binary to
~/.tt/bin/tt - Installs hook scripts to
~/.tt/hooks/ - Prints the Claude Code configuration to add to
~/.claude/settings.json
Requires Bun --
curl -fsSL https://bun.sh/install | bash
# Manual tracking (works immediately after install)
tt start # Start tracking in current project
tt now # Check status
tt stop # Stop tracking
# Set a daily goal and track your streak
tt goal set 6h # Target 6 hours per day
tt streak # View your tracking streak
# Reports
tt today # Today's time by project
tt week # Weekly breakdown
tt week --billable # With dollar amounts
tt log --from this-week # Session history
# Dashboard
tt dashboard # Open analytics dashboard in browser
# After running `tt setup` and adding hooks to Claude Code:
# Everything is automatic -- just open your terminal and code| Command | Description |
|---|---|
tt start |
Start tracking (auto-detects project from git) |
tt stop |
Stop the current session |
tt now |
Show active session status (includes goal progress) |
tt now --json |
Machine-readable output for editor integrations |
tt away |
Take a break (pause tracking) |
tt back |
Resume after a break |
| Command | Description |
|---|---|
tt goal set <duration> |
Set a daily time goal (6h, 4h30m, 90m, 2h 15m) |
tt goal show |
View goal progress with visual progress bar |
tt goal clear |
Remove the daily goal |
tt streak |
View tracking streak with 28-day ASCII heatmap |
| Command | Description |
|---|---|
tt note "fixed auth bug" |
Add a note to current session |
tt tag billable |
Tag the current session |
tt tag -r billable |
Remove a tag |
| Command | Description |
|---|---|
tt today |
Today's time by project (includes goal progress) |
tt week |
This week's report |
tt week --billable |
Include dollar amounts |
tt log |
Full session history |
tt log --project client-a --from 2026-01-01 |
Filtered history |
tt projects |
All projects with weekly totals |
tt last |
Last completed session |
tt export csv --project client-a --from 2026-01-01 |
Export to CSV |
tt dashboard |
Open local analytics dashboard in browser |
| Command | Description |
|---|---|
tt edit <id> --start 09:30 --end 17:00 |
Fix times on a past session |
tt edit <id> --project other-project |
Reassign to different project |
tt split <id> 12:00 |
Split a session at noon |
tt merge <id1> <id2> |
Merge two adjacent sessions |
tt undo |
Undo the last operation |
| Command | Description |
|---|---|
tt logs |
Recent command events (last 25) |
tt logs --stats |
Usage frequency, avg latency, error rates |
tt logs --errors |
Show only failed commands |
tt logs --json |
Raw JSON for AI analysis |
tt logs -c start --from 2026-03-01 |
Filter by command and date |
tt doctor |
Health check (20 checks + auto-repair) |
tt config list |
Show all configuration |
tt config set sourceRepo /path/to/time-tracker |
Set source repo for dashboard |
tt update |
Update to latest version from source |
tt update --check |
Check for updates without installing |
Session IDs are the first 8 characters shown in
tt log.
Set a daily time goal to stay on track:
tt goal set 6h # Set a 6-hour daily goal
tt goal show # View progress with a visual progress bar
tt goal clear # Remove the goalWhen a goal is set, progress is shown automatically in tt now and tt today output.
Track your consistency with streaks:
$ tt streak
Current streak: 12 days
Best streak: 34 days
Average daily: 5h 42m
Jan 27 - Feb 23 (28 days)
Mo Tu We Th Fr Sa Su
.. .. .. .. ## ## ##
## ## ## ## ## ## ##
## ## ## ## ## ## ..
## ## ## ## ## ## ..The heatmap uses intensity shading to show how much you tracked each day over the last 28 days.
tt now --json returns machine-readable data for editor integrations and scripts:
{
"active": true,
"project": "client-project",
"durationMs": 4980000,
"todayTotalMs": 15300000,
"idleState": "active",
"goalMinutes": 360,
"goalPercent": 71
}The VS Code extension uses this endpoint to power its status bar display.
The tt extension for VS Code brings passive time tracking to your editor. Located at packages/vscode/.
Supported editors: VS Code, Cursor, Windsurf, and any VS Code fork.
Features:
- Passive tracking -- sends pulses on file save and editor focus changes
- Status bar -- shows current project, elapsed time, and goal percentage
- Zero config -- auto-discovers the
ttbinary from config,~/.tt/bin/tt, or PATH
Settings:
| Setting | Default | Description |
|---|---|---|
tt.enabled |
true |
Enable or disable the extension |
tt.binaryPath |
(auto) | Path to the tt binary |
tt.statusBarInterval |
30 |
Status bar refresh interval in seconds |
Install:
cd packages/vscode
bun install
bun run build
# Install the generated .vsix file:
code --install-extension tt-time-tracker-*.vsix
# Or for Cursor:
cursor --install-extension tt-time-tracker-*.vsixtt dashboard opens a local analytics dashboard in your browser with a GitHub-inspired dark theme.
Features:
- Contribution heatmap (GitHub-style)
- Weekly time charts
- Session timeline
- Project breakdown
- Streak statistics
Setup:
The dashboard requires a sourceRepo config pointing to your local time-tracker clone:
tt config set sourceRepo /path/to/time-trackerBuild and run:
cd packages/dashboard
bun install
bun run build
tt dashboard # Opens in your default browser
tt dashboard --port 8888 # Use a custom portBuilt with Svelte 5 and Tailwind CSS v4, served by Bun.
graph TD
subgraph CLI["CLI Layer"]
A["tt start / stop / now / ..."]
B["tt pulse (hooks)"]
end
subgraph Core["Business Logic"]
C["SessionService"]
D["IdleDetector"]
E["ReportService"]
F["ExportService"]
G2["GoalService"]
H2["StreakService"]
end
subgraph Data["Data Layer"]
G["Repositories"]
H["SQLite + Drizzle ORM"]
end
subgraph Packages["Packages"]
I["VS Code Extension"]
J["Dashboard (Svelte)"]
end
A --> C
B --> C
C --> D
C --> G
E --> G
F --> G
G2 --> G
H2 --> G
G --> H
I -->|tt now --json| A
J -->|Bun.serve API| H
Clean layers, no magic:
- CLI -- Gunshi command definitions, formatting, user I/O
- Core -- Pure business logic. Sessions, idle detection, reports, goals, streaks, CSV export
- Data -- Repository pattern over SQLite. Drizzle ORM for type-safe queries
- Packages -- VS Code extension (passive tracking), dashboard (Svelte analytics UI)
src/
cli/ Command definitions (gunshi), formatting, helpers
commands/ One file per command (start.ts, stop.ts, now.ts, goal.ts, streak.ts, ...)
core/ Pure business logic
session/ Session lifecycle, idle detection
reports/ Report generation
export/ CSV export
review/ Work review generation
goals/ Daily goal tracking
streaks/ Streak calculation and heatmap
shared/ Shared utilities (time math, duration formatting)
services/ Service factory layer (creates services with DB access)
db/ SQLite schema (Drizzle ORM), repositories, migrations
config/ Config loading, Zod schemas, types
hooks/ Claude Code hook scripts (pulse, session lifecycle)
packages/
vscode/ VS Code / Cursor extension (TypeScript, esbuild)
dashboard/ Local analytics dashboard (Svelte 5, Tailwind CSS v4)
tests/
cli/ CLI command tests
core/ Business logic tests
integration/ End-to-end integration tests
skills/ Claude Code slash commands (/tt, /tt:start, /tt:week, ...)
tt automatically figures out which project you're working on:
- Config alias (highest priority) -- Match directory to a configured project
- Git root (fallback) -- Use the git repository name as the project slug
- Manual flag --
tt start --project my-project
stateDiagram-v2
[*] --> Active: Activity pulse
Active --> SoftIdle: 8min no activity
SoftIdle --> Active: Activity pulse
SoftIdle --> HardIdle: 20min no activity
HardIdle --> Active: Activity pulse
Active --> Paused: tt away
Paused --> Active: tt back
note right of HardIdle: Time deducted from\nbillable duration
note right of Paused: Break time deducted\nimmediately
- Active -- Working normally, time accumulates
- Soft idle (8min) -- Warning shown in
tt now, no deduction yet - Hard idle (20min) -- Time auto-paused, excess deducted from billable hours
- Paused -- Manual break via
tt away, deducted immediately
Thresholds are configurable in ~/.tt/config.json.
Create ~/.tt/config.json to configure projects and rates:
{
"projects": {
"~/code/client-a": {
"slug": "client-a",
"displayName": "Client A Website",
"clientName": "Client A Inc",
"hourlyRate": 150,
"currency": "USD"
}
},
"idle": {
"softIdleMinutes": 8,
"hardIdleMinutes": 20
},
"goal": {
"dailyMinutes": 360
},
"sourceRepo": "/path/to/time-tracker"
}The goal field is managed by tt goal set and tt goal clear. The sourceRepo field is required for tt dashboard.
If you use Claude Code, tt ships with slash commands that work inside conversations:
| Command | What it does |
|---|---|
/tt |
Show current tracking status |
/tt:start |
Start tracking |
/tt:stop |
Stop tracking |
/tt:week |
Weekly report |
/tt:projects |
List all projects |
/tt:note meeting notes |
Add a note |
/tt:edit <id> --start 09:00 |
Edit a session |
These are Claude Code skills that invoke the tt binary directly -- no AI processing needed, instant results.
Export your time data for invoicing:
# Export all time for a project in a date range
tt export csv --project client-a --from 2026-01-01 --to 2026-01-31
# Preview what would be exported
tt export csv --project client-a --from 2026-01-01 --dry-run
# Pipe to a file
tt export csv --project client-a > january-hours.csvCSV columns: project, date, start_time, end_time, duration_hours, duration_human, notes, tags
tt can update itself from source:
tt update # Pull, build, and install the latest version
tt update --check # Just check if an update is availableThe update mechanism:
- Verifies the remote origin matches the expected GitHub repository (supply-chain protection)
- Pulls the latest changes from
origin/main - Installs dependencies and builds a new binary
- Atomically replaces the installed binary (write to
.tmp, then rename) - Rolls back automatically if the build fails (resets to the previous commit)
A background check runs on each tt invocation (throttled to once per hour) and shows a status indicator when an update is available.
# Prerequisites
bun --version # Requires Bun (https://bun.sh)
# Setup
git clone https://github.com/aiwithabidi/time-tracker.git
cd time-tracker
bun install
# Development workflow
bun run dev -- now # Run commands without compiling
bun run typecheck # Type checking
bun run test:unit # Unit tests with coverage
bun run test:integration # Integration tests
bun run test # All tests
bun run build # Compile to native binary (dist/tt)
# Build packages
cd packages/vscode && bun install && bun run build # VS Code extension
cd packages/dashboard && bun install && bun run build # DashboardSee CONTRIBUTING.md for full contributor guidelines.
| Component | Choice | Why |
|---|---|---|
| Runtime | Bun | Fast startup (<100ms), built-in SQLite, single-file compile |
| Database | SQLite (WAL mode) | Local-first, zero config, portable |
| ORM | Drizzle | Type-safe queries, lightweight |
| CLI | Gunshi | Lazy-loaded subcommands for fast startup |
| Dates | Luxon | Timezone-aware, reliable date math |
| Validation | Zod | Runtime type safety for config and input |
| Testing | Vitest | Fast, Bun-compatible, coverage built-in |
| Dashboard | Svelte 5 + Tailwind CSS v4 | Minimal bundle, modern reactivity |
| Extension | VS Code Extension API | Native editor integration |
MIT - see LICENSE
Built by Abidi at AgxntSix with Claude Code.