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.
tmux -Vtmux new -s api-refactor# Inside the session, press Ctrl-b, release, then press d to detachtmux lstmux attach -t api-refactor# Run this after the task ends; it kills all processes in the sessiontmux 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. Usetmux new -A -s api-refactorto 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 withtmux lsfirst.no server running: No tmux session exists. Runtmux new -s name.- When does a session end? A session ends when you enter
exitinside it or close the last pane in the session. Pressing onlyCtrl-b ddetaches; 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:
zellij -s api-refactor# With the default keybindings, press Ctrl-o then d to detachzellij lszellij attach api-refactorzellij 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.
setw -g monitor-silence 30set -g visual-silence onset -g bell-action any
The three lines serve different purposes.
monitor-silence 30is a window option. When a window has no output for 30 consecutive seconds, tmux marks that window in the window list.visual-silence ondisplays a message in the status bar telling you which window has gone silent.bell-action anyis 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.
tmux source-file ~/.tmux.conftmux show-options -g visual-silencetmux show-options -gw monitor-silencetmux 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:
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-silenceis 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.
font-family = "JetBrains Mono"shell-integration = detectmacos-option-as-alt = true
The items work as follows.
font-familyspecifies the font. Use a monospaced font to align AI-generated code and tables.shell-integration = detectlets Ghostty automatically detect and enable shell integration.macos-option-as-alt = trueworks 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.
# Method 1: copy local terminfo to the remote hostinfocmp -x xterm-ghostty | ssh username@host tic -x -# Method 2: temporarily use a more compatible terminal typeTERM=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.
npm i -D playwrightnpx playwright install chromium# On a Linux server, you may need to install system dependenciesnpx playwright install --with-deps chromium
Create smoke.mjs in the project with the following content.
import { chromium } from 'playwright';const url = process.argv[2] ?? 'http://localhost:3000';const errors = [];const browser = await chromium.launch();try {const page = await browser.newPage();page.on('pageerror', (err) => errors.push(`pageerror: ${err.message}`));page.on('console', (msg) => {if (msg.type() === 'error') errors.push(`console: ${msg.text()}`);});const resp = await page.goto(url, { waitUntil: 'load', timeout: 15000 });if (!resp || resp.status() >= 400) {errors.push(`http status: ${resp?.status() ?? 'no response'}`);}await page.screenshot({ path: 'smoke.png', fullPage: true });} finally {await browser.close();}if (errors.length > 0) {console.error(errors.join('\n'));process.exit(1);}console.log('smoke test passed');
When running, pass the address as an argument and quote the variable:
URL="http://localhost:3000"node smoke.mjs "$URL"
After running, check the following.
- The exit code is 0, and
smoke test passedis printed. - The generated
smoke.pngmatches the page you expect. - If there is an error, first determine whether the error is
pageerror,console, orhttp 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.
# Create the session on the servertmux new -s pair-review# A collaborator attaches read-only over SSHssh 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.
sudo groupadd pair-reviewsudo usermod -aG pair-review collaboratormkdir -p /srv/tmux-sharedtmux -S /srv/tmux-shared/pair.sock new -s pair-reviewsudo chgrp pair-review /srv/tmux-shared/pair.socksudo 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-historyin the pane to clear the history. Leaked keys should be rotated immediately. - Do not write secrets into configuration: Ghostty configuration,
~/.tmux.conf, andsmoke.mjsmay 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.
