Studio CLI
Generate typed TypeScript interfaces from your published Studio API schemas.
@ohm_studio/cli is the codegen companion to @ohm_studio/sdk. Pull
your published Studio API schemas and emit typed TypeScript interfaces
so ohm.extract<MyApiData>(...) is fully typed against the schema you
designed in Studio.
Install
npm install -D @ohm_studio/cli
# or globally
npm install -g @ohm_studio/cliQuick start
export OHM_API_KEY=ohms_live_xxx
# Generate types for one API
ohm-studio pull opd-clinic
# → ./ohm-types/opd-clinic.ts
# Generate types for every published API
ohm-studio pull-all --out src/ohm
# What's published?
ohm-studio listUse the generated types
import { OHM } from "@ohm_studio/sdk";
import type { OpdClinicData } from "./ohm-types/opd-clinic";
const ohm = new OHM(process.env.OHM_API_KEY!);
const { data } = await ohm.extract<OpdClinicData>({
apiSlug: "opd-clinic",
text: transcript,
});
// `data` is fully typed — autocomplete, type-checked, jump-to-definition
data.diagnoses.forEach((d) => {
console.log(d.name, d.code); // ICD-10 code, optional
});Pre-build hook
Add codegen to your package.json so the types stay in sync with what
you've published in Studio:
{
"scripts": {
"predev": "ohm-studio pull-all --out src/ohm",
"prebuild": "ohm-studio pull-all --out src/ohm"
}
}Now every npm run dev and npm run build regenerates the type
definitions before your app code compiles. If a teammate pushed a
schema change in Studio, you'll see it as a TypeScript diff on the
next build.
Commands
ohm-studio pull <slug>
Generate types for one API. Writes <outDir>/<slug>.ts.
ohm-studio pull opd-clinic
ohm-studio pull opd-clinic --out src/ohm
ohm-studio pull opd-clinic --root-name OpdClinicRecordohm-studio pull-all
Generate types for every published API your credential can see.
ohm-studio pull-all
ohm-studio pull-all --out src/ohmohm-studio list
List APIs visible to your credential.
ohm-studio list
ohm-studio list --status DRAFT
ohm-studio list --status ALLOptions
| Option | Default | Description |
|---|---|---|
--out <dir> | ./ohm-types | Output directory |
--root-name | <PascalSlug>Data | Override the generated interface name |
--key | $OHM_API_KEY | API key or JWT for auth |
--base-url | https://api.ohm.doctor | Override the OHM API base URL (self-host) |
--status | PUBLISHED | PUBLISHED, DRAFT, ARCHIVED, or ALL |
Environment variables
| Variable | Purpose |
|---|---|
OHM_API_KEY | API key (ohms_live_* / ohms_test_*) or Studio JWT |
OHM_BASE_URL | Override the OHM API base URL |
Programmatic API
You can also call the codegen from a Node script — useful when you want to weave it into a larger build pipeline.
import { pull, list, generateTypes } from "@ohm_studio/cli";
// 1) Discover, then pull
const apis = await list({
apiKey: process.env.OHM_API_KEY!,
baseUrl: "https://api.ohm.doctor",
status: "PUBLISHED",
});
for (const a of apis) {
await pull({
slug: a.slug,
apiKey: process.env.OHM_API_KEY!,
baseUrl: "https://api.ohm.doctor",
outDir: "./src/ohm",
});
}
// 2) Or run codegen against a schema you already have in memory
const ts = generateTypes(localSchema, { rootName: "MySchemaData" });Auth
The CLI accepts:
- API keys —
ohms_live_*orohms_test_*. Project-scoped. Returns the published APIs in that project. - Studio user JWTs — organisation-wide. Returns every published API in your org.
Pass either via OHM_API_KEY env var or --key <token>.
Treat live keys as production credentials. The CLI is happy to read them from your shell history — keep them in a secrets manager and source them only at codegen time. Never commit a live key to source control or paste one into a CI log.
Field-type coverage
The codegen handles every Studio field type:
| Studio field | TypeScript |
|---|---|
text, textarea | string |
rich-text | string | { markdown: string } |
date | string (ISO YYYY-MM-DD) |
number | number |
boolean | boolean |
choice | typed string-literal union |
multi-choice | Array<…> of typed string-literal union |
vitals-block | { bp?: { systolic?, diastolic? }, hr?, rr?, … } |
diagnosis-list | Array<{ code?, system?, name, status? }> |
medication-list | Array<{ name, dosage?, frequency?, route?, … }> |
allergy-list | Array<{ substance, reaction?, severity? }> |
investigation-list | Array<{ code?, name, notes? }> |
referral-list | Array<{ name, specialty?, reason? }> |
procedure-list | Array<{ name, code?, date?, notes? }> |
code-list | Array<{ code?, system?, name }> |
repeater | Array<NestedItem> (named <Root><Field>Item) |
The output is dependency-free — pure TypeScript interfaces with JSDoc
generated from each field's label, description, and helpText.