OpenClinic

Documentation · 2 documents

README and docs

Mirrored from the OpenClinic repository every day. View on GitHub

README

OpenClinic

OpenClinic app icon

A provider-facing clinical workspace prototype for patient charting, SMART on FHIR import, and on-device clinical intelligence.

Swift iOS License


Overview

OpenClinic is a native iOS, iPadOS, and macOS clinical workspace prototype designed for healthcare providers. It integrates patient schedules, clinical record logs, visual timelines for dermatological checkups, and a SMART on FHIR synchronization pipeline into a unified SwiftUI experience that keeps chart state local on device.

  • Functional Role: Aggregates patient demographic profiles, clinical record timelines, medication lists, appointments, and photos.
  • Clinician Workflow: Provides offline-capable charting, record lookups, and note completion tools while keeping PHI inside the device sandbox except when explicitly pulling records from configured SMART on FHIR servers and during dictation, which Apple’s Speech framework transcribes, so audio may go to Apple.
  • On-Device LLMs & RAG: Implements a local retrieval-augmented generation (RAG) pipeline to support chart Q&A, clinical note compilation, and documentation checks without transmitting Patient Health Information (PHI) to third-party cloud APIs.
  • Engine Lineage: The clinical retrieval stack adapts OpenIntelligence internals for Core ML embeddings, token budgeting, retrieval shaping, and verification, then specializes those paths for patient-scoped clinical use.
  • EHR Integration: Connects to standard EHR sandbox platforms using SMART on FHIR OAuth scopes to import multi-patient records.
  • Product Boundary: OpenClinic is a prototype and design exploration. It is not approved for live clinical deployment and should not be presented as a production EHR replacement.

Product Snapshot

DimensionDetail
PlatformiOS / iPadOS / macOS
LanguageSwift
UISwiftUI
ArchitectureContainer-driven / Actor-isolated RAG
Primary APIsApple Foundation Models (LanguageModelSession), SMART on FHIR, Core ML
StorageSwiftData, SQLite FTS5, Keychain
StatusPrototype
LicenseProprietary / None

Screenshots

Everything shown is synthetic: the bundled demo panel, or Synthea patients read from the open SMART Health IT R4 sandbox.

Chart summaryComputed panel answer
Chart summary: allergies and flags, vital signs from stored observations, the problem list, active medications.A panel question answered by code from chart facts, each match shown with its sources.
FHIR import summaryImported record
A full-record import from the sandbox, counted by kind of record.The imported record. Each row opens the FHIR resource it was read from.

Key Capabilities

  • On-Device LLM Integration: Apple’s Speech framework transcribes dictations (audio may go to Apple), and local Apple Foundation Models (LanguageModelSession) turn the transcripts into structured notes (ClinicalVisitNote). The model declines some requests; the app then lists the patient’s own chart rows, or sorts the dictation’s own sentences into the note’s sections (DictationSorter, which adds no finding, plan or order), and labels the text as written by the app.
  • Local Vector Search: Generates 384-dimensional embeddings (MiniLM-L6-v2) using a bundled Core ML model, indexing chunks in a local vector database.
  • Computed Panel Answers: A set question such as “which patients have melanoma history” is parsed into a structured query and computed from chart facts by CohortEngine, with the record, prescription, or appointment behind every match. No language model takes part, and a question the parser does not fully understand is not computed.
  • 9-Gate Retrieval Checks: Scores the retrieved records on nine checks before the model runs and shows the results with the answer. The checks do not read or block generated text. Model-written answers are labeled as unchecked in the app.
  • FHIR Interoperability: Imports a patient’s full record from a FHIR R4 server: Patient plus Condition, MedicationRequest, AllergyIntolerance, Observation, Encounter, Procedure, Immunization, DiagnosticReport, DocumentReference, and Appointment, with paging and retries. Servers that need authorization use SMART on FHIR through ASWebAuthenticationSession; the open SMART Health IT sandbox imports with no sign-in.
  • Source Fidelity: Every imported resource is stored as the server sent it, beside the chart row mapped from it; the one change is that a Patient’s government numbers (Social Security, driver’s license, passport, Medicare and its beneficiary identifier, Medicaid, tax, national, social-beneficiary and bank-card numbers) lose their values before storage: in an identifier anywhere in the resource, in any other value equal to one, and in the text of the narrative. A row the server stops returning is marked, never deleted, and a failed search is never read as an empty chart.
  • Data Provenance: Attaches sync timestamps and source system attributes to SwiftData entities to preserve the authority of remote records.
  • OpenIntelligence-Derived Retrieval Internals: Reuses and adapts embedding, full-text, boosting, and verification patterns from OpenIntelligence, but applies them to patient-scoped clinical workflows instead of general document Q&A.
  • Concurrency: The vector store and the keyword index are actors (ClinicalVectorStore, ClinicalFTSService), so vector queries and full-text indexing run off the main thread. SwiftData reads and writes run on the main actor.

How It Works

This flowchart details the clinician onboarding, patient navigation, and database sync workflow:

flowchart TD
    A[Launch App] --> B[Seed or refresh the demo panel]
    B --> C[Sync the retrieval index: embed only changed chart text]
    C --> D[Main tabs: patients, schedule, intelligence]
    D --> E[Open a patient chart]
    D --> F[Settings: Live EHR Import]
    F --> G{Server needs a sign-in?}
    G -->|No: the open sandbox| H[Import one patient's full record]
    G -->|Yes| I[SMART sign-in sheet] --> H
    H --> E

On launch, OpenClinic seeds a baseline configuration and sets up the local SwiftData model container. Clinicians select patients from a daily schedule timeline. If connected to a SMART on FHIR server, the client queries and resolves patient records locally on demand.


Architecture

OpenClinic organizes components into distinct functional layers:

flowchart LR
    subgraph Layers ["System Tiers"]
        UI[SwiftUI View Layer] --> Controllers[State & Orchestration Controllers]
        Controllers --> Ingestion[FHIR Ingestion & RAG Pipelines]
        Ingestion --> Storage[SwiftData & Local Vector Stores]
    end

For a detailed view-by-view diagram covering controllers, services, and local file storage, refer to ARCHITECTURE.md.


Core Workflows

A panel question is computed from chart facts when the parser fully understands it. Every other question goes through a hybrid vector-lexical lookup and checks on the retrieved records:

flowchart TD
    A[Clinician Question] --> P{Set question the parser fully understands?}
    P -->|Yes| Q[CohortEngine computes the answer from chart facts]
    Q --> R[Answer with the source record behind every match]
    P -->|No| B[Generate Query Vector]
    B --> C[Hybrid Search: FTS5 + Core ML]
    C --> D[RRF Fusion & MMR Rerank]
    D --> F[9-Gate Checks on Retrieved Records] --> E[On-Device LLM Synthesis] --> H[Render Response with Gate Results]

For details on chunking parameters, cross-encoders, and reciprocal rank fusion, refer to ARCHITECTURE.md.


Data Flow

This diagram traces the local storage boundaries and data synchronization paths:

flowchart TD
    FHIR[FHIR Server] -->|HTTPS JSON, paged| Import[FHIRR4Client and ChartImportApplier]
    Import -->|Chart rows and source resources| SD[(SwiftData Store)]
    SD -->|Local Chunks| VectorStore[ClinicalVectorStore]
    SD -->|FTS Row| FTS[SQLite FTS5 Index]
    Keychain[[Keychain]] -->|OAuth Tokens| Import

File Entry Points

ConcernFilesResponsibility
App EntryOpenClinicApp.swiftBootstrapping the SwiftData schema, UserDefaults migrations, and launch-time RAG index triggers.
Main UI ShellContentView.swiftHosts the main shell.
Patient Chart UIPatientDashboardView.swiftPrimary clinical layout displaying demographics, visit history, medication lists, and visual timelines.
Encounter WorkspaceClinicalExamView.swiftDictation transcription and structured note generation interface for clinicians.
Intelligence UIClinicIntelligenceView.swiftConsole UI for executing patient-specific or panel-wide local AI queries.
OAuth ConnectionSMARTConnectionController.swiftHandles authorization endpoint discovery, JWT decoding, and token renewal.
FHIR Read LayerFHIRR4Client.swift, FHIRR4ChartMapper.swiftPaging HTTP client and the pure mapping from FHIR R4 resources to plain chart values.
Chart ImportChartImportApplier.swiftApplies an imported record to the store in one transaction and keeps each source resource.
RAG OrchestratorClinicalRAGService.swiftCoordinates embeddings, FTS5 keywords, hybrid rankings, and verification gates.
Retrieval ChecksVerificationGates.swiftImplements the 9-gate checks that score the retrieved records for grounding, completeness, and HIPAA isolation before the model runs.
Computed Panel AnswersCohortEngine.swift, CohortQuery.swiftParses set questions into structured queries and computes the matching patients with the chart facts behind each match.
Demo PanelDemoPanel.json, DemoDataSeeder.swiftThe synthetic ten-patient panel and the code that seeds it and keeps today’s schedule current.

Configuration

These environment configurations control OpenClinic’s local storage and sync behavior:

SettingStorageDefaultRequiredPurpose
EHR Server PresetsUserDefaultshttps://launch.smarthealthit.org/v/r4/fhirYesEndpoint base URL for SMART discovery and patient downloads.
SMART Client IDUserDefaultsmedmod-ios-publicYesPublic application registration identifier on the EHR server.
Redirect SchemeInfo.plistmedmod://smart-callbackYesCallback schema mapping for ASWebAuthenticationSession redirection.
RAG Embedding ModelLocal DirectoryEmbeddingModel.mlpackageYesCore ML package path for text embedding generation.
Token VocabularyLocal Directoryembedding_vocab.jsonYesToken mapping file for the clinical text chunker.
Demo Panel VersionUserDefaultsdemoPanelVersion, demoTimelineDayNoRecords which fixture version is seeded and which day today’s schedule was built for.

Build & Run

Prerequisite Toolchain

  • macOS 27.0+ or compatible development workstation.
  • Xcode 27.0 (the build verified on 2026-10-07) with the iOS 27.0 and macOS 27.0 SDKs. Deployment targets are iOS 26.2 and macOS 26.2.
  • Apple Developer Account configured in Xcode for physical device testing.

Setup Instructions

# Clone the repository
git clone https://github.com/Gunnarguy/OpenClinic.git
cd OpenClinic

# Open the project in Xcode
open OpenClinic.xcodeproj
  1. Select the OpenClinic target in the scheme editor.
  2. Under Signing & Capabilities, select your developer team and update the bundle identifier if compiling for a physical device.
  3. Choose a simulator (e.g. iPad Pro running iOS 26.2) or select a connected Apple device.
  4. Press Cmd + R to compile and run. On launch, the app will seed clinical demo records and start the local vector indexer.

Testing

One command runs the unit tests and then an iOS Simulator build:

./Scripts/verify.sh          # tests on the macOS host, then the iOS Simulator build
./Scripts/verify.sh tests    # tests only
./Scripts/verify.sh build    # iOS Simulator build only

The script refuses to run when iCloud conflict copies are in the tree or less than 4 GB of disk is free, and it writes build products outside the repository.

SuiteWhat it holds the code to
PanelQuestionEvalTests31 panel questions in plain language, each scored against a patient set written by hand from the demo fixture. A case passes only on an exact set match.
CohortEngineTestsParser and engine behavior on a hand-built panel, including the questions the parser must refuse.
DemoPanelTests, DemoChartRowsTestsThe demo fixture is coherent (ages against dates of birth, zones, ICD-10 format, vitals only for roomed visits, lab values that agree with the inbox) and the seeder never duplicates rows or undoes a clinician’s edit.
FHIRR4*TestsThe FHIR R4 read layer against responses captured from the SMART Health IT sandbox: paging, retries, refused redirects and paging links to another server, relative paging links, entered-in-error resources left out, partial dates, deceased patients, and government numbers removed from the stored Patient resource.
ChartImportApplierTests, ChartModelPersistenceTestsA captured sandbox record through the mapper and into the store: importing twice changes nothing, a row the server stops returning is kept and marked, a failed or truncated search removes nothing, a chart stored under another spelling of the server address is found again, the one-time repair of charts an earlier version imported, a patient with no date of birth has no age, and every model saves.
DictationSorterTestsThe note drafted without the model holds only the dictation’s own sentences, matches whole words, and names no diagnosis the dictation denies or gives to a relative.
ProblemListTestsThe problem list a chart shows: charted problems, then diagnoses only a note names, with examination visits (ICD-10-CM Z00 to Z13) left off.
SMARTSessionTestsA callback with a missing or wrong state is refused, an authorization error is reported in the server’s words, the scopes cover every resource type the import reads, launch is asked for only with a launch token, a token request follows no redirect, discovery follows none to another server, and offline_access is asked for only where the server offers refresh tokens.
SMARTLiveSignInTestsOpt-in (./Scripts/verify.sh live): the app’s own sign-in code against the SMART Health IT launcher, including a wrong PKCE verifier that the server must refuse.
ClinicalIndexSyncTests, ClinicalVectorStoreTestsThe plan the launch index sync follows embeds only new text and keeps the vector of a chunk that only moved, and a stale file is never merged into a rebuilt index. The sync itself (syncIndex) is checked by the device self-check, not by a unit test.
ChartDateTextTestsA date the source stated only to the year or month is written that way.
ClinicalIntelligenceServiceTests, VisitNoteTextTestsText the app lists or fills in is reported as that and never as model-written (on screen, in a Shortcut’s dialog and in a saved note’s source kind), a model call is given up on at its time limit, and the plain-text form of a note reads back into its sections.
ClinicalChunkerTests, ClinicalFTSServiceTests, SMARTCredentialStoreTests, othersChunking, FTS5 search and its injection guard, Keychain credential storage, anatomical regions, patient education links.

Checks that still need a person and a device:

CheckProcedureExpected result
SMART sign-in sheetSettings -> Live EHR Import -> SMART R4 Preset -> ConnectThe system sign-in sheet appears, authorizes, and the record imports. The protocol under the sheet (discovery, PKCE, token exchange, authorized read, refresh) is checked by ./Scripts/verify.sh live.
Model-written answers on screenAsk a free-form question about one patient in the Intelligence tab on a device with Apple IntelligenceAn answer labeled as written by the on-device model, with the retrieved sources under it. ./Scripts/verify.sh device asks three such questions without the screen and reports for each whether the model wrote the answer.

Two more modes of the script reach outside the Mac and are not part of the default run:

./Scripts/verify.sh live      # a real SMART on FHIR sign-in against launch.smarthealthit.org (synthetic patients, no password)
./Scripts/verify.sh device    # build, install and self-check on a connected, unlocked iPhone or iPad

Privacy & Security

OpenClinic keeps chart data on the doctor’s device, although dictation audio may go to Apple’s speech service. No clinical data is synced to third-party databases:

  • Encryption at Rest: The SwiftData store has no explicit file-protection class, so it gets the platform’s default data protection.
  • Credentials Storage: The SMART token response (access token, and refresh token when the server issues one) is kept in the Keychain as a this-device-only item. The FHIR base URL, client ID and patient ID fields are kept in UserDefaults; a client secret is never saved.
  • Models: Every prompt runs on the device. A route that would send prompts estimated above 4,000 tokens to Apple’s Private Cloud Compute is in the code but compiled out: with Swift 6.4 a stub that reports it unavailable is built in its place.
  • Log Privacy: System log statements (os.Logger) redact patient names and medical record numbers.

For more details, see PRIVACY.md and SECURITY.md.


Documentation

DocumentPurpose
ArchitectureSystem design, data flow, and service boundaries
SecuritySecret handling, local storage, and release checks
PrivacyData storage, API transmission, and user controls
RoadmapCurrent status, planned work, and known gaps
Case StudyEngineering retrospective and implementation notes

Roadmap

Completed Milestones

  • SwiftData core models mapping patient charts, clinical notes, medications.
  • On-device vector store and SQLite FTS5 search indexers.
  • 9-Gate retrieval checks scoring the retrieved records before the model runs.
  • Computed panel answers with a hand-written evaluation set.
  • SMART on FHIR OAuth discovery and patient record import flows.
  • Reciprocal Rank Fusion (RRF) and MMR search candidate balancing.
  • Multi-platform UI for iOS, iPadOS and macOS.
  • Integration of RAG Evaluation and XCTest Suites.

In Progress

  • Enhancing multi-pass Deep Think query extraction heuristics.
  • Optimizing Core ML inference times on older Apple Silicon devices.

Planned / Backlog

  • Outbound writebacks to FHIR servers (e.g. uploading signed notes).
  • Full-body anatomical mesh mapping in 3D for spatial tracking.

License

No license has been applied to this repository yet. Contact the repository owner before copying, modifying, or redistributing these source materials.