Toggl Jira Sync
Local CLI for syncing Toggl time entries into Jira worklogs. It keeps sync state in a local SQLite database, so repeated runs can skip already-synced entries and recover from interrupted runs.
This is an independent community tool. It is not an official Toggl, Jira, or Atlassian product, and it is not endorsed by those companies.
Setup
Installation
From crates.io:
From GitHub:
Update an existing Cargo install:
For local development from this repository:
GitHub install works directly from the repository and is useful for testing unreleased changes. The crates.io install is the recommended stable path.
1. Build or run the CLI
From this repository:
If you use the local alias:
2. Enter setup values
config setup creates:
- config:
~/.config/toggl-jira-sync/config.toml - credentials:
~/.config/toggl-jira-sync/credentials.env - SQLite path in config:
toggl-jira-sync.sqlite - OS scheduler job for hourly sync, when scheduler installation is supported by the current OS
The setup prompt asks only for values that cannot be derived:
Toggl API token:
Toggl workspace id fallback, only if workspace discovery is skipped or fails
Jira site URL:
Jira email:
Jira API token:
Notes:
- In an interactive terminal, the Toggl API token is used to discover workspaces automatically.
- If one Toggl workspace is found, it is selected automatically.
- If multiple workspaces are found, the CLI shows a numbered list.
Jira site URLis enough; the internal site key is derived from the URL. Example:https://sabservis.atlassian.netbecomessabservis.- No Jira issue prefixes are configured. Jira site selection is resolved dynamically per issue and cached in SQLite.
- The SQLite file is created automatically on first command that opens the DB.
- Setup installs an hourly OS scheduler job by default. Use
tjs schedule status,tjs schedule set --disabled, ortjs schedule uninstallto inspect or disable it.
3. Check the generated config
Secrets are redacted by default. To inspect local secret values explicitly:
4. Validate config
Daily usage
Launch the TUI:
You can also open it explicitly:
The TUI shows recent local sync state from SQLite and lets you run common actions without leaving the terminal:
- search and filter entries
- open matching Jira or Toggl links
- press
dto run a dry-run sync - press
sto run a real sync - press
ato toggle the hourly OS scheduler
It is the main day-to-day view:
Toggl -> Jira Sync TUI normal
Issue search: - | Date/time filter: - | rows=3/3 | OS schedule: on every 60m
date start end duration issue site worklog status reason
2026-05-04 15:59 17:43 1h 44m PROJ-123 acme 26410 synced -
2026-05-04 18:00 18:30 30m PROJ-456 acme - skipped running entry
2026-05-05 09:15 10:00 45m PROJ-789 acme - error issue not found
Issue: PROJ-123 | Worklog: 26410 | Reason: -
Issue URL: https://acme.atlassian.net/browse/PROJ-123
Worklog URL: https://acme.atlassian.net/browse/PROJ-123?focusedWorklogId=26410
While the TUI is open, it also runs an hourly in-process sync. The OS scheduler is separate and keeps hourly sync running when the TUI is not open.
Run a safe preview first:
Run the real sync:
Inspect local sync state:
Recover after an interrupted or uncertain sync:
Manage the hourly OS scheduler:
How Jira site resolution works
For each Toggl entry, the CLI extracts a Jira issue key from the description, for example PROJ-123.
Resolution flow:
- Check SQLite cache for
issue_key -> jira_site_key. - If cached, use it without Jira discovery.
- If not cached, query every enabled Jira site with
GET /rest/api/3/issue/{issueKey}. - If exactly one site has the issue, save that mapping to SQLite.
- If zero or multiple sites match, report an error instead of creating a worklog on the wrong site.
This means setup does not need issue prefixes.
Files created locally
~/.config/toggl-jira-sync/config.toml
~/.config/toggl-jira-sync/credentials.env
toggl-jira-sync.sqlite
credentials.env stores raw local credentials and is written with user-only permissions on Unix/macOS.