# ntn: The Notion CLI

A command-line interface for Notion.

## Installation

macOS and Linux:

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

Windows:

```powershell
winget install --exact --id Notion.ntn
```

Verify the Windows installation:

```powershell
Get-Command ntn
ntn --version
winget list --exact --id Notion.ntn
```

### PowerShell completions

Enable completions for the current PowerShell session:

```powershell
ntn completions powershell | Out-String | Invoke-Expression
```

To enable them for future sessions, add the same command to your PowerShell
profile:

```powershell
$completionSetup = 'ntn completions powershell | Out-String | Invoke-Expression'
if (-not (Test-Path $PROFILE)) {
    New-Item -ItemType File -Path $PROFILE -Force | Out-Null
}
if (-not (Select-String -Path $PROFILE -SimpleMatch $completionSetup -Quiet)) {
    Add-Content -Path $PROFILE -Value $completionSetup
}
. $PROFILE
```

Windows PowerShell 5.1 and PowerShell 7 use different `$PROFILE` files. Run the
setup in each shell if you use both.

WinGet installs `ntn` but does not modify your PowerShell profile.

## 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. `--data` accepts raw JSON, `@path` for a JSON file, and `@-` for
stdin.

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
```

By default this installs the debug build as `ntnd` at `/usr/local/bin/ntnd`, which
avoids colliding with a production `ntn` install.

To replace the `ntn` binary already on your `PATH` instead:

```bash
mise release:local --overwrite
```

## 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
