5.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
ajet-chat is a Clojure monorepo for a team messaging platform (Slack-like). Early stage — module skeletons exist but most code is stubbed out.
Repository Structure
Monorepo with :local/root deps linking modules:
- shared/ — Common DB layer (next.jdbc + HoneySQL), EventBus (NATS via jnats), API client SDK, schemas, protocols
- auth-gw/ — Auth gateway: http-kit edge proxy, session/token validation, routing (has PG access)
- api/ — Stateless REST API: all data reads/writes to PG, publishes events to NATS
- web-sm/ — Web session manager: Hiccup + Datastar SSE for browsers (NATS + API, no PG)
- tui-sm/ — TUI session manager: SSE for terminal clients (NATS + API, no PG)
- cli/ — Terminal client: CLI (one-shot) + TUI (interactive via clojure-tui)
- mobile/ — Mobile client (deferred, placeholder only)
Dependency matrix:
PG NATS API(HTTP)
API yes pub —
Auth GW yes — —
Web SM — sub yes (internal)
TUI SM — sub yes (internal)
CLI — — yes (external, via Auth GW)
Common Commands
Task Runner (Babashka)
Preferred way to run tasks — bb wraps clj commands and manages Docker infra automatically.
bb tasks # List all available tasks
# Development
bb dev # Start dev infra + nREPL (all modules)
bb infra:dev # Start dev Docker infra only
bb infra:dev:stop # Stop dev Docker infra
# Testing
bb test # All tests (starts test infra)
bb test:unit # Unit tests only (no Docker needed)
bb test:integration # Integration tests (starts test infra)
bb test:e2e # E2E tests (starts test infra)
# Per-module testing
bb test:shared # All shared tests
bb test:shared:unit # Shared unit tests only
bb test:api # All API tests
bb test:api:unit # API unit tests only
bb test:auth-gw # All auth-gw tests
# Per-module bb.edn (from module directory)
cd shared && bb test:unit # Delegates to root bb.edn
# Build & Deploy
bb build api # Build uberjar for a module
bb clean api # Clean module artifacts (or bb clean for all)
bb prod # Start production stack (docker compose)
bb prod:stop # Stop production stack
bb prod:logs # Tail production logs
# Database
bb db:reset-test # Drop & recreate test DB schema
Running Services (REPL-driven)
# Via bb (recommended)
bb dev # nREPL with all modules + dev infra
# Via clj directly
clj -A:dev:api:web-sm:tui-sm:auth-gw # Single REPL with all modules
clj -M:dev:api # Individual service REPL
Services expose (start!) / (stop!) / (reset!) in their REPL namespaces.
Testing (Kaocha)
# Via bb (recommended — manages Docker infra automatically)
bb test:unit # Unit tests — no Docker needed
bb test:integration # Integration — starts Docker automatically
bb test # All tiers
# Via clj directly (legacy — requires manual Docker management)
clj -M:test/base:test/unit # Unit tests
clj -M:test/base:test/integration # Integration tests
clj -M:test -m kaocha.runner # All tests (using unified :test alias)
Docker infra for integration tests: docker compose -f docker-compose.test.yml up -d
Architecture Diagram
typst compile architecture.typst architecture.png
Architecture
Request flow: Internet → nginx (TLS, prod only) → Auth Gateway → service (API / Web SM / TUI SM)
Key pattern — data vs events separation:
- All persistent data reads/writes go through the API (stateless REST, only service with PG access besides Auth GW)
- Real-time events flow via NATS pub/sub (community-scoped subjects)
- Session managers hold live client connections, subscribe to NATS for events, fetch full data from API via HTTP. No direct PG connection.
- SMs publish ephemeral events (typing indicators) directly to NATS — bypasses API for latency
Auth Gateway is a Clojure http-kit proxy that does its own DB reads/writes for session validation, then routes authenticated requests to internal services.
Tech Stack
- All server modules: Clojure 1.12, http-kit 2.8, reitit 0.7, Ring 1.13
- Data: PostgreSQL (next.jdbc + HoneySQL) — API + Auth GW only
- Events: NATS (io.nats/jnats) — API publishes, SMs subscribe
- Web: Hiccup 2.0 + Datastar SDK (web-sm)
- CLI: shared API client SDK (babashka http-client) + clojure-tui (local dep at
../../clojure-tui) - Files: MinIO (S3-compatible)
Conventions
- PostgreSQL everywhere — same DB in dev and prod, no SQLite. Dev infra runs in Docker.
- HoneySQL maps for all queries — avoid raw SQL strings
- Migratus for schema migrations
- NATS for all event pub/sub — community-scoped subjects (
chat.events.{community-id}), DM subjects (chat.dm.{channel-id}) - MinIO (S3-compatible) for file storage — same API as AWS S3
- UUIDs for all entity IDs (
java.util.UUID/randomUUID) - EventBus protocol:
publish!,subscribe!,unsubscribe!— backed by NATS - SSE for all server→client streaming (web + TUI), HTTP POSTs for client→server signals
Namespace Conventions
ajet.chat.shared.* — shared/src/
ajet.chat.api.* — api/src/
ajet.chat.web.* — web-sm/src/
ajet.chat.tui-sm.* — tui-sm/src/
ajet.chat.auth-gw.* — auth-gw/src/
ajet.chat.cli.* — cli/src/