Notion Sync
Bi-directional sync between markdown files and Notion pages, plus database management utilities for research tracking and project management.
Upgrading
From v2.0: Replace --token "ntn_..." with --token-file, --token-stdin, or NOTION_API_KEY env var. Bare --token is no longer accepted (credentials should never appear in process listings).
From v1.x: See v2.0 changelog for migration details.
Requirements
- - Node.js v18 or later
- A Notion integration token (starts with
ntn_ or secret_)
Setup
- 1. Go to https://www.notion.so/my-integrations
- Create a new integration (or use an existing one)
- Copy the "Internal Integration Token"
- Pass the token using one of these methods (priority order used by scripts):
Option A — Token file (recommended):
CODEBLOCK0
Option B — Stdin pipe:
CODEBLOCK1
Option C — Environment variable:
CODEBLOCK2
Auto default: If ~/.notion-token exists, scripts use it automatically even without --token-file.
- 5. Share your Notion pages/databases with the integration:
- Open the page/database in Notion
- Click "Share" → "Invite"
- Select your integration
JSON Output Mode
All scripts support a global --json flag.
- - Suppresses progress logs written to stderr
- Keeps stdout machine-readable for automation
- Errors are emitted as JSON: INLINECODE10
Example:
CODEBLOCK3
Path Safety Mode
Scripts that read/write local files are restricted to the current working directory by default.
- - Prevents accidental reads/writes outside the intended workspace
- Applies to:
md-to-notion.js, add-to-database.js, notion-to-md.js, INLINECODE14 - Override intentionally with INLINECODE15
Examples:
CODEBLOCK4
Core Operations
1. Search Pages and Databases
Search across your Notion workspace by title or content.
CODEBLOCK5
Examples:
CODEBLOCK6
Output:
CODEBLOCK7
2. Query Databases with Filters
Query database contents with advanced filters and sorting.
CODEBLOCK8
Examples:
CODEBLOCK9
Common filter patterns:
- - Select equals: INLINECODE16
- Multi-select contains: INLINECODE17
- Date after: INLINECODE18
- Checkbox is true: INLINECODE19
- Number greater than: INLINECODE20
3. Update Page Properties
Update properties for database pages (status, tags, dates, etc.).
CODEBLOCK10
Supported types: select, multiselect, checkbox, number, url, email, date, richtext
Examples:
CODEBLOCK11
4. Batch Update
Batch update a single property across multiple pages in one command.
Mode 1 — Query + Update:
CODEBLOCK12
Example:
CODEBLOCK13
Mode 2 — Page IDs from stdin:
CODEBLOCK14
Features:
- -
--dry-run: prints pages that would be updated (with current property value) without writing - INLINECODE22 : max pages to process (default
100) - Pagination in query mode (
has_more/next_cursor) up to limit - Rate-limit friendly updates (300ms between page updates)
- Progress and summary on stderr, JSON result array on stdout
5. Markdown → Notion Sync
Push markdown content to Notion with full formatting support.
CODEBLOCK15
Example:
CODEBLOCK16
Supported formatting:
- - Headings (H1-H3)
- Bold/italic text
- Links
- Bullet lists
- Code blocks with syntax highlighting
- Horizontal dividers
- Paragraphs
Features:
- - Batched uploads (100 blocks per request)
- Automatic rate limiting (350ms between batches)
- Rich text is automatically chunked to Notion's 2000-character limit (including bold/italic/link spans)
- Returns Notion page URL and ID
Output:
CODEBLOCK17
6. Notion → Markdown Sync
Pull Notion page content and convert to markdown.
CODEBLOCK18
Example:
CODEBLOCK19
Features:
- - Converts Notion blocks to markdown
- Preserves formatting (headings, lists, code, quotes)
- Optional file output (writes to file or stdout)
7. Change Detection & Monitoring
Monitor Notion pages for edits and compare with local markdown files.
CODEBLOCK20
Example:
CODEBLOCK21
State tracking: By default maintains state in memory/notion-watch-state.json (relative to current working directory). You can override with --state-file <path> (supports ~ expansion):
CODEBLOCK22
Default state schema:
CODEBLOCK23
Output:
CODEBLOCK24
Automated monitoring: Schedule periodic checks using cron, CI pipelines, or any task scheduler:
CODEBLOCK25
The script outputs JSON — pipe it to any notification system when hasChanges is true.
8. Database Management
Add Markdown Content to Database
Add a markdown file as a new page in any Notion database.
CODEBLOCK26
Examples:
CODEBLOCK27
Features:
- - Creates database page with title property
- Converts markdown to Notion blocks (headings, paragraphs, dividers)
- Handles large files with batched uploads
- Returns page URL for immediate access
Note: Additional properties (Type, Tags, Status, etc.) must be set manually in Notion UI after creation.
Inspect Database Schema
CODEBLOCK28
Example output:
CODEBLOCK29
Use when:
- - Setting up new database integrations
- Debugging property names/types
- Understanding database structure
Archive Pages
CODEBLOCK30
Note: This archives the page (sets archived: true), not permanent deletion.
Common Workflows
Collaborative Editing Workflow
- 1. Push local draft to Notion:
CODEBLOCK31
- 2. User edits in Notion (anywhere, any device)
- 3. Monitor for changes:
CODEBLOCK32
- 4. Pull updates back:
CODEBLOCK33
- 5. Repeat as needed (update same page, don't create v2/v3/etc.)
Research Output Tracking
- 1. Generate research locally (e.g., via sub-agent)
- 2. Sync to Notion database:
CODEBLOCK34
- 3. User adds metadata in Notion UI (Type, Tags, Status properties)
- 4. Access from anywhere via Notion web/mobile
Page ID Extraction
From Notion URL: INLINECODE32
Extract: abc123-example-page-id-456def (last part after title)
Or use the 32-char format: abc123examplepageid456def (hyphens optional)
Limitations
- - Property updates: Database properties (Type, Tags, Status) must be added manually in Notion UI after page creation. API property updates can be temperamental with inline databases.
- Block limits: Very large markdown files (>1000 blocks) may take several minutes to sync due to rate limiting.
- Formatting: Some complex markdown (tables, nested lists >3 levels) may not convert perfectly.
Troubleshooting
"Could not find page" error:
- - Ensure page/database is shared with your integration
- Check page ID format (32 chars, alphanumeric + hyphens)
"Module not found" error:
- - Scripts use built-in Node.js https module (no npm install needed)
- Ensure running from the skill's directory (where scripts/ lives)
Rate limiting:
- - Notion API has rate limits (~3 requests/second)
- Scripts handle this automatically with 350ms delays between batches
Resources
scripts/
Core Sync:
- - md-to-notion.js - Markdown → Notion sync with full formatting
- notion-to-md.js - Notion → Markdown conversion
- watch-notion.js - Change detection and monitoring
Search & Query:
- - search-notion.js - Search pages and databases by query
- query-database.js - Query databases with filters and sorting
- update-page-properties.js - Update database page properties
- batch-update.js - Batch update one property across many pages (query or stdin IDs)
Database Management:
- - add-to-database.js - Add markdown files as database pages
- get-database-schema.js - Inspect database structure
- delete-notion-page.js - Archive pages
Utilities:
- - notion-utils.js - Shared utilities (error handling, property formatting, API requests)
All scripts use only built-in Node.js modules (https, fs) - no external dependencies required.
references/
- - database-patterns.md - Common database schemas and property patterns
Notion 同步
在 Markdown 文件和 Notion 页面之间进行双向同步,并提供用于研究跟踪和项目管理的数据库管理工具。
升级说明
从 v2.0 升级: 将 --token ntn... 替换为 --token-file、--token-stdin 或 NOTIONAPI_KEY 环境变量。不再接受裸 --token 参数(凭证不应出现在进程列表中)。
从 v1.x 升级: 请参阅 v2.0 更新日志了解迁移详情。
系统要求
- - Node.js v18 或更高版本
- Notion 集成令牌(以 ntn 或 secret 开头)
设置步骤
- 1. 访问 https://www.notion.so/my-integrations
- 创建新集成(或使用现有集成)
- 复制内部集成令牌
- 使用以下方法之一传递令牌(脚本使用的优先级顺序):
选项 A — 令牌文件(推荐):
bash
echo ntnyourtoken > ~/.notion-token && chmod 600 ~/.notion-token
node scripts/search-notion.js query --token-file ~/.notion-token
选项 B — 标准输入管道:
bash
echo $NOTIONAPIKEY | node scripts/search-notion.js query --token-stdin
选项 C — 环境变量:
bash
export NOTIONAPIKEY=ntnyourtoken
node scripts/search-notion.js query
自动默认: 如果 ~/.notion-token 存在,即使不指定 --token-file,脚本也会自动使用它。
- 5. 与集成共享您的 Notion 页面/数据库:
- 在 Notion 中打开页面/数据库
- 点击共享→邀请
- 选择您的集成
JSON 输出模式
所有脚本都支持全局 --json 标志。
- - 抑制写入 stderr 的进度日志
- 保持 stdout 机器可读,便于自动化
- 错误以 JSON 格式输出:{ error: ... }
示例:
bash
node scripts/query-database.js --limit 5 --json
路径安全模式
默认情况下,读写本地文件的脚本仅限于当前工作目录。
- - 防止意外读取/写入预期工作区之外的文件
- 适用于:md-to-notion.js、add-to-database.js、notion-to-md.js、watch-notion.js
- 可通过 --allow-unsafe-paths 有意覆盖
示例:
bash
默认(安全):路径必须在当前工作区内
node scripts/md-to-notion.js docs/draft.md
Draft
有意覆盖(工作区外)
node scripts/notion-to-md.js ~/Downloads/export.md --allow-unsafe-paths
核心操作
1. 搜索页面和数据库
按标题或内容搜索 Notion 工作区。
bash
node scripts/search-notion.js [--filter page|database] [--limit 10] [--json]
示例:
bash
搜索与通讯稿相关的页面
node scripts/search-notion.js newsletter
仅查找数据库
node scripts/search-notion.js research --filter database
限制结果数量
node scripts/search-notion.js AI --limit 5
输出:
json
[
{
id: page-id-here,
object: page,
title: Newsletter Draft,
url: https://notion.so/...,
lastEdited: 2026-02-01T09:00:00.000Z
}
]
2. 使用筛选条件查询数据库
使用高级筛选和排序功能查询数据库内容。
bash
node scripts/query-database.js [--filter ] [--sort ] [--limit 10] [--json]
示例:
bash
获取所有项目
node scripts/query-database.js xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
按状态 = 完成 筛选
node scripts/query-database.js \
--filter {property: Status, select: {equals: Complete}}
按包含AI的标签筛选
node scripts/query-database.js \
--filter {property: Tags, multi_select: {contains: AI}}
按日期降序排序
node scripts/query-database.js \
--sort [{property: Date, direction: descending}]
组合筛选和排序
node scripts/query-database.js \
--filter {property: Status, select: {equals: Complete}} \
--sort [{property: Date, direction: descending}]
常用筛选模式:
- - 选择等于:{property: Status, select: {equals: Done}}
- 多选包含:{property: Tags, multiselect: {contains: AI}}
- 日期之后:{property: Date, date: {after: 2024-01-01}}
- 复选框为真:{property: Published, checkbox: {equals: true}}
- 数字大于:{property: Count, number: {greaterthan: 100}}
3. 更新页面属性
更新数据库页面的属性(状态、标签、日期等)。
bash
node scripts/update-page-properties.js [--type ] [--json]
支持的类型: select、multiselect、checkbox、number、url、email、date、richtext
示例:
bash
设置状态
node scripts/update-page-properties.js Status Complete --type select
添加多个标签
node scripts/update-page-properties.js Tags AI,Leadership,Research --type multi_select
设置复选框
node scripts/update-page-properties.js Published true --type checkbox
设置日期
node scripts/update-page-properties.js Publish Date 2024-02-01 --type date
设置 URL
node scripts/update-page-properties.js Source URL https://example.com --type url
设置数字
node scripts/update-page-properties.js Word Count 1200 --type number
4. 批量更新
在一个命令中跨多个页面批量更新单个属性。
模式 1 — 查询 + 更新:
bash
node scripts/batch-update.js --filter [--type select] [--dry-run] [--limit 100]
示例:
bash
node scripts/batch-update.js Status Review \
--filter {property:Status,select:{equals:Draft}} \
--type select
模式 2 — 从标准输入读取页面 ID:
bash
echo page-id-1\npage-id-2\npage-id-3 | \
node scripts/batch-update.js --stdin [--type select] [--dry-run]
功能特性:
- - --dry-run:打印将要更新的页面(显示当前属性值)但不实际写入
- --limit :最大处理页面数(默认 100)
- 查询模式下的分页(hasmore/nextcursor)直到达到限制
- 速率限制友好的更新(页面更新间隔 300ms)
- 进度和摘要输出到 stderr,JSON 结果数组输出到 stdout
5. Markdown → Notion 同步
将 Markdown 内容推送到 Notion,支持完整格式。
bash
node scripts/md-to-notion.js \
\
\
[--json] [--allow-unsafe-paths]
示例:
bash
node scripts/md-to-notion.js \
projects/newsletter-draft.md \
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
Newsletter Draft - Feb 2026
支持的格式:
- - 标题(H1-H3)
- 粗体/斜体文本
- 链接
- 无序列表
- 带语法高亮的代码块
- 水平分隔线
-