Privacy & data handling — Peribolos
Draft. Not reviewed by a lawyer. This describes how Peribolos handles data so a clinician can assess it against their own obligations. It is written for an Australian private alpha (Privacy Act 1988 / Australian Privacy Principles), but the data-flow facts apply everywhere. A clinician using Peribolos with real clients is the entity responsible for privacy compliance — see TERMS.md.
The short version
- Peribolos is local-first. Your clients, sessions, notes, invoices and clinical record live in SQLite files on your own machine. They are not uploaded anywhere by default.
- Peribolos has no analytics and no remote logging. The developer cannot see your data. It does send one small signal of its own: once a day, a random install number and the app version, so the developer can see Peribolos is in use. It carries nothing about your practice. It is on unless you turn it off (Settings → Privacy & security → Usage and diagnostics); on an install that never made a choice, it starts only after a one-time notice in the Office (see below). Crash reports stay off unless you switch them on.
- Apart from that signal, the only data that leaves your machine is what you trigger, through the integrations you enable. Each is listed below.
- The most significant flow: when you run an AI transformation, de-identified note
content is sent to your configured AI provider — Anthropic (Claude) by default,
processed in the United States, or OpenAI / another OpenAI-compatible provider if
you configure one (
ai.provider: openai). A fully local option (Ollama) sends nothing. - Voice dictation cleanup is local by default. The optional pass that tidies a dictated
transcript runs on a local model (if you've configured one) or is skipped — either way
the raw transcript stays on your machine. It is sent to Anthropic only if you explicitly set
ai.cleanup_allow_cloud: true. On that opt-in path its structured identifiers (email, phone, Medicare, NDIS numbers) are stripped first, but client names you speak aloud are not removed (name de-identification needs a client record this step does not have). See the table. - De-identification is best-effort, not guaranteed anonymisation. It removes your registered clients' names and stored details and pattern-matches common identifiers (emails, phone numbers, Medicare/NDIS), but it is not a guarantee: an unregistered third party's name, a place or employer, or an identifier written in an unusual format can still pass through. Your own note-writing discipline remains part of the safeguard.
What stays on your device
Everything, by default:
practice.db— clients, sessions, invoices, the clinical record, audit trail.process_notes.db— your raw process notes and their transformations..env/config.yaml— your settings and API keys.- Backups — rotated copies in your chosen backup folder.
- Session recordings (if you enable the recording feature) — recorded and transcribed
locally. Audio is kept after transcription so a line of the transcript can be heard
again, and no recording audio is kept longer than
recording.retain_days(default 90 days): a daily sweep deletes any audio older than that, including audio from failed or abandoned transcriptions. A client can ask for their audio to go after 30 days instead (a box on the consent screen, changeable later); each recording keeps the window its client was told, so a later change to the setting never keeps audio longer. Withrecording.retain_audio: false, audio is deleted as soon as the transcript is produced. Transcripts are kept like any other note.
These files are set to owner-only permissions (0600) on macOS/Linux. Disk encryption (FileVault on macOS, BitLocker on Windows) is still your responsibility and is what protects them at rest.
While Peribolos is running it serves only on 127.0.0.1 (your machine, not the network) and
has no login — deliberate for a single-user local app. The trade-off: any program running on
your computer under your own user account can reach that local port and read the same data,
just as it could read the database files (both are scoped to your account, not to Peribolos). This
is the same trust boundary as your files. Keep your computer account password-protected, and don't
run untrusted software while Peribolos is open.
What leaves your device — and only when you enable it
| Flow | What is sent | To whom | Where | When |
|---|---|---|---|---|
| AI transformations / Workshop | Note content, de-identified first (registered client names, DOB, phone, email, address scrubbed; third-party emails/phone-numbers and Medicare/NDIS numbers pattern-scrubbed). | Your configured AI provider: Anthropic (Claude API) by default; OpenAI or another OpenAI-compatible provider if you set ai.provider: openai |
United States (Anthropic / OpenAI); other compatible providers vary | When you trigger a transformation, the Workshop, or goal extraction. Requires your own API key (or a Peribolos access token). |
| Dictation cleanup (off-device only if you opt in) | The dictation transcript with structured identifiers (email/phone/Medicare/NDIS) stripped, but client names you speak aloud are NOT removed (name de-identification cannot run at this step). By default this does not leave your machine: the cleanup pass runs on a local model or is skipped. It is sent here only if you set ai.cleanup_allow_cloud: true. |
Your configured AI provider (as above) | As above | Only if you set ai.cleanup_allow_cloud: true. The master switch is ai.llm_cleanup_enabled; per-note, the "cleanup" checkbox. |
| Hosted access-token mode (optional) | The same content as the two AI rows above — de-identified for transformations, and (only if you opt into cloud cleanup) the dictation transcript with structured identifiers stripped but spoken names intact. | A Peribolos-operated relay, then Anthropic | Relay + United States | Only if you use a Peribolos access token instead of your own Anthropic key. |
| Resource links (optional, per client) | The resources you tick for a client — their titles, descriptions, file names, the files themselves and any links — plus your practice name, published as a page at a random link. Not the client's name, email or any other detail about them, and nothing that identifies your install: which client a link belongs to is recorded only on your computer. Titles, descriptions and file names are checked against your client list and the page isn't updated if a client's name appears in them. Anyone who has the link can open the page. | A Peribolos-operated relay (Fly.io) | Australia (Sydney) | Only when you create a link on a client's Resources tab. Turning the link off removes the page and its files from the relay. Refused while strict local mode is on. |
| Google Calendar sync (optional, off by default) | Session times and the client's name (event titles read "Client Name — Therapy Session"); additionally the client's email if you enable client invitations. | United States | Only if you connect Google Calendar (calendar.provider: google). |
|
| CalDAV calendar sync (optional, off by default) | Session times and the client's name (same event-title convention). No client emails — invitations aren't sent on this provider. | Your calendar provider (Apple iCloud, Fastmail, Nextcloud, or the CalDAV server you configure) | Provider-dependent (Apple/Fastmail: United States; self-hosted Nextcloud: wherever you run it) | Only if you connect a CalDAV server (calendar.provider: caldav). |
| Calendar feed (ICS) (optional, off by default) | Session times and client names, served as a read-only feed from your machine only — nothing is pushed to any third party. The calendar app you subscribe with (e.g. Apple Calendar, Outlook) then holds a copy on your device and in that app's own sync, per its policies. | The calendar app you point at the feed | Your machine; then wherever that app syncs | Only if you switch the feed on in Settings → Calendar. |
| Email reminders (optional) | Reminder text + client email, via your own SMTP provider. | Your email provider | Wherever your provider operates | Only if you enable email. |
| SMS reminders (optional) | Reminder text + client mobile number. | BurstSMS | Provider-dependent | Only if you enable SMS. |
| Stripe payment links (optional) | Invoice amount and reference; the client enters their own card details on Stripe's page. | Stripe | United States / global | Only if you enable Stripe. |
| Bank matching — Basiq (optional, AU) | Bank transaction metadata (not clinical data). | Basiq | Australia | Only if you enable Basiq. |
| Bank feed (optional, off until you connect one) | Nothing is sent. Peribolos reads the transaction lines of the one bank account you chose, from a bridge service you subscribe to that speaks the SimpleFIN standard (e.g. Redbark, which itself relies on an accredited Consumer Data Right recipient). Payer text on a credit can carry a client's name; those lines are kept on your machine like a CSV upload. | The bridge you chose | Provider-dependent (Redbark: Australia) | Only if you paste a setup token under Settings → Bank feed. Off under strict local mode. |
| Claude Code integration (optional, only if you run the setup wizard's "Connect Claude Code" step) | Whatever you then ask Claude Code for. This registers your practice database as a data source it can read directly — identified, not de-identified: real names, sessions, notes. It is the one path in Peribolos where identifying material can reach an AI, it is not covered by strict local mode, and it stays open until you remove practice-db from your Claude Code config (~/.claude.json). |
Anthropic, through your own Claude Code account | Per your Claude Code account | Only if you complete that optional step, and then only when you ask Claude Code something. |
| Your name and email (required at setup) | The name and practice email you gave at setup, with a random install number and the app version. Sent once, and again only if you change either. Nothing about your practice or your clients. | A Peribolos-operated endpoint | Australia (Sydney) | Once, after setup (and on a change). Never in demo mode. |
| Sharing how you move through Peribolos (optional, off by default) | The record Peribolos keeps on your computer of which screens you open and which buttons you press: for each, the minute, the room, the screen's name and the button's name. Never anything typed, never a client's name or details — an entry holding anything that looks like a name, a number or an email is dropped before it is kept. With your random install number. | A Peribolos-operated endpoint | Australia (Sydney) | Once a day, only if you tick it at setup or switch it on under Settings → Privacy & security. Never in demo mode. |
| Daily usage signal (on unless you turn it off) | A random install number (made on your machine), the app version, and the dates on which the AI features were used on this computer. The relay notes the day it arrived. No client data, no notes, nothing about your practice. | A Peribolos-operated endpoint | Australia (Sydney) | At most once per calendar day. On an install that never made a choice, only after the one-time notice in the Office. Never in demo mode. |
| Crash reports (optional, off by default) | When the app itself hits an error: the error type, its message and the stack (the lines of code it passed through), with the app version. Client names, email addresses, phone numbers and home-folder paths are removed first; a report that can't be de-identified is not sent. No local variables, no log history, no computer name. Every text in a report is cut to 300 characters. | Sentry (error-reporting service) | United States | Only if you switch it on, and only when an error occurs. A build with no crash-report destination sends none. |
| In-app feedback (user-initiated) | What you type in the feedback form; any screenshots you attach (up to three — check them before you send, since a screenshot of the app may show a client's name); the same non-PHI technical summary as Help → Copy diagnostics (versions and health checks); and the email address your access token was issued to, so a reply can reach you. | A Peribolos-operated endpoint | Australia (Sydney) | Only when you press Send. |
If you enable none of the optional integrations, never trigger an AI transformation, and turn off the daily usage signal, nothing leaves your machine apart from the name and email you gave at setup.
Google user data (Google Calendar sync)
This section covers what Peribolos does with data from your Google Account when you connect Google Calendar in Settings → Calendar. Nothing here happens unless you connect.
- What Peribolos asks Google for. Two permissions: to see and edit the events on calendars you own, and to see the list of your calendars. Nothing else in your Google Account — not your Gmail, contacts, files or other Google services.
- What it does with them. It puts sessions you book in the Office onto your calendar (with an invitation to the client, if you switch that on), moves or removes those events when you change a session, and reads your calendar's events so changes you make there come back into the Office. It reads the calendar list once, to show which Google account is connected.
- Where it is kept. Everything Peribolos receives from Google stays on your computer: the sign-in token in the app's data folder (readable only by your user account), and the session times and event details the Office keeps in its own database. None of it is sent to Peribolos's servers or to anyone else.
- AI. Data received from Google is not used to develop, improve or train AI or machine-learning models, by Peribolos or anyone else.
- Limited Use. Peribolos's use and transfer of information received from Google APIs adheres to the Google API Services User Data Policy, including the Limited Use requirements.
- Disconnecting. Remove Peribolos's access at any time from your Google Account (Security → Third-party apps & services). Deleting Peribolos's data folder removes the token and everything synced from Google from your computer.
Strict local mode
Settings holds a strict local mode switch (Office → Settings → Strict local mode, stored in your practice database, off by default). With it on, no AI feature will send note content to an online AI service: any transformation, Workshop exchange, or dictation-cleanup step whose configured AI endpoint is off this machine is refused before anything is sent, and the refusal is shown where it happens. AI features keep working when the configured provider runs locally (Ollama, or any OpenAI-compatible server on a loopback address). What counts as "local" is judged by the endpoint's address, not the provider's name — a remote Ollama server is treated as online. Note that local models are not yet dependable for clinical transformations — in testing, a small local model recorded frame-check details that were not in the note — so their output warrants careful review. Strict local mode governs where content goes, not the quality of a local model's output. The switch governs AI sends only; the optional integrations in the table above (email, SMS, calendar, Stripe, Basiq) keep their own separate switches.
Daily usage signal (on unless you turn it off)
Peribolos is a private alpha, and one thing the developer genuinely can't see under a local-first design is whether an install is still in use at all. The daily usage signal is a narrow answer to that — nothing more.
- What is sent: a random install number (a
uuid4, generated once on your machine), the app version string, and the dates (from the last month) on which an AI feature was used on this computer. That is the entire payload. The relay's ledger keeps that number, the day it arrived, the version and those dates — not your email, and not your IP address. - The AI-use dates are dates only. Never what was written or read, which feature, which client, or how many times. A date counts only when you used an AI feature from a page; work Peribolos does in the background on its own doesn't count. The dates are sent only after the Office has shown a notice naming them: an install that saw the earlier notice, which named two things, is shown the new one once, and sends no dates until then.
- What is never sent: no client data, no notes, no names, no email, no content of any kind, nothing about your practice. The signal carries no PHI by construction.
- A random number, not an anonymous one. The number stays the same from day to day, so the developer can tell one install's days apart from another's. If you buy a plan, the purchase is filed under the same number, and from then on the signal can be linked to the email you bought with.
- On unless you turn it off. New installs: the first-run setup form has a pre-ticked box for it (the command-line setup asks, with Yes as the default). Untick it and it never starts. Installs that were set up before this change, or never made a choice: nothing is sent until the Office has shown a one-time notice saying so, with a Turn off button beside it. A choice you already made — on or off — is kept.
- Frequency: at most once per calendar day, best-effort. Never in demo mode.
- How to turn it off: Turn off on the notice, or untick it under Settings → Privacy & security → Usage and diagnostics at any time. No further signal is sent.
Crash reports (opt-in)
When the app itself hits an error, a crash report tells the developer what broke so it can be fixed — without it, a crash on your machine is invisible. Unlike the daily usage signal, it is off by default, and narrow by construction. Until a build carries a crash-report destination, none can be sent, and Settings says so rather than showing a switch.
- What is sent: the technical details of the error — the error type, its message, the stack (the lines of code it passed through, with a few lines of source around each), and the app version — to Sentry, an error-reporting service in the United States.
- What is removed first: registered client names (full name, each part, preferred name and aliases) and the phone numbers, email addresses and other identifiers on their records; any email address, phone number, Medicare or NDIS number; and your home-folder path, which usually carries your name. This is the same de-identification the Workshop uses before anything reaches an AI. A report that can't be de-identified — the client list can't be read, or the removal fails — is not sent.
- What is never sent: no local variables (the values the code was working on), no log history, no computer name, no installed-package list. No performance tracing, no usage analytics. An error message can quote what the code was handling when it failed, so a fragment of other text can ride along with names and contact details removed — the reason this is off unless you turn it on.
- Off by default. It stays off unless you switch it on under Settings → Privacy & security → Usage and diagnostics in the Office, where the switch appears once a destination exists. Once there is a destination the Office asks once, with Turn on and Not now; Not now stores nothing and it stays off. The first-run setup form doesn't offer it.
- How to turn it off: untick it there at any time. It takes effect immediately. Never in demo mode.
Cross-border disclosure (Australian Privacy Act — APP 8)
The AI transformation flow sends de-identified note content to your configured AI provider — Anthropic by default, which processes it in the United States; OpenAI (or another OpenAI-compatible provider) if you have configured one. Under Australian Privacy Principle 8 (cross-border disclosure of personal information):
- De-identified information is generally outside the scope of the Privacy Act. Peribolos
de-identifies registered client identifiers before it sends note content for a transformation,
which is designed to keep that flow out of APP 8. Two caveats matter. First,
de-identification is never guaranteed perfect — free-text content can contain identifiers the
scrub does not know about (a partner's name, an employer, a place). Second, the dictation
cleanup pass is not de-identified — but by default it runs locally or is skipped, so it
normally sends nothing. It reaches Anthropic only if you set
ai.cleanup_allow_cloud: true, and when it does the raw transcript — including any client name you speak — is sent as spoken. You are responsible for what you write and speak into notes and for confirming output is genuinely de-identified. - If you cannot be confident a particular note is de-identified, do not transform it, or edit it first.
- The other integrations above (Calendar, Stripe, SMS) transmit identified personal information to overseas recipients when enabled. Enabling them is a cross-border disclosure you are making, and you must handle it under APP 8 (and your registration body's guidance), including informing clients.
Anthropic's terms, privacy policy and data-handling commitments: anthropic.com/legal. If you configure a different provider (OpenAI: openai.com/policies), that provider's data-handling terms apply instead — verify them yourself before switching; Peribolos makes no representation about any provider's data practices. If you are bound by HIPAA in the US, you must obtain a Business Associate Agreement with your AI provider directly — Peribolos does not manage one for you.
A consent / disclosure note you can adapt for clients
Parts of this practice's note-keeping use an AI tool (Anthropic's Claude — substitute your provider if you have configured a different one) to help draft and structure clinical documentation. Before any note content is sent, identifying details (names, dates of birth, contact details) are removed. The de-identified text is processed on servers in the United States and is not used to train AI models under the API terms in force. You can ask me not to use this tool for your records at any time.
Adapt this to your practice and your professional obligations. This is a starting point, not
legal advice, and not a substitute for your own consent process. Note the dictation-cleanup
setting: the cleanup pass is local (or skipped) by default and sends nothing. Only if you turn on
cloud cleanup (ai.cleanup_allow_cloud) does the "identifying details are removed before sending"
wording stop holding for that step — the raw transcript, including any spoken name, is sent first.
Retention and deletion
- You control retention. Backups rotate on the schedule in
config.yaml(default 90 days). - To delete a client's data, delete it in the app; to delete everything, delete the database files and your backups.
- The clinical record uses an append-only audit trail with a 72-hour lock, so corrections are recorded as revisions rather than silent overwrites — by design, for clinical-record integrity.
Breach response
If client data is exposed — device theft/loss, malware, accidental sharing — you are the party with notification obligations (to clients and, where thresholds are met, to the OAIC under the Notifiable Data Breaches scheme). Peribolos holds no copy of your data and cannot notify on your behalf.
Draft: a lawyer will review this before any wider release.