Log hours in seconds, not minutes. Quietly tracks your OpenProject activity, so everything you need is one click away at the end.
A Chrome extension that runs in the background while you work in OpenProject, noting which work packages you visit, how long you spend on them, and whether you comment or make changes. When it's time to log hours, open the popup and your day is already laid out -- tracked activity, today's meetings, your assignments, and your favorites, all in one place. Adjust the hours, add a note, hit save.
- Passive activity tracking -- Content scripts monitor which work packages and documents you visit, measure foreground time, and detect comments and updates. No manual input required.
- Daily timesheet popup -- View and manage time entries for any date. Adjust hours per entry (+/- 15 min or +/- 1 h), add comments, and save individually or in batch.
- Calendar with hour bars -- Navigate dates with a monthly calendar that shows logged hours per day as visual bars and highlights weeks that exceed a configurable threshold.
- Sidebar panels -- Six categories of context at your fingertips:
- Favorites -- Pinned work packages for quick access
- Recent -- Work packages you've recently interacted with
- Assigned to me -- Your current assignments from OpenProject
- Meetings -- Today's meetings, with the ability to link each meeting to a work package
- Activity -- Live feed of tracked page visits for the selected date, grouped by hour
- Notes -- Per-day notes and todos stored locally
- Work package search -- Search by text with type-prefix filtering (e.g. filter by Task, Bug, Feature).
- Out-of-office tracking -- Mark days as vacation, sick leave, or public holiday (full or half day). OOO hours are reflected in the date bar and calendar.
- Draft persistence -- Unsaved time entries are stored as drafts and survive popup close / browser restart.
- Meeting-WP linking -- Associate a meeting with a work package so you can log time against it with one click.
- Clone or download this repository.
- Open Chrome and navigate to
chrome://extensions. - Enable Developer mode (toggle in the top-right corner).
- Click Load unpacked and select the project folder.
- The extension icon appears in the toolbar.
On first launch the settings panel opens automatically.
- Enter your Host URL (e.g.
https://community.openproject.org). - Enter your API Key. You can generate one in your OpenProject account under My account > Access tokens.
- Click Test Connection to verify. Once successful, the popup loads your time entries.
| Setting | Tab | Description |
|---|---|---|
| Host URL | OpenProject access | Base URL of your OpenProject instance |
| API Key | OpenProject access | Personal API token for authentication |
| Weekly Hours Threshold | Advanced settings | Weeks meeting or exceeding this value are highlighted in the calendar (default: 40) |
├── manifest.json MV3 Chrome extension manifest
├── background.js Service worker -- aggregates activity data, prunes old entries daily
├── content-script.js Isolated-world content script -- detects OP pages, sends heartbeats, tracks interactions
├── content-script-main.js MAIN-world content script -- intercepts fetch/XHR/pushState to detect writes and SPA navigations
├── openproject-api.js OpenProject API v3 client (time entries, work packages, meetings, search, types, projects)
├── storage.js Storage modules: Settings (sync), ActivityStorage, NotesStorage, MeetingsStorage (local)
├── utils.js Shared utilities
├── popup.html Popup shell -- loads all scripts and defines the layout skeleton
├── popup.js Popup orchestrator -- initializes components, wires callbacks, manages API client lifecycle
├── popup.css All popup styles
├── icons/ Extension icons (16, 32, 48, 128)
└── components/
├── top-bar.js Header bar with settings button
├── settings.js Full-screen settings overlay with tabbed panels
├── date-bar.js Date navigation (prev/next, date display, total hours, OOO indicator)
├── calendar-popup.js Monthly calendar dropdown with per-day hour bars and weekly totals
├── time-entries.js Time entry cards with hour adjustment, comments, WP reassignment, batch save
├── sidebar.js Icon rail + flyout panels (Favorites, Recent, Assigned, Meetings, Activity, Notes)
├── ooo-manager.js OOO data storage and retrieval (vacation, sick, public holiday)
└── ooo-popup.js OOO entry creation/editing UI
flowchart LR
subgraph browser [Browser]
CS_MAIN["content-script-main.js\n(MAIN world)"]
CS["content-script.js\n(isolated world)"]
BG["background.js\n(service worker)"]
end
subgraph storage [Chrome Storage]
LOCAL["chrome.storage.local\n(activities, notes, meetings cache, drafts)"]
SYNC["chrome.storage.sync\n(settings, favorites, OOO)"]
end
subgraph popup [Popup]
POP["popup.js + components"]
end
OP["OpenProject API"]
CS_MAIN -->|"CustomEvents\n(writes, navigations)"| CS
CS -->|"chrome.runtime\nmessages"| BG
BG -->|"read/write"| LOCAL
POP -->|"read/write"| LOCAL
POP -->|"read/write"| SYNC
POP -->|"API v3 calls"| OP
Content scripts run on every page. When the URL matches the configured OpenProject host, the isolated-world script identifies work-package and document pages, sends a pageVisit message to the background, and starts a 15-second heartbeat that increments foreground time. The MAIN-world script intercepts fetch, XMLHttpRequest, and history.pushState/replaceState to detect write operations (comments, updates) and SPA navigations, forwarding them as DOM events to the isolated-world script.
Background service worker receives messages and aggregates activity into chrome.storage.local keyed by date (YYYY-MM-DD). Entries older than 30 days are pruned on startup and via a daily alarm.
Popup reads time entries and work-package data from the OpenProject API, and reads activity, notes, and draft data from local storage. All UI state flows through the component modules wired together by popup.js.
| Permission | Reason |
|---|---|
storage |
Persist settings (sync) and activity/notes/cache data (local) |
alarms |
Schedule daily cleanup of old activity data |
notifications |
Reserved for future reminder notifications |
tabs |
Access tab URLs for activity context |
windows |
Open OpenProject links in popup windows so the extension popup stays open |
host_permissions: *://*/* |
Content scripts need to run on the OpenProject instance (URL is user-configured, so the broad pattern is required); API calls go directly to the host |