CLI Reference

Dawn ships a single dawn binary with fourteen commands: add, build, check, dev, docs, eval, inspect, memory, routes, run, start, test, typegen, and verify. Most commands read dawn.config.ts from the current working directory or from --cwd <path>; dawn dev currently uses the current working directory and exposes only its own server flags.

Running the CLI

Always invoke Dawn through the dawn binpnpm exec dawn <command> (or npx dawn … / a package.json script). The bin is what @dawn-ai/cli installs into node_modules/.bin, and it resolves correctly regardless of where the package physically lives.

dawn check

Validates the app structure and configuration.

text
dawn check

Internally, dawn check loads dawn.config.ts, resolves the app root, runs discoverRoutes, and parses each route's tool definitions with discoverToolDefinitions. It surfaces:

  • A dawn.config.ts that fails to load.
  • Any discovered route whose index.ts exports more than one of agent, workflow, graph, chain.
  • Any tool file that fails to parse.
  • A stale build manifest: when .dawn/build/modules.mjs exists (written by dawn build's node target), its routes are compared against the routes on disk — a mismatch (for example a route renamed after the last build) fails with the missing/extra route ids and a prompt to re-run dawn build. .dawn/build/modules.edge.mjs is checked the same way whenever "hono" is a configured target: it is a separate artifact with its own copy of every route's static imports, and an app that builds for hono alone emits no modules.mjs at all — so this pass used to have nothing to look at for exactly the deployment shape that cannot re-walk its route tree at runtime. A manifest that is simply absent is a no-op, and the edge manifest is skipped when hono is not a configured target, so a leftover file from an experiment is not an error.
  • An unknown build.targets entry, and — when "hono" is one of them — every feature that target cannot serve, reported together as DAWN_E1005. The same gate dawn build applies, mirrored here so you learn about all of them before building.

Output is a Dawn app is valid: N routes discovered. line followed by a per-route - <pathname> (<kind>) summary. Exits non-zero on any violation with a detailed message.

Troubleshooting imports

When a route, tool, or config module fails to load with the opaque ESM error does not provide an export named X, Dawn now prints the offending package plus a likely cause and fix instead of the raw SyntaxError. Two cases account for almost all of these:

  • An older @langchain/core got hoisted. Run npm ls @langchain/core to find the duplicate, then upgrade or dedupe so the installed version satisfies Dawn's peer range (^1.1.47).

  • A CommonJS dependency imported with named bindings. Under Dawn's ESM resolver a CommonJS package only has a default export, so import { thing } from "x" fails. Use a default import and destructure instead:

    ts
    import pkg from "x"
    const { thing } = pkg

    Or import the package's ESM build if it ships one.

dawn verify

Runs five checks in one call (app, routes, typegen, deps, runtime) — the canonical preflight before dawn dev, dawn start, or a deploy. A green dawn verify means "this app will boot in this environment."

text
dawn verify
dawn verify --json

Flags:

  • --cwd <path> — operate on a different app root.
  • --json — emit a structured report ({ status, appRoot, checks, counts }) instead of human-readable text.
  • --env-file <path> — path to a .env file (overrides dawn.config.ts env and the default ./.env).

The deps check covers missing packages and missing env vars (advisory). It is provider-aware: it derives the API-key env var from the providers your routes actually use — an Anthropic-only app is checked for ANTHROPIC_API_KEY, an OpenAI app for OPENAI_API_KEY, a multi-provider app for the union, and a local Ollama app for none. A missing key is a warning, not a failure (the key may come from the runtime environment).

The runtime check gates environment readiness:

  • Node — asserts the running Node version is at least 24.0.0 (Dawn's floor: the active LTS line, which bundles npm ≥ 11 and ships node:sqlite unflagged). Below the floor fails verify with a non-zero exit.
  • Docker — present only when dawn.config.ts configures a sandbox provider; it runs the provider's daemon preflight and fails if the daemon is unreachable. Apps with no sandbox skip this sub-check entirely.

See Deployment for the recommended workflow.

dawn routes

Lists every route Dawn discovered and its computed pathname.

text
dawn routes
dawn routes --json

Output:

text
Discovered 2 Dawn routes in /path/to/app
/research -> src/app/research/index.ts
/admin/users -> src/app/(internal)/admin/users/index.ts

Use this to confirm that route groups and dynamic segments are being parsed the way you expect.

dawn typegen

Regenerates .dawn/dawn.generated.d.ts plus per-route .dawn/routes/<routeSlug>/tools.json and .dawn/routes/<routeSlug>/state.json manifests.

text
dawn typegen

The success log reports route, tool-schema, and stateful-route counts. The tools.json artifacts are consumed by dawn build to emit LangGraph entries.

dawn build

Writes deployment artifacts for the configured build.targets (default: ["node", "langsmith"]).

text
dawn build
dawn build --clean

Flags:

  • --cwd <path> — operate on a different app root.
  • --clean — wipe .dawn/build/ before writing.

Emits, per target:

  • node.dawn/build/server.mjs (boots serveRuntime — the real Dawn runtime) and a hardened Dockerfile (written to the app root unless one already exists there, else to .dawn/build/Dockerfile). Run it with dawn start or docker build/docker run.
  • langsmith.dawn/build/langgraph.json plus per-route entry files under .dawn/build/<routeSlug>.ts — the artifacts you hand to LangSmith. Includes graphs (keyed by <routeId>#<kind>), dependencies: ["."], env (.env.example if present, else .env), and node_version: "22". For agent routes, the generated entry imports the default agent() descriptor, materializes it as a LangGraph graph, and wires in every discovered route tool.
  • honoopt-in, not a default. .dawn/build/app.mjs (a Hono app around Dawn's web-standard fetch handler, export defaulted for Cloudflare Workers, Vercel, or Bun), .dawn/build/modules.edge.mjs (the node-builtin-free module manifest), .dawn/build/stores.mjs (a per-request Postgres store factory), and a wrangler.toml scaffold at the app root — written only if you have none, and never overwritten. Deploy with wrangler deploy.

Restrict which targets are emitted via build.targets in dawn.config.ts (e.g. { build: { targets: ["node"] } }). The list replaces the defaults rather than adding to them, so an app deploying to the edge names { build: { targets: ["node", "hono"] } }.

The hono target serves a subset of Dawn, and the build fails with DAWN_E1005 — naming every offending config key and file at once — when the app uses the sandbox, backends.filesystem/backends.exec, a config-supplied store, toolOutput, a workspace/ directory, route skills, or route-level long-term memory. dawn check applies the identical gate whenever hono is a configured target. See Edge and Hono.

toolOutput is a recent addition to that list, and the one gated key that is plain JSON — so it used to be inlined into the bundle and then ignored, and the build went green while the deployed worker never offloaded. An app that sets both toolOutput and "hono" therefore sees a build that passed before start failing: remove the key, or drop "hono" from build.targets. See Upgrading.

See Deployment for the full bridge.

dawn start

Serves the app in production using the real Dawn runtime — Agent Protocol, AG-UI, and /healthz — binding 0.0.0.0:8000 by default.

text
dawn start
dawn start --host 127.0.0.1 --port 3000

Flags:

  • --host <host> — host to bind. Default: 0.0.0.0 (or the HOST env var).
  • --port <number> — port to bind. Default: 8000 (or the PORT env var).

This is what the node build target's generated Dockerfile runs (CMD ["node", ".dawn/build/server.mjs"]), and it's the only server that engages the execution sandbox in production. See Node and Docker.

dawn run

Executes a single route invocation with JSON stdin/stdout.

text
echo '{"messages":[{"role":"user","content":"Hello"}]}' | dawn run '/research'

Flags:

  • --cwd <path> — operate on a different app root.
  • --url <url> — run against a live dev server instead of the in-process runtime.

The route argument can be the parameterized id (e.g. /research) or the relative route entry file path (e.g. src/app/research/index.ts). Dynamic segment values come from the JSON input. When --url is set, dawn run POSTs to /threads/<t-cli-uuid>/runs/wait with { route: "<routeId>#<kind>", input }.

dawn test

Runs every colocated run.test.ts scenario in the app.

text
dawn test
dawn test src/app/(public)/hello

Flags:

  • --cwd <path> — operate on a different app root.

The optional positional [path] argument narrows the discovered scenario set to a subdirectory. To target a live dev server, add .server(url) to that scenario's builder chain inside run.test.ts (there is no command-level --url flag on dawn test). Exits non-zero on any failure with a diff per mismatched scenario. See Testing for scenario authoring.

dawn eval

Runs every colocated *.eval.ts over its dataset and reports per-case scores, then gates on the aggregate.

text
dawn eval
dawn eval src/app/chat
dawn eval --live
dawn eval --record
dawn eval --json

Flags:

  • --cwd <path> — operate on a different app root.
  • --live — run against the real model (requires OPENAI_API_KEY); never use in CI.
  • --record — record real-model responses into sibling fixture files (requires OPENAI_API_KEY); never use in CI. Mutually exclusive with --live.
  • --json [file] — write a JSON report. Defaults to .dawn/eval-report.json.

The optional positional [path] narrows discovery to a subdirectory. By default each case replays its aimock fixtures (deterministic, CI-safe); --live calls the real provider for local prompt tuning; --record captures real-model responses as committed fixture files that plain dawn eval replays. A gated eval that fails exits non-zero, so CI fails when quality drops below the bar; informational evals (no gate/threshold) never affect the exit code. See Evals for authoring.

dawn dev

Starts the local runtime — hot reload + Agent Protocol (AP) HTTP endpoints. Bind address is fixed at 127.0.0.1.

text
dawn dev
dawn dev --port 3001

Flags:

  • --port <n> — HTTP port. Default: dynamically allocated. Pass --port for a stable address.
  • --env-file <path> — path to a .env file (overrides dawn.config.ts env and the default ./.env).

Because the default port is chosen dynamically, copy-paste curl examples should pass an explicit --port (or read the port dawn dev prints on startup) rather than assuming a fixed value.

If LANGSMITH_API_KEY is present in the loaded environment and LANGCHAIN_TRACING_V2 is not already set, dawn dev automatically enables LangSmith tracing by setting LANGCHAIN_TRACING_V2=true. Set LANGCHAIN_PROJECT to control which project receives the traces. See Observability for the full tracing guide.

See Agent Protocol for the full protocol reference and architecture notes.

dawn memory

Inspects and manages the app's long-term memory store — the typed records the agent writes via its generated remember tool. Use it to review and promote the candidate writes that the default memory: { writes: "candidate" } config holds back from recall.

text
dawn memory list
dawn memory search <query>
dawn memory inspect <id>
dawn memory approve <id>
dawn memory reject <id>
dawn memory forget <id>
dawn memory prune [--cap <n>] [--namespace <prefix>]
dawn memory consolidate [--dry-run] [--namespace <prefix>] [--model <id>] [--provider <id>] [--max-batches <n>]
dawn memory reflect [--dry-run] [--namespace <prefix>] [--model <id>] [--provider <id>] [--max-batches <n>]

Subcommands:

  • list — list pending candidate records.
  • search <query> — list candidates whose content or namespace matches <query>.
  • inspect <id> — print one record as formatted JSON.
  • approve <id> — promote a candidate to an active record so recall surfaces it.
  • reject <id> — drop a candidate without promoting it.
  • forget <id> — delete a record by id.
  • prune — run episodic retention manually: delete expired records (TTL) and enforce the per-namespace episode cap. --cap <n> overrides the cap for this pass; --namespace <prefix> scopes the pass to namespaces matching the prefix.
  • consolidate — run distillation's compaction pass: group old episodic records per (namespace, ISO week), summarize each group with one model call, then supersede the sources and stamp them with a TTL so prune reaps them later.
  • reflect — run distillation's insight pass: derive durable insights from each namespace's records newer than its watermark. Insights are written as candidate by default — approve them with approve <id> or the Inspector.

consolidate and reflect share the same flags, and both are threshold-aware no-ops: below the configured thresholds they print one line, exit 0, construct no model and require no API key — which is what makes the cron recipe (dawn memory consolidate && dawn memory reflect) safe to run nightly on any app. --dry-run reports the plan without making a single model call; --namespace <prefix> scopes the pass; --model <id> / --provider <id> override memory.distill; --max-batches <n> caps the work (and spend) for one invocation. These are the only dawn memory subcommands that spend model tokens. See Distillation for the full configuration block.

Flags:

  • --cwd <path> — operate on a different app root.

dawn inspect

Opens the Dawn Inspector — a localhost-only browser UI for browsing, searching, and approving the app's long-term memory records.

text
dawn inspect

The inspector binds to 127.0.0.1 on a free port and prints the URL to open.

Flags:

  • --cwd <path> — operate on a different app root.
  • --port <number> — bind the inspector to a stable localhost port.
  • --env-file <path> — path to a .env file (overrides dawn.config.ts env and the default ./.env).

dawn add

Fetches a blueprint (an agent-facing integration guide) and prints it to stdout so you can hand it to your coding agent.

text
dawn add                 # list available blueprints, grouped by category
dawn add pgvector        # print the pgvector blueprint
dawn add <url>           # fetch a third-party blueprint from any URL

dawn add only prints the guide — your agent applies the changes, and you review them. Set DAWN_BLUEPRINTS_URL to point at a self-hosted catalog instead of dawnai.org.

See Blueprints for authoring and catalog details.

dawn docs

Prints the bundled, version-matched Dawn docs that ship inside the installed CLI — so a coding agent (or you) can read the docs for the exact version in use without a network round-trip. With no topic it lists the available topics and the index; with a topic it prints that doc to stdout.

text
dawn docs
dawn docs README
dawn docs cli

The optional positional [topic] selects a single doc by slug (with or without the .md suffix); an unknown topic exits non-zero and lists the available topics. Running from a source checkout requires the CLI to be built first (pnpm --filter @dawn-ai/cli build) so the bundled docs exist.

Exit codes

CodeMeaning
0Success
1Validation failure (e.g. dawn check) or scenario failure (e.g. dawn test)
2Configuration / runtime error (missing dawn.config.ts, bad appDir, scenario load failure)

Non-zero exit codes from underlying tools (Commander, child processes) may be propagated unchanged.