The tmuxctl application provides fast tmux control optimized for agent workflows. Located in /Users/mike/code/arthack/apps/tmuxctl/.
Subcommands (16 total, defined via run_*.py modules):
| Subcommand | Purpose |
|---|---|
show-diff |
Display git diff against HEAD using critique or delta; includes untracked files |
create-split |
Split current pane along longest axis; returns YAML with target/pane-id/pid |
check-pane |
Query pane status (alive, target, pane-id, pid, foreground command) |
run-commit |
Interactive commit wrapper; logs output and waits for 'q' keypress |
wait-for |
Poll pane content for regex pattern match; returns exit 0 on match, 124 on timeout |
tail-panes |
Show last N lines of all panes; supports session/window scoping; hides _-prefixed sessions by default |
show-tree |
Display session/window/pane tree with real foreground processes |
triangulate-self |
Print current pane's context (session, window, pane, target) as YAML |
run-command |
Send command, wait for prompt, capture output in one call; replaces send-keys + sleep + capture-pane |
capture-pane |
Read pane content; supports line count and full scrollback history |
send-keys |
Send keystrokes to pane; appends Enter by default; supports --no-enter, --literal, --delay |
create-session |
Create detached session; supports working directory, command, window name |
load-session |
Load tmux session from YAML layout file in ~/.config/tmuxctl/layouts/ |
run-claude |
Launch Claude Code in detached session; supports --wait, --prompt, --permission-mode |
Pane targeting conventions: Format is SESSION[:WINDOW[.PANE]] with 1-based indexing. Session names starting with _ are hidden by default (use --show-internal to show). Examples: work (first pane), work:2 (window 2), work:1.3 (window 1, pane 3).
CLI file: apps/tmuxctl/tmuxctl/cli.py (600 lines)
The hookctl system provides a command_advice block in /Users/mike/code/arthack/system/hookctl/.config/hookctl/config.yaml (lines 322–332) that triggers when tmuxctl is invoked:
- match: "tmuxctl"
message: |
tmuxctl tips:
- run-command is your default for shell commands — one call, full output
- create-split for panes — "open a pane" = create-split, never create-session
- After create-split with a command, verify with check-pane or capture-pane
- Targets: use session name (e.g., mysession), not mysession:1
- send-keys --no-enter for interactive prompts (pressing 'y', 'q', C-c)
- wait-for polls at 0.5s; --then-send sends text after a match
- run-claude always passes --skip-commit to claude
Run `tmuxctl --agent-help` for full reference.This advice appears whenever the agent matches "tmuxctl" in a context, providing real-time guidance on best practices.
Location: /Users/mike/code/arthack/claude/work/skills/tmux/
SKILL.md provides:
- Rationale: Bash tool runs non-interactive subprocesses; tmux gives real login shell with aliases, functions, PATH, env vars
- Core command usage (create-split, check-pane, run-command, create-session, capture-pane, send-keys, run-claude, show-tree, tail-panes, wait-for)
- Use cases: launching sibling processes, running interactive CLIs/TUIs, debugging in user environment, testing Claude Code changes end-to-end
- Pane splitting convention: "open a pane" = split current window, never create new session/window
- Raw tmux fallback patterns for advanced cases
references/tmux-commands.md includes:
- Session/window/pane management command reference tables
- Targeting syntax with 1-based indexing
- Send-keys, capture-pane, pane management patterns
- Common workflows: split + verify, send + wait + capture, large output, polling for completion, interactive prompts, multiple windows
File: apps/devctl/devctl/run_choose_project.py (lines 305–327)
When the project picker loads the "work" session, it calls tmuxctl load-session work to populate the session from a YAML layout. If the session doesn't exist, it loads from ~/.config/tmuxctl/layouts/work.yaml. If layout loading fails, it falls back to creating a bare session with tmux new-session.
File: apps/keyctl/keyctl/parsers.py
Parses tmux keybindings from ~/.config/tmux/tmux.conf and conf.d/*.conf via the normalize_tmux_key() function. Part of a 4-layer keyboard shortcut inventory (karabiner > skhd > tmux > nvim). Layer priority is enforced because tmux prefix-scoped bindings don't conflict cross-layer.
File: apps/themectl/themectl/run_scrape_themes.py (lines 39–54)
Implements get_tmux_pane() function that retrieves the current tmux pane ID via the TMUX_PANE environment variable or by calling tmux display-message -p "#{pane_id}". Used during theme screenshot scraping to capture context.
The tmux skill is listed in command templates at /Users/mike/code/arthack/claude/arthack/command-templates/_partials/tool-summaries.md.tmpl (lines 27–29) as part of the Workflows section, with teaser text generated from tmuxctl --agent-teaser.
Simple interaction graph of tmux-aware components:
[devctl project picker]
|
v
[tmuxctl load-session] <-- Loads YAML layout from ~/.config/tmuxctl/layouts/
|
v
[work session created]
|
+--> [keyctl] inspects tmux.conf for binding inventory
|
+--> [themectl] captures current pane during scrape
|
+--> [Claude Code skill] drives interactive workflows
(split panes, run commands, wait for patterns, capture output)
- Pane targeting is unambiguous: Always use session name (e.g.,
mysession) rather than indexed notation (e.g.,mysession:1) for primary targets, as the latter can be ambiguous in layouts with many windows. Session-only targets default to the first pane. - Verify after create-split: When splitting with a command, always capture the target and call
check-panewithin 1 second to detect immediate exits, or after a delay for longer-running processes. - Layout files as code: YAML layouts in
~/.config/tmuxctl/layouts/should be versioned and documented — they define how projects initialize their tmux environment and are critical for reproducible agent workflows.
cwd: /Users/mike/code/arthack
session-id: a722a7fc-bb9c-49a4-99b9-8b21baa4dd06
session-name: remove-tmux-integration-pieces
path: /Users/mike/docs/tmux-features-inventory-current-2026-04-12.mdclaude --resume a722a7fc-bb9c-49a4-99b9-8b21baa4dd06