Read and write Notion pages from your terminal — built for AI coding agents and developers.
# 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 methodFetch and follow instructions from https://raw.githubusercontent.com/andrzejchm/notion-cli/main/docs/README.agents.md
notion search— find any page or database by titlenotion read— render any page as full-fidelity markdownnotion db query— filter, sort, and select columns from any databasenotion append— append markdown content to an existing pagenotion create-page— create a new page with markdown body, prints URL to stdoutnotion comment— add a comment to a page- Agent-friendly — plain text tables by default;
--jsonfor machine-readable output - Flexible auth — interactive setup or
NOTION_API_TOKENenv var - Accepts URLs — pass full Notion URLs anywhere an ID is expected
# 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."
# List everything your integration can access
notion ls| 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 |
notion ls |
List all accessible pages and databases |
notion open <id|url> |
Open a page in your browser |
notion read <id|url> |
Read a page as markdown |
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 |
notion append <id|url> -m <markdown> |
Append markdown blocks to a page |
notion create-page --parent <id|url> --title <title> |
Create a new page, prints URL |
notion completion bash|zsh|fish |
Install shell tab completion |
| 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 |
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.
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| 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)
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 credentialsComments and pages are attributed to your actual Notion account. Access tokens expire after ~1 hour and are refreshed automatically.
notion auth login # interactive selector — choose "Integration token"
# or: environment variable (CI, Docker, agents — no profile needed)
export NOTION_API_TOKEN=ntn_your_token_hereWorks 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
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 directlyRead-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 create-page |
Read content, Insert content |
notion comment |
Read content, Insert content, Read comments, Insert comments |
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.
MIT © Andrzej Chmielewski
