tmux-python / tmux-python/tmuxp
here mode level 2: eliminate send_keys entirely — split-window/swap-pane/kill-pane
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 4.6k
- Forks
- 248
- Avg merge
- 2h 13m
- Merged PRs (30d)
- 1
Description
Parent: #1030
Approach
Eliminate all send_keys usage in --here mode by replacing the "mutate existing pane" pattern with "create fresh pane, swap into position." This is the cleanest possible approach — zero shell assumptions.
Core idea
Instead of sending cd, export, and shell commands to the existing pane (which assumes a POSIX shell is running), create a brand-new pane with the correct directory, environment, and shell, then swap it into the position of the original pane and kill the original.
Implementation
Replace builder.py:690-727:
# Before: send_keys cd, export, shell into existing pane
active_pane.send_keys(f"cd {shlex.quote(start_directory)}", enter=True)
for _ekey, _eval in environment.items():
_here_pane.send_keys(f"export {_ekey}={shlex.quote(str(_eval))}", enter=True)
_here_pane.send_keys(window_shell, enter=True)
With:
# After: create fresh pane with correct state, swap into position
_active_pane = window.active_pane
assert _active_pane is not None
# Build split-window args
split_kwargs: dict[str, t.Any] = {}
if start_directory:
split_kwargs["start_directory"] = start_directory
if environment:
split_kwargs["environment"] = environment
if window_shell:
split_kwargs["shell"] = window_shell
# Create new pane with correct dir/env/shell via tmux primitives
new_pane = window.split(**split_kwargs)
# Swap new pane into the position of the original
new_pane.cmd("swap-pane", "-t", _active_pane.pane_id)
# Kill the original pane (now in the split position)
_active_pane.kill()
How this maps to tmux commands
tmux split-window -c /path/to/dir -e KEY=VALUE [shell_command]
tmux swap-pane -t %original_pane_id
tmux kill-pane -t %original_pane_id
tmux version requirements
split-window -c: Available since tmux 1.9split-window -e: Available since tmux 3.2 (tmuxp's minimum)swap-pane: Available since tmux 0.8- All within tmuxp's tmux 3.2+ minimum requirement
Comparison with teamocil
teamocil uses send_keys cd for directory and split-window -c for new panes. This approach goes further than teamocil by eliminating even the cd send_keys call.
Trade-offs
Pros:
- Zero
send_keysfor infrastructure — no shell assumption at all - Works regardless of what's running in the active pane (vim, python, fish)
- Environment set at pane creation time via
-e(tmux 3.2+) - Directory set via
-c(tmux primitive) - Clean pane with fresh shell — no history pollution
Cons:
- Destroys the user's existing shell state (history, local variables, aliases loaded via
.bashrc) - Brief visual flash as the swap occurs
- More complex than Level 1 — uses
swap-pane+kill-panewhich is unusual in libtmux - The existing pane is killed — if the user had unsaved work in a background process, it's gone
- May need libtmux API additions if
split()doesn't support-ekwargs yet
Behavioral change
This changes --here semantics from "modify the existing pane in-place" to "replace the existing pane with a fresh one." Users who rely on existing shell state in the first pane would lose it. This may be acceptable since --here is conceptually "rebuild this window" — but it should be documented.
Tests to add/update
- Rewrite
test_here_mode_provisions_environmentto verify env via pane capture (new pane inherits env) - Rewrite
test_here_mode_start_directory_special_charsto verify cwd withoutsend_keys - Add test verifying
--hereworks when active pane runs a non-shell program - Add test verifying original pane is replaced (pane count stays at 1)
libtmux prerequisites
Check whether window.split() supports:
environmentkwarg (maps to-e KEY=VALUE)shellkwarg (maps to the shell/command argument)start_directorykwarg (maps to-c)
If not, these would need to be added to libtmux first.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read src/tmuxp/workspace/builder.py lines 690-727 and inspect whether libtmux window.split() supports environment, shell, and start_directory. Run the existing here-mode tests, including test_here_mode_provisions_environment and test_here_mode_start_directory_special_chars, then add coverage for non-shell panes and pane replacement. Done means --here avoids send_keys while preserving one pane with the requested directory, environment, and shell.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, tooling
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100