Architecture¶
How Ringlet is designed and how its components work together.
Overview¶
Ringlet is a single binary (ringlet) that contains both the CLI client and a background daemon. The daemon manages all persistent state — profiles, agent discovery, usage tracking, and real-time events. The CLI communicates with the daemon over IPC.
┌─────────────────────────────────────────────────────────────────┐
│ User / UI │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ringlet CLI │
│ (Thin client — auto-starts daemon, forwards commands) │
└──────────────────────────────┬──────────────────────────────────┘
│ IPC / HTTP
▼
┌─────────────────────────────────────────────────────────────────┐
│ ringlet daemon │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Profile │ │ Agent │ │ Registry │ │
│ │ Manager │ │ Registry │ │ Client │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Proxy │ │ Usage │ │ Scripting │ │
│ │ Manager │ │ Tracking │ │ Engine │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Terminal │ │ HTTP/WS │ │
│ │ Manager │ │ Server │ │
│ └──────────────┘ └──────────────┘ │
└──────────────────────────────┬──────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Claude Code │ │ Codex CLI │ │ ultrallm │
└─────────────┘ └─────────────┘ │ Proxy │
└─────────────┘
Design Goals¶
- Single entry point — one binary that detects, configures, and manages all supported coding agents
- Profile isolation — every profile has completely separate configuration and state
- Multi-provider support — run the same agent against different API backends
- Centralized state — the daemon is the single source of truth
- Usage tracking — monitor token consumption and costs across all profiles
- Extensibility — add new agents through manifests and scripts, not code changes
Unified Binary¶
Ringlet ships as a single binary. When you run a CLI command, it auto-starts the daemon if one isn't already running. The daemon shuts down after an idle timeout unless pinned with --stay-alive.
# CLI mode — runs a command and exits
ringlet profiles list
# Daemon mode — starts the background service
ringlet daemon --stay-alive --foreground
# The daemon also starts automatically on first CLI use
This eliminates the need for separate binaries or manual daemon management.
Core Components¶
CLI¶
A thin client that:
- Parses commands (
agents list,profiles create,profiles run) - Auto-starts the daemon if not running
- Forwards requests over IPC
- Renders responses as tables or JSON
The CLI never performs stateful operations directly — everything goes through the daemon. For local interactive sessions, the CLI may still spawn the final agent process after the daemon has prepared the execution context, so the process can inherit the user's TTY without duplicating profile-resolution logic.
Daemon¶
The heart of Ringlet. Runs as a long-lived background process and manages:
| Responsibility | Description |
|---|---|
| Profile persistence | Stores and retrieves profile configurations |
| Agent discovery | Detects installed agents and their versions |
| Usage tracking | Tracks tokens, sessions, and costs |
| Event distribution | Publishes changes via WebSocket |
| Proxy management | Spawns and monitors ultrallm instances |
| Terminal sessions | Manages remote PTY sessions with sandboxing |
| HTTP API | Serves REST endpoints and the web UI |
Authenticated loopback HTTP clients are treated as the local user. For workspace-oriented routes, the daemon allows any existing canonicalized local path instead of re-sandboxing access to HOME, which keeps the UI usable with normal repositories stored elsewhere.
Profile Manager¶
Handles the profile lifecycle:
- Creation — validates agent + provider pairing, prompts for API key, runs Rhai script
- Storage — writes profile JSON to
~/.config/ringlet/profiles/ - Execution — creates isolated environment, injects variables, spawns agent
- Tracking — updates
last_usedtimestamps
Agent Registry¶
Loads and manages agent manifests:
- Built-in manifests compiled into the binary
- User manifests from
~/.config/ringlet/agents.d/ - Registry manifests from GitHub
Detection probes run in parallel to find installed agents and their versions.
Scripting Engine¶
Embeds Rhai for configuration generation:
- Receives context (provider, profile, preferences)
- Outputs configuration files, environment variables, and optional extra CLI arguments
- Resolution order: user override → registry → built-in
Hook, MCP, and proxy behavior are expressed by generating the agent's real config files, not by a separate backend assembly path.
Proxy Manager¶
Manages ultrallm proxy instances:
- Spawns processes on dedicated ports
- Generates routing configuration from profile rules
- Monitors health and handles graceful shutdown
- Auto-starts proxies when profiles with proxy enabled run
Terminal Manager¶
Manages remote PTY sessions:
- Creates sandboxed agent processes (bwrap on Linux, sandbox-exec on macOS)
- Streams terminal I/O over WebSocket
- Supports multiple concurrent clients per session
- Maintains scrollback buffer for reconnection
Communication¶
CLI to Daemon¶
The CLI and daemon communicate through IPC:
- Request/Reply — commands serialized via JSON, sent over IPC sockets
- Endpoint —
/tmp/ringlet.sock(Unix) or%LOCALAPPDATA%\ringlet\ringlet.ipc(Windows)
HTTP API¶
For UI integrations:
- REST endpoints at
http://127.0.0.1:8765 - WebSocket at
ws://127.0.0.1:8765/wsfor real-time events - Terminal WebSocket at
ws://127.0.0.1:8765/ws/terminal/{id} - Embedded web UI served at the root path
- Bearer-token authentication from
~/.config/ringlet/http_token - Authenticated workspace routes may access any existing local path, not just
HOME
Profile Isolation¶
Home Wrapper Strategy¶
When a profile runs, Ringlet creates an isolated environment:
Real HOME: /home/user
Profile HOME: /home/user/.claude-profiles/my-project
Environment:
HOME=/home/user/.claude-profiles/my-project
ANTHROPIC_BASE_URL=https://api.anthropic.com
ANTHROPIC_AUTH_TOKEN=sk-...
The agent reads configuration from the profile HOME, ensuring:
- Configuration files are isolated
- Conversation history is separate
- Settings don't leak between profiles
What Gets Isolated¶
| Isolated | Not Isolated |
|---|---|
| Agent config files | System binaries |
| API credentials | Shell configuration |
| Conversation history | Network access |
| Agent settings | File system access |
Sandbox Architecture¶
Remote terminal sessions are sandboxed by default:
┌───────────────────────────────────────────────────┐
│ Host System │
│ ┌─────────────────────────────────────────────┐ │
│ │ Sandbox (bwrap / sandbox-exec) │ │
│ │ ┌───────────────────────────────────────┐ │ │
│ │ │ Agent Process (claude) │ │ │
│ │ │ │ │ │
│ │ │ Read-only: /usr, /bin, /lib, /etc │ │ │
│ │ │ Read-write: ~/, working_dir, /tmp │ │ │
│ │ │ Network: allowed (API access) │ │ │
│ │ └───────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────┘
See Security for full details on sandbox configuration and custom rules.
Data Flow¶
Profile Run¶
1. User: ringlet profiles run my-project
2. CLI:
- Connects to daemon (or starts it)
- Sends run request
3. Daemon:
- Loads profile configuration
- Retrieves API key from keychain
- Creates/validates profile home
- If proxy enabled, starts ultrallm
- Spawns agent process with:
- HOME set to profile home
- Environment variables injected
- CLI arguments forwarded
4. Agent runs with isolated configuration
5. Daemon tracks:
- Session start/end times
- Token usage
- Runtime duration
Persistence Layout¶
~/.config/ringlet/
├── config.toml # User preferences
├── http_token # Daemon auth token
├── agents.d/ # Custom agent manifests
├── providers.d/ # Custom provider manifests
├── scripts/ # Custom Rhai scripts
├── profiles/ # Profile definitions
│ └── my-project.json
├── registry/ # Cached registry data
│ ├── current -> commits/f4a12c3
│ ├── registry.lock
│ └── litellm-pricing.json
├── cache/
│ └── agent-detections.json
├── telemetry/ # Usage data
└── logs/
└── daemon.log
Cross-Platform Support¶
| Platform | Config Path | IPC Endpoint |
|---|---|---|
| macOS | ~/.config/ringlet/ | /tmp/ringlet.sock |
| Linux | ~/.config/ringlet/ or XDG | /tmp/ringlet.sock |
| Windows | %APPDATA%\ringlet\ | %LOCALAPPDATA%\ringlet\ringlet.ipc |