docs: tmuxinator/teamocil parity analysis and feature comparison#1014
Draft
docs: tmuxinator/teamocil parity analysis and feature comparison#1014
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1014 +/- ##
==========================================
+ Coverage 81.96% 82.34% +0.37%
==========================================
Files 28 28
Lines 2545 2662 +117
Branches 485 520 +35
==========================================
+ Hits 2086 2192 +106
- Misses 328 339 +11
Partials 131 131 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
304ff40 to
8e9425c
Compare
19b04a3 to
1f937ad
Compare
bb72be2 to
ca74e75
Compare
…amocil Comprehensive side-by-side comparison covering architecture, config keys, CLI commands, hooks, and config file discovery across all three tools.
Documents 12 feature gaps (hooks, stop command, pane sync, pane titles, ERB templating, wemux, debug/dry-run, config management CLIs), import behavior with bug inventory, and WorkspaceBuilder requirements.
Documents v0.x vs v1.x format differences, 3 feature gaps (--here flag, debug mode, shell_command_after), import bugs (v1.x incompatibility, redundant filter loops), and WorkspaceBuilder requirements.
Classifies each config key as difference (translatable) or limitation (needs tmuxp feature). Identifies pre/pre_window bug, missing rvm/pre_tab mappings, and 5 features requiring new tmuxp capabilities.
Documents v0.x-only targeting (v1.x unsupported), string pane TypeError bug, redundant filter loop bug, and 6 missing v1.x key mappings (commands, focus, options, string shorthand).
- Remove duplicate 'Attach on create' row in comparison table, keep
corrected version with '(default: true)' near socket_path
- Annotate pre_tab as (deprecated) in comparison table
- Annotate startup_window as accepting name or index
- Fix pre_tab description: deprecated predecessor, not alias (it was
renamed in tmuxinator, not aliased)
- Clarify startup_window renders as "#{name}:#{value}"
- tmuxinator min tmux is 1.8 (recommended), not 1.5; tmux 2.5 is explicitly unsupported - teamocil has no documented min tmux version - tmuxinator detach is via `attach: false` config or `--no-attach` CLI flag, not `-d` (which doesn't exist in tmuxinator)
- Add socket_path as item 16 (tmuxinator config key not handled) - socket_path takes precedence over socket_name in tmuxinator - tmuxp only accepts socket path via CLI -S flag - Add to summary table as missing Difference
- with_env_var is an import-only fix (tmuxp already has environment key), not a Limitation — moved to new "Import-Only Fixes" section - cmd_separator is irrelevant (tmuxp sends commands individually), clarified it needs no import
- Fix "1.5+" to "1.8+" in architecture description (was already fixed in overview table but missed in prose) - Clarify YAML anchors: tmuxinator enables via YAML.safe_load aliases param, not a config key - Clarify tmuxinator edit is alias of new command
…s equivalent tmuxp doesn't have startup_window/startup_pane keys but achieves the same result via focus: true on individual windows/panes. Add cross-reference annotation so users aren't misled by (none).
- before_script maps to on_project_first_start (runs only when session doesn't exist), not on_project_start (runs every invocation) - Add teamocil --here implementation details: sends cd via send-keys, decrements window count for index calculation
- import-teamocil.md: Code block comment said "Lines 144-149" but the `if "filters"` guard is on line 143, so range is 143-149 - parity-teamocil.md: Referenced "Line 142" for `clear` handling but actual code is lines 140-141 (line 142 is blank)
…, expand CLI table - Fix min tmux: 1.5+ (not "1.8 recommended; not 2.5"), per tmux_version.rb - Note teamocil renames session (rename-session) rather than creating new - Add teamocil auto-generated session name detail - Expand pre_window to show full deprecation chain (rbenv/rvm/pre_tab) - Add synchronize values (true/before/after) - Add --suppress-tmux-version-warning to CLI table - Split deprecated pre/post into separate rows with hook mappings - Fix tmuxp --append flag syntax - Fix pane focus to note startup_pane equivalent
… chain, remove --here - Fix startup_window: accepts name OR index (not just name) - Document pre_window fallback chain: rbenv → rvm → pre_tab → pre_window - Remove section 12 (--here) — this is a teamocil feature, not tmuxinator - Renumber section 13 → 12 - Clarify freeze vs tmuxinator new comparison - Add rvm source reference (project.rb:181) - Add tmuxinator version range to header
…ore, multi-file load why: Source code analysis revealed details not captured in comparison table. what: - Note tmuxinator synchronize true/before deprecated in favor of after - Add pane-level shell_command_before row (tmuxp-unique feature) - Add multi-file loading CLI row (tmuxp load f1 f2)
…ormat default why: tmuxinator source confirms synchronize true/before is deprecated. what: - Note synchronize true/before deprecated in project.rb:21-29 - Add context that import should still honor original semantics per value - Document pane_title_format default and pane_title_position default
why: teamocil agent confirmed v1.0 explicitly dropped v0.x features. what: - Add paragraph explaining v1.0 rewrite dropped hooks, env vars, DSL - Provides context for why v0.x import has more keys than v1.x
why: Deprecation context helps prioritize import implementation. what: - Add deprecation note to synchronize row in summary table
why: Cross-referenced against teamocil source, no corrections needed. what: - Update last-updated date to 2026-03-07
why: Deprecation affects import behavior and priority decisions. what: - Note tmuxinator deprecates true/before in favor of after - Clarify that import should still honor original semantics per value
why: Cross-referencing issue #1016 against source code found 2 inaccuracies. what: - I1 Bug B: Add double-wrapping consequence when pre/pre_window types mismatch - T4: Clarify teamocil always renames session regardless of --here flag
why: Second parity pass found inaccurate fallback chain order and missing CLI commands/flags. what: - Fix pre_window fallback chain: pre_window → pre_tab → rbenv → rvm (was reversed) - Add doctor command and completions to commands table - Add start --append, --no-pre-window, --project-config flags - Add list --active, --newline flags
why: Second parity pass found undocumented behavioral differences. what: - Add section 8: teamocil applies layout after each pane split (vs tmuxp once at end) - Add section 10: root path expansion comparison (no gap, both tools expand) - Renumber existing sections 8-9 to 9-10
why: Third parity pass found importer test fixtures cover only ~40% of real-world patterns. what: - Add Tier 1 crash risks: v1.x teamocil string panes, commands key, rvm - Add Tier 2 missing coverage: YAML aliases, emoji names, pane titles, etc. - List required new fixtures for Phase 1 implementation
…ings why: Third parity pass found untested edge cases from tmuxinator spec fixtures. what: - Add section 18: YAML aliases/anchors (transparent, but untested) - Add section 19: numeric/emoji window names (YAML type coercion risk) - Update summary table with new entries
…organize phases why: libtmux#635 closed — all three API additions shipped in v0.55.0. Line references drifted as code grew. Phase structure misrepresented what's blocked vs unblocked. what: - Mark L1, L2, L3 as RESOLVED with correct libtmux source locations - Fix 20+ stale line number references across importers.py, builder.py, libtmux - Move T2 from Phase 3 to Phase 2, mark Phase 3 COMPLETE - Move T9 to Phase 5 as unblocked, remove L2/L3 from Phase 5 - Fix EnvironmentMixin location (common.py, not session.py)
…ignment why: Eliminate dead loop overhead in importers.py:160-166. what: - Replace `for _b in w["filters"]["before"]:` (and after) with direct assignment. The loop iterated N times but only ever set the same value, producing identical output but obscuring intent. - Output unchanged; tests confirm equivalence. ref: notes/plan.md I3
…tructs
why: tmuxinator's `pre` is a session-level hook that runs once before any
windows are created. The importer was mapping it to `shell_command_before`
(per-pane) when alone, and to the invalid `shell_command` key (silently
dropped) when combined with `pre_window`. Both produced wrong semantics
and execution counts.
Additionally, the combo branch's `isinstance(workspace_dict["pre"], str)`
checked the wrong variable to decide how to wrap `pre_window`.
what:
- Map `pre` -> `before_script` (session-level), matching tmuxinator
semantics in template.erb:18-19.
- Map `pre_window` -> `shell_command_before` independently; isinstance
check now correctly inspects `pre_window`'s type.
- Warn via `logger.warning` with extra={"tmux_key": "pre", ...} when
`pre` contains shell metacharacters (`|`, `&&`, `>`, `$(`, etc.) since
`before_script` runs via `subprocess.Popen` without `shell=True`.
- New module-private `_has_shell_metachars()` helper.
- Fix existing fixtures (test2/test3) that encoded the old buggy
behavior; expected output now matches corrected mapping.
ref: notes/plan.md I1
why: Lock in the corrected pre/pre_window mapping behavior. what: - New fixtures: test_pre_alone (solo pre -> before_script), test_pre_combo (pre + pre_window map independently), and test_pre_shell (pre with shell metacharacters). - Wire fixtures into the parametrized test_config_to_dict suite. - Add test_import_tmuxinator_warns_on_shell_metachars_in_pre asserting WARNING record with extra.tmux_key="pre" and extra.tmux_session set. Build workspace inline since the parametrized fixture dict gets mutated by the importer's .pop() calls in earlier tests. - Add test_import_tmuxinator_no_warning_when_pre_is_plain as the negative case. ref: notes/plan.md I1
why: The previous `str.replace("-f", "").strip()` global replacement
was flag-unaware. It would corrupt paths containing `-f` (e.g.
`~/-f-test.conf`) and silently dropped `-L`/`-S` socket flags entirely.
what:
- New module-private `_parse_tmuxinator_tmux_args()` splits the
argument string with `shlex.split()` and walks tokens, extracting
`-f` -> `config`, `-L` -> `socket_name`, `-S` -> `socket_path`.
- Unknown flags log `WARNING` with extra={"tmux_key": <flag>}.
- Existing test2 (`cli_args: "-f ~/.tmux.mac.conf"`) and test3
(`tmux_options: "-f ~/.tmux.mac.conf"`) still pass — same output
for the simple case.
- Behavior change: configs that previously passed `-L`/`-S` flags
in `cli_args`/`tmux_options` now have those mapped to their tmuxp
equivalents instead of being dropped.
ref: notes/plan.md I2
why: Verify I2 fix for fragile -f parsing.
what:
- New fixture test_cli_args_multi: `-f ~/.tmux.conf -L mysock -S /tmp/...`
-> config + socket_name + socket_path (was: only -f extracted, -L/-S
silently dropped).
- New fixture test_cli_args_dash_path: `-f /home/me/-f-config.conf`
-> config preserved (was: corrupted by str.replace("-f", "")).
- Both wired into parametrized test_config_to_dict.
- New test_import_tmuxinator_warns_on_unknown_cli_args_flag asserts
WARNING fires with extra.tmux_key=<flag>.
ref: notes/plan.md I2
…ttach
why: These tmuxinator config keys were silently dropped by the importer.
Add explicit translation matching tmuxinator's actual semantics.
what:
- `rvm` -> wrapped as `rvm use {value}` in shell_command_before, mirroring
tmuxinator project.rb:181.
- `pre_tab` -> shell_command_before (deprecated predecessor to pre_window).
- `pre_window` source resolution now follows tmuxinator's OR-fallback
chain (rbenv -> rvm -> pre_tab -> pre_window) — first non-nil wins,
matching project.rb:175-188.
- `on_project_first_start` -> before_script when `pre` not set.
- `socket_path` -> socket_path (top-level pass-through).
- `attach: false` -> WARNING directing user to `tmuxp load -d`.
- `startup_window` / `startup_pane`: scan windows by name OR integer
index, set `focus: true` on matched window/pane. Unresolved values
emit WARNING. Pane resolution converts positional pane strings to
dict form when adding `focus`.
- New helpers: `_apply_tmuxinator_startup_focus()`,
`_resolve_startup_index()`.
ref: notes/plan.md I5
why: Lock in the I5 behavior for the new tmuxinator key translations.
what:
- New fixtures: test_rvm, test_startup_window_by_{name,index},
test_socket_path. All wired into parametrized test_config_to_dict.
- New unit tests:
- test_import_tmuxinator_warns_on_attach_false (I5: attach false ->
WARNING about CLI -d).
- test_import_tmuxinator_on_project_first_start_falls_back_to_pre
(I5: hook key mapped to before_script when `pre` absent).
- test_import_tmuxinator_pre_window_chain_first_match_wins (I5:
rbenv wins over rvm/pre_tab/pre_window per project.rb:175-188).
- test_import_tmuxinator_warns_on_unresolved_startup_window (I5:
name not found -> WARNING with tmux_key=startup_window).
ref: notes/plan.md I5
…/clear
why: Triage the v0.x-only TODOs that were in the importer's docstring.
what:
- with_env_var (default true in v0.x per teamocil 0.4-stable): when the
`session:` wrapper is present (v0.x marker) and `with_env_var` is not
explicitly false, emit `environment: {TEAMOCIL: "1"}` at the session
level so each pane inherits the env var.
- cmd_separator: emit a WARNING that it has no effect in tmuxp, since
tmuxp sends commands individually via separate send-keys calls.
- clear: still preserved on the window dict, but emit a WARNING that
the builder does not yet act on it (deferred to a future T-item).
- Refactor the v0.x detection: capture `is_v0x = "session" in
workspace_dict` once for the with_env_var gate.
- Update docstring TODOs: remove the now-handled keys, document the
per-key behavior in a Notes section.
- Existing fixture `three_windows_within_a_session` (the only v0.x
multisession layout) updated to expect the new TEAMOCIL env var.
ref: notes/plan.md I7
why: Lock in I7 behavior for the v0.x TODO key triage.
what:
- New fixtures: test_with_env_var_default (default true -> TEAMOCIL=1)
and test_with_env_var_false (explicit false -> no env var). Wired
into parametrized test_config_to_dict.
- New unit tests:
- test_import_teamocil_warns_on_cmd_separator (I7: WARNING with
extra.tmux_key=cmd_separator).
- test_import_teamocil_warns_on_clear (I7: WARNING with
extra.tmux_key=clear).
- test_import_teamocil_v1x_skips_env_var (I7 regression: a v1.x
config (no session: wrapper) gets no TEAMOCIL env var).
ref: notes/plan.md I7
…itted
why: Real-world v0.x configs sometimes omit the `session:` wrapper but
still use v0.x pane keys (`splits`, `cmd`) and `filters`. Routing them
to the v1.x path silently dropped commands.
what:
- New `_has_v0x_window_markers()` helper inspects the inner workspace
for v0.x signals: window has `splits` or `filters`, or any pane has
`cmd`. Routes to `_import_teamocil_v0x` if found.
- All existing v0.x test fixtures (test1-test4 and the layouts.py
multisession scenarios) updated to expect the new
`environment: {TEAMOCIL: "1"}` from I7's with_env_var default.
- The v1.x skip test (`test_import_teamocil_v1x_skips_env_var`) now
uses the real v1.x `commands` key (was using v0.x `cmd` and
incorrectly being treated as v1.x by the old detection).
ref: notes/plan.md I4
why: Lock in I4 behavior — string pane shorthand, `commands` key,
per-window/pane `focus`, window `options`, and the v1.x format
dispatch.
what:
- New fixture test_v1x_string_pane: bare string panes
(`panes: [vim, top]`) -> `[{shell_command: [vim]}, {shell_command: [top]}]`.
- New fixture test_v1x_full: covers `commands`, window `focus`,
pane `focus`, window `options`, mixed string + dict panes,
session-level `root`, window-level `root`.
- Both wired into parametrized test_config_to_dict.
ref: notes/plan.md I4
why: `width` was already popped silently. `height` and `target` were
left on the pane dict (silently passing through to the builder, which
ignored them). Make all three pop with an audible WARNING so users
know the importer dropped per-pane geometry.
what:
- Loop over ("width", "height", "target") inside the v0.x pane loop;
pop each and emit `logger.warning` with extra={"tmux_key": <key>}.
- Update existing layouts fixture expected output to drop the
previously-preserved `target` key.
ref: notes/plan.md I6
why: Lock in I6 behavior — width/height/target each warn when popped. what: New test_import_teamocil_warns_on_v0x_pane_geometry asserts all three keys produce WARNING records with extra.tmux_key set. ref: notes/plan.md I6
why: Phase 1 (Import Fixes) is complete. Update plan.md status so the table reflects shipped behavior. what: - I1: pre → before_script with shell-metachar warning. - I2: shlex parsing for cli_args/tmux_options. - I3: direct assignment replaces redundant filter loops. - I4: v0.x/v1.x dispatch, detection by session: wrapper OR splits/filters/cmd markers; v1.x handles string panes, commands, focus, options. - I5: pre_window OR-fallback chain (rbenv→rvm→pre_tab→pre_window); startup_window/pane resolved to focus: true; on_project_first_start fallback; socket_path pass-through; attach: false warns. - I6: v0.x height/target now popped with WARNING. - I7: with_env_var → environment.TEAMOCIL=1 for v0.x; cmd_separator and clear warn (clear builder support deferred). Total Phase 1 commits: 14 (7 source + 7 tests). ref: notes/plan.md Phase 1
…Phase 1 why: Phase 1 of the tmuxinator-parity branch (PR #1014) is behavior- changing for users importing tmuxinator/teamocil configs. Document what changed so upgraders know what to expect. what: Adds a "Behavior changes — tmuxinator/teamocil import" section to the upcoming-release placeholder, summarizing all 7 import-side fixes and the v1.x teamocil format support. Also drops a stray blank line in tests/workspace/test_import_teamocil.py left by an autosquash conflict resolution (cosmetic, ruff-format).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/comparison.md— comprehensive feature comparison table (tmuxp vs tmuxinator vs teamocil) covering architecture, config keys, CLI commands, hooks, and config file discoverynotes/parity-tmuxinator.md— identifies 12 feature gaps, import bugs, and WorkspaceBuilder requirements for tmuxinator paritynotes/parity-teamocil.md— documents v0.x/v1.x format differences, 3 feature gaps, and import bugsnotes/import-tmuxinator.md— classifies each tmuxinator config key as translatable difference or tmuxp limitation, identifiespre/pre_windowbugnotes/import-teamocil.md— documents v0.x-only importer targeting (v1.x unsupported), string pane TypeError bug, redundant filter loopsnotes/plan.md— mark L1/L2/L3 as resolved (libtmux v0.55.0), fix 20+ stale line number references, reorganize phases to reflect unblocked items (T2, T9)Key findings
Importer bugs discovered:
import_tmuxinator: when bothpreandpre_windowexist, writes toshell_command(not a valid tmuxp session key) —precommands silently lostimport_teamocil: targets v0.x format only; v1.x string panes cause TypeError; redundantfor _b inloops in filter handlingtmuxinator feature gaps (12):
Lifecycle hooks (5 hooks vs tmuxp's 1), pane synchronization, pane titles, ERB templating, wemux support, stop/kill command, debug/dry-run, config management CLIs,
--no-pre-windowflagteamocil feature gaps (3):
--hereflag (reuse current window),--debugdry-run mode,shell_command_aftertmuxp advantages (unique features):
Per-pane environment/shell/sleep/history control, plugin system, JSON config, session freeze, workspace search, upward config traversal
Test plan
importers.pyline numbers