agentmux is a Go TUI application that wraps tmux via CLI commands. It does not use tmux control mode (reserved for a potential v2). The binary is a single executable with no runtime dependencies beyond tmux itself.
cmd/agentmux/main.go
└── internal/commands (Cobra CLI)
└── internal/app (wiring + lifecycle)
├── internal/adapters/tmux (tmux CLI wrapper)
├── internal/config (TOML config)
├── internal/store (SQLite state)
└── internal/tui (Bubble Tea app)
├── internal/tui/components (header, footer, list, preview)
├── internal/tui/styles (Lip Gloss theme)
└── internal/tui/views (sessions, palette, launcher, help)
All packages under internal/ are unexported. The only public API is the CLI.
Entrypoint. Calls commands.Root().Execute() and exits with code 1 on error.
Cobra command tree. Each file is one command:
root.go— launches TUI when no subcommand givenlist.go— tabwriter output of sessionsnew.go— creates a session with--dirflagattach.go— attaches (process replacement via app layer)kill.go— kills a sessioninit.go— creates default config fileerrors.go— shared error messages (tmux missing)
Application bootstrap:
New()wires all dependencies (client, config, store)RunTUI()starts Bubble Tea, then doessyscall.Execfor attach on exitexec_unix.go/exec_windows.go— platform-specific process replacement
tmux CLI wrapper. Never shells out via sh -c — all arguments are passed as
exec args (no injection risk).
Key design:
- Format strings use
\x1f(Unit Separator) as field delimiter instead of|because pipes can appear in directory paths ValidateSessionName()rejects characters that tmux treats speciallyCapturePane()returns empty string (not error) for missing/empty panesListSessions()returnsnil, nilwhen no server is running
TOML config loading with validation:
Load(path)— parse + validateLoadOrDefault(path)— returns empty config on any error (non-fatal)Validate()— structural checks with joined errorsInitDefault(path)— creates commented example if file doesn't existexpandHome()— handles both~and~/path
Pure domain models with no dependencies:
Session— name, windows, created, attached, directoryWorkspace— name, root, commandsCommand— name, cmd
SQLite persistence via modernc.org/sqlite (pure Go, no CGO):
- Schema versioning with incremental migrations
- Corrupt database auto-recovery (rename + recreate)
RecordSession()— upsert with nanosecond timestampRecentSessions(limit)— ordered by last usePing()— connection health check
Bubble Tea application shell:
Model— top-level state machine- Four view modes: Sessions, Palette, Launcher, Help
- Key handling dispatched by current mode
doRefresh()reloads sessions and rebuilds the palette action listrebuildPalette()dynamically includes workspace and session actions
Reusable rendering primitives:
Header— brand + mode + session count, fills widthRenderFooter()— context-aware keybinding bar with│separatorsSessionList— cursor-navigated list with attached indicators and timestampsPreview— pane output with title, directory, error/empty states, line truncation
Lip Gloss style definitions. A single dark theme with violet accents. Organized into sections: layout (header, panels, footer), content (selected, normal, muted), indicators, overlays, and input.
Full-screen view renderers:
SessionsView— two-panel layout (list + preview), delegates to componentsPaletteView— centered overlay with fuzzy search, action list, keyboard navLauncherView— centered overlay for workspace selection + command drillingHelpOverlay— categorized keybinding reference
User input → tea.KeyMsg → Model.Update() → state mutation → Model.View() → terminal
│
├── handleSessionsKey() → tmux.Client (list/new/kill/rename)
├── handlePaletteKey() → action callbacks
├── handleLauncherKey() → tmux.Client.NewSession()
└── handleConfirmKey() → tmux.Client.KillSession()
main()→commands.Root().Execute()- If no subcommand:
app.New()→app.RunTUI() - Bubble Tea runs until user quits or selects attach
- On attach:
tea.Programexits,execvp("tmux", "attach-session", "-t", name)replaces the process — no parent left behind
- Unit tests cover parsers, validators, store operations, and UI logic
- All tests are deterministic — no tmux required
make smokebuilds and runs CLI commands against a real tmux server- CI runs
go test -raceto catch data races - Race detector is free since the TUI is single-threaded (Bubble Tea model)