Track your time. Not your privacy.
Developer-first time tracking. 100% local. Git-native.
Features · Getting Started · Docker · Architecture · Full Docs
Most time trackers are built for managers who need reports. DevTrack is built for developers who need focus.
Your data belongs on your machine — no cloud, no accounts, no telemetry. Git already knows what you did — DevTrack connects the dots. A timer should work when you forget to start it — smart estimation from commits. Export should be the beginning, not the end — professional Excel reports from day one.
| DevTrack | Toggl | Clockify | ActivityWatch | Super Productivity | |
|---|---|---|---|---|---|
| Data location | Local only | Cloud | Cloud | Local | Local |
| Account required | No | Yes | Yes | No | No |
| Git integration | Native, local | None | None | None | Basic |
| Telemetry | 0 bytes | Analytics | Analytics | Optional | Optional |
| Excel export | 6 styled sheets | CSV (paid) | CSV/PDF (paid) | JSON | Basic |
| Works offline | Yes | No | No | Yes | Yes |
| Setup | npm run dev or docker compose up |
Sign up + plugin | Sign up + plugin | Desktop install | Desktop install |
| Price | Free | $10+/mo | $0-$18/mo | Free | Free |
DevTrack has no mobile app, no team features, and no browser extension. That is by design — it does one thing well.
Timer & Sessions — Work/break timer with idle detection, pause tracking, session persistence across reloads, and full editing after completion.
Git Integration — Track multiple local repositories. Auto-sync commit history with file stats, branch detection, and multi-identity support. Smart work estimation from commit patterns with confidence scoring. Read-only, security-hardened.
Analytics — Daily hours, tag distribution, peak hours, weekly trends. Compare tracked time against git-estimated hours. Date range filtering.
Professional Export — Excel reports with 6 styled sheets (dashboard, timesheet, daily summary, tag analysis, git activity, work log). CSV export. Privacy-aware filtering.
Sync & Recovery — Field-level diffing, three merge strategies, conflict resolution UI. Layered persistence: localStorage + disk backup + version snapshots with one-click restore.
Notes & Work Log — Timestamped checkpoints during sessions. Standalone work log with search. Privacy controls for sensitive entries.
Full feature details in docs/FEATURES.md. Technical deep dives in docs/DEEP_DIVES.md.
- Node.js 18+
- Git CLI (for repository tracking features)
git clone https://github.com/nexiouscaliver/devtrack.git
cd devtrack
npm install
npm run devOpen http://localhost:9000 — the app is ready to use.
No Node.js required — run with Docker instead:
git clone https://github.com/nexiouscaliver/devtrack.git
cd devtrack
docker compose up -dOpen http://localhost:9000. See the Docker section for configuration, data persistence, and git integration.
| Command | Description |
|---|---|
npm run dev |
Start Vite (9000) + git server (9001) |
npm run dev:client |
Vite dev server only |
npm run dev:server |
Companion server only |
npm run build |
Production build to dist/ |
npm run test |
Run test suite |
npm run lint |
ESLint check |
npm run preview |
Preview production build |
Development mode — Vite serves the frontend with HMR and proxies API requests to the companion server:
┌─────────────────────────────────────────────────────────┐
│ Browser (Port 9000) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │Dashboard │ │ Timer │ │ Sessions │ │Analytics│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬────┘ │
│ │ │ │ │ │
│ ┌────┴─────────────┴─────────────┴──────────────┴────┐ │
│ │ Central State (useState) │ │
│ │ sessions · commits · workLog · settings · ui │ │
│ └───────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌────────────┼────────────┐ │
│ │ │ │ │
│ ┌────▼─────┐ ┌────▼────┐ ┌────▼─────┐ │
│ │localStorage│ │SyncView│ │ExportView│ │
│ │ (primary) │ │(merge) │ │(engine) │ │
│ └──────────┘ └────┬────┘ └──────────┘ │
│ │ │
├──────────────────────┼──────────────────────────────────┤
│ Vite Proxy │(/api/* → :9001) │
├──────────────────────┼──────────────────────────────────┤
│ ▼ │
│ Companion Server (Port 9001) │
│ │
│ ┌──────────────────┐ ┌──────────────────────────────┐│
│ │ Git Endpoints │ │ Data Endpoints ││
│ │ /api/git/* │ │ GET/POST/DELETE /api/data ││
│ └───────┬──────────┘ └─────────────┬────────────────┘│
│ │ │ │
│ ┌─────▼───────┐ ┌────────▼────────┐ │
│ │ git CLI │ │ server/data/ │ │
│ │ (local only)│ │ devtrack.json │ │
│ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────┘
Production (Docker) — Express serves both the built frontend and API from a single port:
Browser → Express (port 9000)
├── serves dist/ as static files
├── handles /api/* endpoints directly
├── git operations against mounted repos (read-only)
└── SPA fallback: non-API GET → index.html
| Principle | Implementation |
|---|---|
| Zero cloud dependency | All data stored locally — localStorage + local disk (or Docker volume) |
| Privacy-first | No telemetry, no accounts, no remote APIs |
| Dual reliability | Browser + server persistence with sync engine |
| Atomic operations | tmp+rename writes, write mutex, debounced saves |
| Graceful degradation | Works offline; syncs when server available |
| Containerized deployment | Multi-stage Docker build, non-root runtime, one-command setup |
Run DevTrack with Docker — no Node.js or npm required.
# Build and start
docker compose up -d
# Open http://localhost:9000| Command | Description |
|---|---|
docker compose up -d |
Start in background |
docker compose down |
Stop and remove container |
docker compose logs -f |
View live logs |
docker compose restart |
Restart the container |
docker build -t devtrack .
docker run -d \
--name devtrack \
-p 9000:9000 \
-v ./devtrack-data:/app/server/data \
--restart unless-stopped \
devtrack| Variable | Default | Description |
|---|---|---|
DEVTRACK_PORT |
9000 |
Host port (set via .env file or environment) |
BIND_ADDR |
0.0.0.0 |
Server bind address inside container |
To use a custom host port, create a .env file in the project root:
DEVTRACK_PORT=8080
Your data is stored in ./devtrack-data/ on the host, mapped to /app/server/data in the container. This includes sessions, settings, and version snapshots. The directory is created automatically on first run.
To track git repositories, mount them as volumes in docker-compose.yml:
volumes:
- ./devtrack-data:/app/server/data
- /path/to/your/repo:/repos/your-repo:ro # add your reposThen use the container path (/repos/your-repo) in the DevTrack UI instead of the host path.
Note: The Docker container binds to
0.0.0.0, making DevTrack accessible on your local network. DevTrack has no authentication. Only run on trusted networks, or use--network=host -e BIND_ADDR=127.0.0.1for localhost-only access.
DevTrack takes security seriously even though it runs entirely locally:
- Path traversal prevention — all paths validated,
..sequences rejected - Shell escaping —
shEscape()wraps all git command arguments - Read-only git operations — no push, pull, checkout, or mutating git commands
- No remote access — server binds to
127.0.0.1only (in development mode) - Size limits — 5MB request limit, 10,000 item array caps
- Private note filtering — private content excluded from all exports
All claims are verifiable in the open-source code. The server binds to 127.0.0.1. Git operations are read-only.
Your tracked time survives real-world accidents. Here is exactly what happens when things go wrong.
| Scenario | What happens | How |
|---|---|---|
| Browser tab closed accidentally | Zero data loss | beforeunload fires a synchronous localStorage.setItem + keepalive: true fetch to the server |
| Browser crashes | ≤ 300ms of data loss | Every state change triggers a debounced save (300ms) to both localStorage and server |
| Power cut / PC restart | ≤ 300ms of data loss | localStorage persists across reboots. Server cleans up stale .tmp files on startup. Active session state is stored in localStorage and restored on next load |
| Active timer on reload | Timer resumes exactly where it left off | Running/paused sessions are persisted with full state (start time, pauses, tags, notes). On reload, the timer picks up without missing a beat |
| localStorage corrupted | Auto-recovered from server | Server disk backup loads automatically. A toast notifies you. localStorage is repaired in place |
| Server file corrupted | Auto-renamed, client data used | The .json file is renamed to .corrupt. Client data becomes the source of truth and re-saves to a fresh file |
| Both corrupted | Restored from version snapshots | Up to 20 point-in-time snapshots stored on disk. One-click restore from the Sync view |
| Write interrupted mid-save | No corruption — atomic writes | Server writes to a .tmp file first, then renames. A write mutex prevents concurrent writes from interleaving. If the process dies, the .tmp is cleaned up on next start |
| Multiple tabs open | Conflict detection + warning | storage events detect when another tab writes data. If you have unsaved changes, a warning toast appears. Otherwise, the other tab's data is adopted silently |
| Server not running | Everything still works | The app reads/writes localStorage as primary. When the server comes back, the Sync view reconciles both copies |
Every state change
↓ (300ms debounced)
localStorage.setItem() ← Layer 1: instant, always available
↓
POST /api/data (keepalive) ← Layer 2: disk backup via companion server
↓ (atomic tmp→rename, write mutex)
Server data file corrupted?
↓
Version snapshots (up to 20) ← Layer 3: point-in-time restore
None of this requires configuration. It all works out of the box.
devtrack/
├── index.html # Entry point
├── Dockerfile # Multi-stage build (builder + runtime)
├── docker-compose.yml # One-command deployment with health check
├── .dockerignore # Excludes build artifacts from context
├── src/
│ ├── main.jsx # React root mount
│ ├── App.jsx # Full application (~6,000 lines)
│ └── utils/
│ ├── syncEngine.js # Pure diff/merge engine (~420 lines)
│ ├── syncEngine.test.js # Test suite
│ └── exportEngine.js # Excel/CSV generation (~1,250 lines)
├── server/
│ ├── git-server.mjs # Express companion server (~630 lines)
│ └── data/ # Persisted data (gitignored)
├── docs/
│ ├── FEATURES.md # Detailed feature reference
│ ├── DEEP_DIVES.md # How-it-works technical docs
│ └── adr/ # Architecture Decision Records
├── vite.config.js # Vite + proxy configuration
└── package.json # Dependencies + scripts
Contributions welcome. See CONTRIBUTING.md for setup and code style.
- Pomodoro mode with configurable intervals
- Keyboard shortcuts for timer controls
- Calendar view for session visualization
- Browser extension for external tool tracking
- Docker compose for one-command deployment
React 19 · Vite 8 · Express 5 · Tailwind CSS 3 · Recharts 3 · Framer Motion · xlsx-js-style
Built for developers who take their time seriously.