GAIA is a proactive personal AI assistant — full-stack Nx monorepo with a Next.js frontend, FastAPI/LangGraph backend, React Native mobile app, Electron desktop app, and Discord/Slack/Telegram bots.
mise is the task runner and tool version manager for this repo. It manages Node, Python, uv, and nx versions, and defines all development tasks.
mise tasks # List all available tasks with descriptions
mise run <task> # Run a task (e.g. mise run lint, mise run dev)
mise //apps/api:lint # Run a task in a sub-project from the rootPre-commit hooks are managed via prek (installed by mise). Install once with mise run pre-commit:install. Hooks run automatically on git commit — to run manually: mise run pre-commit.
# Install JS dependencies
pnpm install
# Sync Python dependencies
nx run api:sync
nx run voice-agent:sync
# Run apps
nx dev web # Next.js (Turbopack)
nx dev api # FastAPI (hot reload, port 8000)
nx worker api # ARQ background worker
nx dev desktop # Electron + Next.js
nx dev mobile # React Native (Expo)
nx dev voice-agent # LiveKit voice worker
# Docker (from infra/docker/)
docker compose up -d # infra only
docker compose --profile backend up -d # + API
docker compose --profile all up -d # everything
# Quality (run after changes — see After Major Changes below)
nx run-many -t lint
nx run-many -t type-check
nx run-many -t format
# Build
nx build web
nx build api
# API tests
cd apps/api && uv run pytest# Clean build artifacts
nx clean web
nx clean api
# Run multiple targets in parallel (max 3 by default)
nx run-many -t build lint type-check
# View task graph
nx graphapps/
web/ - Next.js web application
desktop/ - Electron desktop app
mobile/ - React Native mobile app
api/ - FastAPI backend with LangGraph agents
voice-agent/ - Voice processing worker
bots/
discord/ - Discord bot
slack/ - Slack bot
telegram/ - Telegram bot
docs/ - Documentation site
libs/
shared/ - Shared Python utilities (gaia-shared package)
py/ - Python shared code
ts/ - TypeScript shared code
Tech Stack: Next.js 16, React 19, TypeScript, Zustand, TailwindCSS, Biome
Key Directories:
src/app/- Next.js App Router pages (organized by route groups)src/features/- Feature modules (chat, todo, calendar, workflows, integrations, etc.)src/stores/- Zustand state management storessrc/components/- Reusable React componentssrc/lib/- Utility functions and configurationssrc/types/- TypeScript type definitions
State Management: Uses Zustand for global state. Each feature can have its own store in src/stores/ or src/features/{feature}/stores/.
Styling: TailwindCSS with custom configuration. Uses Biome for linting/formatting instead of ESLint/Prettier.
Desktop App: The Electron app uses the Next.js standalone build output to bundle the web app for desktop.
Tech Stack: FastAPI, LangGraph, Python 3.11+, PostgreSQL, MongoDB, Redis, ChromaDB, RabbitMQ
Key Directories:
app/main.py- Application entry pointapp/core/- Core application logic (app factory, middleware, lifespan)app/api/v1/- API routes and endpointsapp/agents/- LangGraph agent systemcore/- Core agent logic (agent.py, state.py, graph_manager.py, nodes/, subagents/)tools/- Agent toolsprompts/- Agent promptsmemory/- Agent memory managementllm/- LLM integrations
app/models/- Database modelsapp/schemas/- Pydantic schemasapp/services/- Business logic servicesapp/db/- Database clients (postgresql, mongodb, redis, chroma, rabbitmq)app/workers/- Background task workersapp/config/- Configuration and settingsapp/utils/- Utility functions
Database Setup: The API depends on PostgreSQL, MongoDB, Redis, ChromaDB, and RabbitMQ. Use Docker Compose for local development.
Background Tasks: Uses ARQ (Redis-based task queue) for async job processing. Run with nx worker api.
Dependency Management: Uses uv for Python package management. Run nx run api:sync to install dependencies.
Tech Stack: React Native, Expo, TypeScript
Similar structure to web app with React Native components. Uses React Navigation for routing.
Python Shared (libs/shared/): Common utilities used across Python apps (API, voice-agent, bots). Includes logging, config, and Pydantic models.
Install: The gaia-shared package is automatically available to Python apps via workspace dependencies.
The full design system is documented in DESIGN.md at the repo root. It covers:
- Color tokens, zinc scale, semantic status colors, dark/light CSS variables
- Typography (Inter, PP Editorial New, Anonymous Pro) and heading scale
- Spacing, border radius decision table, shadows
- Icon library usage (
@icons— never raw SVGs) - Animation tokens, Framer Motion conventions, easing functions
- Toast/notification system (Sileo — never sonner or react-hot-toast)
- Chat bubble architecture and the TextBubble/TOOL_RENDERERS system
- Chat tool card styling contract (outer
rounded-2xl bg-zinc-800 p-4, innerrounded-2xl bg-zinc-900 p-3, no borders) - Adding new tool cards vs OpenUI primitives (decision tree)
- Copy-paste card template and pre-commit checklist
Claude rules for design consistency are in .claude/rules/design.md (auto-loaded).
Chat bubble rules are in apps/web/src/features/chat/components/bubbles/bot/CLAUDE.md.
Visual style guide (rendered as interactive docs) is in docs/design-system.mdx — sourced from DESIGN.md.
- Package manager is pnpm — never use npm or yarn
- Biome for linting/formatting — not ESLint/Prettier
- No inline imports — all imports at the top of the file
- Never use
any— always provide proper type definitions - Before creating a new type, search
src/types/first — do not duplicate existing types - Path alias
@/maps tosrc/in web/desktop - Never use Unicode/text symbols as UI elements — no
→,↗,←,↑,↓,•,✓,×, or any other Unicode symbol characters in rendered JSX. Always use icon components from@iconsinstead. This applies everywhere: demo components, cards, labels, badges, list items.
- No inline imports — all imports at the top of the file
- Full type annotations required on all functions and methods (enforced by mypy)
- Ruff for linting/formatting — not black/flake8/isort
Rules are also enforced via auto-loaded rule files — see .claude/rules/:
- TypeScript/React:
.claude/rules/typescript.md— Biome, strict types, component/hook patterns, Zustand, API layer - Python/Backend:
.claude/rules/python.md— Ruff, mypy, FastAPI patterns, services, logging, caching - Design system:
.claude/rules/design.md— card contract, colors, icons, animations, OpenUI - General engineering:
.claude/rules/general.md— DRY, dead code, constants, feature-based org - SEO:
.claude/rules/seo.md— page title template, no redundant brand suffix, description length - Linear:
.claude/rules/linear.md— issue titles, descriptions, priorities, cycle hygiene, writing style
Never duplicate logic across the monorepo. Before writing new code, search for existing utilities, types, hooks, or services that already solve the problem.
- Shared Python logic belongs in
libs/shared/py/— import it inapps/api,apps/voice-agent, andapps/botsvia thegaia-sharedpackage. - Shared TypeScript logic belongs in
libs/shared/ts/— consumed as@gaia/sharedworkspace package. - Shared React/RN components or hooks that are used across
web,desktop, andmobileshould live inlibs/shared/ts/src/or a dedicated lib, not duplicated in each app. - When extracting shared code, update all call sites — do not leave dead duplicates behind.
- If you find duplicated logic while working, flag it and consolidate it before adding more.
After every refactor or change, clean up before considering work complete.
- Remove unused imports, variables, functions, types, and files — do not leave them commented out or with
_prefixes - When moving logic to shared libs, delete the original copies from all previous locations
- When replacing an implementation, remove the old one entirely — do not keep it "just in case"
- When renaming or restructuring, hunt down all references and update or remove them
- If unsure whether something is still used, grep for it — do not assume it's dead or alive
Always spawn subagents wherever possible — for research, exploration, or independent tasks, use the Agent tool with specialized subagents in parallel. Don't do sequentially what can be done concurrently.
When investigating a bug, feature, or unfamiliar area of the codebase:
- Never assume the root cause — trace the actual code path. Read the relevant files, follow imports, and verify your hypothesis before proposing a fix.
- Explore deeply — use the
Exploresubagent for broad codebase discovery. For complex multi-file investigations, spawn multiple subagents to explore different layers in parallel. - Explore the intricacies — check edge cases, related config, middleware, environment variables, and cross-app interactions. Do not stop at the surface.
- Use relevant skills — before starting any significant task, check if a skill applies (
writing-plans,accurate-testing,logging-best-practices,copywriting, etc.) and invoke it via theSkilltool.
Always create todos for multi-step work — use TaskCreate at the start of any non-trivial task. Update status (in_progress → completed) as you go. Never leave tasks stale.
- Plans must go in
.agents/plans/— never create plan files anywhere else. This directory is gitignored. - Plans must be comprehensive — include architecture decisions, step-by-step implementation, edge cases, and rollback considerations before writing any code.
- Use the
writing-plansskill before starting any significant implementation.
Do NOT create test cases unless explicitly asked. Do not add tests when fixing bugs or adding features unless the user specifically requests it.
Always run type-check and lint for every affected layer before considering work complete:
# Backend
nx type-check api
nx lint api
# Frontend
nx run-many -t type-check --projects=web,desktop
nx run-many -t lint --projects=web,desktopEach app has its own .env file:
apps/api/.env- Backend configurationapps/web/.env.local- Web app configuration
Refer to .env.example files in each directory for required variables.
Dockerfiles are located in each app directory. Docker Compose configuration is in infra/docker/:
docker-compose.yml- Development environmentdocker-compose.prod.yml- Production environment
The project uses Nx release with Docker support. Release groups are configured in nx.json:
- apps group:
api,voice-agent(published to ghcr.io)
Build Docker images:
nx docker:build api
nx docker:build voice-agentOnly use the bd CLI when the user explicitly asks for it. bd is a project-internal CLI for task tracking and dolt database sync — never invoke it automatically. Otherwise, use built-in TodoWrite/TaskCreate tools.
When creating implementation plans, store them in .agents/plans/ directory. This folder is gitignored and used for planning documents before execution.
Never create .md files outside of .agents/plans/ (gitignored) unless explicitly asked. Do not create REVIEW.md, CONSISTENCY_REPORT.md, ANALYSIS.md, spec files, or any other agent-generated documentation in the source tree. Planning and review artifacts belong only in .agents/plans/ and only when absolutely necessary.
- Never add Claude as a co-author in commits. Do not include
Co-Authored-By: Claudeor any similar line in commit messages. developis the base branch, notmaster. All feature branches are created from and merged intodevelop. When comparing branches, analyzing diffs, or creating PRs, always usedevelopas the base — notmasterormain.- NEVER merge pull requests. Do not run
gh pr merge, do not call any GitHub API merge endpoint, and do not take any action that merges a PR into any branch. PRs are merged by the team — not by Claude. This is an absolute rule with no exceptions. - Work is not complete until
git pushsucceeds. Always push before ending a session. - Session close sequence (mandatory when code changed):
git pull --rebase git push git status # must show "up to date with origin"
Always use non-interactive flags to avoid hanging on prompts (shell aliases may add -i by default):
cp -f source dest # NOT: cp source dest
mv -f source dest # NOT: mv source dest
rm -f file # NOT: rm file
rm -rf directory # NOT: rm -r directory- Python deps not resolving →
nx run api:syncornx run voice-agent:sync - Nx daemon issues → daemon is disabled (
useDaemonProcess: falseinnx.json) - Web app uses
output: "standalone"— required for Electron bundling, do not remove - Console logs are stripped in production builds (except
console.error)