Skip to content

andrzejchm/notion-cli

Repository files navigation

notion-cli

Read and write Notion pages from your terminal — built for AI coding agents and developers.

npm version homebrew tap Node.js >=22 License: MIT

# Homebrew (recommended)
brew tap andrzejchm/notion-cli
brew install notion-cli

# npm (alternative)
npm install -g @andrzejchm/notion-cli

notion auth login   # choose your auth method

For AI Agents

Fetch and follow instructions from https://raw.githubusercontent.com/andrzejchm/notion-cli/main/docs/README.agents.md

notion-cli demo


Features

  • notion search — find any page or database by title
  • notion read — render any page as full-fidelity markdown
  • notion db query — filter, sort, and select columns from any database
  • notion append — append markdown content to an existing page
  • notion create-page — create a new page with markdown body, prints URL to stdout
  • notion comment — add a comment to a page, block, or discussion thread
  • Agent-friendly — plain text tables by default; --json for machine-readable output
  • Flexible auth — interactive setup or NOTION_API_TOKEN env var
  • Accepts URLs — pass full Notion URLs anywhere an ID is expected

Examples

# Search for a page, then read it
PAGE_ID=$(notion search "Q1 Planning" | jq -r '.[0].id')
notion read "$PAGE_ID"

# Query a database with filters
notion db query "$DB_ID" --filter "Status=In Progress" --sort "Priority:asc"

# Get JSON output for scripting / AI agents
notion db query "$DB_ID" --filter "Status=Done" | jq '.[] | .properties.Title'

# Append markdown blocks to an existing page
notion append "$PAGE_ID" -m "## Summary\nGenerated by AI agent."

# Create a new page and capture its URL
URL=$(notion create-page --parent "$PAGE_ID" --title "Meeting Notes" -m "# Agenda\n- Item 1")
echo "Created: $URL"

# Pipe content to a new page
my-summarize-command | notion create-page --parent "$PAGE_ID" --title "Auto Summary"

# Add a comment to a page
notion comment "$PAGE_ID" -m "Reviewed and approved."

# Reply to an existing discussion thread
notion comment --reply-to "$DISCUSSION_ID" -m "Agreed, let's proceed."

# Comment on a specific block
notion comment --block "$BLOCK_ID" -m "This section needs revision."

# List everything your integration can access
notion ls

Commands

Command Description
notion auth login Interactive auth setup — choose OAuth or integration token
notion auth logout Remove a profile and all its credentials
notion auth status Show current auth state
notion auth list List all saved profiles
notion auth use <name> Switch the active profile
notion search <query> Search pages and databases by title (--sort asc|desc)
notion ls List all accessible pages and databases (--sort asc|desc)
notion open <id|url> Open a page in your browser
notion read <id|url> Read a page as markdown
notion db create --parent <id|url> --title <title> Create a new database with property definitions
notion db schema <id|url> Show database property schema and valid values
notion db query <id|url> Query database entries with filtering and sorting
notion users List workspace members
notion comments <id|url> Read page comments
notion comment [id|url] -m <text> Add a comment to a page, block, or thread
notion append <id|url> -m <markdown> Append markdown blocks to a page
notion attach <id|url> <file> [files...] Upload and attach file(s) to a page
notion edit-page <id|url> --find <old> --replace <new> Search-and-replace text on a page
notion edit-page <id|url> -m <markdown> Replace entire page content
notion create-page --parent <id|url> --title <title> Create a new page, prints URL
notion update <id|url> --prop "Name=Value" Update properties on a page
notion archive <id|url> Archive (trash) a page
notion move <ids|urls...> --to <id|url> Move pages to a new parent page
notion move <ids|urls...> --to-db <id|url> Move pages to a database parent
notion completion bash|zsh|fish Install shell tab completion

notion attach flags

Flag Example Description
--caption <text> --caption "My screenshot" Caption for the file block(s)
--type <type> --type image Override auto-detected block type (image|file|pdf|audio|video)
--json --json Output JSON response

notion append / notion create-page--file flag

Both commands accept a repeatable --file <path> option to attach local files after the markdown content is written:

# Append markdown and attach a file
notion append "$PAGE_ID" -m "See attached screenshot:" --file screenshot.png

# Create a page with an attached PDF
notion create-page --parent "$PAGE_ID" --title "Report" --file report.pdf

# Attach multiple files
notion append "$PAGE_ID" --file image.png --file data.csv

notion search / notion ls flags

Flag Example Description
--sort --sort desc Sort by last edited time (asc or desc)
--type --type page Filter by object type (page or database)
--cursor --cursor <cursor> Pagination cursor from a previous --next hint
--json --json Force JSON output

notion db create flags

Flag Example Description
--parent --parent <id|url> Parent page ID or URL (required)
--title --title "Tasks" Database title (required)
--prop --prop "Status:select:To Do,Done" Property definition (repeatable)
--json --json Output full JSON response

Property syntax: Name:type[:options]. Supported types: title, rich_text, number, select, multi_select, status, date, checkbox, url, email, phone_number, people, files, created_time, last_edited_time. If no title property is defined, Name:title is added automatically.

notion db query flags

Flag Example Description
--filter --filter "Status=Done" Filter by property value (repeatable)
--sort --sort "Created:desc" Sort by property (:asc or :desc)
--columns --columns "Title,Status" Only show specific columns
--json --json Force JSON output

Output Modes

The CLI auto-detects your context:

Context Default output Override
Terminal (TTY) Formatted tables, colored --json for raw JSON
Piped / agent Plain text tables --json for raw JSON

notion read always outputs markdown — in terminal and when piped.


Authentication

Two authentication methods are available. If both are configured, OAuth takes precedence for API calls.

Start with the interactive setup:

notion auth login   # choose OAuth or integration token

Tradeoff comparison

Method Best for Write attribution Requires
OAuth user login Write-heavy workflows, personal use Your Notion account Browser (or --manual for headless)
Integration token CI, Docker, automated agents Integration bot Token from notion.so/profile/integrations
NOTION_API_TOKEN env var CI/Docker without config files Integration bot Token set in environment

Priority: NOTION_API_TOKEN env var → OAuth token → integration token (first found wins)

OAuth user login

notion auth login         # interactive selector — choose OAuth
notion auth login --manual  # headless: prints URL, prompts to paste redirect
notion auth status        # show current auth state
notion auth logout        # remove profile and credentials

Comments and pages are attributed to your actual Notion account. Access tokens expire after ~1 hour and are refreshed automatically.

Integration token

notion auth login   # interactive selector — choose "Integration token"

# or: environment variable (CI, Docker, agents — no profile needed)
export NOTION_API_TOKEN=ntn_your_token_here

Works everywhere (CI, headless, agents). Write operations are attributed to the integration bot. You must manually connect the integration to each page ( → Add connections).

Token format: starts with ntn_ (new) or secret_ (legacy integrations).
Get a token: notion.so/profile/integrations/internal

Profile management

notion auth list          # list all profiles
notion auth use <name>    # switch active profile
notion auth logout        # remove a profile (interactive selector)
notion auth logout --profile <name>  # remove specific profile directly

Integration capabilities

Read-only commands (search, read, db query, etc.) need Read content only.

Write commands require additional capabilities — enable in your integration settings (notion.so/profile/integrations/internal → your integration → Capabilities):

Command Required capabilities
notion append Read content, Insert content
notion attach Read content, Insert content
notion create-page Read content, Insert content
notion update Read content, Update content
notion comment Read content, Insert content, Read comments, Insert comments

Troubleshooting

Page not found (404): Share the page with your integration — open the page → Add connections.

Unauthorized (401): Run notion auth login to reconfigure, or check your NOTION_API_TOKEN.

Search returns nothing: Search is title-only. The page must also be shared with your integration.

Empty database query: Run notion db schema <id> first to see valid property names and values.

notion comment returns "Insufficient permissions": Enable Read comments and Insert comments in your integration capabilities: notion.so/profile/integrations/internal → your integration → Capabilities.

notion append / notion create-page returns "Insufficient permissions": Enable Insert content in your integration capabilities.


Roadmap & Feature Parity

See docs/FEATURE-PARITY.md for a detailed comparison of this CLI's capabilities against the official Notion MCP server, with prioritized gaps and planned additions.


License

MIT © Andrzej Chmielewski

About

Notion CLI for AI agents and terminal workflows

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors