Yoke.sh
Deployment

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

CommandPurpose
yoke devAuthor hot path — run package from source
yoke startAlias for yoke dev
yoke compileCLI binary crate (run / control-plane / worker, TS baked in)
yoke compile --crateLibrary crate for product workspaces (no binary)
yoke runColocated production — CP + worker, one process
yoke control-planeMulti-tenant scheduler + HTTP API
yoke worker startStandalone tenant executor
yoke appendInject a test event
yoke migrateRun database migrations
yoke tenant-createRegister a tenant row (package ref)
yoke executor startStart 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"
FlagEnvDefaultPurpose
packagerequiredPath to user package
--databaseDATABASE_URLPostgres URL
--storageYOKE_STORAGEpg_sqlitepg_sqlite or s3
--tenant-idYOKE_TENANT_IDdefaultTenant scope
--portYOKE_PORT8080Portal HTTP port
--data-dirYOKE_DATA_DIR.yoke-dataLocal runtime data

yoke compile

yoke compile ./your-package -o dist/my-app
yoke compile ./packages/runtime -o ./crates/yoke --crate
FlagPurpose
-o, --outputOutput directory for the generated crate
--no-bundleSkip deno bundle
--crateLibrary 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
FlagEnvDefaultPurpose
--packagerequiredCompiled dir or source tree
--databaseDATABASE_URLPostgres URL
--cp-portYOKE_CONTROL_PLANE_PORT8090Control plane HTTP
--tenant-idYOKE_TENANT_IDdefaultTenant scope
--storageYOKE_STORAGEpg_sqliteStorage backend
--data-dirYOKE_DATA_DIR.yoke-dataRuntime 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 8090

Exposes 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-package

Equivalent 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-package

yoke 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
FlagEnvDefaultPurpose
--tenant-idYOKE_TENANT_IDrequiredTenant scope
--package-refYOKE_PACKAGE_REFrequiredLocal path or remote package ref
--data-dirYOKE_DATA_DIR/dataRuntime data directory
--storageYOKE_STORAGEpg_sqliteStorage backend
--portYOKE_PORT8080Portal 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"}'

On this page