# ntn: The Notion CLI

A command-line interface for Notion.

## Installation

```bash
curl -fsSL https://ntn.dev | bash
```

## What this is for

`ntn` is the Notion CLI for authenticating with Notion and managing Notion
Workers from your terminal. It is focused on Workers development and operation.

## Basic command overview

Use these commands to authenticate:

```bash
ntn login
ntn logout
```

Workers functionality is nested under the `workers` command namespace:

```bash
ntn workers --help
ntn workers list
ntn workers deploy
```

The public Notion API is available under the `api` command namespace:

```bash
ntn api ls
ntn api v1/pages --spec -X POST
ntn api v1/pages --docs -X POST
```

There is also a convenience wrapper for the File Uploads API:

```bash
ntn files create < file.png
ntn files create --external-url https://example.com/photo.png
ntn files get <upload-id>
ntn files list
```

`ntn files create` is intentionally quiet on success. For byte uploads it only
shows a progress bar when stderr is a TTY.

## Public API request syntax

`ntn api` supports inline request inputs:

```bash
# Direct JSON body
ntn api v1/pages -d '{"parent":{"page_id":"abc123"}}'

# JSON body string assignment
ntn api v1/pages parent[page_id]=abc123

# Typed JSON assignment
ntn api v1/pages archived:=true properties[count]:=10

# Query params and headers
ntn api v1/users page_size==100 Accept:application/json
```

Supported forms:

- `Header:Value` for request headers
- `name==value` for query params
- `path=value` for JSON string body fields
- `path:=json` for typed JSON body fields

Body paths support nested objects and arrays:

```bash
ntn api v1/pages \
  parent[page_id]=abc123 \
  children[][paragraph][rich_text][0][text][content]=Hello
```

Method selection stays simple:

- `GET` by default
- `POST` automatically when stdin JSON, `--data`, or inline body fields are present
- `-X/--method` always wins

Shell completion can also suggest public API paths and, for `-X/--method`, only
the methods supported by the selected path.

Use exactly one request-body source at a time: stdin JSON, `--data`, or inline
body fields.

See [docs/PUBLIC_API_REQUESTS.md](docs/PUBLIC_API_REQUESTS.md) for the full
reference, including:

- the complete inline parser syntax
- body path and array rules
- multipart upload behavior
- `ls`, `--spec`, and `--docs`
- verbose logging and environment variables

## Building from source

Clone the repository and install [mise](https://mise.jdx.dev/), which manages
toolchains and task running. Then build:

```bash
git clone https://github.com/makenotion/cli.git
cd cli
mise build
```

To rebuild automatically when files change:

```bash
mise watch build
```

To rebuild and refresh `/usr/local/bin/ntnd` automatically when files change:

```bash
mise watch release:local
```

`mise watch` uses `watchexec`; this repository declares it in `mise.toml`, so
`mise` will install it if needed.

To do a one-time install of the current debug build:

```bash
mise release:local
```

Both commands install the debug build as `ntnd` at `/usr/local/bin/ntnd`, which
avoids colliding with a production `ntn` install.

## Design

See [this page](https://claude.ai/public/artifacts/56976778-e51d-4e76-b400-c3c00b134678) for some of our design goals and inspiration with ntn (built by Claude).

## Documentation

See the `docs/` directory for additional documentation:

- `docs/PUBLIC_API_REQUESTS.md` for the complete `ntn api` request reference
- `docs/HIDDEN.md` for hidden commands and flags not shown in `--help` output
