Help us shape the future of Go! Take the 2026 Go Developer Survey

tmux

package
v0.0.0-...-c55bb9b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 27, 2026 License: MIT Imports: 9 Imported by: 0

README

pkg/tmux

Tmux session and window management primitives. Wraps the tmux CLI directly via os/exec (with bitfield/script reserved for piped fzf flows).

If SCRIPTS_TMUX_SOCKET is set and non-empty, every tmux invocation targets that socket (-S <socket>), e.g. for talking to a tmux server forwarded over ssh -R.

Session API

  • Switch(name string) error — switches to name, creating the session if it doesn't exist. Inside tmux uses switch-client; outside it uses attach.
  • SwitchExisting(name string) error — switches without creating; used by prev/next rotation through history.
  • NewSession(name string) error — creates a detached session. Local: -c <name> (working directory set to the session name). Qualified HOST:dir: starts at the local home with the ssh pane command and records the remote markers.
  • KillSession(name string) error — terminates the session.
  • HasSession(name string) error — returns nil if the session exists, error otherwise.
  • SessionExists(name string) (bool, error) — same check, surfaced as a boolean.
  • ListSessions() ([]string, error) — lists session names, swallowing the "no server running" error as an empty list.
  • Attach(name string) error / SwitchClient(name string) error — direct primitives behind Switch.
  • DisplaySessions() (string, error) — fzf picker over sessions with pane-capture preview.
  • GetCurrentSession() (string, error) — current session name (uses $TMUX_PANE / display-message).
  • ParseTarget(arg string) (host, session string) — splits the HOST:session argument form; HistoryName(host, session string) string joins it for storage.
  • RemoteInfo(name string) (host, dir string, ok bool) — reads the session's SCRIPTS_REMOTE_HOST / SCRIPTS_REMOTE_DIR markers, mapping a live session name back to its qualified HOST:dir form.

Harness API

  • ListHarnessPanes() ([]HarnessPane, error) — all panes running a harness (claude, codex, opencode), detected via @harness / @harness_state pane options (set by the shell hooks) with fallback inference from title, command, start command, and window name. A bare major.minor.patch foreground command means claude (it rewrites its process name to its version). A live foreground command naming a harness always overrides conflicting stored options (pane reused by another harness), resetting state to title-derived. Drops stale entries where the foreground is back to a shell with no harness title marker, or where the title marker names a different harness than the stored one.
  • IsStaleHarness(pane) bool — true when the harness exited: foreground is an interactive shell or empty with no harness title marker, or the title marker names a different harness than the recorded one.
  • DisplayHarnessPanes(panes) (HarnessPane, error) — fzf picker with pane-capture preview; returns the selected pane.
  • JumpToHarnessPane(pane) error — jumps to the pane across sessions via stable IDs (switch-client + select-window + select-pane), avoiding session-name escaping issues.
  • FormatHarnessPane(pane) string — tab-separated display line (pane_id, status, session, window:pane, title) for fzf with hidden ID column.
  • HarnessSymbol(state) string — maps hook state (working, waiting-input, waiting-permission, done) to ● ? ! ✓.

Notify API

  • Notify(verb, harness, reason string) error — implements scripts tmux notify {working|waiting|done|clear}: sets/clears the pane title and @harness/@harness_state/@harness_updated pane options, and for waiting/done sends an external notification via NOTIFY_SCRIPT (default $HOME/.local/bin/tmux-notifications.sh) when the pane isn't the active one. All tmux failures are swallowed (matches the old hook script); the only error is an unknown verb. The target pane is SCRIPTS_TMUX_PANE if set, else $TMUX_PANE; if neither is set, it's a no-op.

Window API

  • ListWindows() ([]string, error)
  • NewWindow(name, command, directory string) error
  • KillWindow(windowID string) error
  • SelectWindow(name string) error

Session Name Canonicalisation

Sessions are named after directory paths. Dots in directory names conflict with tmux's target-pattern syntax (session:window.pane), so CanonicalSessionName() replaces . with _ before any tmux call. Callers pass real paths; the canonicalisation happens inside the package.

Remote Targets

  • A remote session is addressed as a qualified HOST:session argument (e.g. web1:/a/b). Host names are ~/.ssh/config aliases typed by the user; there are no new config keys.
  • It is a LOCAL tmux session whose panes run ssh — remote machines need only ssh, no tmux. The pane command reverse-forwards the local tmux server socket (ssh -t -R remote_sock:local_sock host ...) and exports SCRIPTS_TMUX_SOCKET=remote_sock in the remote shell before cd dir && "$SHELL" -l, so a scripts binary on the remote drives the local tmux server; the socket is cleaned up with rm -f on shell exit.
  • tmux silently maps : to _ in session names at creation, so CanonicalSessionName() mirrors that (: and . → _) and runs before every tmux -t/-s call: a HOST:dir argument targets the stored HOST_dir session.
  • NewSession also sets the session-scoped default-command to the same ssh pane command, so Ctrl-b c, Ctrl-b %, and Ctrl-b " open new ssh panes in that session.
  • SCRIPTS_REMOTE_HOST / SCRIPTS_REMOTE_DIR session environment markers record the target; RemoteInfo reads them back to map a live session name to HOST:session.
  • The pane command also exports SCRIPTS_TMUX_PANE=$TMUX_PANE remotely (expanded locally, before the ssh hop), so scripts tmux notify run on the remote host still targets the local pane, without touching the remote's own TMUX_PANE.
  • sync maps live sessions through those markers before writing history; --reverse compares names canonically and recreates missing sessions from their qualified history entries.
  • Every tmux call stays local; no remote tmux is involved. A remote directory picker is not implemented yet.

Switch-then-Persist Pattern

History (~/.scripts.yaml) is updated only after a successful switch. If tmux returns an error, the file is left alone — preventing a broken session from polluting recent history.

Error Handling

  • runTmux / runTmuxOutput capture combined output and join non-empty stderr into the returned error with fmt.Errorf("%w: %s", err, message).
  • isExitCode / isNoServerRunning classify expected error shapes (no server running ⇒ empty session list).

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Attach

func Attach(name string) error

func CanonicalSessionName

func CanonicalSessionName(name string) string

func DisplaySessions

func DisplaySessions() (string, error)

func FormatHarnessPane

func FormatHarnessPane(p HarnessPane) string

func GetCurrentSession

func GetCurrentSession() (string, error)

func HarnessSymbol

func HarnessSymbol(state string) string

func HasSession

func HasSession(name string) error

func HistoryName

func HistoryName(host, session string) string

func IsStaleHarness

func IsStaleHarness(p HarnessPane) bool

func JumpToHarnessPane

func JumpToHarnessPane(p HarnessPane) error

func KillSession

func KillSession(name string) error

func KillWindow

func KillWindow(windowID string) error

func ListSessions

func ListSessions() ([]string, error)

func ListWindows

func ListWindows() ([]string, error)

func Ls

func Ls() ([]string, error)

func NewSession

func NewSession(name string) error

func NewWindow

func NewWindow(name, command, directory string) error

func Notify

func Notify(verb, harness, reason string) error

func ParseTarget

func ParseTarget(arg string) (host, session string)

func RemoteInfo

func RemoteInfo(session string) (string, string, bool)

func SelectWindow

func SelectWindow(name string) error

func SessionExists

func SessionExists(name string) (bool, error)

func ShortenHome

func ShortenHome(path string) string

func Switch

func Switch(name string) error

func SwitchClient

func SwitchClient(name string) error

func SwitchExisting

func SwitchExisting(name string) error

Types

type HarnessPane

type HarnessPane struct {
	SessionID    string
	SessionName  string
	WindowID     string
	WindowIndex  string
	WindowName   string
	PaneID       string
	PaneIndex    string
	Harness      string
	State        string
	Title        string
	Command      string
	StartCommand string
	Path         string
}

func DisplayHarnessPanes

func DisplayHarnessPanes(panes []HarnessPane) (HarnessPane, error)

func ListHarnessPanes

func ListHarnessPanes() ([]HarnessPane, error)

func ParseHarnessFields

func ParseHarnessFields(fields []string) (HarnessPane, bool)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL