Skip to content

CLI Reference ​

BabelFHIR-TS: Generate TypeScript interfaces from FHIR StructureDefinitions

Usage:
  babelfhir-ts [options] [<input> [output]]
  babelfhir-ts install [--package] <pkg[@version]|path> [--registry <url>] [options]
  babelfhir-ts update [<pkg@version>] [--recursive] [options]
  babelfhir-ts seed-cache

Arguments:
  input   Input can be:
          - Canonical URL of a FHIR profile (http://... or https://...)
          - Directory containing FHIR packages (.tgz/.zip files)
          - Single FHIR package (.tgz/.zip file)
          - Single StructureDefinition (.json file)
          - Directory containing StructureDefinition files
  output  Output directory or archive name (optional)

Commands:
  install                Download, process, and npm install package as dependency
  update                 Regenerate all installed packages (or a specific one) with current babelfhir-ts
  seed-cache             Install FHIR packages embedded in node_modules into the FHIR cache as <id>#dev

Options:
  -h, --help               Show this help message
  -v, --version            Show version number
  --log <dest>             Log destination: console (default) or file
  --log-level <level>      Log verbosity: error, warn, info (default), or debug
  --cache-dir <path>       Custom cache directory (default: ~/.fhir/packages for FHIR packages, .cache for working files)
  --no-cache               Delete .cache working folder after generation (does not affect shared ~/.fhir/packages)
  --no-classes             Only generate interfaces and types (skip class generation)
  --no-client              Skip FHIR client generation (client generated by default)
  --schema <format>        Generate schema files alongside outputs (supported: zod)
  --zod-invariants         Emit FHIRPath invariants into Zod schemas (fuller checking, slower parse)
  --dicomweb               Generate DICOMweb helpers typed to ImagingStudy profiles in the IG
  --prefab                 Generate Prefab UI render functions per profile (@maxhealth.tech/prefab)
  --prefab-styles <path>   Path to styles module (.ts/.js) copied into the generated prefab/ folder
  --recursive              (update only) Recursively search subdirectories for lib/ folders
  --force                  (update only) Force regeneration even if version and flags haven't changed
  --skip-install           (install/update) Write the tarball without running a package manager install
  --embed-fhir-package     (install/update) Ship the source FHIR package in the generated package, for seed-cache
  --outDir <dir>           Output directory (alias for second positional argument)
  --fhir-version <ver>     FHIR version to target: r4, r4b, or r5 (auto-detected from package if omitted)
  --package <pkg[@version]>  Download FHIR package from registry and process it (latest if no version)
  --registry <url>         FHIR package registry URL (default: https://packages.simplifier.net)
  --tx-server <url>        Terminology server URL for ValueSet expansion (e.g., https://tx.fhir.org/r4)
                           When set, expands ValueSets without explicit codes using $expand operation
  --display-language <lang> BCP-47 language(s) for display terms (e.g., de or de,fr,en).
                           Single value replaces concept displays. Comma-separated values
                           also generate a multi-language display map with getDisplay() helper.
  --max-codes <n>          Max concepts kept per expanded ValueSet (default: 100).
                           Sent as the $expand count; a larger ValueSet is truncated to it.
  --union-threshold <n>    Cap the concepts for which a ValueSet Code type is a
                           string-literal union. Uncapped by default; above a cap
                           the type is "string". For a pathological IG only.

Examples:
  babelfhir-ts                                             # Process ./input to ./output
  babelfhir-ts http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient  # Generate from profile URL
  babelfhir-ts package.tgz                                 # Process package to current directory
  babelfhir-ts package.tgz modified-package.tgz            # Embed interfaces in package
  babelfhir-ts profiles/ generated/                        # Process directory to directory
  babelfhir-ts --package hl7.fhir.us.core@8.0.0            # Download and process from default registry
  babelfhir-ts --package hl7.fhir.us.core@8.0.0 output/    # Download and output to directory
  babelfhir-ts --package pkg@version --log console --log-level debug  # With verbose logging
  babelfhir-ts install de.gematik.isik-basismodul                           # Download latest, process, and install
  babelfhir-ts install de.gematik.isik-basismodul@3.1.0                   # Download specific version
  babelfhir-ts install ./package.tgz                                      # Install from local package file
  babelfhir-ts install hl7.fhir.us.core@8.0.0 --registry <url>            # Install from custom registry
  babelfhir-ts install --package hl7.fhir.us.core@8.0.0 --registry <url>  # Alternative syntax
  babelfhir-ts update                                                      # Regenerate all packages in ./lib
  babelfhir-ts update hl7.fhir.us.core@8.0.0                               # Regenerate a specific package
  babelfhir-ts update --recursive                                          # Regenerate packages in all subdirectories

Supported Inputs ​

  • Directory — scan all .tgz, .zip, or .json files inside the folder
  • Archive — process a FHIR NPM package in .tgz or .zip format
  • StructureDefinition JSON — generate code for a single profile definition
  • Canonical URL — fetch a profile by URL and generate code from it

Caching ​

The generator caches downloaded StructureDefinitions and packages inside .cache/. When you need a clean run, pass --no-cache or manually remove the folder. Temporary downloads land in .temp-* directories and are cleaned up automatically.

The cache directory can be customized with --cache-dir <path> or the FHIR_CACHE_ROOT environment variable.

Install Command ​

babelfhir-ts install downloads a FHIR package, generates TypeScript code, compiles it, and installs it as a local dependency in your project:

bash
babelfhir-ts install hl7.fhir.us.core@8.0.0
babelfhir-ts install ./local-package.tgz
babelfhir-ts install de.gematik.isik-basismodul    # latest version

The install command:

  1. Downloads the package (or reads from a local path)
  2. Generates interfaces, validators, classes, and client
  3. Compiles to JavaScript + .d.ts declarations
  4. Packs the output into a .tgz in your project's lib/ folder
  5. Runs npm install (or bun add, pnpm add — auto-detected) to add the dependency

Package Manager Detection ​

The install command auto-detects your package manager by checking for lockfiles:

LockfileManager Used
bun.lockb / bun.lockbun add
pnpm-lock.yamlpnpm add
package-lock.jsonnpm install

In monorepos, it walks up the directory tree to find the nearest lockfile.

Bun Compatibility ​

When using Bun, the install command automatically patches bun.lock integrity hashes after installation to work around Bun's strict hash checking for local .tgz dependencies.

Depending on your own IG through npm ​

A FHIR IG can depend on another IG that is only published as a generated npm package, for example on a private registry that FHIR tooling cannot read:

bash
# In the IG being depended on: ship the FHIR package inside the generated package
babelfhir-ts install ./my.core-0.1.0.tgz --embed-fhir-package

# In the dependent IG: install that npm package, then before SUSHI
babelfhir-ts seed-cache

--embed-fhir-package copies the source FHIR package into fhir-package/ of the generated package. seed-cache finds every installed package carrying one (walking up through each node_modules, nearest first) and installs it into the FHIR package cache as <id>#dev. Declare the dependency as my.core: dev in sushi-config.yaml: SUSHI and babelfhir-ts read #dev from the cache and never ask a registry for it, so the npm lockfile alone decides which build it is.

Update Command ​

babelfhir-ts update regenerates all previously installed packages with the current version of BabelFHIR-TS:

bash
babelfhir-ts update                              # Regenerate all packages in ./lib
babelfhir-ts update --force                       # Regenerate even if already up to date

Smart Skip (Up-to-Date Detection) ​

The update command checks whether each package was already generated with the same babelfhir-ts version and same generation flags. If nothing has changed, the package is skipped:

$ babelfhir-ts update
Found 2 packages to update:

  hl7.fhir.us.davinci-dtr@2.1.0  →  lib/hl7.fhir.us.davinci-dtr-generated.tgz
  hl7.fhir.us.davinci-pas@2.0.1  →  lib/hl7.fhir.us.davinci-pas-generated.tgz

✓ hl7.fhir.us.davinci-dtr@2.1.0 — already up to date (babelfhir-ts 1.4.2)
✓ hl7.fhir.us.davinci-pas@2.0.1 — already up to date (babelfhir-ts 1.4.2)

✓ 2 packages already up to date
  Use --force to regenerate anyway.

A package is considered up to date when:

  • The stored babelfhir-ts version (major.minor.patch) matches the currently running version
  • No CLI flags were passed that differ from the stored generation settings

A package is always regenerated when:

  • It was generated with an older babelfhir-ts version
  • A CLI flag is explicitly passed that differs from the stored value (e.g. --tx-server changed)
  • The --force flag is used
  • No version metadata is stored (packages generated before this feature)elfhir-ts update hl7.fhir.us.core@8.0.0 # Regenerate a specific package babelfhir-ts update --recursive # Search subdirectories for lib/ folders babelfhir-ts update --force # Regenerate even if already up to date

### Smart Skip (Up-to-Date Detection)

The update command checks whether each package was already generated with the **same babelfhir-ts version** and **same generation flags**. If nothing has changed, the package is skipped:

$ babelfhir-ts update Found 2 packages to update:

hl7.fhir.us.davinci-dtr@2.1.0 → lib/hl7.fhir.us.davinci-dtr-generated.tgz hl7.fhir.us.davinci-pas@2.0.1 → lib/hl7.fhir.us.davinci-pas-generated.tgz

✓ hl7.fhir.us.davinci-dtr@2.1.0 — already up to date (babelfhir-ts 1.4.2) ✓ hl7.fhir.us.davinci-pas@2.0.1 — already up to date (babelfhir-ts 1.4.2)

✓ 2 packages already up to date Use --force to regenerate anyway.


A package is considered **up to date** when:
- The stored `babelfhir-ts` version (major.minor.patch) matches the currently running version
- No CLI flags were passed that differ from the stored generation settings

A package is **always regenerated** when:
- It was generated with an older babelfhir-ts version
- A CLI flag is explicitly passed that differs from the stored value (e.g. `--tx-server` changed)
- The `--force` flag is used
- No version metadata is stored (packages generated before this feature)

### Settings Preservation

The update command reads the `fhir` metadata block from each generated package's `package.json` (see [Package Metadata](./generated-code#package-metadata)) and reuses the original generation settings:

- `--tx-server` — terminology server URL
- `--display-language` — language(s) for display terms
- `--max-codes` — cap on concepts per expanded ValueSet
- `--fhir-version` — target FHIR version
- `--dicomweb` — DICOMweb helper generation
- `--no-client` — client generation flag
- `--no-classes` — class generation flag
- `--schema` — schema format

You can override any saved setting by passing the flag explicitly on the command line.

### Install Redirect

If you run `babelfhir-ts update <pkg>` for a package that isn't installed yet, it will prompt you to install it instead.

## Dependency Resolution

When processing a FHIR package, BabelFHIR-TS automatically downloads transitive dependency packages listed in the IG's `package.json`. Dependencies are fetched from two registries in fallback order:

1. [Simplifier](https://packages.simplifier.net) (default)
2. [FHIR Package Registry](https://packages2.fhir.org/packages)

Use `--registry <url>` to set a custom primary registry.

Released under the ISC License.