Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development Guide

Development workflow, tools, and best practices for Pierre Fitness Platform.

Table of Contents


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.

ServicePortNotes
Pierre MCP Server8081Backend API, health checks, OAuth callbacks
Expo/Metro Bundler8082Mobile dev server (configured in metro.config.js)
Web Frontend5173Vite dev server

Mobile Development Warning

When working on frontend-mobile/:

  • NEVER run expo start without specifying port - it defaults to 8081
  • ALWAYS use bun start which 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:

  1. Checks if Pierre server is running (starts it if not)
  2. Validates current JWT token in PIERRE_JWT_TOKEN
  3. Generates fresh 7-day token if expired
  4. Updates .envrc with new token
  5. Verifies MCP endpoint is responding

Why Required

  • JWT tokens expire (24 hours default, 7 days from script)
  • .mcp.json uses ${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
# 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/)

ScriptDescription
start-server.shStart Pierre backend on port 8081
stop-server.shStop Pierre backend
start-frontend.shStart web dashboard
start-tunnel.shStart Cloudflare tunnel for mobile
claude-session-setup.shMANDATORY session setup
setup-and-start.shCombined setup and start

Development Scripts (scripts/)

ScriptDescription
fresh-start.shClean database and start fresh
complete-user-workflow.shCreate admin, user, tenant
dev-start.shDevelopment startup
linear-session-init.shInitialize Linear session tracking

Validation Scripts

ScriptDescription
pre-push-validate.shMarker-based pre-push validation
architectural-validation.shCheck architectural patterns
lint-and-test.shFull CI validation suite
pre-push-frontend-tests.shFrontend-specific validation
pre-push-mobile-tests.shMobile-specific validation

Testing Scripts

ScriptDescription
smoke-test.shQuick smoke tests (~3 min)
fast-tests.shFast test subset (~5 min)
pre-push-tests.shPre-push tests (~10 min)
safe-test-runner.shIsolated 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