Skip to content

Latest commit

 

History

History
118 lines (97 loc) · 7.19 KB

File metadata and controls

118 lines (97 loc) · 7.19 KB

CLAUDE.md — vibe-replay

What is this

vibe-replay turns AI coding sessions into animated, interactive web replays as self-contained HTML files. Supports Claude Code, Cursor, and Codex.

pnpm monorepo: packages/cli (npm: vibe-replay), packages/viewer (React → single HTML), packages/types (shared types), website/ (Astro), cloudflare/ (Workers API).

Commands

pnpm install               # Install deps
pnpm build                 # Full build: viewer → cli
pnpm start                 # Build + run interactive picker
pnpm dev                   # Viewer (Vite HMR) + CLI (tsx watch) together
pnpm dev:dashboard         # Dev mode with dashboard flag (-d)
pnpm dev:website           # Website (Astro HMR) + Viewer (Vite HMR) together
pnpm test                  # Run unit tests
pnpm test:e2e              # Run E2E tests (requires pnpm build first)
pnpm lint                  # Lint + format (auto-fix)
pnpm lint:check            # Lint check (no fix, for CI)

When to use which:

  • pnpm start — validate full user flow (build + run)
  • pnpm dev — daily iteration with full HMR: viewer auto-reloads via Vite, CLI auto-restarts via tsx watch
  • pnpm dev:website — website + viewer iteration: Astro HMR + /view/ redirects to Vite viewer

Database (D1 + Drizzle)

Schema is managed by Drizzle ORM — single source of truth in cloudflare/src/db/schema.ts.

When you change the schema:

cd cloudflare
pnpm db:generate          # Drizzle reads schema.ts, generates SQL migration in drizzle/
pnpm db:migrate:local     # Apply to local D1
pnpm db:migrate:remote    # Apply to production D1 (requires auth)
  • All tables (replays + Better Auth auth tables) are defined in cloudflare/src/db/schema.ts
  • Migration files live in cloudflare/drizzle/ — commit them to git
  • Never hand-edit migration files — always use drizzle-kit generate
  • schema.sql is kept as a reference but migrations are the source of truth
  • Better Auth uses drizzleAdapter — it reads/writes auth tables through the same Drizzle instance

Gotchas

  • </ escaping: JSON in <script> tags MUST escape </ as <\/ — browsers close the tag otherwise (see generator.ts)
  • lastIndexOf("</head>"): Use lastIndexOf, not indexOf — minified JS in the viewer bundle may contain the string </head>
  • Shared types: Scene, Annotation, DataSourceInfo, ReplaySession live in packages/types (@vibe-replay/types). CLI and viewer re-export from there. Provider-specific and viewer-specific types remain in their respective packages.
  • Viewer size limit: Keep under 800KB after build. This is why we use marked instead of react-markdown. Watch for size regressions when adding features.
  • Self-contained HTML: Output must make zero external requests. Everything inlined.
  • Multi-file sessions: Claude Code /resume creates new JSONL files. Parser accepts string | string[] and merges by slug+project.
  • Cursor tri-source: Sessions come from SQLite store.db (primary), globalStorage/state.vscdb, or JSONL (fallback). Discovery merges all sources. DB data is source of truth; JSONL supplements missing thinking/images.
  • Cursor SDK: SDK agents (TypeScript @cursor/sdk) write to ~/.cursor/projects/<workspace>/sdk-agent-store/<projectHash>/index.db (tables: agents, runs, run_events) and a parallel JSONL transcript at agent-transcripts/<agentId>/<agentId>.jsonl. The transcript is the source of user prompts (SDK doesn't store them in events) and the SDK index.db supplies tool results, structured per-run timing, and per-turn model. See providers/cursor/sdk-reader.ts. Detection is by sessionId prefix agent- — IDE chat sessions (UUID-only) skip the SDK SQLite probe.
  • Skip progress lines: These are subagent streaming artifacts in JSONL.
  • sql.js (WASM): Used instead of native SQLite bindings for portability — no C++ compiler needed.
  • Session discovery cache: CLI picker + local dashboard use file cache at ~/.vibe-replay/cache/*.json (stale-while-refresh UX). Cache validity is tied to CLI release version (CLI_VERSION) plus envelope version, so caches auto-invalidate across releases. Keep cache writes best-effort and never block generation/parsing on cache failures.

Rules

  • Always use pnpm — never npm/yarn
  • TypeScript strict mode, ESM throughout
  • oxlint for linting, oxfmt for formatting — both run automatically via PostToolUse hook and pre-commit hook
  • Before commit: run pnpm lint:check and fix any errors. Do NOT commit code that fails lint.
  • Before commit: security review — check for leaked secrets, API keys, tokens, credentials, .env files
  • Never bump versions or publish without explicit user confirmation
  • After changes: update CLAUDE.md / README.md / CONTRIBUTING.md if anything becomes outdated
  • Viewer changespnpm build (rebuilds both packages)
  • CLI-only changespnpm --filter vibe-replay build
  • Shared types changes → edit packages/types/src/index.ts, both CLI and viewer pick them up automatically
  • Test with both small (~30 scenes) and large (~500 scenes) sessions
  • Test modification policy — see packages/cli/test/README.md before changing any test

Release checklist (important)

When creating a release for npm/GitHub, do this in order:

  1. Confirm with user first (no autonomous publish/version bump).
  2. Bump packages/cli/package.json version to the target release version.
  3. Build CLI: pnpm --filter vibe-replay build.
  4. Verify displayed CLI version matches package version:
    • node packages/cli/dist/index.js --version
    • Note: startup banner vX.Y.Z comes from packages/cli/src/version.ts reading packages/cli/package.json.
  5. Only then create tag/release/publish for that same version.

If tag/release is updated but packages/cli/package.json is not, CLI will still show the old version.

Key files

What Where
CLI entry packages/cli/src/index.ts
Shared types packages/types/src/index.ts
CLI types packages/cli/src/types.ts
Transform (turns → scenes) packages/cli/src/transform.ts
HTML generation packages/cli/src/generator.ts
Editor server packages/cli/src/server.ts
Provider interface packages/cli/src/providers/types.ts
Cursor SDK reader packages/cli/src/providers/cursor/sdk-reader.ts
Viewer entry packages/viewer/src/App.tsx
Playback engine (pure) packages/viewer/src/engine/
Playback hook packages/viewer/src/hooks/usePlayback.ts
Session loading packages/viewer/src/hooks/useSessionLoader.ts
View preferences packages/viewer/src/hooks/useViewPrefs.ts
DB schema (all tables) cloudflare/src/db/schema.ts
Auth config cloudflare/src/auth.ts
Worker (Hono routes) cloudflare/src/worker.ts
Drizzle config cloudflare/drizzle.config.ts
Drizzle migrations cloudflare/drizzle/
E2E test helpers e2e/helpers.ts
E2E: generated HTML e2e/generated-html.test.ts
E2E: editor server e2e/editor-server.test.ts
E2E: CLI smoke e2e/cli-smoke.test.ts
E2E: auth worker e2e/auth-worker.test.ts

See CONTRIBUTING.md for full architecture details.