6.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Plano is an AI-native proxy server and data plane for agentic applications, built on Envoy proxy. It centralizes agent orchestration, LLM routing, observability, and safety guardrails as an out-of-process dataplane.
Build & Test Commands
Rust (crates/)
# Build WASM plugins (must target wasm32-wasip1)
cd crates && cargo build --release --target=wasm32-wasip1 -p llm_gateway -p prompt_gateway
# Build brightstaff binary (native target)
cd crates && cargo build --release -p brightstaff
# Run unit tests
cd crates && cargo test --lib
# Format check
cd crates && cargo fmt --all -- --check
# Lint
cd crates && cargo clippy --locked --all-targets --all-features -- -D warnings
Python CLI (cli/)
cd cli && uv sync # Install dependencies
cd cli && uv run pytest -v # Run tests
cd cli && uv run planoai --help # Run CLI
JavaScript/TypeScript (apps/, packages/)
npm run build # Build all (via Turbo)
npm run lint # Lint all
npm run dev # Dev servers
npm run typecheck # Type check
Pre-commit (runs fmt, clippy, cargo test, black, yaml checks)
pre-commit run --all-files
Docker
docker build -t katanemo/plano:latest .
E2E Tests (tests/e2e/)
E2E tests require a built Docker image and API keys. They run via tests/e2e/run_e2e_tests.sh which executes four test suites: test_prompt_gateway.py, test_model_alias_routing.py, test_openai_responses_api_client.py, and test_openai_responses_api_client_with_state.py.
Architecture
Core Data Flow
Requests flow through Envoy proxy with two WASM filter plugins, backed by a native Rust binary:
Client → Envoy (prompt_gateway.wasm → llm_gateway.wasm) → Agents/LLM Providers
↕
brightstaff (native binary: state, routing, signals, tracing)
Rust Crates (crates/)
All crates share a Cargo workspace. Two compile to wasm32-wasip1 for Envoy, the rest are native:
- prompt_gateway (WASM) — Proxy-WASM filter for prompt/message processing, guardrails, and filter chains
- llm_gateway (WASM) — Proxy-WASM filter for LLM request/response handling and routing
- brightstaff (native binary) — Core application server: handlers, router, signals, state management, tracing
- common (library) — Shared across all crates: configuration, LLM provider abstractions, HTTP utilities, routing logic, rate limiting, tokenizer, PII detection, tracing
- hermesllm (library) — Translates LLM API formats between providers (OpenAI, Anthropic, Gemini, Mistral, Grok, AWS Bedrock, Azure, together.ai). Key types:
ProviderId,ProviderRequest,ProviderResponse,ProviderStreamResponse
Python CLI (cli/planoai/)
The planoai CLI manages the Plano lifecycle. Key commands:
planoai up <config.yaml>— Validate config, check API keys, start Docker containerplanoai down— Stop containerplanoai build— Build Docker image from repo rootplanoai logs— Stream access/debug logsplanoai trace— OTEL trace collection and analysisplanoai init— Initialize new projectplanoai cli_agent— Start a CLI agent connected to Planoplanoai generate_prompt_targets— Generate prompt_targets from python methods
Entry point: cli/planoai/main.py. Container lifecycle in core.py. Docker operations in docker_cli.py.
Configuration System (config/)
plano_config_schema.yaml— JSON Schema (draft-07) for validating user config filesenvoy.template.yaml— Jinja2 template rendered into Envoy proxy configsupervisord.conf— Process supervisor for Envoy + brightstaff in the container
User configs define: agents (id + url), model_providers (model + access_key), listeners (type: agent/model/prompt, with router strategy), filters (filter chains), and tracing settings.
JavaScript Apps (apps/, packages/)
Turbo monorepo with Next.js 16 / React 19 applications and shared packages (UI components, Tailwind config, TypeScript config). Not part of the core proxy — these are web applications.
Release Process
To prepare a release (e.g., bumping from 0.4.6 to 0.4.7), update the version string in all of the following files:
CI Workflow:
.github/workflows/ci.yml— docker build/save tags
CLI:
cli/planoai/__init__.py—__version__cli/planoai/consts.py—PLANO_DOCKER_IMAGEdefaultcli/pyproject.toml—version
Build & Config:
build_filter_image.sh— docker build tagconfig/validate_plano_config.sh— docker image tag
Docs:
docs/source/conf.py—releasedocs/source/get_started/quickstart.rst— install commands and example outputdocs/source/resources/deployment.rst— docker image tag
Website & Demos:
apps/www/src/components/Hero.tsx— version badgedemos/llm_routing/preference_based_routing/README.md— example output
Important: Do NOT change 0.4.6 references in *.lock files or Cargo.lock — those refer to the colorama and http-body dependency versions, not Plano.
Commit message format: release X.Y.Z
Workflow Preferences
- Git commits: Do NOT add
Co-Authored-Bylines. Keep commit messages short and concise (one line, no verbose descriptions). NEVER commit and push directly tomain—always use a feature branch and PR. - Git branches: Use the format
<github_username>/<feature_name>when creating branches for PRs. Determine the username fromgh api user --jq .login. - GitHub issues: When a GitHub issue URL is pasted, fetch all requirements and context from the issue first. The end goal is always a PR with all tests passing.
Key Conventions
- Rust edition 2021, formatted with
cargo fmt, linted withcargo clippy -D warnings - Python formatted with Black
- WASM plugins must target
wasm32-wasip1— they run inside Envoy, not as native binaries - The Docker image bundles Envoy + WASM plugins + brightstaff + Python CLI into a single container managed by supervisord
- API keys come from environment variables or
.envfiles, never hardcoded