drift Docs
Start
What is Drift?
The tour, if you are new here.
Use cases
Whether Drift does your thing.
Getting started
Nothing to deployed, in one command.
Architecture
How a slice is put together.
What it costs
The free grant, four unit prices, two rules.
Build
Canvas
Static sites, same origin as your API.
Tools
Operate
Auth
Route gates, API keys and your account.
Security
Boundaries, sandboxing and hardening.
Troubleshooting
Error codes
What went wrong, and what to do about it.
Legal
Acceptable use
What a slice may not be used for.
Data processing
The DPA, and every sub-processor.

drift file

Everything you do with a Driftfile, under one noun. The file declares what runs on a slice, which source files fill which slots, while the slice's own shape and price are chosen in drift slice create/resize. One noun, so there is nothing to learn about where a verb lives before you can type it.

Five of these never leave your laptop: no account, no slice, no network, so “is line 9 a typo?” costs milliseconds instead of a failed deploy.

Command Description
drift file lint [path]Validate a Driftfile exactly as a deploy would. Exits non-zero on the first invalid file, so it can gate a CI job.
drift file explain [key]Describe a key in the Driftfile format: its type, what it means, and the keys it accepts. Bare explain lists the top level; --recursive prints the whole tree.
drift file resolve [path]Print the shape the file resolves to, inherited defaults included. Pass --env staging to apply that environment's overlay first.
drift file fmt [path]Rewrite in canonical key order and 2-space indentation. --write updates in place; comments and short forms survive.
drift file new [path]Write a starter Driftfile with the knobs a first deploy needs filled in. --name, --canvas <dir>, --force.

A bare path argument defaults to ./Driftfile, and a directory argument means the Driftfile inside it.

The rest apply the file, or run what it declares:

Command Description
drift file apply [env]Apply everything the Driftfile declares to a slice. Unchanged functions are skipped.
drift file apply --planPrint what this file would deploy, then exit. Nothing is applied and no hooks run. It prices nothing: a slice's cost belongs to the shape, which this file does not declare.
drift file simulate [env]Print the same diff apply --plan would: resource counts, envelope shape, and the cost change. Never applies; exits non-zero if the manifest would abort.
drift file benchmark [--apply]Measure what each Atomic function actually costs, and print what it should book. --apply opens the resize form with the recommendations already filled in; nothing is bought until you confirm there.
drift file run [env] [--port N] [--persist]Build and run the whole project locally in Docker, with no account and no cloud. --persist keeps Backbone data in a named volume across runs.
drift file test [env] [--port N]Run it locally, wait for health, then run the Driftfile's tests.e2e commands against it.
drift file stop [env] [--purge]Stop the local run. --purge also removes the persisted data volume.
drift file logs [env] [-f]Show logs from the local run. -f/--follow streams new lines instead of printing what's there and exiting.

The four local verbs are one loop: run boots the whole project in Docker, test runs the Driftfile's tests.e2e commands against it, logs tails it, and stop tears it down.

Environments

When the Driftfile declares environments:, apply, simulate, run, test, stop and logs all take one as a positional argument (or --env). It decides which environment's overrides merge onto the base shape, and which slice the command targets: prod/production, and the one slice a project with no environments declares, target the bare slice name; every other environment targets <slice>-<env>, which has to already exist as a slice drift slice create made. With no argument, the target is prod/production when declared, or the single slice otherwise.

Running locally

drift file run builds every function and the Canvas site, bakes a thin image on top of the Drift runtime, and launches it detached on localhost: the same code that runs on Drift Cloud, on your own machine. It needs Docker, and only Docker: every language (Go, Rust, Python, Node, PHP, Ruby) builds inside a throwaway container, so no toolchain has to be installed locally. Set DRIFT_RUN_HOST_BUILD=1 to build with your own installed toolchains instead, which is faster and pulls nothing.

Apply flags

Flag What it does
--planDry run: print what would deploy, apply nothing. Exits non-zero if applying would abort.
--forceRedeploy every function, even ones whose source is unchanged.
--yes, -yAuto-confirm prompts (for CI).
--env <name>Same as the positional environment argument; also sets ${ENV}.
--secret KEY=valueOverride one variable for ${VAR} / $ENVREF resolution. Repeatable.
--no-env-fileDon't read the .env / .env.<env> file beside the Driftfile.
--no-slice-reconcileDeprecated: does nothing. Apply never reconciled a shape after drift slice resize took ownership of it.
--billing-period-months NDeprecated: does nothing. A billing period is chosen when the slice is shaped.

drift project still works, and says so.

The old spelling runs the same commands and prints one line naming what to type instead; drift file deploy and drift file diff do the same for the two verbs that were renamed. They will be removed in a future release.

Applying never changes a slice's shape.

It fills the slots you bought, and refuses against a slice that does not exist. To add a resource, raise a limit or drop one, use drift slice resize, which opens the terminal form on what the slice currently is. Secrets declared in a Driftfile can pull values from your shell with $ENV references, resolved at apply time.

Testing before you ship

drift file test is run plus your own e2e commands. It starts the project locally, waits for it to report healthy, exports the instance URL as DRIFT_TEST_URL (the port is chosen at runtime, so read it rather than hardcoding one), and runs every command under tests.e2e. The first non-zero exit fails the run, and the instance is torn down either way.

Driftfile
# Driftfile
tests:
  e2e:
    - npx playwright test

# then, with no account and no cloud:
$ drift file test

resolve is the one that pays for itself. An environment block that sets three knobs looks like it describes the slice, when it describes three knobs on top of a base you're holding in your head. It prints no price: the server is the single authority on cost, and drift file apply --plan is where that number comes from. It prints names of secrets, never values.

explain answers the other question, the one about the format rather than about your file. drift file explain backbone.nosql prints what that key is, what it may contain, and which of its fields are required, the way kubectl explain does for a manifest field. It renders the schema the CLI already caches, which is the same document lint validates against, so the two can never disagree and a key the platform adds is explainable as soon as the cache refreshes. Where a key accepts more than one spelling, every accepted form is shown rather than the first.

explain used to print what a file resolves to. That is resolve now.

The two answer different questions, so the old spelling is refused rather than quietly redirected: drift file explain ./Driftfile and drift file explain --env staging both name drift file resolve instead of guessing which you meant.

The platform owns the format, so the CLI needs a copy of it.

The Driftfile schema is fetched on first contact and cached at ~/.drift/driftfile.schema.json. On a machine that has never run an online command, lint refuses rather than printing a tick it can't stand behind so run drift account login or drift slice list once and it's cached permanently.

Every key the file accepts is in the Driftfile reference.