A high-performance MITM (Man-In-The-Middle) proxy written in Rust — the core infrastructure for feedback loop driven AI-assisted engineering.
Rustyman is not a Rust rewrite of mitmproxy. It is purpose-built infrastructure that enables AI agents to participate in a closed-loop engineering workflow.
In AI-assisted engineering, the AI agent needs to observe real HTTP traffic as feedback to make decisions. Rustyman provides:
- A programmable control plane — REST API for AI agents to configure mock rules, redirect traffic, and rewrite headers at runtime, without human intervention.
- A structured observation channel — SSE real-time event stream (
/api/events) delivers machine-readable traffic events, enabling AI agents to verify whether requests were sent, responses matched expectations, and status codes are correct. - Frictionless automation — Single binary with zero runtime dependencies. CI/CD pipelines and AI-driven test workflows can spin up a proxy instance, run tests, collect feedback, and tear it down with no environment setup.
- Declarative configuration — YAML-based rules that are machine-writable and version-controllable.
AI Agent
│
├──▶ Configure rules (REST API) ← Control plane
├──▶ Trigger tests ← Execution
├──◀ SSE real-time traffic events ← Observation / Feedback
└──▶ Adjust based on feedback ← Closed-loop iteration
mitmproxy is designed for humans — TUI interaction, Python scripting, manual inspection. Rustyman is designed for AI agents as first-class consumers.
- HTTP/HTTPS Proxy with MITM - Intercept and inspect encrypted HTTPS traffic
- REST API - Programmable control plane for automated rule management
- SSE Event Stream - Real-time, machine-readable traffic observation for AI feedback loops
- Map Remote - Redirect requests to different servers using regex patterns
- Map Local - Serve local files for matching requests
- Header Rewrite - Add, remove, or modify HTTP headers with regex support
- YAML Configuration - Declarative, machine-writable configuration format
- Single Binary - Zero runtime dependencies, CI/CD friendly
- Web UI - Real-time traffic monitoring and rule management
- CLI - Command-line interface with logging options
brew tap johnsonlee/rustyman
brew install rustymanDownload pre-built binaries from GitHub Releases.
# macOS/Linux
tar -xzf rustyman-<target>.tar.gz
chmod +x rustyman
./rustyman --helpmacOS users: If you double-clicked to extract and see
Killed: 9, remove the quarantine attribute:xattr -d com.apple.quarantine rustyman
# Clone the repository
git clone https://github.com/johnsonlee/rustyman.git
cd rustyman
# Build release binary
cargo build --release
# The binary will be at target/release/rustyman- Rust 1.75+ (for building from source)
- Start the proxy:
# With default settings (proxy on :8080, web UI on :8081)
rustyman
# With custom ports
rustyman --port 9090 --web-port 9091
# With configuration file
rustyman --config config.yaml-
Configure your browser/system to use the proxy:
- HTTP Proxy:
127.0.0.1:8080 - HTTPS Proxy:
127.0.0.1:8080
- HTTP Proxy:
-
Install the CA certificate:
- Open Web UI at
http://127.0.0.1:8081 - Click "Download CA Cert"
- Install the certificate in your system/browser trust store
- Open Web UI at
-
Browse the web and monitor traffic in the Web UI
rustyman [OPTIONS] [COMMAND]
Options:
-c, --config <FILE> Configuration file path [default: config.yaml]
-H, --host <HOST> Proxy listen address
-p, --port <PORT> Proxy listen port
-w, --web-port <PORT> Web UI port (0 to disable)
-l, --log-level <LEVEL> Log level (trace, debug, info, warn, error) [default: info]
--log-format <FMT> Log format (text, json) [default: text]
--no-mitm Disable HTTPS MITM
--ca-cert <PATH> CA certificate path
--ca-key <PATH> CA private key path
-h, --help Print help
-V, --version Print version
Commands:
init Generate default configuration file
gen-ca Generate CA certificate
export-ca Export CA certificate
Create a config.yaml file (or use rustyman init to generate one):
# Proxy settings
proxy:
host: "127.0.0.1"
port: 8080
mitm_enabled: true
# Web UI
web_ui:
enabled: true
host: "127.0.0.1"
port: 8081
# Map Remote - redirect requests
map_remote:
- name: "api-to-staging"
enabled: true
pattern: "https://api\\.prod\\.com/(.*)"
target: "https://api.staging.com/$1"
preserve_path: false
preserve_query: true
# Map Local - serve local files
map_local:
- name: "mock-api"
enabled: true
pattern: "https://api\\.example\\.com/users"
local_path: "/path/to/mock/users.json"
mime_type: "application/json"
# Header rewrite rules
header_rules:
- name: "add-auth"
enabled: true
url_pattern: "https://api\\.example\\.com/.*"
apply_to_request: true
apply_to_response: false
operations:
- action: add
name: "Authorization"
value: "Bearer token123"See config.example.yaml for a complete example.
Redirect HTTP/HTTPS requests to different servers:
map_remote:
# Simple redirect
- name: "redirect-api"
pattern: "https://api\\.prod\\.com/.*"
target: "https://api.staging.com"
preserve_path: true
preserve_query: true
# With regex capture groups
- name: "version-rewrite"
pattern: "https://api\\.example\\.com/v(\\d+)/(.*)"
target: "https://api.example.com/v2/$2"Serve local files for matching requests:
map_local:
# Single file
- name: "mock-users"
pattern: "https://api\\.example\\.com/users$"
local_path: "/mocks/users.json"
# Directory mapping with capture groups
- name: "local-assets"
pattern: "https://cdn\\.example\\.com/assets/(.*)"
local_path: "/local/assets/$1"Modify HTTP headers with regex support:
header_rules:
# Add header
- name: "add-header"
url_pattern: ".*"
operations:
- action: add
name: "X-Custom-Header"
value: "my-value"
# Remove header
- name: "remove-cookies"
url_pattern: ".*"
operations:
- action: remove
name: "Cookie"
# Remove headers by pattern
- name: "remove-x-headers"
url_pattern: ".*"
operations:
- action: remove
name: "X-*" # Wildcard pattern
# Modify header value with regex
- name: "modify-ua"
url_pattern: ".*"
operations:
- action: modify
name: "User-Agent"
value_pattern: "Chrome/\\d+"
replacement: "Chrome/999"The Web UI provides:
- Traffic View - Real-time request/response monitoring with search
- Rules Management - Add/edit Map Remote, Map Local, and Header rules
- Settings - View proxy configuration and statistics
- CA Certificate Download - Easy certificate export
Access at http://127.0.0.1:8081 (default)
The Web UI exposes a REST API:
| Endpoint | Method | Description |
|---|---|---|
/api/traffic |
GET | List traffic entries |
/api/traffic/:id |
GET | Get single traffic entry |
/api/traffic/clear |
POST | Clear all traffic |
/api/traffic/search?q= |
GET | Search traffic by URL |
/api/config |
GET/POST | Get/update configuration |
/api/rules/map-remote |
GET/POST | Get/add map remote rules |
/api/rules/map-local |
GET/POST | Get/add map local rules |
/api/rules/header |
GET/POST | Get/add header rules |
/api/rules/reload |
POST | Reload rules from config |
/api/ca/cert |
GET | Download CA certificate |
/api/stats |
GET | Get proxy statistics |
/api/events |
SSE | Real-time traffic event stream |
The /api/events endpoint provides Server-Sent Events (SSE) for real-time traffic monitoring:
# Stream all traffic events
curl -N http://localhost:8081/api/events
# Parse events with jq
curl -N http://localhost:8081/api/events | grep "^data:" | cut -c6- | jq .Event Types:
request- New HTTP request receivedresponse- Response received from servercompleted- Request/response cycle completecleared- Traffic log cleared
Example Event:
{"event":"completed","data":{"id":"uuid","request":{"method":"GET","url":"https://example.com"},"response":{"status":200}}}Multiple clients can connect simultaneously - each receives the full event stream.
# Export the certificate
rustyman export-ca -o rustyman-ca.crt
# Add to system keychain
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rustyman-ca.crt# Export the certificate
rustyman export-ca -o rustyman-ca.crt
# Install
sudo cp rustyman-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates- Export the certificate:
rustyman export-ca -o rustyman-ca.crt - Double-click the .crt file
- Click "Install Certificate"
- Select "Local Machine" → "Place all certificates in the following store"
- Browse → "Trusted Root Certification Authorities"
- Finish the wizard
Firefox uses its own certificate store:
- Open Firefox Settings → Privacy & Security → Certificates → View Certificates
- Import the CA certificate
- Check "Trust this CA to identify websites"
┌─────────────┐ ┌─────────────────────────────────────┐ ┌─────────────┐
│ Client │────────▶│ Proxy (:8080) │────────▶│ Server │
│ (Browser) │◀────────│ HTTP/HTTPS MITM Handler │◀────────│ (Target) │
└─────────────┘ └─────────────────┬───────────────────┘ └─────────────┘
│
▼
┌─────────────────────────────────────┐
│ Traffic Store │
│ (broadcast channel) │
└─────────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Axum Server (:8081) │
├─────────────────┬───────────────────┤
│ Static Files │ API Endpoints │
│ /index.html │ /api/events │
│ /static/* │ /api/traffic │
│ │ /api/rules/* │
└────────┬────────┴─────────┬─────────┘
│ │
┌──────────────────┴──────────────────┴──────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Browser │ │ AI Agent │ │ CI / CD │
└───────────┘ │ (primary) │ │ Pipeline │
└───────────┘ └───────────┘
# Run in development mode
cargo run
# Run tests
cargo test
# Format code
cargo fmt
# Run clippy lints
cargo clippyMIT License - see LICENSE for details.
Contributions are welcome! Please feel free to submit issues and pull requests.