Status: Proposed Date: 2026-01-15 Author: Claude (with Rand) Context: Design unified library for Claude Code plugin + Agentic TUI
We have two systems implementing RLM (Recursive Language Model) capabilities:
-
recurse - A Go-based agentic TUI extending Charmbracelet Crush with RLM orchestration, tiered hypergraph memory, and embedded reasoning traces
-
rlm-claude-code - A Python-based Claude Code plugin providing RLM orchestration, complexity classification, smart routing, and trajectory streaming
Both systems share significant conceptual overlap but are implemented separately, leading to:
- Duplicated effort for new features
- Feature drift between implementations
- Inconsistent behavior across deployment targets
- Maintenance burden
We will create rlm-core, a unified Rust library with Python (PyO3) and Go (CGO) bindings that provides the foundational RLM capabilities for both deployment targets.
Decision: Core library in Rust with language bindings.
Rationale:
- Performance-critical operations (REPL sandbox, memory queries, trajectory streaming)
- Memory safety for sandboxed execution
- Single implementation serves both targets
- PyO3 provides excellent Python integration
- CGO enables Go integration
Alternatives Rejected:
- Pure Python: Would need rewriting for TUI
- Pure Go: Would need rewriting for Claude Code
- Dual implementation: Maintenance burden, feature drift
Decision: Python REPL as external subprocess with JSON-RPC IPC.
Rationale:
- Process isolation prevents crashes from affecting host
- OS-level resource limits (memory, CPU, time)
- Full Python ecosystem access
- RestrictedPython has limitations for sandboxing
Alternatives Rejected:
- Embedded interpreter: Crash affects host, harder to limit
- WASM Python: Limited ecosystem, performance issues
- Starlark: Limited expressiveness
Decision: Full hypergraph memory with 3-tier evolution, unifying both systems.
Rationale:
- Recurse's hypergraph is more expressive than rlm-claude-code's simpler store
- Tier system (task/session/longterm) works for both contexts
- Evolution operations prevent unbounded growth
- Reasoning traces integrate naturally as memory nodes
- SQLite provides portability
Schema:
nodes(id, type, subtype, content, embedding, tier, confidence, provenance)
hyperedges(id, type, label, weight)
membership(hyperedge_id, node_id, role, position)
Decision: Unified smart router considering query type, recursion depth, and budget.
Rationale:
- Both systems benefit from model tiering
- Query classification helps select appropriate model
- Depth-based routing (Opus → Sonnet → Haiku) optimizes cost
Routing Strategy:
| Query Type | Depth 0 | Depth 1 | Depth 2+ |
|---|---|---|---|
| Architecture | Opus | Sonnet | Sonnet |
| Multi-file | Opus | Sonnet | Haiku |
| Debugging | Sonnet | Haiku | Haiku |
| Extraction | Sonnet | Haiku | Haiku |
| Simple | Haiku | Haiku | Haiku |
Decision: Single event schema, context-specific rendering.
Rationale:
- Same events can render differently per context
- Claude Code: Streaming text output
- TUI: Bubble Tea panel updates
- Both: JSON export for analysis/replay
Event Types:
enum TrajectoryEventType {
RlmStart, Analyze, ReplExec, ReplResult,
Reason, RecurseStart, RecurseEnd,
Final, Error, ToolUse, CostReport
}- Single source of truth for RLM logic
- Consistent behavior across Claude Code and TUI
- Shared improvements benefit both targets
- Reduced maintenance burden
- Better testing - core tested once, adapters tested separately
- FFI complexity - Rust ↔ Python and Rust ↔ Go boundaries
- Build complexity - Multi-language build system
- Migration effort - Both existing systems need updates
- Learning curve - Team needs Rust familiarity
- Performance characteristics will differ between targets due to binding overhead
- Some platform-specific optimizations may be harder
- Phase 1 (2-3 weeks): Core engine - types, REPL, basic orchestration
- Phase 2 (2 weeks): Memory system - hypergraph, tiers, evolution
- Phase 3 (1-2 weeks): LLM client - multi-provider, smart routing
- Phase 4 (1 week): Python bindings via PyO3
- Phase 5 (1 week): Go bindings via CGO
- Phase 6 (2 weeks): Full adapters for both targets