Skip to main content
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 — run the services defined in an application file with pxt service. Requires the serve extra (which pulls in fastapi[standard] and uvicorn):
Verify the installation:
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

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

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.

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

Inspection commands

pxt ls

List entries under a directory.
Output of pxt ls -l:
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.

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.

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.

pxt history

Show a table’s version timeline.

pxt status

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

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.

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.

pxt get

Look up a single row by primary key. An Int, Float, or UUID PK column parses its value and rejects one that does not parse. A String PK column keeps the value as typed, so 007 stays 007. Lookup by a PK of any other type, such as Date or Timestamp, is not supported yet and finds no row. The table must declare a primary key. Unstored computed columns are skipped unless requested explicitly via --cols (consistent with rows).
When no row has that key, get exits 1 and prints pxt: no row found for {...} [ROW_NOT_FOUND] on stderr; with --json, stdout still gets the response, with row set to null.

pxt count

pxt errors

List rows where a stored computed column failed. The table must have a primary key (so each failing row can be identified).
For each failed column, a next: line names the pxt recompute ... --errors-only -f that reruns its failed cells, which is the fix once their cause is gone (a provider outage, a missing secret). On a view, a column it inherits is recomputed on the table that defines it. When nothing failed, stdout stays empty and stderr says no failed cells in PATH.

Mutation commands

Every mutation accepts the universal -n/--dry-run and --json flags. The destructive ones (drop, drop-dir, recompute, revert) also prompt [y/N] with a TTY and accept -f/--force to skip the prompt; in non-interactive contexts they exit 3 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.

pxt drop-dir

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

pxt rename

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

pxt mv

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

pxt recompute

Recompute one or more computed columns of a table. Mirrors Table.recompute_columns(), without its where predicate.
Recomputing evaluates the target columns over every row, which can require substantial computing resources. --errors-only limits that recomputation to only the rows that failed. -n reports the target table’s own row count.

pxt revert

Undo recent ops on a table. Each revert undoes one op; --steps repeats.
Revert is irreversible. Run pxt history my_dir/my_table first to see what would be undone.

Project layout

pxt schema and pxt service read a Python file, and the tables they create refer back to the UDFs that file calls. A reference is a module path, so the file has to belong to a project. The project root is the directory with the project configuration, and every local module path is relative to it. pxt init writes that configuration in the current directory:
That file has one entry for each database in the project:
In a directory that already has a pyproject.toml, the same entry is appended there as [[tool.pixeltable.database]] instead, and that section marks the root. Every directory from the root down to a file becomes one component of that file’s module path, so each of those directory names has to be a Python identifier:
Imports resolve from the root down. This is where a single-file recipe and a larger application diverge: a file directly under the root imports its neighbors by their bare names, so recipe.py and functions.py side by side use from functions import .... Once an application moves into a subdirectory, that subdirectory joins the path: from ad_gen.functions import .... A recorded path is how a later process — the daemon, a serving worker, a hosted pod — finds the UDF again, so a command given a file outside any project root is refused. pxt schema check and pxt service check validate a file on its own — it imports without touching the catalog, it declares what the verb needs, and its columns refer to UDFs by paths another process can resolve:

Coding agents

pxt skills install gives a coding agent the Pixeltable skill, which tells it how to build with Pixeltable. Run it at the root of the repository you start the agent in:
The command downloads the skill from the repository’s main branch and prints the version and commit it wrote. A copy that already matches is left as it is. One that differs, such as an older version, is replaced after a yes at the prompt or with -f; without a terminal the command exits 3 instead. It refuses to write through a linked .claude, .agents or skills directory, since the skill would land outside the project. Exit 1 means the download, a read or a write failed; behind a proxy, set HTTPS_PROXY.
  • In Claude Code, /reload-skills loads the skill in a running session and /skills lists it. Other agents load it in a new session.
  • Claude Code started at the repository root loads a copy written in a subdirectory only once it reads a file there, so install at the root.
  • If Claude Code also has the Pixeltable plugin, both copies load, because plugin skills are namespaced: keep one.
  • Commit both directories to give every collaborator’s agent the same copy, and delete them to remove the skill.

Reporting a gap

When Pixeltable cannot do what a task needs, a coding agent drafts a report for the Pixeltable team with pxt feedback:
--kind is bug, gap or docs. The text is one argument of 1 to 4000 characters, in single quotes so the shell runs no `command` and expands no $VARIABLE in it; it may hold newlines and tabs, a carriage return becomes a newline, and any other control character is refused. Without --send, the command prints the destination and every field it would send, and sends nothing. The preview spells out a character a terminal would not show, such as a right-to-left override, as an escape; the report keeps it. With --send, it sends these fields and nothing else: the kind, the text, the Pixeltable version, the Python version, the OS, and the coding agent it runs under, when it can tell. Besides the text, which goes as written, it sends no paths, hostnames, organization or file contents. With DO_NOT_TRACK set to 1, true or yes, --send prints the preview (with --json, an error document with error_code DO_NOT_TRACK), sends nothing and exits 3. PIXELTABLE_SITE_URL, which also points pxt new elsewhere, sends the report to another site; it must use https, except on localhost. A report that fails exits 1, and with --json prints an error document: RATE_LIMITED, with retry_after in seconds when the site gives one; FEEDBACK_UNCONFIRMED, not retryable, after a server error, a read timeout or a dropped connection, when the report may have arrived and a resend may duplicate it; INVALID_CONFIGURATION for a PIXELTABLE_SITE_URL it refuses, even for a preview; FEEDBACK_NOT_SENT otherwise. The text comes from your project, so an agent should show you the preview and wait for your yes before it adds --send. An unexpected daemon failure prints its traceback, followed by a next: line naming pxt feedback --kind bug.

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 to that description. Provisioning an empty target and evolving an existing one are the same command, so there is no separate first-time step. FILE is a path to a Python file. The last argument is a catalog: a local directory such as my_app, or a pxt:// URI. update creates it if it doesn’t exist.

The file

The 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 up a construct:
pxt schema example --brief writes the minimal version instead:
An annotation (name: type) declares a stored column; an assignment (name = expr) declares a computed column. A model with base= becomes a view of that query’s base model. 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 updating

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

pxt schema update

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:
If the plan contains a destructive operation and --allow-destructive is absent, update does not change the catalog and exits 3.
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.
Some differences cannot be migrated 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, update changes nothing, and it exits 1. Adjust the application 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: A drift check in CI is therefore one command:

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 has a path, a resolution, a destructive flag, and its ops:
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 contains 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 a create has 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. pxt schema diff --json-schema prints the JSON Schema of that output. update and prune return the same object with a status on every table and operation: 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 declared by the schema, so tables it doesn’t know about accumulate. diff lists them as extras; prune drops them. A full reconcile is update followed by prune.
Only tables under the last argument 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 with a dependent outside the pruned set is left in place, and the drop fails with an error reporting that dependent.
Pruning is irreversible. Run it with -n first.

Interactive shell

For scripted workloads that issue many commands in sequence, pxt shell amortizes Python startup over the session:
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; Universal flags lists the commands that do not:
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. When another command finishes the job, as after a refusal or a pxt errors listing, stderr names it on a next: line, followed by what running it does:
The command is the one you ran, with -f (or --allow-destructive) added; every refusal for want of consent exits 3, including a destructive schema, service or db update without --allow-destructive. With --json, a command whose output is not a plan prints the refusal on stdout instead:
A person who answers anything but y at the prompt also gets exit 3, and with --json a document with error_code CONFIRMATION_DECLINED and no next. The plan commands (schema, service, db update) keep printing their plan instead; schema update, schema prune and service prune mark the refused operations refused. An unknown command exits 2 and suggests the commands it may have meant, such as pxt db logs and pxt service logs for pxt logs. A request that fails ends its line with the error code, as in pxt: 404 Directory 'nope' does not exist. [DIRECTORY_NOT_FOUND], except a refusal only the user can lift, which prints Cloud’s reason alone (see Plan limits); with --json, stdout gets {"error_code": ..., "message": ..., "retryable": ...}. A daemon that does not start or cannot be reached gives DAEMON_UNREACHABLE; an answer without a code gives HTTP_<status> for a 4xx and INTERNAL_ERROR otherwise. When Pixeltable Cloud says how long to wait, as it does when busy, the --json document adds retry_after in seconds.

Serving

pxt service runs the services in an application file. An application file is any Python source file containing table/view models and either FastAPIRouter instances (which serve routes over them) or a fastapi.FastAPI application of your own. It requires the serve extra (pip install 'pixeltable[serve]'), which pulls in fastapi[standard] and uvicorn.
A service is a full FastAPI application with auto-generated OpenAPI docs at /docs. For the API that defines the routes, see the Python serving API.
One file contains both the schema and the services, so the same file drives both commands:
The last argument is the catalog the models are bound to, so the same file can run against a development directory and a production one.

Serving your own application

A file may supply its own fastapi.FastAPI object instead of leaving Pixeltable to build one. Then the file declares one service, named after its module, and pxt service update serves that application as it is:
The models in the file are bound to the last argument before the application serves, so a handler reaches them by name (Notes.insert(...)). All FastAPIRouter instances in the same source file are expected to be included in the FastAPI application (via include_router()), and the application file still produces a single service:
A router not included in app would never be served, and in that situation pxt service fails with an error. The routes of an included FastAPIRouter are diffed by their declarations (i.e., they take the data types of path parameters into account); the paths served by the application itself are diffed as path strings.

Signing in

Hosted commands need a credential. pxt login, pxt whoami, and pxt key require Pixeltable 0.7.10 or later. There are three: a pxt login session, a pxt new trial (Trial databases), and an API key. You need one of them.
pxt login prints a code and opens a browser. Approve it there, signing in or signing up, and the session lands on this machine. It uses the OAuth device grant, so nothing listens on a port and the browser need not be on this machine: this works over SSH.
A sign-in lasts as long as Pixeltable Cloud honors it: when its token expires, the next command that needs a token renews the session, and nothing on this machine expires it on a timer. pxt whoami reports whether Pixeltable Cloud recognizes the credential, and exits nonzero when it does not; it does not report whether the next command will succeed. A credential that is recognized but not permitted to list organizations, such as a key whose grants do not cover that, still counts as accepted: pxt whoami prints the refusal as a note and exits 0. pxt whoami --offline reports the cached session without asking.
pxt logout forgets this machine’s cached session, or its pxt new trial (Trial databases). When the session has the sign-in service’s session id, pxt logout also opens that service’s sign-out page for the session in your browser, and prints the link when no browser opens. It signs out of both because a browser that is still signed in confirms the next code without naming the account, so signing out of only one leaves you signed in as someone you did not choose. Forgetting the session needs no network. When pxt logout cannot work out the sign-out link, for example because the control plane cannot be reached, it still signs this machine out and warns that the browser was not signed out. Whether the sign-out page itself loads is something only the browser shows.
An API key takes precedence over a sign-in whenever both are present: it is the explicit choice, and what CI runs on. Set one with PIXELTABLE_API_KEY, or with api_key in the [pixeltable] section of your Pixeltable config file; the environment variable wins when both are set. Unlike a sign-in, it does not expire. pxt whoami says which one your commands will actually send.
Signing in proves who you are. If you belong to exactly one organization, pxt login also selects it. A brand-new account belongs to no organization, and every hosted command needs one, so pxt login and pxt whoami print “No organization yet” with the command that creates one, pxt org create NAME, rather than letting the next command fail as an authorization error.

Trial databases

pxt new needs no account. It creates a trial organization with one database, main, and caches the trial’s API key on this machine, so later commands use it without pxt login or an exported key. It prints the database’s URI, the next commands, starting with pxt db diff <uri> --add-config-entry, and a claim link. It never prints the key, and neither does pxt new --json. Until it is claimed, the organization has 1 database and at most 2 services, each on 1 worker with up to 1 cpu, 2048 MB and 10 GB of disk, and 50 GB of media storage: past that, uploads stop. The server sets its expiry, normally 48 hours after creation. Its pods reach the internet on ports 80, 443 and 5432 only, and one network holds at most 10 unclaimed trials at once. Whoever opens the claim link signs in or signs up and becomes the organization’s admin, so keep the link out of shared logs. Running pxt new again prints the same trial, without the claim link, and creates nothing. pxt whoami shows the trial and its expiry. pxt logout removes the trial’s key from this machine and prints the claim link once more. It revokes nothing: the key works until the organization is claimed or expires. An API key or a pxt login session outranks a trial, so with either one configured, pxt new exits 1 and creates nothing. When the trial’s key is rejected, the organization may have been claimed, and its person signs in with pxt login. PIXELTABLE_SITE_URL points pxt new at a site other than https://www.pixeltable.com. It must use https, except on localhost.

Organizations

Creates the organization, its first database and its storage in one call. The name is the namespace in pxt://acme:main, and it must be unique across Pixeltable. It works with a pxt login session or with a personal API key, one created without grants; a key with grants belongs to its organization and cannot create another. Creating one also switches your pxt login session to it: Pixeltable Cloud takes the organization from your session, not from the URI. If the switch fails, the organization exists anyway, and pxt org create warns and says to run pxt login. An API key stays bound to its own organization and outranks a pxt login session, so to work in the new one, use a key created there, or remove the API key and then run pxt login. pxt org list shows the ones you can reach.

Keys

A key is the credential that does not expire, for the places a browser sign-in cannot reach: CI, a cron job, a deployed service. There is one command and two shapes, and the grants decide which.
Without grants, the key acts as whoever created it and reaches whatever they reach: the API key you already know. With grants it belongs to the organization instead, and reaches only what it was granted, so a service you deploy has no more authority than its job needs.
Keys with grants are a preview. Until they are enabled for your organization, Pixeltable Cloud refuses pxt key create --grant with “Keys with grants are not available yet”.
A grant is a verb on a resource, never a bare resource: a service on its own does not say whether the holder may call it or reconfigure it, and those are not the same permission. A service is addressed by its base path and name, as in access:pxt://acme:main/services/my_dir/ingest. manage applies to services only, so manage:pxt://org:db is refused. access and manage are independent: a key that can call a service cannot reconfigure it, and one that can stop it cannot read what flows through it. The secret is shown once, when the key is created, and is never retrievable afterwards. Deleting a key revokes it. Every member of the organization sees every key, can change any runtime key’s grants, and can delete any key, and pxt key list shows who created each one.

Hosted targets

The last argument may be a pxt://org:db URI, and the services then run in that database rather than on this machine. The database needs this project and its tables first, so the order is:
diff, update, prune, stop, restart and list all accept a hosted target. run does not: it serves from the calling process, so it is local by definition. Two verbs differ in meaning against a hosted database, where a stopped service keeps its registration: stop stops it and leaves it there to be started again, while prune forgets it. Against a hosted database, update sends the services it applies in one submission, which Pixeltable Cloud accepts or refuses as a whole: a refusal, such as one for the plan’s service count, leaves every service as it was. Once accepted, each service rolls out on its own, so a failed rollout of one neither stops nor undoes the others; pxt service list shows where each one is. pxt service stop accepts a service address in several forms. A bare name matches the services of the current project, or every local service when the working directory is outside a project. my_dir/NAME stops the service under my_dir, including one in another project, and /NAME stops the service at the catalog root. A bare name that matches more than one service is refused, and the error lists the qualified path of each match.
A name that matches no service, or matches one that is already stopped, is reported as skipped with the reason (not found or already stopped), so stopping a set of services can be repeated safely. pxt service restart restarts a service’s pods on their current code, keeping the service’s registration and endpoint, and accepts the same service addresses as stop, except that a bare name matches every local service of that name, whatever its project. Use it to pick up the current values of its referenced secrets. A hosted service keeps running the code it was last updated to; after pxt db update, run pxt service update to move it onto the new project. Against a local target restart stops the process and starts it again on the same port, so callers keep their address. pxt service retry pxt://acme:main/ingest retries the failed update of a hosted service. Rerunning the same pxt service update also retries it. pxt service logs reads a service’s log and accepts the same service addresses as restart. pxt db logs reads the log of a hosted database’s pod:
A hosted log merges the serving process’s log records, requests included, with its console output, ordered by time. The console output contains the traceback of a service that failed to start. Health probes are left out unless --include-health is given. The log outlives the pod, so the log of a failed deploy can be read after its pod is gone. A line appears in the log a few seconds after it is written. A service running on this machine logs to a local file instead, and pxt service logs reports the path of that file.

pxt service verbs

Like the schema verbs, diff reports drift in its exit status: 0 in agreement, 2 changes pending, 3 refused, 1 error. So a CI gate needs no output parsing. pxt service diff --json-schema prints the JSON Schema of that output. A dry run (-n) of update or prune leaves each operation’s status null in --json, as diff does, where the schema verbs mark it skipped.

Flags

Tracing

--otel emits OpenTelemetry traces from the served application: Pixeltable’s own spans, nested under the request spans of the FastAPI app. It needs the instrumentation package (pip install 'pixeltable[otel]'), and the endpoint and service name come from the OTEL_* environment variables or the [otel] config section, as they do for any Pixeltable process.
Tracing is configured once per process, so it is a property of the deployment rather than of the file: adding or dropping --otel restarts the service, and pxt service diff app.py my_dir --otel reports that restart as a pending change before update performs it.

Background and foreground

update starts one background process per service, each on its own port, and records it so list and stop can find it again. A service that crashes disappears from list with no cleanup step, because a record is only as live as the process it refers to.
run stays in the foreground until you interrupt it and does not register the service for list or stop, so it is a separate command, not a flag on update. Use it as a container entrypoint or a development loop. It serves one service per process, the same as update; name a specific service as a third argument when the file declares more than one:

Restarts

A service binds its models once, when its process starts, so a changed declaration takes effect when pxt service update replaces the process. diff reports which services that replacement would interrupt, and update reports them before it proceeds. Adding a route is additive; changing or removing one stops serving a contract that callers may be using, so it needs --allow-destructive.

Cloud

pxt db and pxt org manage cloud-hosted databases and organizations. Cloud commands need a credential: a pxt login session, a pxt new trial (Trial databases), or an API key (Signing in). To use an API key, create it in the Cloud dashboard (Get an API key) or with pxt key create, then export it as PIXELTABLE_API_KEY. The CLI reads the process environment and does not load .env on its own (Configuration). Every cloud command except pxt logout accepts --json for machine-readable output.

Cloud configuration reference

pxt db diff and pxt db update read the entry of the target database from the project configuration (pixeltable.toml, or pyproject.toml under [tool.pixeltable]), searched for upward from the working directory. With --add-config-entry, either command first appends an entry with only name set to the target URI, unless the project configuration already has an entry for it.

[[pixeltable.database]] — what a project declares about one database

Defines the attributes of a specific Pixeltable database (which may be either the local database, or a cloud-hosted database), including:
  • Which project files to include
  • Which dependencies to include
  • Compute settings
  • Media destinations
  • Telemetry configuration
An entry with no name configures the local database. A hosted database is configured by the entry whose name is its URI.

pxt db

Manage cloud-hosted Pixeltable databases. A database is a hosted Pixeltable instance with its own compute, storage, and Python environment. Database URIs use the form pxt://org:db. Valid states: PROVISIONING, STARTING, AVAILABLE, UPDATING, STOPPING, STOPPED, FAILED. The URI argument is optional: when it is omitted, these commands use db_uri from the Pixeltable config file (see Configuration), so a project that sets it can run pxt db status and the other db commands with no argument. A usage error, such as an unknown verb or a URI that is not pxt://org:db, exits 1: in pxt db, 2 means changes pending (diff) or a change still under way when a wait ends. A failed update names pxt db retry on a next: line, and a wait that stops names pxt db status.

pxt db update

update creates a hosted database and keeps it current afterwards. Put the database in a [[pixeltable.database]] entry, by hand or with pxt db diff pxt://myorg:mydb --add-config-entry, then run update against the URI in its name:
The URI on the command line selects the entry by its name: an entry for another database configures that one, and a target without an entry is an error, unless --add-config-entry appends one. The first run creates the database, builds the image for its environment and uploads the project files that the pods run; every later run applies whatever has changed since. The cloud configuration reference lists everything an entry can declare. update applies a new image if dependencies changed, then uploaded project files if sources changed, then one resize for any changed CPU, memory, disk, or worker counts so the pods restart only once. The settings in the project configuration (the entry’s vars and db_* settings, and sections such as [openai]) reach the database without an upload, and a change to them restarts its pods. Secrets are set with pxt secret rather than from the project: pxt db update refuses a key such as [openai] api_key in the project configuration, and prints the pxt secret set command to run instead. Pixeltable Cloud applies an accepted update, start, stop, restart, retry, image build or delete even if the command exits early. While the command waits, it shows the current step, what the change is waiting for, and the last error being retried. Ctrl-C only stops the waiting, and --no-wait returns once the change is accepted; pxt db status shows the progress. After three hours the command stops waiting and exits with status 2. Rerunning the same update reports the update already accepted instead of starting another, and retries it if it failed. An update is refused if the database changed after update computed its plan; run it again to plan against the new state.

pxt db list

pxt db status

Prints the state, the resources, the project, its metadata version, the current generation and its progress, and the pods. A resource or project shows its desired value next to the current one while they differ.

pxt db start

Wake a stopped database. Waits until it is running, unless given --no-wait.

pxt db stop

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

pxt db restart

Cycle the pods onto their current image and project, without rebuilding or uploading anything. Use it to pick up a secret set since they started. Waits until it is running again, unless given --no-wait. A stopped database is refused; start it instead.

pxt db retry

Retry the failed current update of a database, without changing it. Rerunning the same pxt db update also retries it.

pxt db diff

pxt db diff compares the hosted database to that config entry (see the cloud configuration reference): capacity, the Python image, the project file archive, and the settings — so an edit to a source file is uploaded in seconds, and only a dependency change costs an image build. Exit status is 0 in agreement and 2 with changes pending; nothing is built, resized or set. With --add-config-entry, diff first appends the database’s entry to the project configuration, unless it is already there, and so previews a first deployment; it changes nothing else. pxt db diff --json-schema prints the JSON Schema of that output.

pxt db build-image

Builds the image from the project environment without comparing anything first, which is how you force a rebuild after a failed one; pxt db update rebuilds only when that environment changed. The project files are uploaded with it, unless the database already has that exact archive. Waits until the build completes or fails, unless given --no-wait; the pods restart on the new image and the new sources. When a command reports an unsupported proxy protocol version and this Pixeltable is newer than the hosted database, run this rebuild against the database URI from the failed command. What that image installs is described in What to run after a change.

pxt db delete

Deletes the database, its storage, and all services. Irreversible. Prompts for confirmation with [y/N] on a TTY; otherwise exits with code 3. Pass -f or --force to skip confirmation. A database recreated under the same name is a different database: its workers are keyed by a new internal id, so credentials for the old database no longer work. Treat a delete followed by an update as a new deployment rather than a reset.

pxt org

pxt org list

List all organizations accessible to the current credential.

pxt org status

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

pxt key

create prints the secret once. list never does. update is a delta, not a replacement, so widening a key does not depend on resending everything it already had. Revoking a grant the key never had is an error rather than a no-op, since a typo would otherwise read as a completed revocation. It applies only to a key that has grants: one that acts as you has nothing to change. Names are unique per organization across both shapes, so pxt key delete NAME never has to choose between two keys. Any member of the organization can delete any key.

pxt usage

Shows this month’s usage of the organization your credential belongs to: the plan and the days left in the month (UTC), the cost so far against what the plan includes, each meter, and what the organization holds against its plan’s limits. Any member can run it.
Costs are at Pro’s rates and bytes are decimal GB. Compute lags up to an hour, storage and egress up to a day. On Pro, the cost line ends with an estimate of what bills past the included credit.

Plan limits

When Pixeltable Cloud refuses a request past your plan’s limits (PLAN_LIMIT), for an unpaid subscription (PAYMENT_REQUIRED), or because the media store is full (STORE_FULL), the command prints the control plane’s reason alone, which ends with the fix, and exits 1. A pxt:// connection to a stopped database fails at once with the command that starts it.

pxt secret

An org secret applies to every database in the org. A database secret applies to that database and wins on a key collision. list prints names, never values. list prints one table for the org and its databases. Without a URI it covers your credential’s org; pxt://myorg:mydb narrows it to the org and that database. A database secret with the same name as an org secret is marked overrides an organization secret, and the org row stays in the table:
With --json, each row is an object with key and scope, plus "overrides_org": true on a database secret that overrides an org secret. With nothing set, list prints No secrets for pxt://myorg. (or the database’s URI), and list --json prints []. set and delete print the keys they changed as the same KEY and SCOPE rows, without NOTE; with --json, as key and scope objects. Earlier releases printed bare key names, and --json printed an array of strings. A running database or service uses the values from its startup. Run pxt db restart for the database’s tables process and pxt service restart for each service. A database or service started afterwards reads the current value at startup. set and delete name each of these on a next: line, for every running database the secret reaches (one for a database secret, all of the organization’s for an org secret) and every running service of those databases, including one whose database is stopped and one whose last roll failed, since it may still serve on its previous pods; a stopped one needs no restart.
A [[pixeltable.database]] entry no longer accepts secrets. A project config that still has secrets.openai_api_key = 'env:OPENAI_API_KEY' fails to load:
Delete the secrets.* lines and set each value with pxt secret set instead. The values were never stored in the file, so nothing is lost.

What’s next

Last modified on October 22, 2026