Storage Architecture
Credentials (Secure Keychain)
Settings (Preferences API)
Credentials
Stored in macOS Keychain under service namecom.omnifocus.plugin.jira-sync.
Your Jira account ID (not email address).How to find:
- Log in to Jira
- Visit your profile page
- Look for the account ID in the URL:
https://yourcompany.atlassian.net/jira/people/{accountId}
5d8f9c0a1234abcd5678efghStorage: Keychain user fieldJira API token for authentication.How to generate:
- Visit https://id.atlassian.com/manage-profile/security/api-tokens
- Click “Create API token”
- Give it a descriptive label (e.g., “OmniFocus Sync”)
- Copy the token immediately (cannot be viewed again)
password fieldSecurity: Transmitted via Basic Auth over HTTPS:Settings
Stored in OmniFocus Preferences as JSON under keyjiraSync.settings.
Connection Settings
Base URL of your Jira instance.Format: Must start with Default: None (required field)
https:// and end without trailing slashExamples:https://yourcompany.atlassian.nethttps://jira.yourcompany.com
JQL (Jira Query Language) query to filter issues.Examples:Default: None (required field)
assignee = currentUser() AND resolution = Unresolvedproject = PROJ AND status != Donelabels = urgent AND created >= -30d
OmniFocus Organization
Tag name to apply to all synced tasks.Format: Use colons for nested tags (e.g., Usage: Used to identify synced tasks during full refreshDefault: None (required field)
Work:JIRA)Validation:Enable parent-child project organization for Jira subtasks.Behavior when enabled:Default:
- Subtasks are created under parent tasks or projects
- Parent-child relationships are preserved from Jira
- Requires parent to exist before subtask is synced
- All issues are created as flat tasks
- No hierarchy is created
falseFolder path for organizing projects created from parent issues.Format: Use colons for nested folders (e.g., Default: Empty (root level)
Work:Projects)Behavior:- If folder exists: Projects created in specified folder
- If folder not found: Projects created at root level (logged warning)
- If empty: Projects created at root level
Status Mapping
List of Jira status names that should mark tasks as completed.Format: Array of strings (comma-separated in UI)Input processing:Default values:Effective resolution:Case sensitivity: Status matching is case-sensitiveExamples:
Done, Closed, ResolvedDone, Released, DeployedComplete, Finished
List of Jira status names that should mark tasks as dropped.Format: Array of strings (comma-separated in UI)Default values:Usage:Examples:
WithdrawnCancelled, RejectedWon't Do, Invalid
Sync State
ISO 8601 timestamp of the last successful sync.Format: Used for incremental queries:Preserved on reconfiguration:Default:
YYYY-MM-DDTHH:mm:ss.sssZExample: 2026-03-03T14:23:45.123ZUpdated after sync:null (first sync fetches all matching issues)Constants
Hardcoded values injiraCommon.js:
API Configuration
Jira REST API version to use.Endpoints:
/rest/api/3/search/jql/rest/api/3/myself
Maximum number of issues to fetch per API request.Pagination is handled automatically using
nextPageToken.Fields retrieved from Jira API.Current fields:
summary: Issue titledescription: ADF-formatted descriptionstatus: Current status (name and category)duedate: Due date (ISO date string)updated: Last update timestampparent: Parent issue (for subtasks)
HTTP Status Codes
Retry Configuration
Maximum number of retry attempts for failed requests.Total attempts = 1 initial + 3 retries = 4 attempts.
Base delay between retries in milliseconds.Exponential backoff:
- Attempt 0: 1000ms (1s)
- Attempt 1: 2000ms (2s)
- Attempt 2: 4000ms (4s)
- Attempt 3: 8000ms (8s)
Maximum delay between retries (1 minute).Used for rate limiting with
Retry-After header:Error Messages
The plugin provides actionable error messages based on HTTP status codes:The plugin attempts to extract detailed error messages from Jira’s JSON response (
errorMessages and errors fields) and appends them to the error message.