Contributing
Praxis is open source and welcomes contributions. This guide covers the codebase structure and how to get involved.
Repository Structure
praxis/
├── common/ # Shared types and utilities
├── node/ # Node component (runs on targets)
├── service/ # Service component (backend)
├── web/ # Web component (frontend + server)
├── semantic_parser/ # LLM-based text parsing library
├── docs/ # This documentation
├── .github/ # CI/CD workflows
└── docker-compose.yml # Local development setup
Components
Common (common/)
Shared code used by all components:
- Message types and serialization
- RabbitMQ utilities
- AI client abstraction
- Logging macros
When adding functionality needed by multiple components, put it here.
Node (node/)
The agent that runs on target machines:
- Agent connectors (Claude Code, Gemini, etc.)
- Traffic interception
- Session management
- Terminal handling
node/src/
├── agent_connectors/ # Per-agent implementations
│ └── lua/ # Lua connector runtime + CDP helpers
├── intercept/ # Traffic interception
├── terminal/ # PTY terminal
└── runtime.rs # Main event loop
Lua-based agent scripts (Claude Code, Codex, Cursor, Gemini, M365 Copilot) live in agents/ at the project root and are embedded into the binary at build time.
Service (service/)
The backend that coordinates everything:
- Node tracking
- Semantic operations
- Chain execution
- Database persistence
service/src/
├── semantic_ops/ # Operation execution
├── chain_execution/ # Chain runner
├── database/ # Persistence layer
└── config/ # Service configuration
Web (web/)
The frontend and HTTP/WebSocket server:
- React SPA frontend
- Axum HTTP server
- WebSocket handler
- RabbitMQ bridge
web/
├── src/ # Rust backend
└── frontend/ # React frontend
└── src/
├── components/
├── pages/
└── context/
Semantic Parser (semantic_parser/)
Standalone library for LLM-based parsing:
- Schema-based extraction
- Multi-provider support
- Retry logic
See Semantic Parser for details.
Development Workflow
Setup
- Install Rust and Node.js
- Start RabbitMQ:
docker compose up rabbitmq - Build:
cargo build - Run service:
cargo run --bin praxis_service - Run web:
cargo run --bin praxis_web - Run node:
cargo run --bin praxis_node
Environment Variables for Development
| Variable | Default (debug) | Description |
|---|---|---|
PRAXIS_IGNORE_SERVICE_AGENTS | 1 | When 1, node ignores Lua scripts pushed from the service and uses only embedded scripts. Set to 0 to test service-managed agent scripts. |
PRAXIS_DATABASE_URL | SQLite in home dir | Database connection string |
PRAXIS_RABBITMQ_URL | amqp://praxis:praxis@localhost:5672 | RabbitMQ connection |
Making Changes
- Create a branch
- Make changes
- Run tests:
cargo test - Build:
cargo build - Test manually
- Submit PR
Code Style
- Follow existing patterns
- Use
common::log_*macros for logging (except innode/src/runtime.rsevent forwarder-usetracing::*there to avoid recursion) - Prefer explicit over clever
- Comment non-obvious blocks
Adding Agent Connectors
See Adding New Connectors. Prefer Lua-based connectors for CLI agents — they can be developed and tested at runtime via the web UI without recompiling.
Lua agent scripts live in agents/ at the project root and are embedded into binaries at build time. Shared libraries are at node/src/agent_connectors/lua/lib/ (helpers.lua for common utilities, devtools.lua for CDP/DevTools support).
Adding Operations
Operations are JSON definitions. Add to the library via the web UI or directly to the database.
Frontend Development
For hot reload:
cd web/frontend
npm run dev
The dev server proxies API requests to the running web component.
Testing
Unit Tests
cargo test
Integration Tests
Run the full stack and test manually. Automated integration tests are on the roadmap.
Testing Connectors
- Install the target agent
- Run a node
- Verify fingerprinting
- Test session creation
- Test interception
Pull Requests
Before Submitting
- Code builds without warnings
- Tests pass
- Changes are documented
- Commit messages are clear
PR Process
- Open a PR against
main - Describe the change
- Wait for review
- Address feedback
- Merge when approved
Feature Requests
Open an issue with:
- What you want
- Why it's useful
- Any implementation ideas
Bug Reports
Open an issue with:
- What happened
- What you expected
- Steps to reproduce
- Logs if available
Contact
- Issues: GitHub Issues
- Email: david.kaplan@preludesecurity.com
- Twitter: @depletionmode