Skip to content

feat: auto-name claude sessions with haiku titler#5

Merged
github-actions[bot] merged 3 commits into
mainfrom
feat/auto-naming
Apr 23, 2026
Merged

feat: auto-name claude sessions with haiku titler#5
github-actions[bot] merged 3 commits into
mainfrom
feat/auto-naming

Conversation

@4Gaige
Copy link
Copy Markdown
Owner

@4Gaige 4Gaige commented Apr 23, 2026

Summary

  • Haiku-backed auto-namer for Claude sessions (Phase 3). Watches ~/.claude/projects/**/*.jsonl, waits 60 s of idle per file, asks Haiku for a 3-5 word title, stores in the existing session_names.custom_name column.
  • Backfills untitled sessions on boot.
  • Sidebar renders the .shimmer Midnight utility on the title while pendingTitle is true (aria-busy for screen readers).

Changes

  • server/services/session-titler.js — new worker: chokidar watcher + serial queue + debounced Haiku call. Prefers the direct @anthropic-ai/sdk when an ANTHROPIC_API_KEY is available (env or ~/.claude/settings.json), falls back to @anthropic-ai/claude-agent-sdk's query() for OAuth-only boots. If both paths fail, skips saving so pending state resumes later.
  • server/services/title-prompt.js — prompt template (adapted from open-webui) plus extractFirstUserTexts and normalizeTitle helpers that mirror the system-message filter in projects.js.
  • server/index.js — single import './services/session-titler.js'; line, self-starts on import. No other edits.
  • server/database/db.jsapplyCustomSessionNames now tags Claude sessions with pendingTitle (true when no custom row, false when resolved).
  • src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx — adds the shimmer class + aria-busy when session.pendingTitle === true (mobile + desktop paths).
  • src/types/app.ts — add pendingTitle?: boolean to ProjectSession.

Acceptance criteria (phase-3 brief)

  • Server restart backfills titles for existing sessions (scan + enqueue)
  • New JSONL → 60 s idle → titled via Haiku
  • Sidebar shows shimmer while pending, resolves live (via existing projects watcher, triggered by trailing-newline append)
  • No edits to server/projects.js or SidebarProjectItem.tsx; single import line in server/index.js
  • npm run build succeeds
  • No raw Tailwind colors in new code; .shimmer utility comes from midnight.css
  • Graceful degradation when no auth is reachable — nothing is saved, sessions stay pending

Test results

  • npm run build — pass (client + server)
  • npm run typecheck — pass
  • npm run lint — pass on changed files (pre-existing warnings only)
  • Unit check on normalizeTitle / extractFirstUserTexts — all assertions pass
  • Smoke test: module loads, self-starts, backfill scan enqueues 75 untitled sessions on this workstation without crashing; clean shutdown via stop()
  • Fresh-eyes Opus review — ALL CHECKS PASS (1 findings round, fixed in daac4fb)

🤖 Generated with Claude Code

4Gaige and others added 3 commits April 23, 2026 06:32
Adds `server/services/session-titler.js` and `server/services/title-prompt.js`.
The titler watches `~/.claude/projects/**/*.jsonl`, waits for 60s of idle per
file, reads the first two non-system user messages, and asks Haiku for a 3-5
word title stored in the existing `session_names.custom_name` column.

On boot it backfills any JSONL that has no custom name. Writes trigger the
existing projects watcher via a blank-line append, so the sidebar updates live
without touching server/index.js beyond a future single import line.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- server/index.js: single-line import of session-titler service so it
  self-starts at boot (matches the "no other edits" rule for churn files).
- server/database/db.js: applyCustomSessionNames now marks Claude sessions
  without a custom_name with pendingTitle=true so the UI can flag them.
- server/services/session-titler.js: prefer @anthropic-ai/sdk directly when
  an ANTHROPIC_API_KEY is available (env or settings.json); fall back to the
  Claude Agent SDK's query() for OAuth-only environments.
- SidebarSessionItem.tsx: render the session name with the `.shimmer`
  Midnight utility class while pendingTitle is true; aria-busy for SR.
- types/app.ts: add optional pendingTitle?: boolean to ProjectSession.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When both the direct Anthropic SDK and the Claude Agent SDK fail to produce
a result (no key, offline, rate limited, ...), treat the title as unresolved
and leave `pendingTitle=true` so the next boot or network recovery picks the
session back up. Previously we wrote 'Untitled' which poisoned the cache.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions github-actions Bot merged commit 5fee0cb into main Apr 23, 2026
2 checks passed
@4Gaige 4Gaige mentioned this pull request Apr 23, 2026
17 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant