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.43% +0.47%
==========================================
Files 28 31 +3
Lines 2545 2921 +376
Branches 485 556 +71
==========================================
+ Hits 2086 2408 +322
- Misses 328 371 +43
- Partials 131 142 +11 ☔ 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
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
…ummaries 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
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).
why: Tmuxinator's `synchronize` key turns on `synchronize-panes` for a
window. tmuxp silently ignored it. With this change, configs that import
from tmuxinator preserve the sync semantics.
what:
- builder.iter_create_windows: when `synchronize` is True or "before",
call `window.set_option("synchronize-panes", "on")` after the
window's `options` block is applied. Pane commands run with sync
enabled.
- builder.config_after_window: when `synchronize` is "after", call the
same option after pane commands complete. Matches tmuxinator's
recommended modern usage (true/before are deprecated upstream but
still accepted).
- import_tmuxinator: pass `synchronize` through unchanged on the
window dict so the builder picks it up.
ref: notes/plan.md T1
why: Lock in T1 behavior across before/after/omitted/true.
what:
- 3 new fixtures (synchronize_before/after/omitted.yaml).
- Parametrized test_synchronize_panes asserts
`window.show_option('synchronize-panes')` is truthy after build for
before/after, falsy when omitted.
- test_synchronize_panes_true_treated_as_before locks in the
true/before equivalence inline (no fixture needed).
ref: notes/plan.md T1
… pane
why: teamocil's `filters.after` (and the I3-fixed importer) emits
`shell_command_after` on a window dict, but tmuxp silently ignored it.
Builder now reads the key and sends each command to every pane after
the main `shell_command` block runs.
what:
- builder.config_after_window: iterate
`window_config.get("shell_command_after", [])` and for each command
call `pane.send_keys(cmd, suppress_history=False)` on every pane in
the window. Window-level only — no trickle to/from session, matching
teamocil's filter semantics.
ref: notes/plan.md T3
why: Lock in the new builder behavior — the after-commands must actually appear in every pane's output. what: - New fixture shell_command_after.yaml: 1 window with shell_command_after: [echo TMUXP_T3_MARKER] and 2 panes. - New test_shell_command_after_runs_in_each_pane uses retry_until on pane.capture-pane to check for the marker in each pane. - @pytest.mark.flaky(reruns=5) since send_keys output capture is timing-sensitive (matches existing test_window_options_after). ref: notes/plan.md T3
why: tmuxinator users have `--no-pre-window` to skip per-pane prep commands during debugging. tmuxp's equivalent: skip the trickle of shell_command_before from session/window/pane levels into each pane's shell_command list. what: - New `--no-shell-command-before` CLI flag on `tmuxp load` (action=store_true, default False). Added to CLILoadNamespace too. - load_workspace gains a `no_shell_command_before` kwarg which is forwarded to loader.trickle(). - loader.trickle now accepts a keyword-only `no_shell_command_before` parameter; when True, skip the entire shell_command_before propagation block for every pane. - Behavior difference from tmuxinator's --no-pre-window noted in the trickle docstring: tmuxinator's flag only suppresses pre_window proper, while tmuxp's flag is broader (skips all shell_command_before regardless of source). ref: notes/plan.md T7
why: The T7 source commit (`a97730a8`) added the kwarg to trickle's signature but a stale edit lost the actual `if not no_shell_command_before:` guard around the prepend block. The kwarg was a no-op until now. what: - loader.trickle: wrap the three `shell_command_before` extend calls in `if not no_shell_command_before:` so the flag actually skips propagation. - tests/workspace/test_config.py: add test_trickle_no_shell_command_before_skips_propagation covering both flag values; deepcopy between calls since trickle mutates nested dicts. ref: notes/plan.md T7
why: tmuxinator's named-pane syntax sets both a pane title and its
command (assets/template.erb:54, pane.rb:35-39). tmuxp had no equivalent.
With L1 (Pane.set_title) shipped in libtmux v0.55.0, the builder can
now wire it through.
what:
- builder.build session-level options block: read enable_pane_titles
(toggle), pane_title_position (default "top"), pane_title_format
(default "#{pane_index}: #{pane_title}"). Apply via
session.set_option("pane-border-status"/"pane-border-format").
- builder.iter_create_panes: after send_keys, before focus handling,
call pane.set_title(pane_config["title"]) when title is present.
Title is stored on the pane regardless of border-status (per tmux
cmd-select-pane.c:215-221).
- import_tmuxinator: new _normalize_tmuxinator_pane helper translates
tmuxinator's named-pane shorthand {name: cmd} into
{title: name, shell_command: [cmd]} so the builder picks it up.
ref: notes/plan.md T2
why: Lock in T2 behavior. pane-border-status / pane-border-format are window-scope options; the initial source landed without global_=True which silently no-op'd at session level (tests caught this). what: - builder: set pane-border-status / pane-border-format with global_=True so the values apply across every window in the session (matches tmuxinator's `set-option -g`). - New fixture pane_titles.yaml. - 3 new tests: explicit position+format, per-pane title verified via display-message format query, defaults-only path. All read options via show_option(..., global_=True). ref: notes/plan.md T2
why: tmuxinator's hook system fires shell commands at well-defined phases (template.erb:14, hooks/project.rb:1-44). tmuxp had `before_script` covering only the first-start case. With T6 the full hook set lands. what: - util.run_lifecycle_hook: new helper accepting str | list[str] | None. Iterates list values sequentially and calls run_before_script for each item. No shell=True (matches before_script's semantics — users wrap shell logic in script files). Aborts list iteration on first non-zero exit code. - builder.build: after `before_workspace_builder` plugin and before `before_script`, fire on_project_start (always), then on_project_restart (when append=True) or on_project_first_start (otherwise). - Hooks share the same `cwd` resolution (session start_directory) and output callback (on_script_output) as before_script. - on_project_exit and on_project_stop wire in via cli/load.py and cli/stop.py respectively in subsequent commits. ref: notes/plan.md T6
why: Lock in the T6 helper's contract — string vs list, sequential execution, abort-on-failure, exception propagation. what: - test_run_lifecycle_hook_none_is_noop: None value returns 0. - test_run_lifecycle_hook_string: single string is run once. - test_run_lifecycle_hook_list_runs_each: list iterates in order (verified by appending to a log file). - test_run_lifecycle_hook_aborts_on_first_failure: when an item exits non-zero, BeforeLoadScriptError raises and remaining items are not invoked. - test_run_lifecycle_hook_propagates_not_found: missing script path raises BeforeLoadScriptNotExists (same as run_before_script). ref: notes/plan.md T6
why: tmuxinator ships new, copy, delete, and implode for workspace config file management (cli.rb:78-457). tmuxp had only `edit`. This brings parity for the full lifecycle of workspace files. what: - New module src/tmuxp/cli/manage.py groups the 4 commands so the shared file-IO helpers (_confirm, _config_path, _open_in_editor, _ensure_dir) live in one place. Each command has its own typed Namespace, subparser builder, and entry function — same shape as the existing per-command modules (load.py, freeze.py). - new <name>: writes a starter YAML to the user's workspace dir if missing, then opens in $EDITOR. - copy <src> <dst>: validates src via find_workspace_file, copies to dst path, prompts on overwrite (unless -y), opens dst in $EDITOR. - delete <name>...: per-name confirmation prompt (unless -y), unlinks each. Skips non-existent with a warning. - implode: deletes ALL tmuxp config directories (legacy ~/.tmuxp + XDG ~/.config/tmuxp). Single global confirmation (unless -y). - Wired into cli/__init__.py: imports, subparsers, dispatch, and the CLISubparserName Literal. ref: notes/plan.md T10
why: Lock in T10 behavior across all 4 management commands. what: - configdir/no_editor fixtures: monkeypatch TMUXP_CONFIGDIR to tmp_path and replace subprocess.call (the $EDITOR invocation) with a no-op so tests run headless. - new: writes starter YAML when missing; preserves an existing file. - copy: duplicates src content to dst; aborts when user declines overwrite (input mocked). - delete: -y removes the file; missing name doesn't raise. - implode: removes every dir from _implode_dirs() with -y; aborts when user declines (dir + content survive). ref: notes/plan.md T10
why: tmuxinator pre-processes its YAML through Erubi (full Ruby) so
config files can interpolate runtime values. tmuxp gets the equivalent
without any new dependency: a ~50-LOC stdlib regex-based engine that
handles only ${var} and ${var:-default} (no conditionals/loops/Ruby
escape hatches). Pre-YAML rendering matches tmuxinator's
ERB-before-YAML semantics.
what:
- New module src/tmuxp/_internal/template.py exporting render() and
parse_cli_vars(). Doctests cover the canonical cases.
UnresolvedVariableError subclasses KeyError so existing
except-KeyError sites still catch.
- cli/load.py: new repeatable `-D KEY=VALUE` / `--var KEY=VALUE` flag.
Plumbed through CLILoadNamespace, command_load, and load_workspace.
- load_workspace: when template_vars is non-empty AND the workspace
file is YAML, read the raw text, render with strict=False, then
hand to ConfigReader._load("yaml", rendered). JSON files are
parsed as-is (escaping headaches not worth the marginal benefit).
- strict=False at the load site so unresolved ${HOME}-style refs flow
through to loader.expandshell, preserving the existing env-var
expansion behaviour.
ref: notes/plan.md T8
why: Lock in the T8 template engine's contract. what: - 12 RENDER_FIXTURES via NamedTuple parametrize (test_id-based ids): plain text, braced, defaults, defaults overridden, missing-strict raises, multiple substitutions, special chars in defaults, underscore names, bare $ untouched, env-var-like syntax, empty default, dash in default. - test_render_non_strict_leaves_missing_alone + test_render_non_strict_still_substitutes_known: cover the load.py integration mode where unresolved vars flow to expandshell. - test_render_default_does_not_apply_when_explicit_none and test_render_unresolved_error_is_keyerror_subclass: lock in the exception contract. - 6 PARSE_FIXTURES for parse_cli_vars: empty, single, multiple, value-contains-equals (URL with query string), empty value, missing-equals raises ValueError. ref: notes/plan.md T8
why: tmuxinator's `stop <project>` (cli.rb:300-322 + template-stop.erb) fires the project's on_project_stop hook then kills the session. tmuxp had no equivalent; users had to `tmux kill-session` directly which skipped any cleanup hooks. what: - New module src/tmuxp/cli/stop.py with command_stop / CLIStopNamespace / create_stop_subparser, mirroring the existing per-command module shape (load.py, freeze.py). - Resolves workspace by name via find_workspace_file, reads session_name + on_project_stop from the config, fires the hook (via T6's run_lifecycle_hook) then calls Server.kill_session. - Idempotent: if no server is alive or session doesn't exist, prints a muted "nothing to stop" and returns without error. - Wired into cli/__init__.py imports, subparsers, dispatch, and the CLISubparserName Literal. Per template-stop.erb tmuxinator runs on_project_stop only (NOT on_project_exit). tmuxp matches that. ref: notes/plan.md T5
ref: notes/plan.md T5
why: teamocil's --here lets users layer a workspace onto the tmux session they're already attached to. tmuxp had no equivalent. what: - New --here flag on tmuxp load. Mutually exclusive with --append. Refuses to run outside a tmux session (TMUX env var must be set). - When --here is set, force append=True so the existing append codepath handles the build (windows added to current session). - args.here flows through CLILoadNamespace and load_workspace(). ref: notes/plan.md T4
why: Lock in the precondition checks the T4 source commit added to load_workspace. what: - test_load_with_here_outside_tmux_errors: with TMUX env var unset, --here raises TmuxpException with the documented message. - test_load_with_here_and_append_errors: with TMUX set (to bypass the outside-tmux check) but both --here and --append given, raises TmuxpException with "mutually exclusive". The full --here-into-real-session smoke test requires running tmuxp from inside an actual nested tmux, deferred to manual verification. ref: notes/plan.md T4
why: tmuxinator's `debug` outputs the rendered shell script for preview.
tmuxp uses libtmux API calls instead of script generation, so the
honest-equivalent preview is to run the build against an isolated tmux
server (so the user's main tmux is untouched), surface libtmux's
existing DEBUG-level `tmux command dispatched` log at INFO, then kill
the temp server.
what:
- New `--dry-run` flag on `tmuxp load`. When set:
- Generate a unique socket name (tmuxp-dryrun-<pid>-<rand>) and
override args.socket_name so the temp server is isolated.
- Force detached=True so we don't attach to a sandbox session.
- Bump libtmux + tmuxp loggers to DEBUG so every libtmux call's
`tmux command dispatched` record (libtmux common.py:284-289) is
visible to the user.
- Wrap the load_workspace call in try/finally; on exit, call
Server(socket_name=...).kill_server() to clean up. Cleanup is
best-effort (suppressed if the build raised early).
- args.dry_run flows through CLILoadNamespace.
Trade-off vs a true zero-execution dry-run: real tmux processes spawn
briefly but the user's main tmux server is never touched. That's the
honest-preview compromise documented in notes/plan.md T9.
ref: notes/plan.md T9
…ons resolved why: This branch closes the remaining feature gaps with tmuxinator and teamocil. Document the new config keys, CLI flags, and CLI commands in user-facing language so the changelog reads like product news, not an internal task list. Stamp the plan's gap section as historical so the next reader knows it's design context, not current backlog. what: - CHANGES: new "New features — tmuxinator/teamocil parity" section above the existing "Behavior changes" entry. Grouped into "New config keys", "New CLI flags on tmuxp load", and "New CLI commands" with one bullet per feature describing what the user can now do. - notes/plan.md: short status callout under "## tmuxp Limitations" pointing readers to CHANGES for current behavior. The gap-by-gap sections below remain intact as design notes for future maintainers.
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