Vibe Notion
Interact with Notion using the unofficial private API - pages, databases, blocks, search, users, comments
Description
name: vibe-notion description: Interact with Notion using the unofficial private API - pages, databases, blocks, search, users, comments version: 0.9.0 allowed-tools: Bash(vibe-notion:*) metadata: openclaw: requires: bins: - vibe-notion install: - kind: node package: vibe-notion bins: [vibe-notion]
Vibe Notion
A TypeScript CLI tool that enables AI agents and humans to interact with Notion workspaces through the unofficial private API. Supports full CRUD operations on pages, databases, blocks, search, and user management.
Note: This skill uses Notion's internal/private API (
/api/v3/), which is separate from the official public API. For official API access, usevibe-notionbot.
Which CLI to Use
This package ships two CLIs. Pick the right one based on your situation:
vibe-notion (this CLI) |
vibe-notionbot |
|
|---|---|---|
| API | Unofficial private API | Official Notion API |
| Auth | token_v2 auto-extracted from Notion desktop app |
NOTION_TOKEN env var (Integration token) |
| Identity | Acts as the user | Acts as a bot |
| Setup | Zero — credentials extracted automatically | Manual — create Integration at notion.so/my-integrations |
| Database rows | add-row, update-row |
Create via page create --database |
| View management | view-get, view-update, view-list, view-add, view-delete |
Not supported |
| Workspace listing | Supported | Not supported |
| Stability | Private API — may break on Notion changes | Official versioned API — stable |
Decision flow:
- If the Notion desktop app is installed → use
vibe-notion(this CLI) - If
NOTION_TOKENis set but no desktop app → usevibe-notionbot - If both are available → prefer
vibe-notion(broader capabilities, zero setup) - If neither → ask the user to set up one of the two
Important: CLI Only
Never call Notion's internal API directly. Always use the vibe-notion CLI commands described in this skill. Do not make raw HTTP requests to notion.so/api/v3/ or use any Notion client library. Direct API calls risk exposing credentials and may trigger Notion's abuse detection, getting the user's account blocked.
If a feature you need is not supported by vibe-notion, let the user know and offer to file a feature request at devxoul/vibe-notion on their behalf. Before submitting, strip out any real user data — IDs, names, emails, tokens, page content, or anything else that could identify the user or their workspace. Use generic placeholders instead and keep the issue focused on describing the missing capability.
Important: Never Write Scripts
Never write scripts (Python, TypeScript, Bash, etc.) to automate Notion operations. The batch command already handles bulk operations of any size. Writing a script to loop through API calls is always wrong — use batch with --file instead.
This applies even when:
- You need to create 100+ rows
- You need cross-references between newly created rows (use multi-pass batch — see Bulk Operations Strategy)
- The operation feels "too big" for a single command
If you catch yourself thinking "I should write a script for this," stop and use batch.
Quick Start
# 1. Find your workspace ID
vibe-notion workspace list --pretty
# 2. Search for a page
vibe-notion search "Roadmap" --workspace-id <workspace-id> --pretty
# 3. Get page content
vibe-notion page get <page-id> --workspace-id <workspace-id> --pretty
# 4. Query a database
vibe-notion database query <collection-id> --workspace-id <workspace-id> --pretty
Credentials are auto-extracted from the Notion desktop app on first use. No manual setup needed.
Important:
--workspace-idis required for ALL commands that operate within a specific workspace. Usevibe-notion workspace listto find your workspace ID.
Authentication
Credentials (token_v2) are auto-extracted from the Notion desktop app when you run any command. No API keys, OAuth, or manual extraction needed.
On macOS, your system may prompt for Keychain access on first use — this is normal and required to decrypt the cookie.
The extracted token_v2 is stored at ~/.config/vibe-notion/credentials.json with 0600 permissions.
Memory
The agent maintains a ~/.config/vibe-notion/MEMORY.md file as persistent memory across sessions. This is agent-managed — the CLI does not read or write this file. Use the Read and Write tools to manage your memory file.
Reading Memory
At the start of every task, read ~/.config/vibe-notion/MEMORY.md using the Read tool to load any previously discovered workspace IDs, page IDs, database IDs, and user preferences.
- If the file doesn't exist yet, that's fine — proceed without it and create it when you first have useful information to store.
- If the file can't be read (permissions, missing directory), proceed without memory — don't error out.
Writing Memory
After discovering useful information, update ~/.config/vibe-notion/MEMORY.md using the Write tool. Write triggers include:
- After discovering workspace IDs (from
workspace list) - After discovering useful page IDs, database IDs, collection IDs (from
search,page list,page get,database list, etc.) - After the user gives you an alias or preference ("call this the Tasks DB", "my main workspace is X")
- After discovering page/database structure (parent-child relationships, what databases live under which pages)
When writing, include the complete file content — the Write tool overwrites the entire file.
What to Store
- Workspace IDs with names
- Page IDs with titles and parent context
- Database/collection IDs with titles and parent context
- User-given aliases ("Tasks DB", "Main workspace")
- Commonly used view IDs
- Parent-child relationships (which databases are under which pages)
- Any user preference expressed during interaction
What NOT to Store
Never store token_v2, credentials, API keys, or any sensitive data. Never store full page content (just IDs and titles). Never store block-level IDs unless they're persistent references (like database blocks).
Handling Stale Data
If a memorized ID returns an error (page not found, access denied), remove it from MEMORY.md. Don't blindly trust memorized data — verify when something seems off. Prefer re-searching over using a memorized ID that might be stale.
Format / Example
Here's a concrete example of how to structure your MEMORY.md:
# Vibe Notion Memory
## Workspaces
- `abc123-...` — Acme Corp (default)
## Pages (Acme Corp)
- `page-id-1` — Product Roadmap (top-level)
- `page-id-2` — Q1 Planning (under Product Roadmap)
## Databases (Acme Corp)
- `coll-id-1` — Tasks (under Product Roadmap, views: `view-1`)
- `coll-id-2` — Contacts (top-level)
## Aliases
- "roadmap" → `page-id-1` (Product Roadmap)
- "tasks" → `coll-id-1` (Tasks database)
## Notes
- User prefers --pretty output for search results
- Main workspace is "Acme Corp"
Memory lets you skip repeated
searchandworkspace listcalls. When you already know an ID from a previous session, use it directly.
Commands
Auth Commands
vibe-notion auth status # Check authentication status
vibe-notion auth logout # Remove stored token_v2
vibe-notion auth extract # Manually re-extract token_v2 (for troubleshooting)
Page Commands
# List pages in a space (top-level only)
vibe-notion page list --workspace-id <workspace_id> --pretty
vibe-notion page list --workspace-id <workspace_id> --depth 2 --pretty
# Get a page and all its content blocks
vibe-notion page get <page_id> --workspace-id <workspace_id> --pretty
vibe-notion page get <page_id> --workspace-id <workspace_id> --limit 50
vibe-notion page get <page_id> --workspace-id <workspace_id> --backlinks --pretty
# Create a new page (--parent is optional; omit to create at workspace root)
vibe-notion page create --workspace-id <workspace_id> --parent <parent_id> --title "My Page" --pretty
vibe-notion page create --workspace-id <workspace_id> --title "New Root Page" --pretty
# Create a page with markdown content
vibe-notion page create --workspace-id <workspace_id> --parent <parent_id> --title "My Doc" --markdown '# Hello\n\nThis is **bold** text.'
# Create a page with markdown from a file
vibe-notion page create --workspace-id <workspace_id> --parent <parent_id> --title "My Doc" --markdown-file ./content.md
# Create a page with markdown containing local images (auto-uploaded to Notion)
vibe-notion page create --workspace-id <workspace_id> --parent <parent_id> --title "My Doc" --markdown-file ./doc-with-images.md
# Replace all content on a page with new markdown
vibe-notion page update <page_id> --workspace-id <workspace_id> --replace-content --markdown '# New Content'
vibe-notion page update <page_id> --workspace-id <workspace_id> --replace-content --markdown-file ./updated.md
# Update page title or icon
vibe-notion page update <page_id> --workspace-id <workspace_id> --title "New Title" --pretty
vibe-notion page update <page_id> --workspace-id <workspace_id> --icon "🚀" --pretty
# Archive a page
vibe-notion page archive <page_id> --workspace-id <workspace_id> --pretty
Database Commands
# Get database schema
vibe-notion database get <database_id> --workspace-id <workspace_id> --pretty
# Query a database (auto-resolves default view)
vibe-notion database query <database_id> --workspace-id <workspace_id> --pretty
vibe-notion database query <database_id> --workspace-id <workspace_id> --limit 10 --pretty
vibe-notion database query <database_id> --workspace-id <workspace_id> --view-id <view_id> --pretty
vibe-notion database query <database_id> --workspace-id <workspace_id> --search-query "keyword" --pretty
vibe-notion database query <database_id> --workspace-id <workspace_id> --timezone "America/New_York" --pretty
# Query with filter and sort (uses property IDs from database get schema)
vibe-notion database query <database_id> --workspace-id <workspace_id> --filter '<filter_json>' --pretty
vibe-notion database query <database_id> --workspace-id <workspace_id> --sort '<sort_json>' --pretty
# List all databases in workspace
vibe-notion database list --workspace-id <workspace_id> --pretty
# Create a database
vibe-notion database create --workspace-id <workspace_id> --parent <page_id> --title "Tasks" --pretty
vibe-notion database create --workspace-id <workspace_id> --parent <page_id> --title "Tasks" --properties '{"status":{"name":"Status","type":"select"}}' --pretty
# Update database title or schema
vibe-notion database update <database_id> --workspace-id <workspace_id> --title "New Name" --pretty
# Add a row to a database
vibe-notion database add-row <database_id> --workspace-id <workspace_id> --title "Row title" --pretty
vibe-notion database add-row <database_id> --workspace-id <workspace_id> --title "Row title" --properties '{"Status":"In Progress","Due":{"start":"2025-03-01"}}' --pretty
# Add row with date range
vibe-notion database add-row <database_id> --workspace-id <workspace_id> --title "Event" --properties '{"Due":{"start":"2026-01-01","end":"2026-01-15"}}' --pretty
# Update properties on an existing database row (row_id from database query)
vibe-notion database update-row <row_id> --workspace-id <workspace_id> --properties '{"Status":"Done"}' --pretty
vibe-notion database update-row <row_id> --workspace-id <workspace_id> --properties '{"Priority":"High","Tags":["backend","infra"]}' --pretty
vibe-notion database update-row <row_id> --workspace-id <workspace_id> --properties '{"Due":{"start":"2026-06-01"},"Status":"In Progress"}' --pretty
vibe-notion database update-row <row_id> --workspace-id <workspace_id> --properties '{"Due":{"start":"2026-01-01","end":"2026-01-15"}}' --pretty
vibe-notion database update-row <row_id> --workspace-id <workspace_id> --properties '{"Related":["<target_row_id>"]}' --pretty
# Delete a property from a database (cannot delete the title property)
vibe-notion database delete-property <database_id> --workspace-id <workspace_id> --property "Status" --pretty
# Get view configuration and property visibility
vibe-notion database view-get <view_id> --workspace-id <workspace_id> --pretty
# Show or hide properties on a view (comma-separated names)
vibe-notion database view-update <view_id> --workspace-id <workspace_id> --show "ID,Due" --pretty
vibe-notion database view-update <view_id> --workspace-id <workspace_id> --hide "Assignee" --pretty
vibe-notion database view-update <view_id> --workspace-id <workspace_id> --show "Status" --hide "Due" --pretty
# Reorder columns (comma-separated names in desired order; unmentioned columns appended)
vibe-notion database view-update <view_id> --workspace-id <workspace_id> --reorder "Name,Status,Priority,Date" --pretty
vibe-notion database view-update <view_id> --workspace-id <workspace_id> --reorder "Name,Status" --show "Status" --pretty
# Resize columns (JSON mapping property names to pixel widths)
vibe-notion database view-update <view_id> --workspace-id <workspace_id> --resize '{"Name":200,"Status":150}' --pretty
# List all views for a database
vibe-notion database view-list <database_id> --workspace-id <workspace_id> --pretty
# Add a new view to a database (default type: table)
vibe-notion database view-add <database_id> --workspace-id <workspace_id> --pretty
vibe-notion database view-add <database_id> --workspace-id <workspace_id> --type board --name "Board View" --pretty
# Delete a view from a database (cannot delete the last view)
vibe-notion database view-delete <view_id> --workspace-id <workspace_id> --pretty
Block Commands
# Get a specific block
vibe-notion block get <block_id> --workspace-id <workspace_id> --pretty
vibe-notion block get <block_id> --workspace-id <workspace_id> --backlinks --pretty
# List child blocks
vibe-notion block children <block_id> --workspace-id <workspace_id> --pretty
vibe-notion block children <block_id> --workspace-id <workspace_id> --limit 50 --pretty
vibe-notion block children <block_id> --workspace-id <workspace_id> --start-cursor '<next_cursor_json>' --pretty
# Append child blocks
vibe-notion block append <parent_id> --workspace-id <workspace_id> --content '[{"type":"text","properties":{"title":[["Hello world"]]}}]' --pretty
# Append markdown content as blocks
vibe-notion block append <parent_id> --workspace-id <workspace_id> --markdown '# Hello\n\nThis is **bold** text.'
# Append markdown from a file
vibe-notion block append <parent_id> --workspace-id <workspace_id> --markdown-file ./content.md
# Append markdown with local images (auto-uploaded to Notion)
vibe-notion block append <parent_id> --workspace-id <workspace_id> --markdown-file ./doc-with-images.md
# Append nested markdown (indented lists become nested children blocks)
vibe-notion block append <parent_id> --workspace-id <workspace_id> --markdown '- Parent item\n - Child item\n - Grandchild item'
# Append blocks after a specific block (positional insertion)
vibe-notion block append <parent_id> --workspace-id <workspace_id> --after <block_id> --markdown '# Inserted after specific block'
vibe-notion block append <parent_id> --workspace-id <workspace_id> --after <block_id> --content '[{"type":"text","properties":{"title":[["Inserted after"]]}}]'
# Append blocks before a specific block
vibe-notion block append <parent_id> --workspace-id <workspace_id> --before <block_id> --markdown '# Inserted before specific block'
# Update a block
vibe-notion block update <block_id> --workspace-id <workspace_id> --content '{"properties":{"title":[["Updated text"]]}}' --pretty
# Delete a block
vibe-notion block delete <block_id> --workspace-id <workspace_id> --pretty
# Upload a file as a block (image or file block)
vibe-notion block upload <parent_id> --workspace-id <workspace_id> --file ./image.png --pretty
vibe-notion block upload <parent_id> --workspace-id <workspace_id> --file ./document.pdf --pretty
vibe-notion block upload <parent_id> --workspace-id <workspace_id> --file ./image.png --after <block_id> --pretty
vibe-notion block upload <parent_id> --workspace-id <workspace_id> --file ./image.png --before <block_id> --pretty
# Move a block to a new position
vibe-notion block move <block_id> --workspace-id <workspace_id> --parent <parent_id> --pretty
vibe-notion block move <block_id> --workspace-id <workspace_id> --parent <parent_id> --after <sibling_id> --pretty
vibe-notion block move <block_id> --workspace-id <workspace_id> --parent <parent_id> --before <sibling_id> --pretty
Block Types Reference
The internal API uses a specific block format. Here are all supported types:
Headings
{"type": "header", "properties": {"title": [["Heading 1"]]}}
{"type": "sub_header", "properties": {"title": [["Heading 2"]]}}
{"type": "sub_sub_header", "properties": {"title": [["Heading 3"]]}}
Text
{"type": "text", "properties": {"title": [["Plain text paragraph"]]}}
Lists
{"type": "bulleted_list", "properties": {"title": [["Bullet item"]]}}
{"type": "numbered_list", "properties": {"title": [["Numbered item"]]}}
Nested Children
List blocks support nested children via the children property:
{"type": "bulleted_list", "properties": {"title": [["Parent"]]}, "children": [{"type": "bulleted_list", "properties": {"title": [["Child"]]}}]}
To-Do / Checkbox
{"type": "to_do", "properties": {"title": [["Task item"]], "checked": [["Yes"]]}}
{"type": "to_do", "properties": {"title": [["Unchecked task"]], "checked": [["No"]]}}
Code Block
{"type": "code", "properties": {"title": [["console.log('hello')"]], "language": [["javascript"]]}}
Quote
{"type": "quote", "properties": {"title": [["Quoted text"]]}}
Divider
{"type": "divider"}
Rich Text Formatting
Rich text uses nested arrays with formatting codes:
| Format | Syntax | Example |
|---|---|---|
| Plain | [["text"]] |
[["Hello"]] |
| Bold | ["text", [["b"]]] |
["Hello", [["b"]]] |
| Italic | ["text", [["i"]]] |
["Hello", [["i"]]] |
| Strikethrough | ["text", [["s"]]] |
["Hello", [["s"]]] |
| Inline code | ["text", [["c"]]] |
["Hello", [["c"]]] |
| Link | ["text", [["a", "url"]]] |
["Click", [["a", "https://example.com"]]] |
| Bold + Italic | ["text", [["b"], ["i"]]] |
["Hello", [["b"], ["i"]]] |
Multiple segments: [["plain "], ["bold", [["b"]]], [" more plain"]]
Comment Commands
# List comments on a page
vibe-notion comment list --page <page_id> --workspace-id <workspace_id> --pretty
# List inline comments on a specific block
vibe-notion comment list --page <page_id> --block <block_id> --workspace-id <workspace_id> --pretty
# Create a comment on a page (starts a new discussion)
vibe-notion comment create "This is a comment" --page <page_id> --workspace-id <workspace_id> --pretty
# Reply to an existing discussion thread
vibe-notion comment create "Replying to thread" --discussion <discussion_id> --workspace-id <workspace_id> --pretty
# Get a specific comment by ID
vibe-notion comment get <comment_id> --workspace-id <workspace_id> --pretty
Batch Operations
Run multiple write operations in a single CLI call. Use this instead of calling the CLI repeatedly when you need to create, update, or delete multiple things at once. Saves tokens and reduces round-trips.
# Inline JSON
vibe-notion batch --workspace-id <workspace_id> '<operations_json>'
# From file (for large payloads)
vibe-notion batch --workspace-id <workspace_id> --file ./operations.json '[]'
Supported actions (14 total):
| Action | Description |
|---|---|
page.create |
Create a page |
page.update |
Update page title, icon, or content |
page.archive |
Archive a page |
block.append |
Append blocks to a parent |
block.update |
Update a block |
block.delete |
Delete a block |
block.move |
Move a block to a new position |
comment.create |
Create a comment |
database.create |
Create a database |
database.update |
Update database title or schema |
database.delete-property |
Delete a database property |
database.add-row |
Add a row to a database |
database.update-row |
Update properties on a database row |
block.upload |
Upload a file as an image or file block |
Operation format: Each operation is an object with action plus the same fields you'd pass to the individual command handler. Example with mixed actions:
[
{"action": "database.add-row", "database_id": "<db_id>", "title": "Task A", "properties": {"Status": "To Do"}},
{"action": "database.add-row", "database_id": "<db_id>", "title": "Task B", "properties": {"Status": "In Progress"}},
{"action": "page.update", "page_id": "<page_id>", "title": "Updated Summary"}
]
Output format:
{
"results": [
{"index": 0, "action": "database.add-row", "success": true, "data": {"id": "row-uuid-1", "...": "..."}},
{"index": 1, "action": "database.add-row", "success": true, "data": {"id": "row-uuid-2", "...": "..."}},
{"index": 2, "action": "page.update", "success": true, "data": {"id": "page-uuid", "...": "..."}}
],
"total": 3,
"succeeded": 3,
"failed": 0
}
Fail-fast behavior: Operations run sequentially. If any operation fails, execution stops immediately. The output will contain results for all completed operations plus the failed one. The process exits with code 1 on failure, 0 on success.
{
"results": [
{"index": 0, "action": "database.add-row", "success": true, "data": {"...": "..."}},
{"index": 1, "action": "page.update", "success": false, "error": "Page not found"}
],
"total": 3,
"succeeded": 1,
"failed": 1
}
Bulk Operations Strategy
For large operations (tens or hundreds of items), use --file to avoid shell argument limits and keep things manageable.
Step 1: Write the operations JSON to a file, then run batch with --file:
# Write operations to a file (using your Write tool), then:
vibe-notion batch --workspace-id <workspace_id> --file ./operations.json '[]'
Multi-pass pattern — when new rows need to reference each other (e.g., relation properties linking row A → row B, where both are new):
- Pass 1 — Create all rows (without cross-references): Write a batch JSON file with all
database.add-rowoperations, omitting relation properties that point to other new rows. Run it. Collect the returned IDs from the output. - Pass 2 — Set cross-references: Write a second batch JSON file with
database.update-rowoperations that set the relation properties using the IDs from Pass 1. Run it.
Pass 1: Create rows A, B, C (no cross-refs) → get IDs for A, B, C
Pass 2: Update A.predecessor=B, C.related=A (using real IDs from Pass 1)
This is the same result as a script, but without writing any code. Just two batch calls.
Rate Limits
Notion enforces rate limits on its API. Batch operations run sequentially, so a large batch (30+ operations) can trigger 429 Too Many Requests errors. To avoid this:
Split large batches into chunks of ~25-30 operations per batch call
If a batch fails mid-way with a 429, re-run with only the remaining (unprocessed) operations
The batch output shows which operations succeeded before the failure — use the index field to determine where to resume
Search Command
# Search across workspace (--workspace-id is required)
vibe-notion search "query" --workspace-id <workspace_id> --pretty
vibe-notion search "query" --workspace-id <workspace_id> --limit 10 --pretty
vibe-notion search "query" --workspace-id <workspace_id> --start-cursor <offset> --pretty
vibe-notion search "query" --workspace-id <workspace_id> --sort lastEdited --pretty
User Commands
# Get current user info
vibe-notion user me --pretty
# Get a specific user
vibe-notion user get <user_id> --workspace-id <workspace_id> --pretty
Output Format
JSON (Default)
All commands output JSON by default for AI consumption:
# Search results
vibe-notion search "Roadmap" --workspace-id <workspace_id>
{
"results": [
{
"id": "305c0fcf-90b3-807a-bc1a-dc7cc18e0022",
"title": "Getting Started",
"score": 76.58
}
],
"has_more": true,
"next_cursor": "20",
"total": 100
}
# Database query — properties use human-readable field names from the collection schema
vibe-notion database query <database_id> --workspace-id <workspace_id>
{
"results": [
{
"id": "row-uuid",
"properties": {
"Name": "Acme Corp",
"Status": "Active",
"Type": "Enterprise"
}
}
],
"has_more": false,
"next_cursor": null
}
Schema Hints ($hints)
database get and database query may include a $hints array when the database schema has issues. These are actionable warnings — follow the instructions in each hint to fix the problem.
{
"id": "collection-uuid",
"name": "My Database",
"schema": { "Name": "title", "Status": "select" },
"$hints": [
"Rollup 'Revenue Sum' depends on deleted relation 'Deals'. This rollup will return empty values. Fix: run `database delete-property --property \"Revenue Sum\"` to remove it."
]
}
When $hints is present: Read each hint carefully and execute the suggested fix commands. Broken properties can crash the Notion app for the user. Common issues detected:
- Dead properties: Soft-deleted but still in schema. Usually harmless but indicates past issues.
- Broken rollups: Reference deleted or missing relations. Will return empty values and may crash Notion.
- Broken relations: Missing target collection. May crash Notion.
If $hints is absent, the schema is clean — no action needed.
# Page get — returns page metadata with content blocks
vibe-notion page get <page_id> --workspace-id <workspace_id>
{
"id": "page-uuid",
"title": "My Page",
"blocks": [
{ "id": "block-1", "type": "text", "text": "Hello world" },
{ "id": "block-2", "type": "to_do", "text": "Task item" }
]
}
# With --backlinks: includes pages that link to this page/block
vibe-notion page get <page_id> --workspace-id <workspace_id> --backlinks
vibe-notion block get <block_id> --workspace-id <workspace_id> --backlinks
{
"id": "page-uuid",
"title": "My Page",
"blocks": [...],
"backlinks": [
{ "id": "linking-page-uuid", "title": "Page That Links Here" }
]
}
# Block get — collection_view blocks include collection_id and view_ids
vibe-notion block get <block_id> --workspace-id <workspace_id>
{
"id": "block-uuid",
"type": "collection_view",
"text": "",
"parent_id": "parent-uuid",
"collection_id": "collection-uuid",
"view_ids": ["view-uuid"]
}
Pretty (Human-Readable)
Use --pretty flag for formatted output on any command:
vibe-notion search "Roadmap" --workspace-id <workspace_id> --pretty
When to Use --backlinks
Backlinks reveal which pages/databases link to a given page. This is critical for efficient navigation.
Use --backlinks when:
- Tracing relations: A search result looks like a select option, enum value, or relation target (e.g., a plan name or category). Backlinks instantly reveal all rows/pages that reference it via relation properties — no need to hunt for the parent database.
- Finding references: You found a page and want to know what other pages mention or link to it.
- Reverse lookups: Instead of querying every database to find rows pointing to a page, use backlinks on the target page to get them directly.
Example — finding who uses a specific plan:
# BAD: 15 API calls — search, open empty pages, trace parents, find database, query
vibe-notion search "Enterprise Plan" ...
vibe-notion page get <plan-page-id> ... # empty
vibe-notion block get <plan-page-id> ... # find parent
# ... many more calls to discover the database
# GOOD: 2-3 API calls — search, then backlinks on the target
vibe-notion search "Enterprise Plan" ...
vibe-notion page get <plan-page-id> --backlinks --pretty
# → backlinks immediately show all people/rows linked to this plan
Pagination
Commands that return lists support pagination via has_more, next_cursor fields:
block children: Cursor-based. Passnext_cursorvalue from previous response as--start-cursor.search: Offset-based. Passnext_cursorvalue (a number) as--start-cursor.database query: Use--limitto control page size.has_moreindicates more results exist, but the private API does not support cursor-based pagination — increase--limitto fetch more rows.
Troubleshooting
Authentication failures
If auto-extraction fails (e.g., Notion desktop app is not installed or not logged in), run the extract command manually for debug output:
vibe-notion auth extract --debug
This shows the Notion directory path and extraction steps to help diagnose the issue.
vibe-notion: command not found
The vibe-notion package is not installed. Run it directly using a package runner. Ask the user which one to use:
npx vibe-notion ...
bunx vibe-notion ...
pnpm dlx vibe-notion ...
If you already know the user's preferred package runner, use it directly instead of asking.
Limitations
- Auto-extraction supports macOS and Linux. Windows DPAPI decryption is not yet supported.
token_v2uses the unofficial internal API and may break if Notion changes it.- This is a private/unofficial API and is not supported by Notion.
Reviews (0)
No reviews yet. Be the first to review!
Comments (0)
No comments yet. Be the first to share your thoughts!