Guidance for AI agents working with the purl codebase.
purl is a curl-like CLI for making HTTP requests to payment-gated APIs using the x402 payment protocol. It supports EVM chains (Ethereum, Base, Polygon, etc.) and Solana.
purl/
├── cli/ # CLI application (binary)
│ └── src/
│ ├── main.rs # Entry point
│ ├── cli.rs # Argument parsing (clap)
│ ├── request.rs # HTTP request execution
│ ├── payment.rs # Payment flow orchestration
│ ├── *_commands.rs # Subcommand implementations
│ └── output.rs # Display formatting
├── lib/ # Core library (purl-lib)
│ └── src/
│ ├── client.rs # High-level PurlClient API
│ ├── http.rs # HTTP client wrapper
│ ├── protocol/ # Payment protocol abstraction
│ ├── x402/ # x402 protocol implementation
│ ├── providers/ # Blockchain providers (EVM, Solana)
│ ├── keystore/ # Wallet encryption/storage
│ ├── network.rs # Network definitions
│ └── currency.rs # Token/currency definitions
├── skills/ # AI agent skill definitions
└── Formula/ # Homebrew formula
Trait for implementing payment protocols. Currently only x402 is implemented.
Trait for blockchain-specific payment execution. Implementations:
EvmProvider- Ethereum-compatible chainsSolanaProvider- Solana network
Feature flags control which providers are compiled:
evm- Enables EVM support (default)solana- Enables Solana support (default)
High-level API combining HTTP client, protocol handling, and payment execution.
make build # Debug build
make test # Run tests
make check # Format check + clippy + tests + build
make fmt # Auto-format and fix lints
make release # Release build
make install # Install to ~/.cargo/bin- Run
make fmtbefore committing - All warnings are errors (
-D warningsin clippy) - Use
thiserrorfor error types - Use
remainfor sorted match arms - Prefer
anyhow::Resultin CLI,PurlErrorin library
Tests live alongside source files. Run with cargo test.
Key test files:
lib/src/x402/*.rs- Protocol parsing testslib/src/providers/*.rs- Provider logic testscli/src/inspect_command/*.rs- Command output tests
- Add network definition to
lib/src/network.rsin thenetworks()function - Add currency/token to
lib/src/currency.rsif needed - Ensure the provider (EVM/Solana) supports it
- Create module under
lib/src/(likex402/) - Implement
PaymentProtocoltrait fromlib/src/protocol/mod.rs - Register in
lib/src/protocol/registry.rs
// Library code - use PurlError
use crate::error::{PurlError, Result};
// CLI code - use anyhow for context
use anyhow::{Context, Result};
result.context("failed to parse response")?;#[cfg(feature = "evm")]
pub mod evm;
#[cfg(feature = "solana")]
pub mod solana;The project uses tokio. CLI entry point sets up the runtime:
#[tokio::main]
async fn main() { ... }| File | Purpose |
|---|---|
lib/src/client.rs |
Main API surface |
lib/src/protocol/mod.rs |
Protocol trait definition |
lib/src/payment_provider.rs |
Provider trait definition |
lib/src/x402/protocol.rs |
x402 implementation |
cli/src/cli.rs |
CLI argument definitions |
cli/src/payment.rs |
Payment flow logic |
PURL_PASSWORD- Wallet decryption passwordNO_COLOR- Disable colored outputRUST_LOG- Control log verbosity
User config lives at ~/.purl/config.toml. See purl.toml.example for format.
Keystores are stored in ~/.purl/keystores/.