A Python tool that synchronizes JIRA tickets to your Obsidian vault using the JIRA REST API and Obsidian Local REST API.
- 🔄 Sync in-progress JIRA tickets to Obsidian notes
- 📝 Rich markdown formatting with metadata, descriptions, and comments
- 🔗 Automatic wiki-linking for assignees and reporters
- 📊 Includes ticket metadata: priority, story points, sprint, dates
- 🔍 Test connections before syncing
- 🎨 Beautiful CLI output with progress indicators
- ⚡ Fast and efficient using UV package manager
- Python 3.11+
- UV package manager
- JIRA Cloud account with API access
- Obsidian Local REST API plugin installed and running
-
Clone the repository:
git clone <repository-url> cd jira-to-obsidian
-
Copy the environment template:
cp .env.example .env
-
Configure your
.env
file with your credentials:# JIRA Configuration JIRA_SERVER=https://your-domain.atlassian.net JIRA_EMAIL=[email protected] JIRA_API_TOKEN=your-jira-api-token JIRA_PROJECTS=PROJ1,PROJ2,PROJ3 # Comma-separated list # Obsidian Configuration OBSIDIAN_API_URL=http://localhost:27123 OBSIDIAN_API_KEY=your-obsidian-api-key OBSIDIAN_FOLDER=JIRA # Folder within vault for tickets
- Log in to Atlassian Account Settings
- Click "Create API token"
- Give it a name and copy the token
- Install the Obsidian Local REST API plugin
- Enable the plugin in Obsidian settings
- Configure the API key in the plugin settings
- Make sure the server is running (default port: 27123)
You can use either jira-to-obsidian
or the shorter j2o
alias for all commands.
Before syncing, test that both JIRA and Obsidian connections are working:
uv run j2o test-connections
# or
./run.sh test-connections
This will show:
- ✅ JIRA connection status, server version, and accessible projects
- ✅ Obsidian API connection and authentication status
- ❌ Any configuration errors
Sync all tickets (excluding Done/Resolved/Closed) from configured projects:
uv run j2o sync
# or simply
./run.sh
To see what would be synced without actually creating/updating files:
uv run j2o sync --dry-run
# or
uv run j2o sync -n
This will show:
- Which tickets would be created or updated
- The full HTTP request details (endpoint, method, headers)
- A preview of the content that would be sent
- File paths where notes would be saved
Sync a single ticket by its key:
uv run j2o sync --ticket PROJ-123
# or
./run.sh sync --ticket PROJ-123
List all JIRA tickets (excluding Done/Resolved/Closed) sorted by priority:
uv run j2o list-jira
# or with specific project
uv run j2o list-jira --project PROJ
This displays a color-coded table with:
- Ticket key and summary
- Priority (color-coded from Highest to Lowest)
- Current status
- Assignee
List all Obsidian notes for a specific JIRA project:
uv run j2o list-obsidian
# or with specific project
uv run j2o list-obsidian --project PROJ
For detailed logging, add the -v
flag:
uv run j2o -v sync
Each JIRA ticket is saved as a markdown note with the following structure:
---
aliases:
- PROJ-123
assignee: "[[John Doe]]"
reporter: "[[Jane Smith]]"
priority: High
status: In Progress
project: PROJ
key: PROJ-123
story_points: 5
sprint: Sprint 23
created: 2024-01-01 10:00
due_date: 2024-01-15
updated: 2024-01-02 15:30
tags:
- jira
- proj
- in-progress
---
# PROJ-123 Ticket Title
## Description
The ticket description content...
## Comments
### Alice - 2024-01-01 11:00
Comment content...
---
[View in JIRA](https://your-domain.atlassian.net/browse/PROJ-123)
Variable | Description | Default |
---|---|---|
JIRA_SERVER |
Your JIRA instance URL | Required |
JIRA_EMAIL |
Email for JIRA authentication | Required |
JIRA_API_TOKEN |
JIRA API token | Required |
JIRA_PROJECTS |
Comma-separated project keys | Required |
OBSIDIAN_API_URL |
Obsidian REST API URL | http://localhost:27123 |
OBSIDIAN_API_KEY |
Obsidian API key | Required |
OBSIDIAN_FOLDER |
Folder for JIRA tickets | JIRA |
UPDATE_EXISTING_NOTES |
Update existing notes | true |
SYNC_INTERVAL_MINUTES |
Sync interval (for automation) | 5 |
uv run pytest
# or with coverage
uv run pytest --cov
uv run black src tests
uv run ruff src tests
jira-to-obsidian/
├── src/jira_to_obsidian/
│ ├── config.py # Configuration management
│ ├── jira_client.py # JIRA API client
│ ├── obsidian_client.py # Obsidian REST API client
│ ├── formatter.py # Ticket formatting
│ ├── sync.py # Synchronization logic
│ └── cli.py # CLI commands
├── tests/ # Unit tests
├── .env.example # Environment template
└── pyproject.toml # Project configuration
-
JIRA Connection Failed
- Verify your JIRA server URL (should end with
.atlassian.net
) - Check API token is valid
- Ensure your email matches the JIRA account
- Verify your JIRA server URL (should end with
-
Obsidian Connection Failed
- Make sure Obsidian is running
- Verify the Local REST API plugin is enabled
- Check the API URL and port (default:
http://localhost:27123
) - Confirm the API key matches the plugin configuration
-
Projects Not Accessible
- Ensure you have read access to the JIRA projects
- Verify project keys are spelled correctly
- Notes not updating: Check
UPDATE_EXISTING_NOTES
is set totrue
- Folder not found: The tool will automatically create the folder if needed
- Missing fields: Some fields (story points, sprint) may use custom field IDs that vary by JIRA instance
MIT License - see LICENSE file for details