turboEnv

CLI reference

Every turboenv command, option and environment variable, and the rules for how they combine.

npm install -g turboenv-cli

Node 24 or newer. You can also run it without installing, which is what CI usually wants:

npx turboenv-cli run -- npm start

Commands

turboenv login

Signs this machine in to your team through a browser. Writes a credential to ~/.turboenv/credentials.json with mode 0600.

turboenv login
turboenv login --no-browser    # print the URL instead of opening it

Your terminal prints a short confirmation code that you type into the approval page. If a page ever asks you to approve a login and your terminal is not showing a code, something else started that request — deny it.

The credential covers every project your team owns, so -p and -e become required unless a turboenv.json supplies them. See Tokens and access.

turboenv init

Writes a turboenv.json holding the project and environment this directory works against, so the other commands need no flags.

turboenv init                                        # pick from a list
turboenv init -p checkout-service -e development     # non-interactive
turboenv init --force                                # overwrite an existing file

With no flags it lists your team's projects, then that project's environments, and asks you to choose. Both are checked against the server either way, so a typo fails now rather than at your next deploy.

Commit the file — see Project configuration.

turboenv pull

Safely merges a stored snapshot into a local .env.

turboenv pull                         # show the diff, then confirm
turboenv pull -f .env.production      # write a different file
turboenv pull --version 12            # pull an immutable older snapshot
turboenv pull --prune                 # make an exact remote copy

Remote values replace matching local values; local-only variables remain unless you pass --prune. Existing files are backed up to <file>.bak, then replaced atomically with mode 0600. Formatting and comments are rewritten. Project tokens can pull because they are read-only credentials.

turboenv push

Pushes a local .env up as a new version.

turboenv push                       # show the diff, then confirm
turboenv push -f .env.production    # read a different file
turboenv push --prune               # also remove what the file omits
turboenv push --yes -m "rotate key" # no prompt, for scripts

Requires a turboenv login credential; project tokens are read-only. Full behaviour in Project configuration. turboenv sync remains a deprecated alias for push.

turboenv run -- <command>

Fetches variables, injects them into the environment, and runs your command.

turboenv run -- node server.js
turboenv run -p checkout-service -e production -- ./bin/api
turboenv run --version 12 -- python manage.py runserver

Everything after -- is your command, untouched, so its own flags cannot be confused with turboEnv's.

turboenv print

Writes the variables to stdout in .env format, with values quoted so the output is safe to source.

turboenv print > .env
turboenv print -p checkout-service -e development

This puts decrypted values on disk. Prefer run unless something genuinely needs a file.

turboenv delete

Deletes a project, its environments, every version and variable in them, and every token issued for it.

turboenv delete                        # summarise, then type the slug to confirm
turboenv delete -p checkout-service    # name the project rather than using turboenv.json
turboenv delete -p checkout-service --yes  # no prompt, for scripts

Confirming means typing the project's slug, not pressing y. There is no version to roll back to afterwards and no undo, so the prompt asks you to spell out what you are destroying.

--yes only works alongside an explicit -p. Otherwise turboenv delete --yes run in the wrong directory would silently destroy whichever project the nearest turboenv.json happens to point at.

Requires a turboenv login credential; project tokens cannot delete anything. Anything deploying with a token from the deleted project stops being able to read its configuration immediately.

Customer-managed projects

Configure the separately held customer key before reading, pulling or pushing:

turboenv key generate --key-file .turboenv-key
export TURBOENV_KEY_FILE="$PWD/.turboenv-key"
turboenv run -- npm start

Use a deployment secret mount rather than committing the file. TURBOENV_KEY also works. The CLI unwraps and decrypts locally, caches only ciphertext for these projects, and removes both key variables before starting the child. There is no recovery if every copy of the customer key is lost.

Options

Option Effect
-p, --project <slug> Which project to read
-e, --environment <name> Which environment to read
--version <n> Pin a version instead of taking the latest
--token <token> Override TURBOENV_TOKEN
--url <url> Override TURBOENV_URL, for a self-hosted instance
--override Let stored values replace ones already in the environment
--no-cache Do not read or write the local cache
--no-browser With login, print the URL instead of opening it
-f, --file <path> With pull/push, which file to use (default .env)
-m, --message <text> With push, why this changed
--prune With pull/push, remove variables missing at the source
--yes With pull/push, skip confirmation. With delete, skip it too, but only alongside an explicit -p
--force With init, overwrite an existing turboenv.json

Whether -p and -e are required depends on your credential and whether a turboenv.json is present. A project token already knows its scope, so they are optional — and naming a different project is refused rather than quietly ignored. A login credential has no implicit target, so both are required unless the config file supplies them.

Which project and environment win

Most explicit first:

  1. -p and --environment flags
  2. TURBOENV_PROJECT and TURBOENV_ENVIRONMENT
  3. turboenv.json, from this directory or the nearest one above it
  4. The token's own scope, for a project token

The two are resolved independently, so a turboenv.json naming a project can be combined with -e staging for one command.

Environment variables

Variable Meaning
TURBOENV_TOKEN A project token from the dashboard
TURBOENV_URL API base URL, for a self-hosted instance
TURBOENV_PROJECT Default project, overriding turboenv.json
TURBOENV_ENVIRONMENT Default environment, overriding turboenv.json

Which credential wins

Most explicit first:

  1. --token
  2. TURBOENV_TOKEN
  3. A stored turboenv login credential

A stored login is refused when CI is detected, whatever the file says. The CLI looks for CI, GITHUB_ACTIONS, GITLAB_CI, CIRCLECI, BUILDKITE, JENKINS_URL, TEAMCITY_VERSION, TF_BUILD, BUILD_NUMBER and CONTINUOUS_INTEGRATION. A value of false or 0 is believed, since some providers set CI=false deliberately.

Existing variables are not overwritten

If a variable is already set in the environment, the stored value does not replace it. A value you exported in your shell, or one your orchestrator injected, always wins.

PORT=4000 turboenv run -- node server.js   # PORT stays 4000

That default makes local debugging predictable — you can override one value for one run without editing anything stored. Pass --override to invert it, which is occasionally what you want when a base image sets a variable you need to replace.

Caching

The last successful response is written to ~/.turboenv/cache with mode 0600, keyed by a hash of the credential, project, environment and version. If the API is unreachable at startup, the cache is used and a warning goes to stderr, so an outage does not stop your app from booting.

The cache holds plaintext values, which is why it is 0600 and why the key includes the credential: two people on one machine do not share a cache entry, and neither do two projects.

--no-cache disables reading and writing it.

Self-hosted instances

Point the CLI at your own deployment with --url or TURBOENV_URL:

export TURBOENV_URL=https://turboenv.internal.example.com/api
turboenv login

Credentials are stored per base URL, so you can be signed in to your own instance and the hosted one at the same time without one replacing the other.

Exit codes

turboenv run exits with the exact status of the command it ran, and forwards SIGINT, SIGTERM and SIGHUP to it. A failure inside turboEnv itself — no credential, unknown project, unreachable API with no cache — exits 1 with a message on stderr.