Temporal Loom is a local first, self hosted time tracker built as a Clockify compatible alternative you run yourself. It lives entirely on your own machine: no account, no cloud sync, no third party server ever sees your data. It is aimed at solo use, originally built for tracking bug bounty work and personal life projects side by side, but works for any kind of time tracking. This README documents every feature that exists in the app today, how to run it, and how to use each part of it.
- Why Temporal Loom
- Features
- Quick start
- Core concepts
- Feature guide
- Settings and feature toggles
- Importing and backing up your data
- Running it on your network
- What's not built yet
- Technical reference
- Your data stays on your machine: Everything lives in one SQLite file, with no telemetry, no analytics, and no external calls except the ones you trigger yourself, such as a Clockify import.
- Built to replace Clockify, not just log hours: Projects, tasks, tags, goals, a scheduler, a dashboard, and exportable reports are all included.
- Goals that adjust as you go: It tracks daily minimums and ceilings, recalculates your required pace as a month progresses, and tells you plainly if a goal is no longer realistic instead of quietly showing an unreachable number.
- Quick to use day to day: Timers can be started with one click from several places in the app, not just the main picker.
- Timer: with a live countdown in the browser tab title, and a one click restart for any past entry
- Projects and tasks: with colors, nested sub tasks, and an automatic fallback task so untracked time still has a home
- Tags and sub tags: independent of project or task, that can be attached to any entry
- Goals: for daily, weekly, monthly, and yearly periods, with per project targets and a self adjusting daily pace
- Work Hours: an optional setting that checks whether a goal is still realistically reachable today
- Scheduler: for planning which project you intend to work on, either weekly or on a specific date
- Dashboard: with stacked charts and breakdowns by project over any date range
- Reports: with drill down into entries, saved custom views, and export to CSV, HTML, or PDF
- Calendar: view of any day's entries
- Clockify import and export: plus a full backup and restore as a single JSON file
- A full REST API: for scripting or extending the app
Requirements: Node.js 18 or newer, and npm.
npm install
cp server/.env.example server/.env
npm run devOpen http://localhost:5173. The API server runs on port 4310 and the web app on port 5173.
Other useful commands:
| Command | What it does |
|---|---|
npm run dev:server |
Run only the API server |
npm run dev:client |
Run only the web app |
npm run build |
Build both workspaces for production |
If you are upgrading from an older install, no manual steps are needed. Any tables or columns added since your version are created automatically the first time the server starts, and Work Hours and the Scheduler both start out turned off until you enable them in Settings.
| Entity | What it is |
|---|---|
| Project | A top level bucket of work, for example Bug Bounty or Life. Has a name and a color. |
| Task (called an activity internally) | A specific kind of work inside a project, for example Recon. Tasks can be nested under other tasks. Every project has a hidden General fallback task so time tracked without picking a task still lands somewhere. |
| Tag | A label that can be attached to any entry, independent of project or task. Tags can also have sub tags. |
| Time entry | A single tracked interval: a start time, an end time, a description, a project, a task, and any number of tags. |
| Goal | A time target for one of four periods, Daily, Weekly, Monthly, or Yearly, either overall or scoped to one project. Daily also carries fixed minimum, max, and extreme caps that apply regardless of any goal. |
-
Time Tracker: This is the home page. Pick a project and task, optionally add a description and tags, and press Start. Entries within a day are grouped by project, task, and description; if the same combination was logged more than once, they collapse into one row with a count badge. Click a group to expand it, edit any field inline, including start and end times, and reassign the project or task if needed. Every row also has a button to start a new timer with the same details.
-
Goals: Daily, Weekly, Monthly, and Yearly targets, each optionally split across projects. Monthly is the most involved: it recalculates how much time you need per remaining day based on what is left and how many days remain, and reports whether the goal is comfortable, tight, or no longer achievable as set, rather than showing a target that has quietly become impossible.
-
Work Hours: An optional setting, off by default, where you define your normal working window. Once set, the app can tell you whether a daily minimum is still reachable given the time left in that window, instead of assuming you can work indefinitely into the evening.
-
Scheduler: Also optional and off by default. Lets you plan a project for a recurring weekday or for a specific future date, with an optional time target. Whatever is scheduled for today shows up automatically on the Time Tracker under "Today's schedule."
-
Dashboard: Pick a date range, such as this week or a custom range, and see total time, the top project, a stacked daily bar chart by project, and a donut breakdown of the whole range.
-
Reports: Shows totals for a range, a by project table with optional drill down into the underlying entries, and a by activity table with nested task rollups. Any range can be saved as a named view, and reports can be exported as CSV, HTML, or PDF.
-
Projects and Tags: Managed from their own pages: create, rename, recolor, archive, and organize into sub tags or sub tasks inline.
-
Calendar: Pick a single date and see everything logged that day, grouped the same way as the Time Tracker.
Settings is split into five tabs: General (goals and caps), Features (the toggles below), Work Hours, Scheduler, and Import/Export.
The following are all on by default and can be turned off independently under Features:
- Dashboard charts
- Hierarchical task rollups in Reports
- Drill down into entries from Reports
- Saved report views
- CSV, HTML, and PDF report export
Turning everything off gives a minimal tracker that only shows totals; leaving it all on gives the full analytics suite. These toggles are a per browser display preference, not synced data.
Team and Clients sidebar entries also exist as togglable placeholders. Neither has real functionality yet; they are kept for layout parity with Clockify.
- Import from Clockify: Upload a Clockify CSV export. Projects, tasks, and tags are matched by name or created if missing. Timestamps are converted using your browser's timezone. Re-uploading the same file is safe, since already imported entries are detected and skipped.
- Export to Clockify: The reverse of the above, useful if you ever want to move away from Temporal Loom.
- Full backup and restore: One versioned JSON file covering projects, tasks, tags, entries, goals, caps, work hours, the scheduler, and saved views. Restoring the same file twice is safe and will not create duplicates.
- App settings export: A smaller export covering configuration only: caps, goals, work hours, the scheduler, saved views, and display preferences. Useful for moving your setup to a new browser or install without re-entering everything by hand.
By default, both the server and the client dev server bind to 0.0.0.0, so any device on the same network can reach the app at your machine's local IP address, for example http://192.168.1.20:5173.
There is no authentication built in. Anyone who can reach that address can read and write your data. This is fine on a trusted home network and not fine on an untrusted one. To restrict access to just this machine, set HOST=127.0.0.1 in server/.env and remove host: true from client/vite.config.ts.
- A user interface for Targets: a planned layer under project and task for tracking a specific bug bounty target. The database table exists, but there is no screen for it.
- Per task colors: The database column exists, but there is no color picker for tasks yet.
- A proper Calendar grid: The current Calendar page is a single day list, not a month or week view.
- Multi user support:
TeamandClientsare placeholders only. - Saved views apply to Reports only: not to the Dashboard's date range picker.
- Scheduler reminders: The Scheduler currently drives the Time Tracker's Daily tab only, with no notifications and no feed into the Weekly, Monthly, or Yearly tabs.
This section is for contributors and anyone scripting against the API.
Server: Node.js, TypeScript, Express, SQLite through better-sqlite3, and PDFKit for PDF generation.
Client: React, TypeScript, Vite, React Router, and Recharts for charts.
The two run as separate processes from one repository, using npm workspaces for server and client.
All data lives in a single SQLite file at server/data/tracker.db. This file is gitignored and never sent anywhere. There is no telemetry, no analytics, and no external API calls beyond ones you explicitly trigger, such as a Clockify import.
server/
src/db/ schema.sql, ULID generator, sqlite client, migrations
src/models/ workspace, project, activity, tag, goal, dailyCaps, workHours,
scheduleEntry, savedView, timeEntry
src/services/ reportService, reportExportService, exportService, settingsExportService,
clockifyExportService, csv, importClockify, goalStatusService,
scheduleStatusService
src/utils/ timezone (shared zoned time conversion, plus day of week and
date key helpers, used by the importer, exporter, goal engine,
and scheduler)
src/routes/ one file per resource, mounted under /api/v1
src/index.ts app entry point
client/
public/ favicon assets and the mascot logo image
src/api/ typed fetch client and shared types
src/context/ TimerContext, for global running timer state and the live tab title
src/components/ Sidebar, Timer, ProjectTaskPicker, TagPicker, Combobox, HMInput,
GroupedEntryList, GoalsSummary, RangePicker, ColorDot
src/pages/ TimeTracker, Dashboard, Reports, Calendar, Projects, Tags,
TimeEntries, Team, Clients, Settings (with sub-pages:
General, Features, WorkHours, Scheduler, DataManagement)
src/utils/ date, range, format, colors, featurePrefs, sidebarPrefs,
goalPeriodPrefs, timerStart
All endpoints are under /api/v1.
| Resource | Endpoints |
|---|---|
| Workspaces | GET /workspaces, GET /workspaces/current |
| Projects | GET /projects, GET /projects/:id, POST /projects, PATCH /projects/:id, POST /projects/:id/archive |
| Activities (tasks) | GET /activities, POST /activities, PATCH /activities/:id, POST /activities/:id/archive |
| Tags | GET /tags, POST /tags, PATCH /tags/:id, DELETE /tags/:id |
| Time entries | GET /time-entries, GET /time-entries/running, POST /time-entries/start, POST /time-entries/:id/stop, POST /time-entries, PATCH /time-entries/:id, DELETE /time-entries/:id |
| Reports | GET /reports/summary, GET /reports/analytics, GET /reports/by-project, GET /reports/by-activity, GET /reports/export.csv, GET /reports/export.html, GET /reports/export.pdf |
| Goals | GET /goals/status, GET /goals/caps, PUT /goals/caps, GET /goals/:period, PUT /goals/:period/overall, DELETE /goals/:period/overall, PUT /goals/:period/project/:projectId, DELETE /goals/:period/project/:projectId (:period is daily, weekly, monthly, or yearly) |
| Work hours | GET /work-hours, PUT /work-hours |
| Scheduler | GET /schedule, POST /schedule, PATCH /schedule/:id, DELETE /schedule/:id, GET /schedule/today, GET /schedule/settings, PUT /schedule/settings |
| Saved views | GET /saved-views, POST /saved-views, DELETE /saved-views/:id |
| Imports | POST /imports/clockify, POST /imports/temporal-loom, POST /imports/settings |
| Exports | GET /exports/json, GET /exports/clockify.csv, GET /exports/settings.json |
- Schema v1: the original whole workspace export, from before goals and daily caps existed. It still imports correctly.
- Schema v2: added goals, caps, and saved views.
- Schema v3 (current): added Work Hours and the Scheduler.
- The app settings export has its own separate version number, currently v2.