This document provides technical details for developers contributing to Claude Code Viewer.
- Framework: Vite + TanStack Router
- UI Libraries: React 19, Radix UI, Tailwind CSS
- State Management: Jotai (global state), TanStack Query (server state)
- API Framework: Hono (standalone server with @hono/node-server)
- Type-safe communication via Hono RPC
- Validation using
@hono/zod-validator
- Effect-TS: All backend business logic is implemented using Effect-TS
- Service layer managed through Effect Context (dependency injection container)
- Controller → Service layered architecture, with each layer implemented in Effect
- Type-safe error handling and side effect control
- Abstracts Node.js built-ins (
FileSystem.FileSystem,Path.Path,Command.string) for testability
- Single Source of Truth (SSoT): Claude Code's standard session logs (
~/.claude/projects/)- No separate database; reads directly from JSONL files
- Strict validation via Zod schemas ensures conversation data integrity
- Caching Mechanism: For performance optimization, metadata is cached in
~/.claude-code-viewer/- Frequently accessed data like session lists and project information
- Cache is automatically invalidated via SSE events
- Server-Sent Events (SSE): Provides
/api/sseendpoint (src/server/hono/route.ts:430-444)- Clients maintain persistent SSE connections to listen for server events
- Real-time delivery of session log updates, process state changes, etc.
- Type-safe SSE events (
TypeSafeSSEservice) guarantee payload types for each event kind viaSSEEventDeclaration - Event types: connect, heartbeat, sessionListChanged, sessionChanged, sessionProcessChanged, permissionRequested
SSEControllersubscribes to EventBus and broadcasts typed events usingTypeSafeSSE.writeSSE()- Client-side easily subscribes to events using the
useServerEventListenerhook
Claude Code Viewer provides advanced control over Claude Code session processes:
- After starting a session, the process remains in the background unless explicitly aborted
- Paused sessions can continue without changing the session-id (no resume needed)
- Memory sharing between processes is required, making production build verification crucial
- Node.js: Version 20.19.0 or later (see .node-version)
- Package Manager: pnpm 10.8.1 or later
# Install dependencies
pnpm installpnpm devThis command starts both servers in parallel using npm-run-all2:
- Frontend: Vite development server (port 3400 by default, configurable via
DEV_FE_PORT) - Backend: Node server with tsx watch (port 3401 by default, configurable via
DEV_BE_PORT)
Frontend proxy configuration forwards /api requests to the backend server.
Build and run in production mode:
# Build
pnpm build
# Start production server
pnpm startBuild Process (./scripts/build.sh):
- Clean
dist/directory - Compile i18n files (
lingui:compile) - Build frontend with Vite →
dist/static/ - Bundle backend with esbuild →
dist/main.js(ESM format, external dependencies excluded)
Build Output Structure:
dist/
├── main.js # Backend server bundle + CLI entry point
├── main.js.map # Source map
└── static/ # Frontend static files (Vite output)
├── index.html
└── assets/
The production server serves static files and handles API requests on a single port (3000 by default, configurable via PORT). The dist/main.js is registered as the CLI binary in package.json's bin field.
Biome is used as the formatter and linter.
Commands:
# Auto-fix issues (format + lint with unsafe fixes)
pnpm fix
# Check only (format + lint check, run in CI)
pnpm lintConfiguration: /biome.json
- Recommended rules enabled
noProcessEnvset to error level- e2e and config files excluded from checks
CI Requirement: Passing Biome checks is mandatory for PR merges.
Vitest-based tests are written for backend core logic (Effect-TS based service layer).
Commands:
# Run once
pnpm test
# Watch mode
pnpm test:watchConfiguration:
- Global mode enabled
- Setup file:
src/testing/setup/vitest.setup.ts
Test Coverage: Primarily business logic under src/server/core/
CI Requirement: All tests must pass for PR merges.
pnpm typecheckStrict type configuration (@tsconfig/strictest) is adopted, emphasizing type safety.
Playwright-based snapshot capture is implemented to visually confirm UI changes.
Note: This is Visual Regression Testing (VRT) for confirming UI changes, not traditional E2E testing.
Implementation: Custom TypeScript script (not standard Playwright config file)
# Run server startup and snapshot capture together
pnpm e2e
# Or execute manually
pnpm e2e:start-server # Start server
pnpm e2e:capture-snapshots # Capture snapshotsImportant: In local environments, UI varies based on the current path. Do not commit locally captured snapshots.
When the vrt label is added to a PR, the VRT workflow (.github/workflows/vrt.yml) automatically captures and commits snapshots. Use this label for PRs with UI changes to update snapshots.
src/
├── routes/ # TanStack Router routes
│ ├── __root.tsx # Root route with providers
│ ├── index.tsx # Home route
│ └── projects/ # Project-related routes
├── app/ # Shared components and hooks (legacy directory name)
│ ├── components/ # Shared components
│ ├── hooks/ # Custom hooks
│ └── projects/ # Project-related page components
├── components/ # UI components library
│ └── ui/ # shadcn/ui components
├── lib/ # Frontend common logic
│ ├── api/ # API client (Hono RPC)
│ ├── sse/ # SSE connection management
│ └── conversation-schema/ # Zod schemas for conversation logs
├── server/ # Backend implementation
│ ├── core/ # Core domain logic (Effect-TS)
│ │ ├── claude-code/ # Claude Code integration
│ │ ├── events/ # SSE event management
│ │ ├── session/ # Session management
│ │ └── ...
│ ├── hono/ # Hono application
│ │ ├── app.ts # Hono app instance
│ │ └── route.ts # API routes definition
│ ├── lib/ # Backend common utilities
│ └── main.ts # Server entry point
└── testing/ # Test helpers and mocks
- Learning Effect-TS: The backend is built with Effect-TS. Refer to the official documentation
- Debugging SSE: Check the Network tab in browser developer tools to inspect SSE connections
- Log Inspection: Directly reference JSONL files under
~/.claude/projects/to understand data structures - Mock Data: Mock data for E2E tests in
mock-global-claude-dir/is useful for development reference
We welcome contributions! Please:
- Fork the repository
- Create a feature branch
- Make your changes with appropriate tests
- Ensure all quality checks pass (
pnpm lint,pnpm test,pnpm typecheck) - Submit a pull request with a clear description of your changes
For UI changes, add the vrt label to your PR to update visual snapshots.