Cells/ribo.toml Reference

ribo.toml Reference

Every Cell has a ribo.toml configuration file. ribo deploy reads it from the current directory by default, or from the path given by --config.


[cell]

The [cell] table is required.

[cell]
name  = "my-cell"          # required
js    = "./cell.js"        # required (or wasm, or static)
build = "npm run build"    # optional — run before uploading

Fields

Field Type Required Description
name string yes Human-readable name. Used to derive the stable address.
js string one of Path to the JavaScript entry point (relative to ribo.toml)
wasm string one of Path to the compiled .wasm file
static string one of Path to a local directory — deploys a static site with no JS required
build string no Shell command to run before deploying. Runs in the directory containing ribo.toml.
bindgen_glue string no Path to the wasm-bindgen JS glue file. Required when wasm is set and the binary uses wasm-bindgen.
account_id string no Pin this project to an account (acct_...). See Account pin.
account string no Human-readable label for the pinned account. Display-only — never enforced.

Exactly one of js, wasm, or static must be present.

Account pin

account_id pins the Cell to a specific account so it can't be deployed into the wrong one. When set, ribo deploy compares it against your active account (from your auth token) and refuses to deploy on a mismatch, before uploading anything:

[cell]
name       = "my-cell"
js         = "./cell.js"
account_id = "acct_3f8c1a2b4d6e8f00"   # only deployable from this account
account    = "Acme Corp"               # optional label, shown in output

The pin is an assertion, not a selector: it never changes which account is used, it only guards against deploying this workspace somewhere unintended. The optional account label is display-only and is never used for enforcement (account names are mutable; the id is the identifier). Generate the pin without hand-copying the id with ribo account pin.

Don't pin shared/example templates that others deploy into their own accounts — the pin would refuse their deploys.

The pin catches a wrong account; it doesn't choose the right one. If you regularly work across several accounts — or run agents that deploy for you — bind each project tree to its own credential with profiles, and keep the pin as the backstop.


[[bindings]]

Each [[bindings]] block declares a resource that the Cell can access at runtime. The binding name becomes a property on the env object passed to fetch.

c3 — SQLite database

[[bindings]]
type     = "c3"
binding  = "DB"        # env.DB in your cell
database = "myapp"     # database name (created with ribo db create)

Multiple databases:

[[bindings]]
type     = "c3"
binding  = "USERS"
database = "users"

[[bindings]]
type     = "c3"
binding  = "LOGS"
database = "request-logs"

g7 — Object storage bucket

[[bindings]]
type    = "g7"
binding = "IMAGES"     # env.IMAGES in your cell
bucket  = "avatars"    # bucket name (created with ribo bucket create)

files — Static file tree

[[bindings]]
type    = "files"
binding = "ASSETS"     # env.ASSETS in your cell
dir     = "./public"   # local directory to upload

Files are uploaded at deploy time and served from object storage. The binding has a fetch(request) method for URL-based serving and a get(key) method for direct access.

text — Plain string value

[[bindings]]
type    = "text"
binding = "API_KEY"    # env.API_KEY in your cell
value   = "sk-..."     # literal string value

Use text bindings for configuration, feature flags, or non-secret string values.

vault — Encrypted secret

[[bindings]]
type    = "vault"
binding = "JWT_SECRET"   # env.JWT_SECRET in your cell

A vault binding injects a secret value at dispatch time. Unlike text, the value is not stored in ribo.toml — only the key name is. The value itself is set separately with ribo vault set and stored encrypted server-side. Use vault bindings for API keys, signing secrets, database credentials, and any other sensitive value you don't want committed to source control.

ribo vault set my-cell JWT_SECRET    # set the value (prompts for hidden input)
ribo deploy                          # then deploy

Important: set the vault value with ribo vault set before deploying a cell that declares a vault binding. If the value is missing at deploy time the binding is stored as a placeholder, and the cell will receive that placeholder instead of the real secret — causing silent failures. See ribo vault for the full command reference.

For how vault values are protected — encryption at rest, when decryption happens, scopes, auditing, and rotation — see the Vault Security Model.


[[pulse]]

Each [[pulse]] block declares a cron schedule. The platform calls the Cell's pulse(event, env) handler at each scheduled time.

[[pulse]]
schedule = "0 * * * *"     # every hour at :00

[[pulse]]
schedule = "*/15 * * * *"  # every 15 minutes

Multiple [[pulse]] blocks are allowed. Each fires independently.

Fields

Field Type Required Description
schedule string yes 5-field POSIX cron expression (UTC). Validated at deploy time.

Cron syntax: min hour dom month dow. All times are UTC. Minimum interval is 1 minute.

See Pulse Overview for the handler interface and examples.


[server]

Override the default management API URL. Useful for local development.

[server]
url = "http://localhost:8082"

When omitted, ribo uses https://api.tissue.systems.


Complete example

[cell]
name  = "notes-app"
js    = "./dist/cell.js"
build = "esbuild src/cell.ts --bundle --outfile=dist/cell.js --format=esm"

[[pulse]]
schedule = "0 * * * *"     # hourly cleanup

[[bindings]]
type     = "c3"
binding  = "DB"
database = "notes"

[[bindings]]
type    = "g7"
binding = "UPLOADS"
bucket  = "note-attachments"

[[bindings]]
type    = "text"
binding = "APP_VERSION"
value   = "1.0.0"

Static site shorthand

For a Cell that only serves static files, the static field eliminates the need for a JS entry point entirely:

[cell]
name   = "my-site"
static = "./public"

ribo generates the pass-through worker automatically and deploys the directory contents. See Static Sites for routing behaviour and the hybrid (static + dynamic) pattern.