Guidance for Claude Code (claude.ai/code) working with this repository.
NEVER write memory files outside this project. Use .claude/memory/ within the repo for all persistent notes. Do not use ~/.claude/projects/*/memory/.
CRITICAL: These are ACTIVE RULES, not reference docs. You MUST apply them to EVERY response.
Read .claude/ESSENTIAL_PROTOCOLS.md (~5 KB)
This single file contains ALL core rules:
- Verification before claiming
- Communication style
- Testing requirements
- Coding standards essentials
- Session start workflow
- Contextual protocol loading guide
Token savings: 86% reduction (5 KB vs 37 KB)
After reading ESSENTIAL_PROTOCOLS.md, load additional protocols based on task:
| Task Type | Load Protocol |
|---|---|
| Git work (commit/push) | GIT_VERIFICATION_PROTOCOL.md |
| Refactoring code | TESTING_BEFORE_REFACTORING_PROTOCOL.md, then MANDATORY_REFACTORING_PROTOCOL.md |
| Test failures | FUNCTIONAL_TEST_DEBUGGING_GUIDE.md |
| Error recovery | ERROR_RECOVERY_PROTOCOL.md |
| Creating docs | DOCUMENTATION_PLACEMENT_GUIDE.md |
Decision tree: See .claude/README.md "What Do You Want to Do?" section
IMMEDIATELY AFTER reading protocols, EXECUTE these commands (not later - NOW):
# 1. Git state check
git status && git diff && git diff --staged
# 2. Backport review - DISABLED (codebase diverged too much from 5.0)
# LAST_HASH=$(grep "Last reviewed commit" .claude/BACKPORT.md | awk '{print $NF}')
# echo "=== Commits since last backport review ($LAST_HASH) ==="
# git log $LAST_HASH..HEAD --oneline
# 3. Plan state check
ls -la plan/THEN use AskUserQuestion tool to ask about any issues found:
If modified/staged files exist OR new commits since backport review, use AskUserQuestion with questions like:
Question 1 (if modified files found):
header: "Modified files"
question: "Found N modified files: [list]. How should I handle them?"
options:
- label: "Continue work", description: "These are my in-progress changes, continue working on them"
- label: "Discard changes", description: "Reset these files to HEAD"
- label: "Review first", description: "Show me the diff before deciding"
Question 2 (if plan files exist):
header: "Active plans"
question: "Active plans found: [list with status]. Which plan are we working on?"
options:
- label: "[plan name]", description: "Continue work on this plan"
- label: "None", description: "Not working on any plan today"
Self-check after reading:
- Can I state the emoji rule? (Start every line with emoji)
- Can I state the verification rule? (Paste command output before claiming)
- Can I state the git rule? (Fresh git status before operations)
- Did I RUN the plan state check above? (Not just read about it)
- Will I APPLY these to my next response? (Not just "know" them)
THEN complete: .claude/PRE_FLIGHT_CHECKLIST.md before starting work.
.claude/DOCUMENTATION_PLACEMENT_GUIDE.md to know where to put it.
NEVER declare code "fixed"/"ready"/"working"/"complete" without running ALL tests:
./qa/bin/test_everything # ALL 6 test suites, exits on first failureDO NOT:
- Skip tests
- Run partial tests and claim success
- Claim "fixed" without verification
See: .claude/CI_TESTING.md for complete checklist.
First time setup:
# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install dependencies
uv syncUpdate dependencies:
uv lock # Update lock file
./qa/bin/sync_requirements.sh # Sync qa/requirements.txt# ALL tests (required before declaring success)
./qa/bin/test_everything
# Individual (for debugging only)
uv run ruff format src && uv run ruff check src
env exabgp_log_enable=false uv run pytest ./tests/unit/
./qa/bin/functional encoding # ALL 72 tests
./qa/bin/functional decoding
./sbin/exabgp configuration validate -nrv ./etc/exabgp/conf-ipself6.conf
# Debug specific encoding test
./qa/bin/functional encoding --list # List all tests
./qa/bin/functional encoding <letter> # Run one test
# Inspect test configuration (view all test files)
env EDITOR=cat ./qa/bin/functional encoding --edit <letter>
# Debug in separate terminals
./qa/bin/functional encoding --server <letter> # Terminal 1
./qa/bin/functional encoding --client <letter> # Terminal 2
# Capture run logs for intermittent failures
./qa/bin/functional encoding <letter> --save /tmp/runs/
# Logs include: timing, message hashes, match/mismatch status
# Compare logs from multiple runs to diagnose intermittent issues
# Stress test - run N times and report statistics
./qa/bin/functional encoding <letter> --stress 10
# Shows pass/fail per run, timing stats (min/avg/max/stddev)
# Verbose mode - show full daemon/client output for each test
./qa/bin/functional encoding -v
# Shows ALL output (no truncation) on failure, useful for debugging
# Filters only keepalive timer spam, all other output preserved
# Quiet mode - minimal output, verbose only on failure
./qa/bin/functional encoding -q
# Single line on success: "passed N/N (100.0%)"
# Full verbose output on failure with debug hintsSee:
.claude/FUNCTIONAL_TEST_DEBUGGING_GUIDE.mdfor systematic debugging.claude/FUNCTIONAL_TEST_EDIT.mdfor inspecting test configurations
# ENCODE: Convert route config to hex UPDATE message
./sbin/exabgp encode "route 10.0.0.0/24 next-hop 1.2.3.4"
./sbin/exabgp encode "route 10.0.0.0/24 next-hop 1.2.3.4 as-path [65000 65001]"
./sbin/exabgp encode -f "ipv6 unicast" "route 2001:db8::/32 next-hop 2001:db8::1"
./sbin/exabgp encode -n "route 10.0.0.0/24 next-hop 1.2.3.4" # NLRI only
# DECODE: Parse hex message to JSON
./sbin/exabgp decode "<hex>" # Decode UPDATE
./sbin/exabgp decode -c <config> "<hex>" # With config context
echo "<hex>" | ./sbin/exabgp decode # From stdin
./sbin/exabgp encode "route ..." | ./sbin/exabgp decode # Round-trip
# Use decode when server shows "unexpected message"
# IMPORTANT: Use -c with same config as test (from qa/encoding/<test>.ci)uv run ruff format src # Single quotes, 120 char
uv run ruff check src # Must passkillall -9 Python # macOS uses capital PSlash commands for development workflow:
| Command | Purpose | Usage |
|---|---|---|
/validate |
Run tests | /validate (full suite), /validate quick (lint only) |
/review |
Semantic code review | /review (staged), /review all, /review src/file.py |
/review-docs |
Documentation review | /review-docs src/file.py |
Validation modes:
- quick: Lint only (~30s) - for fast feedback during development
- full: Complete test suite (~5min) - default, use before commit
Auto-linter hook (.claude/hooks/auto_linter.py):
- Triggers on Write/Edit of Python files
- Runs
ruff formatandruff check --fixautomatically - Advisory mode: reports remaining issues but doesn't block
Configuration: See .claude/settings.local.json for hook setup.
π¨ CRITICAL RULES π¨
NEVER COMMIT without explicit user request:
- User must say: "commit", "make a commit", "git commit"
- DO NOT commit after completing work
- WAIT for user review
NEVER PUSH without explicit user request:
- Each push requires explicit instruction for THAT work
- User must say: "push", "git push", "push now"
When work complete:
- Stop, report what was done
- WAIT for user instruction
- Only commit if explicitly asked
- Only push if explicitly asked
Before ANY git operation:
git status && git log --oneline -5Verify no unexpected changes. If found: STOP and ask user.
See: .claude/GIT_VERIFICATION_PROTOCOL.md for complete requirements.
ExaBGP: BGP protocol implementation + JSON API. Does NOT manipulate FIB.
Core Components:
-
BGP Protocol (
src/exabgp/bgp/):fsm.py- State machine (IDLE β ESTABLISHED)message/- OPEN, UPDATE, NOTIFICATION, KEEPALIVEmessage/update/- Attributes, NLRI, address families
-
Reactor (
src/exabgp/reactor/):- Event-driven (custom, not asyncio)
peer.py- BGP peer handlingapi/- External process communication
-
Configuration (
src/exabgp/configuration/):- Flexible parser, templates, validation
-
RIB (
src/exabgp/rib/):- Routing information base
Supported Address Families: IPv4/IPv6, VPNv4/v6, EVPN, BGP-LS, FlowSpec, VPLS, MUP, SRv6
Design Patterns:
- Registry/Factory:
@Message.register,@NLRI.register - Template Method:
pack_nlri(),unpack_nlri() - State Machine: BGP FSM
- Observer: Reactor coordinates peers
Data Flow:
- Inbound: Network β Reactor β Message β NLRI/Attributes β API
- Outbound: Config β RIB β Update β Protocol β Network
MUST READ when starting work on new features or major changes:
-
.claude/exabgp/CODEBASE_ARCHITECTURE.md- Complete directory structure, module purposes, file locations- Read when: Need to find where specific functionality lives
- Contains: Directory tree, file sizes, core vs peripheral modules
-
.claude/exabgp/DATA_FLOW_GUIDE.md- How data moves through the system- Read when: Adding features, debugging message flow
- Contains: Inbound/outbound pipelines, parsing/serialization, RIB operations
-
.claude/exabgp/REGISTRY_AND_EXTENSION_PATTERNS.md- How to extend ExaBGP- Read when: Adding NLRI types, attributes, capabilities, API commands
- Contains: Step-by-step patterns, required file changes, common pitfalls
-
.claude/exabgp/BGP_CONCEPTS_TO_CODE_MAP.md- BGP RFC concepts to code locations- Read when: Implementing BGP features from RFCs
- Contains: AFI/SAFI mappings, message types, attribute codes, capability codes
-
.claude/exabgp/CRITICAL_FILES_REFERENCE.md- Most frequently modified files- Read when: Need quick navigation to important files
- Contains: Top 10 files, "change X update Y" table, stable interfaces
-
.claude/exabgp/CLI_COMMANDS.md- Complete CLI command reference- Read when: Working with CLI, adding commands, understanding syntax
- Contains: All 43 commands, syntax, examples, neighbor selectors, display modes
-
.claude/exabgp/CLI_SHORTCUTS.md- CLI shortcut reference- Read when: Working with CLI, understanding shortcuts
- Contains: Single/multi-letter shortcuts, context rules, expansion examples
-
.claude/exabgp/CLI_IMPLEMENTATION.md- CLI internal architecture- Read when: Modifying CLI code, adding completion features
- Contains: 4 main classes, command flow, tab completion, threading model
-
.claude/exabgp/UNIX_SOCKET_API.md- Unix socket API protocol- Read when: Working with API, socket communication
- Contains: Protocol spec, connection handshake, response parsing
-
.claude/exabgp/NEIGHBOR_SELECTOR_SYNTAX.md- Neighbor selector grammar- Read when: Working with neighbor-targeted commands
- Contains: Selector syntax, matching algorithm, usage patterns
-
.claude/exabgp/ENVIRONMENT_VARIABLES.md- Environment variables reference- Read when: Working with configuration, environment variables, reactor/daemon/logging/API settings
- Contains: All exabgp_* variables, tcp.attempts, bgp., daemon., log., api., reactor., cache., debugging options
-
.claude/exabgp/PEP688_BUFFER_PROTOCOL.md- Python 3.12 Buffer protocol reference- Read when: Working with wire data, bytes/memoryview handling, type annotations for binary data
- Contains:
collections.abc.Bufferusage, zero-copy patterns, when to convert to bytes
-
.claude/exabgp/PACKED_BYTES_FIRST_PATTERN.md- Packed-bytes-first NLRI pattern- Read when: Converting NLRI classes to store wire bytes, optimizing memory allocation
- Contains: Pattern explanation, implementation steps, conversion checklist, VPLS reference
-
doc/RFC_WIRE_FORMAT_REFERENCE.md- RFC wire format quick reference- Read when: Working with NLRI/attribute pack/unpack, reviewing wire format, debugging protocol issues
- Contains: Wire format diagrams, byte layouts, TLV codes, validation rules, all RFCs in one place
-
.claude/exabgp/NLRI_CLASS_HIERARCHY.md- NLRI class inheritance and slot storage- Read when: Modifying NLRI
__init__methods, refactoring NLRI classes, understanding slot inheritance - Contains: Class hierarchy diagram, slot definitions per class, ClassVar vs instance var, factory patterns
- Read when: Modifying NLRI
-
.claude/exabgp/WIRE_SEMANTIC_SEPARATION.md- Wire vs Semantic container design- Read when: Modifying Update, Attribute, NLRI or their Collection counterparts
- Contains: Immutability rules,
_negotiatedstorage, transformation flow, common mistakes
-
.claude/exabgp/COLLECTION_PATTERN.md- Collection pattern reference- Read when: Working with UpdateCollection, AttributeCollection, NLRICollection
- Contains: Wire vs Semantic containers, factory patterns, iterator patterns, when to use each
-
.claude/exabgp/API_COMMAND_ROUNDTRIP.md- API command round-trip testing- Read when: Working with API commands, round-trip testing, adding new family support
- Contains: Test commands, CI file format,
groupcommand patterns, family support guide
-
.claude/exabgp/FLOWSPEC_ROUNDTRIP_LIMITATIONS.md- FlowSpec round-trip status- Read when: Debugging FlowSpec encoding issues, understanding resolved limitations
- Contains: Coverage stats, resolved issues,
groupcommand solutions
Quick reference:
- Adding NLRI type β Read #3, then #1
- Understanding message flow β Read #2
- Finding where BGP concept lives β Read #4
- Starting new feature β Read #1, #3, #5
- Working with CLI β Read #6, #7, #8
- Adding CLI commands β Read #6, #8, #3
- Understanding API protocol β Read #9, #10
- Environment variables/configuration β Read #11
- Working with wire data/bytes/memoryview β Read #12 (PEP 688)
- Converting NLRI to packed-bytes-first β Read #13, reference VPLS implementation
- Wire format/pack/unpack debugging β Read #14
- Modifying NLRI init or slots β Read #15
- Modifying Update/Attribute/Collection classes β Read #16, #17
- Understanding wire vs semantic separation β Read #16
- API command round-trip testing β Read #18, #19
Dual-mode: Generator (default) vs Async (opt-in)
Both are async I/O - differ in syntax only:
- Generator:
yield+select.poll() - Async:
await+ asyncio
Current: Phase 2 (Production Validation)
Enable async:
exabgp_reactor_asyncio=true ./sbin/exabgp config.confTest parity: 100% (72/72 functional, 1376/1376 unit)
See: .claude/asyncio-migration/ for details.
Python 3.12+ ONLY:
- Prefer
int | stroverUnion[int, str] - Prefer
str | NoneoverOptional[str] - See
.claude/CODING_STANDARDS.md
BGP Method APIs (STABLE - DO NOT CHANGE):
def pack(self, negotiated: Negotiated) -> bytes: passUnused negotiated parameters are OK and EXPECTED.
No asyncio introduction - uses custom reactor No FIB manipulation - BGP protocol only
Buffer Protocol (Zero-Copy) - IMPORTANT:
- Use
BufferNOTbytesfor unpack methoddataparameters - Import:
from exabgp.util.types import Buffer - NEVER change
data: Bufferback todata: bytes- this undoes optimization - See
.claude/exabgp/PEP688_BUFFER_PROTOCOL.md
Environment Variables:
- See
.claude/exabgp/ENVIRONMENT_VARIABLES.mdfor all configuration options (tcp., bgp., daemon., log., api., reactor., etc.)
.claude/ - Core protocols and codebase documentation:
- Protocols: 14 session files (ESSENTIAL_PROTOCOLS.md, SESSION_END_CHECKLIST.md, etc.)
- Codebase reference: exabgp/ - architecture, patterns, BGP mappings
- Reference: FUNCTIONAL_TEST_ARCHITECTURE.md, FILE_NAMING_CONVENTIONS.md
- Documentation: docs/ - projects, reference, plans, wip, archive
plan/ - Implementation plans and active work:
- Naming: See plan/README.md for conventions
- Template: Includes Progress, Failures, Blockers, Resume Point sections
Before declaring success:
- Read ESSENTIAL_PROTOCOLS.md
-
./qa/bin/test_everythingpasses -
git statusreviewed - Plan files updated (if working on a plan)
- User approval for commit/push
- Python 3.12+ syntax
- No asyncio introduced
Before ending session:
- Run SESSION_END_CHECKLIST.md (mandatory)
- Update plan files with progress/failures/resume point
Updated: 2025-12-16