Command reference
Source:
src/Command/Build.ts
A Build runs a shell command that produces an output asset (a file or
directory) and tracks that asset in state. Unlike Exec, a Build has an
output contract: reconcile verifies the command actually produced outdir
and exposes its location so downstream resources (e.g. a Cloudflare.Worker’s
static assets) can consume it.
Inputs are content-hashed by default so an unchanged project skips the
rebuild entirely; set memo: false to rebuild on every deploy.
Build: Building a Vite App
Section titled “Build: Building a Vite App”const build = yield* Build("vite-build", { command: "npm run build", cwd: "./frontend", outdir: "dist",});yield* Console.log(build.outdir); // path to the dist directory, relative to the initial cwdyield* Console.log(build.hash.output); // hash of the output files (when memo is enabled)Build: Building with Custom Environment
Section titled “Build: Building with Custom Environment”const build = yield* Build("production-build", { command: "npm run build", cwd: "./app", outdir: "dist", env: { NODE_ENV: "production", API_URL: "https://api.example.com", },});Build: Customizing Memoization
Section titled “Build: Customizing Memoization”const build = yield* Build("custom-build", { command: "npm run build", cwd: "./app", outdir: "dist", memo: { include: ["src/**", "package.json"], exclude: ["node_modules", "dist"] },});Source:
src/Command/Dev.ts
A long-lived shell process scoped to a stack instance, started during
alchemy dev and restarted when its inputs change. During alchemy deploy
this is a no-op — Dev resources only run in dev mode.
The child process runs inside the dev sidecar (see Command/Local.ts) so it
survives user-code HMR — Alchemy’s user process can restart without killing
your npm run dev server. Its stdout/stderr are mirrored to the terminal
(preserving colored output) and scanned for an http(s)://… URL, favoring
a localhost/IP URL (the dev server’s own address) over any unrelated URL
the command prints first. The result is exposed as the url output
attribute — useful for surfacing a dev server’s local URL back out to
whatever resource declared this Dev.
Dev: Basic Usage
Section titled “Dev: Basic Usage”Pass a shell command that starts a long-lived dev server. Alchemy runs it in the background and extracts the first URL it prints.
const dev = yield* Dev("Frontend", { command: "npm run dev",});yield* Console.log(dev.url); // e.g. "http://localhost:5173"Dev: Working Directory
Section titled “Dev: Working Directory”Use cwd to run the command in a subdirectory — useful in
monorepos where each package has its own dev server.
const dev = yield* Dev("Web", { command: "npm run dev", cwd: "apps/web",});Dev: Environment Variables
Section titled “Dev: Environment Variables”Extra environment variables are merged on top of process.env.
Sensitive values can be wrapped in Redacted to keep them out
of logs and state files.
const dev = yield* Dev("Api", { command: "npm run dev", env: { PORT: "4000", DATABASE_URL: Redacted.make("postgres://..."), },});Source:
src/Command/Exec.ts
An Exec runs a shell command purely for its side effects — it has no
output contract. Unlike Build, it does not produce or track an output
asset; reconcile runs the command and the resource succeeds as long as the
command exits with code 0 (a non-zero exit fails with a CommandError).
Use it for one-off setup steps — running migrations, seeding data, code
generation, or any command whose result lives outside Alchemy’s state. By
default the input files are content-hashed so the command only re-runs when
its inputs (or command/cwd/env) change; set memo: false to re-run on
every deploy.
Exec: Running a Command
Section titled “Exec: Running a Command”yield* Exec("codegen", { command: "npm run codegen", cwd: "./packages/api",});Exec: Running with Custom Environment
Section titled “Exec: Running with Custom Environment”yield* Exec("migrate", { command: "npm run db:migrate", env: { DATABASE_URL: Redacted.make("postgres://..."), },});Exec: Memoizing Re-Runs
Section titled “Exec: Memoizing Re-Runs”yield* Exec("codegen", { command: "npm run codegen", memo: { include: ["schema/**"] },});Exec: Bounding Command Runtime
Section titled “Exec: Bounding Command Runtime”yield* Exec("migrate", { command: "npm run db:migrate", timeout: "5 minutes",});