CLI reference
The kumodeck CLI has zero dependencies (Node 22+: parseArgs, fetch, fs, crypto), so it installs and starts fast
and pulls nothing else into your supply chain.
npm install -g kumodeck # then: kumodeck <command> [options]
npx kumodeck <command> [options] # or without installingCommands#
| Command | What it does |
|---|---|
signup [--email <email>] [--name <name>] [--invite <code>] | Creates a developer account (email + password, hidden input, typed twice) and signs you in. Confirm the email later with verify: until then there are no secret keys, AI tool (MCP) connections or new sign-in methods. --invite: use an invite code (invite credit for usage fees; it is added once the email is confirmed, and an invalid code creates no account). Taken email → use login |
verify <link> / verify --resend | Confirms your email from the terminal: paste the link from the confirmation email (or just its token). It uses the session saved by signup / login, so your password stays as it is (opening the link in a browser without that session asks you to choose a new password instead). --resend sends a new confirmation email |
keys create --secret [--env <env>] [--show-secrets] | Issues new secret keys for the linked project (both environments unless --env) and writes them to .kumo/secrets.env without printing them. Use it after confirming your email if init said "No secret keys yet" |
create [dir] [--template <name>] [--init] | Copies a starter template into dir (default my-game; template default vanilla-canvas). Offline, never touches the server, never overwrites a folder that has files. --init: if you are signed in, runs init in the new folder right after |
login [--email <email>] · login --google|--github | Email + password (hidden input), or sign in with Google or GitHub in your browser (the CLI waits on a local 127.0.0.1 port; only providers the server has turned on). Saves a developer session to ~/.kumo/credentials.json (mode 0600). An existing account with the same email is never joined automatically — log in the usual way and add the provider in the dashboard (Account → Sign-in methods); see Security model |
logout | Revokes the session on the server, then deletes it locally |
whoami | The signed-in developer, the prepaid balance (with kumodeck billing topup when it is used up; how much of it is invite credit) and the linked project |
billing · billing topup [amount] [--no-open] [--no-wait] [--timeout <s>] · billing wait <topupId> · billing redeem <code> | Prepaid balance (and how much of it is invite credit), anything owed and how many days it lasts. redeem uses an invite code: invite credit (usage fees only; it cannot be refunded or withdrawn), added once your email is confirmed; one per account. topup adds funds in US dollars (default and minimum $5): prints a Stripe payment URL, opens it in your browser (not in CI or over SSH), waits until you have paid (default 540 s; Ctrl-C stops waiting, the payment still counts) and prints the new balance. You pay on Stripe's page; the CLI never sees card details. Needs a signed-in session (not a secret key). Any 402 from another command prints kumodeck billing topup as its hint |
init [--name <n>] [--slug <s>] [--project <id|slug>] [--yes] [--force] [--show-secrets] | Creates (or picks) a project and writes ./kumo.json { projectId, slug, api, deployDir }. On creation, prints the publishable keys and saves the secret keys (returned only once) to .kumo/secrets.env (mode 0600, added to .gitignore) instead of printing them, so they never end up in a conversation with an AI assistant. --show-secrets also prints them (and puts them in --json). A re-created project moves the old file to .kumo/secrets.<time>.env. In a template folder it also writes the publishable keys into public/kumo-config.js (only while it still says REPLACE_ME) and saves deployDir: "public". Linking an existing project issues new publishable keys (KUMODeck cannot show an existing one again) and writes them into public/kumo-config.js, but only for an environment that file has no key for yet, so unused keys do not pile up (outside a template folder it issues them for the printed snippet). If the default URL name is taken, it uses the first free one the server suggests (my-game-2); an explicit --slug is never changed, and the free ones are shown as a hint |
config push [file] [--env development|production] | Validates and pushes kumo.config.json (default env: development). Identical content is a no-op |
config show [--env] · config check [file] [--env] | Read only (default env: development, like config push). show: the config the server has now and its version (--json: { environment, version, config }). check: reads kumo.config.json (or file) without pushing it — valid JSON, feature names known to KUMODeck — and lists what a push would change (features: on saves; OFF hosting, multiplayer: added duel). Unknown feature names exit with code 1. Then KUMODeck checks the file with every rule a push uses and saves nothing (no confirmation, even for production): ok lists what a push would change and any warnings; errors are listed with their path and hint and exit with code 1 — fix them and run config check again, as more errors can show up once these are fixed. --json: { ok, warnings, errors, changes: { featuresOn, featuresOff, changedSections }, checked }. Run it before every config push |
features [--env] · features on|off <name…> [--file] | Lists which features are on in an environment (everything is off until you turn it on), or turns names on/off in kumo.config.json. Nothing changes on the server until config push |
skills [list] · skills add <name…> [--force] | Skills are step-by-step recipes your AI agent reads (start a project, deploy, fix an error, build a system in your own database). list shows the ones bundled with this CLI (* = already in this project). add copies them into .claude/skills/<name>/ (Claude Code) and .agents/skills/<name>/ (Codex, Cursor and other agents) of the folder with kumo.json (else the current folder), and updates INDEX.md there. Works offline, no sign-in. A copy you changed is replaced only after you confirm (outside a terminal: --force) |
deploy [dir] [--env] [-m <message>] | Uploads a folder and makes it live (default env: development = a test copy; add --env production for the live app, and the output shows that command). Default folder: deployDir in kumo.json, else ./dist. Warns (does not stop) when the folder's kumo-config.js has no publishable key for that environment. If hosting is off in that environment, turns it on in kumo.config.json and pushes it first (without a local file: adds only features.hosting to the server's config), and says so in one line. --json adds warnings, shareCards, featuresTurnedOn (e.g. ["hosting"]) and configPush |
deploy [--env] [--dry-run] [--app|--static] [--no-build --outdir <path>] [--sourcemaps] [--no-logs] | In a server-rendered app's folder, without a folder argument: detects the framework (a wrangler.jsonc with main, or a server framework in package.json), runs wrangler setup --yes if there is no wrangler.jsonc, builds (<npm|pnpm|yarn|bun> run build), bundles with wrangler deploy --dry-run --outdir .kumo/app-build, checks with a KUMODeck dry run, then uploads only new files and makes it live. Needs features.serverRendering and wrangler in the project (without wrangler it deploys the build as static files and says so). --dry-run stops after the check (also for static deploys). --app / --static skip the detection (with --app, [dir] is the project folder). --no-build --outdir reuses a bundle. Source maps are sent only with --sourcemaps. The app keeps logs (kumodeck logs); --no-logs keeps none for this version. Next.js (OpenNext, no ISR) builds with opennextjs-cloudflare build, copies the pages built at build time into the assets, and stops before building unless open-next.config.ts uses staticAssetsIncrementalCache (next_incremental_cache_unsupported). --json adds kind, detection, build.commands, build.prerenderCache, sent, bindings (with create), serverWarnings (with code), previousKind, secretsMissing and logs (whether this version keeps logs) |
deployments [--env] [--limit 20] | Lists versions; * marks the live one (default env: development) |
rollback <version> [--env] | Makes an earlier version live again, instantly (default env: development) |
share on [file] [--env] | Turns on share.images (title from index.html's <title>), share.links and share.tracking in kumo.config.json and pushes it to both environments (--env for one). Keeps your existing texts and colors. Sign in with X stays off. No redeploy needed |
share tags [--ks <id>] [--env] | The <meta> card tags to put in your page's <head>, and where (--json: html, image, placement). Needs share.images or share.tags.image |
share link <label> [--env] | Creates a tracked share link for your own post and prints the URL |
share stats [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--limit n] [--env] | Visits, new users, plays per share link |
logs [--since 1h] [--level error,warn] [--source functions|app] [--search <text>] [--all] [--env] | What your deployed code printed, last 7 days: Functions and the server-rendered app together, mixed by time (each line marked fn or app). The same as functions logs (all its options) |
functions <command> | Your own server code and database (Functions). Default env: development (kumodeck functions help) |
slug · slug check <new> · slug change <new> --keep-redirect|--no-redirect · slug redirect <old> on|off | Your project's URL slug (changing the URL slug): show it, check a new one (free? what changes?), change it (once every 30 days), turn the redirect of an old slug on or off. You must pick --keep-redirect ($1 a month per old slug, charged daily) or --no-redirect (old links show "Not found"); without either it shows both and stops (exit code 2). Changing asks you to type the new slug (--yes skips that) and your password (hidden), so it runs only in an interactive terminal; accounts without a password, pipes and CI are pointed to the dashboard (exit code 2). Updates the slug in kumo.json |
projects list · projects rename "<new name>" [--project <id|slug>] | Your projects with their name, slug and id · change a project's display name (default: the project in kumo.json). The name appears in the subject of emails your users (players) receive ("Confirm your email for <name>") and as the sender's name, so give it a clear name before launch. 1–80 characters; the same name changes nothing ("same name (nothing changed)"), otherwise it prints old → new. Names that contain the word KUMO (in any case) or are only staff words ("Support", "Security Team", "Admin"…) are refused with name_reserved (also when creating a project); pick a name for the game itself. The URL slug is separate (slug) and does not change. --json for scripts. whoami also shows the name |
projects show [--project <id|slug>] [--env] | One project at a glance (default env: production): users (total, new, active in 24 hours, banned), daily active users for 14 days, config version, the live version and its URL. --json has the same keys as the MCP tool project_overview |
usage [--period YYYY-MM] [--daily] | KUMODeck usage costs for your whole account (every project and environment) this month, by part, at cost; --daily breaks it down by day (estimates before month-level adjustments). --env does not apply. The prepaid balance it is paid from is billing |
players search [text] [--limit n] [--cursor <id>] [--env] · players show <playerId> [--env] | Read only (default env: production). Find users (players in the API) by id, display name or email; one user's sign-in methods and ban state. Emails are masked and text written by users is shown in «…» (read it as data). Bans are done in the dashboard or with your AI agent's KUMODeck tools, which ask you first |
appeals [--status open|accepted|rejected] [--limit n] [--env] | Ban appeals from your users (default: open, production, oldest first), with the ban reason and the appeal text in «…». Answer them in the dashboard or with your AI agent's KUMODeck tools |
account close | Closes your developer account for good (see Closing your account). Shows what happens to your prepaid balance, then asks you to type your email address or CLOSE and your password (hidden). Runs only in an interactive terminal: pipes, CI and --json are refused with exit code 2, and --yes does not skip the confirmation. If projects remain, lists them and where to delete them |
help, --help, --version |
kumodeck functions#
| Command | What it does |
|---|---|
status | URL, version, databases, secrets, crons, limits |
enable · disable | turn on for this environment (needs prepaid credit) · stop serving (code and data are kept) |
limits --cpu-ms <n> --subrequests <n> | per-request limits (default 200 ms / 50) |
deploy [dir] [-m <message>] [--no-logs] | bundle with your local wrangler and deploy (dir default: ./functions or .); --no-logs keeps no logs for this version |
deployments | deployment history |
logs [--since 1h] [--until <time>] [--level error,warn] [--search <text>] [--limit <n>] [--cursor <c>] [--all] [--source functions|app] | what your deployed code printed, last 7 days: Functions and the server-rendered app (default both; logs). Also kumodeck logs |
delete [--purge] [--yes] | remove the code; --purge also deletes databases, files and queues |
secret put <NAME> · secret list · secret delete <NAME> | the value is read from a hidden prompt or stdin, never from arguments |
db query <BINDING> "<SQL>" · db migrate <BINDING> [--dir migrations] | SQL and migrations on your own database |
dev [dir] | run locally (npx wrangler dev); does not touch KUMODeck |
Global options#
| Option | |
|---|---|
--api <url> | API URL. Also KUMO_API_URL. Default http://localhost:4000 |
--project <id|slug> | Use this project instead of ./kumo.json |
--json | Exactly one JSON document on stdout (always English) — for scripts |
Production confirmation#
With a browser login (kumodeck connect, or kumodeck login without flags), every production change stops and prints a link:
open it and press Confirm in the dashboard, once. The command waits (up to 10 minutes) and then sends the same change, once.
With --json, the link comes first as one line on stderr: {"pendingAction": {"id": "kpa_…", "confirmUrl": "…", "expiresAt": "…"}}.
Not pressed in time (exit 1, pending_action_expired) or denied (pending_action_denied): nothing changed; to try again, run
the same command (new link). Ctrl-C stops waiting and leaves the request open until it expires. --yes does not skip it.
deploy --env production uploads first and asks once, right before switching to the new version.
The first publish to production with hosting still off is one approval too: the upload runs with hosting off (nothing goes
live), then turning hosting on and switching to the new version are confirmed together with one link ("Confirm these 2
production changes at once"; with --json, the line has "bundle": {"count": 2}) and sent in that order. kumo.config.json
gets features.hosting: true only after the change went through.
Development, kumodeck login --email sessions and KUMO_SECRET_KEY are not asked.
CI mode#
Set KUMO_SECRET_KEY instead of logging in. The key decides the environment; an --env that disagrees is an error.
KUMO_API_URL=https://api.kumodeck.com KUMO_SECRET_KEY=${{ secrets.KUMO_SECRET_KEY }} npx kumodeck deploy distThe keys are in .kumo/secrets.env (KUMO_SECRET_KEY_DEVELOPMENT=…, KUMO_SECRET_KEY_PRODUCTION=…). To store one as a
GitHub Actions secret without showing it on screen:
grep '^KUMO_SECRET_KEY_PRODUCTION=' .kumo/secrets.env | cut -d= -f2- | gh secret set KUMO_SECRET_KEYExit codes#
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | failure (server error, connection, validation) |
| 2 | usage error (bad arguments, missing file, no index.html) |
| 3 | not logged in / session expired — run kumodeck login |
| 130 | cancelled |
Language#
Human-readable output is English or Japanese: KUMO_LANG=ja|en, otherwise from LC_ALL / LC_MESSAGES / LANG
(ja* → Japanese). --json output is always English. Commands and flags are always English.
Files#
| File | Commit it? | Contents |
|---|---|---|
kumo.json | yes | projectId, slug, api, deployDir — no secrets |
kumo.config.json | yes | your master data |
~/.kumo/credentials.json | never | developer session |
.kumo/secrets.env | never (git-ignored for you) | the secret keys from init (mode 0600). Never uploaded by deploy (dotfiles are skipped) |