OpenScribe is an open-source AI scribe that records patient encounters and generates structured clinical notes automatically. You keep full control over data, workflows, and patient privacy with no vendor lock-in.
209
stars
187
commits
TypeScript
primary language
Aug 17, 2026
updated
Open-source AI medical scribe for recording encounters and generating structured clinical notes.
OpenScribe is a free, MIT-licensed, open-source AI medical scribe that helps clinicians record patient encounters, transcribe audio, and generate structured draft clinical notes using LLMs. The default web deployment path is mixed mode: local Whisper transcription + Anthropic Claude note generation. A fully local desktop path is also available, forked from StenoAI.
OpenScribe is not HIPAA compliant yet. The team is actively working toward HIPAA compliance.
If you only want to try OpenScribe as an app:
Full guide: docs/DOWNLOAD_AND_USE.md
node --version # Check you have Node.js 18+
# If not installed (macOS): brew install node
# If installed but <18 (macOS): brew upgrade node
npm install -g pnpm
git clone https://github.com/sammargolis/OpenScribe.git
cd OpenScribe
pnpm install
Create env defaults:
pnpm run setup # Auto-generates .env.local with secure storage key
Edit apps/web/.env.local and add:
TRANSCRIPTION_PROVIDER=whisper_local
WHISPER_LOCAL_MODEL=tiny.en
ANTHROPIC_API_KEY=sk-ant-YOUR_KEY_HERE
# NEXT_PUBLIC_SECURE_STORAGE_KEY is auto-generated, don't modify
OPENAI_API_KEY is optional unless you switch to TRANSCRIPTION_PROVIDER=whisper_openai.
pnpm dev:local # One command: Whisper local server + web app
Optional desktop app path:
pnpm electron:dev
Desktop production builds:
pnpm build:desktop:mac
pnpm build:desktop:win
pnpm build:desktop:linux
# or
pnpm build:desktop:all
GA support target for packaged desktop releases:
x64, arm64x64x64, arm64See release gate details in docs/RELEASE_READINESS_CHECKLIST.md. Manual reviewer sign-off template: docs/MANUAL_SIGNOFF_TEMPLATE.md.
SAM is the easiest way to run OpenScribe for new contributors: one command starts the web app and local Whisper transcription service.
pnpm run setup
Edit apps/web/.env.local and set:
ANTHROPIC_API_KEY=sk-ant-YOUR_KEY_HERE
docker compose -f docker-compose.sam.yml up --build
http://localhost:3001
curl http://127.0.0.1:8002/health
OpenScribe supports three workflows. Mixed web mode is the default path.
pnpm whisper:server) with default model tiny.enpnpm dev:localTRANSCRIPTION_PROVIDER=whisper_local in apps/web/.env.localWHISPER_UNHEALTHY and model-download failuresLanguage support
tiny.en as well as all .en-models transcribes English onlyWHISPER_LANGUAGE (see .env.local.example for details) and (for local use) switching to a non-.en Whisper model (e.g. tiny, base, small)Settings -> Transcription Language. An explicit choice overrides WHISPER_LANGUAGE; leaving it on Auto (default) keeps the existing env/auto-detect behavior unchanged. Precedence rules and detailslocal-only/openscribe-backendllama3.2:*, gemma3:4b)apps/web/.env.localSend to OpenClaw (desktop app path).Send to OpenClaw.Optional environment variables for demos:
# OpenClaw CLI (default: openclaw on PATH)
OPENCLAW_BIN=openclaw
# Target OpenClaw agent/session (default: main)
OPENCLAW_AGENT=main
# If set to 1, OpenClaw can deliver responses to a configured channel
OPENCLAW_DELIVER=0
# Optional webhook transport instead of CLI
# OPENCLAW_DEMO_WEBHOOK_URL=http://127.0.0.1:8787/openscribe/handoff
# OPENCLAW_DEMO_WEBHOOK_TOKEN=your-token
OpenAI (transcription): platform.openai.com/api-keys - Sign up → API Keys → Create new secret key
Anthropic (note generation): console.anthropic.com/settings/keys - Sign up → API Keys → Create Key
Both services offer $5 free credits for new accounts
git pull origin main # Pull latest changes
pnpm install # Update dependencies
# If you encounter issues after updating:
rm -rf node_modules pnpm-lock.yaml && pnpm install
A note template is the markdown skeleton the model fills in. Pick one in Settings → Note Template; the choice is stored locally and applies to every new encounter.
| Option | What you get |
|---|---|
| Default | History and Physical: Chief Complaint, HPI, Review of Systems, Past Medical History, Medications |
| SOAP | Subjective (CC / HPI / ROS), Objective (Physical Examination), Assessment, Plan |
| Custom | Your own markdown, edited in the Settings text area |
Presets live in packages/llm/src/prompts/clinical-note/templates/index.ts. The
custom template stays on your device, in the same local preferences store as
note length and processing mode.
Use markdown ATX headings to define the structure:
# — the note title (one per template, e.g. # Cardiology Follow-Up)## — a section; each one is parsed as a separate note section### — a subsection, kept inside its parent section# Cardiology Follow-Up
## Reason for Visit
## Interval History
## Medications
### Cardiac
### Other
## Assessment and Plan
Section names are free text, so add specialty sections and drop the ones you do not use. Content under a heading is optional — the model fills sections from the transcript and omits what the transcript does not support.
A custom template must be non-empty and contain at least one markdown heading. If it is blank or heading-less, note generation logs a warning and falls back to the Default template instead of failing.
Selecting Default keeps the existing behavior where a visit type of "problem visit" maps to the SOAP structure. Choosing SOAP or Custom overrides the visit type for every encounter.
OpenScribe exists to provide a simple, open-source alternative to cloud dependent clinical documentation tools. The project is built on core principles:
This repo now includes a fully local, text-only MedGemma scribe workflow in
packages/pipeline/medgemma-scribe. It requires pre-transcribed text and
does not perform speech-to-text. See
packages/pipeline/medgemma-scribe/README.md for setup and usage.
Physical Controls:
See architecture.md for complete details.
┌─────────────────────────────────────────────────────────┐
│ UI Layer (Next.js) │
│ ┌──────────────┐ ┌─────────────────────┐ │
│ │ Encounter │ │ Workflow States │ │
│ │ Sidebar │◄────────────►│ - Idle │ │
│ │ │ │ - Recording │ │
│ │ │ │ - Processing │ │
│ │ │ │ - Note Editor │ │
│ └──────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Processing Pipeline │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────┐ │
│ │ Audio │──►│Transcribe│──►│ LLM │──►│Note │ │
│ │ Ingest │ │ (Whisper)│ │ │ │Core │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────┘ │
│ │ │ │
│ └───────────────┐ ┌─────────────────┘ │
└───────────────────────┼─────────┼───────────────────────┘
▼ ▼
┌─────────────────────────────────────────────────────────┐
│ Storage Layer │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Encrypted LocalStorage (AES-GCM) │ │
│ │ - Encounters (patient data, transcripts, notes) │ │
│ │ - Metadata (timestamps, status) │ │
│ │ - Audio (in-memory only, not persisted) │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Key Components:
apps/web/ using Next.js App Routerwhisper.cpp via pywhispercpp, model tiny.en)packages/llmlocal-only/openscribe-backendpackages/llmMonorepo Structure:
apps/web/ – Next.js frontend + Electron rendererpackages/pipeline/ – Audio ingest, transcription, assembly, evaluationpackages/ui/ – Shared React componentspackages/storage/ – Encrypted storage + encounter managementpackages/llm/ – Provider-agnostic LLM clientpackages/shell/ – Electron main processconfig/ – Shared configuration filesbuild/ – Build artifactsStorage: AES-GCM encrypted localStorage. Audio processed in-memory, not persisted.
Transmission: In the default mixed mode, audio stays local for transcription and transcript text is sent to Anthropic Claude over HTTPS/TLS for note generation. If TRANSCRIPTION_PROVIDER=whisper_openai, audio is sent to OpenAI Whisper over HTTPS/TLS. The application enforces HTTPS-only connections and displays a security warning if accessed over HTTP in production builds.
No Tracking: Zero analytics, telemetry, or cloud sync
Use Responsibility
HIPAA Compliance: OpenScribe includes foundational privacy/security features, but this alone does not make the application HIPAA-compliant. Below is what is already built, followed by a checklist a health system must complete to operate compliantly.
Built (foundational rails)
Health System Checklist (required to run compliantly)
No EHR Integration: Standalone tool
Browser Storage Limits: ~5-10MB typical
No Warranty: Provided as-is under MIT License
Contributions welcome! See CONTRIBUTING.md for detailed guidelines.
Quick Start:
Portions of this project include or were derived from code in:
StenoAI – https://github.com/ruzin/stenoai
Copyright (c) 2025 Skrape Limited
Licensed under the MIT License.
All third-party code remains subject to its original license terms.
MIT
MIT License
Copyright (c) 2026 Sam Margolis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
OpenScribe
GitHub: https://github.com/sammargolis/OpenScribe
Maintainer: Sam Margolis (@sammargolis)
TypeScript
57.4%
Python
22.3%
JavaScript
18.2%
Shell
1.7%
OpenScribe is an open-source AI scribe that records patient encounters and generates structured clinical notes automatically. You keep full control over data, workflows, and patient privacy with no vendor lock-in.
209
stars
187
commits
TypeScript
primary language
Aug 17, 2026
updated
Open-source AI medical scribe for recording encounters and generating structured clinical notes.
OpenScribe is a free, MIT-licensed, open-source AI medical scribe that helps clinicians record patient encounters, transcribe audio, and generate structured draft clinical notes using LLMs. The default web deployment path is mixed mode: local Whisper transcription + Anthropic Claude note generation. A fully local desktop path is also available, forked from StenoAI.
OpenScribe is not HIPAA compliant yet. The team is actively working toward HIPAA compliance.
If you only want to try OpenScribe as an app:
Full guide: docs/DOWNLOAD_AND_USE.md
node --version # Check you have Node.js 18+
# If not installed (macOS): brew install node
# If installed but <18 (macOS): brew upgrade node
npm install -g pnpm
git clone https://github.com/sammargolis/OpenScribe.git
cd OpenScribe
pnpm install
Create env defaults:
pnpm run setup # Auto-generates .env.local with secure storage key
Edit apps/web/.env.local and add:
TRANSCRIPTION_PROVIDER=whisper_local
WHISPER_LOCAL_MODEL=tiny.en
ANTHROPIC_API_KEY=sk-ant-YOUR_KEY_HERE
# NEXT_PUBLIC_SECURE_STORAGE_KEY is auto-generated, don't modify
OPENAI_API_KEY is optional unless you switch to TRANSCRIPTION_PROVIDER=whisper_openai.
pnpm dev:local # One command: Whisper local server + web app
Optional desktop app path:
pnpm electron:dev
Desktop production builds:
pnpm build:desktop:mac
pnpm build:desktop:win
pnpm build:desktop:linux
# or
pnpm build:desktop:all
GA support target for packaged desktop releases:
x64, arm64x64x64, arm64See release gate details in docs/RELEASE_READINESS_CHECKLIST.md. Manual reviewer sign-off template: docs/MANUAL_SIGNOFF_TEMPLATE.md.
SAM is the easiest way to run OpenScribe for new contributors: one command starts the web app and local Whisper transcription service.
pnpm run setup
Edit apps/web/.env.local and set:
ANTHROPIC_API_KEY=sk-ant-YOUR_KEY_HERE
docker compose -f docker-compose.sam.yml up --build
http://localhost:3001
curl http://127.0.0.1:8002/health
OpenScribe supports three workflows. Mixed web mode is the default path.
pnpm whisper:server) with default model tiny.enpnpm dev:localTRANSCRIPTION_PROVIDER=whisper_local in apps/web/.env.localWHISPER_UNHEALTHY and model-download failuresLanguage support
tiny.en as well as all .en-models transcribes English onlyWHISPER_LANGUAGE (see .env.local.example for details) and (for local use) switching to a non-.en Whisper model (e.g. tiny, base, small)Settings -> Transcription Language. An explicit choice overrides WHISPER_LANGUAGE; leaving it on Auto (default) keeps the existing env/auto-detect behavior unchanged. Precedence rules and detailslocal-only/openscribe-backendllama3.2:*, gemma3:4b)apps/web/.env.localSend to OpenClaw (desktop app path).Send to OpenClaw.Optional environment variables for demos:
# OpenClaw CLI (default: openclaw on PATH)
OPENCLAW_BIN=openclaw
# Target OpenClaw agent/session (default: main)
OPENCLAW_AGENT=main
# If set to 1, OpenClaw can deliver responses to a configured channel
OPENCLAW_DELIVER=0
# Optional webhook transport instead of CLI
# OPENCLAW_DEMO_WEBHOOK_URL=http://127.0.0.1:8787/openscribe/handoff
# OPENCLAW_DEMO_WEBHOOK_TOKEN=your-token
OpenAI (transcription): platform.openai.com/api-keys - Sign up → API Keys → Create new secret key
Anthropic (note generation): console.anthropic.com/settings/keys - Sign up → API Keys → Create Key
Both services offer $5 free credits for new accounts
git pull origin main # Pull latest changes
pnpm install # Update dependencies
# If you encounter issues after updating:
rm -rf node_modules pnpm-lock.yaml && pnpm install
A note template is the markdown skeleton the model fills in. Pick one in Settings → Note Template; the choice is stored locally and applies to every new encounter.
| Option | What you get |
|---|---|
| Default | History and Physical: Chief Complaint, HPI, Review of Systems, Past Medical History, Medications |
| SOAP | Subjective (CC / HPI / ROS), Objective (Physical Examination), Assessment, Plan |
| Custom | Your own markdown, edited in the Settings text area |
Presets live in packages/llm/src/prompts/clinical-note/templates/index.ts. The
custom template stays on your device, in the same local preferences store as
note length and processing mode.
Use markdown ATX headings to define the structure:
# — the note title (one per template, e.g. # Cardiology Follow-Up)## — a section; each one is parsed as a separate note section### — a subsection, kept inside its parent section# Cardiology Follow-Up
## Reason for Visit
## Interval History
## Medications
### Cardiac
### Other
## Assessment and Plan
Section names are free text, so add specialty sections and drop the ones you do not use. Content under a heading is optional — the model fills sections from the transcript and omits what the transcript does not support.
A custom template must be non-empty and contain at least one markdown heading. If it is blank or heading-less, note generation logs a warning and falls back to the Default template instead of failing.
Selecting Default keeps the existing behavior where a visit type of "problem visit" maps to the SOAP structure. Choosing SOAP or Custom overrides the visit type for every encounter.
OpenScribe exists to provide a simple, open-source alternative to cloud dependent clinical documentation tools. The project is built on core principles:
This repo now includes a fully local, text-only MedGemma scribe workflow in
packages/pipeline/medgemma-scribe. It requires pre-transcribed text and
does not perform speech-to-text. See
packages/pipeline/medgemma-scribe/README.md for setup and usage.
Physical Controls:
See architecture.md for complete details.
┌─────────────────────────────────────────────────────────┐
│ UI Layer (Next.js) │
│ ┌──────────────┐ ┌─────────────────────┐ │
│ │ Encounter │ │ Workflow States │ │
│ │ Sidebar │◄────────────►│ - Idle │ │
│ │ │ │ - Recording │ │
│ │ │ │ - Processing │ │
│ │ │ │ - Note Editor │ │
│ └──────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Processing Pipeline │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────┐ │
│ │ Audio │──►│Transcribe│──►│ LLM │──►│Note │ │
│ │ Ingest │ │ (Whisper)│ │ │ │Core │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────┘ │
│ │ │ │
│ └───────────────┐ ┌─────────────────┘ │
└───────────────────────┼─────────┼───────────────────────┘
▼ ▼
┌─────────────────────────────────────────────────────────┐
│ Storage Layer │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Encrypted LocalStorage (AES-GCM) │ │
│ │ - Encounters (patient data, transcripts, notes) │ │
│ │ - Metadata (timestamps, status) │ │
│ │ - Audio (in-memory only, not persisted) │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Key Components:
apps/web/ using Next.js App Routerwhisper.cpp via pywhispercpp, model tiny.en)packages/llmlocal-only/openscribe-backendpackages/llmMonorepo Structure:
apps/web/ – Next.js frontend + Electron rendererpackages/pipeline/ – Audio ingest, transcription, assembly, evaluationpackages/ui/ – Shared React componentspackages/storage/ – Encrypted storage + encounter managementpackages/llm/ – Provider-agnostic LLM clientpackages/shell/ – Electron main processconfig/ – Shared configuration filesbuild/ – Build artifactsStorage: AES-GCM encrypted localStorage. Audio processed in-memory, not persisted.
Transmission: In the default mixed mode, audio stays local for transcription and transcript text is sent to Anthropic Claude over HTTPS/TLS for note generation. If TRANSCRIPTION_PROVIDER=whisper_openai, audio is sent to OpenAI Whisper over HTTPS/TLS. The application enforces HTTPS-only connections and displays a security warning if accessed over HTTP in production builds.
No Tracking: Zero analytics, telemetry, or cloud sync
Use Responsibility
HIPAA Compliance: OpenScribe includes foundational privacy/security features, but this alone does not make the application HIPAA-compliant. Below is what is already built, followed by a checklist a health system must complete to operate compliantly.
Built (foundational rails)
Health System Checklist (required to run compliantly)
No EHR Integration: Standalone tool
Browser Storage Limits: ~5-10MB typical
No Warranty: Provided as-is under MIT License
Contributions welcome! See CONTRIBUTING.md for detailed guidelines.
Quick Start:
Portions of this project include or were derived from code in:
StenoAI – https://github.com/ruzin/stenoai
Copyright (c) 2025 Skrape Limited
Licensed under the MIT License.
All third-party code remains subject to its original license terms.
MIT
MIT License
Copyright (c) 2026 Sam Margolis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
OpenScribe
GitHub: https://github.com/sammargolis/OpenScribe
Maintainer: Sam Margolis (@sammargolis)
TypeScript
57.4%
Python
22.3%
JavaScript
18.2%
Shell
1.7%