Skip to content

Quickstart

Install @dragonmastery/tamer from npm and go from empty repo to a live deployment. This is the consumer track — for contributing to Tamer itself, see the README on GitHub.

Prerequisites

  • Node.js 22+ (engines.node) + Bun (the tamer bin has a bun shebang; see Installation).
  • Cloudflare account + CLOUDFLARE_ACCOUNT_ID / CLOUDFLARE_API_TOKEN (API token scopes).
  • wrangler peer (>=4.0.0) — install next to Tamer; Tamer shells out for deploy, migrate, and types.
  • Optional: R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY for bucket emptying on tamer destroy.

1. Install

No global installs (npm install -g, etc.). Install @dragonmastery/tamer and wrangler as devDependencies in your stack repo so CI and developers share one lockfile:

bash
npm install -D @dragonmastery/tamer wrangler
# or: bun add -d @dragonmastery/tamer wrangler

The package exposes a tamer binary (node_modules/.bin/tamer). Run via package.json scripts, npx tamer …, or bunx tamer …. Keep wrangler local too — Tamer shells out with bunx wrangler … for deploy, migrate, and types; project-local installs are picked up automatically when dependencies are installed.

json
{
  "scripts": {
    "tamer": "tamer",
    "tamer:apply:dev": "tamer apply --env dev",
    "tamer:deploy:dev": "tamer deploy --env dev"
  }
}

Ad hoc: npx tamer --help, bunx tamer doctor --env dev.

2. Stack layout

my-stack/
├── tamer/
│   ├── project.config.ts      # required
│   └── env/dev.config.ts      # optional overlay
├── workers/ …
├── .env                       # gitignored CLOUDFLARE_* vars
└── package.json

Alternative: tamer.project.config.ts at repo root + tamer.env.<env>.ts. Override path with --config <file>.

3. tamer/project.config.ts

Import from the published package (not paths into the Tamer monorepo):

ts
import { cf, defineConfig } from "@dragonmastery/tamer";

export default defineConfig({
  stack: "my-product",
  compatibility_date: "2025-12-01",
  workers: {
    api: {
      main: "workers/api/src/index.ts",
      resources: { d1: [{ logicalName: "app-db", type: "single" }] },
      vars: { DB_NAME: cf.d1("app-db").name },
    },
  },
  outputs: {
    api_worker_name: cf.worker("api").name,
    app_db_name: cf.d1("app-db").name,
  },
});

More patterns: Project Config, Resource Kinds, outputs.

Existing Cloudflare resources (brownfield): keep legacy D1/R2/workflow/worker names via a naming block or per-resource cloudflareName — no IDs in config. Flow is still bootstrap → sync → plan. See Brownfield Adoption and Naming Conventions.

4. Bootstrap → apply → deploy

From the stack repo root:

bash
bun run tamer -- doctor --env dev
bun run tamer -- bootstrap    # once per account: tamer-state + tamer-artifacts + tamer-secrets
bun run tamer -- apply --env dev
bun run tamer -- migrate --env dev
bun run tamer -- deploy --env dev

Subdirectory support

Tamer discovers tamer/project.config.ts by walking up from the current working directory (since 0.35.4), so you can run any command from a worker subdirectory — cd workers/api && tamer deploy --env dev --worker api works without -C ../... Worker paths resolve against the discovered project root, not cwd.

Preview: tamer plan --env dev. Refresh state: tamer sync --env dev (adopts existing CF resources when derived names match — brownfield-adoption.md).

Worker secrets: declare secrets.required in config; store values via tamer secrets (master key in CI + password manager, never on Cloudflare). See secrets.md.

Multi-stack: apply producers before consumers so ${tamer:import:…} resolves — typically platform → portal → internal.

5. Cross-stack ${tamer:import:…}

Stack B consumes stack A's published outputs via ${tamer:import:<stack>.<output>} in vars, routes, or nested outputs. Grammar and examples: README → Cross-stack imports. Shared envs use one tamer-state D1; each stack row is tamer_state:{env}:{stackName} (stack.name or tenant.slug).

Brownfield stacks: per-resource Cloudflare name overrides via cloudflareName on resource configs — see Naming Conventions and Brownfield Adoption.

Version pinning

Pin the exact released semver in CI; relax to a caret range once you trust the release train. Treat outputs-key renames as semver events for downstream contract packages. Upgrades: GitHub releases.

json
"devDependencies": {
  "@dragonmastery/tamer": "0.65.1",
  "wrangler": "^4.72.0"
}

Next steps

Released under the Tamer Evaluation License.