Project-specific instructions for Claude Code.
TypeScript monorepo with Bun workspaces and Turborepo:
apps/bot/— Slack bot + agent runtime (main entry point)apps/web/— Admin dashboard (Phase 7, React + Vite)packages/db/— PostgreSQL schema with Prisma ORMpackages/shared/— Shared types, config (zod), logger (pino), errorspackages/tools/— Tool registry + executorspackages/integrations/— External service clients (GitHub, Linear, etc.)
# Install
bun install
# Development
bun run dev # Start all dev servers
bun run --filter @openviktor/bot dev # Start bot only
# Database
bun run db:generate # Regenerate Prisma client
bun run db:migrate # Run migrations (dev)
bun run --filter @openviktor/db db:migrate:deploy # Run migrations (prod)
bun run --filter @openviktor/db db:studio # Database GUI
# Quality
bun run lint # Biome check
bun run lint:fix # Biome auto-fix
bun run typecheck # TypeScript strict check
bun run test # Run all tests
bun run test:coverage # Tests with coverage
# Infrastructure
docker compose -f docker/docker-compose.yml up -d # Start PostgreSQL + Redis
docker compose -f docker/docker-compose.yml down # Stop infrastructureAfter modifying packages/db/prisma/schema.prisma:
- Regenerate Prisma client:
bun run db:generate - Create migration:
cd packages/db && bunx prisma migrate dev --name describe-change - Run type check:
bun run typecheck
- Follow clean code principles: no unnecessary comments
- Only write doc-strings for public APIs, exported functions, and non-obvious interfaces
- Do not add inline comments explaining what the code does
- TypeScript strict mode is enforced
- Biome handles formatting and linting
- PostgreSQL 16 with Prisma ORM
- Schema:
packages/db/prisma/schema.prisma - Migrations:
packages/db/prisma/migrations/ - Uses
prisma migrate deployin Docker (notdb push)
We use Linear for issue tracking (OpenViktor project). Follow this workflow:
- Find existing issue or create a new one in the OpenViktor project
- Move the issue to "In Progress"
- Read relevant files until you understand the issue
- Understand the current implementation
- Ask 5-10 questions about scope, expected behavior, edge cases
- Add a comment with the full Q&A
- Plan the implementation: files to touch, schema changes, pitfalls
- Post as a Linear comment with
#SPECIFICATIONheader
- Ask: "Ready to start implementation? Clear context first if needed"
- Create branch (use Linear's suggested branch name)
- Implement according to specification
- Write tests alongside code — never leave tests for later
Before marking a Linear issue as done or creating a PR, you MUST complete ALL of these:
- Tests pass:
bun run test— all existing and new tests green - Lint passes:
bun run lint - Typecheck passes:
bun run typecheck - Test coverage: new code has meaningful test coverage (unit tests co-located, integration tests in
__tests__/) - Docs updated: if the feature is user-facing or changes setup/config:
- Update
README.md(phase table status, new sections if needed) - Update
docs/self-hosting.mdif deployment steps changed - Update
.env.exampleif new environment variables were added
- Update
- Viktor cross-validation: checked relevant
docs/viktor-reference/docs - Create pull request and link to Linear issue
Every implementation change must be cross-validated against our reverse-engineering knowledge in docs/viktor-reference/. Before implementing any feature:
- Check relevant reference docs (e.g.,
thread-orchestrator.mdfor thread handling,tool-gateway.mdfor tool execution) - Ensure behavior matches Viktor's known patterns — deviations must be intentional and documented
- Key reference files:
architecture.md— Overall system design and subsystem interactionsconversational-style.md— Tone, formatting, response patternsthread-orchestrator.md— Thread lifecycle, concurrency (16 thread limit)tool-gateway.md— Tool execution, timeouts (600s tool, 120s bash)heartbeat.md— Proactive check-in system (4x/day)memory.md— Knowledge persistence and retrievalskill-routing.md— How Viktor routes to capabilitiescost-control.md— Token budgets and tier system
- Slack connection via Socket Mode (no public URL needed)
- LLM calls through provider abstraction (
apps/bot/src/agent/llm.ts) - All agent work tracked as
AgentRunrows in PostgreSQL - Structured logging with pino (JSON in production, pretty in dev)
- Environment config validated with zod at startup