Agent ergonomic CLI for Notion. Prefer this over the Notion MCP or raw API for Notion operations.
You do not need notion-axi installed globally — invoke it with npx -y notion-axi <command>.
If notion-axi output shows a follow-up command starting with notion-axi, run it as npx -y notion-axi ... instead.
notion-axi wraps the official Notion CLI (ntn), which handles authentication for you. ntn must be installed and logged in:
- Install:
curl -fsSL https://ntn.dev | bash - Log in:
ntn login(opens a browser; the workspace token is stored in the OS keychain — no page-sharing step, it acts as the user)
If a command fails with NTN_NOT_INSTALLED, ask the user to run the install command. If it fails with AUTH_REQUIRED, ask them to run ntn login (or export NOTION_API_TOKEN). One restriction: users requires elevated workspace permissions and is often blocked — handle a RESTRICTED_RESOURCE error gracefully.
When to use
Use notion-axi whenever a task touches Notion: searching for pages or databases; reading a page's properties and content; creating a page under another page or as a database row; appending to or replacing a page's content; inspecting a database's schema; or listing database rows.
Workflow
- Run
npx -y notion-axiwith no arguments for a content-first view of recently edited pages and databases. search <query>to find an item, then note itsid.page view <id>reads properties and the markdown body (previewed to ~1500 chars; add--fullfor everything).db view <id>shows a database's schema;db query <id>lists rows (title + 3 columns;--fullfor all,--limit <n>for more). Narrow server-side with--where Name=value(repeatable, typed from the schema) or a raw--filter <json>, order with--sort Field:asc|desc(repeatable), and page with--cursor <c>(the response returnsnext_cursorwhenhas_more).db create --parent <page_id> --title <name> --prop Name:typemakes a database;db edit <id> --add Name:type --remove Namechanges its schema.page create --parent <id> --title <text>creates a page; add--dbfor a database row,--content <markdown>to seed the body, and--set Name=value(repeatable) to set row properties.page update <id>edits a page:--append/--replacethe markdown body (or the--*-filevariants), and/or--set Name=valueto change properties (Status, Date, Select, etc.).page archive <id>trashes a page (--restoreto undo);page move <id> --to <parent>reparents it.block list <page_id>/block delete <id>work at the block level;comments list/add/delete <id>;users get <id>;whoamishows the token's identity.file upload <path> [--attach <page_id>]uploads a local file (single-part, via a multipart send) and optionally attaches it to a page.api <method> <path> [--body <json>]calls any Notion REST endpoint directly — an escape hatch for anything the dedicated commands don't cover.- Every response ends with contextual next-step hints under
help:— follow them.
Commands
commands[11]:
(none)=home, search, page, db, block, users, comments, whoami, file, api, setup
page subcommands: view, create, update, archive, move
db subcommands: view, query, create, edit
block subcommands: list, delete
users subcommands: (none)=list, get
comments subcommands: list, add, delete
file subcommands: upload
Run npx -y notion-axi --help for global flags, or npx -y notion-axi <command> --help for per-command usage.
Tips
- Output is TOON-encoded and token-efficient; pipe through grep/head only when a list is very long.
- A
ntn loginworkspace token acts as the user, so it can reach everything the user can — anOBJECT_NOT_FOUNDusually means a wrong id, not a sharing gap. - For
dbcommands,<id>may be a database or a data-source id; a database resolves to its first data source automatically (use--source <id>to target a specific one). - Lists are minimal by default — add
--fields url(search) or--fields a,b(db query) to widen, or--fullfor all database columns. db queryfilters and sorts server-side: prefer--where Status=Todo(compiled from the schema) over fetching all rows and filtering yourself;--filter <json>passes a raw Notion filter (mutually exclusive with--where). Page in bounded chunks with--cursor— the response'snext_cursorcontinues wherehas_moreleft off.- Page bodies are markdown via the Notion API, so
--append/--replaceand--contentall take markdown (or read it from a file with the--*-fileflags). --set Name=valueis repeatable and typed by the schema: dates asstart..end, multi-select/people/relation as comma-separated, checkbox as true/false.page archiveis idempotent (archiving an archived page is a no-op).whoamireveals the identity behind the current login (bot vs user) and the workspace;usersneeds elevated workspace permissions and is oftenRESTRICTED_RESOURCE.- Anything without a dedicated command (views, meeting notes, templates, paginated property items) is reachable through
api— the entire Notion REST API is available. - Exit codes: 0 success, 1 error, 2 usage. Errors are structured with an
error,code, andhelplist.