Skip to content
 
 

Repository files navigation

TherapyNotes

A cross-platform, browser-based, locally-deployed psychotherapy documentation platform: a Docker Compose stack (FastAPI api + FastAPI gateway + SvelteKit web + Postgres) that runs entirely on hardware you control, with inference and storage local by default. It re-architects an existing, validated macOS app (ClientNote / Euni™) into a portable, dramatically easier-to-run product.

Its guiding idea: you don't have to take our word for how it treats your clients' data — there are receipts, and the code is open. The app runs on your own computer (or a server your practice controls); if you choose a cloud model, the note is de-identified on your machine first and only the de-identified version leaves. See the in-app About & Privacy area (/about, readable before you sign in) for the plain-language explanation and interactive walk-throughs.

The two P0 commitments

  1. No fabrication. The system never quotes or attributes anything to a client's record unless that text appears verbatim in that specific client's record — anything unverifiable is rendered as unverified, never presented as fact.
  2. No missed safety-critical content. Safety-critical statements (suicidal/homicidal ideation, self-harm, plans and means, abuse disclosures, risk to others) must never be silently dropped or summarized away — they are detected, preserved verbatim, and forced into the clinician's view for confirmation.

Get it running (from a fresh clone)

These steps stand the whole stack up on your own machine. They assume you're comfortable running a few terminal commands, but not that you know Docker or Ollama.

1. Prerequisites

  • Docker Desktop (macOS/Windows) or Docker Engine + Compose v2 (Linux). This is the only hard requirement — the app itself runs in containers.
  • Git, to clone the repository.
  • A local AI model (recommended default). Install Ollama on your computer, then pull the default model once:
    ollama pull gemma4:12b-mlx
    On a memory-constrained machine, use the smaller gemma4:e4b tag instead. (Prefer not to install Ollama on the host? See Containerized Ollama below.) A local model means nothing ever leaves your machine; a cloud model is optional and configured later in the app's Settings.

2. Clone and configure

git clone <this-repo-url> TherapyNotes
cd TherapyNotes
cp .env.example .env

The defaults in .env work for the host-Ollama setup above — you don't need to edit anything to start.

3. Start the stack

docker compose up --build -d

This builds and starts postgres, the gateway, the api (which runs its database migrations automatically on start), the transcription placeholder, and the web app. The first build takes a few minutes; subsequent starts are fast. (make up is a shortcut for the same command.)

Check that the backend is healthy:

make smoke      # or: curl -fsS http://127.0.0.1:8000/health && curl -fsS http://127.0.0.1:8100/health

4. Create your login

The app requires a sign-in (there's no open registration — you provision accounts yourself). Create one:

docker compose exec api python -m app.manage create-user --username you

It will prompt you to set a password. (To add more people later, run it again with a different --username.)

5. Open the app

Visit http://localhost:3000 and sign in with the account you just created.

To stop everything: docker compose down (add -v to also erase the database).


Using it

  • Write a note: pick a client, paste or type your session notes, choose a format (PIRP/SOAP), and generate. Review the draft — statements the app couldn't verify against your record are flagged — resolve any safety content, then Sign. Change a signed note with Amend (a new version; the original is preserved). Copy a signed note to paste into your system of record.
  • See the receipts: open the trust receipt under a note to see where each line came from, and "What the AI saw" on a draft to read exactly what was sent to the model and what came back.
  • Diagnosis codes: the "Diagnosis codes" panel in the left sidebar is an offline ICD-10-CM lookup (common mental-health codes) — search by code or keyword and copy the code. It works with no internet; the panel shows when the code set was verified and against what.
  • About & Privacy: /about (reachable before login) explains, in plain language and with interactive diagrams, how your data is protected and what changes if you use a cloud model.

Local inference: host Ollama vs. containerized Ollama

  • Host-managed Ollama (default): install Ollama on the host and ollama pull gemma4:12b-mlx. The gateway container reaches it via host.docker.internal (see .env.example) — no extra compose profile needed.
  • Containerized Ollama: run docker compose --profile local-ollama up -d, then docker compose exec ollama ollama pull gemma4:12b-mlx, and set OLLAMA_BASE_URL=http://ollama:11434 in .env so the gateway talks to the containerized instance.

Cloud models (optional)

Cloud models are off by default. To use one (e.g. Claude), add your API key in the app's Settings; every note is de-identified through the privacy firewall before anything leaves the equipment you control. If you never add a cloud key, the app runs entirely locally.


Deploying for a small practice (over a LAN)

The default setup above is loopback-only (just your machine). To host it for a few clinicians on a trusted local network over HTTPS, use the hardened production profile and follow docs/product/deploying-on-lan.md.

For developers

License

Open-source edition: AGPL-3.0-or-later, © 2026 Tucuxi, Inc. AGPL's network-copyleft means anyone can read, run, and modify this code, but a commercial or hosted product built on it must either stay open under the AGPL or take a separate commercial license, available from Tucuxi, Inc. See NOTICE and ADR-0004.

Upgrading between releases of this repository

This repository publishes its database schema as a single squashed migration rather than the incremental chain the project develops against. That keeps each release self-contained and easy to install — and it has one consequence worth stating plainly rather than letting you discover it:

A fresh install is unaffected. You get exactly the schema the project runs, verified against the full chain before each release.

An installation created from an EARLIER release of this repository cannot upgrade in place across a squash boundary. Alembic will not recognise the revision your database is stamped with. If you are running an older build with data you care about, export it, install fresh, and re-import — do not run alembic upgrade head and hope.

If in-place upgrades across releases matter to you, please open an issue and say so. It is a solvable problem; whether it is worth solving depends on whether anyone is actually running this.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages