Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions home-manager/programs/tmux/tmux.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ set-option -g automatic-rename-format '#{b:pane_current_path}'
set-window-option -g mode-keys vi
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi r send-keys -X rectangle-toggle
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'pbcopy'
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel '#{@clipboard_cmd}'

# Open splits and windows in the current folder
bind u split-window -l 30% -v -c "#{pane_current_path}"
Expand All @@ -37,6 +37,7 @@ set-option -g repeat-time 1000

# Clipboard
set -g set-clipboard on
set -g @clipboard_cmd "command -v pbcopy >/dev/null 2>&1 && pbcopy || { [ -n \"$WAYLAND_DISPLAY\" ] && wl-copy || xclip -selection clipboard; }"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The removal of reattach-to-user-namespace could cause clipboard issues on some macOS systems where it's required for tmux to access the system pasteboard. The original configuration used it for mouse-drag copying.

To ensure compatibility, I recommend updating the @clipboard_cmd to check for reattach-to-user-namespace and use it with pbcopy if it's available. This makes your cross-platform solution more robust.

set -g @clipboard_cmd "command -v reattach-to-user-namespace >/dev/null 2>&1 && reattach-to-user-namespace pbcopy || command -v pbcopy >/dev/null 2>&1 && pbcopy || { [ -n \"$WAYLAND_DISPLAY\" ] && wl-copy || xclip -selection clipboard; }"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

鈿狅笍 Potential issue | 馃煚 Major

馃З Analysis chain

馃弫 Script executed:

#!/bin/bash
set -euo pipefail
rg -nP '^\s*set\s+-g\s+@clipboard_cmd\s+".*\$WAYLAND_DISPLAY.*"$' home-manager/programs/tmux/tmux.conf
# Expected (current state): one match at Line 40
# Expected (after fix): no matches

Repository: shunkakinoki/dotfiles

Length of output: 212


馃寪 Web query:

In tmux config, are $ENV vars expanded when parsing set -g @option "..."? What is the recommended way to preserve $WAYLAND_DISPLAY for runtime shell evaluation in clipboard commands?

馃挕 Result:

No, $ENV vars like $WAYLAND_DISPLAY are not expanded when parsing set -g @option "..." in tmux config. Tmux config parsing replaces $ENV with values from the global environment at parse time, storing the literal expanded string as the user option value. User options (@options) are arbitrary strings without further shell-like expansion. This follows the general command parsing rule where $vars expand during parsing, before execution. The recommended way to preserve $WAYLAND_DISPLAY for runtime shell evaluation in clipboard commands is to use set -s copy-command "wl-copy" (requires tmux 3.2+ and wl-clipboard package). This sets a server option where the command string has $WAYLAND_DISPLAY expanded at config parse time from the global env (inherited when tmux server starts). At runtime, when copy-pipe or similar invokes the copy-command during copy operations, it runs the shell command in a new shell inheriting the current session's environment, which includes $WAYLAND_DISPLAY if preserved via set-environment -g WAYLAND_DISPLAY or update-environment WAYLAND_DISPLAY in .tmux.conf. To ensure $WAYLAND_DISPLAY is available in sessions/shells: set-environment -g WAYLAND_DISPLAY $WAYLAND_DISPLAY or set update-environment "WAYLAND_DISPLAY" The latter copies it from global to session env on new sessions. For copy bindings (vi mode example): bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "wl-copy" With set -g mouse on, mouse selections will use copy-command automatically. This works because the subshell launched by copy-pipe/copy-command inherits the pane's environment, including $WAYLAND_DISPLAY.

Citations:


Runtime detection frozen at parse time due to double-quote expansion.

Line 40 uses $WAYLAND_DISPLAY inside double quotes in the tmux option value. Tmux expands $ENV variables during config parsing (not at runtime), so the clipboard backend selection locks to whatever environment was present when the tmux server started. This directly breaks runtime environment adaptation. Additionally, wl-copy and xclip should have command existence checks before use.

馃敡 Suggested fix
-set -g `@clipboard_cmd` "command -v pbcopy >/dev/null 2>&1 && pbcopy || { [ -n \"$WAYLAND_DISPLAY\" ] && wl-copy || xclip -selection clipboard; }"
+set -g `@clipboard_cmd` 'if command -v pbcopy >/dev/null 2>&1; then pbcopy; elif [ -n "$WAYLAND_DISPLAY" ] && command -v wl-copy >/dev/null 2>&1; then wl-copy; elif [ -n "$DISPLAY" ] && command -v xclip >/dev/null 2>&1; then xclip -selection clipboard; else exit 1; fi'

Use single quotes to defer variable expansion until shell execution time, and add command checks for both fallback commands.

馃 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@home-manager/programs/tmux/tmux.conf` at line 40, The tmux option set -g
`@clipboard_cmd` currently uses double quotes so $WAYLAND_DISPLAY is expanded at
tmux parse time; change the value assigned by set -g `@clipboard_cmd` to use
single quotes so the shell evaluates $WAYLAND_DISPLAY at runtime, and update the
shell expression referenced by `@clipboard_cmd` to check for the existence of
wl-copy and xclip (e.g., using command -v wl-copy >/dev/null 2>&1 && wl-copy)
before falling back, ensuring each fallback has a command-existence test and
pbcopy remains checked first.


# Status bar
set -g status "on"
Expand All @@ -59,7 +60,7 @@ bind r command-prompt -I "#{window_name}" "rename-window '%%'"
bind R command-prompt -I "#{session_name}" "rename-session '%%'"

# Copy text on select
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy"
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel '#{@clipboard_cmd}'

# Switch window
bind , previous-window
Expand Down Expand Up @@ -90,8 +91,8 @@ bind-key "%" split-window -h -c "#{pane_current_path}"
bind-key '"' split-window -v -c "#{pane_current_path}"

# Yank pane history to clipboard
bind y run-shell 'tmux capture-pane -pS - | pbcopy && tmux display-message "Full pane history copied to clipboard"'
bind v run-shell 'tmux capture-pane -p | pbcopy && tmux display-message "Visible pane copied to clipboard"'
bind y run-shell 'tmux capture-pane -pS - | #{@clipboard_cmd} && tmux display-message "Full pane history copied to clipboard"'
bind v run-shell 'tmux capture-pane -p | #{@clipboard_cmd} && tmux display-message "Visible pane copied to clipboard"'
Comment on lines +94 to +95

Copilot AI Mar 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The run-shell bindings are referencing @clipboard_cmd as {@clipboard_cmd} (missing the leading #), so tmux will not expand the option and the shell will try to execute a literal {...} token, breaking these bindings. Use the tmux format form #{@clipboard_cmd} here (matching the copy-mode bindings).

Copilot uses AI. Check for mistakes.

# Pane number indicator
set -g display-panes-colour colour233
Expand Down
Loading