A pixel-flavored habit tracker for Linux. Tick a square for every day you show up, watch your streaks grow, and finish your 10 / 21 / 30 / 66 / 90 / 365-day challenges.
One Rust core, three ways to use it: a desktop app with a liquid-glass pixel UI, a terminal CLI for the keyboard-first, and a Python reminder service that nags you gently at 20:00.
ββββββββββββββββββββββββββββββββββββββββββββββββ
β β PixelHabits Good evening, Alex β
β β
β ββββββββββββββββββ ββββββββββββββββββ β
β β π Morning Run β β π Read 20 pagesβ β
β β [β][β][β][ ][ ] β β [β][ ][β][ ][ ] β β
β β streak: 17 π₯ β β Day 12/365 β β
β ββββββββββββββββββ ββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββ
The squares β the heart of the app. Check a square each day you complete a habit; miss a day and the grid remembers.
- Desktop dashboard β habit cards with progress rings, streaks, weekly bars, and animated check squares (pixel sparkle included)
- 12-week heatmap per habit, plus a monthly calendar heatmap
- Challenges β pick 10/21/30/66/90/365 days (or any length). Verdicts:
β³ Day 17/30: 16 doneββ complete/β window over. Windows anchor to your first check, so backfilled history counts - Reports β total completions, average rate, longest streak, most consistent habit, weekly/monthly bar charts, progress line chart
- Accounts β multi-user on one machine, each with username + PIN. The app opens on a lock screen; every launch starts locked
- Sign-out that makes sense β with multiple accounts it switches users instead of locking you out
- Account deletion β PIN-verified, wipes the account's data, hands the session to another account if one exists
- Encrypted sync β export an end-to-end encrypted (AES-256-GCM, PBKDF2 200k) bundle of the signed-in account to any shared folder (Nextcloud/Dropbox/Syncthing/USB) and merge it on another machine. Checks are unioned: a day done on any device stays done
- Activity log β every add/check/edit/delete is recorded with device and timestamp
- Themes β Light, Dark, System, Catppuccin (Mocha & Latte), Nord, Dracula, Tokyo Night, Gruvbox β plus an accent color picker for the regular themes
- Liquid Glass mode β opt-in frosted-glass material (blur + saturate panels over a drifting aurora) that leaves your theme colors untouched
- Same file everywhere β the GUI and CLI share
~/.local/share/pixelhabits/habits.json(XDG)
| Platform | Status | Data location | Notes |
|---|---|---|---|
| Linux (X11/Wayland) | β Primary β developed & tested on Hyprland | ~/.local/share/pixelhabits/ |
webkit2gtk-4.1; .deb/AppImage via npx tauri build |
| Windows 10/11 | β Supported | %APPDATA%\pixelhabits\ |
WebView2 runtime; .msi installer via npx tauri build |
| macOS 12+ | β Supported | ~/Library/Application Support/pixelhabits/ |
.app bundle via npx tauri build |
The Rust core, CLI and sync format are identical on all three; the reminder service is Linux-only (systemd).
pixelhabits/
βββ app/
β βββ src-tauri/ # Rust core (Tauri 2)
β β βββ src/
β β βββ store.rs # storage engine: accounts, habits, challenges,
β β β # streaks, merge-safe sync, E2E crypto, tests
β β βββ lib.rs # Tauri command layer (user-scoped DTOs)
β βββ ui/ # HTML/CSS/JS frontend (no framework, offline fonts)
β βββ icons/ # generated from app/icon-source.png
βββ src/ # Node CLI (shares the same habits.json)
β βββ bin/pixelhabits.js # commands: add, check, grid, chart, stats, tuiβ¦
β βββ lib/ # storage (v2 format), charts, rendering
βββ services/ # Python reminder service + systemd user units
βββ scripts/ # smoke tests, icon generator, desktop installer
Why this stack: Rust owns the data (atomic writes, corruption backup, typed model, real tests). Tauri 2 gives a tiny native window instead of an Electron monster. Python does the one thing it's great at β a cron-able notifier. No frameworks, no telemetry, fully offline.
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/enjo2/PixelHabits/main/scripts/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/enjo2/PixelHabits/main/scripts/install.ps1 | iexThe installer detects your OS and package manager, installs everything (Rust, Node.js, WebKit/WebView2), clones the repo to a temp dir, builds, and wires up desktop integration (.desktop entry on Linux, Start Menu shortcut on Windows). Pass --release for an optimized build.
Repo URLs default to
enjo2/PixelHabitsβ forked? Override withPIXELHABITS_REPO=<your-fork-url>(andPIXELHABITS_BRANCHif needed).
git clone https://github.com/enjo2/PixelHabits && cd pixelhabits
./scripts/install.sh # or scripts/install.ps1 on WindowsDependencies: webkit2gtk-4.1 (Linux), Xcode CLT (macOS), WebView2 (Windows, pre-installed on Win 11), cargo (1.75+), Node.js (18+).
# Debian/Ubuntu
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file
# Desktop app (debug build)
cd app
npm install
npx tauri build --debug --no-bundle
./src-tauri/target/debug/pixelhabits
# CLI
npm install -g . # or just: node bin/pixelhabits.js
ph --helpShow the icon in your panel/launcher (Linux):
./scripts/install-desktop.sh # installs user-local .desktop + hicolor iconsRelease build (optimized binary + .deb/AppImage):
cd app && npx tauri buildmkdir -p ~/.local/share/systemd/user
cp services/pixelhabits-remind services/pixelhabits-remind.{service,timer} ~/.local/share/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now pixelhabits-remind.timerA Python script checks habits.json and sends a notify-send with your open squares at 20:00.
- Machine A: Settings β Export encrypted bundleβ¦ β choose a path in your shared folder β set a passphrase
- Machine B (same account username): Settings β Import encrypted bundleβ¦ β same passphrase
Only ciphertext leaves the device. The merge is conflict-safe:
- Checks are unioned β done anywhere = done
- Metadata (name, color, challengeβ¦) resolves last-writer-wins via
updated_at - Activity events deduplicate by id; re-importing is idempotent
ph add "Gym" --challenge 30-day --color mint
ph check "Gym" # tick today
ph check "Gym" yesterday # fix a missed day
ph ls # today's dashboard
ph grid # GitHub-style checkbox grids
ph chart # sparkline + weekly bars
ph stats # streaks + challenge verdicts
ph export -o progress.svg # shareable SVG chart
ph tui # interactive: arrows + spacebar- Everything lives in
~/.local/share/pixelhabits/habits.json(override withPIXELHABITS_DATA) - Atomic writes + backup-on-corruption: a crash can't destroy your history
- PINs are hashed, sync bundles are ciphertext, no network calls anywhere
cd app/src-tauri && cargo test # Rust core (accounts, sync merge, crypto, streaks)
npm test # CLI: storage, charts, challenge math
bash scripts/smoke.sh # end-to-end CLI smoke run- Native file picker for sync bundles (currently typed paths)
- Optional hosted sync server (the bundle/merge protocol is ready for it)
- Widget overlays for Wayland bars (open squares count)
- More theme flavors (RosΓ© Pine, Everforest)
PixelHabits β tiny squares, mighty streaks.