Development Guide
Development workflow, tools, and best practices for Pierre Fitness Platform.
Table of Contents
- Quick Start
- Port Allocation
- Server Management
- Claude Code Sessions
- Validation Workflow
- Testing
- Mobile Development
- Frontend Development
- Admin Tools
- Database
- Scripts Reference
Quick Start
# 1. Start the Pierre server
./bin/start-server.sh
# 2. Verify health
curl http://localhost:8081/health
# 3. Run setup workflow (creates admin, user, tenant)
./scripts/complete-user-workflow.sh
# 4. Load credentials
source .workflow_test_env
echo "JWT Token: ${JWT_TOKEN:0:50}..."
Port Allocation
CRITICAL: Port 8081 is RESERVED for the Pierre MCP Server.
| Service | Port | Notes |
|---|---|---|
| Pierre MCP Server | 8081 | Backend API, health checks, OAuth callbacks |
| Expo/Metro Bundler | 8082 | Mobile dev server (configured in metro.config.js) |
| Web Frontend | 5173 | Vite dev server |
Mobile Development Warning
When working on frontend-mobile/:
- NEVER run
expo startwithout specifying port - it defaults to 8081 - ALWAYS use
bun startwhich is configured for port 8082
Server Management
Startup Scripts
./bin/start-server.sh # Start backend (loads .envrc, port 8081)
./bin/stop-server.sh # Stop backend (graceful shutdown)
./bin/start-frontend.sh # Start web dashboard (port 5173)
./bin/start-tunnel.sh # Start Cloudflare tunnel for mobile testing
Manual Startup
# Backend
cargo run --bin pierre-mcp-server
# Frontend (separate terminal)
cd frontend && npm run dev
# Mobile (separate terminal)
cd frontend-mobile && bun start
Health Check
curl http://localhost:8081/health
Claude Code Sessions
Session Setup (MANDATORY)
Run this at the START OF EVERY Claude Code session:
./bin/claude-session-setup.sh
This script automatically:
- Checks if Pierre server is running (starts it if not)
- Validates current JWT token in
PIERRE_JWT_TOKEN - Generates fresh 7-day token if expired
- Updates
.envrcwith new token - Verifies MCP endpoint is responding
Why Required
- JWT tokens expire (24 hours default, 7 days from script)
.mcp.jsonuses${PIERRE_JWT_TOKEN}environment variable- Expired tokens cause “JWT token signature is invalid” errors
Manual Token Refresh
# Generate new 7-day token
cargo run --bin admin-setup -- generate-token --service claude_code --expires-days 7
# Update .envrc
export PIERRE_JWT_TOKEN="<paste_token_here>"
# Reload environment
direnv allow
Linear Session Tracking
Sessions are tracked via Linear issues:
# Automatic - runs via SessionStart hook
./scripts/linear-session-init.sh
# Manual session commands (via /session skill)
/session # Show current session status
/session update # Add work log entry
/session decision # Document a key decision
/session end # Add end-of-session summary
Validation Workflow
Pre-Push Validation (Marker-Based)
The pre-push hook uses marker-based validation to avoid SSH timeouts:
# 1. Run validation (creates marker valid for 15 minutes)
./scripts/pre-push-validate.sh
# 2. Push (hook checks marker)
git push
Tiered Validation Approach
Tier 1: Quick Iteration (during development)
cargo fmt
cargo check --quiet
cargo test <test_name_pattern> -- --nocapture
Tier 2: Pre-Commit (before committing)
cargo fmt
./scripts/architectural-validation.sh
cargo clippy --all-targets -- -D warnings -D clippy::all -D clippy::pedantic -D clippy::nursery -W clippy::cognitive_complexity
cargo test <module_pattern> -- --nocapture
CRITICAL: Always use --all-targets with clippy to catch errors in tests.
Tier 3: Full Validation (before PR/merge)
./scripts/lint-and-test.sh
Test Targeting Patterns
# By test name
cargo test test_training_load
# By test file
cargo test --test intelligence_test
# By module path
cargo test intelligence::
# With output
cargo test <pattern> -- --nocapture
Testing
Quick Validation
./scripts/smoke-test.sh # ~3 minutes
./scripts/fast-tests.sh # ~5 minutes
./scripts/pre-push-tests.sh # ~10 minutes
Full Test Suite
cargo test # All tests (~13 min, 647 tests)
./scripts/lint-and-test.sh # Full CI suite
Finding Related Tests
# Find test files mentioning your module
rg "mod_name" tests/ --files-with-matches
# List tests in a specific test file
cargo test --test <test_file> -- --list
See testing.md for comprehensive testing documentation.
Mobile Development
Setup
cd frontend-mobile
bun install
Running
# Start Metro bundler on port 8082
bun start
# iOS Simulator
bun run ios
# Android Emulator
bun run android
Validation
# TypeScript
bun run typecheck
# ESLint
bun run lint
# Unit tests
bun test
# All tiers
../scripts/pre-push-mobile-tests.sh
# E2E tests (requires iOS Simulator)
bun run e2e:build && bun run e2e:test
Testing on Physical Device (Cloudflare Tunnel)
# From frontend-mobile directory
bun run tunnel # Start tunnel only
bun run start:tunnel # Start tunnel AND Expo
bun run tunnel:stop # Stop tunnel
# After starting tunnel:
# 1. Run `direnv allow` in backend directory
# 2. Restart Pierre server: ./bin/stop-server.sh && ./bin/start-server.sh
# 3. Mobile app connects via tunnel URL
Frontend Development
Setup
cd frontend
npm install
Running
npm run dev # Start Vite dev server (port 5173)
Validation
# TypeScript
npm run type-check
# ESLint
npm run lint
# Unit tests
npm test -- --run
# All tiers
../scripts/pre-push-frontend-tests.sh
# E2E tests
npm run test:e2e
Environment
# Add to .envrc for custom backend URL
export VITE_BACKEND_URL="http://localhost:8081"
Admin Tools
admin-setup Binary
# Create admin user for frontend login
cargo run --bin admin-setup -- create-admin-user \
--email admin@example.com \
--password SecurePassword123
# Generate API token for a service
cargo run --bin admin-setup -- generate-token \
--service my_service \
--expires-days 30
# Generate super admin token (no expiry, all permissions)
cargo run --bin admin-setup -- generate-token \
--service admin_console \
--super-admin
# List all admin tokens
cargo run --bin admin-setup -- list-tokens --detailed
# Revoke a token
cargo run --bin admin-setup -- revoke-token <token_id>
Complete User Workflow
# Creates admin, user, tenant, and saves JWT token
./scripts/complete-user-workflow.sh
# Load saved credentials
source .workflow_test_env
Database
SQLite (Development)
# Location
./data/users.db
# Reset
./scripts/fresh-start.sh
PostgreSQL (Production)
# Test PostgreSQL integration
./scripts/test-postgres.sh
See configuration.md for database configuration.
Scripts Reference
Server Scripts (bin/)
| Script | Description |
|---|---|
start-server.sh | Start Pierre backend on port 8081 |
stop-server.sh | Stop Pierre backend |
start-frontend.sh | Start web dashboard |
start-tunnel.sh | Start Cloudflare tunnel for mobile |
claude-session-setup.sh | MANDATORY session setup |
setup-and-start.sh | Combined setup and start |
Development Scripts (scripts/)
| Script | Description |
|---|---|
fresh-start.sh | Clean database and start fresh |
complete-user-workflow.sh | Create admin, user, tenant |
dev-start.sh | Development startup |
linear-session-init.sh | Initialize Linear session tracking |
Validation Scripts
| Script | Description |
|---|---|
pre-push-validate.sh | Marker-based pre-push validation |
architectural-validation.sh | Check architectural patterns |
lint-and-test.sh | Full CI validation suite |
pre-push-frontend-tests.sh | Frontend-specific validation |
pre-push-mobile-tests.sh | Mobile-specific validation |
Testing Scripts
| Script | Description |
|---|---|
smoke-test.sh | Quick smoke tests (~3 min) |
fast-tests.sh | Fast test subset (~5 min) |
pre-push-tests.sh | Pre-push tests (~10 min) |
safe-test-runner.sh | Isolated test runner |
See scripts/README.md for complete documentation.
Debugging
Server Logs
# Real-time debug logs
RUST_LOG=debug cargo run --bin pierre-mcp-server
# Log to file
./bin/start-server.sh # logs to server.log
SDK Debugging
npx pierre-mcp-client@next --server http://localhost:8081 --verbose