9d9

CLI

The 9d9 CLI: push a directory, manage deploys, attach domains.

Install

No install needed for one-off use — npx grabs the latest:

npx @9d9dev/cli deploy ./dist

For repeat use, install globally so the 9d9 command is always on PATH:

npm i -g @9d9dev/cli

Authenticate

Generate an API key in your dashboard at Settings → New key. The secret is shown once. Save it locally:

9d9 set-key ak_xxx --org=org_xxx

Config is written to .9d9.json in the current directory. Subsequent commands walk up from cwd to find it — so each repo gets its own org binding. The file is local; add it to .gitignore.

Commands

9d9 deploy [dir]

Walks dir (defaults to .), uploads files in parallel, commits a manifest, atomically activates the deploy.

  • Skips dotfiles and node_modules.
  • Content-hashes each file (sha256, first 16 hex chars) — used as the manifest fingerprint.
  • Detects 404.html and registers it as the deploy's not-found page.
  • Concurrency: 6 file uploads in flight.
  • 25 MB per-file limit.
9d9 deploy ./dist
# Deploying 13 file(s), 127.2 KB total...
# Deploy dep_qXpgSbWcNGfoWy3PxJfE24Ls created.
#   10/13
#   13/13
#
# Active. Deploy dep_qXpgSbWcNGfoWy3PxJfE24Ls is live.
#   https://your-slug.9d9.dev/

9d9 deploys [list]

Lists recent deploys for the current site.

9d9 deploys
# active      dep_qXpgSb...    13 files  2026-05-30T05:26:46.000Z
# superseded  dep_DCAcX6...     4 files  2026-05-29T22:14:55.000Z

9d9 set-key <key> [--org=<org_id>]

Saves the API key and org ID locally.

9d9 status

Prints the current local config (token shown truncated).

9d9 logout

Clears local credentials.

Multiple sites on one machine

Each repo holds its own .9d9.json, so switching sites means switching directories — no global state to forget about. For CI / scripted use, override per-invocation with env vars: NINEDENINE_API_KEY, NINEDENINE_API_URL.

Rolling back

The Deploys tab in the dashboard lists every deploy with an "Activate" button. Old deploys' files are preserved in R2 for 7 days. After that they're garbage-collected by a daily cron.