@jordancoin/notioncli 1.0.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.
- package/.github/workflows/ci.yml +31 -0
- package/LICENSE +21 -0
- package/README.md +353 -0
- package/bin/notion.js +847 -0
- package/lib/helpers.js +291 -0
- package/package.json +44 -0
- package/skill/SKILL.md +262 -0
- package/skill/install.sh +4 -0
- package/test/integration.test.js +110 -0
- package/test/mock.test.js +378 -0
- package/test/unit.test.js +663 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
node-version: [18, 20, 22]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: ${{ matrix.node-version }}
|
|
23
|
+
- run: npm ci
|
|
24
|
+
- run: npm run test:coverage
|
|
25
|
+
- name: Upload coverage
|
|
26
|
+
if: matrix.node-version == 22
|
|
27
|
+
uses: codecov/codecov-action@v4
|
|
28
|
+
with:
|
|
29
|
+
files: coverage/lcov.info
|
|
30
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
31
|
+
fail_ci_if_error: false
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JordanCoin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# notioncli
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@jordancoin/notioncli)
|
|
4
|
+
[](https://github.com/JordanCoin/notioncli/actions/workflows/ci.yml)
|
|
5
|
+
[](https://codecov.io/gh/JordanCoin/notioncli)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
|
|
9
|
+
A powerful CLI for the Notion API — query databases, manage pages, and automate your workspace from the terminal.
|
|
10
|
+
|
|
11
|
+
**No more copy-pasting UUIDs.** Set up aliases once, then just type `notion query tasks` or `notion add projects --prop "Name=Ship it"`.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @jordancoin/notioncli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# 1. One command to set up
|
|
21
|
+
notion init --key ntn_your_api_key_here
|
|
22
|
+
|
|
23
|
+
# That's it. Aliases are created automatically:
|
|
24
|
+
# ✅ projects → Project Tracker
|
|
25
|
+
# ✅ reading-list → Reading List
|
|
26
|
+
# ✅ meetings → Meeting Notes
|
|
27
|
+
|
|
28
|
+
# 2. Start using them immediately
|
|
29
|
+
notion query projects
|
|
30
|
+
notion add projects --prop "Name=Ship it" --prop "Status=Todo"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Zero UUIDs. One command. You're ready to go.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Setup
|
|
38
|
+
|
|
39
|
+
### 1. Create a Notion Integration
|
|
40
|
+
|
|
41
|
+
1. Go to [notion.so/profile/integrations](https://www.notion.so/profile/integrations)
|
|
42
|
+
2. Click **"New integration"**
|
|
43
|
+
3. Give it a name (e.g. "My CLI")
|
|
44
|
+
4. Copy the API key (starts with `ntn_`)
|
|
45
|
+
|
|
46
|
+
### 2. Share Your Databases
|
|
47
|
+
|
|
48
|
+
In Notion, open each database you want to access:
|
|
49
|
+
- Click the **•••** menu → **Connections** → Add your integration
|
|
50
|
+
|
|
51
|
+
### 3. Initialize
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
notion init --key ntn_your_api_key_here
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This saves your key, discovers all shared databases, and **creates aliases automatically**:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
✅ API key saved to ~/.config/notioncli/config.json
|
|
61
|
+
|
|
62
|
+
Found 3 databases:
|
|
63
|
+
|
|
64
|
+
✅ project-tracker → Project Tracker
|
|
65
|
+
✅ reading-list → Reading List
|
|
66
|
+
✅ meeting-notes → Meeting Notes
|
|
67
|
+
|
|
68
|
+
3 aliases saved automatically.
|
|
69
|
+
|
|
70
|
+
Ready! Try:
|
|
71
|
+
notion query project-tracker
|
|
72
|
+
notion add project-tracker --prop "Name=Hello World"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
That's it — no IDs, no extra steps. If you want shorter names:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
notion alias rename project-tracker projects
|
|
79
|
+
notion alias rename reading-list reads
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> **Alternative:** Skip `init` and set an environment variable:
|
|
83
|
+
> ```bash
|
|
84
|
+
> export NOTION_API_KEY=ntn_your_api_key
|
|
85
|
+
> ```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Commands
|
|
90
|
+
|
|
91
|
+
### `notion query` — Query a Database
|
|
92
|
+
|
|
93
|
+
The command you'll use most. Filter, sort, and browse your data:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
$ notion query projects
|
|
97
|
+
Date │ Name │ Status │ Priority
|
|
98
|
+
───────────┼─────────────────┼────────┼──────────
|
|
99
|
+
2026-02-09 │ Launch CLI │ Active │ High
|
|
100
|
+
2026-02-08 │ Write Docs │ Active │ Medium
|
|
101
|
+
2026-02-07 │ Design Landing │ Done │ Low
|
|
102
|
+
|
|
103
|
+
3 results
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
With filters and sorting:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
$ notion query projects --filter Status=Active --sort Date:desc --limit 5
|
|
110
|
+
Date │ Name │ Status │ Priority
|
|
111
|
+
───────────┼───────────────┼────────┼─────────
|
|
112
|
+
2026-02-09 │ Launch CLI │ Active │ High
|
|
113
|
+
2026-02-08 │ Write Docs │ Active │ Medium
|
|
114
|
+
|
|
115
|
+
2 results
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `notion add` — Add a Page
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
$ notion add projects --prop "Name=New Feature" --prop "Status=Todo" --prop "Date=2026-02-10"
|
|
122
|
+
✅ Created page: a1b2c3d4-...
|
|
123
|
+
URL: https://www.notion.so/...
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Properties are matched **case-insensitively** against the database schema. No need to memorize exact field names.
|
|
127
|
+
|
|
128
|
+
**Supported types:** title, rich_text, number, select, multi_select, date, checkbox, url, email, phone_number, status.
|
|
129
|
+
|
|
130
|
+
### `notion update` — Update a Page
|
|
131
|
+
|
|
132
|
+
By page ID:
|
|
133
|
+
```
|
|
134
|
+
$ notion update a1b2c3d4-5678-90ab-cdef-1234567890ab --prop "Status=Done" --prop "Priority=Low"
|
|
135
|
+
✅ Updated page: a1b2c3d4-...
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
By alias + filter (no UUIDs needed):
|
|
139
|
+
```
|
|
140
|
+
$ notion update workouts --filter "Name=LEGS #5" --prop "Notes=Great session"
|
|
141
|
+
✅ Updated page: a1b2c3d4-...
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### `notion delete` — Delete (Archive) a Page
|
|
145
|
+
|
|
146
|
+
By page ID:
|
|
147
|
+
```
|
|
148
|
+
$ notion delete a1b2c3d4-5678-90ab-cdef-1234567890ab
|
|
149
|
+
🗑️ Archived page: a1b2c3d4-...
|
|
150
|
+
(Restore it from the trash in Notion if needed)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
By alias + filter:
|
|
154
|
+
```
|
|
155
|
+
$ notion delete workouts --filter "Date=2026-02-09"
|
|
156
|
+
🗑️ Archived page: a1b2c3d4-...
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `notion get` — View Page Details
|
|
160
|
+
|
|
161
|
+
By page ID:
|
|
162
|
+
```
|
|
163
|
+
$ notion get a1b2c3d4-5678-90ab-cdef-1234567890ab
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
By alias + filter:
|
|
167
|
+
```
|
|
168
|
+
$ notion get workouts --filter "Name=LEGS #5"
|
|
169
|
+
Page: a1b2c3d4-5678-90ab-cdef-1234567890ab
|
|
170
|
+
URL: https://www.notion.so/New-Feature-a1b2c3d4...
|
|
171
|
+
Created: 2026-02-10T14:30:00.000Z
|
|
172
|
+
Updated: 2026-02-10T14:30:00.000Z
|
|
173
|
+
|
|
174
|
+
Properties:
|
|
175
|
+
Name: New Feature
|
|
176
|
+
Status: Todo
|
|
177
|
+
Date: 2026-02-10
|
|
178
|
+
Priority: High
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### `notion blocks` — View Page Content
|
|
182
|
+
|
|
183
|
+
By page ID or alias + filter:
|
|
184
|
+
```
|
|
185
|
+
$ notion blocks projects --filter "Name=Project Overview"
|
|
186
|
+
# Project Overview
|
|
187
|
+
This is the main project page.
|
|
188
|
+
• First task
|
|
189
|
+
• Second task
|
|
190
|
+
☑ Completed item
|
|
191
|
+
☐ Pending item
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### `notion dbs` — List All Databases
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
$ notion dbs
|
|
198
|
+
id │ title │ url
|
|
199
|
+
─────────────────────────────────────┼──────────────────┼──────────────
|
|
200
|
+
a1b2c3d4-e5f6-7890-abcd-ef1234567890 │ Project Tracker │ https://...
|
|
201
|
+
f9e8d7c6-b5a4-3210-fedc-ba0987654321 │ Reading List │ https://...
|
|
202
|
+
|
|
203
|
+
2 results
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### `notion search` — Search Everything
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
$ notion search "meeting"
|
|
210
|
+
id │ type │ title │ url
|
|
211
|
+
─────────────────────────────────────┼─────────────┼────────────────┼──────────────
|
|
212
|
+
a1b2c3d4-e5f6-7890-abcd-ef1234567890 │ page │ Meeting Notes │ https://...
|
|
213
|
+
f9e8d7c6-b5a4-3210-fedc-ba0987654321 │ data_source │ Meetings DB │ https://...
|
|
214
|
+
|
|
215
|
+
2 results
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### `notion alias` — Manage Aliases
|
|
219
|
+
|
|
220
|
+
Aliases are created automatically by `notion init`, but you can manage them:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# See your aliases
|
|
224
|
+
notion alias list
|
|
225
|
+
|
|
226
|
+
# Rename one
|
|
227
|
+
notion alias rename project-tracker projects
|
|
228
|
+
|
|
229
|
+
# Add one manually (auto-discovers the right IDs)
|
|
230
|
+
notion alias add tasks a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
|
231
|
+
|
|
232
|
+
# Remove one
|
|
233
|
+
notion alias remove tasks
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### `--json` — Raw JSON Output
|
|
237
|
+
|
|
238
|
+
Add `--json` to any command for the raw Notion API response:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
notion --json query projects --limit 1
|
|
242
|
+
notion --json dbs
|
|
243
|
+
notion --json get a1b2c3d4-...
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Great for piping into `jq` or other tools.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Use It With AI Agents
|
|
251
|
+
|
|
252
|
+
notioncli is designed to be fast for both humans and LLMs. AI coding agents can:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
# Discover what's available
|
|
256
|
+
notion dbs
|
|
257
|
+
notion alias list
|
|
258
|
+
|
|
259
|
+
# Query and filter data
|
|
260
|
+
notion query tasks --filter Status=Todo --sort Priority:desc
|
|
261
|
+
|
|
262
|
+
# Create and update pages — zero UUIDs workflow
|
|
263
|
+
notion add tasks --prop "Name=Fix bug #42" --prop "Status=In Progress"
|
|
264
|
+
notion update tasks --filter "Name=Fix bug #42" --prop "Status=Done"
|
|
265
|
+
|
|
266
|
+
# View, comment, and append — all by alias + filter
|
|
267
|
+
notion get tasks --filter "Name=Fix bug #42"
|
|
268
|
+
notion comment tasks "Shipped! 🚀" --filter "Name=Fix bug #42"
|
|
269
|
+
notion append tasks "Deployed to production" --filter "Name=Fix bug #42"
|
|
270
|
+
|
|
271
|
+
# Delete by alias + filter
|
|
272
|
+
notion delete tasks --filter "Name=Fix bug #42"
|
|
273
|
+
|
|
274
|
+
# Or use raw page IDs if you already have them
|
|
275
|
+
notion update <page-id> --prop "Status=Done"
|
|
276
|
+
|
|
277
|
+
# Get raw JSON for parsing
|
|
278
|
+
notion --json query projects --limit 10
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
No API key management, no curl commands, no JSON formatting — just simple shell commands.
|
|
282
|
+
|
|
283
|
+
### Zero-UUID Workflow
|
|
284
|
+
|
|
285
|
+
Every page-targeted command (`update`, `delete`, `get`, `blocks`, `comments`, `comment`, `append`) now accepts a **database alias + `--filter`** as an alternative to a raw page ID:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
# Instead of: notion update a1b2c3d4-5678-90ab-cdef-1234567890ab --prop "Status=Done"
|
|
289
|
+
# Just use: notion update projects --filter "Name=Ship it" --prop "Status=Done"
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The filter queries the database and expects **exactly one match**. If zero or multiple pages match, you get a clear error with guidance.
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Configuration
|
|
297
|
+
|
|
298
|
+
Config is stored at `~/.config/notioncli/config.json`:
|
|
299
|
+
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"apiKey": "ntn_...",
|
|
303
|
+
"aliases": {
|
|
304
|
+
"projects": {
|
|
305
|
+
"database_id": "a1b2c3d4-...",
|
|
306
|
+
"data_source_id": "a1b2c3d4-..."
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**API key resolution order:**
|
|
313
|
+
1. `NOTION_API_KEY` environment variable
|
|
314
|
+
2. Config file
|
|
315
|
+
3. Error with setup instructions
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Technical Notes
|
|
320
|
+
|
|
321
|
+
### Notion API 2025-09-03 — Dual IDs
|
|
322
|
+
|
|
323
|
+
The latest Notion API introduced a dual-ID system for databases. Each database now has both a `database_id` and a `data_source_id`. **notioncli handles this automatically** — when you add an alias, both IDs are discovered and stored. When you pass a raw UUID, it resolves correctly.
|
|
324
|
+
|
|
325
|
+
You don't need to think about this. It just works.
|
|
326
|
+
|
|
327
|
+
### Built on the Official SDK
|
|
328
|
+
|
|
329
|
+
notioncli uses [`@notionhq/client`](https://github.com/makenotion/notion-sdk-js) v5.x, Notion's official JavaScript SDK.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Contributing
|
|
334
|
+
|
|
335
|
+
1. Fork the repo
|
|
336
|
+
2. Create a feature branch (`git checkout -b feature/my-feature`)
|
|
337
|
+
3. Commit your changes (`git commit -am 'Add my feature'`)
|
|
338
|
+
4. Push to the branch (`git push origin feature/my-feature`)
|
|
339
|
+
5. Open a Pull Request
|
|
340
|
+
|
|
341
|
+
### Development
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
git clone https://github.com/JordanCoin/notioncli.git
|
|
345
|
+
cd notioncli
|
|
346
|
+
npm install
|
|
347
|
+
export NOTION_API_KEY=ntn_your_test_key
|
|
348
|
+
node bin/notion.js --help
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## License
|
|
352
|
+
|
|
353
|
+
MIT © [JordanCoin](https://github.com/JordanCoin)
|