Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting Started

Start from the workspace template

Don’t start an empty project. interbox-workspace is the reference pipeline template — fork it, adjust for your own data, and deploy:

git clone https://github.com/HealthSamurai/interbox-workspace.git
cd interbox-workspace
docker compose up

No .env to copy first — every setting docker-compose.yaml reads has a built-in default (AIDBOX_CLIENT_SECRET, INTERBOX_VERSION, …), and the image is licensed but there’s no manual key to paste in either: the dashboard’s first-run portal OAuth flow signs both the Interbox and Aidbox licenses for you — the pipeline just stays paused (with an activation screen) until you click through it once.

Open http://localhost:3001 for the dashboard, then send HL7v2 over MLLP to localhost:2575 and watch messages flow through to the FHIR server.

No MLLP client handy? The dashboard’s Sources screen has a “Simulate message” panel on each non-facility source — paste raw HL7v2 (or drag in .hl7/text files) and hit Send. It’s not a dry run: the pasted message goes through the exact same parse → mapper → sender path as a real MLLP write, so it’s a fine way to poke the pipeline before wiring up a real sender.

Copy .env.example to .env only if you want to override a default — pinning INTERBOX_VERSION, setting a real AIDBOX_CLIENT_SECRET, or pointing at a private registry.

# postinstall runs `interbox sync` automatically, mirroring this package's
# skills/interbox/* into .claude/skills/interbox-*
bun install
bun run typecheck
bun test

How a workspace is laid out

src/
  index.ts             # imports ./mappers and ./pipelines (registration side effects),
                        # re-exports { MapperRegistry, PipelineRegistry } for the engine
  mappers/
    index.ts           # imports every mapper module
    v2-to-fhir/…        # your defineMapper() implementations
  pipelines/
    index.ts           # imports every pipeline module
    hl7-to-aidbox/index.ts
// src/index.ts
import "./mappers";
import "./pipelines";
export { MapperRegistry, PipelineRegistry } from "@health-samurai/interbox";
// src/pipelines/hl7-to-aidbox/index.ts
import { env, pipeline } from "@health-samurai/interbox";
import {
  aidboxSender,
  hl7v2Parser,
  mllpSource,
} from "@health-samurai/interbox/builtins";
import { v2ToFhirMapper } from "../../mappers/v2-to-fhir/index.ts";

pipeline("hl7-to-aidbox")
  .source(
    mllpSource({
      id: "mllp-default",
      host: env("MLLP_HOST"),
      port: env("MLLP_PORT"),
      parser: hl7v2Parser({ skipZSegments: false }),
    }),
  )
  .mapper(v2ToFhirMapper())
  .sender(
    aidboxSender({
      url: env("AIDBOX_URL"),
      auth: { kind: "basic", user: env("AIDBOX_CLIENT_ID", "root"), password: env("AIDBOX_CLIENT_SECRET") },
    }),
  );

Every stage is referenced by value (built-in descriptors + your own mapper), so types — including the source↔mapper parser match, see Pipelines — are checked at compile time. Deployment values (MLLP_HOST, AIDBOX_URL, secrets) come from env(), resolved by the engine when it builds the runner config — see Env & Config.

The engine bundles src/index.ts itself — a workspace has no build step of its own. It takes one INTERBOX_WORKSPACE_GIT_URL: a remote URL (clones + bun installs, for deploy) or a local file:///bare path (bundles the live working tree in place, no clone/install, for a fast edit → hot-reload loop). A pipeline change reloads into its own runtime, not by restarting interbox itself: in local dev the engine polls the workspace (INTERBOX_WORKSPACE_POLL_MS, 2s in the template’s docker-compose.yaml) and swaps workers in place; elsewhere, trigger the same reload from the dashboard (“Pull now”).