A lightweight, local-first Jira time tracker that lives in your menu bar.
Features • Download • Build • CLI + MCP • Contributing • License
Catet Task is a tray-first desktop app for tracking time on Jira tasks. Start, pause, and resume timers from the system tray, review daily or weekly totals, and push worklogs to Jira — all with local-first persistence so your data is never lost.
| Layer | Technology |
|---|---|
| App shell | Tauri v2 (Rust) |
| Frontend | Svelte 5 + TypeScript + Vite |
| Local DB | SQLite via sqlx |
| Credentials | OS keychain via keyring |
| HTTP | reqwest (rustls) |
| Automation | catet-cli + MCP server (Model Context Protocol) |
Pre-built binaries are available from Releases. Builds are produced via GitHub Actions on every tag push.
| Platform | Artifact |
|---|---|
| macOS (Apple Silicon) | .dmg |
| macOS (Intel) | .dmg |
| Windows (x64) | .msi / .exe |
macOS note: The app is signed and notarized. If Gatekeeper still warns you, right-click the app and choose "Open".
# Clone the repo
git clone https://github.com/nicvit/catet-task.git
cd catet-task
# Install frontend dependencies
npm install
# (Optional) Build CLI standalone binary
cargo build --manifest-path catet-cli/Cargo.toml --release
# Run in development mode (hot-reload)
npm run tauri dev
# Build for production
npm run tauri build
| Command | Purpose |
|---|---|
npm run dev |
Frontend only (Vite dev server) |
npm run build |
Build frontend assets |
npm run tauri dev |
Full app in dev mode |
npm run tauri build |
Production build |
cargo build --manifest-path catet-cli/Cargo.toml --release |
Build CLI binary |
catet-cli --help |
List CLI commands |
catet-cli serve-mcp |
Run MCP server over stdio |
cd src-tauri && cargo check |
Validate Rust compilation |
cd src-tauri && cargo clippy |
Lint Rust code |
cd src-tauri && cargo fmt |
Format Rust code |
The timer runs entirely in Rust — not in the browser. A tokio interval ticks every second, updates the tray title, and emits events to the Svelte frontend. This means:
assignee = currentUser() AND status IN ("To Do", "In Progress") AND sprint IN openSprints())/rest/api/3/issue/{key}/worklog with Atlassian Document Format commentsAll data lives locally in a SQLite database at the Tauri app config directory:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/id.rickyirfandi.catettask/catet-task.db |
| Windows | %APPDATA%/id.rickyirfandi.catettask/catet-task.db |
| Linux | ~/.local/share/id.rickyirfandi.catettask/catet-task.db |
Entries are never hard-deleted — soft flags preserve history for reporting.
Catet Task ships with a companion CLI, catet-cli, that can be used directly in Terminal and as an MCP server for Claude clients.
status, today, week, entries, set-comment, set-duration, submit, report)tasks, catet_search_tasks through MCP)catet-cli serve-mcpWhen installed from app Settings (or catet-cli install), default binary path is:
| OS | Path |
|---|---|
| macOS | ~/.local/bin/catet-cli |
| Windows | %LOCALAPPDATA%/Programs/catet-cli/catet-cli.exe |
| Linux | ~/.local/bin/catet-cli |
Recommended:
Manual config (if needed), in Claude Desktop config:
{
"mcpServers": {
"catet-task": {
"command": "C:\\Users\\<you>\\AppData\\Local\\Programs\\catet-cli\\catet-cli.exe",
"args": ["serve-mcp"]
}
}
}
catet-cli connect-claude-code
Or manually:
claude mcp add catet-task "catet-cli" serve-mcp --scope user
catet_status, catet_today, catet_week, catet_range, catet_entriescatet_set_comment, catet_set_durationcatet_submit_preview, catet_submitcatet_tasks, catet_search_taskscatet_plan_manual_log, catet_add_manual_logcatet_reportprintf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' | catet-cli serve-mcp
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' | catet-cli serve-mcp
Expected result includes:
protocolVersion: 2025-11-25serverInfo.name: catet-taskcatet-task/
├── src/ # Svelte 5 frontend
│ ├── components/ # UI screens and shared components
│ ├── lib/stores/ # Reactive state (auth, tasks, timer, entries)
│ ├── lib/api/ # Type-safe Tauri invoke wrappers
│ └── lib/utils/ # Formatting, rounding helpers
│
├── src-tauri/ # Rust backend
│ ├── src/commands/ # Tauri command handlers
│ ├── src/jira/ # Jira API client and models
│ ├── src/timer/ # Timer engine and heartbeat
│ ├── src/db/ # SQLite queries
│ └── migrations/ # SQL schema migrations
│
└── .github/workflows/ # CI: macOS and Windows builds
| Shortcut | Action |
|---|---|
Cmd/Ctrl + Shift + T |
Toggle panel |
Cmd/Ctrl + Shift + P |
Pause / Resume |
Cmd/Ctrl + Shift + L |
Open log flow |
Cmd/Ctrl + K |
Focus search (panel open) |
Escape |
Close panel |
serve-mcp.printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' | catet-cli serve-mcp
vite build fails with spawn EPERM / esbuildThis is usually caused by editors or antivirus tools locking files in node_modules:
rm -rf node_modules package-lock.json
npm install
npm run build
On macOS, you may also need to remove quarantine flags:
xattr -dr com.apple.quarantine node_modules
Contributions are welcome! Here's how to get started:
git checkout -b feature/my-feature)npm run build — frontend compilescd src-tauri && cargo clippy — no warningscd src-tauri && cargo fmt --check — formatting passesFor bug fixes involving timer, sleep/wake, or restart recovery, please include reproduction steps.
MIT © Ricky Irfandi