This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
make dev- Start development environment (PostgreSQL, NATS)make dev-api- Run API server in development modemake dev-worker- Run worker in development modemake migrate-up- Apply database migrationsmake test- Run unit testsmake lint- Run linter (requires golangci-lint)make fmt- Format code and tidy modulesmake build- Build the binary
make test- Unit tests only (short flag)make test-integration- Integration tests (starts Docker services)make test-coverage- Generate coverage reportmake test-all- Run all tests with coveragego test ./internal/path/to/package -v- Run tests for specific packagego test ./internal/path/to/package -run TestFunctionName -v- Run specific test functiongo test ./... -timeout 10s- Run all tests with timeout (always use timeout)
make install-tools- Install goreman, migrate CLI, cobra-climake dev-down- Stop development environmentmake dev-clean- Stop and remove volumes (clean slate)make migrate-create name=<name>- Create new migration filemake build-docker- Build Docker imagesmake vet- Run go vet static analysismake psql- Connect to development PostgreSQL databasemake nats-stream-info- Show NATS JetStream informationmake nats-consumer-info- Show NATS consumer informationmake logs-api- Show API logs with JSON formattingmake logs-worker- Show worker logs with JSON formattingast-grep- Search for AST nodes in Go source code, favor this over regex for code parsing tasks
- PostgreSQL:
localhost:5432(user: dev, password: dev, db: codechunking) - NATS:
localhost:4222(client),localhost:8222(HTTP monitoring) - pgAdmin:
localhost:5050(email: admin@example.com, password: admin) - requiresdocker-compose --profile tools up
This is a production-grade code chunking and semantic search system using hexagonal architecture:
- Domain Layer (
internal/domain/): Business entities, value objects, domain services - Application Layer (
internal/application/): Command/query handlers, DTOs - Port Layer (
internal/port/): Interface definitions for inbound/outbound adapters - Adapter Layer (
internal/adapter/): Concrete implementations (API, DB, NATS, etc.)
- Language: Go 1.24 (requires CGO_ENABLED=1 for tree-sitter)
- Database: PostgreSQL with pgvector extension
- Messaging: NATS JetStream for async job processing
- Embeddings: Google Gemini API (gemini-embedding-001 model)
- CLI: Cobra framework with Viper configuration
- Code Parsing: Tree-sitter for semantic code chunking (go-sitter-forest with 300+ language parsers)
- Primary Parser Location: Uses
go-sitter-forestfor comprehensive language support - Grammar Development: Additional working directory at
/tmp/tree-parser-grammar/for custom grammars - Language Support: Includes parsers for Go, Python, JavaScript, TypeScript, and 300+ other languages
- Parser Usage: Custom parsers in
internal/adapter/outbound/treesitter/parsers/for language-specific chunking - Build Requirement: Must use
CGO_ENABLED=1for all builds due to tree-sitter C bindings
Repository: Git repository with indexing status, metadata, and file/chunk countsIndexingJob: Async job for processing repositories with retry and error handlingAlert: Error monitoring and alerting system entitiesClassifiedError: Error classification and aggregation for monitoring- Value Objects:
RepositoryURL,RepositoryStatus,JobStatus,AlertType,ErrorSeverity,Language,CloneOptions
- Configuration hierarchy: CLI flags > Environment variables > Config files > Defaults
- Environment variables use
CODECHUNK_prefix - Config files:
configs/config.yaml(base),config.dev.yaml,config.prod.yaml
- REST API on port 8080 with OpenAPI 3.0 specification
- Main endpoints:
/health,/repositories(POST),/search(POST) - Health checks and metrics endpoints available
- Background workers process indexing jobs from NATS JetStream
- Configurable concurrency (default: 5 workers)
- Jobs include: git cloning, code parsing, chunking, embedding generation
The system supports two modes for generating embeddings:
- Purpose: Fast local testing without API costs
- Configuration:
batch_processing.use_test_embeddings: true - Behavior: Generates synthetic 768-dimensional vectors locally
- Use case: Development, testing, CI/CD pipelines
- No external API calls: Completely offline
- Purpose: Efficient embedding generation at scale
- Configuration:
batch_processing.use_test_embeddings: false - Behavior: Uses Google Gemini Batches API for asynchronous processing
- Requirements:
CODECHUNK_GEMINI_API_KEYenvironment variable must be set- Batch directories must be configured in config file:
gemini: batch: enabled: true input_dir: /tmp/batch_embeddings/input output_dir: /tmp/batch_embeddings/output poll_interval: 5s max_wait_time: 30m
- Repository must have more than
threshold_chunks(default: 10)
- Automatic fallback: If batch API fails, falls back to sequential processing
Test Mode Active (logs will show):
"Processing batch embedding results (TEST MODE)"
"Using test embeddings for development"
Production Mode Active (logs will show):
"Processing batch embedding results (PRODUCTION MODE)"
"Using batch embeddings API for production"
"chunk_count": 8269
Batch Not Working (fallback to sequential):
"Production batch processing not implemented - falling back to sequential"
If you see the fallback message, check:
use_test_embeddingsis set tofalse- Batch directories are configured (
input_dir,output_dir) CODECHUNK_GEMINI_API_KEYis setgemini.batch.enabledistrue
See BATCH_JOB_STATUS.md for troubleshooting and monitoring batch jobs.
The application uses a centralized slogger package that wraps the ApplicationLogger infrastructure and ensures compliance with Go's structured logging best practices.
Location: internal/application/common/slogger/slogger.go
import "codechunking/internal/application/common/slogger"
// Simple logging with context
slogger.Info(ctx, "Repository created successfully", slogger.Fields{
"repository_id": repoID,
"url": repositoryURL,
})
// Error logging with structured fields
slogger.Error(ctx, "Failed to process repository", slogger.Fields{
"repository_id": repoID,
"error": err.Error(),
"operation": "clone_repository",
})
// Using helper functions for cleaner syntax
slogger.Info(ctx, "Processing completed",
slogger.Fields2("duration", duration, "records_processed", count))
slogger.Debug(ctx, "Detailed processing info",
slogger.Fields3("step", "validation", "items", len(items), "batch_size", batchSize))For situations where context is not available (initialization, cleanup, etc.):
// Use sparingly - only when context is truly unavailable
slogger.InfoNoCtx("Application starting", slogger.Fields{
"version": version,
"environment": env,
})When migrating existing code from global slog usage:
Before (violates sloglint):
slog.Info("Processing repository", "url", repositoryURL)
slog.Error("Database error", "error", err)After (compliant):
slogger.Info(ctx, "Processing repository", slogger.Fields{"url": repositoryURL})
slogger.Error(ctx, "Database error", slogger.Fields{"error": err})- sloglint Compliant: No more linting violations for global slog usage ~
- Context Propagation: Automatic correlation ID and request ID handling
- Structured Fields: Consistent field formatting across the application
- Thread-Safe: Global singleton with proper initialization
- Backward Compatible: Maintains existing ApplicationLogger infrastructure
- Always prefer context-aware functions (
Info,Error, etc.) over no-context versions - Use structured fields (
slogger.Fields{}) instead of key-value pairs - The slogger package automatically handles ApplicationLogger initialization
- All logging output maintains JSON format for production observability
- IMPORTANT: MUST use Test-Driven Development with specialized agents:
@agent-red-phase-tester- Write failing tests first@agent-green-phase-implementer- Make tests pass with minimal code@agent-tdd-refactor-specialist- Refactor for quality and maintainability
- Focus on Input/Output: Design tests around input/output pairs rather than mocks
- Mandatory Timeouts: Always use timeout flags to prevent hanging tests
- Example:
go test ./... -timeout 10s - Example:
go test ./internal/path/to/package -run TestFunctionName -v -timeout 30s
- Example:
- Isolation: Unit tests should be fast and isolated; use short flag (
-short) for unit tests - Coverage: Maintain high test coverage (currently 100+ passing tests across all layers)
CREATE INDEX CONCURRENTLYmust always live in its own dedicated migration file — golang-migrate runs migrations inside a transaction by default, andCONCURRENTLYcannot execute inside a transaction (it will error). Only useCONCURRENTLYwhen adding indexes to existing tables with live data; for new tables created in the same migration, non-concurrent indexes are fine (empty table = no lock contention).- Never use
ALTER SYSTEMin migrations — it writes topostgresql.confand affects all databases on the instance. It belongs in ops config, not schema migrations.
- Keep files under 500 lines (preferred), max 1000 lines for readability and parsability
- Follow hexagonal architecture patterns (domain, application, port, adapter layers)
- Use conventional commits for all commits (e.g.,
feat:,fix:,refactor:,test:)
- Metrics: Use OpenTelemetry (OTEL) for all metrics
- Logging: Use structured logging with
sloggerpackage - Tracing: Leverage correlation IDs for request tracking across components
- Wiki: Add important information to the wiki (git submodule at
./wiki/)- Configuration guides, architecture decisions, troubleshooting tips
- Wiki serves as primary documentation for developers and users
- Always usee tree sitter queries and syntax.