@andrzejchm/notion-cli 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@
4
4
  > This document tracks gaps and serves as a prioritized roadmap for closing them.
5
5
 
6
6
  **Legend:**
7
- - **CLI** = `@andrzejchm/notion-cli` (this repo, v0.8.0)
7
+ - **CLI** = `@andrzejchm/notion-cli` (this repo, v0.9.0)
8
8
  - **MCP** = Official Notion MCP server
9
9
 
10
10
  ---
@@ -16,12 +16,12 @@
16
16
  | Search | Keyword + sort by last edited | Semantic + AI + connected sources + date/creator filters | Partial |
17
17
  | Page read | Markdown via API | Markdown + discussions + transcripts | Partial |
18
18
  | Page create | Under pages only | Under pages, databases, data sources; batch; templates; icon/cover | Partial |
19
- | Page edit | Surgical replace via `--range` | Search-and-replace (multi-op), full replace, template apply, verification | Partial |
19
+ | Page edit | Multi-op `--find`/`--replace`, `--range` | Search-and-replace (multi-op), full replace, template apply, verification | Partial |
20
20
  | Page properties | Read + write via `update --prop` | Full read + write (update any property) | ✅ Parity |
21
- | Move pages | - | Batch move to any parent | Gap |
21
+ | Move pages | `move --to` / `--to-db` | Batch move to any parent | Parity |
22
22
  | Duplicate pages | - | Duplicate with async content copy | Gap |
23
23
  | Archive/delete | `archive` | Trash pages | ✅ Parity |
24
- | Database create | - | SQL DDL `CREATE TABLE` syntax | Gap |
24
+ | Database create | `db create --prop` syntax | SQL DDL `CREATE TABLE` syntax | Partial |
25
25
  | Database schema update | Read-only schema | `ADD/DROP/RENAME/ALTER COLUMN` via DDL | Gap |
26
26
  | Database views | - | Create + update 10 view types with DSL | Gap |
27
27
  | Comments | Page-level + block-level + thread replies, list with discussion IDs | Page-level + inline (selection-anchored) + reply to thread + rich text | Partial |
@@ -69,17 +69,15 @@ These gaps directly limit what an AI agent can accomplish through the CLI compar
69
69
  **CLI:** Thread replies (`--reply-to <discussion-id>`) and block-level comments (`--block <block-id>`) shipped. Discussion IDs shown in `notion comments` list output. Inline text-selection anchoring is not available in the public API. Plain text only.
70
70
  **Remaining gap:** Rich text (mentions, dates, links) and inline text-selection anchoring (`selection_with_ellipsis`) — the latter requires internal API access.
71
71
 
72
- #### 6. Create databases
72
+ #### 6. Create databases (shipped v0.10.0)
73
73
  **MCP:** `CREATE TABLE` DDL with full type system (select, relation, rollup, formula, unique_id, etc.).
74
- **CLI:** No equivalent.
75
- **Why:** Agents building project scaffolds or workflows need to create structured databases, not just pages.
76
- **Suggested command:** `notion create-db --parent <id> --title "Tasks" --schema "Name TITLE, Status SELECT(Todo,Done)"`
74
+ **CLI:** `notion db create --parent <id> --title "Tasks" --prop "Status:select:To Do,Done"` — supports title, rich_text, number, select, multi_select, status, date, checkbox, url, email, phone_number, people, files, created_time, last_edited_time. Relation, rollup, formula, and unique_id are not supported (too complex for CLI flags).
75
+ **Status:** Shipped in v0.10.0.
77
76
 
78
- #### 7. Move pages
77
+ #### 7. Move pages (shipped v0.11.0)
79
78
  **MCP:** Batch move up to 100 pages/databases to a new parent (page, database, data source, or workspace).
80
- **CLI:** No equivalent.
81
- **Why:** Reorganizing content (moving completed items to archive, restructuring projects) is a common agent task.
82
- **Suggested command:** `notion move <id...> --to <parent-id>`
79
+ **CLI:** `notion move <ids...> --to <page-id>` or `notion move <ids...> --to-db <database-id>`. Supports multiple page IDs as variadic arguments.
80
+ **Status:** Shipped in v0.11.0.
83
81
 
84
82
  #### 8. Update database schema
85
83
  **MCP:** `ADD COLUMN`, `DROP COLUMN`, `RENAME COLUMN`, `ALTER COLUMN SET` via DDL.
@@ -87,11 +85,10 @@ These gaps directly limit what an AI agent can accomplish through the CLI compar
87
85
  **Why:** Evolving database structure (adding a new status option, renaming a field) without leaving the terminal.
88
86
  **Suggested command:** `notion db alter <id> --add "Priority SELECT(High,Medium,Low)" --rename "Status:Project Status"`
89
87
 
90
- #### 9. Multi-operation content editing
88
+ #### 9. Multi-operation content editing (shipped v0.9.0)
91
89
  **MCP:** `update_content` accepts an array of `{ old_str, new_str }` pairs (up to 100) in a single call, with `replace_all_matches` option.
92
- **CLI:** `notion edit-page` supports single `--range` replacement. No batch search-and-replace.
93
- **Why:** Agents making multiple edits to a page (updating several sections) currently need multiple CLI invocations.
94
- **Suggested approach:** Support multiple `--replace "old...new"` flags or a JSON patch file.
90
+ **CLI:** `notion edit-page` supports multiple `--find`/`--replace` pairs in a single invocation (PR #6).
91
+ **Status:** Shipped in v0.9.0.
95
92
 
96
93
  #### 10. Duplicate pages
97
94
  **MCP:** `duplicate-page` — async copy of any accessible page.
@@ -180,6 +177,6 @@ The CLI isn't just chasing MCP parity — it has unique strengths:
180
177
 
181
178
  ---
182
179
 
183
- *Last updated: 2026-03-23*
184
- *CLI version compared: 0.8.0*
180
+ *Last updated: 2026-03-24*
181
+ *CLI version compared: 0.9.0*
185
182
  *MCP version compared: Official Notion MCP (2026-03)*
@@ -1,10 +1,10 @@
1
- # notion-cli for OpenCode
1
+ # notion-cli for AI Coding Agents
2
2
 
3
- Complete guide for using notion-cli with [OpenCode](https://opencode.ai).
3
+ Complete guide for using notion-cli with AI coding agents (Claude Code, OpenCode, Cursor, Windsurf, etc.).
4
4
 
5
5
  ## Quick Install
6
6
 
7
- Tell OpenCode:
7
+ Tell your AI agent:
8
8
 
9
9
  ```
10
10
  Fetch and follow instructions from https://raw.githubusercontent.com/andrzejchm/notion-cli/main/docs/README.agents.md
@@ -24,14 +24,17 @@ npm install -g @andrzejchm/notion-cli
24
24
 
25
25
  Homebrew bundles Node.js automatically. npm requires Node.js ≥ 22.
26
26
 
27
- ### 2. Install the skill file
27
+ ### 2. Install the skill
28
28
 
29
- ```bash
30
- mkdir -p ~/.config/opencode/skills/using-notion-cli
31
- curl -fsSL https://raw.githubusercontent.com/andrzejchm/notion-cli/main/docs/skills/using-notion-cli/SKILL.md \
32
- -o ~/.config/opencode/skills/using-notion-cli/SKILL.md
29
+ The skill file teaches your AI agent how to use notion-cli. It follows the open [Agent Skills](https://agentskills.io) standard.
30
+
31
+ **Skill URL:**
32
+ ```
33
+ https://raw.githubusercontent.com/andrzejchm/notion-cli/main/.agents/skills/using-notion-cli/SKILL.md
33
34
  ```
34
35
 
36
+ **Agent:** Ask the user whether they want the skill installed **globally** (all projects) or **per-project**, then consult your own documentation for the correct skill install path. The skill directory name must be `using-notion-cli` and the file must be named `SKILL.md`.
37
+
35
38
  ### 3. Authenticate
36
39
 
37
40
  **Interactive setup** (choose OAuth or integration token):
@@ -63,7 +66,7 @@ notion --version # CLI installed
63
66
  notion ls # auth works
64
67
  ```
65
68
 
66
- Restart OpenCode after installing. The skill is now discoverable via the `skill` tool.
69
+ Restart your agent session after installing so it picks up the new skill.
67
70
 
68
71
  ## Updating
69
72
 
@@ -73,12 +76,10 @@ brew upgrade notion-cli
73
76
 
74
77
  # npm
75
78
  npm install -g @andrzejchm/notion-cli
76
-
77
- # Update skill file (either install method)
78
- curl -fsSL https://raw.githubusercontent.com/andrzejchm/notion-cli/main/docs/skills/using-notion-cli/SKILL.md \
79
- -o ~/.config/opencode/skills/using-notion-cli/SKILL.md
80
79
  ```
81
80
 
81
+ To update the skill file, re-download it from the URL in step 2 to the same location.
82
+
82
83
  ## Commands Reference
83
84
 
84
85
  ### `notion search <query>` / `notion ls`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrzejchm/notion-cli",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Read Notion pages and databases from the terminal. Built for AI agents and developers.",
5
5
  "keywords": [
6
6
  "notion",
@@ -1,258 +0,0 @@
1
- ---
2
- name: using-notion-cli
3
- description: Reads and writes Notion pages using the `notion` CLI tool. Use when accessing Notion content, searching workspace pages, querying database entries, reading page markdown, appending content, creating pages, or adding comments from the terminal or within automated workflows.
4
- license: MIT
5
- compatibility: opencode
6
- ---
7
-
8
- ## Setup
9
-
10
- Install once:
11
- ```bash
12
- npm install -g @andrzejchm/notion-cli
13
- notion auth login # interactive setup — choose OAuth or integration token
14
- ```
15
-
16
- Or set env var (preferred for CI/agents):
17
- ```bash
18
- export NOTION_API_TOKEN=ntn_your_token_here
19
- ```
20
-
21
- Get token: https://www.notion.so/profile/integrations/internal
22
-
23
- Pages must be shared with your integration: open page → `⋯` → **Add connections**.
24
-
25
- **Integration capabilities** (set at notion.so/profile/integrations/internal → your integration → Capabilities):
26
- - Read-only commands: **Read content** only
27
- - `notion append`, `notion append --after`, `notion create-page` (page parent): also need **Insert content**
28
- - `notion create-page --parent <db>`: also need **Insert content** + database must be shared with integration
29
- - `notion edit-page`: also need **Update content** + **Insert content**
30
- - `notion comment`: also need **Read comments** + **Insert comments**
31
-
32
- ---
33
-
34
- ## Authentication
35
-
36
- Two auth methods are available. If both are configured, **OAuth takes precedence**.
37
-
38
- | Method | Command | Attribution | Notes |
39
- |--------|---------|-------------|-------|
40
- | Interactive setup | `notion auth login` | — | Guides you to choose; TTY required |
41
- | OAuth user login | select "OAuth user login" in `notion auth login` | Your Notion account | Browser required; `--manual` for headless |
42
- | Integration token | select "Integration token" in `notion auth login` | Integration bot | Works in CI/headless; must connect integration to pages |
43
-
44
- ```bash
45
- notion auth login # interactive selector — OAuth or integration token
46
- notion auth login --manual # headless OAuth (prints URL, paste redirect back)
47
- notion auth status # show current auth state
48
- notion auth logout # remove a profile (interactive selector)
49
- notion auth logout --profile <name> # remove specific profile directly
50
- notion auth list # list all saved profiles
51
- notion auth use <name> # switch active profile
52
- ```
53
-
54
- **Headless/CI agents:** Use `NOTION_API_TOKEN=<token>` env var — overrides all config, no TTY needed.
55
-
56
- ---
57
-
58
- ## Output Modes
59
-
60
- | Context | Default | Override |
61
- |---------|---------|----------|
62
- | Terminal (TTY) | Formatted tables | `--json` |
63
- | Piped / agent | Plain text tables | `--json` |
64
-
65
- `notion read` always outputs **markdown** — in terminal and when piped.
66
-
67
- Pipe any command to get JSON:
68
- ```bash
69
- notion search "query" | jq '.[0].id'
70
- notion ls | jq '.[] | select(.type == "database")'
71
- ```
72
-
73
- ---
74
-
75
- ## Commands
76
-
77
- ### Search & Discovery
78
-
79
- ```bash
80
- notion search "query" # search all pages/databases by title
81
- notion search "query" --type page # pages only
82
- notion search "query" --type database # databases only
83
- notion ls # list everything accessible to integration
84
- notion users # list workspace members
85
- notion comments <id|url> # list page comments
86
- notion open <id|url> # open in browser
87
- ```
88
-
89
- ### Reading Pages
90
-
91
- ```bash
92
- notion read <id|url> # markdown (always, even when piped)
93
- notion read <id|url> --json # raw Notion JSON block tree
94
- ```
95
-
96
- ### Database Operations
97
-
98
- ```bash
99
- notion db schema <id|url> # inspect properties + valid values
100
- notion db query <id|url> # all rows
101
- notion db query <id|url> --filter "Status=Done" # filter (repeatable)
102
- notion db query <id|url> --sort "Created:desc" # sort (repeatable)
103
- notion db query <id|url> --columns "Title,Status" # limit columns
104
- notion db query <id|url> --json | jq '.[] | .properties'
105
- ```
106
-
107
- ### Write Operations
108
-
109
- ```bash
110
- notion append <id|url> -m "## Heading\nParagraph text" # append markdown blocks to a page
111
- notion append <id|url> -m "$(cat notes.md)" # append file contents
112
-
113
- notion create-page --parent <page-id|url> --title "Title" # child page under a page
114
- notion create-page --parent <page-id|url> --title "Title" -m "# Hello" # with markdown body
115
- echo "# Content" | notion create-page --parent <page-id|url> --title "Title" # from stdin
116
-
117
- # Create entry in a database (auto-detected from parent ID)
118
- notion create-page --parent <db-id|url> --title "New Task"
119
- notion create-page --parent <db-id|url> --title "Task" --prop "Status=To Do" --prop "Priority=High"
120
- notion create-page --parent <db-id|url> --title "Task" --prop "Due=2026-04-01" -m "# Details"
121
-
122
- # Icon and cover
123
- notion create-page --parent <id|url> --title "Page" --icon "🚀"
124
- notion create-page --parent <id|url> --title "Page" --cover "https://example.com/img.jpg"
125
-
126
- URL=$(notion create-page --parent <id|url> --title "Summary" -m "...") # capture URL
127
-
128
- notion comment <id|url> -m "Reviewed and approved." # add comment to a page
129
- ```
130
-
131
- #### Updating Page Properties
132
-
133
- ```bash
134
- notion update <id|url> --prop "Status=Done" # set a single property
135
- notion update <id|url> --prop "Status=Done" --prop "Priority=1" # multiple properties
136
- notion update <id|url> --title "New Title" # set the title
137
- notion update <id|url> --prop "Due=2026-04-01" # set a date
138
- notion update <id|url> --prop "Tags=bug,urgent" # multi-select (comma-separated)
139
- notion update <id|url> --prop "Done=true" # checkbox (true/yes/false/no)
140
- notion update <id|url> --prop "Status=" # clear a property (empty value)
141
- ```
142
-
143
- Supported types: title, rich_text, select, status, multi_select, number, checkbox, url, email, phone_number, date.
144
-
145
- #### Surgical Editing
146
-
147
- Search-and-replace specific text, replace the full page, or insert content at a specific location.
148
-
149
- ```bash
150
- # Search-and-replace: find text and replace it
151
- notion edit-page <id|url> --find "old text" --replace "new text"
152
-
153
- # Multiple search-and-replace operations in one call
154
- notion edit-page <id|url> --find "old1" --replace "new1" --find "old2" --replace "new2"
155
-
156
- # Replace all occurrences (not just the first match)
157
- notion edit-page <id|url> --find "TODO" --replace "DONE" --all
158
-
159
- # Replace an entire page's content
160
- notion edit-page <id|url> -m "# Replacement\nNew full-page content"
161
-
162
- # Pipe replacement content from a file
163
- cat updated-section.md | notion edit-page <id|url>
164
-
165
- # Allow deletion of child pages/databases during replace
166
- notion edit-page <id|url> -m "## Clean Slate" --allow-deleting-content
167
-
168
- # Append after a matched section (inserts new blocks right after the match)
169
- notion append <id|url> -m "New content" --after "## Status...end of status"
170
- ```
171
-
172
- > **`--range` (deprecated):** The `--range` flag still works for backward compatibility but uses the older `replace_content_range` API. Prefer `--find`/`--replace` for targeted edits.
173
-
174
- ---
175
-
176
- ## ID Formats
177
-
178
- All commands accept any of:
179
- - `abc123def456789012345678901234ab` (32-char hex)
180
- - `abc123de-f456-7890-1234-5678901234ab` (UUID)
181
- - `https://www.notion.so/workspace/Page-Title-abc123` (full URL)
182
-
183
- ---
184
-
185
- ## Agent Patterns
186
-
187
- ```bash
188
- # Find page by title, read it
189
- PAGE_ID=$(notion search "Meeting Notes" --type page | jq -r '.[0].id')
190
- notion read "$PAGE_ID"
191
-
192
- # Get database ID, then query with filter
193
- DB_ID=$(notion search "Project Tracker" --type database | jq -r '.[0].id')
194
- notion db query "$DB_ID" --filter "Status=In Progress" | jq '.[] | .properties'
195
-
196
- # Always check schema before filtering (see valid property names/values)
197
- notion db schema "$DB_ID"
198
- notion db query "$DB_ID" --filter "Status=Done"
199
-
200
- # Extract page section
201
- notion read "$PAGE_ID" | grep -A 10 "## Action Items"
202
-
203
- # Summarize a page and append the summary back
204
- SUMMARY=$(notion read "$PAGE_ID" | your-summarize-command)
205
- notion append "$PAGE_ID" -m "## AI Summary\n$SUMMARY"
206
-
207
- # Create a page and capture its URL for further use
208
- URL=$(notion create-page --parent "$PAGE_ID" --title "Report $(date +%Y-%m-%d)" -m "# Report\n...")
209
- echo "Created: $URL"
210
-
211
- # Pipe command output into a new page
212
- my-report-command | notion create-page --parent "$PAGE_ID" --title "Auto Report"
213
-
214
- # Surgically update specific text on a page
215
- # 1. Read the page to find the text you want to change
216
- notion read "$PAGE_ID"
217
- # 2. Use --find/--replace to swap specific text
218
- notion edit-page "$PAGE_ID" --find "Status: In Progress" --replace "Status: Done"
219
-
220
- # Multiple replacements in one call
221
- notion edit-page "$PAGE_ID" \
222
- --find "Status: In Progress" --replace "Status: Done" \
223
- --find "Blocked: yes" --replace "Blocked: none"
224
-
225
- # Create a database entry with properties
226
- DB_ID=$(notion search "Tasks" --type database | jq -r '.[0].id')
227
- notion db schema "$DB_ID" # check property names and valid values first
228
- notion create-page --parent "$DB_ID" --title "Fix login bug" \
229
- --prop "Status=To Do" --prop "Priority=High" --prop "Due=2026-04-15"
230
-
231
- # Insert a new sub-section after an existing section
232
- notion append "$PAGE_ID" -m "## New Sub-section\nContent here" \
233
- --after "## Existing Section...last line of section"
234
- ```
235
-
236
- ---
237
-
238
- ## Troubleshooting
239
-
240
- **404 / page not found** — Share the page with your integration: page → `⋯` → **Add connections**.
241
-
242
- **401 / unauthorized** — Run `notion auth login` or set `NOTION_API_TOKEN`.
243
-
244
- **Search returns nothing** — Search is title-only. Page must be shared with integration.
245
-
246
- **Empty db query** — Run `notion db schema <id>` to see valid property names and values.
247
-
248
- **`notion auth login` requires TTY** — Use `NOTION_API_TOKEN` env var in agents, or use `notion auth login --manual` for headless OAuth.
249
-
250
- **`notion comment` returns "Insufficient permissions"** — Enable **Read comments** + **Insert comments** in integration capabilities: notion.so/profile/integrations/internal → your integration → Capabilities.
251
-
252
- **`notion append` / `notion create-page` returns "Insufficient permissions"** — Enable **Insert content** in integration capabilities.
253
-
254
- **`notion edit-page` returns "Insufficient permissions"** — Enable **Update content** in integration capabilities.
255
-
256
- **`--find` text not found** — Run `notion read <id>` to see the exact page content. The `--find` value must match text on the page exactly.
257
-
258
- **`--after` selector not found** — Run `notion read <id>` to see the exact page content. The selector must match real text: `"start...end"` with ~10 chars from the beginning and end of the target range.