Dial is a lightweight time tracker with two faces on the same tool: a fast CLI for starting/stopping/logging work from the terminal, and a native desktop GUI (built with Wails + Svelte) for a visual tracker and dashboard. Both share the same local SQLite database, so you can start a session from the CLI and see it live in the GUI, or vice versa.
- Running
dialwith no arguments launches the GUI. - Running
dialwith a subcommand (start,stop,status,log,today) runs the CLI. - Both read/write the same database at
~/.dial/data.db, created automatically on first run.
Go to the project's Releases page and download the archive for your OS/architecture:
| Platform | Archive | Contains |
|---|---|---|
| macOS (Apple Silicon) | dial-darwin-arm64.zip |
Dial.app |
| macOS (Intel) | dial-darwin-amd64.zip |
Dial.app |
| Windows (x64) | dial-windows-amd64.zip |
dial.exe |
| Windows (ARM64) | dial-windows-arm64.zip |
dial.exe |
| Linux (x64) | dial-linux-amd64.tar.gz |
dial |
-
Unzip the archive and drag
Dial.appto/Applications. -
Double-clicking
Dial.applaunches the GUI directly. -
Dial.appis also the CLI binary — the executable inside the bundle is a normaldialbinary that behaves like any other CLI tool when given arguments. To use it from the terminal, symlink it onto yourPATH:sudo ln -s /Applications/Dial.app/Contents/MacOS/dial /usr/local/bin/dial dial statuss
The app isn't notarized/signed by an Apple-registered developer, so macOS may block it on first launch ("cannot be opened because the developer cannot be verified"). Either right-click Dial.app in Finder and choose Open to bypass the check once, or remove the quarantine flag:
xattr -d com.apple.quarantine /Applications/Dial.app-
Extract
dial-windows-to get.zipt;.zip dial.exe. -
Double-click it to launch the GUI, or move it onto your
PATHto use it from a terminal:dial status
Since the binary isn't code-signed, Windows may show an "unrecognized app" SmartScreen warning. Click More info → Run anyway if you trust the source.
tar -xzf dial-linux-amd64.tar.gz
chmod +x dial
sudo mv dial /usr/local/bin/dial
dial status # CLI
dial # GUI (requires GTK3 + WebKit2GTK installed, see below)The Linux GUI is built against webkit2gtk-4.1/GTK3, which need to be installed on your system (most desktop Linux distros already have these as part of GNOME/GTK apps). On Debian/Ubuntu: sudo apt install libgtk-3-0 libwebkit2gtk-4.1-0.
- Go 1.25+
- Node.js + npm (for the frontend)
- Wails CLI v2 (
go install github.com/wailsapp/wails/v2/cmd/wails@latest) if you want to usewails dev/wails builddirectly - A native GUI toolchain for your OS — Xcode Command Line Tools on macOS, GTK3 + WebKit2GTK dev packages on Linux (
sudo apt install libgtk-3-dev libwebkit2gtk-4.1-dev), or a workinggo buildtoolchain on Windows. (The SQLite driver itself is pure Go and needs no C compiler; the GUI's native webview bindings are what require these.)
git clone this-repo-url>gt;
cd dial
cd frontend &∓& npm install &∓& cd .. The repo includes scripts/dial.sh, a helper for common dev tasks:
./scripts/dial.sh build # go build -> bin/dialial
./scripts/dial.sh run # build + run (args after `run` are passed through)
./scripts/dial.sh test # go test with race detector + coverage
./scripts/dial.sh lint # gofmt check + go vet (+ golangci-lint if installed)
./scripts/dial.sh fmt # gofmt -w .
./scripts/dial.sh tidy # go mod tidy
./scripts/dial.sh check # lint + test (what CI should run)
./scripts/dial.sh clean # remove bin/ and coverage.out
./scripts/dial.sh all # tidy + fmt + lint + test + buildscripts/dial.sh build runs a plain go build, which produces a working CLI binary but embeds whatever is already in frontend/dist for the GUI. If you're changing frontend code, build the frontend first:
cd frontend &∓& npm run build &∓& cd ..
./scripts/dial.sh builddNote: a plain
go build(without theproductionbuild tag) links in a stub Wails backend that does nothing when you rundialwith no arguments — the CLI subcommands still work, but the GUI window won't appear. This is fine for CLI-only development. If you need a build where the GUI actually launches, usego build -tags productionor, better,wails build(see below).
For live-reloading GUI development:
wails devTo produce a full desktop app bundle (e.g. a .app on macOS):
wails buildThe output binary/bundle will be under build/bin/.
Dial's GUI links against a different native toolkit per OS (Cocoa on macOS, WebView2 on Windows, GTK3/WebKit2GTK on Linux), so a single machine can't produce all release artifacts — each platform has to be built on that platform. .github/workflows/release.yml handles this: pushing a v*.*.* tag spins up a macOS runner (arm64 + amd64), a Windows runner (amd64 + arm64), and a Linux runner (amd64) in parallel, and publishes all five archives to a GitHub Release.
dial [flags]
lags]
Start tracking a task. Automatically stops any currently running session first.
| Flag | Description |
|---|---|
--project |
Project name |
--tag |
Comma-separated tags |
dial start "Write proposal"
dial start "Fix login bug" --project dial --tag bug,urgentStop the currently running session, if any.
dial stopShow the currently running session (task, elapsed time, project, tags), or say nothing is running.
dial statusLog a completed session retroactively (e.g. work you forgot to track live).
| Flag | Description | Required |
|---|---|---|
--duration |
Duration, e.g. 30m, 1h15m |
Yes |
--at |
End time in HH:MM (defaults to now) |
No |
--project |
Project name | No |
--tag |
Comma-separated tags | No |
# Log 45 minutes ending now
dial log "Code review" --duration 45m
# Log a session that ended at 14:30
dial log "Team standup" --duration 15m --at 14:30 --project dial --tag meetingsShow all sessions tracked today and the total time.
dial todayLaunch the GUI by running dial with no arguments (or by opening the installed app).
The window has two parts:
- Tracker panel — enter a task (and optionally a project/tags), then Start. While a session is running you can Pause, Resume, or Stop it. The elapsed time updates live.
- Dashboard panel — a pie chart of time by tag, a bar chart of daily totals, and summary stats (total time, session count, top tag, streak), selectable over Today / This Week / This Month / This Year.
Starting or stopping a session in the GUI refreshes the dashboard automatically, and since the GUI and CLI share the same database, a session started from the CLI will show up next time the dashboard refreshes.
Dial stores all data locally in a SQLite database at ~/.dial/data.db (created on first run). There is no cloud sync, backup, or telemetry — the data never leaves your machine. Back up that file yourself if you want to preserve your history.
- This is an unsigned/unnotarized personal-project binary — see the Gatekeeper/SmartScreen notes above before running it on macOS or Windows.
I used AI for debugging the dashboard wheel along with some styling issues for different screen sizes.