Extract provider style profiles from existing clinical notes and portal messages. Runs entirely on your local machine - PHI never leaves your infrastructure.
Status: v1.0.0 - Initial Release | January 2026
ProviderTone Local analyzes your existing clinical documentation to generate style profiles compatible with the ProviderTone website and API. Instead of completing an interrogation wizard, providers can leverage years of existing notes and messages.
Key Features:
- Runs 100% locally - PHI stays on your infrastructure
- Supports CSV, JSON, and text file exports from any EHR
- Uses Claude API (with BAA) or local LLMs for air-gapped environments
- Outputs website-compatible JSON style profiles
- Built-in PHI detection and automatic redaction
- Rich CLI with progress indicators and summaries
# 1. Clone and install
cd providertone-local
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -e .
# 2. Set up API key
cp .env.example .env
# Edit .env and add your ANTHROPIC_API_KEY
# 3. Run extraction
providertone extract \
--messages exports/messages.csv \
--notes exports/notes/ \
--provider-id dr-smith \
--output profiles/dr-smith.json- Python 3.9+
- Anthropic API key (or local LLM for air-gapped)
# Clone the repository
git clone https://github.com/your-org/providertone.git
cd providertone/providertone-local
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Install CLI tool
pip install -e .
# Verify installation
providertone --helpCopy .env.example to .env and configure:
# Required: Anthropic API key
ANTHROPIC_API_KEY=sk-ant-...
# Optional: Custom API endpoint
# ANTHROPIC_BASE_URL=https://api.anthropic.com
# Optional: For local LLM (air-gapped environments)
# LOCAL_LLM_ENDPOINT=http://localhost:11434
# LOCAL_LLM_MODEL=llama3:70b# Analyze portal messages
providertone analyze-messages \
--input messages.csv \
--provider-id "dr-smith" \
--output analysis/messages.json
# Analyze clinical notes
providertone analyze-notes \
--input notes/ \
--provider-id "dr-smith" \
--output analysis/notes.json
# Generate combined profile
providertone generate-profile \
--messaging analysis/messages.json \
--documentation analysis/notes.json \
--output profiles/dr-smith.json
# One-shot: analyze and generate in one command
providertone extract \
--messages messages.csv \
--notes notes/ \
--provider-id "dr-smith" \
--output profiles/dr-smith.json# Use local LLM (air-gapped mode)
providertone analyze-messages \
--input messages.csv \
--provider-id "dr-smith" \
--llm local \
--output analysis/messages.json
# Specify sample size
providertone analyze-notes \
--input notes/ \
--provider-id "dr-smith" \
--sample-size 100 \
--output analysis/notes.json
# Filter by date range
providertone analyze-messages \
--input messages.csv \
--provider-id "dr-smith" \
--start-date 2024-01-01 \
--end-date 2024-12-31 \
--output analysis/messages.json
# Auto-redact PHI from output
providertone generate-profile \
--messaging analysis/messages.json \
--output profiles/dr-smith.json \
--redact
# Verbose output
providertone analyze-messages \
--input messages.csv \
--provider-id "dr-smith" \
--verbose \
--output analysis/messages.jsonmessage_id,provider_id,patient_id,direction,sent_at,subject,body
msg001,dr-smith,pt123,outbound,2024-06-15T10:30:00Z,RE: Fever question,"Hi Sarah, I understand..."
msg002,dr-smith,pt456,outbound,2024-06-15T14:22:00Z,RE: Refill request,"Hello John, I've sent..."{
"messages": [
{
"message_id": "msg001",
"provider_id": "dr-smith",
"patient_id": "pt123",
"direction": "outbound",
"sent_at": "2024-06-15T10:30:00Z",
"subject": "RE: Fever question",
"body": "Hi Sarah, I understand..."
}
]
}{
"notes": [
{
"note_id": "note001",
"provider_id": "dr-smith",
"patient_id": "pt789",
"note_type": "progress_note",
"visit_type": "acute",
"created_at": "2024-06-15T09:00:00Z",
"chief_complaint": "Ear pain",
"content": {
"hpi": "2-year-old female presents with...",
"physical_exam": "TMs - R bulging...",
"assessment": "Right acute otitis media",
"plan": "Amoxicillin 80mg/kg/day..."
}
}
]
}note_id,provider_id,patient_id,note_type,visit_type,created_at,chief_complaint,hpi,physical_exam,assessment,plan
note001,dr-smith,pt789,progress_note,acute,2024-06-15,Ear pain,"2yo presents...","TMs bulging...","AOM","Amoxicillin..."notes/
├── 2024-06-15_pt789_acute.txt
├── 2024-06-15_pt012_chronic.txt
└── 2024-06-16_pt345_wellchild.txt
Each file contains the full note text. Metadata can be in YAML header:
---
provider_id: dr-smith
patient_id: pt789
visit_type: acute
---
Chief Complaint: Ear pain
HPI: 2-year-old female presents with...
The generated profile is compatible with the ProviderTone website:
{
"exportedAt": "2024-06-15T15:30:00.000Z",
"exportedBy": "providertone-local",
"version": "1.0.0",
"providerId": "dr-smith",
"messaging": {
"completedAt": "2024-06-15T15:30:00.000Z",
"generatedProfile": {
"surfacePatterns": { ... },
"toneDimensions": { ... },
"negativeConstraints": { ... },
"judgmentPatterns": { ... },
"signatureMoves": [ ... ],
"voiceSummary": "...",
"exampleFragments": [ ... ]
}
},
"documentation": {
"completedAt": "2024-06-15T15:30:00.000Z",
"generatedProfile": {
"structuralPatterns": { ... },
"voiceDimensions": { ... },
"standardPhrasings": { ... },
"visitTypeVariations": { ... },
"signatureMoves": [ ... ],
"voiceSummary": "..."
}
}
}The tool automatically scans output for potential PHI:
- Names (Mr./Mrs./Dr. patterns)
- Dates
- Phone numbers
- Email addresses
- SSNs
- MRNs
- Addresses
Use --redact to automatically replace detected PHI:
providertone generate-profile \
--messaging analysis.json \
--output profile.json \
--redact- Run on encrypted disk - Use FileVault/BitLocker
- Delete intermediate files - Remove analysis JSONs after profile generation
- Review output - Always review before sharing
- Use BAA - Ensure Anthropic BAA is in place before using Claude API
For fully air-gapped environments, use a local LLM via Ollama:
# Start Ollama
ollama serve
# Pull a model
ollama pull llama3:70b
# Run analysis with local LLM
providertone extract \
--messages messages.csv \
--provider-id dr-smith \
--llm local \
--output profile.jsonConfigure in .env:
LOCAL_LLM_ENDPOINT=http://localhost:11434
LOCAL_LLM_MODEL=llama3:70bCheck that provider_id in your data matches the --provider-id argument exactly.
Ensure Ollama is running: ollama serve
The tool includes delays between API calls. For large datasets, consider:
- Reducing
--sample-size - Running during off-peak hours
- Using local LLM
Review the findings and either:
- Use
--redactfor automatic redaction - Manually review and edit the output file
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Format code
black src/
# Lint
ruff src/MIT License - See LICENSE file