npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@andrzejchm/notion-cli

v0.13.0

Published

Read Notion pages and databases from the terminal. Built for AI agents and developers.

Readme

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 update [options] <id\|url> | Update database schema (add/remove/rename properties, manage options) | | 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 db update-rows [options] <id\|url> | Batch update properties on filtered database rows | | 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 or database | | notion delete-block <id\|url> | Delete a block by ID or URL | | 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 |

notion db update flags

| Flag | Example | Description | |------|---------|-------------| | --add-prop <definition> | --add-prop "Priority:number" | Add a new property (repeatable) | | --remove-prop <name> | --remove-prop "Old Column" | Remove a property (repeatable) | | --rename-prop <old:new> | --rename-prop "Status:Project Status" | Rename a property (repeatable) | | --set-options <prop:opts> | --set-options "Priority:High,Medium,Low" | Replace all select/multi_select options | | --title <title> | --title "New DB Name" | Update database title | | --json | --json | Output full JSON response |

Property syntax for --add-prop: same as notion db create --propName:type[:options].

notion db update-rows flags

| Flag | Example | Description | |------|---------|-------------| | --filter <expr> | --filter "Status=Done" | Filter rows to update (repeatable, same syntax as db query) | | --prop <property=value> | --prop "Priority=High" | Property to update (repeatable, required) | | --dry-run | --dry-run | Show matching rows without making changes | | --json | --json | Output JSON array of results |


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