The Problem

AI agents that need to interact with terminal‑based programs (vim, htop, ncurses installers) cannot rely on simple stdin/stdout piping. They require a real PTY, screen rendering, and a way to send keystrokes, all without a graphical display.

What This Does

terminal-use (tu) provides a headless PTY backed by the vt100 emulator and a JSON‑over‑Unix‑socket daemon that manages independent sessions. The CLI (src/main.rs) talks to the daemon, which spawns a PTY (src/pty/spawn.rs) and tracks screen state (src/render/screen.rs). Commands such as tu run, tu monitor, and tu screenshot are implemented in src/commands/*.rs. The daemon’s core logic lives in src/daemon/*, with session.rs handling per‑session PTY I/O, server.rs exposing the socket API, and manager.rs tracking idle time and cleanup.

How It Is Wired

Execution begins in src/main.rs::main (line 267). main parses CLI arguments and dispatches to a command module; for the primary workflow tu run, control passes to src/commands/run.rs::run (line 8).

run first calls ensure_daemon (defined in src/daemon/server.rs::ensure_daemon) up to 12 times, which in turn calls socket_path (5 places) and start_daemon_background (via start). Once the daemon is active, run invokes send_request (7 call sites) to forward the JSON command to the daemon.

On the daemon side, src/daemon/server.rs::handle_connection receives the request and forwards it to src/daemon/manager.rs::handle. The manager creates a new Session (src/daemon/session.rs::new) if needed, then spawns the PTY via src/pty/spawn.rs::spawn. The PTY process lives in PtyProcess, which reads/writes through write_to_pty (called from three places) and reports screen updates back to the manager.

Screen rendering is performed by src/render/screen.rs::from_vt100, called four times from render_screen (which also uses color_to_rgba). Screenshot commands (src/commands/screenshot.rs) ultimately call src/render/image.rs::render, which converts the screen buffer to PNG bytes.

The most connected functions are send_request (7 callers) and socket_path (5 callers); changes to these ripple through the CLI, daemon, and session management. No circular import edges were detected, but deep nesting (max indentation depth 8) appears in list.rs, monitor.rs, and run.rs, making the control flow harder to follow.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/terminal-use
cd terminal-use

# Build from source (Cargo is the package manager)
cargo install --path .

# Run a terminal program in a headless session
tu run --name demo -- cmd_to_run

# Watch the session in a separate terminal
tu monitor --name demo

# Capture a screenshot as PNG
tu screenshot --name demo --png out.png

The binary tu is produced by src/main.rs. No additional configuration files are required; defaults (120×40 size, xterm-256color) are hard‑coded in src/main.rs and src/paths.rs.

Real‑World Use

An AI agent can launch a text‑based game (nethack) via tu run, read the rendered screen with tu screenshot --png, decide on a move, and send the keystroke with tu press --key "h". The daemon automatically cleans up after 8 hours of inactivity, keeping resource usage bounded.

Code Health & Issues

  • HIGH – Pin third‑party GitHub Actions to a commit SHA (.github/workflows/*).
  • HIGH – Upgrade vulnerable dependencies (e.g., tokio@1 CVE‑2021‑45710, regex@1 CVE‑2022‑24713).
  • HIGH – No test suite; 36 source files with zero tests.
  • MEDIUM – Declare least‑privilege GITHUB_TOKEN permissions in CI.
  • MEDIUM – Enable Dependabot or Renovate for automated updates.
  • MEDIUM – Add a dependency‑vulnerability scan step to CI.
  • MEDIUM – Set persist-credentials: false on the checkout action.
  • LOW – Add timeout-minutes to workflow jobs to avoid runaway runs.

Additional observations: the repository includes a LICENSE (MIT) and a lockfile (Cargo.lock), but lacks Docker support and any documentation beyond the README and two markdown files. The codebase shows duplicated 6‑line blocks across seven files, suggesting a DRY opportunity.

The Bottom Line

terminal-use delivers a functional headless PTY solution with a clear CLI and daemon architecture, suitable for embedding in AI agents that need terminal interaction. However, the code suffers from deep nesting, duplicated logic, and a complete lack of automated tests, while critical security hygiene (pinned actions, vulnerable dependencies) needs remediation before production deployment. Engineers should prioritize adding tests, refactoring the heavily nested command modules, and applying the listed health fixes.