Building an AI Coding Session and Alert Workbench with tmux

    This article shows how to use tmux as the foundation of an AI coding workbench. It separates the roles of terminal emulators, multiplexers, and scripts; explains named tmux sessions for long-running AI tasks; configures silence monitoring for alerts; covers Ghostty configuration and remote terminal type issues; adds a Playwright smoke test for front-end output; and discusses read-only and shared-socket remote collaboration, security risks, and troubleshooting.

    1. Separate the responsibilities of each tool

    A terminal workbench consists of three kinds of components. A terminal emulator (such as Ghostty) displays output and receives keyboard input. A multiplexer (such as tmux or Zellij) splits panes and keeps programs running after you close the terminal window. Scripts and plugins handle alerts, automation, and integration with external tools.

    The table below lists common capabilities. “Not supported” means the tool has no native feature and another tool must fill the gap.

    Capability tmux Zellij Ghostty
    Multiple panes Supported Supported Supported
    Processes continue after closing terminal window Supported (detach) Supported (detach) Not supported; use with tmux or Zellij
    Layout restoration Requires plugins such as tmux-resurrect Built-in session serialization Does not restore running processes
    Alert after long silence Built-in (monitor-silence) Requires a plugin or script Requires external implementation
    Script control of panes Supported (tmux commands) Supported (zellij action commands) Limited; see official documentation
    Built-in browser, SSH manager Not supported Not supported Not supported

    Commands in this article are written for common syntax in tmux 3.x, Zellij 0.4x series, and Ghostty 1.x. Your versions may differ; confirm with tmux -V, zellij --version, and Ghostty’s version information.

    If you need session persistence and waiting alerts, a common combination is tmux plus any terminal emulator. In this combination, Ghostty only displays output and accepts input; it does not provide detach itself. Zellij can also detach and is suitable for people who do not want to write configuration files and prefer to describe panes directly in layout files. However, Zellij’s silence alerts require a plugin or script.

    2. Use tmux to preserve a session for each task

    Create a named session for each task. The name should be related to the task so you can find it later.

    1. tmux -V
    2. tmux new -s api-refactor
    3. # Inside the session, press Ctrl-b, release, then press d to detach
    4. tmux ls
    5. tmux attach -t api-refactor
    6. # Run this after the task ends; it kills all processes in the session
    7. tmux kill-session -t api-refactor

    After detaching, the AI program continues running in the background. Later, run tmux attach to reconnect and see output produced while you were disconnected.

    Common runtime issues:

    • duplicate session: A session with the same name already exists. Use tmux new -A -s api-refactor to attach to the existing session directly, or choose another name.
    • can't find session: The session name is misspelled or the session has ended. Check names with tmux ls first.
    • no server running: No tmux session exists. Run tmux new -s name.
    • When does a session end? A session ends when you enter exit inside it or close the last pane in the session. Pressing only Ctrl-b d detaches; it does not end the session.
    • Session disappears after a reboot: Detaching prevents closing the terminal window, but it cannot prevent a machine reboot or shutdown. Running processes end with the machine. tmux-resurrect can restore pane layouts, but it usually cannot restore running programs; you need to restart the AI tool manually.

    If you use Zellij, the corresponding commands are:

    1. zellij -s api-refactor
    2. # With the default keybindings, press Ctrl-o then d to detach
    3. zellij ls
    4. zellij attach api-refactor
    5. zellij kill-session api-refactor

    Use the following table when choosing a tool:

    Use case Recommendation Reason
    Single-user local development, frequent configuration file editing tmux Mature configuration style; can be script-controlled
    Do not want to write configuration, prefer to describe layouts directly in files Zellij Layout files and built-in serialization work out of the box
    Need remote collaboration tmux Supports read-only attachment or shared sockets; more permission control options
    Need to batch-control panes with scripts tmux or Zellij Both have command-line interfaces; tmux has more public documentation

    3. Make waiting sessions alert you

    When an AI coding assistant is waiting for your confirmation, it usually stops producing output. tmux can use “no output for a period of time” as an alert signal. Add the following configuration to ~/.tmux.conf.

    1. setw -g monitor-silence 30
    2. set -g visual-silence on
    3. set -g bell-action any

    The three lines serve different purposes.

    • monitor-silence 30 is a window option. When a window has no output for 30 consecutive seconds, tmux marks that window in the window list.
    • visual-silence on displays a message in the status bar telling you which window has gone silent.
    • bell-action any is unrelated to silence. It handles the bell character (BEL) emitted by programs; any window that emits a bell triggers a mark.

    If you only need silence alerts, you can omit bell-action.

    After changing the configuration, run the following commands to apply it and confirm that the options are set.

    1. tmux source-file ~/.tmux.conf
    2. tmux show-options -g visual-silence
    3. tmux show-options -gw monitor-silence
    4. tmux show-options -g bell-action

    To test, run (echo start; sleep 35; echo done) in one window, switch to another window, wait about 30 seconds, and observe whether the first window gets a mark.

    Silence detection cannot distinguish “waiting for confirmation” from “performing a long computation.” Compilation, downloads, and tests can all run for a long time without output, so false positives occur. There are two ways to handle this. First, increase the global number of seconds. Second, adjust only the windows that need it, for example:

    1. tmux set -w -t api-refactor:1 monitor-silence 120

    When troubleshooting, check in the following order.

    • The window has no mark: Confirm that the output of show-options -gw monitor-silence is the number of seconds you set. During testing, if you stay in the same window, you may not see the mark; switch to another window and observe.
    • The status bar shows no message: If the configuration disables the status bar (set -g status off), the message will not appear.
    • The bell makes no sound: System Do Not Disturb mode, terminal bell settings, or system notification permissions may block the sound. In this case, rely on the mark in the window list.

    4. Correct Ghostty configuration

    Ghostty’s configuration file is usually located at ~/.config/ghostty/config. Configuration item names and default values are subject to the official documentation for your version. Below is a minimal example.

    1. font-family = "JetBrains Mono"
    2. shell-integration = detect
    3. macos-option-as-alt = true

    The items work as follows.

    • font-family specifies the font. Use a monospaced font to align AI-generated code and tables.
    • shell-integration = detect lets Ghostty automatically detect and enable shell integration.
    • macos-option-as-alt = true works only on macOS. It makes the Option key act as Alt, which helps when entering shortcuts in tmux and vim.

    After making changes, on macOS you can press Cmd+Shift+, to reload the configuration (default shortcut; check your settings). If the shortcut does not work, restart Ghostty directly. If your version supports it, run ghostty +show-config to view the currently effective configuration values.

    When Ghostty closes a window, the shell and child processes in it usually end as well. Therefore, AI tasks that need to run for a long time should be placed in a tmux session, not run directly in a Ghostty tab.

    A common issue on remote servers is that the terminal type is not recognized. Ghostty sets TERM to xterm-ghostty by default. If the remote host has no corresponding terminfo entry, you will see an error such as 'xterm-ghostty': unknown terminal type. There are two solutions.

    1. # Method 1: copy local terminfo to the remote host
    2. infocmp -x xterm-ghostty | ssh username@host tic -x -
    3. # Method 2: temporarily use a more compatible terminal type
    4. TERM=xterm-256color ssh username@host

    Method 2 loses some terminal features, such as some color or keyboard protocol support, but it is suitable for temporary use.

    5. Use a browser smoke test to check front-end output

    A common problem with AI-generated web code is that the page opens but the console reports errors or resources fail to load. A smoke test opens the page with a headless browser and checks the HTTP status code, page script errors, and console errors.

    Start the development server in one tmux window, then run the test in another window. Using Node.js as an example, install as follows.

    1. npm i -D playwright
    2. npx playwright install chromium
    3. # On a Linux server, you may need to install system dependencies
    4. npx playwright install --with-deps chromium

    Create smoke.mjs in the project with the following content.

    1. import { chromium } from 'playwright';
    2. const url = process.argv[2] ?? 'http://localhost:3000';
    3. const errors = [];
    4. const browser = await chromium.launch();
    5. try {
    6. const page = await browser.newPage();
    7. page.on('pageerror', (err) => errors.push(`pageerror: ${err.message}`));
    8. page.on('console', (msg) => {
    9. if (msg.type() === 'error') errors.push(`console: ${msg.text()}`);
    10. });
    11. const resp = await page.goto(url, { waitUntil: 'load', timeout: 15000 });
    12. if (!resp || resp.status() >= 400) {
    13. errors.push(`http status: ${resp?.status() ?? 'no response'}`);
    14. }
    15. await page.screenshot({ path: 'smoke.png', fullPage: true });
    16. } finally {
    17. await browser.close();
    18. }
    19. if (errors.length > 0) {
    20. console.error(errors.join('\n'));
    21. process.exit(1);
    22. }
    23. console.log('smoke test passed');

    When running, pass the address as an argument and quote the variable:

    1. URL="http://localhost:3000"
    2. node smoke.mjs "$URL"

    After running, check the following.

    • The exit code is 0, and smoke test passed is printed.
    • The generated smoke.png matches the page you expect.
    • If there is an error, first determine whether the error is pageerror, console, or http status, then locate it in the code.

    This script can only find errors during the load phase. Clicks, form submissions, and login flows require separate test steps. Errors from third-party scripts are also counted, so you need to judge which errors are related to your code.

    6. Basic approach to remote collaboration

    Run tmux on a remote server, and collaborators connect to the same session over SSH. The simplest way is read-only attachment: collaborators can watch but cannot type.

    1. # Create the session on the server
    2. tmux new -s pair-review
    3. # A collaborator attaches read-only over SSH
    4. ssh username@server -t 'tmux attach -r -t pair-review'

    If collaborators also need to type, use a separate socket and restrict permissions to a specific user group.

    1. sudo groupadd pair-review
    2. sudo usermod -aG pair-review collaborator
    3. mkdir -p /srv/tmux-shared
    4. tmux -S /srv/tmux-shared/pair.sock new -s pair-review
    5. sudo chgrp pair-review /srv/tmux-shared/pair.sock
    6. sudo chmod 660 /srv/tmux-shared/pair.sock

    A collaborator connects with tmux -S /srv/tmux-shared/pair.sock attach -t pair-review. After collaboration ends, close the session and remove members from the user group.

    Note the following points.

    • Writable attachment is equivalent to handing a shell on the server to the other person; they can execute any command.
    • Do not use remote sessions to handle sensitive production configuration unless explicitly authorized.
    • Remote access should use SSH keys and disable password login. Follow the server’s security requirements for the specific configuration.

    7. Security risks and protections

    AI coding tools execute commands and read/write files, so the risk is higher than with ordinary scripts. Consider the following points.

    • Least privilege: Do not run AI tools as root. Give them only the permissions needed to access the current project directory.
    • Control automatic confirmation: Some tools provide parameters that skip confirmation. Such parameters let the tool execute commands without your confirmation and should be used only in isolated environments.
    • Clean sensitive output: tmux keeps scrollback history. If API keys, tokens, or database passwords have appeared in the terminal, run clear-history in the pane to clear the history. Leaked keys should be rotated immediately.
    • Do not write secrets into configuration: Ghostty configuration, ~/.tmux.conf, and smoke.mjs may all be committed to code repositories. Secrets should be stored in environment variables or a secret management tool.
    • Check content before sharing your screen: Read-only attachment also displays everything on the screen. Before sharing, confirm that no sensitive information is visible.
    • Alerts may miss confirmations: Silence alerts are based on time. If a window is waiting for confirmation while producing no other output, the alert will still fire, but when multiple windows need confirmation at the same time, you still need to check them one by one.

    8. Troubleshooting checklist

    Symptom Possible cause Check or action
    AI task is interrupted after closing Ghostty The task is running directly in a Ghostty tab Run it in a tmux session and detach before closing the window
    tmux new reports duplicate session A session with the same name already exists Use tmux new -A -s name, or choose another name
    Session disappears after a reboot Detaching only prevents closing the window, not reboots Recreate the session and start the AI tool manually
    Window does not show a silence mark The seconds value is too long, or testing stays in the same window Check with show-options, switch windows, and observe
    Status bar shows no message The status bar is disabled, or the option did not take effect Check the status option, then run source-file
    Remote host reports unknown terminal type The remote host lacks terminfo for xterm-ghostty Copy terminfo, or temporarily set TERM=xterm-256color
    Smoke test exits with code 1 The page has console errors or an abnormal HTTP status Check the error category in the output and locate the specific code
    Remote collaborator cannot connect Socket permissions or user group settings are wrong Check the group ownership and permissions in ls -l; they should be 660

    When you encounter a problem, first confirm the version, then check item by item whether the configuration is active. Most failures can be diagnosed with tmux ls and show-options.