-
Notifications
You must be signed in to change notification settings - Fork 236
Description
Summary
Tracking issue for reaching feature parity with tmuxinator (3.3.7) and teamocil (1.4.2). Based on a comprehensive source-level analysis of both projects, their importers, and the tmuxp builder/loader/CLI.
Tracking issue for libtmux-side API additions: tmux-python/libtmux#635
Phase 1: Import Fixes (No Builder/libtmux Changes)
These fix existing bugs and add missing translations without touching the builder.
I1. tmuxinator pre / pre_window Mapping Bugs
Two bugs in importers.py:59-70:
Bug A — Solo pre maps to wrong key: When only pre exists (no pre_window), it maps to shell_command_before — a per-pane key. But tmuxinator's pre runs once before any windows are created. Correct target: before_script.
Bug B — Combo pre + pre_window loses pre: When both exist, pre maps to shell_command (invalid session key, silently ignored). The isinstance check on line 62 tests the wrong variable (pre instead of pre_window).
Correct mapping: pre -> before_script, pre_window -> shell_command_before
Note: before_script uses Popen without shell=True (util.py:27-32), so pipes/&&/redirects won't work. Forward path is on_project_start (T6).
I2. tmuxinator cli_args / tmux_options Fragile Parsing
str.replace("-f", "").strip() at importers.py:41,48 does global string replacement, not flag-aware parsing. Ignores -L (socket name) and -S (socket path) flags entirely.
Fix: Use shlex.split() + iterate to find -f flag and its value.
I3. teamocil Redundant Filter Loops
for _b in w["filters"]["before"]: loops at importers.py:145-149 iterate N times but set the same value each time.
Fix: Replace with direct assignment.
I4. teamocil v1.x Format Not Supported
Importer assumes v0.x format. String panes (v1.x format) are not handled — when p is a string, if "cmd" in p performs substring containment instead of dict key lookup, and p.pop("cmd") would raise AttributeError. commands key (v1.x) not mapped.
v0.x pane width is silently dropped (importers.py:161-163). height is not even popped — it passes through as a dead key. libtmux's Pane.resize() exists, so both could be preserved.
Fix: Add format detection. Handle string panes, commands key, focus, and options.
I5. tmuxinator Missing Keys
Not imported but translatable:
rvm->shell_command_before: ["rvm use {value}"]pre_tab->shell_command_before(deprecated predecessor topre_window)startup_window-> find matching window, setfocus: truestartup_pane-> find matching pane, setfocus: trueon_project_first_start->before_scriptpost-> deprecated predecessor toon_project_exit(needs T6)socket_path-> warn user to use CLI-Sflagattach: false-> warn user to use CLI-dflag
I6. teamocil Missing Keys
v1.x keys (same key names in tmuxp):
commands->shell_commandfocus(window/pane) ->focus(pass-through)options(window) ->options(pass-through)- String pane shorthand ->
shell_command: [command]
v0.x keys:
with_env_var->environment: { TEAMOCIL: "1" }height(pane) -> should be popped likewidth
I7. Importer TODOs Need Triage
importers.py:121,123 lists with_env_var and cmd_separator as TODOs. Both are verified v0.x features (not stale):
with_env_var: Implement — map toenvironment: { TEAMOCIL: "1" }clear: Preserved in config at line 141 (window_dict["clear"] = w["clear"]) but builder ignores it. libtmux hasPane.clear().cmd_separator: Remove TODO — irrelevant since tmuxp sends commands individually.
Phase 2: Builder Additions (tmuxp Only)
T1. No synchronize Config Key
WorkspaceBuilder does not check for synchronize on window configs. Silently ignored.
Blocks: tmuxinator synchronize: true/before/after.
Implementation: window.set_option("synchronize-panes", "on") — before pane commands for before/true, in config_after_window() for after.
T3. No shell_command_after Config Key
Teamocil importer produces shell_command_after (from filters.after), but builder never reads it.
Blocks: teamocil v0.x filters.after.
Implementation: Read window_config.get("shell_command_after", []) in config_after_window() and send to panes.
T4. No Session Rename Mode / --here CLI Flag
tmuxp load has no --here flag. Always creates new windows.
Blocks: teamocil --here (reuse current window for first window) and session rename mode.
Implementation: Add --here to cli/load.py. For first window: rename_window() + send_keys("cd <root>") instead of new_window(). Also rename_session() when --here is used.
Phase 3: libtmux Additions
Tracked in tmux-python/libtmux#635
T2. No Pane Title Config Key
Depends on: libtmux Pane.set_title() (L1)
Implementation: Session-level enable_pane_titles, pane_title_position, pane_title_format via session.set_option(). Per-pane title via pane.set_title().
Phase 4: New CLI Commands
T5. No stop / kill CLI Command
tmuxp has no stop command.
Blocks: tmuxinator stop / stop-all.
Implementation: tmuxp stop <session> — find session, call session.kill(). Run on_project_stop hook before kill.
T10. Missing Config Management Commands
tmuxp only has edit. Missing: new, copy, delete.
Blocks: tmuxinator new, copy, delete, implode.
Phase 5: Larger Features (Nice-to-Have)
T6. No Lifecycle Hook Config Keys
tmuxp's plugin system has 5 Python hooks, but no config-driven shell command hooks.
Blocks: tmuxinator on_project_start, on_project_first_start, on_project_restart, on_project_exit, on_project_stop.
Mapping:
on_project_start-> run at start ofbuild(), beforebefore_scripton_project_first_start-> partially covered bybefore_scripton_project_restart-> run on reattachon_project_exit->session.set_hook("client-detached", cmd)on_project_stop-> run intmuxp stop(T5)
T7. --no-shell-command-before CLI Flag
Skip shell_command_before for debugging. Equivalent to tmuxinator --no-pre-window.
T8. Config Templating
tmuxp has no user-defined variable interpolation (env vars work, custom key=value does not).
Blocks: tmuxinator ERB templating.
T9. --debug / Dry-Run CLI Flag
Depends on: libtmux L3 (pre-execution logging)
L2. Custom tmux Binary
Depends on: libtmux L2
Blocks: tmuxinator tmux_command: wemux
Dead Config Keys
Keys produced by importers but silently ignored by the builder:
| Key | Producer | Issue |
|---|---|---|
shell_command (session-level) |
tmuxinator | Bug I1-B: pre commands lost |
config |
tmuxinator | Dead data — extracted -f path unused |
socket_name |
tmuxinator | Dead data — CLI uses -L flag |
clear |
teamocil | Builder doesn't read it (libtmux has Pane.clear()) |
height (pane) |
teamocil | width is popped but height passes through |
target (pane) |
teamocil | Accidentally preserved (libtmux has Pane.split(target=...)) |
shell_command_after |
teamocil | Builder has no after-command support |