Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Miru Time Tracking

Miru Time Tracking is a local-first macOS menu bar app for employees who need a fast, focused way to track work in Miru. It keeps the timer visible in the system menu bar, opens into a compact desktop tracker, and syncs the current timer with Miru web when an account is connected.

Built from LuanRoger/electron-shadcn with Electron Forge, Vite, React, TypeScript, Tailwind, TanStack Router, Vitest, and Playwright.

Miru Time Tracking is MIT-licensed software.

Screenshots

Miru Time Tracking running timer Miru Time Tracking account and settings popover Miru Time Tracking idle recovery modal Miru Time Tracking profile avatar in the timer window

These screenshots are generated from the packaged Electron app flow used by the integration specs: signed-in timer, account/sync menu, idle recovery, and a sanitized profile-avatar preview. The avatar preview uses generic local work data and does not expose email, tokens, workspace, client, project, or entry details.

Downloads

Latest release: https://github.com/saeloun/miru-time-desktop/releases/tag/v0.1.8

Highlights

  • Native macOS menu bar timer with a stable-width time label and stateful tray icon colors for ready, running, paused, and idle.
  • Compact time tracker window positioned below the menu bar, with high-contrast timer controls, fixed-width icon dock, and a Miru-styled command surface.
  • Local-first tracking through renderer local storage plus persisted Electron userData timer state, so timers survive app relaunches.
  • Resumable timer stack so starting a new timer keeps the previous timer available to resume or remove.
  • Timesheet drill-down from Today, This week, and Entries summary cards into detailed time entries.
  • Miru account bridge for login, signup handoff, logout, workspace switching, current timer pull/push, and saving, editing, or deleting time entries.
  • Current timer sync with Miru web through GET/PUT /api/v1/desktop/current_timer, including multiple desktop timer states.
  • Idle recovery with a custom in-app modal: trim and continue, trim and restart, or keep idle time.
  • Employee-focused UI with no billing, rates, invoice, admin, or dashboard surfaces.
  • Profile-aware settings showing the Miru user avatar when available, workspace, sync status, idle threshold, and locale.
  • Miru locale support that reads user.locale or user settings first, then falls back to stored/browser locale and English strings.
  • Integration coverage for the desktop timer, tray title, idle recovery, persistence, account menu behavior, and locale rendering.

Product Shape

The app intentionally behaves like a small desktop utility, not a full web dashboard.

  • The first screen is login/signup when no Miru session exists.
  • The primary surface is the timer, project/task notes, summary, and timesheet entries.
  • Account and sync controls live in a focused popover from the profile button.
  • The tray icon carries state visually; the tray title stays width-stable to avoid menu bar jitter.

Local Development

rtk mise exec -- bun install
rtk mise exec -- bun run start

The app opens an Electron window and creates a macOS menu bar item. During normal development it stores app data in Electron userData.

Miru Web Connection

Production builds connect to Miru web at https://app.miru.so by default and do not show a Miru URL field in the sign-in flow.

Useful development overrides:

MIRU_API_BASE_URL=http://127.0.0.1:3000 rtk mise exec -- bun run start
MIRU_SHOW_BASE_URL_FIELD=true rtk mise exec -- bun run start
MIRU_ALLOW_BASE_URL_OVERRIDE=true rtk mise exec -- bun run start

MIRU_API_BASE_URL changes the default API host. MIRU_SHOW_BASE_URL_FIELD exposes the sign-in URL field. MIRU_ALLOW_BASE_URL_OVERRIDE lets the main process honor stored or submitted custom hosts.

Build From Source

Use Node 24, matching CI.

rtk mise exec -- bun install
rtk mise exec -- bun run check
rtk mise exec -- bun run test
rtk mise exec -- bun run package

bun run package creates an unpacked macOS app under out/. bun run make creates distributable release artifacts under out/make/.

Portable ZIP builds for release:

rtk mise exec -- bun run make:mac:release
rtk mise exec -- bun run make:mac:release:apple
rtk mise exec -- bun run make:mac:release:intel
rtk mise exec -- bun run make:linux
rtk mise exec -- bun run make:windows

Use make:mac:release for public macOS ZIPs; it enables the release-only Forge signing and notarization path. See Release Checklist for the required Apple certificate and notarization environment variables.

Verification

rtk mise exec -- bun run check
rtk mise exec -- bun run test
rtk mise exec -- bun run test:e2e
rtk mise exec -- bun run package

Useful full release check:

rtk mise exec -- bun run check
rtk mise exec -- bun run test
rtk mise exec -- bun run test:e2e
rtk mise exec -- bun run make
rtk mise exec -- bun audit

The Playwright Electron specs launch the packaged app in a temporary profile so tests do not touch your real timer or Miru session.

Package and Install Locally

Package the macOS app:

rtk mise exec -- bun run package

Open the packaged app:

open "out/Miru Time Tracking-darwin-arm64/Miru Time Tracking.app"

Install it into /Applications:

ditto "out/Miru Time Tracking-darwin-arm64/Miru Time Tracking.app" "/Applications/Miru Time Tracking.app"
open "/Applications/Miru Time Tracking.app"

Build a distributable ZIP:

rtk mise exec -- bun run make

The ZIP is generated under:

out/make/zip/darwin/arm64/

Miru Sync

Renderer calls are exposed through window.miruApi:

  • login, signup, logout
  • switchWorkspace
  • syncCurrentTimer("pull" | "push")
  • saveTimerEntry, updateTimerEntry, deleteTimerEntry

The main process owns API calls, local account persistence, timer persistence, tray updates, and offline fallback. Email/password login completes a desktop session today. Signup returns users to the login form after Miru creates the account, and Google opens Miru web sign-in until Miru web exposes a native desktop token callback. See Sync strategy for the API contract and conflict rules.

Testing Scope

See Integration specs for the current e2e coverage.

Covered flows include:

  • Signed-out onboarding.
  • Shared desktop timer behind the renderer.
  • Native tray title and icon state.
  • Idle recovery actions.
  • Timer hero layout guard so elapsed time and controls do not overlap.
  • Start-new-timer and paused timer resume flows.
  • Timer context persistence across relaunch.
  • Account menu close/logout behavior.
  • Miru user locale rendering.
  • RTL locale layout.
  • Live timesheet history, date switching, and summary-card drill-down.
  • Miru current timer push/pull with multiple timer states.

Release Prep

  1. Run rtk mise exec -- bun run check.
  2. Run rtk mise exec -- bun run test.
  3. Run rtk mise exec -- bun run test:e2e.
  4. Run rtk mise exec -- bun run make:mac:release.
  5. Open the packaged app and confirm the Miru icon, tray timer, account popover, and idle modal render correctly.
  6. Publish the generated ZIP manually or run rtk mise exec -- bun run publish when ready for a draft GitHub release.

Additional release notes live in Release checklist.

Docs

About

Miru Time Desktop, an Electron app for time tracking, projects, invoices, expenses, and reports.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages