Skip to content

CLI

Terminal window
bun alchemy <command> [options]

Every command operates on an alchemy.run.ts stack file (or a custom entrypoint passed with --config <file>, which must exist) and targets a stage.

Terminal window
alchemy
├─ deploy # plan → approve → apply
├─ plan # preview changes, apply nothing
├─ destroy # delete every resource in a stage
├─ drift # detect (and optionally repair) infrastructure drift
├─ unsafe nuke # delete everything a provider can list, tracked or not
│
├─ dev # hot-reloading development loop
├─ logs # fetch past log entries, or tail live with --tail
│
├─ profile create|rename|edit|refresh|current|list|show|delete
│ # manage credentials and accounts (bare `profile` opens the dashboard)
│
├─ state list|read|delete # inspect and manage the state store (bare `state` opens the explorer)
├─ state bootstrap|teardown|logs # provision, delete, or debug a provider's state store (--backend)
│
└─ provider
├─ check-env # CI preflight: verify required provider env vars are set
├─ aws bootstrap|teardown # the deploy assets bucket
├─ cloudflare token
└─ prisma generate

Each command has its own page: deploy, plan, destroy, drift, unsafe nuke, dev, logs, profile, state, AWS provider commands, and Cloudflare provider commands. The workflow guides cover adopting resources and inspecting state. To run the same operations from a script, see the Programmatic API.

Option Description
--stage <name> Stage to target. Falls back to $ALCHEMY_STAGE, then live_$USER (dev_$USER for alchemy dev). Must match [a-z0-9]+([-_a-z0-9]+)*.
--profile <name> Auth profile from ~/.alchemy/profiles.json. Overrides $ALCHEMY_PROFILE; defaults to default.
--env-file <path> File to load environment variables from. Defaults to .env.
--yes Yes to all prompts.
--no-input Disable prompts and the interactive TUI. Commands that would need input fail instead of hanging.
--config, -c <file> Stack entrypoint. Defaults to alchemy.run.ts; must exist.
--fast-distilled Under Node, load each distilled SDK operation on first use. This lowers the CLI’s memory and startup time for stacks that import whole providers. Same as ALCHEMY_FAST_DISTILLED=1.

Use --profile with deploy, plan, destroy, dev, logs, drift, or state.

In an interactive terminal, deploy, destroy, and plan render a live TUI: the rendered plan, an arrow-key approval prompt, and per-resource apply progress that unmounts into the final output. Everywhere else the same commands emit plain line-oriented logs.

The --no-input flag and environment variables override the detection, in this order:

Signal Effect
--no-input flag Force plain output
ALCHEMY_PLAIN=1 or ALCHEMY_NO_TUI=1 Force plain output
ALCHEMY_TUI=1 Force the TUI
No TTY, CI=1, or a known agent env var (CLAUDECODE, CLAUDE_CODE_ENTRYPOINT, CURSOR_AGENT, AIDER_MODEL, CODEX_CLI) Force plain output

Interactive terminals use the animated TUI; redirected and non-interactive runs use append-only output.

Plain mode never prompts — it prints the plan, makes no changes, and fails with error: Cannot approve this operation without terminal input. Pass --yes to continue. In CI, always pass --yes.

Every log line is a record. Output from child processes (dev servers, workerd, the local provider sidecar) is captured as records too, so it can be shown either way:

Option Description
--log-format pretty|json pretty (default) prints lines; json prints one record per line on stderr, with child output as written. Also $ALCHEMY_LOG_FORMAT.
--log-level <level> Lowest level printed. Defaults to info. Also $ALCHEMY_LOG_LEVEL.

Every record has the same keys:

Key Value
time Unix time in milliseconds
level trace, debug, info, warn, error or fatal
kind log, event, output or run (see below)
process The alchemy process that produced it: cli, exec (the alchemy dev worker) or sidecar
scope project or global
trace { traceId, spanId } of the span it was logged in, or of the process outside any span. Child processes and sidecar calls join their caller’s trace.
attributes Annotations on the record, including fqn when it is about a resource
data Depends on kind
kind data
log { message, cause }: a line alchemy logged
event A typed event, as Alchemist.onEvent receives it
output { stream, text }: a line a child process wrote, exactly as written, ANSI styling included
run { version, pid, cwd, argv }: the first line of a run log
{"time":1793186948542,"level":"info","kind":"output","process":"sidecar","scope":"project",