The /chat detail (ChatDetailPanel) now passes context 'chat' to usePiChat, so the
backend actually runs the session from claude_sessions (the earlier tag was on the
wrong component). The left panel (SessionList) now reads GET /chat/sessions —
Claude's own transcripts — instead of the old saved-sessions model. List-only:
rows display title/time/count; click-to-resume comes next.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The standalone /chat route now tags its context as 'chat'; the backend runs those
sessions with cwd = DATA_PATH/<email>/claude_sessions (created on demand), so their
transcripts form an isolated Claude project group instead of polluting the home-dir
history. Other chat contexts (email/project panels) keep their own cwd.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First slice of making Claude's session store the source of truth. Adds a reader
(api/chat/claude-sessions.ts) that lists sessions straight from Claude's JSONL
transcripts under $HOME/.claude/projects/<cwd-slug>/, plus GET /chat/sessions
over a dedicated per-user claude_sessions working directory. No bookkeeping
layer — Claude's files are authoritative. Verified against real transcripts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 1 of removing Pi (Claude-only). Cuts the non-Claude branches in the chat
WS handler, pipeline executor, and channel send-and-await; deletes the Pi
sidecar, its ecosystem entry, pi-bridge, and the Pi model-listing spawn (now a
static Claude tier list). Adds a guard coercing any legacy non-claude-code model
preference to the Claude default so old settings don't break chat or jobs.
Removes the dead no-op session-save REST route and stale Pi docs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The API and email sidecar both open emails.db; without a busy timeout a write
overlap (resync, or the thread_id backfill) throws "database is locked" and
500s a request. Wait up to 5s for the other writer instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hybrid grouping via a new thread_id column: new mail threads exactly on
References/In-Reply-To (id is sha1(Message-Id), so a referenced id hashes to
the ancestor's own id); already-synced mail is backfilled with a
normalized-subject + counterpart key. Folder views collapse to one row per
thread with a count badge; the reader shows the thread as a collapsible stack.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
exposes the duress lockdown as an endpoint (needs the distress password in the
body, rate-limited) so it can be tripped from a shortcut/webhook, not only by
typing the distress password at the login form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a duress password (DISTRESS_PASSWORD env): entering it at login trips an
in-memory full lockdown — all new logins (password + passkey) and every existing
session are refused until the server is restarted, and the login itself returns a
normal "invalid credentials" so it gives nothing away. Also add
POST /api/auth/blacklist-token as a clearly-named alias for revoking the current
JWT (same effect as signout).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>