curl directly — the Functions local-dev guide covers that. A Stateful Actor project is different: the fetch handler reaches its actors through an env.<BINDING> call, and that binding resolves only against a running actor runtime. There is no in-process emulation to fall back on.
telnyx-edge dev supplies the missing runtime. It generates the actor stack your project needs, boots it in Docker, serves your fetch handler on a local port, and hot-reloads on save — so env.<BINDING> calls hit real actors before you ship.
telnyx-edge dev is a development command; it does not deploy anything. When it works locally, ship with telnyx-edge ship.
Prerequisites
-
Docker, running. The stack is a set of containers booted with
docker compose. -
A
telnyx.tomlumbrella project — the two-export shape from Project structure: one module that exports an actor class and afetchhandler, wired by an[[actors]]binding. Runtelnyx-edge devfrom the directory that holds the manifest, or point at it with-f/--from-dir. Without atelnyx.toml, the command errors:The Quick Start scaffolds exactly this shape withtelnyx-edge new-func --actor.
The Loop
From an umbrella project directory:.telnyx/dev, and boots it. Your fetch handler is served on http://localhost:8787 (change it with --port). Exercise it the same way the Quick Start exercises the deployed URL — but against localhost, and with actors resolving locally:
env.ACCOUNT.idFromName(...) call routes to a real actor instance in the local stack — the same code path that runs deployed. Edit your actor class or fetch handler and save; telnyx-edge dev watches the source and hot-reloads the affected runtime. Actor state lives in the stack’s Postgres store, so it survives a reload — alice is still 70 after you edit and save.
Press Ctrl-C to stop watching. The stack keeps running; the command only detaches the file watcher.
What the Stack Contains
telnyx-edge dev writes the stack under .telnyx/dev and runs it with docker compose. It is a local stand-in for the deployed platform, containing:
- the function runtime — serves your
fetchhandler on the published port; - one actor runtime per actor type — each hosts the instances of its own type, as each type gets its own deployment in production (CLI v0.5.12 and later; earlier versions run every type in one shared actor runtime);
- a Dapr sidecar for each runtime, plus Dapr placement — the routing layer that sends each actor name to its owner;
- a Postgres actor state store — where
ctx.storagepersists, so state survives reloads.
env.<BINDING> calls from the function runtime reach the actors in the actor runtimes through this layer.
Environment Variables
telnyx-edge dev (CLI v0.5.12 and later) delivers [env_vars] the way production does. Each actor runtime gets only its own type’s resolved environment — [env_vars.shared], then [env_vars.actor], then that type’s [[actors]] env_vars — and the function runtime gets the function’s set. Your code reads both through process.env. The manifest is validated with the same rules as ship (reserved names, the 50-variable cap, conflicting env_vars for one type), so a manifest ship would reject fails here before the stack starts. The start-up output lists what each runtime received:
PATH, PORT, and DAPR_HTTP_PORT in an actor scope are set by the local stack itself, so dev ignores your value with a warning. Secrets are not emulated locally: env.SECRETS is undefined under dev. See Environment variables for the scopes and their precedence. This is what a plain func.toml function lacks: it has no local binding emulation, so binding-backed code paths only run once deployed.
Flags
Use
--generate-only to inspect or customize the generated compose stack before booting it, and --no-watch when you want the stack up for an out-of-band test run (for example, from a CI script) rather than an interactive edit loop.
Notes
- Actor state survives reloads. Because
ctx.storagepersists to the stack’s Postgres store, a hot reload does not reset your instances — balances, counters, and any other state carry across saves. Tear the stack down withdocker compose(or remove.telnyx/dev) when you want a clean slate. - Ctrl-C leaves the stack running. It stops the watcher, not the containers. Stop the stack explicitly with
docker composewhen you’re done. - A
telnyx.tomlis required.telnyx-edge devruns umbrella projects. A single-functionfunc.tomlproject has no actors to host — develop those with the Functions local-dev workflow instead.
Next Steps
- Quick Start — scaffold, write, and deploy an
Accountactor end to end - Project structure — the two-export shape
telnyx-edge devruns - Deploy — ship, revisions, and rollback