Skip to main content

Development

This guide covers building Codex from source for development purposes.

Prerequisites​

  • Rust 1.93 or later
  • Cargo (comes with Rust)
  • OpenSSL development libraries
  • UnRAR library (optional, for CBR support)

Installing Rust​

If you don't have Rust installed, use rustup:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Installing System Dependencies​

macOS​

brew install openssl

Ubuntu/Debian​

sudo apt-get update
sudo apt-get install build-essential pkg-config libssl-dev

Fedora/RHEL​

sudo dnf install gcc openssl-devel

Building from Source​

Clone the Repository​

git clone https://github.com/AshDevFr/codex.git
cd codex

Install Pre-commit Hooks​

After cloning, install pre-commit hooks to ensure generated files stay in sync:

make setup-hooks

This requires Python and will install pre-commit if not already available. The hooks ensure that web/openapi.json and web/src/types/api.generated.ts are regenerated when backend API changes are committed.

Standard Build (with CBR support)​

By default, Codex includes CBR support:

cargo build --release

The binary will be located at target/release/codex.

Build without CBR Support​

If you want to avoid the proprietary UnRAR dependency:

cargo build --release --no-default-features

This disables CBR parsing but keeps all other formats (CBZ, EPUB, PDF) working.

Development Build​

For faster iteration during development:

cargo build

This creates an unoptimized binary at target/debug/codex that compiles faster.

Running Tests​

All Tests​

cargo test

Specific Test Suites​

# Parser tests
cargo test parsers

# Database tests
cargo test db

# API tests
cargo test api

Tests without CBR Support​

cargo test --no-default-features

PostgreSQL Integration Tests​

For running PostgreSQL tests, start the test container with make test-up and run make test-postgres.

Fast Parallel Tests (cargo-nextest)​

For significantly faster test execution, install cargo-nextest:

cargo install cargo-nextest --locked

Then run tests with:

# Fast parallel tests
make test-fast

# Fast PostgreSQL tests
make test-fast-postgres

Nextest runs tests in parallel and is typically 2-3x faster than cargo test.

Speeding Up Builds​

Codex's .cargo/config.toml is preconfigured to use faster linkers and (optionally) a compilation cache. Installing these tools will noticeably reduce rebuild times during development.

Faster Linker​

On a typical Apple Silicon machine, lld cuts warm rebuild link time by roughly a third (e.g., ~23s instead of ~35s) compared to the system linker. On Linux, mold provides a similar improvement.

macOS​

brew install lld

Linux​

# Ubuntu/Debian
sudo apt-get install mold clang

# Fedora
sudo dnf install mold clang

If the linker is not installed, Cargo falls back to the default linker automatically (no errors), so this step is optional.

Compilation Cache (sccache)​

sccache caches compiled crates across cargo clean, branch switches, and changes to Cargo.lock. It mainly helps cold builds and dependency recompiles; it adds ~2s of wrapper overhead on warm incremental rebuilds, but the cold-build savings (around 10% on this project) typically outweigh that.

Install it:

# macOS
brew install sccache

# Linux / other
cargo install sccache --locked

sccache is opt-in per developer. The repo's .cargo/config.toml deliberately doesn't wire it in, so checkouts work on machines and in CI/Docker environments where it isn't installed. Pick whichever opt-in fits your setup:

# Shell profile (applies to every cargo project on your machine)
export RUSTC_WRAPPER=sccache
# Or in ~/.cargo/config.toml (user-level, also applies everywhere)
[build]
rustc-wrapper = "sccache"

To disable temporarily for a single build, prefix it with RUSTC_WRAPPER= cargo build.

Check the cache hit rate at any time:

sccache --show-stats

macOS: Exclude target/ from Spotlight​

The target/ directory can grow to many gigabytes with thousands of small files. Spotlight indexing those files causes very high system CPU during builds. Exclude the directory:

touch target/.metadata_never_index

Or add target/ to System Settings → Siri & Spotlight → Spotlight Privacy. The Privacy entry is path-based and survives cargo clean.

Verify Setup​

Check that your development tools are properly installed:

make dev-check

This will show which optional performance tools are available.

Development Workflow​

Running the Server​

# Development mode (with debug logging)
RUST_LOG=debug cargo run -- serve --config config/config.sqlite.yaml

Hot Reload (Docker)​

Use Docker Compose with watch mode for automatic rebuilds:

docker compose -f docker-compose.yml -f compose.watch.yml --profile dev up --watch

Frontend Development​

For full-stack development with the React frontend:

# Start backend and frontend (recommended)
docker compose --profile dev up

# Access the app at http://localhost:5173
# The Vite dev server proxies /api and /opds requests to the backend

Or run them separately:

# Terminal 1 - Backend
cargo run -- serve --config config/config.sqlite.yaml

# Terminal 2 - Frontend
cd web
npm install
npm run dev

# Access at http://localhost:5173

Important: Always use http://localhost:5173 (frontend) in development. The Vite dev server automatically proxies API requests to the backend at http://localhost:8080.

The frontend is a React/TypeScript application using Vite, Mantine UI, and TanStack Query.

Mock API Mode​

For frontend-only development without a backend, you can use the mock API:

cd web
VITE_MOCK_API=true npm run dev

Environment variables for mock mode:

VariableDescriptionDefault
VITE_MOCK_APIEnable mock API modefalse
VITE_MOCK_SETUP_REQUIREDShow the setup wizard instead of loginfalse

Example to test the setup wizard:

VITE_MOCK_API=true VITE_MOCK_SETUP_REQUIRED=true npm run dev

Code Formatting​

cargo fmt

Linting​

cargo clippy

Project Structure​

Codex is a Cargo workspace. The top-level binary crate (src/) is intentionally thin; the bulk of the code lives in sibling crates under crates/. Editing one subsystem only recompiles that crate and its downstream consumers, which keeps warm rebuilds fast.

codex/
├── src/ # codex (binary) crate
│ ├── main.rs # CLI entry point
│ └── commands/ # Per-subcommand orchestration (scan, serve, ...)
├── crates/
│ ├── codex-api/ # HTTP API: axum routes, OPDS, Komga, observability
│ ├── codex-config/ # YAML config + env overrides
│ ├── codex-db/ # SeaORM entities + repositories
│ ├── codex-events/ # In-process event broadcaster
│ ├── codex-models/ # Cross-layer DTOs and shared types
│ ├── codex-parsers/ # CBZ/CBR/EPUB/PDF parsing
│ ├── codex-scanner/ # Library scan workflow
│ ├── codex-scheduler/ # Cron/interval scheduler
│ ├── codex-search/ # In-memory fuzzy search index
│ ├── codex-services/ # Business logic (auth, plugins, metadata, ...)
│ ├── codex-tasks/ # Background worker + task handlers
│ └── codex-utils/ # Crypto, JWT, hashing, error types
├── migration/ # SeaORM migrations (own crate, used by codex-db)
├── tests/ # Integration tests against codex-api
└── docs/ # Documentation

Per-crate builds work in isolation, e.g. cargo build -p codex-parsers.

Database Migrations​

Running Migrations​

Migrations run automatically on server startup. To run manually:

cd migration
cargo run

Creating New Migrations​

Use SeaORM's migration CLI:

# Install migration CLI
cargo install sea-orm-cli

# Create new migration
sea-orm-cli migrate generate <migration_name>

Contributing​

Code Style​

  • Follow Rust standard formatting (cargo fmt)
  • Run cargo clippy before submitting PRs
  • Write tests for new features

Testing​

  • Add unit tests for new functions
  • Add integration tests for API endpoints
  • Ensure all tests pass before submitting

Documentation​

  • Update relevant documentation when adding features
  • Add code comments for complex logic
  • Update API documentation if endpoints change

Debugging​

Enable Debug Logging​

RUST_LOG=debug codex serve --config codex.yaml

Database Debugging​

For SQLite, you can inspect the database directly:

sqlite3 data/codex.db

For PostgreSQL:

psql -U codex -d codex

Tracing​

Codex uses the tracing crate for structured logging. Set log levels:

RUST_LOG=codex=debug,tower_http=info codex serve

Performance Profiling​

Release Build​

Always profile with release builds:

cargo build --release

Profiling Tools​

  • perf (Linux): perf record ./target/release/codex serve
  • Instruments (macOS): Use Xcode Instruments
  • flamegraph: Generate flamegraphs for performance analysis

Next Steps​