square_export.csv
The raw booking export. Names, emails, phones, dates of birth.
And you lose almost nothing by doing it that way. Here is the whole system on one page, so you can come back to it without having to remember a call.
Claude does not read it, act on it, or send it — whatever file, message, filename, or commit it happens to sit in.
Your Claude plan has no Business Associate Agreement, which is the contract that would let a vendor handle protected health information on your behalf. Without it, patient records are not covered. That is a fact about the plan, not a flaw in the tool, and the honest response is to keep the data out rather than hope nobody pastes it in.
You could just try to remember that. Everybody intends to. What follows is the same rule, built into the software so it does not depend on anyone's memory at four in the afternoon.
Identity stays on the left. Everything you actually analyze lives on the right. One command is the only way across, and it never carries a name with it.
Real people. Never opened here.
square_export.csv
The raw booking export. Names, emails, phones, dates of birth.
reid_map.SECRET.csv
The only file that can turn a code back into a person. Lives in a private folder in your home directory, readable by you and nobody else.
your inbox, your phone
Where a real name gets attached to a message, at send time, outside all of this.
Codes and operations. Work freely here.
appointments_deidentified.csv
Same rows, same appointments, no identities. Each patient becomes a stable code like PT-0374BC4436B1.
weekly reports, analysis
No-show rates by location, by service, by staff member. Repeat no-shows. Booking drop-off.
message drafts
Written with [PATIENT_NAME] where the name goes. You fill that in outside, when you send.
The same patient always gets the same code, in every export, forever. That is what lets you say "this person has missed three appointments" without anyone in this workspace knowing who they are.
De-identifying is not the same as deleting. The columns that answer operational questions are exactly the ones that carry no identity, so they all survive the trip.
| Dropped at the door | Kept, in full | What you can still answer |
|---|---|---|
given_name, family_name |
location |
Which location has the worse no-show rate |
email_address, phone_number |
service_name |
Which treatments get cancelled most |
date_of_birth |
team_member |
Whether load is spread evenly across staff |
customer_id, booking_id |
start_at, status |
When cancellations cluster, and how late they arrive |
| notes with names in them | intake_form_completed |
Whether a missing intake form predicts a no-show |
That last row is not hypothetical. On the sample data we will use together, patients with no completed intake form missed appointments at nearly twice the rate. Small sample, synthetic data, so it is a hypothesis rather than a finding. But it was found without a single real name being involved, which is the whole argument in one line.
This runs automatically on every file opened, every command run, and every message sent out. You do not turn it on and you cannot forget it.
Names that read like raw patient data, in English and Spanish.
patient_list.csv · pacientes.csv · *.SECRET.csvThe actual header row. This is the one that does the work: anyone can rename a file, nobody strips the columns out.
email_address · pt_dob · Customer Name · fecha_nacimientoThings shaped like a social security number, a real email address, a phone number, even when the columns are labelled innocently.
123-45-6789 · 713-555-0134Spreadsheets and databases cannot be inspected from the outside, so they are refused rather than waved through. Export to CSV first.
.xlsx · .parquet · .numbersAnything that would push a file off this machine. The destination is the part nobody can vouch for.
curl · scp · upload · git pushSlack, Gmail, Drive, anything fetched from the web. These carry their contents directly, so the contents get read before they leave.
a name in a draft · a phone number in a URLClearly patient data. It does not happen, and no approval makes it happen.
Might be a patient, might be a supplier. It stops and shows you exactly what would be sent and to whom.
Ordinary work. Coded data, normal commands, nothing personal. No interruption.
On a pause, Claude is instructed in writing that it may not approve the send on your behalf, may not reword the message and try again, and may not write it off as a false alarm. If you are not around, the answer is no. That judgment call is exactly the one that should never be automated, so it is not.
One more thing worth knowing: if the guard itself ever breaks, it blocks. A guard that fails open would be decoration.
CLAUDE.mdthe rules, read first, every sessionregistry/which process uses which steps, and whether it touches patient datadirectives/how each recurring job is done, in plain languageexecution/the scripts that do it the same way every timelearnings/what surprised you, and what became a permanent rule.envcredentials. Never opened, never printed, never sharedThe split matters more than it looks. Anything that must give the same answer every time belongs in a script, not in a conversation. Judgment stays with you and with Claude. Arithmetic does not.
An error takes two attempts, a tool behaves oddly, an instruction turns out to be stale. It gets written down in the same session, not later.
At twenty entries it stops asking politely and requires a clean-up pass before anything else is added.
The lessons worth keeping become permanent rules. The rest is archived. The active log goes back to empty.
Capture is the easy half and it is the half most systems stop at. The log grows, nobody reads it, and the lessons in it stop changing anything. Bounding it is what keeps it alive.
If you ever find yourself looking at something that is obviously patient data and nothing stopped you, stop yourself, and tell us what got through. That is how the list of things it recognizes gets longer.