frankenterm

frankenterm

Terminal hypervisor for AI agent swarms: real-time pane capture, state-machine pattern detection, and a JSON API for coordinating fleets of coding agents across WezTerm

Stars: 57

Visit
 screenshot

A swarm-native terminal platform designed to replace legacy terminal workflows for massive AI agent orchestration. `ft` is a full terminal platform for agent swarms with first-class observability, deterministic eventing, policy-gated automation, and machine-native control surfaces. It offers perfect observability, intelligent detection, event-driven automation, Robot Mode API, lexical + hybrid search, and a policy engine for safe multi-agent control. The platform is actively expanding with concepts learned from Ghostty and Zellij, purpose-built subsystems for agent swarms, and integrations from other projects like `/dp/asupersync`, `/dp/frankensqlite`, and `/frankentui`.

README:

ft — FrankenTerm

ft - Swarm-Native Terminal Platform for AI Agent Fleets

CI License: MIT+Rider Rust

A swarm-native terminal platform designed to replace legacy terminal workflows for massive AI agent orchestration.

Quick Install

cargo install --git https://github.com/Dicklesworthstone/frankenterm.git ft

TL;DR

The Problem: Running large AI coding swarms across ad-hoc terminal panes is chaos. You can't reliably observe state, detect rate limits or auth failures, coordinate handoffs, or automate safe recovery without brittle glue code.

The Solution: ft is a full terminal platform for agent swarms — with first-class observability, deterministic eventing, policy-gated automation, and machine-native control surfaces (Robot Mode + MCP). Existing WezTerm integration is a migration bridge, not the product boundary.

Platform Direction

ft is developed as a replacement-class terminal runtime for multi-agent systems, not a thin wrapper around another terminal. The architecture is actively expanding with:

  • Concepts learned from Ghostty and Zellij (session model, ergonomics, and runtime resilience)
  • Ground-up ft subsystems purpose-built for agent swarms
  • Targeted integrations and code adaptation from /dp/asupersync, /dp/frankensqlite, and /frankentui

Why Use ft?

Feature What It Does
Perfect Observability Captures all terminal output across all panes with delta extraction (<50ms lag)
Intelligent Detection Multi-agent pattern engine detects rate limits, errors, prompts, completions
Event-Driven Automation Workflows trigger on patterns — no sleep loops or polling heuristics
Robot Mode API JSON interface optimized for AI agents to control other AI agents
Lexical + Hybrid Search FTS5 lexical search plus semantic/hybrid retrieval modes across captured output
Policy Engine Capability gates, rate limiting, audit trails for safe multi-agent control

Quick Example

# Start the ft watcher/runtime
$ ft watch

# See all active panes as JSON
$ ft robot state
{
  "ok": true,
  "data": {
    "panes": [
      {"pane_id": 0, "title": "claude-code", "domain": "local", "cwd": "/project"},
      {"pane_id": 1, "title": "codex", "domain": "local", "cwd": "/project"}
    ]
  }
}

# Compact TOON output (token-optimized)
$ ft robot --format toon state

# Token stats (printed to stderr so stdout stays data-only)
$ ft robot --format toon --stats state

# Get recent output from a specific pane
$ ft robot get-text 0 --tail 50

# Wait for a specific pattern (e.g., agent hitting rate limit)
$ ft robot wait-for 0 "core.codex:usage_reached" --timeout-secs 3600

# Search all captured output (lexical default)
$ ft robot search "error: compilation failed"

# Semantic/hybrid search mode
$ ft robot search "error: compilation failed" --mode hybrid

# Send input to a pane (with policy checks)
$ ft robot send 1 "/compact"

# View recent detection events
$ ft robot events --limit 10

Read/query interfaces (ft get-text, ft search, ft robot get-text, ft robot search, and MCP wa.get_text / wa.search) are policy-evaluated and redact secret material in returned text/snippets.


Design Philosophy

1. Passive-First Architecture

The observation loop (discovery, capture, pattern detection) has no side effects. It only reads and stores. The action loop (sending input, running workflows) is strictly separated with explicit policy gates.

2. Event-Driven, Not Time-Based

No sleep(5) loops hoping the agent is ready. Every wait is condition-based: wait for a pattern match, wait for pane idle, wait for an external signal. Deterministic, not probabilistic.

3. Delta Extraction Over Full Capture

Instead of repeatedly capturing entire scrollback buffers, ft uses 4KB overlap matching to extract only new content. Efficient storage, minimal latency, explicit gap markers for discontinuities.

4. Single-Writer Integrity

A watcher lock ensures only one watcher can write to the database. No corruption from concurrent mutations. Graceful fallback for read-only introspection.

5. Agent-First Interface

Robot Mode returns structured JSON with consistent schemas. Every response includes ok, data, error, elapsed_ms, and version. Designed for machines to parse, not humans to read.

Safety Guarantees

  • Observe vs act split: ft watch is read-only; mutating actions must pass the Policy Engine.
  • No silent gaps: capture gaps are recorded explicitly and surfaced in events/diagnostics.
  • Policy-gated sending: ft send and workflows enforce prompt/alt-screen checks, rate limits, and approvals.
  • Policy-gated reads: get-text/search surfaces enforce policy checks and return redacted text payloads.

Secure Distributed Mode

Secure distributed mode is available as an optional feature-gated build and is off by default.

# Build ft with distributed mode support
cargo build -p frankenterm --release --features distributed

Operator guidance:

  • Keep distributed.bind_addr on loopback unless you explicitly need remote access.
  • For non-loopback binds, enable TLS and use file/env token sources (avoid inline tokens).
  • Use ft doctor (or ft doctor --json) to verify effective distributed security status.
  • Follow docs/distributed-security-spec.md for setup, rotation, and troubleshooting.

How ft Compares

Feature ft WezTerm Zellij Ghostty
Swarm-native orchestration First-class External glue required External glue required External glue required
Event-driven automation Built-in workflows + policy gate Not native Not native Not native
Machine API for agents Robot Mode + MCP No equivalent No equivalent No equivalent
Cross-session state + recovery Built-in snapshots/sessions Partial/manual Session-centric, not swarm-centric Minimal
Agent-safe control plane Capability/risk/approval/audit Not native Not native Not native
Backend extensibility Explicit platform direction Terminal app only Terminal app only Terminal app only

When to use ft:

  • Running 2+ AI coding agents that need coordination
  • Building automation that reacts to terminal output
  • Debugging multi-agent workflows with full observability

When ft might not be ideal:

  • Single shell/single-agent usage where orchestration is unnecessary
  • Environments that only need a lightweight interactive terminal and no swarm control plane

Installation

From Source (Recommended)

# Clone and build
git clone https://github.com/Dicklesworthstone/frankenterm.git
cd frankenterm
cargo build --release

# Install to PATH
cp target/release/ft ~/.local/bin/

Via Cargo

cargo install --git https://github.com/Dicklesworthstone/frankenterm.git ft

Requirements

  • Rust 1.85+ (nightly required for Rust 2024 edition)
  • Compatibility backend bridge (current): WezTerm CLI available for existing pane/session interop while native runtime coverage expands
  • SQLite (bundled via rusqlite)

Quick Start

1. Run Setup (recommended)

# Guided setup (generates config snippets and shell hooks)
ft setup

# Bundled Pragmasevka Nerd Font auto-installs on normal ft usage
# (no `ft setup font --apply` required), and generated wezterm config
# defaults to it automatically.

# Manual install / reinstall path:
ft setup font --apply

# Opt out of automatic font install for this invocation:
FT_SKIP_BUNDLED_FONT_INSTALL=1 ft status

2. Verify Terminal Backend Connectivity

# Compatibility backend check (current migration path)
wezterm cli list

3. Start the Watcher

# Start observing all panes
ft watch

# Or run in foreground for debugging
ft -v watch --foreground

4. Check Status

# See what ft is observing
ft status

# Robot mode for JSON output
ft robot state

5. Search Captured Output

# Full-text search across all panes (alias: `ft query`)
ft search "error"
ft query "error"

# Events feed (recent detections)
ft events

# Annotate/triage events
ft events annotate 123 --note "Investigating"
ft events triage 123 --state investigating
ft events label 123 --add urgent

# Robot mode with structured results
ft robot search "compilation failed" --limit 20

6. React to Events

# Wait for an agent to hit its rate limit
ft robot wait-for 0 "core.codex:usage_reached"

# Then send a command to handle it
ft robot send 0 "/compact"

Commands

Watcher Management

ft watch                     # Start watcher in background
ft watch --foreground        # Run in foreground
ft watch --auto-handle       # Enable auto workflows
ft stop                      # Stop running watcher

Pane Inspection

ft status                    # Overview of observed panes
ft show <pane_id>           # Detailed pane info
ft get-text <pane_id>       # Recent output from pane

Pane Actions

ft send <pane_id> "<text>"                 # Send input (policy-gated)
ft send <pane_id> "<text>" --dry-run       # Preview without executing
ft send <pane_id> "<text>" --wait-for "ok" # Verify via wait-for
ft send <pane_id> "<text>" --no-paste --no-newline

Search

ft search "<query>"          # Full-text search
ft search "<query>" --pane 0 # Scope to specific pane
ft search "<query>" --limit 50

Explainability

ft why --list                # List available explanation templates
ft why deny.alt_screen       # Explain a common policy denial

Workflows

ft workflow list                         # List available workflows
ft workflow run handle_usage_limits --pane 0
ft workflow run handle_usage_limits --pane 0 --dry-run
ft workflow status <execution_id> -v

Rules

ft rules list                            # List detection rules
ft rules test "Usage limit reached"      # Test text against rules
ft rules show codex.usage_reached        # Show rule details

Audit & Approvals

ft approve AB12CD34 --dry-run            # Check approval status
ft audit --limit 50 --pane 3             # Filter audit history
ft audit --decision deny                 # Only denied decisions

Diagnostics

ft triage                               # Summarize issues (health/crashes/events)
ft diag bundle --output /tmp/ft-diag    # Collect diagnostic bundle
ft reproduce --kind crash               # Export latest crash bundle

Robot Mode (JSON API)

Use --format toon for token-efficient output and ft robot help for the full command list.

ft robot state               # All panes as JSON
ft robot state --include-text --tail 20  # Pane metadata + per-pane tail output
ft robot get-text <id> --tail 50      # Single pane output as JSON
ft robot get-text --panes 0,1,2 --tail 20  # Batch pane output in one call
ft robot get-text --all --tail 10     # Batch all active panes in one call
ft robot send <id> "<text>" # Send input (with policy)
ft robot send <id> "<text>" --dry-run  # Preview without executing
ft robot wait-for <id> <rule_id>       # Wait for pattern
ft robot search "<query>" --mode <lexical|semantic|hybrid>  # Structured search
ft robot events             # Recent detection events
ft robot help               # List all robot commands

MCP (Model Context Protocol)

# Build with MCP feature enabled
cargo build --release --features mcp

# Start MCP server over stdio
ft mcp serve

MCP mirrors robot mode. See docs/mcp-api-spec.md for the tool list and docs/json-schema/ for response schemas. For multi-agent operating procedures, see docs/swarm-playbook.md.

Configuration

ft config show               # Display current config
ft config validate           # Check config syntax
ft config reload             # Hot-reload config (SIGHUP)

For the full command matrix (human + robot + MCP), see docs/cli-reference.md.


Configuration

Configuration lives in ~/.config/ft/ft.toml:

[general]
# Logging level: trace, debug, info, warn, error
log_level = "info"
# Output format: pretty (human) or json (machine)
log_format = "pretty"
# Data directory for database and locks
data_dir = "~/.local/share/ft"

[ingest]
# How often to poll panes for new content (milliseconds)
poll_interval_ms = 200
# Filter which panes to observe
[ingest.panes]
include = []  # Empty = all panes
exclude = ["*htop*", "*vim*"]  # Glob patterns

# Pane priority overrides (lower number = higher priority)
[ingest.priorities]
default_priority = 100

[[ingest.priorities.rules]]
id = "critical_codex"
priority = 10
title = "codex"

[[ingest.priorities.rules]]
id = "deprioritize_ssh"
priority = 200
domain = "SSH:*"

# Capture budgets (0 = unlimited)
[ingest.budgets]
max_captures_per_sec = 0
max_bytes_per_sec = 0

[storage]
# Write queue size for batched inserts
writer_queue_size = 100
# How long to retain captured output
retention_days = 30

[vendored]
# Optional explicit socket for single-backend mux access
mux_socket_path = "~/.local/share/wezterm/default.sock"

[vendored.mux_pool]
# Connection pool tuning for direct mux RPC
max_connections = 64
idle_timeout_seconds = 60
acquire_timeout_seconds = 10
pipeline_depth = 32
pipeline_timeout_ms = 5000
compression = "auto"

[vendored.sharding]
# Multi-socket sharding mode (requires 2+ socket_paths when enabled)
enabled = false
socket_paths = ["/tmp/ft-shard-0.sock", "/tmp/ft-shard-1.sock"]
# Assignment strategy tag: round_robin | by_domain | by_agent_type | manual | consistent_hash
assignment = { strategy = "round_robin" }

[backup.scheduled]
# Enable scheduled backups
enabled = false
# Schedule: hourly, daily, weekly, or 5-field cron
schedule = "daily"
# Retention policy
retention_days = 30
max_backups = 10
# Optional destination root
destination = "~/.local/share/ft/backups"
# Optional tweaks
compress = false
metadata_only = false
# Notifications
notify_on_failure = true
notify_on_success = false

[sync]
# Feature gate
enabled = false
# Require confirmation for any write
require_confirmation = true
# Default overwrite policy
allow_overwrite = false
# Payload toggles (global defaults)
allow_binary = false
allow_config = true
allow_snapshots = true
# Optional allow/deny path globs
allow_paths = []
deny_paths = ["~/.local/share/ft/ft.db", "~/.local/share/ft/ft.db-wal", "~/.local/share/ft/ft.db-shm"]

[[sync.targets]]
name = "staging"
transport = "ssh"
endpoint = "ft@staging-host"
root = "~/.local/share/ft/sync"
default_direction = "push"

[patterns]
# Which detection packs to enable
packs = ["core"]
# Core pack detects: Claude Code, Codex, Gemini state transitions

[workflows]
# Enable automatic workflow execution on pattern matches
enabled = true
# Maximum concurrent workflows
concurrency = 10

[safety]
# Require approval for actions on new hosts
approve_new_hosts = true
# Redact sensitive patterns (API keys, tokens) in logs
redact_secrets = true
# Rate limits per action type
[safety.rate_limits]
send_text = { max_per_second = 2 }

Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                         ft Swarm Runtime Core                           │
│   Session Graph │ Pane Registry │ State Store │ Control Plane          │
└─────────────────────────────────────────────────────────────────────────┘
                                   │
                    Backend Adapters + Runtime Integrations
                                   ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                      Ingest + Normalization Pipeline                     │
│   Discovery → Delta Extraction → Fingerprinting → Observation Filter    │
└─────────────────────────────────────────────────────────────────────────┘
                                   │
                                   ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                         Storage Layer (SQLite + FTS5)                   │
│   output_segments │ events │ workflow_executions │ audit_actions        │
└─────────────────────────────────────────────────────────────────────────┘
                                   │
                    ┌──────────────┼──────────────┐
                    ▼              ▼              ▼
             ┌───────────┐  ┌───────────┐  ┌───────────┐
             │  Pattern  │  │   Event   │  │  Workflow │
             │  Engine   │  │    Bus    │  │  Engine   │
             │ (detect)  │  │ (fanout)  │  │ (execute) │
             └───────────┘  └───────────┘  └───────────┘
                    │              │              │
                    └──────────────┼──────────────┘
                                   ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                         Policy Engine                                    │
│   Capability Gates │ Rate Limiting │ Audit Trail │ Approval Tokens      │
└─────────────────────────────────────────────────────────────────────────┘
                                   │
                                   ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                 Robot Mode API + MCP + Platform Interfaces               │
│   ft robot state │ get-text │ send │ wait-for │ search │ events         │
│   ft mcp serve (feature-gated, stdio transport)                          │
└─────────────────────────────────────────────────────────────────────────┘

For a deeper architecture writeup (OSC 133 prompt markers, gap semantics, library map), see docs/architecture.md.

Data Flow

  1. Discovery: Enumerate pane/session resources via active backend adapters
  2. Capture: Stream output and state deltas from adapters/runtime hooks
  3. Delta: Compare with previous capture using 4KB overlap matching
  4. Store: Append new segments to SQLite with FTS5 indexing
  5. Detect: Run pattern engine against new content
  6. Event: Broadcast detections to event bus subscribers
  7. Workflow: Execute registered workflows on matching events
  8. Policy: Gate all actions through capability and rate limit checks
  9. API: Expose everything via Robot Mode JSON interface

Pattern Detection

ft detects state transitions across multiple AI coding agents:

Agent Pattern Examples
Codex core.codex:usage_reached, core.codex:compaction_complete
Claude Code core.claude:rate_limited, core.claude:approval_needed
Gemini core.gemini:quota_exceeded, core.gemini:error
Terminal Runtime core.wezterm:pane_closed, core.wezterm:title_changed

Pattern IDs

Every detection has a stable rule_id like core.codex:usage_reached. Use these in:

  • ft robot wait-for <pane_id> <rule_id> — wait for specific condition
  • Workflow triggers — automatically react to patterns
  • Allowlists — suppress false positives

Performance Benchmarks

Benchmarks live under crates/frankenterm-core/benches/ and use Criterion. Each bench includes a short, human-readable budget and emits machine-readable artifacts under target/criterion/.

# Compile benches (fast sanity check)
cargo bench -p frankenterm-core --benches --no-run

# Run a specific bench
cargo bench -p frankenterm-core --bench pattern_detection
cargo bench -p frankenterm-core --bench delta_extraction
cargo bench -p frankenterm-core --bench fts_query

When a bench runs, it prints a [BENCH] {...} metadata line and writes:

  • target/criterion/ft-bench-meta.jsonl (budgets + environment)
  • target/criterion/ft-bench-manifest-<bench>.json (artifact manifest)

Troubleshooting

For a step-by-step operator guide (triage → why → reproduce), see docs/operator-playbook.md.

Compatibility backend returns empty pane list

# Ensure compatibility backend is up
wezterm start --always-new-process

Daemon won't start: "watcher lock held"

Another ft watcher is already running.

# Check for existing watcher
ft status

# Force stop if stuck
ft stop --force

# Or remove stale lock
rm ~/.local/share/ft/watcher.lock

High memory usage

Delta extraction is failing; falling back to full captures.

# Check for gaps in capture
ft robot events --event-type gap

# Reduce poll interval
# In ft.toml:
[ingest]
poll_interval_ms = 500  # Slower polling

Pattern not detecting

# Enable debug logging
ft -vv watch --foreground

# Test pattern manually
ft rules test "Usage limit reached. Try again later."

Robot mode returns errors

# Check watcher is running
ft status

# Verify pane exists
ft robot state

# Compatibility backend sanity check
wezterm cli list

# Check policy blocks
ft robot send 0 "test" --dry-run

Limitations

What ft Doesn't Do (Yet)

  • Complete backend independence: Compatibility bridge still leans on WezTerm in current builds.
  • Unified UX parity across all target backends: Active migration area.
  • GUI interaction: Core focus is terminal/state orchestration, not arbitrary GUI automation.
  • Production-grade multi-host federation: Distributed mode exists, but hardening is still ongoing.

Known Limitations

Capability Current State Planned
Backend decoupling from compatibility bridge In progress Ongoing
Browser automation (OAuth) Feature-gated, partial v0.2+
MCP server integration Feature-gated (stdio) v0.2+
Web dashboard Feature-gated (health-only) v0.3+
Multi-host federation Early distributed mode v2.0+

FAQ

Why "ft"?

FrankenTerm. Short, typeable, memorable.

Is my terminal output stored permanently?

By default, output is retained for 30 days (configurable via storage.retention_days). Data is stored locally in SQLite at ~/.local/share/ft/ft.db.

Does ft send data anywhere?

Default mode is local-first: no telemetry and no cloud dependency. Network activity only occurs when you explicitly enable integrations like webhooks, SMTP email alerts, or distributed mode.

Can I use ft without running AI agents?

Yes. The pattern detection and search work for any terminal output. Useful for debugging, auditing, or building custom automation.

How do I add custom patterns?

Edit ~/.config/ft/patterns.toml:

[[patterns]]
id = "custom:my_error"
pattern = "FATAL ERROR:.*"
severity = "critical"

What's the performance overhead?

  • CPU: <1% during idle; brief spikes during pattern detection
  • Memory: ~50MB for watcher with 100 panes
  • Disk: ~10MB/day for typical multi-agent usage (compressed deltas)
  • Latency: <50ms average capture lag

About Contributions

Please don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via gh and independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.


License

MIT License (with OpenAI/Anthropic Rider). See LICENSE for details.


Built to be the terminal runtime for the AI agent age.

For Tasks:

Click tags to check more tools for each tasks

For Jobs:

Alternative AI tools for frankenterm

Similar Open Source Tools

For similar tasks

For similar jobs