CLI
yoke CLI commands — dev, compile, run, control plane, worker, and development workflows.
The yoke CLI is the authoring and ops entry point — iterate on an internal package, compile a CLI crate or an embeddable library. It is not the product your users run. Production is compile --crate into your workspace.
Command overview
| Command | Purpose |
|---|---|
yoke dev | Author hot path — run package from source |
yoke start | Alias for yoke dev |
yoke compile | CLI binary crate (run / control-plane / worker, TS baked in) |
yoke compile --crate | Library crate for product workspaces (no binary) |
yoke run | Colocated production — CP + worker, one process |
yoke control-plane | Multi-tenant scheduler + HTTP API |
yoke worker start | Standalone tenant executor |
yoke append | Inject a test event |
yoke migrate | Run database migrations |
yoke tenant-create | Register a tenant row (package ref) |
yoke executor start | Start a tenant-scoped executor (Docker sandbox entrypoint) |
See Compile & deploy for the full compile/run workflow.
yoke dev / yoke start
Boot a user package from source (single tenant, no control plane):
export DATABASE_URL=postgres://yoke:yoke@localhost:5432/yoke
export YOKE_STORAGE=pg_sqlite
yoke dev ./your-package --database "$DATABASE_URL"| Flag | Env | Default | Purpose |
|---|---|---|---|
package | required | Path to user package | |
--database | DATABASE_URL | Postgres URL | |
--storage | YOKE_STORAGE | pg_sqlite | pg_sqlite or s3 |
--tenant-id | YOKE_TENANT_ID | default | Tenant scope |
--port | YOKE_PORT | 8080 | Portal HTTP port |
--data-dir | YOKE_DATA_DIR | .yoke-data | Local runtime data |
yoke compile
yoke compile ./your-package -o dist/my-app
yoke compile ./packages/runtime -o ./crates/yoke --crate| Flag | Purpose |
|---|---|
-o, --output | Output directory for the generated crate |
--no-bundle | Skip deno bundle |
--crate | Library crate (no binary); omit for CLI binary crate |
yoke run
Colocated single-tenant — control plane + in-process worker:
yoke run \
--package ./your-package \
--database "$DATABASE_URL" \
--cp-port 8090| Flag | Env | Default | Purpose |
|---|---|---|---|
--package | required | Compiled dir or source tree | |
--database | DATABASE_URL | Postgres URL | |
--cp-port | YOKE_CONTROL_PLANE_PORT | 8090 | Control plane HTTP |
--tenant-id | YOKE_TENANT_ID | default | Tenant scope |
--storage | YOKE_STORAGE | pg_sqlite | Storage backend |
--data-dir | YOKE_DATA_DIR | .yoke-data | Runtime data |
yoke append
Inject test events without writing code:
yoke append \
--database "$DATABASE_URL" \
--type slack.message.received \
--payload '{"channel":"#general","text":"hello"}'Control plane
Start multi-tenant control plane (scheduler + HTTP API):
yoke control-plane --database "$DATABASE_URL" --port 8090Exposes conversation HTTP API, schedules, tenant management, and tenant ingress proxy. See HTTP API.
yoke tenant-create
Register a tenant in Postgres before using control plane APIs:
yoke tenant-create \
--database "$DATABASE_URL" \
--id acme \
--package-ref ./your-packageEquivalent to POST /v1/tenants. The scheduler uses package_ref to resolve the user package when waking a cold executor.
Worker
Standalone tenant executor:
yoke worker start \
--database "$DATABASE_URL" \
--tenant-id acme \
--package ./your-packageyoke executor start
Tenant-scoped executor entrypoint (used inside Docker sandboxes; sets YOKE_EXECUTOR_MODE):
yoke executor start \
--database "$DATABASE_URL" \
--tenant-id acme \
--package-ref ./your-package \
--data-dir /data \
--port 8080| Flag | Env | Default | Purpose |
|---|---|---|---|
--tenant-id | YOKE_TENANT_ID | required | Tenant scope |
--package-ref | YOKE_PACKAGE_REF | required | Local path or remote package ref |
--data-dir | YOKE_DATA_DIR | /data | Runtime data directory |
--storage | YOKE_STORAGE | pg_sqlite | Storage backend |
--port | YOKE_PORT | 8080 | Portal HTTP port |
If package_ref is a local path that exists, it is used directly. Otherwise the runtime resolves the ref into --data-dir/package.
Rust crate embedding
yoke compile --crate writes a library with the package baked in. Your crates depend on that — they do not pass a yoke.ts path.
let rt = my_pkg::start_colocated(database, data_dir, "default", 8090).await?;
let worker = my_pkg::start_worker("default", database, data_dir, 8080).await?;For a standalone executor CLI, yoke compile (no --crate) emits a binary crate instead.
Full walkthrough: Embed Yoke in your product.
Development workflow
# Terminal 1: Postgres
docker compose up -d
# Terminal 2: Dev runtime
export DATABASE_URL=postgres://yoke:yoke@localhost:5432/yoke
export YOKE_STORAGE=pg_sqlite
yoke dev ./your-package --database "$DATABASE_URL"
# Terminal 3: Test event
yoke append \
--database "$DATABASE_URL" \
--type slack.message.received \
--payload '{"channel":"#general","text":"build feature X"}'