Skip to content

hotl — human on the loop terminal AI agent

It's fast, slim, secure, and extensible — plus a tmux dashboard for every agent you run.

Context that stays slim

The window is spent on your task, not on ceremony — every reduction is deliberate, not incidental:

  • oversized tool results are evicted to files — a preview stays inline, the agent pages the rest back on demand
  • skills are indexed, lazily loaded & searched: what rides on every request is a grouped overview — one line per source, descriptions omitted, large sources collapsed to their first few names plus a count
  • compaction summaries precompute in the background from ~60% full and fold in at ~80% without pausing the session
  • the prompt prefix is byte-stable, so provider caches keep hitting — and a per-turn meter shows how full the window actually is

Configuration → · Skills →

Nothing is ever lost

Sessions are append-only event logs that nothing rewrites:

  • hotl resume picks any session back up where it stopped
  • hotl undo restores the agent’s last clean checkpoint via shadow-git snapshots taken at quiet windows, always off the turn path
  • a long session keeps its thread: compaction folds the middle into a typed digest — goal, state, decisions, files, what’s next — and leaves recent turns verbatim, a summary added on top of history rather than a rewrite of it

Overview →

You own the loop

Steer mid-turn without killing the run — queued steers apply at the next step. And approvals are a vocabulary, not a y/N:

  • allow, allow with an edited input, or answer as the tool yourself
  • deny with a message the model actually reads
  • allow-rules absorb the repetitive asks, so approval fatigue never trains you to say yes
  • walk away entirely: an ask raised while you’re detached from a hotl bg session is parked, not denied, and re-presented the moment you reattach

Permissions → · Background sessions →

tmux-native, out of the box

hotl watch in a pane discovers every AI agent in your tmux session:

  • live status per agent, a ping when one blocks on you, enter jumps focus to its pane
  • Ctrl-h/j/k/l pane navigation composes with vim-tmux-navigator
  • watch’s list speaks j/k/gg/G, and vim hands can switch the console’s input editor to a real modal one — motions, operators, counts, Ctrl-e to $EDITOR ([behavior] vim_mode = true; off by default, because a modal editor ambushes everyone else)

Shell integration →

Goes brrrr

One static binary — no Node, no Python, no runtime to install — and an async policy strict enough to keep it that way:

  • Rule 0: async is for waiting, threads are for working. The tokio runtime only ever hosts tasks blocked on I/O or doing sub-millisecond coordination
  • fan-out is green threads, not OS threads: parallel reads, or thirty spawned sub-agents each with their own context and log, cost a task apiece — bounded by permits, capped at one level of depth, returning only their result
  • every entry point builds a current_thread runtime — nothing pays for thread-pool spinup on the cold-start path that hotl -p and the zsh plugin live on
  • work that genuinely blocks leaves the async path: glob’s tree walk via spawn_blocking (a pool that’s yours to size), shadow-git snapshots on their own dedicated worker thread
  • one actor per session is the sole committer, so there’s no lock order to get wrong: parallel-safe calls overlap, anything that mutates runs alone in source order, and Ctrl-c trips a cancellation token out-of-band rather than queueing behind a full mailbox

Sub-agents → · Concurrency →

Any model, any protocol

HOTL_MODEL=provider/model is the whole model-selection story, and standard protocols sit at the edges:

  • anthropic/… speaks the Messages API — SSE streaming, prompt-cache placement
  • openai/… covers every OpenAI-compatible endpoint: OpenAI, Groq, a local Ollama server, or a gateway like LiteLLM
  • keys come from the environment or a command you name, never from the config file
  • an MCP client (stdio transport) brings in external tools, and hotl acp embeds the agent in any ACP-speaking editor

Gateways → · MCP →

Extend it without forking it

Your own logic at hotl’s seams, all from the one config file:

  • skills and sub-agent types you define yourself — tool scope, model, system prompt. Claude Code’s ~/.claude/skills, ~/.claude/agents, and plugins load in place, no porting
  • six hook events — pre_tool, post_tool, user_prompt, notification, stop, session_end — to block a call, rewrite its input, inject context, or ring a bell. A hook can never grant: crashed, malformed, or timed out is a no-op, not an auto-approval
  • [diagnostics] rs = "cargo check -q" puts your compiler’s output in the tool result for the edit that broke it
  • recall plugs in a search backend for corpora that outgrew grep

Hooks → · Sub-agents →

One config file, fail-closed

Everything hand-editable lives in a single config.toml — no permissions.toml/mcp.toml/hooks.toml sprawl:

  • precedence is always env var > config.toml > default, so CI can override anything without editing the file
  • a malformed file is ignored with a warning, never half-applied
  • a typo’d permission mode fails closed to ask
  • hotl setup writes a commented starter, hotl doctor checks the lot

Configuration →

Security floor that never turns off

Every mutating tool call passes one fixed gate, and what sits under it has no off switch — in any mode:

  • bash runs confined by the kernel: Seatbelt on macOS, Landlock on Linux ≥ 5.13 including WSL2. Writes land in the working directory and temp, nowhere else
  • where the floor can’t be enforced, hotl degrades fail-closed — every exec is individually human-gated with an UNSANDBOXED banner and bash allow-rules stop applying
  • protected paths (git hooks, shell rc, Makefiles, .ssh/, credential stores, agent-instruction files) are checked before allow rules and never auto-approve
  • optional egress restriction is kernel-backed, not proxy-backed: a client that ignores the proxy hits a loopback-only wall
  • secrets are masked at log ingestion, and secret-bearing files never enter the undo snapshot store at all

Stated honestly: this is write-confinement, not exfiltration prevention. Permissions & sandbox →

Building on top of hotl, or pointing an agent at these docs? llms.txt is the machine-readable map.