Cheela Labs
START

Installation

Cheela is a set of small packages rather than one framework. Install the two or three that match what you are building.

Requirements

  • Node 22 or newer. Every package declares engines.node >= 22; the runtime uses crypto.randomUUID and node:crypto’s timing-safe comparison.
  • A package manager. The monorepo uses pnpm; npm and yarn work identically for consumers.
  • An HTTPS endpoint if you are serving capabilities. Cheela calls in, so a local runtime needs a tunnel.

Which packages

Serving capabilities

The common case: your product exposes things a model can do. You need the CLI to deploy, and the runtime to serve.

Terminal
npm install @cheela/runtime @cheela/sdk
npm install -D @cheela/cli

@cheela/sdk is a peer of the runtime — it holds the Capability and Action types, plus the naming rules both the CLI and the control plane enforce. You will also want a schema library; every example here uses Zod, but anything exposing parse(value) satisfies the Schema interface.

Embedding chat in React

Terminal
npm install @cheela/ui

@cheela/ui re-exports the types you need from @cheela/client, so most React projects never depend on it directly.

Embedding chat without a build step

index.html
<script src="https://unpkg.com/@cheela/web-component/dist/cheela-chat.js"></script>
<cheela-chat api-key="ch_pk_..."></cheela-chat>

The custom element registers itself and lazily fetches its own core chunk, so the tag in the markup costs almost nothing until it mounts.

Everything else

PACKAGEINSTALL IT WHEN
@cheela/clientYou are building a chat UI for a framework that is not React.
@cheela/protocolYou need the wire types (Message, ExecutionResult) without a client.
@cheela/providerYou are calling OpenAI, Anthropic, Gemini or OpenRouter through one interface, outside Cheela.
@cheela/adpYou are reading or validating Agent Discovery Specification manifests.

Project layout

cheela init writes a conventional layout. Nothing here is magic — every path is configurable — but the defaults are what the CLI looks for.

Project
.
├── .cheela/
│   ├── runtime.ts              # you write this — capabilities live here
│   ├── generated/              # commit this — reviewable in PRs
│   │   ├── capability-manifest/capabilities.json
│   │   ├── runtime-manifest/runtime.json
│   │   ├── openapi/openapi.json
│   │   └── adp/agent-discovery.json
│   └── generate.cache.json     # gitignored — incremental build cache
├── cheela.config.ts
├── .env
└── package.json
Commit .cheela/generated

The generated artifacts are diffable. Committing them means a pull request shows exactly how a capability’s published schema changed, which is the review you want before a stranger’s agent starts relying on it. Only generate.cache.json is local.

To keep capabilities somewhere else, point runtime at it:

cheela.config.ts
export default defineConfig({
  apiKey: process.env.CHEELA_API_KEY!,
  runtime: "src/cheela/capabilities.ts",
});

Environment variables

The CLI loads .env from the project root before it evaluates cheela.config.ts, so process.env is populated by the time your config reads it.

VARIABLEUSED BYWHAT IT IS
CHEELA_API_KEYCLIThe deploy key, ch_sk_…. Authorises deploy and status. Secret.
CHEELA_RUNTIME_SECRETYour endpointVerifies Cheela’s request signature. Shown when the runtime is created.
CHEELA_RUNTIME_IDYour endpointOptional. Pins signatures to one runtime, so a signature minted for another is rejected.
Never default the runtime secret

Reading it as process.env.CHEELA_RUNTIME_SECRET ?? "" verifies every signature against the empty string, so every request fails as signature_mismatch — which reads like a wrong key and sends you off rotating a credential that was fine. Throw instead.

TypeScript and bundlers

Every package ships ESM with type declarations and no CommonJS build. Set "type": "module" in your package.json, and use "moduleResolution": "bundler" or "nodenext".

The CLI evaluates cheela.config.ts and your runtime module through tsx, so neither file needs compiling before cheela deploy — and neither ends up in your application bundle unless you import it there.

@cheela/ui marks its components "use client" internally. In the Next.js App Router you can render <CheelaProvider> directly from a Server Component; the boundary is drawn for you.