> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pixeltable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Reference

> Inspect, query, and serve Pixeltable catalogs from the terminal with the pxt command.

The `pxt` CLI ships with the `pixeltable` package. It covers two surfaces:

* **Catalog operations** -- inspect, query, and manage tables, views, and directories. Backed by a long-lived local daemon so each command takes \~40 ms after the first invocation.
* **Service deployment** -- turn tables, computed columns, and `@pxt.query` functions into HTTP endpoints with `pxt serve`, and publish them with `pxt deploy`. `pxt serve` requires the `serve` extra (which pulls in `fastapi[standard]` and `uvicorn`):

  ```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
  pip install 'pixeltable[serve]'
  ```

Verify the installation:

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt --help
pxt health
```

On the first catalog command, `pxt` auto-spawns a daemon bound to `127.0.0.1:22089`. The daemon survives across shells and stays warm for subsequent commands. Override the port with `PXT_PORT`.

## Command structure

```text theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt <command> [args...]
```

Use `pxt <command> --help` for per-subcommand flags and examples.

| Category        | Commands                                                                       |
| --------------- | ------------------------------------------------------------------------------ |
| **Inspection**  | `ls`, `describe`, `columns`, `computed`, `idxs`, `history`, `status`, `config` |
| **Navigation**  | `cd`, `pwd`                                                                    |
| **Query**       | `rows`, `get`, `count`, `errors`                                               |
| **Mutation**    | `drop`, `drop-dir`, `rename`, `mv`, `revert`                                   |
| **Schema**      | `schema diff`, `schema update`, `schema prune`                                 |
| **Interactive** | `shell`                                                                        |
| **Serving**     | `serve`                                                                        |
| **Cloud**       | `db`, `service`, `org`                                                         |
| **Lifecycle**   | `daemon`, `dashboard`, `health`                                                |

### Universal flags

These flags work the same way across the catalog commands that support them and are not repeated in the per-command tables below.

| Flag              | Available on                                                                                                                                                                                                                                                                             | Description                                                                                                                                                                                                                                                    |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-h`, `--help`    | Every command                                                                                                                                                                                                                                                                            | Print the command's usage and examples                                                                                                                                                                                                                         |
| `--json`          | Inspection, query, and mutation commands (`ls`, `describe`, `columns`, `computed`, `idxs`, `history`, `status`, `config`, `rows`, `get`, `count`, `errors`, `drop`, `drop-dir`, `rename`, `mv`, `revert`), the `schema` verbs, plus `serve`, `db`, `service`, `org`, and `daemon status` | Emit machine-readable JSON instead. Not accepted by `shell` (interactive REPL), `health` (always JSON), `dashboard` (URL launcher), the navigation commands (`cd`, `pwd`), or the lifecycle subcommands that print plain status lines (`daemon start`/`stop`). |
| `-n`, `--dry-run` | Every catalog mutation (`drop`, `drop-dir`, `rename`, `mv`, `revert`), plus `schema update` and `schema prune`                                                                                                                                                                           | Print the intended action; don't execute. `pxt serve` accepts the long form `--dry-run` only.                                                                                                                                                                  |
| `-f`, `--force`   | Mutations that prompt for confirmation (`drop`, `drop-dir`, `revert`, `schema update`, `schema prune`)                                                                                                                                                                                   | Skip the `[y/N]` prompt. Required in non-interactive contexts. `rename` and `mv` don't prompt and don't accept `-f`.                                                                                                                                           |

### Working directory

`pxt cd` sets a working directory that is prepended to *relative* paths in later commands, and `pxt pwd` prints it -- the catalog analogue of a shell's `cd`/`pwd`.

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt cd my_dir                      # relative paths now resolve under my_dir
pxt pwd                            # print the current working directory
pxt ls sub                         # lists my_dir/sub
pxt cd ..                          # up one level
pxt cd                             # clear it
```

Absolute paths ignore the working directory: a leading `/` (e.g. `pxt ls /other_dir`) resolves from the catalog root, and a `pxt://org:db/...` URI addresses a hosted catalog. `.` and `..` work in any path and resolve against the working directory; `..` at the catalog root keeps the root.

The working directory is scoped to the **invoking terminal**, not the daemon globally -- it is keyed by the shell's session, sent with every command. So separate terminals have independent working directories, and, crucially, it does **not** leak into subprocesses or agents you launch: a spawned process runs under its own session with no working directory, so its `pxt` commands resolve relative paths from the catalog root regardless of what you set interactively.

Because of that isolation, scripts and agents should address the catalog with absolute paths (`/...` or `pxt://...`) and ignore the working directory; it is a convenience for interactive terminal use.

## Quick reference

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
# inspect
pxt ls -l                          # everything under root, with metadata
pxt ls some_dir --counts           # row counts (parallelized)
pxt describe my_dir/my_table       # schema
pxt rows my_dir/my_table -n 5      # first 5 stored cells

# query
pxt get my_dir/my_table 42         # PK lookup
pxt count my_dir/my_table          # row count
pxt errors my_dir/my_table         # rows where a computed column failed

# ops
pxt drop my_dir/my_table -f
pxt mv my_dir/my_table other_dir
pxt revert my_dir/my_table --steps 3 -f

# navigate
pxt cd my_dir                      # set the working directory (this terminal)
pxt pwd                            # print it

# declarative schemas
pxt schema diff   schema.py my_app   # what 'update' would change (exit 2 = drift)
pxt schema update schema.py my_app   # create and migrate the declared tables
pxt schema prune  schema.py my_app -f # drop the undeclared ones

# interactive
pxt shell

# serve locally
pxt serve my-service

# cloud — databases
pxt db create pxt://myorg:mydb
pxt db list pxt://myorg
pxt db update-runtime pxt://myorg:mydb

# cloud — services
pxt service create my-service --base-uri pxt://myorg:mydb
pxt service list pxt://myorg:mydb
pxt service status pxt://myorg:mydb/services/my-service
```

## Inspection commands

### `pxt ls`

List entries under a directory.

| Flag           | Description                                                 |
| -------------- | ----------------------------------------------------------- |
| `-l`, `--long` | Include column count, last version, and flags               |
| `--counts`     | Include row counts (runs `count()` per table, parallelized) |
| `--tree`       | Tree view                                                   |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt ls                            # root
pxt ls some_dir                   # contents of some_dir
pxt ls -l some_dir                # with metadata
pxt ls --counts                   # with row counts
```

Output of `pxt ls -l`:

```text theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
path                kind   cols  version  flags
agent_demo          dir                       -
audio_chunks        view      9        3  ci
chess_vids          table     3        3  ci
chk                 table     2        1  i
```

Flag letters: `c` = has at least one computed column, `i` = has at least one index.

### `pxt describe`

Show a table's schema and metadata. The plain form is human-readable; `--json` returns the full `get_metadata()` dict.

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt describe my_dir/my_table
pxt describe my_dir/my_table --json
```

### `pxt columns` / `pxt computed`

List columns for one or more tables. `pxt computed` is shorthand for `pxt columns --computed`. The path argument may be a single table or a directory; a directory path lists columns for every table beneath it, recursively. A directory path may be a local path or a hosted uri (`pxt://org:db/...`). With no path, every table in the in-process catalog is listed.

| Flag         | Description                                                                       |
| ------------ | --------------------------------------------------------------------------------- |
| `--computed` | Restrict to computed columns (no effect for `pxt computed`, which always sets it) |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt columns                       # every column in the catalog
pxt columns my_dir/my_table       # one table
pxt columns my_dir                # every table under a directory, recursively
pxt columns pxt://org:db          # every table in a hosted database
pxt columns --computed            # computed columns across every table
pxt computed                      # same as above
```

### `pxt idxs`

List indexes. Shows both B-tree and embedding indexes by default; the `--embedding` flag restricts to embedding indexes. Like `pxt columns`, the path may be a single table or a directory (walked recursively), a hosted database root (`pxt://org:db`), or omitted for the whole in-process catalog.

| Flag          | Description                   |
| ------------- | ----------------------------- |
| `--embedding` | Restrict to embedding indexes |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt idxs                          # every index
pxt idxs my_dir/my_table          # indexes on one table
pxt idxs my_dir                   # every table under a directory, recursively
pxt idxs pxt://org:db             # every table in a hosted database
pxt idxs --embedding              # only embedding indexes
```

### `pxt history`

Show a table's version timeline.

| Flag   | Description                         |
| ------ | ----------------------------------- |
| `-n N` | Show at most N most recent versions |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt history my_dir/my_table
pxt history my_dir/my_table -n 5  # last 5 versions
```

### `pxt status`

Daemon and runtime state: pxt version, daemon PID, configured paths, total tables, total errors.

| Flag      | Description                                                                 |
| --------- | --------------------------------------------------------------------------- |
| `--sizes` | Also report media and file-cache disk usage (slower; scans the directories) |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt status
pxt status --sizes --json
```

### `pxt config`

Every documented configuration setting with its current value and source (`env`, `file`, or `unset`). Credentials show `<redacted>` when set; the `source` column reveals presence even when the value is masked.

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt config
pxt config --section openai
pxt config --source env
```

## Query commands

### `pxt rows`

Show the first N rows of a table. Unstored computed columns are skipped by default (selecting one forces evaluation, which can invoke LLMs or expensive compute); pass them explicitly via `--cols` to include them.

| Flag           | Description                                                |
| -------------- | ---------------------------------------------------------- |
| `-n N`         | Number of rows (default 10)                                |
| `--cols a,b,c` | Comma-separated column subset. Default: all stored columns |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt rows my_dir/my_table -n 3
pxt rows my_dir/my_table --cols id,text,score
```

### `pxt get`

Look up a single row by primary key. A numeric-looking PK token is coerced to int or float; everything else stays a string. There is no quoting escape for a string-typed PK whose value looks numeric -- if your PK column is a string but the value is `42`, the server will reject the type mismatch. The table must declare a primary key. Unstored computed columns are skipped unless requested explicitly via `--cols` (consistent with `rows`).

| Flag           | Description                                                |
| -------------- | ---------------------------------------------------------- |
| `--cols a,b,c` | Comma-separated column subset. Default: all stored columns |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt get my_dir/my_table 42                    # single-column PK, int
pxt get my_dir/my_table some_string_id        # single-column PK, string
pxt get my_dir/my_table 42 abc                # composite PK, in declared order
pxt get my_dir/my_table 42 --cols id,text     # restrict to listed columns
```

### `pxt count`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt count my_dir/my_table         # prints the integer
pxt count my_dir/my_table --json
```

### `pxt errors`

List rows where a stored computed column failed. The table must have a primary key (so each failing row can be identified).

| Flag         | Description                        |
| ------------ | ---------------------------------- |
| `--col NAME` | Filter to a single computed column |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt errors my_dir/my_table
pxt errors my_dir/my_table --col embedding
```

## Mutation commands

Every mutation accepts the universal `-n`/`--dry-run` and `--json` flags. The destructive ones (`drop`, `drop-dir`, `revert`) also prompt `[y/N]` with a TTY and accept `-f`/`--force` to skip the prompt; in non-interactive contexts they refuse to proceed without `-f`. `rename` and `mv` don't prompt: renaming or moving a catalog entry is reversible and doesn't lose data.

### `pxt drop`

Drop a table or view. Use `pxt drop-dir` for directories.

| Flag        | Description               |
| ----------- | ------------------------- |
| `--cascade` | Also drop dependent views |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt drop my_dir/my_table -f                 # drop a table
pxt drop my_dir/my_table --cascade -f       # also drop dependent views
pxt drop my_dir/my_table -n                 # dry-run
```

### `pxt drop-dir`

Remove a directory. Use `pxt drop` for tables/views.

| Flag                | Description                                       |
| ------------------- | ------------------------------------------------- |
| `-r`, `--recursive` | Also remove contained tables/views/subdirectories |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt drop-dir my_dir -f            # remove an empty directory
pxt drop-dir my_dir -r -f         # recursive: also remove contained tables/subdirs
```

### `pxt rename`

Rename in place; the parent directory is preserved. `<new_name>` must be a single leaf name (no `/` or `.`). Takes only universal flags.

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt rename my_dir/old_name new_name
```

### `pxt mv`

Move a table/view/dir under a different directory; the leaf name is preserved. `<new_dir>` can be `''` or `/` for the root directory. Takes only universal flags.

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt mv my_dir/my_table other_dir              # -> other_dir/my_table
pxt mv my_dir/my_table /                      # move to root
```

### `pxt revert`

Undo recent ops on a table. Each revert undoes one op; `--steps` repeats.

| Flag        | Description                               |
| ----------- | ----------------------------------------- |
| `--steps N` | Number of consecutive reverts (default 1) |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt revert my_dir/my_table -f                 # undo the last op
pxt revert my_dir/my_table --steps 3 -f       # roll back 3 versions
```

<Warning>
  Revert is irreversible. Run `pxt history my_dir/my_table` first to see what would be undone.
</Warning>

## Schema management

The commands above act on one object at a time. `pxt schema` works differently: you describe the tables you want in a Python file, and the CLI reconciles a catalog directory to that description. Provisioning an empty target and evolving an existing one are the same command, so there is no separate first-time step.

| Command                           | Description                                                                     |
| --------------------------------- | ------------------------------------------------------------------------------- |
| `pxt schema diff SCHEMA TARGET`   | Show what `update` would change. Read-only                                      |
| `pxt schema update SCHEMA TARGET` | Create the tables the schema declares under `TARGET`, and migrate existing ones |
| `pxt schema prune SCHEMA TARGET`  | Drop the tables under `TARGET` that the schema does not declare                 |
| `pxt schema example`              | Write a working schema file to start from                                       |

`SCHEMA` is a path to a Python file. `TARGET` is a catalog directory or a `pxt://` URI; it is created by `update` if it doesn't exist.

### The schema file

A schema file defines one or more models on a `pxt.model_base()`. Each model becomes one table, named by `name=`. `pxt schema example` writes a file covering every construct the schema DSL supports, so you never have to start from a blank page and never have to look a construct up:

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt schema example --out schema.py
```

`pxt schema example --brief` writes the minimal version instead:

```python theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
from __future__ import annotations  # required to declare a model on Python 3.14+

import pixeltable as pxt
import pixeltable.functions as pxtf

TableModel = pxt.model_base()

class Docs(TableModel, name='docs'):
    title: pxt.Required[pxt.String]           # a stored column; without Required it is nullable
    body: pxt.String
    title_upper = pxtf.string.upper(title)    # a computed column: an assignment, not an annotation

class Titled(TableModel, name='titled', base=Docs.where(Docs.title != '')):
    headline = Docs.title_upper + '!'         # a view of Docs, filtered by its base= query
```

An annotation (`name: type`) declares a stored column; an assignment (`name = expr`) declares a computed column. A model with `base=` becomes a view of the model that query selects from.

The daemon imports the file, so it must be readable there. Its own directory is added to `sys.path`, so it can import modules sitting next to it.

### Reviewing and applying

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt schema diff   schema.py my_app     # review
pxt schema update schema.py my_app     # apply
```

`diff` prints one line per table, then one per operation:

```text theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
~ my_app/docs              update
    + column 'author' will be added  safe
    - column 'body' will be dropped  DESTRUCTIVE
= my_app/titled_docs       no change
! my_app/scratch           extra (not in schema)

Plan: 0 create, 1 update, 1 unchanged, 1 extra  |  1 destructive
```

| Marker | Meaning                                                                 |
| ------ | ----------------------------------------------------------------------- |
| `+`    | The table will be created, or the column/index will be added            |
| `~`    | The table will be migrated                                              |
| `=`    | The table already matches its model                                     |
| `-`    | The column/index will be dropped                                        |
| `!`    | The table cannot be migrated in place, or is not declared by the schema |

### Applying

`update` creates missing tables and migrates existing ones, adding and dropping columns and indexes. It takes the same flags as the other mutations, plus one of its own:

| Flag                  | Description                                                    |
| --------------------- | -------------------------------------------------------------- |
| `-n`, `--dry-run`     | Print the plan; apply nothing. Exit `2` if changes are pending |
| `--allow-destructive` | Permit operations that drop a column or index                  |
| `-f`, `--force`       | Skip the `[y/N]` prompt shown before destructive operations    |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt schema update schema.py my_app                          # safe changes
pxt schema update schema.py my_app -n                       # the plan, applying nothing
pxt schema update schema.py my_app --allow-destructive -f   # including drops
```

If the plan contains a destructive operation and `--allow-destructive` is absent, nothing at all is applied and `update` exits `3`.

<Warning>
  Dropping a column or an index destroys its data. Run `pxt schema diff` (or `update -n`) first: the plan marks every operation `safe`, `DESTRUCTIVE`, or `UNSUPPORTED`.
</Warning>

Some differences cannot be applied in place: a table declared where a view exists, a changed iterator, or a column whose type or properties changed. Those are reported as `UNSUPPORTED`, nothing is applied, and `update` exits `1`. Adjust the schema file or the table by hand.

### Exit codes

The schema commands report their outcome in the exit status, so a caller never has to parse the output:

| Code | Meaning                                                                                                                    |
| ---- | -------------------------------------------------------------------------------------------------------------------------- |
| `0`  | The target agrees with the schema (including when there was nothing to do)                                                 |
| `1`  | Error: bad arguments, the schema file failed to import, or a table cannot be reconciled                                    |
| `2`  | Changes are pending (`diff`, or `update -n` / `prune -n`)                                                                  |
| `3`  | Refused: the plan is destructive and `--allow-destructive` was not given, or `-f` was needed to confirm without a terminal |

A drift check in CI is therefore one command:

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt schema diff schema.py pxt://acme:main/prod    # 0 = in sync, 2 = drift, 1 = error
```

### Machine-readable plans

`pxt schema diff --json` emits the whole plan as one object: `schema_file`, `catalog_dir`, `in_agreement`, `tables`, `extras`, and a `summary` with one count per resolution. Each entry in `tables` carries its `path`, `resolution`, whether it is `destructive`, and its `ops`:

```json theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
{
  "path": "my_app/docs",
  "model_cls": "Docs",
  "kind": "table",
  "exists": true,
  "resolution": "update_destructive",
  "destructive": true,
  "ops": [
    {"target": "column", "name": "author", "op": "add", "severity": "additive", "destructive": false,
     "description": "column 'author' will be added", "details": {"type": "String"}},
    {"target": "column", "name": "body", "op": "drop", "severity": "destructive", "destructive": true,
     "description": "column 'body' will be dropped", "details": {}}
  ]
}
```

An op's `target` is `column`, `index`, or `table`, and its `op` is `add`, `drop`, or `alter`. `name` is what it acts on -- a column, an index, the differing attribute when the target is a table, or the table path for a drop -- and `details` holds that operation's operands, such as the `type` of an added column. `severity` is `additive`, `destructive`, or `unsupported`; `destructive` is the boolean form of the middle case. A table's `resolution` is `up_to_date`, `create`, `update_additive`, `update_destructive`, or `unsupported`, and one with `create` carries no ops, because the create subsumes them.

These field names and values are the catalog's own, as returned by `TableModel.get_model_diff()`, so a plan read from the CLI and a diff read from Python describe a change the same way.

`update` and `prune` return the same object with a `status` on every table and operation:

| Status    | Meaning                                                                                       |
| --------- | --------------------------------------------------------------------------------------------- |
| `applied` | Carried out                                                                                   |
| `skipped` | Not carried out: a dry run, or nothing to do                                                  |
| `refused` | Not carried out because consent was missing (`--allow-destructive`, or `-f` with no terminal) |

Every path returns the plan, including the ones that refuse before reaching the daemon, so an `--allow-destructive` refusal is as machine-readable as a success: exit `3`, with the offending operations marked `refused` and the rest `skipped`. `prune` reports its drops in a top-level `ops` array, each with `target: "table"`, `op: "drop"`, and the dropped table's path in `name`.

### Pruning

`update` only ever touches tables the schema declares, so tables it doesn't know about accumulate. `diff` lists them as extras; `prune` drops them. A full reconcile is `update` followed by `prune`.

| Flag              | Description                                               |
| ----------------- | --------------------------------------------------------- |
| `-n`, `--dry-run` | List what would be dropped; exit `2` if anything would be |
| `-f`, `--force`   | Skip the `[y/N]` prompt                                   |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt schema prune schema.py my_app -n     # list what would be dropped
pxt schema prune schema.py my_app -f     # drop it
```

Only tables under `TARGET` are considered, so nothing elsewhere in the catalog is affected, and declared tables are never dropped. A view is dropped before its base. Prune never force-drops: a table that something outside the pruned set depends on is left in place and the drop fails, naming what depends on it.

<Warning>
  Pruning is irreversible. Run it with `-n` first.
</Warning>

## Interactive shell

For agentic or scripted workloads that issue many commands in sequence, `pxt shell` amortizes Python startup over the session:

```text theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
$ pxt shell
pxt> ls
path                kind
agent_demo          dir
chess_vids          table
...
pxt> describe chess_vids
...
pxt> exit
```

Inside the shell, every `pxt` command is available unmodified. Errors from one command don't kill the session. Use `help`, `exit`, `quit`, or Ctrl-D to leave.

## Output and scripting

Most catalog commands accept `--json` for stable, machine-readable output (exceptions: `shell` is interactive, `health` is already JSON):

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt ls --json | jq '.entries[] | select(.kind == "table")'
pxt get my_dir/my_table 42 --json | jq '.row'
pxt count my_dir/my_table --json | jq '.count'
```

Without `--json`, output is column-aligned text.

The `schema` commands additionally report drift in their exit status (`0` in sync, `2` pending, `3` refused, `1` error), so a CI gate needs no output parsing at all.

## Serving

`pxt serve` turns tables, computed columns, and `@pxt.query` functions into HTTP endpoints, no application code required. The serve and deploy subcommands import `pixeltable` directly and require the `serve` extra (`pip install 'pixeltable[serve]'`), which pulls in `fastapi[standard]` and `uvicorn`.

<Info>
  `pxt serve` generates a full FastAPI application with auto-generated [OpenAPI docs](https://fastapi.tiangolo.com/features/#automatic-docs) at `/docs`. For programmatic control over the same endpoints, see the [Python serving API](/howto/deployment/serving#quickstart-python) using `FastAPIRouter`.
</Info>

### `pxt serve` subcommands

| Command                    | Description                                                                                             |
| -------------------------- | ------------------------------------------------------------------------------------------------------- |
| `pxt serve <service-name>` | Start a named service defined in a [TOML config](/howto/deployment/serving#toml-service-file-reference) |
| `pxt serve insert`         | Start a single insert endpoint                                                                          |
| `pxt serve update`         | Start a single update endpoint                                                                          |
| `pxt serve delete`         | Start a single delete endpoint                                                                          |
| `pxt serve query`          | Start a single query endpoint                                                                           |

### Quick start

#### Named service (TOML config)

Define your routes in a TOML file and start everything with one command:

```toml theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
# service.toml
[[pixeltable.service]]
name = "my-service"
port = 8000

[[pixeltable.service.routes]]
type = "insert"
table = "my_dir/my_table"
path = "/generate"
inputs = ["prompt"]
outputs = ["prompt", "result"]

[[pixeltable.service.routes]]
type = "query"
path = "/search"
query = "myapp.queries.search_docs"
```

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve my-service --config service.toml
```

```text Output theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
Pixeltable is running on http://localhost:8000
  Routes: 2
  API docs at http://localhost:8000/docs
```

#### Single-endpoint mode

For quick experiments, skip the TOML file and configure one route directly:

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve insert --table my_dir.my_table --path /generate \
  --inputs prompt --outputs prompt result --port 8000
```

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve query --query myapp.queries.search_docs --path /search
```

Single-endpoint mode is meant for development; for production or multi-route services, use the TOML config.

### Serve flags

Every `pxt serve` subcommand accepts these flags:

| Flag        | Type    | Default   | Description                                                          |
| ----------- | ------- | --------- | -------------------------------------------------------------------- |
| `--host`    | string  | `0.0.0.0` | Bind address (overrides TOML `host`)                                 |
| `--port`    | integer | `8000`    | Bind port (overrides TOML `port`)                                    |
| `--prefix`  | string  | `""`      | URL prefix prepended to all routes (must start with `/` or be empty) |
| `--config`  | string  |           | Path to an additional TOML config file to merge                      |
| `--dry-run` | flag    |           | Print the resolved config and exit without starting the server       |
| `--json`    | flag    |           | Emit machine-readable JSON on stdout (startup) or stderr (errors)    |

When `--json` is set, a successful start emits:

```json theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
{"status": "started", "host": "0.0.0.0", "port": 8000, "url": "http://localhost:8000", "docs_url": "http://localhost:8000/docs", "routes": 2}
```

Errors (including port conflicts) emit to stderr:

```json theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
{"status": "error", "code": "EADDRINUSE", "port": 8000, "message": "port 8000 is already in use"}
```

Combine `--dry-run` and `--json` to validate a config in CI without starting a server:

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve my-service --config service.toml --dry-run --json
```

### `pxt serve insert`

Start a service with a single insert endpoint.

| Flag                    | Type    | Required | Description                                           |
| ----------------------- | ------- | -------- | ----------------------------------------------------- |
| `--table`               | string  | yes      | Pixeltable table path (e.g. `my_dir.my_table`)        |
| `--path`                | string  | yes      | URL path (e.g. `/generate`)                           |
| `--inputs`              | strings | no       | Columns accepted from the request body                |
| `--uploadfile-inputs`   | strings | no       | Columns accepted as multipart file uploads            |
| `--outputs`             | strings | no       | Columns returned in the response                      |
| `--return-fileresponse` | flag    | no       | Return the single media output as a raw file download |
| `--background`          | flag    | no       | Run the insert in a background thread                 |

SQL export flags are also available on insert and update routes. See [SQL export flags](#sql-export-flags).

<Warning>
  `--background` and `--return-fileresponse` are mutually exclusive. Similarly, `--export-sql-*` flags cannot be combined with `--return-fileresponse`. These constraints apply to all serve subcommands that support these flags.
</Warning>

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve insert --table my_dir.my_table --path /generate \
  --inputs prompt --outputs prompt result --port 8000
```

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
curl -X POST http://localhost:8000/generate \
  -H 'Content-Type: application/json' \
  -d '{"prompt": "a sunset over the ocean"}'
```

### `pxt serve update`

Start a service with a single update endpoint. The table must have a primary key.

| Flag                    | Type    | Required | Description                                               |
| ----------------------- | ------- | -------- | --------------------------------------------------------- |
| `--table`               | string  | yes      | Pixeltable table path                                     |
| `--path`                | string  | yes      | URL path                                                  |
| `--inputs`              | strings | no       | Non-PK columns to update (PK columns are always accepted) |
| `--outputs`             | strings | no       | Columns returned in the response                          |
| `--return-fileresponse` | flag    | no       | Return the single media output as a raw file download     |
| `--background`          | flag    | no       | Run the update in a background thread                     |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve update --table my_dir.my_table --path /update \
  --inputs prompt --outputs id prompt result
```

### `pxt serve delete`

Start a service with a single delete endpoint.

| Flag              | Type    | Required | Description                                   |
| ----------------- | ------- | -------- | --------------------------------------------- |
| `--table`         | string  | yes      | Pixeltable table path                         |
| `--path`          | string  | yes      | URL path                                      |
| `--match-columns` | strings | no       | Columns to match on (defaults to primary key) |
| `--background`    | flag    | no       | Run the delete in a background thread         |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve delete --table my_dir.my_table --path /delete
```

### `pxt serve query`

Start a service with a single query endpoint.

| Flag                    | Type           | Required | Description                                             |
| ----------------------- | -------------- | -------- | ------------------------------------------------------- |
| `--query`               | string         | yes      | Dotted Python path to a `@pxt.query` or `retrieval_udf` |
| `--path`                | string         | yes      | URL path                                                |
| `--inputs`              | strings        | no       | Parameters accepted from the request                    |
| `--uploadfile-inputs`   | strings        | no       | Parameters accepted as multipart file uploads           |
| `--one-row`             | flag           | no       | Expect exactly one result row (404 on 0, 409 on >1)     |
| `--return-fileresponse` | flag           | no       | Return the single media result as a raw file            |
| `--background`          | flag           | no       | Run the query in a background thread                    |
| `--method`              | `get` / `post` | no       | HTTP method (default: `post`)                           |

The dotted path is resolved at startup; the module is imported automatically.

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve query --query myapp.queries.search_docs --path /search
```

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve query --query myapp.queries.lookup_by_id --path /lookup \
  --one-row --method get
```

### SQL export flags

Insert and update routes can export each successful request as a row in an external SQL database. These flags mirror the [`export_sql` TOML config](/howto/deployment/serving#exporting-rows-to-an-external-database):

| Flag                      | Type                          | Description                                                        |
| ------------------------- | ----------------------------- | ------------------------------------------------------------------ |
| `--export-sql-db-connect` | string                        | SQLAlchemy connection string for the external database             |
| `--export-sql-table`      | string                        | Target table name (required when `--export-sql-db-connect` is set) |
| `--export-sql-db-schema`  | string                        | Optional database schema qualifier                                 |
| `--export-sql-method`     | `insert` / `update` / `merge` | How to write each row (default: `insert`)                          |

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve insert --table my_dir.my_table --path /generate \
  --inputs prompt --outputs prompt result \
  --export-sql-db-connect 'postgresql+psycopg://user:pw@host/analytics' \
  --export-sql-table generations
```

### Serve patterns

#### Validate a config without starting a server

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve my-service --config service.toml --dry-run
```

```text Output theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
Service:  my-service
  Host:   0.0.0.0
  Port:   8000
Routes (2):
  [insert] /generate
  [query] /search
```

#### Override port for local development

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve my-service --config service.toml --port 9000
```

#### File upload endpoint

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve insert --table my_dir.images --path /resize \
  --inputs width height --uploadfile-inputs image \
  --outputs resized --return-fileresponse
```

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
curl -X POST http://localhost:8000/resize \
  -F image=@photo.jpg -F width=640 -F height=480 \
  --output resized.jpg
```

#### Background processing for slow pipelines

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt serve insert --table my_dir.videos --path /ingest --background
```

The endpoint returns immediately with a job handle:

```json theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
{"id": "abc123", "job_url": "http://localhost:8000/jobs/abc123"}
```

Poll `job_url` until `status` is `"done"` or `"error"`.

## Cloud

`pxt db`, `pxt service`, and `pxt org` manage cloud-hosted databases, services, and organizations. All cloud commands require `PIXELTABLE_API_KEY` to be configured (see [Configuration](/platform/configuration)).

All cloud commands accept `--json` for machine-readable output.

### `pixeltable.toml` reference

Cloud operations that affect a database's runtime image or service routes read configuration from `pixeltable.toml` in the current directory.

#### `[pixeltable.database]` — runtime bundle config

Read by `pxt db update-runtime`. Defines which local files to bundle and, optionally, a custom Pixeltable source branch.

```toml theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
[pixeltable.database]
# Include/exclude patterns for project files bundled into the runtime image.
# Glob patterns relative to the project root.
include = ["app/**", "models/**"]
exclude = ["__pycache__", "*.pyc", ".git", ".env", "*.egg-info", ".venv"]

# Optional: build Pixeltable itself from source instead of the published PyPI release.
# Use this to deploy changes from a feature branch before they are released.
[pixeltable.database.pixeltable_source]
git    = "https://github.com/pixeltable/pixeltable.git"
branch = "my-feature-branch"
# rev  = "abc1234"  # pin to a specific commit or tag instead of branch HEAD
```

#### `[[pixeltable.service]]` — service route config

Read by `pxt service create` and `pxt service update`. Each `[[pixeltable.service]]` block defines one named service; `name` must match the service name argument passed to `pxt service create`.

```toml theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
[[pixeltable.service]]
name    = "my-service"
modules = ["app"]        # Python modules imported at service startup

# INSERT / COMPUTE — append a row, trigger computed columns, return outputs
[[pixeltable.service.routes]]
type    = "insert"       # "compute" is an alias for "insert"
path    = "/ingest"
table   = "my_schema/documents"
inputs  = ["text", "title"]
outputs = ["text", "summary", "embedding"]

# FILE UPLOAD — accept multipart/form-data, return a file or JSON
[[pixeltable.service.routes]]
type              = "compute"
path              = "/image"
table             = "my_schema/images"
uploadfile_inputs = ["image"]
outputs           = ["description"]
background        = true           # returns job_url immediately; poll for result

# QUERY — call a @pxt.query function
[[pixeltable.service.routes]]
type   = "query"
path   = "/search"
query  = "app:search_docs"         # module:attr path to a @pxt.query function
inputs = ["query_text", "limit"]
method = "post"                    # "get" or "post" (default: "post")

# UPDATE — mutate existing rows by primary key
[[pixeltable.service.routes]]
type    = "update"
path    = "/update"
table   = "my_schema/documents"
inputs  = ["id", "text"]
outputs = ["text", "summary"]

# DELETE — remove rows matching specified columns
[[pixeltable.service.routes]]
type          = "delete"
path          = "/delete"
table         = "my_schema/documents"
match_columns = ["id"]
```

Route type reference:

| `type`               | Required fields | Optional fields                                                                         |
| -------------------- | --------------- | --------------------------------------------------------------------------------------- |
| `insert` / `compute` | `table`, `path` | `inputs`, `uploadfile_inputs`, `outputs`, `background`, `return_fileresponse`           |
| `update`             | `table`, `path` | `inputs`, `outputs`, `background`, `return_fileresponse`                                |
| `delete`             | `table`, `path` | `match_columns`, `background`                                                           |
| `query`              | `query`, `path` | `inputs`, `uploadfile_inputs`, `one_row`, `method`, `background`, `return_fileresponse` |

### `pxt db`

Manage cloud-hosted Pixeltable databases. A database is a hosted Pixeltable instance with its own compute, storage, and Python runtime.

Database URIs use the form `pxt://org:db`. Valid states: `PROVISIONING`, `STARTING`, `AVAILABLE`, `UPDATING`, `STOPPING`, `STOPPED`, `FAILED`.

The URI argument is optional: with it omitted, these commands use `db_uri` from the Pixeltable config file (see [Configuration](/platform/configuration)), so a project that sets it can run `pxt db status` and friends with no argument.

#### `pxt db create`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db create pxt://myorg:mydb
pxt db create pxt://myorg:mydb --location aws --region us-east-1
```

| Argument / flag | Description                     |
| --------------- | ------------------------------- |
| `db_uri`        | `pxt://org:db`                  |
| `--location`    | Cloud provider (default: `aws`) |
| `--region`      | Region (default: `us-east-1`)   |

Provisions a new database. Polls until state is `AVAILABLE`.

#### `pxt db list`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db list pxt://myorg
pxt db list pxt://myorg --json
```

#### `pxt db status`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db status pxt://myorg:mydb
```

Prints current state, endpoint, location, and timestamps.

#### `pxt db start`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db start pxt://myorg:mydb
```

Wake a stopped database. Polls until `AVAILABLE`.

#### `pxt db stop`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db stop pxt://myorg:mydb
```

Stop a running database (releases compute; storage is preserved).

#### `pxt db update`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db update pxt://myorg:mydb --workers 2
pxt db update pxt://myorg:mydb --cpu 1 --memory 2048 --disk 20
```

| Flag          | Description                    |
| ------------- | ------------------------------ |
| `--workers N` | Number of proxy daemon workers |
| `--cpu N`     | CPU cores per worker           |
| `--memory N`  | Memory per worker in MB        |
| `--disk N`    | Disk per worker in GB          |

Triggers a rolling restart; polls until `AVAILABLE`.

#### `pxt db update-runtime`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db update-runtime pxt://myorg:mydb
```

Reads `[pixeltable.database]` from `pixeltable.toml` in the current directory, packages the project bundle, uploads it, and triggers a CodeBuild image rebuild. Polls until the build completes or fails. Running services are restarted on the new image automatically.

#### `pxt db delete`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt db delete pxt://myorg:mydb --json
```

Deletes the database, its storage, and all services. Irreversible.

### `pxt service`

Manage cloud-hosted services. A service exposes a table in a cloud database as an HTTPS endpoint. Service URIs use the form `pxt://org:db/services/<name>`.

Valid states: `DEPLOYING`, `STARTING`, `AVAILABLE`, `UPDATING`, `STOPPING`, `STOPPED`, `FAILED`.

#### `pxt service create`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt service create my-service --base-uri pxt://myorg:mydb
pxt service create my-service --base-uri pxt://myorg:mydb --workers 2
```

| Argument / flag  | Description                                                                    |
| ---------------- | ------------------------------------------------------------------------------ |
| `name`           | Service name; must match a `[[pixeltable.service]]` block in `pixeltable.toml` |
| `--base-uri URI` | `pxt://org:db[/<dir>]` — database and optional base path prefix for routes     |
| `--workers N`    | Number of workers (default: 1)                                                 |
| `--cpu N`        | CPU cores per worker (default: 0.5)                                            |
| `--memory N`     | Memory per worker in MB (default: 512)                                         |
| `--disk N`       | Disk per worker in GB (default: 10)                                            |

Reads route config from the `[[pixeltable.service]]` block matching `name` in `pixeltable.toml`. Polls until `AVAILABLE`.

#### `pxt service list`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt service list pxt://myorg:mydb
```

#### `pxt service status`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt service status pxt://myorg:mydb/services/my-service
```

Prints state, endpoint, worker count, and timestamps.

#### `pxt service start`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt service start pxt://myorg:mydb/services/my-service
```

#### `pxt service stop`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt service stop pxt://myorg:mydb/services/my-service
```

#### `pxt service update`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt service update pxt://myorg:mydb/services/my-service --workers 2
```

| Flag          | Description              |
| ------------- | ------------------------ |
| `--workers N` | New minimum worker count |
| `--cpu N`     | CPU cores per worker     |
| `--memory N`  | Memory per worker in MB  |
| `--disk N`    | Disk per worker in GB    |

Re-reads `[[pixeltable.service]]` from `pixeltable.toml` for route config changes. Triggers a rolling restart if routes changed; polls until `AVAILABLE`.

#### `pxt service delete`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt service delete pxt://myorg:mydb/services/my-service
```

### `pxt org`

#### `pxt org list`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt org list
pxt org list --json
```

List all organizations accessible to the current API key.

#### `pxt org status`

```bash theme={"theme":{"light":"light-plus","dark":"dark-plus"}}
pxt org status pxt://myorg
```

Show the organization's name, ID, and default database.

## What's next

* [Working with the Pixeltable CLI](/howto/cookbooks/core/working-with-cli): hands-on cookbook for inspect, query, debug, and serve workflows
* [HTTP Serving Guide](/howto/deployment/serving): TOML config reference, Python `FastAPIRouter` API, decorator routes
* [Configuration](/platform/configuration): API keys, storage paths, and environment settings
