App identity
The immutable app id, name leases, renames, undeploy, and ownership transfer.
On this page
Every app has an immutable id — app_ followed by 26 characters — minted when the app is created. It lives in wrangler.toml:
[vars]
DEEPSPACE_APP_ID = "app_01HZXYABCDEFGHJKMNPQRSTVWX"
The id is the app's durable identity. Data, secrets, collaborators, billing, and custom domains all address the app through it. For an identity-migrated app, the backend maps the id to a permanent private resourceId that still owns the physical stores — you never handle the resourceId directly; the app id is the one identity you work with.
Id versus name#
The name field in wrangler.toml is only a lease on <name>.app.space. It can change without the app losing anything: the id stays, and everything keyed to the id travels along. Treat names as URL labels; treat the id as the app.
In scripts and automation, always prefer the id. A name can be renamed out from under a script; the id cannot.
Where ids come from#
There are exactly three mints, and they all end in the same place — DEEPSPACE_APP_ID in wrangler.toml:
- Scaffold —
npm create deepspacemints one into the new project. - First deploy —
npx deepspace deployin a repo without an id mints one on the spot and writes it towrangler.toml. Commit that change; it is the app's identity record. - Explicit init —
npx deepspace app initstamps an id into an existing repo without deploying.
Forking with --new-id#
npx deepspace app init --new-id
--new-id writes a fresh id for a fork: same code, separate data, separate secrets store. Use it when a cloned repo still identifies someone else's app — the tell is a "registered to another user" error on secrets or deploy.
--new-id does not change Wrangler's name or reserve a URL. Pick the fork's own name before its first deploy, or the deploy will try to claim the original's lease.
Environments are separate apps#
Each [env.<name>] block in wrangler.toml is its own app with its own id, its own Durable Objects, and its own secrets store. Mint that identity with npx deepspace app init --env <name>, or let the environment's first deploy mint it. Remove one with npx deepspace app undeploy --env <name>.
Renaming an app#
Change name in wrangler.toml and deploy. The CLI asks you to confirm the rename (or pass --rename to pre-confirm):
npx deepspace deploy --rename
The new URL serves immediately and the old one stops. Data, secrets, collaborators, and custom domains follow the id, untouched. In particular, an attached custom domain keeps routing without any re-attach.
The old name stays reserved for you for 30 days while links drain, then frees up for anyone. Within that window you can rename back at will; after it, the name is fair game.
Listing your apps#
npx deepspace app list # every app you can access: id, URL, role, deploy state
npx deepspace app list --json
app list shows every app you can access — the ones you own and the ones shared with you as a collaborator — with a ROLE column telling them apart. Use it to recover an id you have lost track of — including when a quota refusal names an app you no longer recognize.
Undeploy and revival#
npx deepspace app undeploy # resolves DEEPSPACE_APP_ID from the nearest wrangler.toml
npx deepspace app undeploy --env staging # that environment's app
npx deepspace app undeploy <app-id-or-name> # positional, registry-resolved — works from anywhere
npx deepspace app undeploy --yes # skip the confirmation
The positional form takes an app id or a live subdomain name, so you can undeploy an app without being in its checkout. A positional target overrides --env; omit both to fall back to the surrounding wrangler.toml.
Undeploy confirms at an interactive terminal, defaulting to No. At a TTY the command asks before the URL goes dark, and the question is the table below in one sentence: it names the app (Take my-app (app_…) offline now?), says the URL stops serving immediately and the data — records, messages, canvas state, cron history — is destroyed with the worker, and that secrets and the registration stay with the name reserved for 30 days. Declining refuses with the code undeploy_declined and changes nothing. --yes skips the prompt. Scripts and agents never see it: a non-TTY stdin or --json runs straight through, because the invocation itself is the consent — so an automated undeploy cannot hang waiting for an answer nobody will type. Read the sentence back to whoever asked before answering Yes: it is the only place the loss is stated at the moment of the decision.
Undeploying twice is a no-op the second time, and reported as one: alreadyUndeployed: true with an empty releasedHosts (human: "was already offline — no URL was serving, so nothing changed"). A real takedown lists the released hosts.
Undeploy deletes the Worker script and releases its routes, then best-effort deletes the recorded auto-provisioned Cloudflare resources. There is no separate data-purge step: the app's Durable Objects — records, messages, canvas state, cron history — are destroyed with the Worker script as a consequence of its deletion, and data in auto-provisioned resources can be lost too. What goes and what stays:
| Removed | Retained |
|---|---|
| The deployed Worker | The app id and registry identity |
| Its routes and subdomain serving | Collaborators |
| Durable Object data — records, messages, canvas, cron history | The secrets store |
| Auto-provisioned resources (best effort; their data can be lost) | The cloud Git repository |
Because identity survives, a later deploy from the same repo revives the app. Active apps count against your tier's cap; undeployed ones do not — and revival is quota-checked, so reviving can be refused with app_quota_exceeded until you undeploy something else.
Only the owner (or a platform admin) can undeploy. Collaborators cannot — destructive access is deliberately narrower than deploy access.
Ownership transfer#
Transfer is a two-step handshake, GitHub-style: nothing changes until the recipient accepts.
# Owner:
npx deepspace app transfer offer teammate@acme.com # 7-day offer; --replace swaps a pending one
npx deepspace app transfer status
npx deepspace app transfer cancel
# Recipient:
npx deepspace app transfer accept --app app_01HZ… # the commit point — they own it now
On acceptance the app moves as-is — data, secrets, routes, custom domains — and only the owner (and billing) changes. The recipient must have signed in to DeepSpace at least once; offering to an unknown email fails with user_not_found.
An offer expires after 7 days. Re-offering to a different email refuses with confirmation_required unless you pass --replace, which swaps the pending offer wholesale.
Who can do what#
| Action | Who |
|---|---|
transfer offer | Owner (or platform admin on the owner's behalf). Collaborators can never start one — they could otherwise transfer the app to themselves. |
transfer status | Owner and the named recipient only |
transfer cancel | Either party |
transfer accept | The named recipient only |
undeploy | Owner or platform admin |
A collaborator who is the named recipient participates as that recipient, not through the collaborator role. Platform admins operate deploy, secrets, and undeploy through their override, but the transfer handshake stays owner-scoped — the one exception is an operator opening an offer on behalf of an unreachable owner, and even then the offer is recorded as the owner's.
See also#
- Collaborators — who can ship the app without owning it
- Source control — the app's one authoritative Git repository
- Custom domains — domains bind to the id, not the name
- Command reference:
app