Therp Timer is a browser extension for recording time on Odoo project work and posting that time to Odoo timesheets.
It lets you:
- connect to one or more Odoo instances
- load assigned issues or tasks
- start and stop a timer from the browser popup
- write the result back to Odoo timesheets
- optionally export timesheet data to CSV
The extension has separate manifests for Chromium-based browsers and Firefox because background script support differs between the two browser families.
At a high level, the extension works like this:
- You configure one or more Odoo remotes in the options page.
- You open the popup and choose a remote.
- The extension either reuses an existing Odoo browser session or logs in with a username and password.
- It loads project items from Odoo, usually
project.taskorproject.issuedepending on the configured data source. - You start a timer on a selected row.
- When you stop the timer, the extension creates the correct timesheet record in Odoo.
- Optionally, it can download CSV timesheet data.
The extension supports two common flows.
When the remote is configured to use project.task, the extension writes time to:
account.analytic.line
When the remote is configured to use project.issue, the extension writes time to:
hr.analytic.timesheet
The extension also tries to find the correct analytic account from the issue/task or its related project.
- popup-based timer UI
- support for multiple Odoo remotes
- use existing browser Odoo session or manual login
- task/issue filtering and search
- automatic timer state persistence
- CSV export for current month timesheets
- optional download of issue/task-specific timesheets
- browser-specific manifests for Chromium and Firefox
A practical layout is:
therp_timer_owl/
src/
popup.html
options_main_page.html
js/
css/
img/
dist/
chrome/
manifest.json
popup.html
options_main_page.html
js/
css/
img/
firefox/
manifest.json
popup.html
options_main_page.html
js/
css/
img/
In this structure:
srcis your editable sourcedist/chromeis the loadable Chromium builddist/firefoxis the loadable Firefox build
Each browser folder must contain its own root manifest.json.
Chromium-based browsers and Firefox handle extension background execution differently.
Use a service worker background definition:
{
"background": {
"service_worker": "js/background.js"
}
}Use background scripts:
{
"background": {
"scripts": ["js/background.js"],
"type": "module"
}
}Because of that difference, keeping separate browser build folders is the easiest setup.
Before loading the extension, make sure you have:
- a working Odoo instance
- access to tasks or issues you want to track
- a browser supported by one of the two builds
- the extension files arranged so the correct
manifest.jsonis at the root of the browser-specific folder
Examples:
- Brave
- Chrome
- Chromium
- Edge
- Vivaldi
- Open the extensions page in your browser.
- Enable Developer mode.
- Choose Load unpacked.
- Select the browser-specific extension folder, for example:
/dist/chrome
- Confirm that the extension appears in the extensions list.
- Pin the extension to the toolbar if desired.
The Chromium build should use a manifest.json with a background service worker, for example:
{
"manifest_version": 3,
"background": {
"service_worker": "js/background.js"
}
}- Click the extension icon.
- Open Options.
- Add an Odoo remote:
- name
- base URL
- database
- data source such as
project.taskorproject.issue
- Save the remote.
- Return to the popup.
- Select the remote.
- Either:
- keep Use Existing Session enabled if already logged into Odoo in the browser, or
- disable it and log in manually
- Start a timer on a task or issue.
- Stop the timer to write the timesheet back to Odoo.
Examples:
- Firefox
- Firefox Developer Edition
- Open:
about:debugging#/runtime/this-firefox
- Click Load Temporary Add-on....
- Select the actual Firefox manifest file:
/dist/firefox/manifest.json
- The temporary add-on should load into Firefox.
Firefox expects the file to be named exactly:
manifest.json
Do not try to load a file called manifest.firefox.json directly unless you have copied or renamed it to manifest.json inside the Firefox build folder.
The Firefox build should use background scripts instead of a service worker:
{
"manifest_version": 3,
"background": {
"scripts": ["js/background.js"],
"type": "module"
}
}The usage flow is the same as Chromium:
- Open Options.
- Add a remote.
- Return to the popup.
- Select the remote.
- Reuse an existing Odoo session or log in manually.
- Start and stop timers as needed.
A remote usually includes:
- Name: friendly label shown in the popup
- URL: base Odoo URL, for example
https://example.odoo.com - Database: target database name
- Data source: usually
project.taskorproject.issue
If the wrong data source is selected, the extension may load the wrong model or fail to create the expected timesheet record type.
This is the easiest option when you are already logged into Odoo in the same browser.
- Log into Odoo normally in a browser tab.
- Open the extension popup.
- Choose the remote.
- Leave Use Existing Session enabled.
- Click Login.
If the session is valid, the extension will load your tasks/issues.
Use this when there is no active browser Odoo session.
- Open the popup.
- Disable Use Existing Session.
- Enter username and password.
- Click Login.
When you start a timer:
- the active item is remembered
- the start time is stored in extension storage
- the popup can continue showing elapsed time
When you stop a timer:
- the elapsed time is calculated
- rounding logic is applied
- you may be prompted for a description
- a new timesheet record is created in Odoo
The extension can export:
- current month timesheets
- issue/task-specific timesheets
This is useful for local backup, manual review, or reporting.
Check the following:
- the selected file is named
manifest.json - the file is inside the Firefox build folder
- the Firefox manifest uses
background.scripts - the JSON is valid
This usually means the Chromium manifest was used in Firefox. Switch to the Firefox build folder.
Possible causes:
- Odoo session expired
- remote URL does not match the actual Odoo login host
- browser cookies are missing or blocked
Try disabling Use Existing Session and log in manually.
Possible causes:
- wrong data source configured
- current user has no assigned records
- Odoo model fields differ from what the extension expects
- slow Odoo response during startup
Check:
- the related project or task has an analytic account
- the remote is using the correct model
- your Odoo user has permission to create timesheets
- the correct journal exists for the issue-based flow
A good workflow is:
- maintain common source files in
src - produce separate
dist/chromeanddist/firefoxbuilds - keep the code shared as much as possible
- only vary the manifest and browser-specific behavior where required
The extension currently keeps its working runtime templates in the JavaScript entry files under:
dist/chrome/js/components/popup-app.jsdist/chrome/js/components/options-app.jsdist/chrome/js/components/readmore.jsdist/firefox/js/components/popup-app.jsdist/firefox/js/components/options-app.jsdist/firefox/js/components/readmore.js
Those createBlock(...) templates remain the runtime fallback so that the
extension keeps working even when ahead-of-time compiled Owl templates are not
available.
Editable source XML templates live under:
src/templates/popup_app.xmlsrc/templates/options_app.xmlsrc/templates/readmore.xml
At runtime, the extension loads js/templates.js before the app modules.
If that file registers compiled templates on
globalThis.__THERP_TIMER_TEMPLATES__, the app will use them. If not, it
falls back to the current JavaScript createBlock(...) templates.
Browser extensions often cannot rely on runtime template compilation in the way standard Odoo web builds do. Keeping the JavaScript fallback avoids breaking the popup or options page while developers gradually move templates into XML source files.
To avoid changing the host system Node installation, create an isolated Node environment with Python:
python3 -m pip install --user nodeenv
python3 -m nodeenv .nodeenv
. .nodeenv/bin/activateA helper script is included:
./scripts/setup_nodeenv.sh
. .nodeenv/bin/activate- Clone the Owl repository locally.
- Activate the
nodeenvenvironment. - Build the runtime and compiler.
- Compile the XML templates from
src/templates.
Example workflow:
git clone https://github.com/odoo/owl.git
cd owl
npm install
npm run build:runtime
npm run build:compiler
npm run compile_templates -- /path/to/odoo-timer/src/templatesA helper script is also included in this repository:
./scripts/compile_owl_templates.sh /path/to/owl #(i.e path to owl is the cloned Odoo's OWL repo => https://github.com/odoo/owl.git)NB:
- Make sure you have templates to be compile by the scrip in
src/template/*.xml*otherwise script might fail. - Please note you need to clone Odoo's OWL repo branch that is identical to your owl js library when compiling templates otherwise you will get templat errors when generating
template.js. For instance: this current project is using OWL lib v2.8.2. So we need to clone owl repo branch owl-2.x (i.e https://github.com/odoo/owl/tree/owl-2.x) to compile template with.
The extension expects compiled templates to be made available through:
globalThis.__THERP_TIMER_TEMPLATES__ = {
ReadMore: /* compiled template */,
PopupApp: /* compiled template */,
OptionsApp: /* compiled template */,
};The distributed dist/*/js/templates.js files are safe placeholders.
Replace them during development with your generated template registration code,
or adapt the generated Owl output into that registry shape.
Shared libraries now live under:
dist/chrome/js/lib/dist/firefox/js/lib/
Application entry modules now live under:
dist/chrome/js/components/dist/firefox/js/components/
This keeps library-style files such as browser-polyfill.js, owl.iife.js,
and common.js separated from the popup and options app modules.
Therp Timer is a practical browser-based Odoo timer that helps users quickly record work against Odoo project items.
Use:
- the Chrome/Brave build for Chromium-based browsers
- the Firefox build for Firefox-based browsers
Keep a separate manifest.json in each browser build folder, and load that folder with the browser’s extension developer tools.
