Skip to content

NejcZdovc/monitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

62 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Monitor

A lightweight macOS menu bar app that automatically tracks how you spend time on your computer. It runs quietly in the background, recording which apps you use, how much you type, and how long you spend in meetings or watching YouTube β€” then presents it all in a clean, dark-themed dashboard.

No cloud. No accounts. Everything stays local on your machine in a SQLite database.

macOS Electron TypeScript

Why

Most time-tracking tools require manual input or send your data to external servers. Monitor takes a different approach:

  • Fully automatic β€” no timers to start or stop, no manual categorization
  • 100% local β€” your activity data never leaves your machine
  • Zero config β€” install, grant Accessibility permission, and it just works
  • Low overhead β€” runs in a worker thread, async I/O, no impact on typing or performance

Whether you want to understand your work habits, track how much time you spend coding vs. browsing, or just see if meetings are eating your day β€” Monitor gives you that visibility with no effort.

Features

Automatic Tracking

  • App usage β€” tracks the active window every 5 seconds, recording app name, window title, and category
  • Input activity β€” counts keystrokes and mouse clicks (aggregated counts only, no keylogging)
  • Idle detection β€” automatically pauses tracking after 5 minutes of inactivity; resumes when you return
  • Call detection β€” detects active calls in Zoom, Microsoft Teams, Google Meet, and FaceTime; suppresses idle detection during calls
  • YouTube tracking β€” detects YouTube playing in any browser (12 browsers supported), even when the browser is not focused
  • AI time tracking β€” tracks time spent with AI tools both as native apps and in browser tabs
  • Project detection β€” extracts project names from IDE window titles (VS Code, Cursor, JetBrains, Zed, Sublime Text)
  • Sleep/wake resilience β€” automatically recovers input and window tracking after macOS sleep cycles

Smart Categorization

Apps are automatically sorted into categories:

Category Examples
Coding VS Code, Cursor, Xcode, JetBrains suite, Zed, Neovim, Sublime Text
Terminal Terminal, iTerm2, Warp, Ghostty, Alacritty, kitty
AI Claude, ChatGPT, Copilot, Ollama, Perplexity, Poe
Communication Slack, Discord, Messages, Mail, Telegram, WhatsApp
Meetings Zoom, Teams, FaceTime, Google Meet, Webex, Skype
Browsers Chrome, Safari, Firefox, Arc, Brave, Edge, Vivaldi, Orion, Zen Browser
Productivity Notion, Obsidian, Figma, Sketch, Office suite, Linear, Bear
DevTools Postman, Docker, TablePlus, Tower, GitKraken, Proxyman
Entertainment Spotify, YouTube, Music, Netflix, Twitch, VLC
System System Settings, Activity Monitor, Disk Utility

AI usage in browsers (Claude, ChatGPT, Gemini, Perplexity, Midjourney, Hugging Face, etc.) is automatically detected and categorized from window titles.

Dashboard

  • Summary cards β€” active time, keystrokes, mouse clicks, call time, entertainment time, AI time
  • Active time chart β€” hourly (today) or daily breakdown of active vs. idle time; click a bar to drill down
  • Input activity chart β€” keystroke and click trends over time
  • Categories doughnut β€” visual breakdown by category, click to drill down into individual apps
  • Top apps β€” ranked bar chart of most-used applications, color-coded by category
  • Project breakdown β€” top 10 coding projects extracted from IDE window titles
  • AI time chart β€” daily breakdown by AI tool (Claude, ChatGPT, Perplexity, etc.)
  • Call time chart β€” time spent in calls by service (Zoom, Teams, FaceTime, Google Meet)
  • Entertainment chart β€” foreground entertainment apps plus background YouTube consumption
  • Hour drill-down β€” click any hourly bar to see all apps active during that hour
  • Day drill-down β€” click any daily bar to drill into that day's hourly breakdown
  • Time range picker β€” today, this week, this month, or custom date range
  • Auto-refresh β€” dashboard updates every 30 seconds while focused

Menu Bar

  • Tray icon with a quick-stats popup showing today's active time, keystrokes, clicks, call time, entertainment, AI time, and top app
  • Pause/resume tracking with status indicator
  • Open dashboard or quit from the tray

Download

  1. Go to the Releases page
  2. Download Monitor.dmg (or the ZIP)
  3. Open the DMG and drag Monitor to your Applications folder
  4. Launch Monitor from Applications

On first launch, macOS will ask you to grant Accessibility permission:

  1. Go to System Settings β†’ Privacy & Security β†’ Accessibility
  2. Enable Monitor in the list

Development

Prerequisites

  • macOS (Apple Silicon or Intel)
  • Node.js 18+ and npm
  • Python (for building native modules β€” usually pre-installed on macOS)

Setup

# Clone the repository
git clone https://github.com/NejcZdovc/monitor.git
cd monitor

# Install dependencies
npm install

# Run the app
npm start

In development mode the app appears as "Electron" in the Accessibility list. You may need to add it manually: Click + β†’ navigate to node_modules/electron/dist/Electron.app β†’ Open

Scripts

Command Description
npm start Run the app in development mode
npm test Run the test suite (Jest)
npm run package Package the app for distribution
npm run make Create DMG and ZIP installers
npm run lint Lint with Biome
npm run typecheck Type-check with TypeScript
npm run full-check Run lint, typecheck, and tests

Building for Distribution

# Package the app
npm run package

# Create a DMG installer
npm run make

The packaged app will appear in the out/ directory. The distributed version shows as "Monitor" in all system menus and uses the correct app icon.

Publishing a Release

Releases are published via a manual GitHub Actions workflow:

  1. Go to Actions β†’ Publish β†’ Run workflow
  2. Select the version bump type: patch, minor, or major
  3. Click Run workflow

The workflow bumps the version in package.json, creates a git tag, builds the app on macOS, and uploads ZIP and DMG artifacts as a GitHub Release. Go to the repo's Releases page to review and publish.

Auto Updates

The app uses electron-updater to check for updates from GitHub Releases every 24 hours. Updates download silently in the background and install automatically when the user quits the app. Failed checks are retried up to 3 times with a 60-second delay.

Users can also check manually via the app menu (Monitor β†’ Check for Updates...).

Note: Auto-updates on macOS require a code-signed build. Add APPLE_ID, APPLE_PASSWORD, and APPLE_TEAM_ID as repository secrets for notarization.

Architecture

src/
β”œβ”€β”€ main/                        # Electron main process (TypeScript)
β”‚   β”œβ”€β”€ main.ts                  # App entry point
β”‚   β”œβ”€β”€ auto-updater.ts          # GitHub Releases auto-updater
β”‚   β”œβ”€β”€ tray.ts                  # Menu bar tray icon + popup
β”‚   β”œβ”€β”€ window-manager.ts        # Dashboard window lifecycle
β”‚   β”œβ”€β”€ ipc-handlers.ts          # IPC bridge between main ↔ renderer
β”‚   β”œβ”€β”€ categories.ts            # App β†’ category mapping rules
β”‚   β”œβ”€β”€ constants.ts             # Shared config (poll intervals, thresholds)
β”‚   β”œβ”€β”€ types.ts                 # Shared TypeScript types
β”‚   β”œβ”€β”€ data/
β”‚   β”‚   β”œβ”€β”€ database.ts          # SQLite schema, migrations, orphan cleanup
β”‚   β”‚   β”œβ”€β”€ query-engine.ts      # Dashboard read queries (prepared statements)
β”‚   β”‚   β”œβ”€β”€ activity-store.ts    # Activity session writes
β”‚   β”‚   β”œβ”€β”€ input-store.ts       # Input count writes
β”‚   β”‚   β”œβ”€β”€ call-store.ts        # Call session writes
β”‚   β”‚   └── background-entertainment-store.ts  # YouTube session writes
β”‚   └── tracking/
β”‚       β”œβ”€β”€ tracker-manager.ts   # Orchestrates all trackers
β”‚       β”œβ”€β”€ window-tracker.ts    # Active window polling (AppleScript)
β”‚       β”œβ”€β”€ input-tracker.ts     # Keystroke/click aggregation (main thread)
β”‚       β”œβ”€β”€ input-worker.ts      # Keystroke/click hooks (worker thread)
β”‚       β”œβ”€β”€ idle-detector.ts     # System idle detection
β”‚       β”œβ”€β”€ call-detector.ts     # Call process detection (pgrep)
β”‚       β”œβ”€β”€ youtube-tracker.ts   # Background YouTube detection
β”‚       β”œβ”€β”€ session-lifecycle.ts # Reusable session open/split/close state machine
β”‚       └── hour-split.ts        # Hour-boundary splitting utilities
β”œβ”€β”€ renderer/
β”‚   β”œβ”€β”€ main_window/             # Dashboard UI
β”‚   β”‚   β”œβ”€β”€ index.html
β”‚   β”‚   β”œβ”€β”€ styles/main.css
β”‚   β”‚   └── js/
β”‚   β”‚       β”œβ”€β”€ app.ts           # Dashboard controller
β”‚   β”‚       β”œβ”€β”€ date-utils.ts
β”‚   β”‚       β”œβ”€β”€ format-utils.ts
β”‚   β”‚       └── components/      # Chart components (Chart.js)
β”‚   β”œβ”€β”€ tray_popup/              # Tray quick-stats popup
β”‚   β”‚   β”œβ”€β”€ index.html
β”‚   β”‚   └── styles/tray.css
β”‚   β”œβ”€β”€ preload.ts               # Main window context bridge
β”‚   └── tray-preload.ts          # Tray popup context bridge
β”œβ”€β”€ assets/                      # Icons, update manifest
└── test/                        # Jest test suite

Key Design Decisions

  • TypeScript β€” the entire codebase is TypeScript, built with Vite via electron-forge
  • AppleScript for window titles β€” only requires Accessibility permission (not Screen Recording)
  • Worker thread for input tracking β€” prevents keystroke hooks from blocking the main thread; auto-restarts after macOS sleep since IOKit event taps become invalid
  • Hour-boundary splitting β€” all sessions are split at hour boundaries during tracking (not at query time), making hourly aggregation queries trivially correct
  • Idle suppression during calls β€” idle detection is suppressed when Zoom, Teams, Google Meet, or FaceTime calls are active
  • Retroactive idle timestamps β€” idle start is calculated retroactively (now - idleSeconds) for accurate session boundaries
  • SQLite with WAL mode β€” fast, embedded, zero-config database using better-sqlite3
  • No frameworks β€” vanilla TypeScript frontend with Chart.js for visualization
  • Biome for linting and formatting

Privacy

Monitor is designed to be privacy-first:

  • All data is stored locally in a SQLite database in your app data directory
  • No network requests except update checks to GitHub Releases β€” no telemetry, no analytics
  • Input tracking records counts only β€” it does not log what you type
  • Window titles are stored locally for categorization β€” they are never transmitted

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors