A personal "context instrument": a single-file dashboard that visualises your own social graph derived from Telegram message history and Obsidian person-cards.
This repository contains a fully synthetic demo with zero real people. The real instance keeps all raw messages local and never sends data anywhere.
Relationship OS answers the question: who in my life deserves attention right now, and what kind of attention?
It models each relationship along four axes drawn from the research literature
(see research/):
| Axis | What it measures |
|---|---|
| Decay / state | Time elapsed relative to per-tier cadence interval × resilience multiplier (research/mechanics.md) |
| Closeness | Interaction volume + reciprocity + tier assignment (research/categories.md) |
| Context richness | Obsidian card coverage × conversation depth × years known × shared groups (research/phases.md) |
| Phase / sync | Long-range relationship arc: initiation → build → maintenance → dormancy (research/sync.md) |
eff = (days_since_contact / tier_interval) / R
state = warm | cooling | overdue | atrisk | dormant | nodata
score = 100 × clamp(1 − eff/8, 0, 1)
where R (resilience) ∈ {0.6, 1.0, 1.5, 2.0} based on tie type and longevity.
Tier intervals: inner=7d · close=30d · network=90d · dormant/archived=365d.
Plain version: a read-only script pulls your Telegram message history, another
gathers your Obsidian person-cards, a build step joins them and recomputes the
four axes into a single data.js, and one HTML file renders it all. Nothing
runs in the cloud; the dashboard never sends a message — you copy the ping and
write it yourself.
flowchart LR
TG["telegram<br/><i>read-only, Telethon</i>"] --> PULL["pipeline/pull_full.py"]
OBS["obsidian<br/><i>person-cards</i>"] --> GA["pipeline/gather_authors.py"]
PULL --> B["pipeline/build_v3.py<br/><b>engine: decay · closeness ·<br/>richness · phase</b>"]
GA --> B
B --> DJ["data.js"] --> UI["index.html<br/><i>6 tabs, zero backend</i>"]
UI -. "ping is copy-only — you send it" .-> YOU(["a decision:<br/>who to write today"])
Six tabs: today / people / graph / decay / coach / obsidian.
- Today queue: who to ping now, 4 ping templates (warm / playful / business / reconnect), random-contact serendipity card, unread counter
- Decay colour coding: warm (green) → cooling → overdue → atrisk → dormant
- Person detail panel: recent messages, topic clusters, momentum arrows (win30 vs win60), 7-phase relationship arc, context richness bar, Obsidian card links, ping anchor, rule-based recommendation
- Graph with three layouts: contours (concentric Dunbar rings, you at the centre, sector = tie type), force (shared-group edges), topic clusters — with lenses for state / tier / category / closeness / context richness
- Multiplex view: people with both work and personal cards
- No-card audit: active contacts without an Obsidian card
- Duplicate detection: two identities resolving to the same person
- ⌘K command palette, hotkeys (
/search ·ttheme ·rrandom ·1–6tabs), light/dark theme, data-freshness badge - Copy-only by design: the instrument never sends a message — you do
![]() |
![]() |
| people — search, filters, closeness dots | graph — Dunbar contour rings |
![]() |
![]() |
| decay matrix by tier × state | coach — neglect rating, reach-out stats |
All names on the screenshots are generated by make_demo.py.
git clone https://github.com/aPoWall/relationship-os
cd relationship-os
# generate synthetic data
python3 make_demo.py
# serve locally
python3 -m http.server 8137
# open http://localhost:8137make_demo.py writes data.js (approx 150 KB) with 50 invented people and
~40 synthetic edges. No network access required.
The pipeline lives in pipeline/. You need:
- A Telegram account and a Telegram app (https://my.telegram.org → API_ID + API_HASH)
- A dedicated Telethon session (
dashboard.session) — see Telethon docs - An Obsidian vault with
@authors/person-cards (optional but enriches output) - Python 3.10+,
telethon,pyyaml
pip install telethon pyyaml
# 1. Pull Telegram data (6-month window, read-only)
export TG_API_ID=your_api_id
export TG_API_HASH=your_api_hash
export TG_SELF_ID=your_telegram_user_id
export RELOS_DATA=./data
python3 pipeline/pull_full.py
# 2. Gather Obsidian identity layer
export VAULT=~/path/to/your/obsidian/vault
python3 pipeline/gather_authors.py
# 3. Build data.js
python3 pipeline/build_v3.py
# 4. Open dashboard
python3 -m http.server 8137For incremental refresh (after initial pull):
python3 pipeline/pull_refresh.py last # cheap: update last_active ~12 s
python3 pipeline/pull_refresh.py delta # medium: fetch new messagesKey config points in pipeline/build_v3.py:
CURATEDdict: your handle → tier overridesKNOWNdict: handle → known_since dateCURATED_CATEGORYdict: handle → category overrideNOHANDLElist: people in your circle with no Telegram account
This public repo is 100% synthetic. The make_demo.py generator produces
invented names, handles, and generic message text. No real Telegram IDs, no
real handles, no real message content.
The real instance of Relationship OS:
- runs entirely locally (no cloud, no external API calls from the pipeline)
- stores message data in
/tmp(never in the vault or cloud sync) - reads Telegram via a dedicated read-only Telethon session
- never sends any message
Avatars are stored locally in data/avatars/ and are excluded from this repo
via .gitignore.
index.html single-file dashboard (reads data.js)
data.js generated by make_demo.py (synthetic) or pipeline/build_v3.py (real)
make_demo.py synthetic data generator
pipeline/
build_v3.py joins TG + Obsidian layers -> data.js
pull_full.py Telegram 6-month deep pull (Telethon, read-only)
pull_refresh.py incremental refresh (last | delta modes)
gather_authors.py Obsidian @authors layer
research/
categories.md tie classification framework
mechanics.md decay formula derivation
phases.md relationship phase model
sync.md synchrony and maintenance patterns
- harness-setup-selfdev — the personal AI harness this tool grew on: guide, skill, worked examples, dashboard. Relationship OS is the «possible result» chapter of that story.
MIT. Use freely; attribution appreciated.




