Skip to content

seungbinshin/opsidian-graph

Repository files navigation

Opsidian Graph

Generate an Obsidian knowledge graph from your GitHub PRs, JIRA issues, and Confluence pages — automatically.

GitHub PRs + JIRA Issues + Confluence Pages → Auto-Categorized Notes → Obsidian Vault with [[wikilinks]]

Your entire engineering history as a searchable, interconnected knowledge graph. Updated daily. No manual work.

What you get

From GitHub:

  • PR Notes — one note per pull request, with commits, topics, and cross-links
  • Repo Maps — Maps of Content per repository, listing all your PRs

From JIRA:

  • Issue Notes — one note per JIRA issue, with status, priority, description, and labels

From Confluence:

  • Page Notes — one note per Confluence page you've contributed to

Cross-source:

  • Topic Maps — Auto-clustered by engineering topic (e.g., Clock, CI/CD, Memory). Same keywords categorize PRs, JIRA issues, AND Confluence pages into shared topic MOCs
  • Weekly Notes — Weekly activity grouped by repo
  • Monthly Notes — Monthly rollups with per-repo and per-type breakdown
  • Expertise Profile — Auto-generated "Areas of Expertise" with bar charts
  • Dashboard — Stats, streaks, and recent activity at a glance
  • Color-Coded Graph — Each source type and repo gets its own color
  • Offline Mode — Vault regenerates from local cache, even without any API access

Example: JIRA Issue Note

---
title: "BEV-179: [EDGE_TOP] bid mismatch"
type: issue
jira_key: "BEV-179"
project: "BEV"
status: "Done"
issue_type: "Bug"
priority: "Medium"
topics:
  - "Verification"
---

# BEV-179: [EDGE_TOP] bid mismatch

- **Project:** Bertha-Edge-Verification (`BEV`)
- **Status:** Done
- **Type:** Bug

## Topics
- [[Verification]]

## Links
- [JIRA](https://your-company.atlassian.net/browse/BEV-179)

Every [[wikilink]] connects to another note — repos, topics, weeks, issues — forming a navigable graph.

Quick Start

Prerequisites

  • Python 3.10+
  • GitHub CLI (gh) — authenticated with repo scope
  • Obsidian — to view the generated vault
  • Atlassian account (optional) — for JIRA and Confluence integration

1. Install

git clone https://github.com/seungbinshin/opsidian-graph.git
cd opsidian-graph
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

2. Configure credentials

Copy the example env file and fill in your values:

cp .env.example .env

Edit .env:

# Required for JIRA + Confluence (get token at https://id.atlassian.com/manage-profile/security/api-tokens)
ATLASSIAN_EMAIL=your-email@company.com
ATLASSIAN_TOKEN=your-api-token
ATLASSIAN_URL=https://your-company.atlassian.net

# Optional — for LLM-powered topic extraction and weekly summaries
ANTHROPIC_API_KEY=sk-ant-...

.env is gitignored — your secrets stay local.

3. Initialize — find your repos

The init command auto-discovers which GitHub repos you've contributed to:

opsidian-graph init --org <YOUR_ORG>

This creates config/repos.yaml with every repo you've touched.

Important: Edit config/repos.yaml to keep only repos you actively modify. Ask yourself: "Which repos do I open PRs in regularly?" Keep those, delete the rest.

Also add your JIRA projects and Confluence spaces:

org: My-Company
author: my-github-username

# JIRA projects to sync (issues assigned to you)
jira_projects:
  - PROJ
  - BACKEND
  - INFRA

# Confluence spaces to sync (pages you contributed to)
confluence_spaces:
  - Engineering
  - Architecture

repos:
  - name: backend-api
    description: "Main backend service"
    color: "#4A90D9"        # Blue in Obsidian graph
  - name: infra-k8s
    description: "Kubernetes infrastructure"
    color: "#50C878"        # Green

How to find your JIRA project keys: Look at your JIRA issue URLs — the prefix before the number (e.g., PROJ-123 → project key is PROJ).

How to find your Confluence space keys: Look at your Confluence page URLs — the space key appears after /spaces/ (e.g., /spaces/Engineering/pages/...).

4. Customize topics (optional but recommended)

Topics are keyword patterns that auto-tag PRs, JIRA issues, AND Confluence pages. Edit config/topics.yaml:

topics:
  # Each topic has regex patterns matched against titles and descriptions
  # Use \b for word boundaries so "ci" matches "CI" but not "special"

  Database:
    - "\\bdb\\b"
    - "\\bmigration\\b"

  API:
    - "\\bapi\\b"
    - "\\bendpoint\\b"

  CI/CD:
    - "\\bci\\b"
    - "\\bworkflow\\b"

How to pick good topics: Look at your recent PR titles and JIRA issue summaries. What words keep appearing? Those are your topics.

Items that don't match any keyword get labeled "Uncategorized". If you set ANTHROPIC_API_KEY, unmatched PRs are classified by an LLM instead.

5. First sync

# Without LLM (free, uses keyword matching only)
opsidian-graph sync --full --no-llm

# With LLM (requires Anthropic API key)
opsidian-graph sync --full

6. Open in Obsidian

  1. Open Obsidian
  2. Click the vault switcher (bottom-left)
  3. Select "Open folder as vault"
  4. Choose the vault/ folder inside this project
  5. Open the Graph View (left sidebar) to see your knowledge graph
  6. (Optional) Install the 3D Graph community plugin for an interactive 3D visualization: Settings > Community plugins > Browse > search "3D Graph" > Install > Enable

Daily Use

# Incremental sync — only fetches new/updated items (fast)
opsidian-graph sync

# Full re-sync — re-fetches everything
opsidian-graph sync --full

# Regenerate vault from cache — no internet needed
opsidian-graph generate

Auto-sync with cron (recommended)

Set up a weekly cron job so your vault stays fresh without re-reading already-synced items:

# Create log directory
mkdir -p /path/to/opsidian-graph/logs

# Open crontab editor
crontab -e

# Add this line — syncs every Monday at 9:00 AM (adjust path to your install)
0 9 * * 1 /path/to/opsidian-graph/.venv/bin/opsidian-graph sync --no-llm >> /path/to/opsidian-graph/logs/sync.log 2>&1

How incremental sync works: The tool tracks a last_updated_at timestamp per repo/project in .opsidian_state.json. Each sync only fetches items modified after that timestamp — it never re-reads already-synced content. This makes weekly syncs fast even with large histories.

Cron field Meaning
0 9 * * 1 Every Monday at 9:00 AM
0 9 * * * Every day at 9:00 AM
0 */6 * * * Every 6 hours

Verify it's working:

# Check your crontab
crontab -l

# Check sync logs
tail -20 /path/to/opsidian-graph/logs/sync.log

# Check last sync time
cat .opsidian_state.json

Note: cron jobs require your Mac to be awake. If your machine is asleep at 9 AM Monday, the sync will be skipped until the next trigger. For a more reliable alternative on macOS, use launchd (see below).

Alternative: launchd (macOS-native, runs even after wake)

Create ~/Library/LaunchAgents/com.opsidian-graph.sync.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.opsidian-graph.sync</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/opsidian-graph/.venv/bin/opsidian-graph</string>
        <string>sync</string>
        <string>--no-llm</string>
    </array>
    <key>WorkingDirectory</key>
    <string>/path/to/opsidian-graph</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Weekday</key>
        <integer>1</integer>
        <key>Hour</key>
        <integer>9</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/path/to/opsidian-graph/logs/sync.log</string>
    <key>StandardErrorPath</key>
    <string>/path/to/opsidian-graph/logs/sync-error.log</string>
</dict>
</plist>

Load it:

launchctl load ~/Library/LaunchAgents/com.opsidian-graph.sync.plist

Unlike cron, launchd will run the missed job when your Mac wakes up.

Offline / Portfolio Mode

All data is cached locally in cache/ (PRs, JIRA issues, Confluence pages). The generate command rebuilds the vault entirely from cache — no API access needed.

This means:

  • Your vault survives losing access to private repos and company Atlassian (e.g., leaving a company)
  • You can regenerate with different templates without re-fetching
  • The cache is your portable engineering archive

Vault Structure

vault/
├── Dashboard.md              ← Home page with stats, streaks, links
├── Expertise.md              ← Auto-generated Areas of Expertise profile
├── PRs/                      ← One note per GitHub PR, organized by repo
│   ├── backend-api/
│   └── infra-k8s/
├── Issues/                   ← One note per JIRA issue, organized by project
│   ├── PROJ/
│   └── BACKEND/
├── Pages/                    ← One note per Confluence page, organized by space
│   ├── Engineering/
│   └── Architecture/
├── Repos/                    ← Map of Content per repository
├── Topics/                   ← Map of Content per topic (cross-source!)
├── Weekly/                   ← Weekly activity notes
├── Monthly/                  ← Monthly rollup notes
└── .obsidian/
    └── graph.json            ← Color config for graph view

Configuration Reference

config/repos.yaml

org: Your-Org               # GitHub organization name
author: your-username        # Your GitHub username

vault_path: vault            # Output directory (default: vault, relative to project root)
                             # Use absolute path for custom location, e.g.:
                             # vault_path: "/mnt/c/Users/me/Documents/OpsidianVault"

jira_projects:               # JIRA project keys (optional)
  - PROJ
  - BACKEND

confluence_spaces:           # Confluence space keys (optional)
  - Engineering

repos:
  - name: repo-name          # Exact GitHub repo name
    description: "..."       # Shows in Repo Map of Content
    color: "#4A90D9"         # Hex color for Obsidian graph view

config/topics.yaml

topics:
  Topic Display Name:
    - "\\bkeyword\\b"       # Regex pattern (case-insensitive)
    - "\\bother-keyword\\b"  # Multiple patterns per topic OK

Patterns are matched against titles AND descriptions of PRs, JIRA issues, and Confluence pages. Use \\b for word boundaries.

.env

ATLASSIAN_EMAIL=...          # Your Atlassian login email
ATLASSIAN_TOKEN=...          # API token from id.atlassian.com
ATLASSIAN_URL=...            # e.g., https://your-company.atlassian.net
ANTHROPIC_API_KEY=...        # Optional, for LLM features

Cross-Device Sync

To access your vault from multiple devices (e.g., work laptop + personal machine), push it to a private GitHub repo and use the Obsidian Git plugin for auto-sync.

1. Set a custom vault path (optional)

If you want the vault generated outside the project directory (e.g., a shared folder on Windows from WSL), set vault_path in config/repos.yaml:

vault_path: "/mnt/c/Users/<username>/Documents/OpsidianVault"

2. Push the vault to a private repo

cd /path/to/vault
git init
git add -A
git commit -m "Initial vault sync"
gh repo create <username>/opsidian-vault --private --source=. --push

3. Clone on other devices

git clone https://github.com/<username>/opsidian-vault.git

Open the cloned folder as an Obsidian vault.

4. Install Obsidian Git plugin (optional)

Install the Obsidian Git community plugin to auto pull/push on a schedule (e.g., every 5 minutes), keeping the vault in sync without manual git commands.

Important: Always use a private repo — your vault may contain internal project data (JIRA issues, PR details, Confluence pages).

Ecosystem

opsidian_graph is part of the opsidian knowledge graph ecosystem:

opsidian_core           ← shared library (cache, categorize, template, write)
    │
    ├── opsidian_graph  ← THIS PROJECT: work knowledge graph
    ├── drive_og        ← personal knowledge graph (Google Drive)
    └── opsidian_meta   ← unified analysis vault (reads both caches)
Project What it does
opsidian_core Shared library for all graph generators
opsidian_graph Work knowledge graph (GitHub PRs, JIRA, Confluence)
drive_og Personal knowledge graph (Google Drive)
opsidian_meta Unified productivity analysis (timeline, focus reports, gap detection)

After syncing with opsidian_graph, you can run opsidian_meta to generate cross-domain productivity reports that combine your work and personal activity.

Contributing

See CONTRIBUTING.md for how to fork, develop, and submit pull requests.

Privacy

  • .env — gitignored, contains your API credentials
  • vault/ and cache/ — gitignored, contain data from private repos and company Atlassian
  • The tool code itself is safe to share publicly

Tech Stack

  • Python 3.10+, Jinja2, PyYAML
  • GitHub CLI (gh) for GitHub API access
  • atlassian-python-api + requests for JIRA and Confluence
  • python-dotenv for credential management
  • Anthropic API (optional, for LLM-powered features)

About

Generate an Obsidian knowledge graph from GitHub PR history

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors