All skills
Skillintermediate
ralph-proto
Protocol types shared across all Ralph crates.
Claude Code Knowledge Pack7/10/2026
Overview
ralph-proto
Protocol types shared across all Ralph crates.
Overview
ralph-proto defines the core data structures used throughout Ralph:
- Events and Topics for communication
- Hats for persona definitions
- EventBus for routing
Key Types
Event
A message with topic, payload, and routing information.
pub struct Event {
pub topic: Topic,
pub payload: Option,
pub source_hat: Option,
pub target_hat: Option,
pub timestamp: DateTime,
}
Creating events:
use ralph_proto::Event;
// Simple event
let event = Event::new("build.done");
// With payload
let event = Event::new("build.done")
.with_payload("tests: pass, lint: pass, typecheck: pass, audit: pass, coverage: pass");
// With source hat
let event = Event::new("build.done")
.from_hat("builder");
Topic
Event routing with glob pattern matching.
pub struct Topic(String);
impl Topic {
pub fn matches(&self, pattern: &str) -> bool;
}
Pattern matching:
let topic = Topic::new("build.done");
topic.matches("build.done"); // true
topic.matches("build.*"); // true
topic.matches("*.done"); // true
topic.matches("test.*"); // false
Hat
A specialized Ralph persona.
pub struct Hat {
pub id: HatId,
pub name: String,
pub description: Option,
pub triggers: Vec, // Subscription patterns
pub publishes: Vec, // Allowed event types
pub default_publishes: Option,
pub instructions: String,
pub backend: Option,
pub max_activations: Option<usize>,
}
Creating hats:
use ralph_proto::Hat;
let hat = Hat::builder("builder")
.name("Builder")
.triggers(vec!["task.start", "plan.ready"])
.publishes(vec!["build.done", "build.failed"])
.instructions("Implement the task...")
.build();
HatId
Unique identifier for a hat.
pub struct HatId(String);
impl HatId {
pub fn new(id: impl Into) -> Self;
}
EventBus
Registry of hats and event routing.
pub struct EventBus {
hats: HashMap<HatId, Hat>,
pending_events: VecDeque,
event_history: Vec,
}
impl EventBus {
pub fn register_hat(&mut self, hat: Hat);
pub fn publish(&mut self, event: Event);
pub fn next_event(&mut self) -> Option;
pub fn matching_hat(&self, event: &Event) -> Option<&Hat>;
}
Using EventBus:
use ralph_proto::{EventBus, Event, Hat};
let mut bus = EventBus::new();
// Register hats
bus.register_hat(planner_hat);
bus.register_hat(builder_hat);
// Publish events
bus.publish(Event::new("task.start"));
// Get next event and matching hat
if let Some(event) = bus.next_event() {
if let Some(hat) = bus.matching_hat(&event) {
// Execute hat with event
}
}
UX Events
Events for TUI interaction.
pub enum UxEvent {
TerminalWrite(String),
Resize { width: u16, height: u16 },
FrameCapture(Vec<u8>),
}
Error Types
pub enum ProtoError {
InvalidTopic(String),
InvalidHat(String),
EventRoutingError(String),
}
Feature Flags
| Flag | Description |
|---|---|
default | Standard features |
serde | Serialization support |
Example: Event Flow
use ralph_proto::{EventBus, Event, Hat};
// Setup
let mut bus = EventBus::new();
let planner = Hat::builder("planner")
.triggers(vec!["task.start"])
.publishes(vec!["plan.ready"])
.instructions("Create a plan")
.build();
let builder = Hat::builder("builder")
.triggers(vec!["plan.ready"])
.publishes(vec!["build.done"])
.instructions("Implement the plan")
.build();
bus.register_hat(planner);
bus.register_hat(builder);
// Start flow
bus.publish(Event::new("task.start"));
// First event matches planner
let event = bus.next_event().unwrap();
let hat = bus.matching_hat(&event).unwrap();
assert_eq!(hat.id.as_str(), "planner");
// Planner publishes plan.ready
bus.publish(Event::new("plan.ready").from_hat("planner"));
// Second event matches builder
let event = bus.next_event().unwrap();
let hat = bus.matching_hat(&event).unwrap();
assert_eq!(hat.id.as_str(), "builder");