Skip to content

FroeMic/notion-cli

Repository files navigation

notion-cli

A production-grade command-line interface for the Notion API. Built with TypeScript, featuring comprehensive type safety via Zod schemas, automatic retry logic with rate limiting, and multiple output formats.

Features

  • Pages β€” Create, read, update, archive, and restore pages with full property support
  • Databases β€” Create and manage databases, query with filters and sorts
  • Blocks β€” Append, update, and delete block content (paragraphs, headings, lists, code, and more)
  • Search β€” Full-text search across pages and databases with filtering and sorting
  • Users β€” List workspace members and retrieve user details
  • Comments β€” Create and list comments on pages and blocks

Technical Highlights:

  • JSON-first output with table and CSV formatting options
  • Automatic retry on rate limits (429) with exponential backoff
  • Runtime type validation using Zod schemas
  • Comprehensive error handling with actionable messages

Installation

From Source

git clone https://github.com/yourusername/notion-cli.git
cd notion-cli
npm install
npm run build
npm link  # Makes 'notion' command available globally

Development Mode

npm run dev -- <command>  # Run without building

Quick Start

1. Create a Notion Integration

  1. Go to My Integrations
  2. Click New integration
  3. Give it a name and select a workspace
  4. Copy the Internal Integration Secret (starts with ntn_ or secret_)

2. Configure the CLI

Create a .env file in the project root:

cp .env.example .env

Edit .env and add your API key:

NOTION_API_KEY=ntn_your_integration_secret_here

Or pass it directly via flag:

notion search --api-key ntn_your_key_here

3. Share Pages with Your Integration

In Notion, open a page or database, click β€’β€’β€’ β†’ Connections β†’ Add connection β†’ select your integration.

4. Build the CLI

npm install
npm run build

Then either link it globally:

npm link  # Creates global 'notion' command
notion users me

Or run directly without linking:

node dist/cli.js users me

5. Test the Connection

notion users me

Usage

Global Options

All commands support these options:

Option Description
--api-key <key> Override the API key from environment
-f, --format <fmt> Output format: json, table, csv (default: table)
--help Show help for any command

Search

# Search everything
notion search "meeting notes"

# Search only pages
notion search "quarterly report" --filter page

# Search only databases
notion search "tasks" --filter database

# Sort by last edited (ascending)
notion search --sort ascending --limit 10

Pages

# Get a page by ID
notion pages get <page-id>

# Create a page in a database
notion pages create --parent <database-id> --title "New Task"

# Create a page with properties (JSON)
notion pages create --parent <database-id> --title "Bug Fix" \
  --properties '{"Status": {"select": {"name": "In Progress"}}}'

# Update page properties
notion pages update <page-id> --properties '{"Status": {"select": {"name": "Done"}}}'

# Set page icon
notion pages update <page-id> --icon "πŸš€"

# Archive a page
notion pages archive <page-id>

# Restore an archived page
notion pages restore <page-id>

Databases

# Get database schema
notion databases get <database-id>

# Create a database
notion databases create --parent <page-id> --title "Project Tasks" \
  --properties '{"Status": {"select": {"options": [{"name": "Todo"}, {"name": "Done"}]}}}'

# Query a database
notion databases query <database-id>

# Query with filter
notion databases query <database-id> \
  --filter '{"property": "Status", "select": {"equals": "In Progress"}}'

# Query with sort
notion databases query <database-id> \
  --sort '{"property": "Created", "direction": "descending"}'

Blocks

# Get a block
notion blocks get <block-id>

# Get block children (page content)
notion blocks children <page-id>

# Append blocks to a page
notion blocks append <page-id> --content '[
  {"type": "paragraph", "paragraph": {"rich_text": [{"text": {"content": "Hello world"}}]}},
  {"type": "heading_2", "heading_2": {"rich_text": [{"text": {"content": "Section Title"}}]}}
]'

# Update a block
notion blocks update <block-id> --content '{"paragraph": {"rich_text": [{"text": {"content": "Updated text"}}]}}'

# Delete a block
notion blocks delete <block-id>

Users

# Get current bot user
notion users me

# List all users
notion users list

# Get a specific user
notion users get <user-id>

Comments

# List comments on a block/page
notion comments list --block <block-id>

# Create a comment on a page
notion comments create --page <page-id> --content "This looks great!"

# Reply to a discussion
notion comments reply --discussion <discussion-id> --content "Thanks for the feedback"

Output Formats

Table (default)

notion search "project" --format table
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Type     β”‚ ID                                   β”‚ Title           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ page     β”‚ 12345678-1234-1234-1234-123456789abc β”‚ Project Plan    β”‚
β”‚ database β”‚ 87654321-4321-4321-4321-cba987654321 β”‚ Project Tasks   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

JSON

notion pages get <page-id> --format json

CSV

notion databases query <database-id> --format csv > tasks.csv

Configuration

Environment Variables

Variable Description
NOTION_API_KEY Your Notion integration secret
NOTION_DEBUG Set to true for verbose logging

Config File

Create .env in the project root:

# Required
NOTION_API_KEY=ntn_your_secret_here

# Optional
NOTION_DEBUG=true

Development

Prerequisites

  • Node.js 18+
  • npm 9+

Setup

git clone https://github.com/yourusername/notion-cli.git
cd notion-cli
npm install

Scripts

Command Description
npm run dev Run CLI in development mode (tsx)
npm run build Compile TypeScript to JavaScript
npm test Run unit tests
npm run test:watch Run tests in watch mode
npm run test:integration Run integration tests (requires API key)
npm run test:coverage Run tests with coverage report
npm run lint Check code style
npm run lint:fix Fix code style issues
npm run format Format code with Prettier
npm run type-check Type-check without emitting

Running Tests

Unit tests (mocked, no API key required):

npm test

Integration tests (requires valid NOTION_API_KEY in .env):

npm run test:integration

Integration tests create temporary pages and databases, test operations, then clean up automatically.

Project Structure

notion-cli/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ client.ts          # HTTP client with retry logic
β”‚   β”‚   β”œβ”€β”€ errors.ts          # Error hierarchy
β”‚   β”‚   β”œβ”€β”€ types.ts           # Zod schemas (30+ types)
β”‚   β”‚   └── endpoints/         # API endpoint modules
β”‚   β”œβ”€β”€ commands/              # CLI command handlers
β”‚   β”œβ”€β”€ formatters/            # Output formatters (JSON, table, CSV)
β”‚   └── utils/                 # Config, validation, filter builders
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ unit/                  # Mocked tests (193 tests)
β”‚   └── integration/           # Live API tests (22 tests)
└── docs/                      # API documentation

Error Handling

The CLI provides clear, actionable error messages:

Error: Page not found

The requested page does not exist or your integration doesn't have access.

Suggestions:
  β€’ Verify the page ID is correct
  β€’ Ensure the page is shared with your integration
  β€’ Check that the page hasn't been deleted

Rate Limiting

The Notion API has a rate limit of 3 requests per second. The CLI automatically:

  • Retries on 429 (rate limit) responses
  • Respects the Retry-After header
  • Uses exponential backoff (up to 3 retries)

API Version

This CLI targets the Notion API version 2022-06-28.

License

MIT

Contributing

Contributions are welcome! Please ensure:

  1. All tests pass (npm test && npm run test:integration)
  2. Code is formatted (npm run format)
  3. No linting errors (npm run lint)
  4. Type-check passes (npm run type-check)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors