Cascade Protocol CLI v0.3.3 — Requires Node.js 18+. All processing runs locally on your machine.

Prerequisites

Before you begin, make sure you have the following installed:

Node.js 18+
Runtime
npm
Included with Node.js

Verify your Node.js version:

node --version
# v18.0.0 or higher
1

Install the CLI

Install the CLI globally so the cascade command is available anywhere:

Terminal
npm install -g @the-cascade-protocol/cli

Verify the installation:

Terminal
cascade --version
cascade --help

The CLI bundles the Cascade Protocol SHACL shapes and all conversion logic. It has no external network dependencies — every operation runs entirely on your machine.

Available commands

Command Description
cascade validate Validate Turtle files against SHACL shapes
cascade convert Convert between FHIR R4 JSON and Cascade Turtle
cascade pod init Create a new Pod directory structure
cascade pod info Show Pod metadata and record counts
cascade pod query Query records from a Pod by type
cascade pod export Export a Pod as a ZIP archive or directory
cascade pod import Convert FHIR files and import them directly into a Pod, splitting records by type and updating type indexes v0.3.3
cascade reconcile Merge Cascade Turtle files from multiple EHR systems, resolving duplicates and conflicts
cascade conformance run Run the conformance test suite against fixtures
cascade serve --mcp Start a local MCP-compatible agent server
cascade capabilities Print machine-readable tool descriptions as JSON
2

Initialize a Pod

A Pod is a local directory that organizes your health data into a standard structure. Create one with pod init:

Terminal
cascade pod init ./my-health-pod
Expected output
Cascade Pod initialized at: ./my-health-pod

Created:
  .well-known/solid
  profile/card.ttl
  settings/publicTypeIndex.ttl
  settings/privateTypeIndex.ttl
  clinical/
  wellness/
  index.ttl
  README.md

Next steps:
  1. Edit profile/card.ttl to set patient name and demographics
  2. Add data files to clinical/ and wellness/ directories
  3. Run: cascade pod info ./my-health-pod

View Pod metadata at any time with pod info:

Terminal
cascade pod info ./my-health-pod
3

Convert FHIR data

Apple Health, Epic MyChart, and most EHR patient portals can export your records as FHIR R4 JSON. Use convert to transform them into Cascade Protocol Turtle:

Terminal
cascade convert patient-export.json --from fhir --to cascade

This outputs Turtle to stdout. Redirect it to a file or pipe it directly into your Pod:

Terminal
# Save to a file
cascade convert patient-export.json --from fhir --to cascade \
  > ./my-health-pod/clinical/medications.ttl

# Or read from stdin (for piping)
cat patient-export.json | cascade convert --from fhir --to cascade
Example output (FHIR MedicationStatement → Cascade Turtle)
@prefix cascade: <https://ns.cascadeprotocol.org/core/v1#> .
@prefix health: <https://ns.cascadeprotocol.org/health/v1#> .
@prefix clinical: <https://ns.cascadeprotocol.org/clinical/v1#> .
@prefix rxnorm: <http://www.nlm.nih.gov/research/umls/rxnorm/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<urn:uuid:3d441e1f-1578-46f3-b2fb-32f59ae808a5> a health:MedicationRecord ;
    cascade:dataProvenance cascade:ClinicalGenerated ;
    cascade:schemaVersion "1.3" ;
    health:medicationName "Metformin HCl 500mg" ;
    health:isActive true ;
    health:rxNormCode rxnorm:860975 ;
    health:dose "500mg twice daily" ;
    health:startDate "2024-01-15T00:00:00Z"^^xsd:dateTime .

Converted 1 resource (fhir -> turtle)

The converter handles FHIR Bundles (multiple resources at once) as well as single resources. It maps FHIR resource types to the appropriate Cascade vocabularies and preserves coded values like RxNorm, SNOMED CT, LOINC, and ICD-10.

To get machine-readable JSON output instead of raw Turtle, use --json:

Terminal
cascade convert patient-export.json --from fhir --to cascade --json

Import manifest

Add --manifest to write a sidecar JSON file that records exactly what was converted, what types were preserved as Layer 1 passthrough, and what was intentionally excluded and why.

Terminal
cascade convert patient-export.json --from fhir --to cascade \
  --source-system my-ehr --manifest \
  > patient.ttl
# Also writes: patient-export-manifest.json
patient-export-manifest.json
{
  "sourceFile": "patient-export.json",
  "sourceSystem": "my-ehr",
  "convertedAt": "2026-03-12T10:00:00.000Z",
  "summary": {
    "total": 47,
    "fullyMapped": 41,
    "passthrough": 2,
    "excluded": 4
  },
  "byType": {
    "MedicationStatement": { "count": 8, "strategy": "mapped" },
    "Condition": { "count": 12, "strategy": "mapped" },
    "Encounter": { "count": 6, "strategy": "mapped" },
    "Procedure": { "count": 7, "strategy": "mapped" },
    "DiagnosticReport": { "count": 4, "strategy": "mapped" },
    "Claim": { "count": 4, "strategy": "mapped" },
    "QuestionnaireResponse": { "count": 2, "strategy": "passthrough" },
    "CareTeam": { "count": 3, "strategy": "excluded",
      "reason": "Personnel registry. Care team context is captured via encounter provenance." },
    "Medication": { "count": 1, "strategy": "excluded",
      "reason": "Standalone medication definitional resources. Clinical meaning is in MedicationRequest/Statement." }
  }
}

You can specify a custom manifest path with --manifest path/to/my-manifest.json.

Exporting Cascade Turtle back to FHIR

The same convert command handles the reverse direction. Use --from cascade --to fhir to produce a FHIR R4 Bundle from a Cascade Turtle file:

Terminal
cascade convert --from cascade --to fhir reconciled-patient.ttl \
  > patient-fhir-export.json

Records converted with full Layer 2 mapping export with all original fields. Records preserved as Layer 1 passthrough (types without a full Cascade vocabulary mapping) are restored verbatim from the embedded cascade:fhirJson triple — the original FHIR JSON is preserved inline in the Turtle file for exactly this purpose.

4

Import FHIR Data into a Pod v0.3.3

cascade pod import is the recommended way to populate a Pod from FHIR data. It combines conversion, type-based splitting, and Pod index registration into a single command — replacing the manual convert-then-copy workflow for most use cases.

Recommended workflow: pod initpod importpod query. The pod import command handles conversion, splitting records by type, and updating the type index in one step.

Single-source import

Pass a FHIR JSON file and the Pod directory. Use --source-system to tag all imported records with the originating system name (used later for reconciliation):

Terminal
cascade pod import ./my-pod patient-records.json \
  --source-system "mass-general"

Records are split by type into organized files under clinical/:

Pod structure after import
my-pod/
  clinical/
    patient-profile.ttl       (1 record per patient)
    medications.ttl
    conditions.ttl
    allergies.ttl
    lab-results.ttl
    immunizations.ttl
    vital-signs.ttl
    procedures.ttl
    encounters.ttl
    documents.ttl
    lab-reports.ttl
    imaging.ttl
    claims.ttl
    benefits.ttl
    fhir-passthrough.ttl      (unmapped FHIR types, preserved verbatim)
  settings/
    publicTypeIndex.ttl       (updated with solid:TypeRegistration entries)
  index.ttl                   (updated with ldp:contains references)

Preview before importing

Use --dry-run to see what would be written without making any changes:

Terminal
cascade pod import ./my-pod patient-records.json --dry-run

Multi-source import with automatic reconciliation

Pass multiple FHIR files to import from several providers at once. The command automatically reconciles duplicates across sources using the same logic as cascade reconcile. Use --trust to set per-source trust scores, and --report to write a full import report:

Terminal
cascade pod import ./my-pod \
  hospital-records.json \
  primary-care.json \
  --trust hospital-records=0.95,primary-care=0.85 \
  --report import-report.json

Use --no-reconcile to skip reconciliation even when multiple input files are provided.

Options reference

OptionDescription
--source-system <name>Tag all imported records with this system name (used for reconciliation)
--no-reconcileSkip reconciliation even when multiple input files are provided
--trust <scores>Per-source trust scores for multi-source reconciliation, e.g. hospital=0.95,clinic=0.85
--dry-runPreview the import without writing any files
--report <file>Write an import report JSON to the specified file
--passthrough full|minimalControls whether FHIR passthrough resources include the raw JSON blob (default: full)
5

Validate your data

The validate command checks Turtle files against the bundled SHACL shapes for all Cascade Protocol vocabularies. It catches missing required fields, type mismatches, and vocabulary violations.

Validate a single file:

Terminal
cascade validate ./my-health-pod/clinical/medications.ttl
Expected output
PASS ./my-health-pod/clinical/medications.ttl (192 triples)

Validate an entire directory at once:

Terminal
cascade validate ./my-health-pod/clinical/
Expected output (all passing)
PASS clinical/allergies.ttl      (29 triples)
PASS clinical/conditions.ttl     (64 triples)
PASS clinical/immunizations.ttl  (64 triples)
PASS clinical/lab-results.ttl    (187 triples)
PASS clinical/medications.ttl    (192 triples)

Validation Summary
  Files: 5 total, 5 passed, 0 failed

Use --verbose to see which SHACL shapes were applied and which RDF types were detected:

Terminal
cascade validate medications.ttl --verbose

Use --json for machine-readable output suitable for CI pipelines:

Terminal
cascade validate ./my-health-pod/clinical/ --json

Exit codes

CodeMeaning
0All files pass validation
1One or more SHACL violations
2Error (file not found, malformed Turtle, etc.)
6

Query a Pod

Read records out of a Pod by type using pod query:

Terminal
# View all medications (human-readable)
cascade pod query ./my-health-pod --medications

# View all data types as JSON
cascade pod query ./my-health-pod --all --json

Available query filters:

FlagReturns
--medicationsPrescription and OTC medications
--conditionsDiagnoses and active conditions
--allergiesDrug, food, and environmental allergies
--lab-resultsLab and diagnostic results
--immunizationsVaccine records
--vital-signsClinical vital sign readings
--supplementsSupplements and OTC vitamins
--insuranceInsurance / coverage plans
--proceduresSurgical and clinical procedures
--encountersClinical encounters and visits
--documentsClinical documents (e.g. discharge summaries)
--lab-reportsLaboratory reports (DiagnosticReport)
--medication-administrationsInpatient medication administrations
--devicesImplanted medical devices
--imagingImaging studies (CT, MRI, X-ray)
--claimsInsurance claims
--benefitsExplanation of benefits
--fhir-passthroughFHIR resource types without a full Cascade mapping
--allAll data types in the Pod

The JSON output from --json is designed for consumption by AI agents and is the same format returned by the MCP cascade_pod_query tool.

Zero network calls

The CLI is designed for complete offline operation.

  • No data leaves your machine. SHACL validation, FHIR conversion, and Pod management all run locally.
  • No telemetry. There is no usage tracking, no error reporting, and no analytics.
  • No account required. Install and use without signing up for anything.
  • The Docker image adds an extra layer: docker run --rm -v $(pwd):/data cascade-protocol/tools cascade validate /data/record.ttl

Read the Security & Compliance Guide for a full description of the trust model and data flow.

Reconciling Records from Multiple Systems v0.3.3

When the same patient has records in multiple EHR systems, use cascade reconcile to merge them into a single canonical Turtle file. The reconciler removes exact duplicates, merges near-duplicates, and resolves conflicts using configurable trust scores.

Simpler alternative: If you are importing directly into a Pod, cascade pod import with multiple FHIR files handles reconciliation automatically as part of the import step — no separate convert-then-reconcile workflow needed. The manual cascade reconcile workflow below is still available for full control over the process or for working with pre-converted Turtle files.

Step 1: Tag records with their source system during conversion

Use the --source-system flag when converting each system's FHIR export:

Terminal
cascade convert patient.json --from fhir --to cascade \
  --source-system primary-care > primary-care.ttl

cascade convert patient.json --from fhir --to cascade \
  --source-system hospital > hospital.ttl

Step 2: Reconcile

Terminal
cascade reconcile primary-care.ttl specialist.ttl hospital.ttl \
  --output merged.ttl \
  --report reconciliation-report.json \
  --trust primary-care=0.90,specialist=0.85,hospital=0.95
Console output
Reconciliation complete
  Input records:      1,737 (across 3 systems)
  Exact duplicates:   -452 removed
  Near-duplicates:    ~9 merged
  Conflicts resolved: 2 (trust_priority)
  Final record count: 787

  Output: merged.ttl
  Report: reconciliation-report.json

How conflicts are resolved

Match type Strategy Description
exact_duplicate trust_priority All values identical across systems — keep highest-trust source
near_duplicate merge_values Same record identity, minor differences — merge fields from all sources
status_conflict trust_priority Conflicting status (e.g. active vs resolved) — highest-trust system wins
value_conflict trust_priority Conflicting clinical value — highest-trust system wins
unresolved flag_unresolved Trust scores too similar (<3% gap) — flagged with cascade:reconciliationStatus "unresolved-conflict" for manual review

Records identified as coded using RxNorm, SNOMED CT, LOINC, CVX, or ICD-10 are matched by code first; plain-text records fall back to normalized name matching. Reconciliation provenance is written using Core Vocabulary v2.4 reconciliation properties.

Conformance Testing

The CLI ships with a conformance test runner for verifying that your data producer or consumer correctly implements the Cascade Protocol. The conformance fixtures are published separately and cover all data types with both positive and negative test cases.

Terminal
# Clone the fixtures
git clone https://github.com/the-cascade-protocol/cascadeprotocol.org.git
cd cascadeprotocol.org

# Run the full suite
cascade conformance run --suite ./conformance/fixtures --self
Expected output (abridged)
Cascade Protocol Conformance Test Suite
========================================
Suite: ./conformance/fixtures
Mode: self-conformance
Fixtures: 59

  Medication (10 fixtures)
    ✓ med-001: Happy path: Active prescription medication (Lisinopril)
    ✓ med-002: Happy path: Self-reported OTC medication (Cetirizine)
    ✓ med-008: [negative] Negative: Medication missing required medicationName field
    ...

Results: 59 passed, 0 failed, 0 errors
Exit code: 0

Add --json to get a structured report you can parse in CI.

Agent Server (MCP)

The CLI includes a local Model Context Protocol server that exposes your Pod to AI assistants like Claude. It provides six typed tools: cascade_pod_read, cascade_pod_query, cascade_validate, cascade_convert, cascade_write, and cascade_capabilities.

Start the server in stdio mode (for Claude Desktop or other MCP clients):

Terminal
cascade serve --mcp --pod ./my-health-pod

To add it to your Claude Desktop configuration, edit ~/Library/Application Support/Claude/claude_desktop_config.json:

claude_desktop_config.json
{
  "mcpServers": {
    "cascade": {
      "command": "cascade",
      "args": ["serve", "--mcp", "--pod", "/path/to/my-health-pod"]
    }
  }
}

All data read and written by the agent stays in your local Pod. Agent-written observations are tagged with cascade:AIGenerated provenance, keeping them distinct from clinical and patient-entered data. Every operation is logged to provenance/audit-log.ttl.

See the full list of available tools:

Terminal
cascade capabilities --json
← Back to Documentation