Skip to main content
Documentation

Updating an app

Moving an existing app onto a newer SDK with the read-only `app update` guide.

On this page

An app's worker code is a copy, scaffolded once and owned by you. app update inspects that copy and returns a checklist for the running CLI's SDK release. It never edits the app: you choose and apply every dependency, source, and policy change.

The sequence#

Ask the target CLI for guidance

npx deepspace@latest app update --json
bash

Run the target CLI, not only the version the app has installed. Its own package version is the target, and it owns that release's migration guidance.

Read the whole checklist

Inspect status, dependencies, migrations, manualInstructions, and the ordered steps. The command always reports writes: []: it does not rewrite package.json, stamp migrations, install packages, or scan unrelated repository files.

Apply and validate the app-owned changes

Make each dependency edit and migration change that applies to this app. Install only after reviewing the dependency plan, then type-check and test:

npm install
npm run type-check
npx deepspace test run
bash

After a migration passes, add its id to deepspace.migrations.json. If the named seam does not exist in this app, record the id as not applicable so a later run does not repeat it.

Review, commit, and redeploy

git diff
git commit
npx deepspace deploy
bash

A deploy is what makes the updated dependency and app-owned code reach the live app. A deploy guard may still refuse an incomplete retrofit; fix the stated cause rather than marking its migration complete early.

Reading the result#

FieldMeaningWhat you do
status / readyaligned is the only ready state. guidance_available means work is listed; dependency_unverified means a local/VCS SDK is developer-owned; cli_version_behind means this CLI is older than the app; version_gap_too_wide means the releases must be reviewed one at a time.Branch on the status, then read steps. These are successful guidance states, not partial writes.
dependencies: [{ dependency, from, to }]Manual edits needed in package.json. A published SDK also names the compatible direct ai dependency when the app declares one.Make the edits together, review the manifest, then run the detected package manager's install command.
migrations: [{ id, description, files, guidance }]Outstanding release changes according to the app-owned ledger. files are the seams to inspect, not files the CLI searched or changed.Apply the guidance where relevant, validate it, then add the id to deepspace.migrations.json.
manualInstructionsA choice or verification the CLI cannot safely make, such as an app-owned users-schema visibility policy or an unverifiable local SDK.Decide explicitly; never treat an empty write set as permission to skip it.
stepsThe ordered human checklist assembled from the fields above.Follow it in order and commit only after type-checking and testing.
writesAlways [].Use your normal editor and review workflow; there is no apply mode or install action.

A malformed package.json or deepspace.migrations.json refuses with invalid_package_manifest or invalid_migration_manifest. The command will not repair either source of truth. A version gap that is too wide returns ok: true, ready: false, and status: "version_gap_too_wide"; move through the intervening releases' changelog rather than asking one release checklist to cover the whole history.

Scaffolds that predate server-minted ids#

Older SDKs minted DEEPSPACE_APP_ID locally, at scaffold time, and no server ever registered it. Ids are server-minted at registration now, and an existing unregistered id cannot be claimed. Such an app shows up in one of two ways on the newest CLI:

  • deploy, push, or secrets refuse app_not_registered - the id no server has registered.
  • app init refuses app_not_registered too, instead of the old "already initialized", and ships the fix as its action.

The fix is the same in both cases:

npx deepspace@latest app init --new-id
bash

This registers the directory as a fresh app under your account: a new id in wrangler.toml, new data, new secrets store, and new registration. There is no old platform state under the unregistered id. Commit wrangler.toml (the command offers that commit as its next action when needed), then run app update again.

Two related refusals from the same era are app_id_env_mismatch (the browser bundle still carries an id frozen at scaffold time in src/constants.ts) and app_id_define_unsubstituted (constants moved to the build-time define without the vite.config.ts half). The deploy refusal prints the three-file retrofit, and app update reports the matching 2026-08-build-injected-app-id guidance. Apply all three parts, validate them together, then record the migration id.

Next steps#