This guide covers building CXDB from source, running tests, and contributing to the project.
- Rust: 1.75 or later with Cargo
- Go: 1.22 or later
- Node.js: 20 or later
- pnpm: Latest version (via
coreutils enable) - Git: For cloning the repository
Optional:
- Docker: For containerized testing
- tmux: For running the dev stack
git clone https://github.com/strongdm/cxdb.git
cd cxdbcxdb/
├── server/ # Rust server (binary protocol + HTTP gateway)
│ ├── src/
│ │ ├── blob_store/ # Content-addressed storage
│ │ ├── turn_store/ # Turn DAG
│ │ ├── protocol/ # Binary protocol
│ │ ├── http/ # HTTP gateway
│ │ ├── registry/ # Type registry
│ │ └── projection/ # Msgpack → JSON
│ ├── Cargo.toml
│ └── tests/
├── clients/
│ ├── go/ # Go client SDK
│ │ ├── client.go
│ │ ├── turn.go
│ │ └── cmd/ # Example programs
│ └── rust/ # Rust client SDK
│ └── cxdb/
├── gateway/ # Go OAuth proxy + static serving
│ ├── cmd/server/
│ ├── internal/
│ └── pkg/
├── frontend/ # React UI
│ ├── app/ # Next.js pages
│ ├── lib/ # Shared utilities
│ └── tests/ # Playwright tests
├── docs/ # Documentation
├── deploy/ # Deployment configs
└── scripts/ # Build and test scripts
# Debug build
cargo build
# Release build (optimized)
cargo build --release
# Check without building
cargo check
# Run directly
cargo runBinaries are output to:
- Debug:
target/debug/ai-cxdb-store - Release:
target/release/ai-cxdb-store
Environment variables:
# Data directory
CXDB_DATA_DIR=./data
# Bind addresses
CXDB_BIND=127.0.0.1:9009
CXDB_HTTP_BIND=127.0.0.1:9010
# Logging
CXDB_LOG_LEVEL=debugcd clients/go
# Build
go build -v
# Run tests
go test -v
# Build example programs
go build -o bin/fixtures ./cmd/cxdb-fixturescd gateway
# Install dependencies
go mod download
# Build
go build -o bin/gateway ./cmd/server
# Run in dev mode (no OAuth)
make -C .. gateway-devDev mode creates gateway/.env with:
DEV_MODE=true
DEV_EMAIL=dev@localhost
DEV_NAME=Developer
PUBLIC_BASE_URL=http://localhost:8080
CXDB_BACKEND_URL=http://127.0.0.1:9010
PORT=8080cd frontend
# Install dependencies
pnpm install
# Dev server (with hot reload)
pnpm dev
# Production build
pnpm build
# Static export
pnpm exportFrontend dev server runs on http://localhost:3000.
Run all components in a tmux session:
make devThis starts:
- Backend on :9009 (binary) and :9010 (HTTP)
- Gateway on :8080
- Frontend on :3000
Access:
- Frontend: http://localhost:3000
- Gateway: http://localhost:8080 (with OAuth bypass)
- Backend: http://localhost:9010 (direct)
Attach to tmux:
tmux attach -t cxdb
# Switch windows:
Ctrl+B, 0 # Backend
Ctrl+B, 1 # Gateway
Ctrl+B, 2 # FrontendStop:
make dev-stopTerminal 1 - Backend:
CXDB_DATA_DIR=./data \
CXDB_HTTP_BIND=127.0.0.1:9010 \
CXDB_LOG_LEVEL=debug \
cargo run --releaseTerminal 2 - Gateway:
cd gateway
make -C .. gateway-devTerminal 3 - Frontend:
cd frontend
pnpm dev# Run all tests
cargo test
# Run specific test
cargo test test_append_turn
# Run with output
cargo test -- --nocapture
# Run tests in specific module
cargo test --package ai-cxdb-store --lib blob_storecd clients/go
# Run all tests
go test -v ./...
# Run specific test
go test -v -run TestAppendTurn
# With race detector
go test -race -v ./...
# Generate coverage
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.outcd frontend
# Lint
pnpm lint
# Type check
pnpm type-check
# Unit tests (if any)
pnpm test
# E2E tests (Playwright)
pnpm test:e2e
# E2E with UI
pnpm test:e2e:uiPlaywright tests require server running:
# Terminal 1
cargo run --release
# Terminal 2
cd frontend
pnpm test:e2eRun full-stack tests:
# Start stack
make dev
# In another terminal
cd clients/go
go test -v -tags=integration ./...Use rustfmt and clippy:
# Format code
cargo fmt --all
# Check formatting
cargo fmt --all -- --check
# Lint with clippy
cargo clippy --workspace -- -D warnings
# Fix clippy warnings
cargo clippy --fixrustfmt.toml (already configured):
max_width = 100
hard_tabs = false
tab_spaces = 4
newline_style = "Unix"Use gofmt and golangci-lint:
# Format code
gofmt -w .
# Check formatting
gofmt -l .
# Lint (if golangci-lint installed)
golangci-lint runUse ESLint and Prettier:
cd frontend
# Lint
pnpm lint
# Fix lint errors
pnpm lint:fix
# Format
pnpm formatRun all checks before committing:
make precommitThis runs:
cargo fmt --checkcargo clippycargo test
cd clients/go
# Build fixture generator
go build -o bin/fixtures ./cmd/cxdb-fixtures
# Generate fixtures
./bin/fixtures -addr localhost:9009 -count 100This creates:
- 10 contexts
- 100 turns with various types
- Msgpack + registry bundles
Example registry for testing:
// clients/go/cmd/cxdb-fixtures/registry.go
bundle := map[string]interface{}{
"registry_version": 1,
"bundle_id": "test-2025-01-30",
"types": map[string]interface{}{
"com.test.Message": map[string]interface{}{
"versions": map[string]interface{}{
"1": map[string]interface{}{
"fields": map[string]interface{}{
"1": map[string]interface{}{"name": "role", "type": "string"},
"2": map[string]interface{}{"name": "text", "type": "string"},
},
},
},
},
},
}# Build with debug symbols
cargo build
# Run with debugger
rust-lldb target/debug/ai-cxdb-store
# Set breakpoint
(lldb) b blob_store::mod::put
(lldb) run
# Inspect variables
(lldb) p blob_hash
(lldb) bt.vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug CXDB",
"cargo": {
"args": ["build", "--package=ai-cxdb-store"]
},
"args": [],
"cwd": "${workspaceFolder}",
"env": {
"CXDB_DATA_DIR": "./data",
"CXDB_LOG_LEVEL": "debug"
}
}
]
}# Install delve
go install github.com/go-delve/delve/cmd/dlv@latest
# Debug test
cd clients/go
dlv test -- -test.run TestAppendTurn
# Set breakpoint
(dlv) b client.go:123
(dlv) c
(dlv) p payload# Frontend with source maps
cd frontend
pnpm dev
# Open http://localhost:3000
# Press F12 → Sources
# Set breakpoints in .tsx files# Install cargo-flamegraph
cargo install flamegraph
# Profile
cargo flamegraph --bin ai-cxdb-store
# Opens flamegraph.svg in browser# Add to test
import _ "net/http/pprof"
func TestWithProfile(t *testing.T) {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// ... test code
}
# Profile
go test -cpuprofile=cpu.prof -bench=.
go tool pprof cpu.prof# Rust
cargo install cargo-valgrind
cargo valgrind run
# Go
go test -memprofile=mem.prof
go tool pprof mem.prof# Generate docs
cargo doc --open
# Document private items
cargo doc --document-private-items# Generate docs
godoc -http=:6060
# View at http://localhost:6060/pkg/github.com/strongdm/cxdb/clients/go/-
Fork the repository
-
Create a feature branch:
git checkout -b feature/amazing-feature
-
Make changes:
- Write code
- Add tests
- Update docs
-
Run pre-commit checks:
make precommit
-
Commit with conventional commit messages:
git commit -m "feat(blob_store): add compression level config" git commit -m "fix(protocol): handle EOF gracefully" git commit -m "docs: update type registry guide"
-
Push to your fork:
git push origin feature/amazing-feature
-
Open a Pull Request
Follow Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Formatting, missing semi-colons, etcrefactor: Code change that neither fixes a bug nor adds a featureperf: Performance improvementtest: Adding or fixing testschore: Build process, tooling, dependencies
Examples:
feat(registry): support nested type descriptors
Adds support for nested types in the type registry, allowing
for complex structured payloads.
Closes #123
fix(blob_store): prevent race condition in dedup check
Use double-checked locking pattern to avoid race when multiple
writers try to store the same blob concurrently.
Fixes #456
PRs require:
- At least one approval
- All CI checks passing
- No merge conflicts
- Conventional commit messages
CXDB uses Semantic Versioning:
MAJOR.MINOR.PATCH(e.g.,1.2.3)- Major: Breaking changes
- Minor: New features (backward compatible)
- Patch: Bug fixes
-
Update version:
# server/Cargo.toml version = "1.2.3" # clients/go/version.go const Version = "1.2.3" # frontend/package.json "version": "1.2.3"
-
Update CHANGELOG.md:
## [1.2.3] - 2025-01-30 ### Added - New feature X ### Fixed - Bug in Y
-
Commit and tag:
git add -A git commit -m "chore: release v1.2.3" git tag -a v1.2.3 -m "Release v1.2.3" git push origin main --tags
-
Build and publish:
# Docker images docker build --platform linux/amd64 -t cxdb/cxdb:1.2.3 . docker push cxdb/cxdb:1.2.3 docker tag cxdb/cxdb:1.2.3 cxdb/cxdb:latest docker push cxdb/cxdb:latest # Go module (automatic via GitHub tags) # Rust crate (if publishing to crates.io) cargo publish
-
Create GitHub Release:
- Go to Releases → Draft a new release
- Tag: v1.2.3
- Title: CXDB v1.2.3
- Copy CHANGELOG entry
- Attach binaries (optional)
Rust:
# Use cargo-watch for auto-rebuild
cargo install cargo-watch
cargo watch -x runFrontend:
# Hot reload is automatic with pnpm dev
cd frontend && pnpm dev# Rust: test name
cargo test test_blob_dedup
# Go: test name pattern
go test -run "TestAppend*"
# Frontend: test file
pnpm test:e2e tests/turn-dag.spec.ts# Remove all data (start fresh)
rm -rf data/
# Or
make clean-data# Use local Go client in examples
cd examples/my-example
go mod edit -replace github.com/strongdm/cxdb/clients/go=../../clients/go
go mod tidy- GitHub Discussions: https://github.com/strongdm/cxdb/discussions
- Slack: https://strongdm-community.slack.com #cxdb
- Issues: https://github.com/strongdm/cxdb/issues
- Architecture - System design
- Contributing Guidelines - Detailed contribution guide
- Code of Conduct - Community guidelines