A universal synchronization tool for Personal Knowledge Management (PKM) systems. Connect Google Calendar, Gmail, and Drive to Obsidian or Logseq.
# 1. Build
go build -o pkm-sync ./cmd
# 2. Place your Google OAuth credentials
cp credentials.json ~/.config/pkm-sync/credentials.json
# 3. Create a config file and verify authentication
pkm-sync config init
pkm-sync setup
# 4. Sync everything
pkm-sync syncSee Authentication Setup for OAuth credential creation steps.
pkm-sync uses a Sources → Transformers → Sinks pipeline:
- Sources fetch items from Gmail, Google Calendar, or Google Drive
- Transformers clean content (HTML→Markdown, strip signatures, auto-tag, filter)
- Sinks write items to a PKM target (Obsidian/Logseq files) or a vector database
Gmail ──┐
Calendar ──┼──► Transformers ──► Files (Obsidian / Logseq)
Drive ──┘ └──► Vector DB (semantic search)
The primary entry point is pkm-sync sync, which runs all enabled sources through the full pipeline in one shot.
pkm-sync config init # Write default config to ~/.config/pkm-sync/config.yaml
pkm-sync config show # Print current effective config
pkm-sync config path # Show config file location
pkm-sync config edit # Open config in $EDITOR
pkm-sync config validate # Validate config fileConfig is loaded from the first location that exists:
--config-dirflag~/.config/pkm-sync/config.yaml./config.yaml(current directory)
sync:
enabled_sources: ["gmail_work", "my_drive"]
default_target: obsidian
default_output_dir: ~/vault
default_since: 7d
sources:
gmail_work:
enabled: true
type: gmail
gmail:
query: "in:inbox to:me"
include_threads: true
thread_mode: "summary" # individual | consolidated | summary
my_drive:
enabled: true
type: google_drive
drive:
folder_ids: ["<folder-id>"]
workspace_types: ["document", "spreadsheet"]
targets:
obsidian:
type: obsidian
obsidian:
default_folder: Inbox
include_frontmatter: trueSee CONFIGURATION.md for all available options.
Sync all enabled sources in one operation. An optional positional argument filters to a source type or specific source name.
pkm-sync sync # All enabled sources
pkm-sync sync gmail # All enabled Gmail sources
pkm-sync sync gmail_work # Specific source by name
pkm-sync sync drive --since 7d
pkm-sync sync --target logseq --output ~/graph
pkm-sync sync --since 7d --dry-run
pkm-sync sync gmail --dry-run --format jsonSource type aliases accepted: gmail, drive, calendar, jira, slack, snow/servicenow.
Flags: --source, --target, --output/-o, --since, --dry-run, --limit (default 1000), --format (summary|json)
Fetch a single item by URL or source-qualified identifier and write to stdout or a file with YAML frontmatter.
# URLs are auto-routed to the right source
pkm-sync fetch "https://docs.google.com/document/d/abc123/edit"
pkm-sync fetch "https://company.atlassian.net/browse/PROJ-123"
# Source-type prefix for non-URL keys
pkm-sync fetch jira/PROJ-123
pkm-sync fetch drive/FILE_ID
# Write markdown with frontmatter to a file or directory
pkm-sync fetch "https://docs.google.com/document/d/abc123/edit" --output ./docs/
pkm-sync fetch jira/PROJ-123 --output ./jira/ --format md
# Include Google Doc comments as footnotes
pkm-sync fetch "https://docs.google.com/document/d/abc123/edit" --comments
# Disambiguate when multiple sources of the same type exist
pkm-sync fetch jira/PROJ-123 --source jira_workFlags: --source, --format (txt|md|json), --output/-o, --comments
Query the vector database built by index. An optional first argument scopes the search to a source type or specific instance.
# Semantic search across all sources
pkm-sync search "kubernetes deployment issues"
# Gmail full-text search (uses archive.db when available, falls back to vector)
pkm-sync search gmail "meeting with alice"
# Scope to a source type or specific instance
pkm-sync search slack "deploy failed"
pkm-sync search gmail/work_gmail "rosa boundary"
pkm-sync search jira/jira_work "auth error"
pkm-sync search "project status" --format json --limit 5Flags: --limit (default 10), --source-name, --source-type, --format (text|json), --min-score
Index items into a local SQLite vector database (requires Ollama or compatible embedding provider).
pkm-sync index --source gmail_work --since 30d
pkm-sync index --since 7d --limit 500
pkm-sync index --reindex # Re-index all itemsFlags: --source, --since (default 30d), --limit (default 1000), --reindex, --delay (ms between embeddings), --max-content-length
Standalone command; not part of the sync pipeline. Displays calendar events as a table or JSON.
pkm-sync calendar # Current week to today
pkm-sync calendar --start today
pkm-sync calendar --start 2025-01-01 --end 2025-01-31
pkm-sync calendar --format json
pkm-sync calendar --include-details # Attendees, meeting URLs
pkm-sync calendar --export-docs --export-dir ./docs # Export attached DocsFlags: --start/-s, --end/-e, --format/-f (table|json), --include-details, --export-docs, --export-dir, --max-results/-n
Connects to a source's API and presents a multi-select TUI to pick what to sync.
pkm-sync configure # Pick from configured sources
pkm-sync configure slack_redhat # Configure a specific source
pkm-sync configure --type slack # Create a new Slack source interactivelySupports Slack (channels, channel groups, DMs), Gmail (labels), Google Drive (folders), Jira (projects), and Google Calendar (calendars). Shows recent-item previews alongside each option and displays a diff of added/removed items before saving.
gmail, drive, jira, slack, and servicenow are still available but deprecated. Use pkm-sync sync <type> instead.
The slack and servicenow commands retain their auth subcommands for first-time authentication:
pkm-sync slack auth --workspace https://myorg.slack.com
pkm-sync slack channels # List channels + starred
pkm-sync servicenow auth --instance https://mycompany.service-now.compkm-sync setupTests connectivity to Google Calendar, Drive, and Gmail. Provides clear error messages if anything is misconfigured.
--credentials/-c Path to credentials.json
--config-dir Custom config directory
--debug/-d Enable debug logging
--start/-s Global start date (used by calendar)
--end/-e Global end date (used by calendar)
| Source | Status |
|---|---|
| Gmail | Fully implemented — multi-instance, thread grouping |
| Google Calendar | Fully implemented |
| Google Drive | Fully implemented — Docs, Sheets, Slides |
| Slack | Fully implemented — bearer token auth, channel groups, threads, DMs |
| Jira | Fully implemented — JQL queries, comments, bearer token auth |
| ServiceNow | Fully implemented — RITMs, incidents, bearer token auth |
| Target | Format |
|---|---|
| Obsidian | YAML frontmatter, hierarchical folders, standard Markdown |
| Logseq | Property blocks, flat structure, [[date]] links, #tags |
- Go 1.24.4 or later
- A Google Cloud project with API access
- Go to the Google Cloud Console
- Create or select a project
- Enable Google Calendar API, Google Drive API, and Gmail API
- Configure the OAuth consent screen (Internal or External)
- Create OAuth 2.0 Client ID credentials → Desktop application
- Add
http://127.0.0.1:*to authorized redirect URIs - Download
credentials.json
Default locations (checked in order):
~/.config/pkm-sync/credentials.json~/Library/Application Support/pkm-sync/credentials.json(macOS)%APPDATA%\pkm-sync\credentials.json(Windows)./credentials.json(current directory)
Or use a flag: pkm-sync --credentials /path/to/credentials.json setup
pkm-sync setupThe app opens your browser automatically for OAuth consent. The token is saved in the same directory as credentials.json. If the automatic flow fails, it falls back to manual copy/paste mode.
- Verify Calendar, Drive, and Gmail APIs are enabled in Google Cloud Console
- Check that the OAuth consent screen includes the required scopes
- Delete
token.jsonand re-authenticate
- Ensure the file is named exactly
credentials.json(notclient_secret_*.json) - Run
pkm-sync setupto see which paths are being checked
- Your token may have expired or been revoked
- Delete
token.jsonfrom your config directory and runpkm-sync setupagain
Run pkm-sync setup to diagnose authentication issues.
- CONFIGURATION.md — Complete configuration reference
- CONTRIBUTING.md — Development workflow