# persian — Persian-language tutor at omidlab.net/persian

## Current state (updated 2026-06-23)

A live, web-based Farsi tutor with two modes: free-form **Chat** (translate/breakdown/pronounce) and structured **Lessons** (11 curated conversational topics). Cameron uses it for everyday practice toward casual spoken fluency.

- **URL**: https://omidlab.net/persian (Chat) · https://omidlab.net/persian/lessons (Lessons)
- **Backend**: Flask app at `/data/cameron/life/projects/persian/app.py`, runs on `localhost:5001` in the dedicated `srv_persian` tmux window (`debug=False`, launched via `run.sh`)
- **Chat persistence**: transcript + Claude context in browser `localStorage`, survives refresh; "Clear" button resets
- **Lessons**: curated specs (`lessons/specs.json`) → Claude-authored content (`gen_lessons.py` → `lessons/data/*.json`) → served read-only via `lessons.py`. Transliteration-first, casual register, per-phrase on-demand audio, in-lesson Q&A
- **Proxy**: `serve.py` at `/data/cameron/para/.agents/reports/serve.py` reverse-proxies `/persian/*` (port 8094)
- **Tunnel**: Cloudflared (`cloudflared-omidlab.service`) exposes omidlab.net publicly
- **Tutor model**: `claude-sonnet-4-6` with structured-output system prompt (Persian / Transliteration / English / Notes)
- **TTS**: ElevenLabs `eleven_multilingual_v2`, currently George voice (free tier, English-accented). Persian ≈70% native quality — gated on ElevenLabs Starter upgrade to swap to Nazy Entezari (`WwAjIyMBDBNl1dvId9Xe`)
- **Transliteration**: informal Iranian Finglish (kh/sh/aa/gh), NOT academic UniPers/DIN

## Architecture

```
browser → omidlab.net/persian
       → cloudflared (omidhub VPS)
       → serve.py :8094 (reverse-proxy /persian/* → :5001)
       → app.py :5001 (Flask)
           ├─ Claude → tutor response
           └─ ElevenLabs → audio (hash-cached at static/audio/<hash>.mp3)
```

Endpoints (all under `/persian` prefix):
- `GET /persian` — chat UI
- `GET /persian/lessons` — lessons library + detail (hash-routed)
- `POST /persian/api/ask` — main tutor endpoint
- `POST /persian/api/breakdown` — word-by-word breakdown
- `POST /persian/api/tts` — synthesize+cache audio for a phrase (used by lessons)
- `GET /persian/api/lessons` — lesson index · `GET /persian/api/lessons/<id>` — full lesson
- `GET /persian/static/audio/<hash>.mp3` — cached TTS
- `GET /persian/health` — health check

## Origin

Originally scoped on 2026-06-21 as a **glasses-first** Persian tutor (see [[persian_tutor-overview]] — the design-stage planning slice). After the VPS migration on 2026-06-22, the design pivoted to **web-first**: Cameron wanted a usable thing today, glasses integration can layer on later via the same chat/feed pattern voice_interface uses.

Life_manager seeded the agent with a thorough ROLE.md scaffold; persian agent itself did the bootstrap pass (read scaffold, exercised live app, found + fixed a real cached-audio prefix bug at `app.py:77`).

## North star

An agent Cameron talks to many times per day, embedded in his life, that accelerates fluency toward:
1. Speaking with family
2. Understanding Khanega (Sufi) lectures
3. Cultural rootedness as "Persian" — the second pillar of his Jacked/Persian/Robots identity

## Coordinates with

- **glasses** (`vault/fleet/agents/glasses/`) — for future HUD integration. Reuse the chat/feed pattern in [[voice_interface-overview]], don't reinvent.
- **life_manager** — owns context like Brandon practice familiarity, identity vision; persian agent reads life KB for "what should I be drilling this week" hints
- **sufi_lectures** (`agents/sufi_lectures/`) — producer for Khanega integration (forked from life_manager 2026-07-06): lecture download + Persian ASR → transcripts at `/data/cameron/life/projects/khanega/transcripts/`. Pings my inbox per batch; persian ingests lecture phrases Cameron has actually heard into the vocab/SRS layer. It owns source material, persian owns active learning.
