learn-alchemy
Learn how Alchemy 2 turns an Effect program into a planned Cloudflare deployment.
Skill by joelhooks
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/joelhooks-learn-alchemy-a26214
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: cloud
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/learn-alchemy
What's inside
- Skill name
learn-alchemy- Description
- Learn how Alchemy 2 turns an Effect program into a planned Cloudflare deployment.
- License
- MIT
- Instructions
- 137 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Learn Alchemy
Alchemy 2 declares and deploys cloud resources through Effect programs. Effect describes work with typed failures and required dependencies. One program declares resources, bindings, deployment state, and the Worker that uses them.
A service is a named interface for one job. A Layer builds services and supplies their construction dependencies. A contract defines an action's name, input, output, failure, and metadata.
Start with this repo's Cloudflare resources. Alchemy also supports other providers. Learn the vocabulary to write infrastructure and check planned changes.
Sam Goodwin describes an Effect as a promise with more information: its return value, errors, and requirements. His Alchemy shorthand is "if it compiles, it should deploy and run." Use compilation for feedback. Check cloud API failures during deployment.
## The vocabulary
- **Alchemy Stack** groups one infrastructure program and its outputs. Rat-stack exports `Alchemy.Stack("RatStack", ...)` in `apps/infra/alchemy.run.ts`.
- **Provider** supplies the cloud API implementation. `Cloudflare.providers()` appears in the Stack options in `apps/infra/alchemy.run.ts`.
- **State** records the resources that a Stack already owns. Rat-stack uses `Cloudflare.state()` in `apps/infra/alchemy.run.ts`.
- **Resource** is a declared cloud object such as a Zone, DNS record, DNSSEC setting, or Worker. Each gets a stable logical name in `apps/infra/alchemy.run.ts`.
- **Binding** is a typed runtime value attached to a Worker. Rat-stack declares the `CODE_SANDBOX` WorkerLoader and four RateLimit bindings in `apps/site/src/worker.ts`.
- **Plan** shows differences between declared resources and stored deployment state before a provider changes anything. Read it with the `plan` script in `apps/infra/package.json`.
- **Stage** names an isolated deployment state. Rat-stack's production stage is `prod`; the unflagged default is `live_$USER`.
- **Profile** holds provider credentials for the Alchemy CLI. This repo uses an Alchemy profile, not environment variables, for Cloudflare authentication.
- **Adopt** means take ownership of an existing resource explicitly. The existing `ratstack.sh` Zone and its DNSSEC setting use `adopt(true)` in `apps/infra/alchemy.run.ts`.
- **Dev** is local workerd execution with `ALCHEMY_DEV=true`. Rat-stack uses it to skip the production Zone and DNS resources in `apps/infra/alchemy.run.ts`.
## Trace one deploy
Read `apps/infra/alchemy.run.ts` from top to bottom.
1. The file imports Alchemy, the Cloudflare provider, Effect, and the `Mischief` Worker from `apps/site/src/worker.ts`.
2. `Alchemy.Stack` creates the program. `Effect.gen` gives it a place to yield resources and return outputs.
3. `Cloudflare.providers()` supplies Cloudflare operations. `Cloudflare.state()` lets Alchemy compare this run with prior state.
4. `ALCHEMY_DEV` guards resources that should not be touched by local development.
5. The Zone is named `RatstackZone` and adopted because `ratstack.sh` already exists. A Zone normally retains on destroy, and this Stack does not opt into deleting it.
6. The DNS-AID SVCB and TXT records point agent discovery at the deployed site. They use the adopted Zone's `zoneId`.
7. `Cloudflare.DNS.Dnssec` keeps DNSSEC active. It is adopted for the same reason as the Zone.
8. `Mischief` declares the Worker with `ratstack.sh` as its custom domain, `www.ratstack.sh` as a redirect, and port 1337 for dev.
9. The Worker construction yields its WorkerLoader and four RateLimit bindings: `API_PER_IP`, `EXECUTE_GLOBAL`, `EXECUTE_PER_IP`, and `INTEREST_PER_IP`. `Effect.provide(Cloudflare.Workers.RateLimitBinding)` supplies the RateLimit client layer.
10. `apps/site/src/worker.ts` also yields the Interest and InterestIndex Durable Objects. `EVENTS_ENABLED` chooses `Basin` or `basinFoundation`: both keep the bucket, stream, and visitor salt; enabled adds the catalog, sink, and pipeline. The Worker supplies the subscriber delivery implementation when it starts, outside core.
11. The Stack yields `Website` from `apps/web/src/website.ts` and returns both `mischiefUrl` and `websiteUrl`.
The outputs omit the production DNS declarations:
```ts
export default Alchemy.Stack(
"RatStack",
{ providers: Cloudflare.providers(), state: Cloudflare.state() },
Effect.gen(function* stack() {
const mischief = yield* Mischief;
const website = yield* Website;
return { mischiefUrl: mischief.url, websiteUrl: website.url };
})
);
```
The Stack is an Effect. Importing it describes work. The CLI runs it during a plan or deploy.
### Follow the Worker bindings
`apps/site/src/worker.ts` exports `class Mischief extends Cloudflare.Worker<Mischief>()(...) {}` with `main: import.meta.url`, so Alchemy bundles the default Worker export. Its construction Effect yields bindings before it returns the `fetch` implementation. Alchemy populates `Cloudflare.WorkerEnvironment` dynamically; this repo keeps the expected binding shape in local types at that boundary.
```ts
const stageRateLimits = rateLimitDeclarations(yield * Stage);
yield * Cloudflare.WorkerLoader("CODE_SANDBOX");
yield * Cloudflare.RateLimit("API_PER_IP", stageRateLimits.API_PER_IP);
yield * Cloudflare.RateLimit("EXECUTE_GLOBAL", stageRateLimits.EXECUTE_GLOBAL);
yield * Cloudflare.RateLimit("EXECUTE_PER_IP", stageRateLimits.EXECUTE_PER_IP);
yield *
Cloudflare.RateLimit("INTEREST_PER_IP", stageRateLimits.INTEREST_PER_IP);
const environment = yield * Cloudflare.WorkerEnvironment;
// SAFETY: the Worker construction declares every RateLimitBindings member and CODE_SANDBOX before reading this environment.
const bindings = environment as RateLimitBindings & {
readonly CODE_SANDBOX: WorkerLoaderBinding;
};
```
`apps/site/src/rate-limits.ts` keeps the four native binding names and their numeric namespace IDs together. `rateLimitsFrom` calls the native `.limit({ key })` method and turns a failed runtime call into a defect instead of failing open.
`apps/site/src/sandbox-worker-loader.ts` consumes the `CODE_SANDBOX` binding. It loads a fresh Dynamic Worker with limits and `globalOutbound: null`, so the code-mode Worker can compute and call declared capabilities without reaching the network. A capability is one named action with shared value definitions and a server-side implementation.
Sam describes the constructor as a Layer: declare dependencies in the Effect, use them, then return the implementation. In his React analogy, dependencies are the hooks at the top. The returned Worker is the component.
Declarations and consumers share one construction Effect. The environment assertion relies on the declared bindings. Check missing bindings in the plan and at runtime; typecheck alone cannot prove they exist.
## Plan, then deploy
The scripts live in `apps/infra/package.json`:
```sh
pnpm infra:plan
pnpm infra:deploy
pnpm infra:dev
pnpm infra:destroy
```
Run the plan first. It shows `create`, `update`, `adopt`, and `noop` actions before a provider is changed. Review replacements, domains, DNS, bindings, and stage before approving a deploy.
Production is stage `prod`. Pass `--stage prod` to the Alchemy CLI. An unflagged deploy defaults to `live_$USER`, which can create a second Worker instead of updating production. Never run an indiscriminate stage destroy. Name the stage explicitly and read its plan first.
Alchemy v2 represents outputs as values whose contents become available during deployment. Resources can still reference one another. Sam compares this to Pulumi's output model. The engine sees the graph before it acts. The engine orders resource operations without hand-written await chains.
## Why not wrangler.toml or Terraform
Wrangler is a good Cloudflare-specific tool. This repo needs one Effect program that declares the Zone, DNS records, DNSSEC, Worker, and the bindings consumed by the Worker, so Alchemy is the chosen boundary.
Terraform would keep infrastructure and the Effect Worker in separate languages and graphs. Alchemy can infer the Worker binding wiring from the same construction code that consumes it, while still showing a plan first.
Keep an existing tool when it already owns the state and the team knows its review path. Choose Alchemy here because the typed application and the cloud graph are one lesson.
## Gotchas from this repo
- The Worker bundle uses Alchemy's Rolldown path, and Node's type stripping is outside the normal TypeScript program. A red `pnpm typecheck` does not stop Alchemy from producing a deploy plan or bundle. Run `pnpm turbo run check test build` first and inspect the failing task. Do not use a deploy to bypass a red gate.
- Cloudflare API changes have broken Alchemy releases before. Check the pinned version in `apps/infra/package.json` and the generated pins page before changing it.
- The repo pins Alchemy to a beta. Alpha and beta APIs drift. Read the current pins and vendored source before copying an example from elsewhere.
- Cloudflare rejected string rate-limit namespace IDs during a deploy even though the local type allowed them. `apps/site/src/rate-limits.ts` uses numeric IDs and documents the boundary.
- `adopt(true)` authorizes adoption. Without it, Alchemy refuses to take over an existing Zone. Keep adoption narrow and never assume a resource is safe to destroy.
- Profiles carry Cloudflare credentials. Do not add provider tokens to `.env`, source files, or Worker bindings for CLI convenience.
## Try it
1. Run `pnpm infra:plan` and read every action. Do not approve a deploy. Identify which resources are `noop` and which would change.From joelhooks/rat-stack, MIT.
More from joelhooks/rat-stack
- 0.684score
rat-stack-mode
joelhooks
Route non-trivial rat-stack code, data, design, investigation, and documentation tasks to every matching playbook and principle.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
profile-a-worker
joelhooks
Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
investigate-a-failure
joelhooks
Find the cause of a crash, wrong output, flaky test, or slow run with evidence, fix it at its source, and leave a notebook a person can learn from.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
uncomplect
joelhooks
Find responsibilities that a rat-stack design combines, separate them into capabilities, cartridges, machines, features, and clients, and enforce that…
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
query-design
joelhooks
Design or review SQL reads, writes, scans, backfills, and slow database paths.
SkillAFreshness: A★ 129Claude Code +9 - 0.681score
ship
joelhooks
Learn how to ship a change through merge, CI, release, stage deployment, rollout, verification, rollback and flags.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
learn
joelhooks
Present Effect, Alchemy, XState, and application-design concepts during real work when the operator enables learn mode.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
add-a-store
joelhooks
Add persistence through a service named for an application job, with validation, vendor Layers, migrations, bounded reads, and shared backend tests.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
find-peers
joelhooks
Refresh public peers, exact stack versions, and usefulness tiers every week or two and after each shared dependency update.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
gardener
joelhooks
Keep rat-stack current and clean.
SkillAFreshness: A★ 129Claude Code +9 - 0.676score
add-a-capability
joelhooks
Learn how one contract and its handler become a command, HTTP route, MCP tool, browser RPC, and sandbox call.
SkillAFreshness: A★ 129Claude Code +9 - 0.676score
add-a-lifecycle-machine
joelhooks
Learn how XState owns a lifecycle while Effect owns its work, errors, and services.
SkillAFreshness: A★ 129Claude Code +9
Compare and alternatives
Featured in
Signals
- Stars
- 129
- Forks
- 8
- Open issues
- 2
- Last commit (this folder)
- Oct 10, 2026 (18 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/joelhooks/rat-stack
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
Same skill elsewhere
Copies of this SKILL.md published by others; search shows only one of them.
- 0.337score
learn-alchemy
joelhooks
Learn how Alchemy 2 turns an Effect program into a planned Cloudflare deployment.
SkillAFreshness: A★ 27Claude Code +9 - 0.335score
learn-alchemy
ChindanaiNaKub
Learn how Alchemy 2 turns an Effect program into a planned Cloudflare deployment.
SkillAFreshness: AClaude Code +9 - 0.323score
learn-alchemy
joelhooks
Learn how Alchemy 2 turns an Effect program into a planned Cloudflare deployment.
SkillAFreshness: A★ 6Claude Code +9
More from joelhooks
- 0.684score
rat-stack-mode
joelhooks
Route non-trivial rat-stack code, data, design, investigation, and documentation tasks to every matching playbook and principle.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
uncomplect
joelhooks
Find responsibilities that a rat-stack design combines, separate them into capabilities, cartridges, machines, features, and clients, and enforce that…
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
investigate-a-failure
joelhooks
Find the cause of a crash, wrong output, flaky test, or slow run with evidence, fix it at its source, and leave a notebook a person can learn from.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
profile-a-worker
joelhooks
Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
query-design
joelhooks
Design or review SQL reads, writes, scans, backfills, and slow database paths.
SkillAFreshness: A★ 129Claude Code +9 - 0.681score
ship
joelhooks
Learn how to ship a change through merge, CI, release, stage deployment, rollout, verification, rollback and flags.
SkillAFreshness: A★ 129Claude Code +9
Cite this page
learn-alchemy skill. Agent Mart. https://agentmart.dev/skills/joelhooks-learn-alchemy-a26214 (last updated 2026-10-24)