tmux-ide

repository·main·Indexed 19 days ago

https://github.com/wavyrai/tmux-ide

A terminal enhancement tool (v2.8.0) that transforms projects into tmux-powered IDEs using .tmux-ide/workspace.yml. It adds an agent-aware UI layer to tmux sessions, providing live status tracking, multi-agent coordination, and crash-proof session restoration. The system consists of a background daemon (@tmux-ide/daemon) providing a WebSocket PTY bridge, a SolidJS/Vite desktop renderer (@tmux-ide/desktop-renderer), and a thin Electron shell (@tmux-ide/electron-shell) for OS hosting.

Tokens
54.9K
Snippets
165
Records
249
Agent score
67%

What's inside tmux-ide

  1. Overview of the tmux-ide unified server

    main

    The tmux-ide server (v2.5.0+) is a unified single-binary service providing both HTTP and WebSocket (WS) surfaces. Its primary role is to act as a bridge between the terminal environment and the browser-based desktop renderer.

    Key capabilities include:

    • WebSocket PTY Bridge: Provides a PTY (Pseudo-Terminal) endpoint at /ws/pty/:id.
    • Shell Spawning: Uses node-pty to spawn shells.
    • Terminal Bridging: Bridges the spawned shell to wterm in the browser.

    For detailed technical specifications on the communication format, refer to the v2.5.0-protocol.md and v2.5.0-architecture.md design documents in the repository.

  2. Understand the tmux-ide architecture

    main

    tmux-ide is a CLI tool that transforms any project into a tmux-powered terminal IDE combined with a single-page web dashboard.

    It operates using a long-lived daemon built with Node.js, Effect, and Hono. This daemon supports two primary user interfaces:

    1. A Solid SPA dashboard: A web-based interface for high-fidelity interaction.
    2. TUI widgets: Terminal User Interface components rendered directly inside tmux panes.

    The architecture follows the opencode model, utilizing Solid.js for UI and the Effect ecosystem for core logic, async services, and dependency injection.

  3. Using the Bottom Workbench Dock

    main

    The dock is a persistent home for project tools, separate from terminal rows. It contains three functional groups:

    1. + New: For creating new Terminals and Agents using the typed create-pane flow.
    2. Surface Tabs: Navigation between Files, Changes, Missions, and Activity.
    3. Dock Actions: Controls for collapse/restore and maximize/restore.

    Dock Behavior:

    • Persistence: Open height and the last active tab are persisted per project.
    • Interaction: Selecting an active tab while the dock is open collapses it. Selecting a tab while collapsed opens it. Maximize is a separate toggle.
    • Navigation: Use Left/Right/Home/End for roving tab focus. Enter or Space activates a tab.
    • Lifecycle: Inactive tools retain selection, scroll, and draft state. They only stop background work through an explicit surface lifecycle contract.
  4. Terminal Attachment Lifecycle and Security

    main

    Terminal attachments follow a strict multi-step lifecycle to ensure security and resource management:

    1. Issue: The Electron main process calls issueTerminalAttachment(...). The daemon authenticates this request using a durable credential and issues a mode-bound, expiring ticket.
    2. Redemption: The renderer uses the ticket and the daemon URL to redeem the attachment. This must happen within a 1,000 ms deadline.
    3. Connection: Once redeemed, a direct WebSocket connection is established. The first frame is limited to 4 KiB to prevent flood attacks.
    4. Cleanup: Each attachment creates an ephemeral tmux view. Strict cleanup is required to manage capacity limits.

    Security Constraints:

    • Single-use: Tickets are one-time use and expire quickly.
    • Origin Validation: The daemon enforces exact Origin checks, CSP, and subprotocol matching during redemption.
    • Redaction: Logs, snapshots, and crash reports must redact sensitive ticket and credential information.
  5. Using the Command Palette

    main

    The command palette acts as the product's command and resource router. It is a unified registry consumed by both DOM (Desktop) and OpenTUI (Terminal) hosts.

    Features:

    • Searchable Resources: Includes commands, workspaces, sessions, agents, panes, files, and settings (only when capabilities are available).
    • Ranking: Uses normalized prefix, word-boundary, subsequence, recency, and context signals to ensure consistent ordering across hosts.
    • Navigation: Up/Down/Home/End to navigate; Enter to run the primary action; Escape to close.
    • Scope: While the palette is open, global surface shortcuts and PTY forwarding are suspended.
    • Safety: Searching raw terminal output is an explicit command with explicit scope; the palette does not silently index PTY contents.
  6. Understand the tmux-ide product architecture and authority

    main

    tmux-ide is designed as a single terminal-native product with two hosts: a TUI (OpenTUI/Solid) and a Desktop application (Solid/Electron).

    The Core Authority: tmux is the sole authority for terminals, processes, topology, and terminal history. The tmux-ide daemon manages typed resources and descriptors, acting as the bridge between the user and the tmux server.

    Key Architectural Constraints:

    • No Synthetic Panes: All terminal surfaces (including agent harnesses) are views onto real tmux panes. Native app surfaces like Files, Changes, Missions, and Activity are never synthetic tmux panes.
    • Renderer Isolation: Renderers (Desktop/TUI) cannot spawn PTYs, invent pane identities, or author terminal commands. They only receive semantic pane identities issued by the daemon.
    • Secure Terminal Streaming: The Electron host issues a short-lived, single-use attachment descriptor to the renderer. The renderer then streams bytes directly to the daemon. The Electron main process never proxies terminal input, output, or lifecycle events.
    • State Resolution: While the app layout describes how panes are presented, terminal existence, command execution, and scrollback always resolve back to tmux.
  7. Understand the terminal attachment lifecycle

    main

    The tmux-ide terminal attachment process follows a strict security and lifecycle model to ensure that terminal bytes flow directly between the renderer and the daemon without being proxied by the Electron main process.

    1. Issue: The Electron host calls the daemon's issue endpoint. This is a privilege transition that requests a terminal attachment. The daemon validates the request and returns an Attachment Descriptor.
    2. Upgrade: The renderer uses the descriptor to initiate a WebSocket connection to the daemon. This requires a specific path (/v1/terminal/attachments/redeem) and subprotocol (tmux-ide-terminal.v1).
    3. Redeem: The renderer sends a redemption control frame containing the one-time ticket. The daemon validates the ticket, consumes it, and spawns a real tmux attach-session via a PtyAdapter.
    4. Live Connection: Once redeemed, terminal input/output and resize messages flow directly over the binary WebSocket between the renderer and the daemon.
  8. How the RSC shell and siloed blocks architecture works

    main

    The tmux-ide dashboard uses a hybrid architecture to manage different UI frameworks (React, Solid, xterm.js, etc.) without performance degradation or state loss.

    Core Abstractions

    • RSC (React Server Components): Used for the dashboard shell, static pages, and navigation. These render on the server to avoid hydration overhead.
    • React Client Components: Used for interactive elements requiring useState, useEffect, or browser APIs (e.g., form widgets, command palettes).
    • Silos: Independent UI packages (e.g., @tmux-ide/chat-solid) built in foreign frameworks. They own their own DOM subtree.
    • Bridge Components: The only authorized way to mount a Silo into the React dashboard. Bridges translate React props into imperative calls on the Silo's mounting handle.

    The Data Contract

    Silos do not receive live React state. Instead, they implement a mount function that returns a MountHandle. Communication happens via imperative setter methods on this handle, ensuring the Silo is not re-mounted (and thus its internal state is preserved) when props change.

    // The Silo public API contract
    export interface SiloMountHandle {
      /** Tear down the silo and release every DOM/event/network resource it owns. */
      unmount(): void;
    
      /** One typed setter per prop the bridge needs to update. 
       * Setters MUST be idempotent. */
      // setX(value: T): void;
    }
    
    export function mount(el: HTMLElement, initial: InitialProps): SiloMountHandle;
  9. Understand the Native Terminal Transport Boundary

    main

    The native-terminal-websocket-transport.ts adapter manages the direct WebSocket connection for terminal capabilities. It is designed to be a privileged, isolated component that does not rely on Electron or daemon credentials.

    Key operational characteristics:

    • Security: It uses an injected issueAttachment(request) function. The request is validated via a shared semantic terminal-attachment contract, but the result is treated as unknown and handled by an untrusted, card-local parser.
    • Connection: The connection uses a short-lived loopback ws: or wss: descriptor. The one-use ticket is sent in a single bounded first control frame and is never exposed in URLs, errors, or reconnection attempts.
    • Data Flow: Binary daemon output is passed directly to the Solid terminal listener via a fixed frame/count/byte queue.
    • Operations: Resize operations are bounded and use latest-value-coalescing. The write() method is fail-closed with input-backpressure-unavailable until specific daemon recovery gates are enabled.
    • Lifecycle: The adapter does not implement automatic reconnect loops. Any retry triggers a completely new issue request, ticket, socket, and tmux redraw.