notion
Read and write Notion pages, blocks, databases, and data sources through a local integration token.
Important
- Use the script in this skill directory; invoke with
bun. - Secrets live in the skill's
.envfile; never print or read that file into chat.- Claude Code:
.claude/skills/notion/.env - Codex:
.agents/skills/notion/.env
- Claude Code:
.envis gitignored.- The default Notion API version is
2026-03-11. Override withNOTION_VERSIONonly when the task requires an older API contract. - Notion integrations only see pages/databases explicitly shared with the connection.
- Write operations change real Notion content. Confirm intent before creating, appending, updating, archiving, trashing, or locking pages.
- Page metadata is not page content. Use
blocks --id PAGE_IDorpage --id PAGE_ID --contentto read page body blocks. - For current Notion APIs, query rows through data sources:
query-data-source --id DATA_SOURCE_ID. Retrieve a database first if you only have a database ID.
Setup / status
From repo root:
Claude Code
bun .claude/skills/notion/scripts/notion.ts status
Codex
bun .agents/skills/notion/scripts/notion.ts status
If not configured, create an internal Notion connection, grant it access to target pages/databases, and put the token in .env:
NOTION_API_KEY=ntn_...
NOTION_VERSION=2026-03-11
For first-time setup, use setup-guides/notion/SETUP_GUIDE.md.
Commands
Replace <skill_path> with:
.claude/skills/notionfor Claude Code.agents/skills/notionfor Codex
Auth
bun <skill_path>/scripts/notion.ts status
Search
bun <skill_path>/scripts/notion.ts search --query "meeting notes" --type page --limit 10
bun <skill_path>/scripts/notion.ts search --query "tasks" --type data_source --limit 20
bun <skill_path>/scripts/notion.ts search --limit 50
--type accepts page or data_source. Omit --query to list shared pages/data sources.
Pages and blocks
bun <skill_path>/scripts/notion.ts page --id PAGE_ID
bun <skill_path>/scripts/notion.ts page --id PAGE_ID --content
bun <skill_path>/scripts/notion.ts blocks --id PAGE_ID --limit 100
bun <skill_path>/scripts/notion.ts blocks --id BLOCK_ID --recursive --limit 100
Use the page ID as --id for blocks to read page body content.
Databases and data sources
bun <skill_path>/scripts/notion.ts database --id DATABASE_ID
bun <skill_path>/scripts/notion.ts data-source --id DATA_SOURCE_ID
bun <skill_path>/scripts/notion.ts query-data-source --id DATA_SOURCE_ID --limit 25
bun <skill_path>/scripts/notion.ts query-data-source --id DATA_SOURCE_ID --body ./query.json
query-data-source --body accepts inline JSON or a path to JSON containing Notion filter, sorts, and/or page_size.
Create and append
Create a normal child page under another page:
bun <skill_path>/scripts/notion.ts create-page --parent-page PAGE_ID --title "New notes" --text "First paragraph"
Create a row/page under a data source:
bun <skill_path>/scripts/notion.ts create-page \
--data-source DATA_SOURCE_ID \
--properties '{"Name":{"title":[{"text":{"content":"New task"}}]}}' \
--text "Details"
Append text blocks to a page or block:
bun <skill_path>/scripts/notion.ts append --id PAGE_ID --text "One paragraph\n\nAnother paragraph"
bun <skill_path>/scripts/notion.ts append --id PAGE_ID --type heading_2 --text "Decision"
append --type accepts paragraph, heading_1, heading_2, heading_3, bulleted_list_item, numbered_list_item, and to_do.
Update
Use update-page for property updates, icon/cover changes, lock/archive/trash flags, or raw body patches:
bun <skill_path>/scripts/notion.ts update-page --id PAGE_ID --properties ./properties.json
bun <skill_path>/scripts/notion.ts update-page --id PAGE_ID --body '{"is_locked":true}'
bun <skill_path>/scripts/notion.ts update-page --id PAGE_ID --archive true
Confirm with the user before --archive true, --trash true, or broad property rewrites.
Raw API escape hatch
bun <skill_path>/scripts/notion.ts api GET /v1/users/me
bun <skill_path>/scripts/notion.ts api POST /v1/search --body '{"query":"notes"}'
Output discipline
- Summarize large Notion responses instead of dumping raw page bodies into chat.
- Never expose the Notion token or raw
.envcontent. - Prefer IDs over names. Notion titles are not unique.
- If a 404 appears for a page/database that exists, check that the connection was shared with the original page or database, not only a linked database view.