Prized docs

Environments.

What a new box inherits, kept as versions on your account. Repos to clone, a setup script, env vars, secret files, and which of your credentials a box may receive.

What a box receives

Pick an environment at create time (the dashboard form, or environment on POST /api/v1/boxes), or let the default apply. The box receives, in order:

ItemWhenWhere it lands
Env varsfirst boot + live/etc/doppel/box-env.sh, sourced by every login shell
Reposfirst boot~/<dir> (default: the repo name), cloned as your box user, blocking repos first
Setup scriptfirst bootRuns once as your box user in your home, after the repos; log in /var/log/doppel-setup.log
Secret filesfirst boot + live~/<path>, owned by your box user, mode 0600 unless you set another

Env vars and secret files are kept live: changes reach the box within seconds, and new login shells see them. Repos and the setup script run at first boot only. Secret files travel over the box's authenticated channel, never in the launch configuration, and the dashboard and CLI show only their path and size.

The default environment

Nothing is a default until you mark one: "Make it the default for new boxes" when creating, "Make default" on its card, or prized environments default <name>. A box created without naming an environment then takes it; none (dashboard) or environment: null (API) opts out. The box your plan launches, a restore, and a fork never inherit one.

Versions and upgrade

Every save that changes what a box inherits mints a new immutable version; a rename or a new description does not. A running box keeps the version it was created from until you upgrade it. A name is unique within the workspace regardless of case (prod and Prod are one name), so --environment on the CLI always means the same environment for everyone.

Versions
environment ml        v1 ──── v2 ──── v3 (latest)
                               
box kiwi (created v1)  ●────────┼──── upgrade ──▶ v3
box mango (created v2)          ●──── stays on v2 until upgraded

prized environments upgrade <name> (or Upgrade on the environment or a box's page) pins boxes to the latest version:

  • Env vars and secret files re-apply within seconds; a dropped file or var is removed from the box.
  • Repos and the setup script do not re-run.
  • A safe-for-third-parties version makes the box restricted, permanently: mounted secrets stop resolving, its phone password is revoked, device keys leave.
  • A box whose own vars would not fit the launch budget is skipped (named in skipped) and keeps its version.

Each environment keeps up to 50 versions; older ones no live box pins are pruned. Deleting an environment leaves its boxes on the version they carry.

Safe for third parties

A box built for someone else (a contractor, a demo, an agent you do not fully trust) should hold none of your credentials. Switch on Safe for third parties on the environment, or tick Restricted when creating one box. Four channels close:

ChannelWhat is refused
Secret mountsPOST /api/v1/boxes/:id/secrets answers 409 box_restricted; no connector or secret can be mounted
Device keysNo member device SSH keys reach the box; desktop apps that rely on them cannot log in
Phone accessPOST /api/v1/boxes/:id/mobile-ssh answers 409 box_restricted
CLI credential handoffprized agents handoff and the agent, secrets and data steps of prized setup refuse with CHECK_FAILED (exit 5); prized setup also keeps .env files out of every sync session to the box

Env vars still apply, but a safe environment cannot carry secret files (safe_environment_has_secret_files), and a restricted box never receives any: an environment's secret files are left out of a restricted box's setup at create and on every upgrade, whichever environment it runs. Restricted is one-way for a box: set at create (restricted: true, or a safe environment), by an upgrade onto a safe version, or inherited by a restore, and never unset. The three channels can also be closed one at a time on an environment without restricting the box.

Repos

A repo is owner/name (GitHub) or an https:// clone URL, with an optional branch, a directory under your home (default: the repo name), an optional setup script run inside the clone, and a blocking flag: blocking repos clone before the others and before the environment's setup script.

Clones are plain https, so no credential rides a URL into .git/config. For a private repo, clone on the box once gh is signed in there (Credentials), or ship a deploy key as a secret file and clone in the setup script. An existing directory is left alone.

Vars and secret files

Env vars are non-secret by definition: shell-identifier names, single-line values, shown in the dashboard and CLI. Put anything sensitive in a secret or a secret file: a body of at most 64 KiB at a path relative to your home (.aws/credentials, .npmrc), encrypted at rest, decrypted only for its box, written 0600 or the mode you set. Up to 16 per environment.

Per-box vars

A box can carry its own vars: env at create (POST /api/v1/boxes with {"env": {"NAME": "value"}}), or the Vars editor on the box page (PATCH /api/v1/boxes/:id with {"env": {...}}), which replaces the set. A per-box var wins over an environment var of the same name. Environment plus per-box vars must fit the launch budget of about 16 KiB compressed, checked as rendered for a snapshot restore; a create or PATCH that would not fit is refused with environment_too_large.

Limits

Every cap, the launch budget included, is on Limits.

CLI

prized environments (alias prized envs); every command takes --json.

CommandWhat it does
prized environments lsOne row per environment. JSON: {"environments": [...]}
prized environments info <name>Channels, repos, vars, secret files (path, mode, size), versions with box counts. JSON: {"environment": {...}}
prized environments new <name> [--description] [--setup-script FILE] [--default]Create; --default marks it the default for new boxes
prized environments default <name>Make it the default for new boxes
prized environments rm <name>Delete (asks; -y skips); boxes keep their version
prized environments set <name> --safe-for-third-parties true|false --secret-mounts true|false --device-keys true|false --phone-access true|false [--description] [--setup-script FILE]Flip the switches or replace the description or script
prized environments set-var <name> K=V / rm-var <name> KSet or remove one env var
prized environments set-file <name> <path> --from FILE|- [--mode 0600] / rm-file <name> <path>Set a secret file from a local file or stdin, or remove it
prized environments add-repo <name> owner/repo [--branch] [--dir] [--setup-script FILE] [--blocking] / rm-repo <name> owner/repoAdd, replace, or remove a repo
prized environments upgrade <name> [--box B]...Pin every live box (or just --box ones) to the latest version. JSON: {"environment", "version", "upgraded": [ids], "skipped": [ids]}

The CLI's environment object carries the API row's fields in snake_case (safe_for_third_parties, secret_files, latest_version, versions with boxes counts).

Exit codes follow the CLI table: an unknown environment or a restricted-box refusal is CHECK_FAILED (5), a bad value USAGE (2), a taken name CONFLICT (6).

API

All routes take your session or a dcp_ CLI bearer and are scoped to your workspace. Bodies are JSON.

RouteBody / answer
GET /api/v1/environments{"environments": [row]}; a row carries isDefault, the four switches, latestVersionNo, repos, secretFiles as {path, mode, size}, versions as {versionNo, createdAt, boxCount}
POST /api/v1/environments{name, description?, baseTier?, setupScript?, envVars?, repos?, secretFiles?: [{path, content (base64), mode?}], safeForThirdParties?, passSecretMounts?, passDeviceKeys?, passPhoneAccess?, isDefault?} → 201 {environment}
PATCH /api/v1/environments/:idAny of the above; a config field mints a version → 200 {environment}
DELETE /api/v1/environments/:id204; boxes keep their version
POST /api/v1/environments/:id/defaultMake it the default → {environment}
POST /api/v1/environments/:id/toggles{safeForThirdParties?, passSecretMounts?, passDeviceKeys?, passPhoneAccess?}{environment}
POST /api/v1/environments/:id/vars{name, value}{environment}; DELETE /:id/vars/:name removes
PUT /api/v1/environments/:id/files{path, content (base64), mode?}{environment}; DELETE /:id/files?path= removes
POST /api/v1/environments/:id/repos{repo, branch?, dir?, setupScript?, blocking?}{environment}; DELETE /:id/repos?repo= removes
POST /api/v1/environments/:id/upgrade{boxIds?}{upgraded: [ids], skipped: [ids], latestVersionNo}

On the box routes, POST /api/v1/boxes takes environment (id or name; null = none; absent = your default), env: {K: V} and restricted; PATCH /api/v1/boxes/:id with {env} replaces the per-box vars; GET /api/v1/boxes/:id carries environment: {id, name, versionNo, latestVersionNo}, envVars and restricted.

Errors: 400 invalid_repo, invalid_file, invalid_env_var, invalid_env, too_many_repos, too_many_files, environment_too_large (also from the box create and PATCH), safe_environment_has_secret_files; 404 not_found; 409 name_taken; 409 box_restricted from the mount and phone-access routes.

Something unclear or out of date?

On this page