boo

repository·main·Indexed 20 days ago

https://github.com/coder/boo

A GNU screen-style terminal multiplexer built in Zig using libghostty's terminal emulation core. boo provides faithful terminal state rehydration and automation primitives—such as send, wait, and peek—designed for scripts and AI agents to manage headless sessions without a TTY.

Tokens
4.3K
Snippets
16
Records
23
Agent score
73%

What's inside boo

  1. How boo architecture works

    main

    boo uses a client-daemon model to manage terminal sessions:

    1. Client: Puts your TTY in raw mode and communicates with the daemon via a framed Unix-socket protocol.
    2. Daemon: A persistent process that owns the session. It manages a PTY-attached child process.
    3. Terminal State: The daemon uses libghostty-vt to parse all output from the PTY. This allows the daemon to maintain a perfect record of the screen state (contents, styles, cursor, scrollback, and modes).
    4. Rehydration: When a client attaches, the daemon uses a TerminalFormatter to replay the screen from the saved libghostty state, ensuring a faithful redraw.
    5. Detached Queries: While a session is detached, the daemon can answer terminal queries (like DSR or DA) using the stored state, preventing TUIs from hanging.
  2. Automate terminal tasks with boo

    main

    boo provides automation primitives designed for scripts and AI agents. Most commands work without a TTY. The canonical workflow for headless automation is:

    1. Create: Start a headless session.
    2. Send: Type commands into the session.
    3. Wait: Block until the output reaches a specific state.
    4. Peek: Read the rendered screen state.
    5. Kill: Clean up the session.

    Automation Commands

    • send --text '<text>' [--enter] [--key <key_name>]: Sends literal text to the session. --enter submits the input. Use --key for control keys like C-c or Up. This mode is binary safe and performs no escape processing.
    • wait [--text '<text>'] [--idle] [--timeout <duration>]: Blocks execution. --text waits for specific text; --idle waits until output has been quiet for 2 seconds. Durations follow formats like 500ms, 2s, 1m, 4h, 1d.
    • peek [--scrollback] [--json]: Reconstructs the rendered screen from terminal state. --scrollback includes history; --json provides machine-readable metadata (size, cursor, title).
    • ls --json: Lists sessions in JSON format.
    boo new build -d -- bash               # 1. headless session
    boo send build --text 'make' --enter   # 2. type into it
    boo wait build --idle                  # 3. let output settle
    boo peek build --scrollback            # 4. read the screen
    boo kill build                         # 5. clean up
  3. Install boo

    main

    For Linux and macOS, you can install boo using the official installation script:

    curl -fsSL https://raw.githubusercontent.com/coder/boo/main/install.sh | sh

    Alternatively, pre-built binaries are available on the releases page.

    You can control the installation behavior using these environment variables:

    • BOO_VERSION: Pin a specific release version.
    • BOO_INSTALL_DIR: Change the installation directory (defaults to /usr/local/bin if writable, otherwise ~/.local/bin).
  4. Manage terminal sessions with boo

    main

    boo is a terminal multiplexer that allows you to create, manage, and reattach to sessions. Sessions can be named or unnamed (unnamed sessions default to the current directory name).

    Common Commands

    • boo new: Start a new session running your current $SHELL and attach to it.
    • boo new <name>: Start a named session.
    • boo new <name> -d -- <command>: Create a detached session running a specific command.
    • boo ls: List all active sessions.
    • boo attach <name>: Reattach to an existing session (aliases: at, a).
    • boo rename <old_name> <new_name>: Rename a session.
    • boo kill <name>: End a specific session.
    • boo kill --all: End all sessions.
    • boo ui: Open a full-screen session manager (alias: i).
    boo new                    # new session running $SHELL, attached
    boo new work               # named session
    boo new work -d -- make    # create detached, running a command
    boo ui                     # manage sessions in a full-screen UI (alias: i)
    boo ls                     # list sessions
    boo attach work            # reattach (alias: at, a)
    boo rename work api        # rename a session
    boo kill work              # end a session
    boo kill --all             # end every session
  5. Internal Daemon Lifecycle and Socket Binding

    main

    The boo CLI manages sessions by spawning background daemons. The following internal mechanisms handle the transition from a foreground command to a detached daemon:

    • Socket Binding (bindListen): Creates a UNIX domain socket for communication. If the socket path is already in use, it checks if a live session exists via a connection probe. If no session is active, it deletes the stale socket file and re-binds.
    • Daemon Detachment (runDaemon): When a daemon starts, it detaches from the controlling terminal using setsid(). It redirects stdin and stdout to /dev/null and redirects stderr to a log sink (defined by the BOO_LOG environment variable, or /dev/null if unset) to ensure debug logs are preserved.
  6. Wait for conditions with `wait`

    main

    The wait command blocks until a specific condition is met in a session, useful for automation scripts.

    Options:

    • <name>: The name of the session.
    • --idle: Wait until the session has been idle for a certain duration. The session must be idle for at least 2000ms (the idle_settle_ms) before the timer starts.
    • --text <string>: Wait until the specified string appears in the session's screen output.
    • --timeout <duration>: The maximum time to wait. Supports formats like 500ms, 2s, 1m, 4h, 1d. Defaults to 30s.

    Example:

    # Wait up to 1 minute for 'done' to appear in the screen
    boo wait my-session --text "done" --timeout 1m
    
    # Wait for the session to become idle for 5 seconds
    boo wait my-session --idle --timeout 5s
    boo wait my-session --text "done" --timeout 1m
  7. Kill sessions with `kill`

    main

    The kill command terminates sessions.

    Options:

    • --all: Terminate all active sessions. This cannot be combined with a specific session name.
    • <name>: The name of the session to terminate.

    Example:

    # Kill a specific session
    boo kill my-session
    
    # Kill all sessions
    boo kill --all
    boo kill --all
  8. Create a new session with `new`

    main

    Use the new command to start a new session. You can specify a session name, terminal dimensions, a working directory, or run a specific command.

    Options:

    • <name>: The name of the session. If omitted, a default name is used.
    • --detached (-d): Start the session in the background and exit immediately (prints the session name to stdout).
    • --rows <number>: Set the number of rows (1-65535).
    • --cols <number>: Set the number of columns (1-65535).
    • --cwd <path>: Set the working directory for the session. This must be an absolute, accessible directory.
    • -- <command> [args...]: Use -- to separate boo options from the command you want to run inside the session.

    Example:

    # Create a named session running 'top' in a specific directory
    boo new my-session --cwd /home/user -- top
    
    # Create a detached session
    boo new -d my-session
    boo new my-session --cwd /home/user -- top
  9. Attach to a session with `attach`

    main

    Use attach (or at, a) to connect to an existing session. If you provide a partial name, boo will attempt to resolve it to a unique session name.

    Example:

    # Attach to a session named 'work'
    boo attach work
    boo attach work
  10. Send input to a session with `send`

    main

    The send command allows you to inject text, key sequences, or stdin into a running session.

    Options:

    • <name>: The name of the target session.
    • --text <string>: Send a specific string of text.
    • --key <key1,key2,...>: Send specific key sequences (e.g., enter, tab, up, down, left, right, escape, backspace).
    • --stdin: Read input from standard input and send it to the session.
    • --enter: Append a carriage return (\r) to the end of the payload.

    Constraints:

    • --text and --key cannot be used together.
    • --stdin cannot be used with --text or --key.
    • You cannot send NUL bytes.

    Example:

    # Send 'ls' followed by Enter
    boo send my-session --text "ls" --enter
    
    # Send an Escape key sequence
    boo send my-session --key escape
    
    # Send content from a pipe
    cat script.sh | boo send my-session --stdin
    boo send my-session --text "ls" --enter
  11. Peek at a session with `peek`

    main

    The peek command provides a snapshot of a session's current state without attaching to it.

    Options:

    • <name>: The name of the session.
    • --scrollback: Peek at the scrollback buffer instead of the current screen.
    • --json: Output the peek data in JSON format.

    Example:

    # Get a JSON snapshot of the screen
    boo peek my-session --json
    boo peek my-session --json