Beck
Scott’s health companion. Replaces iris360, which paywalled him out on 2–3 August 2026 in the middle of a blood-pressure titration. Named after Aaron Beck.
Design rationale and the build-vs-pay argument: docs/rebuild-scope.md.
Project status: BRIEF.md.
The split that matters
Code and docs live here — ~/Projects/Unicorn.Land/beck, git, private repo.
Scott’s data lives in BECK_HOME — ~/Projects/Obadiah/workspace/beck, which sits inside
Obadiah’s gitignored workspace/. His health record, the iris360 transcripts, the guides, the
database, and the curated notes are all on that side and none of it is tracked anywhere.
This repo’s .gitignore blocks the same paths as a second line of defence. Keep the split.
BECK_HOME/
beck.db store
notes/
identity.md who Scott is — rarely changes
current-focus.md the live picture — read before every reply
autopilot.md cadence, milestones, weekly review
topics/ blood-pressure.md, and others as they matter
archive/
data/
transcripts/ 188 iris360 daily files (10.12.2025 → 03.08.2026)
guides/ iris360's guide library, saved 03.08.2026
notes/ iris360's own case file — 17 notes, exported as PDF 03.08 and
pdf/ text-extracted. Read-only archive; the live notes are above.
entries.md the hand-written Phase 0 log, superseded by beck.db
Setup
./beck.py init # create the db + notes tree
./seed_transcripts.py --dry-run # check what the parser finds
./seed_transcripts.py # import readings + conversation index
./beck.py status
Seeding is idempotent — a unique index on (ts, kind, payload) means re-running it cannot
duplicate readings.
Daily use
./beck.py context # READ THIS FIRST — notes + recent record
./beck.py log "128/79 p:73" --at 21:38
./beck.py trend bp --days 14
beck.py log parses BP shorthand (142/92 p:100), sleep durations, and dose/posture context.
Anything it cannot parse is still kept as a note rather than dropped.
Pre-dose versus post-dose and seated versus post-walk are stored as separate fields, because a
reading can be both and the dose relation is the clinically load-bearing one. Getting that
backwards is worse than leaving it blank — see the comment in beck.py.
The agents
Three, not iris360’s five.
| Prompt | Role |
|---|---|
prompts/beck.md |
The front door. The only one Scott talks to. Carries the safety discipline. |
prompts/autopilot.md |
Decides whether and what to check in on. Allowed to stay silent. |
prompts/curator.md |
Not written yet — will maintain and compress the notes. |
Autopilot — NOT ENABLED
The scripts work. The cron entries are deliberately not installed.
Turning them on means an automated system starts messaging Scott about his health on a schedule he has not agreed to. His preference is documented (see below) but it was a preference given to iris360, not consent for Beck to start messaging him. Confirm with him before switching this on.
Test without messaging him:
BECK_DRY_RUN=1 BECK_SLOT=morning BECK_NOW="Tuesday 4 August 2026, 06:15" \
./scripts/beck-checkin.sh
When it is time to go live:
30 8 * * * BECK_SLOT=morning /Users/joshua/Projects/Unicorn.Land/beck/scripts/beck-checkin.sh >> /tmp/beck-checkin.log 2>&1
0 18 * * * BECK_SLOT=evening /Users/joshua/Projects/Unicorn.Land/beck/scripts/beck-checkin.sh >> /tmp/beck-checkin.log 2>&1
0 * * * * /Users/joshua/Projects/Unicorn.Land/beck/scripts/beck-heartbeat.sh >> /tmp/beck-heartbeat.log 2>&1
Those times are Scott’s documented preference, recovered from iris360’s own autopilot.md:
morning 08:00–08:30 after the school drop-off, evening 18:00–19:00. He asked for one check-in a
day during a calm baseline, two only around a known gate, and explicitly not to be chased —
so the evening slot exists but should mostly resolve to SKIP.
Install the heartbeat at the same time as the check-ins, not later. It alerts #secure-it when
no check-in has posted in 26 hours, which is the failure this whole design is most worried about:
cron dies quietly, Scott stops being asked, and nobody notices for a week.
The viewer — running
server.py gives Scott his own record on the home network. Live at http://192.168.178.53:8771
and http://joshuas-mac-mini-2.local:8771, under launchd, restarting on crash and on reboot.
launchctl load -w ~/Library/LaunchAgents/land.unicorn.beck-viewer.plist # start
launchctl unload -w ~/Library/LaunchAgents/land.unicorn.beck-viewer.plist # stop
tail -f /tmp/beck-viewer.log
Four pages: today’s reading with a 21-day chart and what Beck is watching · every BP reading · sleep · the notes, rendered.
Three constraints hold it together, and all three are load-bearing:
- Read-only. No route mutates anything.
- Private networks only. Every request is checked against RFC1918 and loopback ranges and refused otherwise, so a misconfigured router fails closed rather than publishing a medical record. Do not port-forward this. If it ever needs to work away from home, that is a different conversation — a tunnel with real authentication, not a wider bind.
- Standard library, no external requests. The chart is server-rendered SVG and the fonts are system fonts, so the page works with the router offline and cannot break on a dependency upgrade.
Still missing
prompts/curator.mdand the note-compression loop.- Away-from-home access, if he wants it. Deliberately not built.
scott-bp-log.pages.devalready does a doctor-ready PDF — worth folding that export into the viewer rather than maintaining two things.