local-sync
A CLI tool for bidirectional sync between Markdown files and Notion pages.
日本語
Features
- Push: Sync local Markdown files to Notion (create/update)
- Pull: Sync Notion pages back to local Markdown files
- Recursive directory sync (preserving hierarchy)
- Convert various Markdown elements to Notion blocks
- Headings (H1-H3, H4+ as bold paragraphs)
- Paragraphs, lists, numbered lists, todo lists
- Code blocks (60+ languages supported)
- Tables, quotes, dividers
- Inline formatting (bold, italic, code, links)
- Track page IDs via frontmatter (updates on re-sync)
Installation
go install github.com/yuri67-xk/local-sync-cli/cmd/local-sync@latest
Or build from source:
git clone https://github.com/yuri67-xk/local-sync-cli.git
cd local-sync-cli
make build
Setup
1. Create a Notion Integration
- Go to Notion Integrations
- Click "New integration"
- Enter a name and create
- Copy the "Internal Integration Secret"
2. Connect to a Page
- Open the target Notion page
- Click "..." → "Connections" → Add your integration
local-sync setup
Interactive setup for API key and Parent Page ID. Settings are saved to ~/.config/local-sync/.env.
Usage
Push: Sync Local Files to Notion
# Push a single file
local-sync push document.md
# Push a directory
local-sync push ./docs/
# Shorthand (push is default)
local-sync document.md
Pull: Sync Notion Pages to Local Files
# Pull content from Notion to update local file
local-sync pull document.md
# Skip confirmation prompt
local-sync pull --force document.md
Note: The file must have a notion_page_id in its frontmatter (added automatically after push).
Directory Sync (Push)
local-sync push ./docs/
Directory structure:
index.md → Created as parent page
- Other
.md files → Created as child pages
- Subdirectories → Processed recursively
Example:
docs/
├── index.md → Main page
├── getting-started.md → Child of main page
├── api/
│ ├── index.md → API section (child of main)
│ └── endpoints.md → Child of API section
Commands
local-sync push [options] <file|directory> # Push to Notion
local-sync pull [options] <file> # Pull from Notion
local-sync setup # Interactive configuration
local-sync <file|directory> # Same as push (backward compatible)
Push Options
-k, --api-key Notion API key (or set NOTION_API_KEY env var)
-p, --parent-page-id Parent page ID (or set NOTION_PARENT_PAGE_ID env var)
-v, --verbose Enable verbose output
--dry-run Show what would be done without making changes
Pull Options
-k, --api-key Notion API key (or set NOTION_API_KEY env var)
-v, --verbose Enable verbose output
-f, --force Skip confirmation prompt
--dry-run Show what would be done without making changes
Environment Variables
export NOTION_API_KEY="secret_xxx..."
export NOTION_PARENT_PAGE_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Or configure in ~/.config/local-sync/.env:
NOTION_API_KEY=secret_xxx...
NOTION_PARENT_PAGE_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Frontmatter
After syncing, the Notion page ID is automatically added to the Markdown file:
---
notion_page_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
title: Page Title (optional)
---
# Content
License
MIT - see LICENSE for details.