Development Guide
Complete developer documentation for contributing to Agor.
Quick Setup
Docker Compose (Recommended)
Fastest way to start developing:
git clone https://github.com/preset-io/agor
cd agor
docker compose up
# Visit http://localhost:5173 → Login: admin@agor.live / adminPros:
- ✅ No Node.js/pnpm installation required
- ✅ Consistent environment across team
- ✅ Easy to run multiple instances on different branches
- ✅ Supports both SQLite (default) and PostgreSQL databases
Cons:
- ❌ Docker-in-docker complexity if your worktree environments use Docker (e.g.,
docker compose upin environment configs)
Database Modes
Agor supports both SQLite (default) and PostgreSQL databases in Docker.
SQLite mode (default):
docker compose up
# Uses SQLite database at ~/.agor/agor.db (inside container)
# Perfect for single-user developmentPostgreSQL mode:
# Single command - auto-starts postgres container
docker compose --env-file .env.postgres up
# Alternative: Copy env file for simpler workflow
cp .env.postgres .env
docker compose up # Now defaults to PostgreSQL
# Switch back to SQLite
rm .env
docker compose upWhat happens in PostgreSQL mode:
- Postgres container starts automatically (via
COMPOSE_PROFILES=postgresin.env.postgres) - Agor connects to
postgresql://agor:agor_dev_secret@postgres:5432/agor - Database runs in a Docker volume (persisted across restarts)
- Great for testing multi-user scenarios or production-like setups
Check which database you’re using:
Open Settings → About tab (admin only) to see:
- 💾 SQLite - Shows database file path
- 🐘 PostgreSQL - Shows connection URL (password masked)
Git Commits in Docker:
When using Docker, pnpm install installs Linux binaries (e.g., turbo-linux-arm64, eslint-linux), which won’t run on your host OS. If you commit from your host machine, pre-commit hooks will fail because Husky tries to execute these Linux binaries.
Two solutions:
-
Commit inside the container (Recommended)
docker compose exec agor-dev git add . docker compose exec agor-dev git commit -m "your message"Hooks run inside the container with correct Linux binaries.
-
Reinstall node_modules on host
pnpm install # Get host-specific binaries (macOS/Windows) git commit -m "your message" # Hooks use host binariesNote: This means you’ll have both host and Linux binaries in node_modules.
Running multiple instances in parallel:
If you’re developing across multiple branches, run each with unique ports:
# Main branch
cd ~/code/agor
docker compose up # :3030 (daemon), :5173 (UI)
# Feature branch 1
cd ~/code/agor-feature-auth
PORT=4030 VITE_PORT=5174 docker compose -p agor-feature-auth up
# Feature branch 2
cd ~/code/agor-feature-payments
PORT=5030 VITE_PORT=5175 docker compose -p agor-feature-payments upThe -p flag ensures isolated volumes and no container naming conflicts.
Local Development with pnpm (For Environment Testing)
Use this if you’re working on:
- Environment management (process spawning, health checks, port allocation)
- Testing environments that use Docker (avoids docker-in-docker complexity)
- Faster iteration with instant HMR/hot-reload
Setup:
git clone https://github.com/preset-io/agor
cd agor
pnpm installTwo-process workflow:
# Terminal 1: Daemon (watches @agor/core + daemon, auto-restarts)
cd apps/agor-daemon
pnpm dev
# Terminal 2: UI dev server (Vite HMR for instant updates)
cd apps/agor-ui
pnpm dev
# Visit http://localhost:5173Why local for testing Environment features?
The Environment system spawns processes defined in your repo’s environment config (e.g., pnpm dev, docker compose up, etc.). If your environment commands use Docker, running Agor itself in Docker requires docker-in-docker setup. Local development avoids this complexity.
Project Structure
agor/
├── apps/
│ ├── agor-daemon/ # FeathersJS backend (REST + WebSocket)
│ ├── agor-cli/ # CLI tool (oclif-based)
│ ├── agor-ui/ # React UI (Ant Design + React Flow)
│ └── agor-docs/ # Documentation website (Nextra)
├── packages/
│ ├── core/ # Shared @agor/core package
│ │ ├── types/ # TypeScript types (Session, Task, Worktree, etc.)
│ │ ├── db/ # Drizzle ORM + repositories + schema
│ │ ├── git/ # Git utils (simple-git only, no subprocess)
│ │ ├── claude/ # Claude Code session loading utilities
│ │ └── api/ # FeathersJS client utilities
│ └── agor-live/ # Published npm package
└── context/ # 📚 Architecture documentation (READ THIS!)
├── concepts/ # Core design docs
└── explorations/ # Experimental designsMonorepo & Development Tooling
Agor is a pnpm workspace monorepo with several automation tools:
pnpm Workspaces
Structure:
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'Workspace protocol:
- Packages reference each other via
workspace:* - Example:
@agor/clidepends on@agor/core@workspace:* - pnpm symlinks workspace packages (no need to rebuild on every change)
Turbo
Parallel builds and task orchestration:
# Build all packages in dependency order
pnpm build
# Run typecheck across all packages in parallel
pnpm typecheck
# Run dev servers (daemon + UI)
pnpm devHow it works:
- Reads
turbo.jsonfor task definitions - Understands package dependencies
- Runs tasks in parallel when possible
- Caches build outputs for speed
Git Hooks (Husky + lint-staged)
Pre-commit checks:
- Runs automatically before
git commit - Only checks staged files (fast!)
- Runs: biome (linting), prettier (formatting), typecheck
Setup:
pnpm prepare # Installs git hooksCode Quality
Linting:
- biome - Fast linter and formatter
- Config:
biome.json - Run:
pnpm lintorpnpm lint:fix
Formatting:
- prettier - Code formatter
- Config:
.prettierrc - Run:
pnpm format
Root Scripts
Common commands from root directory:
# Development
pnpm dev # Start daemon + UI
pnpm docs:dev # Start docs site
# Code quality
pnpm typecheck # Type check all packages
pnpm lint # Lint all packages
pnpm lint:fix # Lint and auto-fix
pnpm format # Format all files
pnpm check # typecheck + lint + build
pnpm check:fix # lint:fix + typecheck + build
# Building
pnpm build # Build all packages
pnpm clean # Clean all build artifacts
# CLI (from root)
pnpm agor <command> # Run CLI without global installTech Stack
See the Architecture Guide for the complete tech stack (FeathersJS, Drizzle, React, Ant Design, etc.).
Development Patterns
Code Standards
- Type-driven - Use branded types for IDs, strict TypeScript
- Centralize types - ALWAYS import from
packages/core/src/types/(never redefine) - Read before edit - Always read files before modifying
- Prefer Edit over Write - Modify existing files when possible
- Git operations - ALWAYS use
simple-git(NEVER subprocessexecSync,spawn, etc.) - Error handling - Clean user-facing errors, no stacktraces in CLI
Important Rules
Git Library:
- ✅ Use
simple-gitfor ALL git operations - ❌ NEVER use
execSync,spawn, or bash for git commands - Location:
packages/core/src/git/index.ts
Watch Mode:
- User runs
pnpm devin daemon (watches core + daemon) - DO NOT run builds unless explicitly asked or you see compilation errors
- DO NOT start background processes
Type Reuse:
- Import types from
packages/core/src/types/ - Sessions, Tasks, Worktrees, Messages, Repos, Boards, Users, etc.
- Never redefine canonical types
Worktree-Centric Architecture:
- Boards display Worktrees as primary cards (NOT Sessions)
- Sessions reference worktrees via required FK
- Read
context/concepts/worktrees.mdbefore touching boards
Key Documentation
Before diving into code, familiarize yourself with the architecture:
- AGENTS.md - Development patterns and project structure
- CONTRIBUTING.md - Complete contribution guide
- context/README.md - Architecture documentation index
- context/concepts/core.md - Core primitives and design philosophy
Testing
Database Operations
SQLite:
# Query database directly
sqlite3 ~/.agor/agor.db "SELECT COUNT(*) FROM messages"
sqlite3 ~/.agor/agor.db "SELECT * FROM sessions LIMIT 5"PostgreSQL:
# Connect to postgres container
docker compose exec postgres psql -U agor -d agor
# Example queries
docker compose exec postgres psql -U agor -d agor -c "SELECT COUNT(*) FROM messages"
docker compose exec postgres psql -U agor -d agor -c "SELECT * FROM sessions LIMIT 5"Health Checks
# Daemon health
curl http://localhost:3030/health
# Check which database is active (admin auth required)
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" http://localhost:3030/healthCLI Commands
# Test CLI (ensure clean exit, no hanging)
pnpm agor session list
pnpm agor repo list
# CLI auto-detects database from environment
# Works with both SQLite and PostgreSQLTroubleshooting
”Method is not a function” after editing @agor/core
Should NOT happen with new 2-process workflow (daemon watches core and auto-restarts).
If it still happens:
cd packages/core && pnpm build
cd apps/agor-daemon && pnpm devtsx watch not picking up changes
cd apps/agor-daemon
rm -rf node_modules/.tsx
pnpm devDaemon hanging
lsof -ti:3030 | xargs kill -9
cd apps/agor-daemon && pnpm devWhat to Contribute
Browse the roadmap issues for contribution ideas, or propose your own!
Next Steps
- Architecture - System design and internals
- Run
agor --helpfor complete CLI documentation - API Reference - REST endpoints and WebSocket events
- AGENTS.md - Development patterns and project structure