OHMOHM Studio

Studio CLI

Generate typed TypeScript interfaces from your published Studio API schemas.

View as Markdown

@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/cli

Quick 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 list

Use 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 OpdClinicRecord

ohm-studio pull-all

Generate types for every published API your credential can see.

ohm-studio pull-all
ohm-studio pull-all --out src/ohm

ohm-studio list

List APIs visible to your credential.

ohm-studio list
ohm-studio list --status DRAFT
ohm-studio list --status ALL

Options

OptionDefaultDescription
--out <dir>./ohm-typesOutput directory
--root-name<PascalSlug>DataOverride the generated interface name
--key$OHM_API_KEYAPI key or JWT for auth
--base-urlhttps://api.ohm.doctorOverride the OHM API base URL (self-host)
--statusPUBLISHEDPUBLISHED, DRAFT, ARCHIVED, or ALL

Environment variables

VariablePurpose
OHM_API_KEYAPI key (ohms_live_* / ohms_test_*) or Studio JWT
OHM_BASE_URLOverride 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 keysohms_live_* or ohms_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 fieldTypeScript
text, textareastring
rich-textstring | { markdown: string }
datestring (ISO YYYY-MM-DD)
numbernumber
booleanboolean
choicetyped string-literal union
multi-choiceArray<…> of typed string-literal union
vitals-block{ bp?: { systolic?, diastolic? }, hr?, rr?, … }
diagnosis-listArray<{ code?, system?, name, status? }>
medication-listArray<{ name, dosage?, frequency?, route?, … }>
allergy-listArray<{ substance, reaction?, severity? }>
investigation-listArray<{ code?, name, notes? }>
referral-listArray<{ name, specialty?, reason? }>
procedure-listArray<{ name, code?, date?, notes? }>
code-listArray<{ code?, system?, name }>
repeaterArray<NestedItem> (named <Root><Field>Item)

The output is dependency-free — pure TypeScript interfaces with JSDoc generated from each field's label, description, and helpText.