1---
2title: 2.0.0-beta.63 - Durable Object Transfers & Action Bindings
3date: 2026-07-17T06:00:00Z
4category: release
5excerpt: v2.0.0-beta.63 moves Durable Object classes between Workers with their data intact, lets Actions bind resources and read Outputs with your CLI credentials, and makes `alchemy login` work from any folder. The website now lives at alchemy.run.
6---
7
8beta.63 moves **Durable Object classes between Workers** with
9their data intact, lets **Actions bind resources** and read
10Outputs with your CLI credentials, and makes **`alchemy login`**
11work from any folder. The website now lives at
12[alchemy.run](https://alchemy.run).
13
14## Move a Durable Object to another Worker
15
16A Durable Object class can now move between Workers **with its
17data intact** — same instances, same storage — via Cloudflare's
18`transferred_classes` migration
19([#803](https://github.com/alchemy-run/alchemy/pull/803)).
20
21Moves are always declared. A class that disappears from one
22Worker and appears on another is ambiguous between "transfer the
23data" and "delete it, start fresh", so Alchemy never guesses.
24The class states where it came from:
25
26```diff lang="typescript"
27export class Counter extends Cloudflare.DurableObject<
28 Counter,
29 {
30 increment: () => Effect.Effect<number, never, RuntimeContext>;
31 get: () => Effect.Effect<number, never, RuntimeContext>;
32 }
33->()("Counter") {}
34+>()("Counter", { transferredFrom: "WorkerA" }) {}
35```
36
37Whichever Worker hosts `Counter` next transfers the namespace
38from `WorkerA`. `transferredFrom` accepts a Worker logical id, a
39physical script name (for cross-stack moves), the Worker class
40itself, or a thunk for import cycles.
41
42The declaration is a host *history*: after a second move you
43write `transferredFrom: ["WorkerA", "WorkerB"]`, and the
44namespace transfers from whichever listed host currently holds
45it — so a stage that lagged behind or skipped a release still
46converges. Once a transfer completes, the declaration is inert
47and safe to keep in code forever.
48
49If you move a host without declaring it, the deploy fails
50**before any upload** with the typed
51`DurableObjectTransferRequired` error, naming the exact
52declaration to add. Durable Object data is never silently
53destroyed or forked.
54
55Docs: [Bind to another Worker's Durable
56Object](/cloudflare/compute/cross-worker-durable-object).
57
58## Bind resources inside Actions
59
60[Actions](/blog/2026-05-13-beta-38) run arbitrary Effects during
61deploy — seed a database, ping Slack, invalidate a cache. They
62can now **bind resources** the same way a Worker does, and read
63resource **Outputs**
64([#807](https://github.com/alchemy-run/alchemy/pull/807)):
65
66```typescript
67const Seed = Alchemy.Action(
68 "Seed",
69 Effect.gen(function* () {
70 const db = yield* Cloudflare.D1.QueryDatabase(database);
71 const databaseId = yield* database.databaseId;
72
73 return Effect.fn(function* () {
74 yield* db.exec("CREATE TABLE IF NOT EXISTS users (id TEXT, name TEXT)");
75 return { databaseId: yield* databaseId };
76 });
77 }).pipe(Effect.provide(Cloudflare.D1.QueryDatabaseLocal)),
78);
79```
80
81The new `*Local` layers make this work. They're a third binding
82variant alongside `*Binding` (native Worker binding) and `*Http`
83(scoped API token): a `*Local` layer authenticates with your
84**current CLI credentials** and returns the same typed client,
85so an Action running on your machine or in CI talks to the same
86data plane your Worker would. Every Cloudflare capability with
87an HTTP data plane has one — D1, KV, R2, Queues, DNS, Vectorize,
88Tunnel, AI Search, Browser Rendering, and more.
89
90Reading `yield* database.databaseId` inside an Action also
91records a dependency edge, so the Action waits for the database
92to exist before it runs.
93
94## `alchemy login` works anywhere
95
96`alchemy login` no longer requires an `alchemy.run.ts`
97([#842](https://github.com/alchemy-run/alchemy/pull/842)). With
98no entrypoint in sight, it offers every built-in auth provider
99and configures the ones you pick, so you can set up or refresh
100credentials from any folder:
101
102```
103$ cd /some/empty/dir && alchemy login
104No alchemy.run.ts found — using Alchemy's built-in providers.
105◆ Select providers to log in with
106│ ◻ AWS
107│ ◻ Axiom
108│ ◻ Cloudflare
109│ ◼ GitHub (configured)
110│ ◻ Neon
111│ ◻ Planetscale
112```
113
114Already-configured providers are pre-selected and labeled. In
115CI the prompt is skipped and all built-ins are configured
116non-interactively. With an `alchemy.run.ts` present, behavior is
117unchanged.
118
119Docs: [alchemy login](/cli/login).
120
121## The website moved to alchemy.run
122
123The v2 site now serves from the apex domain, and
124`v2.alchemy.run` 301s to it at the edge
125([#806](https://github.com/alchemy-run/alchemy/pull/806)). The
126redirect is itself deployed by Alchemy — a
127`Cloudflare.Ruleset` on the adopted zone:
128
129```typescript
130yield* Cloudflare.Ruleset.Ruleset("V2Redirect", {
131 zone,
132 phase: "http_request_dynamic_redirect",
133 rules: [{
134 expression: 'http.host eq "v2.alchemy.run"',
135 action: "redirect",
136 actionParameters: {
137 fromValue: {
138 targetUrl: { expression: 'concat("https://alchemy.run", http.request.uri.path)' },
139 preserveQueryString: true,
140 statusCode: 301,
141 },
142 },
143 }],
144});
145```
146
147## A new test runner
148
149This release also lands `alchemy-test`, the Effect-native test
150runner that executes our 4,000+ live-cloud test suite in a
151single bun process
152([#848](https://github.com/alchemy-run/alchemy/pull/848)). It
153got its own post: [A Test Runner for Agents and
154Humans](/blog/2026-07-22-a-test-runner-for-agents).
155
156## Also in this release
157
158- **Durable Object metadata packs into a single script tag**
159 ([#824](https://github.com/alchemy-run/alchemy/pull/824)) —
160 one tag per DO binding blew Cloudflare's 10-tag-per-Worker
161 limit at 7+ DOs; all mappings now fit in one tag.
162- **Vite-based Workers hash sibling workspace packages**
163 ([#822](https://github.com/alchemy-run/alchemy/pull/822)) —
164 editing only a sibling package used to skip the deploy and
165 serve stale code.
166- **Alchemy's Vite plugin no longer double-registers**
167 ([#833](https://github.com/alchemy-run/alchemy/pull/833)) —
168 apps that also build standalone keep the plugin in their
169 `vite.config.ts`; Alchemy signals its own injection via
170 `ALCHEMY_CLOUDFLARE_VITE_INJECTED`. Thanks **Alex**!
171- **MySQL replicas reconcile in place**
172 ([#825](https://github.com/alchemy-run/alchemy/pull/825)) —
173 changing `replicas` on a PlanetScale MySQL database resizes
174 the keyspace instead of replacing the database.
175- **Unresolved Outputs never persist in state**
176 ([#835](https://github.com/alchemy-run/alchemy/pull/835)) —
177 an interrupted create could snapshot live `Output` proxies
178 into state and poison later reads.
179- **Auto-bound `Config` resolves in request handlers**
180 ([#829](https://github.com/alchemy-run/alchemy/pull/829)) —
181 re-yielding a `Config` inside a handler decoded the secret
182 marker JSON instead of the value.
183- **`proxyChain` values pass `Effect.isEffect`**
184 ([#827](https://github.com/alchemy-run/alchemy/pull/827)) —
185 chained Drizzle clients now work with predicate-dispatched
186 operators like `Effect.catchTag`. Thanks **Julian Archila**!
187
188## Where to go next
189
190- [Bind to another Worker's Durable Object](/cloudflare/compute/cross-worker-durable-object)
191- [alchemy login](/cli/login)
192- [A Test Runner for Agents and Humans](/blog/2026-07-22-a-test-runner-for-agents)
193- [CHANGELOG](https://github.com/alchemy-run/alchemy/blob/main/CHANGELOG.md#v200-beta63)
194- [Compare v2.0.0-beta.62 → v2.0.0-beta.63](https://github.com/alchemy-run/alchemy/compare/v2.0.0-beta.62...v2.0.0-beta.63)