Repository navigation
/terminal-setup writes a new ~/.tmux.conf without checking for an existing tmux config or saying it created a file #1972
Description
Summary
When run inside tmux, /terminal-setup always targets ~/.tmux.conf. If that file does not exist, the command creates it, even when the user's tmux config lives at ~/.config/tmux/tmux.conf. The only message shown is Updated <path>, which reads as an edit to an existing file. It does not say a new file was created, that another config was found, or which lines were written.
Expected: /terminal-setup should find the config tmux actually uses, edit that file, and report clearly what it changed. It should not create a second config file without saying so.
Reproduction
-
Keep the tmux config at
~/.config/tmux/tmux.conf, with no~/.tmux.conf. -
Run jcode inside a tmux pane and run
/terminal-setup. -
A new
~/.tmux.confis created containing only:# jcode: let Shift+Enter reach the application instead of collapsing to Enter. set -s extended-keys on set -s extended-keys-format csi-u set -as terminal-features 'xterm*:extkeys'
-
The command output is
✓ Configured tmux …/Updated /Users/<user>/.tmux.conf/Run tmux source ~/.tmux.conf, then restart jcode.
The real config is left unchanged. The output gives no hint that there are now two config files.
Impact
A new config file next to the existing one can change which settings tmux loads, depending on how tmux is started. In the setup where this was found, a shell wrapper loads only one config file and prefers ~/.tmux.conf. The next tmux session started with only the 3 jcode lines and none of the user's settings. Because the output had said "Updated", it was not clear that /terminal-setup had caused this. The cause only became visible after tracing the shell's tmux startup back to the new file.
Which tools pick which file differs: tmux ≥3.2 loads every file in its default search list, while wrappers, plugin managers, and dotfile setups often load just one. jcode cannot know all of these. The safe behavior is to avoid creating a second config file and to state clearly what was written.
Root cause
crates/jcode-tui/src/tui/terminal_setup.rs:
pub fn tmux_config_path(home: &Path) -> PathBuf {
home.join(".tmux.conf")
}- No config discovery. The path is hardcoded.
$XDG_CONFIG_HOME/tmux/tmux.confand~/.config/tmux/tmux.confare never checked, and the running tmux server is never asked which files it loaded. - A missing file means "create it".
apply_tmuxreads the path withunwrap_or_default(), treats a missing file as an empty config, and writes a new file. - The "already configured" check reads the wrong file.
tmux_config_is_configuredonly looks at~/.tmux.conf. A user who already setextended-keysin an XDG config still gets a new file. - The message hides what happened.
Applied::Changed { detail: "Updated …" }uses the same wording for creating a file and for appending to one. The written lines are not shown. - The reload hint is hardcoded.
activation_notealways saystmux source ~/.tmux.conf, whatever file was written. - Tests and docs treat the path as correct. The test
config_paths_are_the_documented_locationsanddocs/SHIFT_ENTER.mdboth assert~/.tmux.conf.
The WezTerm path has the same problem: wezterm_config_path hardcodes ~/.wezterm.lua and ignores $XDG_CONFIG_HOME/wezterm/wezterm.lua.
Related: unreadable config gets overwritten
apply_tmux and apply_wezterm turn any read error into an empty string, not only NotFound. A config with non-UTF-8 bytes (InvalidData), for example, is then treated as empty, and std::fs::write replaces the whole file with only the jcode block. Only ErrorKind::NotFound should count as an empty config. Any other read error should be reported and stop the command.
Expected behavior
Checking
- Find the config tmux actually uses. Inside tmux,
tmux display -p '#{config_files}'lists the files the running server loaded. Otherwise, check tmux's default search order (~/.tmux.conf,$XDG_CONFIG_HOME/tmux/tmux.conf,~/.config/tmux/tmux.conf). - Look for existing
extended-keyssettings in all of those files, not just one, before deciding anything needs to change. - Never create a new config file when one already exists in the search path. Append to the file in use. If several exist and it is unclear which one the server loaded, ask.
- If no config exists anywhere, ask before creating one, and say where it will go.
- Treat only
NotFoundas an empty config. Report any other read error and write nothing.
Feedback
- Say exactly what was done: "Created new file
<path>" or "Appended 3 lines to<path>". - Show the lines that were written.
- Name any other tmux config files found, especially when the change went into a different file.
- Build the reload hint from the file actually written (
tmux source-file <path>).
Optional
- Apply the settings to the running server first (
tmux set -s extended-keys on, etc.), and make writing them to a file a separate step the user confirms.
Environment
- jcode v0.99.154-dev; same code at upstream
b09a8a5 - tmux 3.8, macOS, kitty
- tmux started through a shell wrapper that loads only one config file. This explains why the effect was so visible here, but the problems above are in jcode's checking and reporting, whatever wrapper is used.
Activity
ianalitis commentedon Oct 26, 2026
Reproduced the shape of the problem from the code:
/terminal-setuptargets~/.tmux.confunconditionally, creates it when missing, and reports the same "Updated " line either way, so a second config can appear without the user being told.Two open PRs address it and they overlap heavily: #1975 (@aphelion31) and #1976 (@ianalitis). Both replace the fixed path with discovery of the config tmux actually reads and stop the "Updated" wording from covering a create. A maintainer should pick one rather than merge both, so this is bucketed needs-decision until that choice is made.
Independent of which lands: reporting "Created X" vs "Updated X" and mentioning the other config files that were found is the part that prevents the reported footgun, and it is worth keeping in whichever version merges.
— Jcode agent (automated triage), on behalf of @1jehuang