Skip to content

refactor(tmux): flatten tmuxinator dir and improve tsh/tss - #935

Merged
shunkakinoki merged 5 commits into
mainfrom
refactor/tmux-tsh-tss-tmuxinator
Feb 26, 2026
Merged

refactor(tmux): flatten tmuxinator dir and improve tsh/tss#935
shunkakinoki merged 5 commits into
mainfrom
refactor/tmux-tsh-tss-tmuxinator

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Feb 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Flatten config/tmuxinator/tmuxinator/*.ymlconfig/tmuxinator/*.yml, updating default.nix to reference each file directly
  • Make tsh default to pane content search (fzf over live + archived pane snapshots); optional arg pre-fills the query
  • Move session history log browsing to tss --log

Test plan

  • tsh opens fzf over pane content files
  • tsh <query> pre-fills fzf with query
  • tss --log browses session/window metadata log
  • tss still fuzzy-picks/creates sessions as before
  • NixOS rebuild picks up tmuxinator ymls at ~/.config/tmuxinator/

🤖 Generated with Claude Code


Summary by cubic

Flattened tmuxinator configs to config/tmuxinator/*.yml and updated Nix to reference each file. tsh now defaults to pane content search with rg previews (archived panes in bat); session history is now tss --log or tsw --log; added tsk to kill sessions/windows plus tmux Prefix+H (search) and Prefix+K (kill).

  • Migration
    • Replace tsh --log with tss --log (or tsw --log for window picking) in scripts/aliases.
    • Rebuild Home Manager/NixOS to sync tmuxinator files to ~/.config/tmuxinator/.

Written for commit f87cb97. Summary will update on new commits.

- Move tmuxinator ymls from config/tmuxinator/tmuxinator/ to config/tmuxinator/
- Update default.nix to reference each yml directly
- Make tsh default to pane content search (drop --log)
- Move session history log browsing to tss --log

Entire-Checkpoint: 813d9926c401
@mesa-dot-dev

mesa-dot-dev Bot commented Feb 26, 2026

Copy link
Copy Markdown

You do not have enough credits to review this pull request. Please purchase more credits to continue.

@coderabbitai

coderabbitai Bot commented Feb 26, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@shunkakinoki has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 6 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 6cfffbe and f87cb97.

📒 Files selected for processing (5)
  • home-manager/programs/fish/default.nix
  • home-manager/programs/fish/functions/_tsh_function.fish
  • home-manager/programs/fish/functions/_tsk_function.fish
  • home-manager/programs/fish/functions/_tsw_function.fish
  • home-manager/programs/tmux/tmux.conf
📝 Walkthrough

Walkthrough

Expands tmuxinator configuration from a single entry to four separate YAML profile files, and refactors fish shell functions to implement pane-content-based search workflow and add session history log navigation capability.

Changes

Cohort / File(s) Summary
Tmuxinator Configuration
config/tmuxinator/default.nix
Replaces single tmuxinator config source with four distinct xdg.configFile entries for primary, mobile, work, and desktop YAML profiles.
Fish Tmux Navigation Functions
home-manager/programs/fish/functions/_tsh_function.fish, home-manager/programs/fish/functions/_tss_function.fish
Reworks _tsh_function to search pane content files (live + archived) via rg with unified fzf selection flow; adds --log branch to _tss_function for session history log navigation with preview capability.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant RipGrep as rg<br/>(search)
    participant Fzf as fzf<br/>(selection)
    participant Tmux as Tmux<br/>(session mgmt)

    User->>RipGrep: Search pane content files<br/>(pane_dir + archive_dir)
    RipGrep-->>Fzf: Return matching files
    User->>Fzf: Select match with preview
    Fzf-->>User: Return selected pane filename
    User->>User: Parse filename for<br/>session & window index
    User->>Tmux: Validate session exists
    alt Session found
        User->>Tmux: Switch/attach and<br/>select window
        Tmux-->>User: Active session
    else Session missing
        User-->>User: Show archived<br/>pane content notice
    end
Loading
sequenceDiagram
    participant User
    participant SessionLog as Session History<br/>Log File
    participant Fzf as fzf<br/>(selection)
    participant Tmux as Tmux<br/>(session mgmt)

    User->>User: Invoke --log flag
    User->>SessionLog: Validate log exists<br/>(~/.local/share/tmux/session-history.log)
    alt Log found
        SessionLog-->>Fzf: Return log entries
        User->>Fzf: Select entry with preview
        Fzf-->>User: Return session/window entry
        User->>User: Parse session & window index
        User->>Tmux: Validate session exists
        alt Session active
            User->>Tmux: Switch/attach and<br/>select window
        else Session gone
            User-->>User: Error: session not found
        end
    else Log missing
        SessionLog-->>User: Error: log not found
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Four configs now dance where one lived before,
Pane contents searched with rg's eager roar,
Fzf picks the winners, tmux opens the door,
Session history logs get their --log encore!
Navigation flows smooth, what could we adore?

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: tmuxinator directory flattening and improvements to tsh/tss functions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description clearly aligns with the changeset, detailing the tmuxinator flattening, tsh pane search refactoring, and tss --log migration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/tmux-tsh-tss-tmuxinator

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @shunkakinoki, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request streamlines the management of tmuxinator configurations by flattening their directory structure and updating the NixOS configuration to reflect this change. Additionally, it refactors the tmux utility functions, tsh and tss, to improve their usability: tsh now primarily focuses on searching pane content with enhanced query capabilities, while tss gains a dedicated option for browsing session history.

Highlights

  • Tmuxinator Configuration Flattening: The config/tmuxinator/tmuxinator directory structure has been flattened, moving all tmuxinator YAML configuration files directly into config/tmuxinator.
  • NixOS Configuration Update: The config/tmuxinator/default.nix file was updated to explicitly reference each individual tmuxinator YAML file, adapting to the flattened directory structure.
  • Enhanced tsh Functionality: The tsh (tmux search history) function now defaults to searching live and archived tmux pane contents using fzf, and supports pre-filling the search query with command-line arguments.
  • Refactored tss for Session History: The functionality for browsing the tmux session history log has been moved from tsh to a new --log option within the tss (tmux session selector) function.
Changelog
  • config/tmuxinator/default.nix
    • Updated NixOS configuration to reference individual tmuxinator YAML files directly instead of the directory.
    • Removed the directory-level source for tmuxinator configurations.
    • Added explicit sources for primary.yml, mobile.yml, work.yml, and desktop.yml.
  • config/tmuxinator/desktop.yml
    • Renamed desktop.yml to flatten the directory structure.
  • config/tmuxinator/mobile.yml
    • Renamed mobile.yml to flatten the directory structure.
  • config/tmuxinator/primary.yml
    • Renamed primary.yml to flatten the directory structure.
  • config/tmuxinator/work.yml
    • Renamed work.yml to flatten the directory structure.
  • home-manager/programs/fish/functions/_tsh_function.fish
    • Changed _tsh_function description to reflect its new primary purpose: searching tmux pane contents.
    • Removed the conditional logic for searching session history log based on arguments.
    • Implemented default behavior to search live and archived pane content files using fzf.
    • Added support for pre-filling the fzf query with command-line arguments.
    • Simplified the session/window attachment logic after selecting a pane.
  • home-manager/programs/fish/functions/_tss_function.fish
    • Introduced a new --log option to _tss_function to browse the tmux session history log.
    • Moved the session history log search functionality from _tsh_function to _tss_function --log.
    • Implemented fzf-based browsing for the session history log when --log is used.
    • Included logic to attach to a selected session/window from the history log.
Activity
  • The pull request was generated with Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@mesa-dot-dev

mesa-dot-dev Bot commented Feb 26, 2026

Copy link
Copy Markdown

Mesa Description

TL;DR

Flattened tmuxinator configuration directory and updated default.nix to directly reference individual YAML files. Refactored tsh to focus on interactive pane content search using fzf and rg, with query pre-filling. Introduced tss --log and tsw --log for browsing and interacting with tmux session/window history, and added a tmux keybinding (Prefix+H) for pane content search.

What changed?

  • config/tmuxinator/default.nix: Modified to explicitly source individual project YAML files instead of sourcing the entire tmuxinator directory.
  • home-manager/programs/fish/functions/_tsh_function.fish: Refactored to focus solely on searching tmux pane contents (live and archived) using rg and fzf, with arguments pre-filling the fzf query; removed functionality to switch to or attach to tmux sessions/windows after selection.
  • home-manager/programs/fish/functions/_tss_function.fish: Enhanced with a new --log option, enabling users to browse and interactively switch to or attach to tmux sessions from their history log using fzf.
  • home-manager/programs/tmux/tmux.conf: Introduced a new tmux keybinding H that triggers a pane content search using _tsh_function within a new fish shell window.
  • home-manager/programs/fish/functions/_tsw_function.fish: Added a new --log option to fuzzy-pick and restore previous tmux sessions and windows from a history log file.

Description generated by Mesa. Update settings

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request refactors the tmuxinator configuration by flattening files into a single directory and enhances the tsh and tss Fish shell functions. The _tsh_function now focuses on searching tmux pane contents, and _tss_function handles session history browsing via --log. However, it introduces command injection vulnerabilities in both tsh and tss functions. This is due to the unsafe interpolation of user-controlled data, specifically the query in tsh and session history log content in tss --log, into shell commands executed by fzf without proper sanitization or escaping.

| fzf --prompt="pane-search> " \
--height=40% \
--query="$query" \
--preview="rg -n -- '$query' {} 2>/dev/null | head -80" \

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.

security-high high

The query variable, derived from user-supplied arguments, is directly interpolated into the fzf --preview command string. Since fzf executes this command in a shell, an attacker can provide a query containing single quotes and shell metacharacters to execute arbitrary commands. For example, a query like foo' ; touch /tmp/pwned ; ' would result in the execution of touch /tmp/pwned.

--height=40% \
--tac \
--no-sort \
--preview='echo {}')

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.

security-high high

The fzf preview command echo {} uses the {} placeholder, which is replaced by the literal content of the selected line from the session history log. Since the log contains session names, window names, and paths that can be influenced by users or processes (e.g., by creating a tmux session with a malicious name), an attacker can inject shell commands into these fields to achieve command execution when the log is browsed via tss --log. For example, a session named $(touch /tmp/pwned) would cause the command to execute when highlighted in the fzf list.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
home-manager/programs/fish/functions/_tsh_function.fish (1)

27-29: Add a guard for malformed pane filenames.

If a file does not match the expected naming pattern, widx can be empty and tmux targeting becomes brittle. A small validation check improves resilience.

Proposed fix
   set -l parts (string split -- '--' $fname)
+  if test (count $parts) -lt 2
+    echo "Could not parse session/window from pane file: $selected"
+    return
+  end
   set -l sess $parts[1]
   set -l widx $parts[2]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@home-manager/programs/fish/functions/_tsh_function.fish` around lines 27 -
29, The split of fname into parts can produce an empty widx for malformed pane
filenames; after computing parts, sess, and widx in _tsh_function.fish, add a
guard that validates the split (e.g., ensure count of parts >= 2 and widx is
non-empty) and handle the failure by printing an error/notice and returning
early (or falling back) instead of proceeding to tmux targeting; reference the
variables parts, sess, and widx to locate where to insert the check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@home-manager/programs/fish/functions/_tsh_function.fish`:
- Around line 6-8: The current early return in _tsh_function.fish aborts when
pane_dir is missing even if archive_dir exists; change the logic so it only
returns when neither pane_dir nor archive_dir exist: update the check around the
"if not test -d \"$pane_dir\"" block (and the similar block around lines 12-13)
to test both pane_dir and archive_dir, proceeding when archive_dir exists (so
archive-only search is reachable) and only echoing "No pane content store..."
and returning when both are absent.

In `@home-manager/programs/fish/functions/_tss_function.fish`:
- Around line 22-25: The parsing of the tmux target token is fragile: replace
the rigid split-by-"  " + index access (variables target, parts, sess, widx)
with defensive parsing and validation; first ensure $selected contains a token
with a session:window form, split the token on ':' into parts and check that
parts has at least 2 elements before assigning sess and widx, and if validation
fails log an error or return early instead of calling tmux commands (so the tmux
calls that use sess/widx are not run with empty values); update the code paths
that reference target, parts, sess, and widx to use the validated values only.

---

Nitpick comments:
In `@home-manager/programs/fish/functions/_tsh_function.fish`:
- Around line 27-29: The split of fname into parts can produce an empty widx for
malformed pane filenames; after computing parts, sess, and widx in
_tsh_function.fish, add a guard that validates the split (e.g., ensure count of
parts >= 2 and widx is non-empty) and handle the failure by printing an
error/notice and returning early (or falling back) instead of proceeding to tmux
targeting; reference the variables parts, sess, and widx to locate where to
insert the check.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a2705de and 6cfffbe.

📒 Files selected for processing (7)
  • config/tmuxinator/default.nix
  • config/tmuxinator/desktop.yml
  • config/tmuxinator/mobile.yml
  • config/tmuxinator/primary.yml
  • config/tmuxinator/work.yml
  • home-manager/programs/fish/functions/_tsh_function.fish
  • home-manager/programs/fish/functions/_tss_function.fish

Comment on lines +6 to 8
if not test -d "$pane_dir"
echo "No pane content store found at $pane_dir"
return

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

Archive-only search is currently unreachable.

Line [6] returns when pane_dir is missing, even if archive_dir exists. That breaks the intended “live + archived” behavior.

Proposed fix
-  if not test -d "$pane_dir"
-    echo "No pane content store found at $pane_dir"
-    return
-  end
+  set -l search_dirs
+  if test -d "$pane_dir"
+    set -a search_dirs "$pane_dir"
+  end
+  if test -d "$archive_dir"
+    set -a search_dirs "$archive_dir"
+  end
+  if test (count $search_dirs) -eq 0
+    echo "No pane content store found at $pane_dir or $archive_dir"
+    return
+  end
@@
-  set -l selected (rg -l -- "$query" "$pane_dir" "$archive_dir" 2>/dev/null \
+  set -l selected (rg -l -- "$query" $search_dirs 2>/dev/null \

Also applies to: 12-13

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

In `@home-manager/programs/fish/functions/_tsh_function.fish` around lines 6 - 8,
The current early return in _tsh_function.fish aborts when pane_dir is missing
even if archive_dir exists; change the logic so it only returns when neither
pane_dir nor archive_dir exist: update the check around the "if not test -d
\"$pane_dir\"" block (and the similar block around lines 12-13) to test both
pane_dir and archive_dir, proceeding when archive_dir exists (so archive-only
search is reachable) and only echoing "No pane content store..." and returning
when both are absent.

Comment on lines +22 to +25
set -l target (string split ' ' $selected)[2]
set -l parts (string split ':' $target)
set -l sess $parts[1]
set -l widx $parts[2]

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 | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "_tss_function.fish" | head -5

Repository: shunkakinoki/dotfiles

Length of output: 122


🏁 Script executed:

cat -n ./home-manager/programs/fish/functions/_tss_function.fish

Repository: shunkakinoki/dotfiles

Length of output: 3250


🏁 Script executed:

find . -name "*session-history*" -o -name "*tss*" | grep -E "(log|script|config)" | head -20

Repository: shunkakinoki/dotfiles

Length of output: 47


🏁 Script executed:

rg "session-history" --type fish --type sh --type bash

Repository: shunkakinoki/dotfiles

Length of output: 93


🏁 Script executed:

rg "session-history"

Repository: shunkakinoki/dotfiles

Length of output: 355


🏁 Script executed:

cat -n ./home-manager/programs/tmux/session-logger.sh

Repository: shunkakinoki/dotfiles

Length of output: 1809


Harden log-entry parsing before using tmux targets.

Line 22 assumes a strict " " (two-space) delimiter and fixed field position [2]; if the log format is malformed or incomplete, $sess and $widx can be empty or invalid. This causes silent failures in the subsequent tmux commands (lines 27, 34, 36) because errors are suppressed. Parse the session:window token defensively and validate before use.

Proposed fix
-    set -l target (string split '  ' $selected)[2]
-    set -l parts (string split ':' $target)
-    set -l sess $parts[1]
-    set -l widx $parts[2]
+    set -l target (string match -r '[^[:space:]]+:[0-9]+' -- $selected)
+    if test -z "$target"
+      echo "Could not parse session/window from: $selected"
+      return 1
+    end
+    set -l parts (string split ':' -- $target)
+    set -l sess $parts[1]
+    set -l widx $parts[2]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
set -l target (string split ' ' $selected)[2]
set -l parts (string split ':' $target)
set -l sess $parts[1]
set -l widx $parts[2]
set -l target (string match -r '[^[:space:]]+:[0-9]+' -- $selected)
if test -z "$target"
echo "Could not parse session/window from: $selected"
return 1
end
set -l parts (string split ':' -- $target)
set -l sess $parts[1]
set -l widx $parts[2]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@home-manager/programs/fish/functions/_tss_function.fish` around lines 22 -
25, The parsing of the tmux target token is fragile: replace the rigid
split-by-"  " + index access (variables target, parts, sess, widx) with
defensive parsing and validation; first ensure $selected contains a token with a
session:window form, split the token on ':' into parts and check that parts has
at least 2 elements before assigning sess and widx, and if validation fails log
an error or return early instead of calling tmux commands (so the tmux calls
that use sess/widx are not run with empty values); update the code paths that
reference target, parts, sess, and widx to use the validated values only.

@shunkakinoki
shunkakinoki merged commit 4bc86b3 into main Feb 26, 2026
9 checks passed
@shunkakinoki
shunkakinoki deleted the refactor/tmux-tsh-tss-tmuxinator branch February 26, 2026 04:05

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

2 issues found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="home-manager/programs/fish/functions/_tss_function.fish">

<violation number="1" location="home-manager/programs/fish/functions/_tss_function.fish:22">
P2: Validate the parsed log entry before using it to build tmux targets; otherwise malformed lines can lead to empty session/window values and broken tmux commands.</violation>
</file>

<file name="home-manager/programs/fish/functions/_tsh_function.fish">

<violation number="1" location="home-manager/programs/fish/functions/_tsh_function.fish:11">
P1: This preview command is vulnerable to command injection. If `$query` contains a single quote (e.g., `user's`), it breaks the quoting in the shell command executed by `fzf`, potentially executing arbitrary code. 

Escape single quotes in the query before passing it to the preview command.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment on lines +11 to +17
set -l query (string join ' ' $argv)
set -l selected (rg -l -- "$query" "$pane_dir" "$archive_dir" 2>/dev/null \
| fzf --prompt="pane-search> " \
--height=40% \
--query="$query" \
--preview="rg -n -- '$query' {} 2>/dev/null | head -80" \
--preview-window=right:60%)

@cubic-dev-ai cubic-dev-ai Bot Feb 26, 2026

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.

P1: This preview command is vulnerable to command injection. If $query contains a single quote (e.g., user's), it breaks the quoting in the shell command executed by fzf, potentially executing arbitrary code.

Escape single quotes in the query before passing it to the preview command.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/fish/functions/_tsh_function.fish, line 11:

<comment>This preview command is vulnerable to command injection. If `$query` contains a single quote (e.g., `user's`), it breaks the quoting in the shell command executed by `fzf`, potentially executing arbitrary code. 

Escape single quotes in the query before passing it to the preview command.</comment>

<file context>
@@ -1,72 +1,35 @@
-    --tac \
-    --no-sort \
-    --preview='echo {}')
+  set -l query (string join ' ' $argv)
+  set -l selected (rg -l -- "$query" "$pane_dir" "$archive_dir" 2>/dev/null \
+    | fzf --prompt="pane-search> " \
</file context>
Suggested change
set -l query (string join ' ' $argv)
set -l selected (rg -l -- "$query" "$pane_dir" "$archive_dir" 2>/dev/null \
| fzf --prompt="pane-search> " \
--height=40% \
--query="$query" \
--preview="rg -n -- '$query' {} 2>/dev/null | head -80" \
--preview-window=right:60%)
set -l query (string join ' ' $argv)
set -l query_escaped (string replace -a "'" "'\\''" "$query")
set -l selected (rg -l -- "$query" "$pane_dir" "$archive_dir" 2>/dev/null \
| fzf --prompt="pane-search> " \
--height=40% \
--query="$query" \
--preview="rg -n -- '$query_escaped' {} 2>/dev/null | head -80" \
--preview-window=right:60%)
Fix with Cubic

Comment on lines +22 to +25
set -l target (string split ' ' $selected)[2]
set -l parts (string split ':' $target)
set -l sess $parts[1]
set -l widx $parts[2]

@cubic-dev-ai cubic-dev-ai Bot Feb 26, 2026

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.

P2: Validate the parsed log entry before using it to build tmux targets; otherwise malformed lines can lead to empty session/window values and broken tmux commands.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/fish/functions/_tss_function.fish, line 22:

<comment>Validate the parsed log entry before using it to build tmux targets; otherwise malformed lines can lead to empty session/window values and broken tmux commands.</comment>

<file context>
@@ -1,4 +1,43 @@
+      return
+    end
+
+    set -l target (string split '  ' $selected)[2]
+    set -l parts (string split ':' $target)
+    set -l sess $parts[1]
</file context>
Suggested change
set -l target (string split ' ' $selected)[2]
set -l parts (string split ':' $target)
set -l sess $parts[1]
set -l widx $parts[2]
set -l target (string split ' ' $selected)[2]
set -l parts (string split ':' $target)
if test -z "$target" -o (count $parts) -lt 2
echo "Malformed log entry: $selected"
return
end
set -l sess $parts[1]
set -l widx $parts[2]
Fix with Cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

4 issues found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="home-manager/programs/tmux/tmux.conf">

<violation number="1" location="home-manager/programs/tmux/tmux.conf:152">
P2: This rebinds the existing `K` resize-pane shortcut, so pane resize up via `Prefix+K` stops working. Pick a different key or update the resize binding accordingly to avoid a regression.</violation>
</file>

<file name="home-manager/programs/fish/functions/_tsk_function.fish">

<violation number="1" location="home-manager/programs/fish/functions/_tsk_function.fish:4">
P2: Using a double-space delimiter is fragile, as session or window names containing double spaces will break the parsing. Consider using a more robust delimiter like a tab character (`\t`) in both the tmux format strings and the split logic.</violation>

<violation number="2" location="home-manager/programs/fish/functions/_tsk_function.fish:5">
P1: The format string uses 3 spaces after 'window' (likely for alignment), but the parsing logic splits on 2 spaces (`  `). This results in the `target` variable containing a leading space (e.g., `' s1:1'`), causing `tmux kill-window` to fail. Reduce to 2 spaces to match the delimiter.</violation>

<violation number="3" location="home-manager/programs/fish/functions/_tsk_function.fish:13">
P1: The `{}` placeholder is unquoted in the preview command. If a session name contains special characters (like parentheses `( )` in Fish), this allows command injection or causes syntax errors. Quote the placeholder to treat it as a string.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

--height=40% \
--multi \
--preview='
set kind (string split " " {})[1]

@cubic-dev-ai cubic-dev-ai Bot Feb 26, 2026

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.

P1: The {} placeholder is unquoted in the preview command. If a session name contains special characters (like parentheses ( ) in Fish), this allows command injection or causes syntax errors. Quote the placeholder to treat it as a string.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/fish/functions/_tsk_function.fish, line 13:

<comment>The `{}` placeholder is unquoted in the preview command. If a session name contains special characters (like parentheses `( )` in Fish), this allows command injection or causes syntax errors. Quote the placeholder to treat it as a string.</comment>

<file context>
@@ -0,0 +1,34 @@
+          --height=40% \
+          --multi \
+          --preview='
+            set kind (string split "  " {})[1]
+            set target (string split "  " {})[2]
+            if test "$kind" = session
</file context>
Fix with Cubic

# Build list: sessions and windows
set -l items (begin
tmux list-sessions -F 'session #{session_name}' 2>/dev/null
tmux list-windows -a -F 'window #{session_name}:#{window_index} #{window_name}' 2>/dev/null

@cubic-dev-ai cubic-dev-ai Bot Feb 26, 2026

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.

P1: The format string uses 3 spaces after 'window' (likely for alignment), but the parsing logic splits on 2 spaces ( ). This results in the target variable containing a leading space (e.g., ' s1:1'), causing tmux kill-window to fail. Reduce to 2 spaces to match the delimiter.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/fish/functions/_tsk_function.fish, line 5:

<comment>The format string uses 3 spaces after 'window' (likely for alignment), but the parsing logic splits on 2 spaces (`  `). This results in the `target` variable containing a leading space (e.g., `' s1:1'`), causing `tmux kill-window` to fail. Reduce to 2 spaces to match the delimiter.</comment>

<file context>
@@ -0,0 +1,34 @@
+  # Build list: sessions and windows
+  set -l items (begin
+    tmux list-sessions -F 'session  #{session_name}' 2>/dev/null
+    tmux list-windows -a -F 'window   #{session_name}:#{window_index}  #{window_name}' 2>/dev/null
+  end)
+
</file context>
Fix with Cubic

bind H run-shell "tmux new-window 'fish -c _tsh_function'"

# Kill sessions/windows via fzf
bind K run-shell "tmux new-window 'fish -c _tsk_function'"

@cubic-dev-ai cubic-dev-ai Bot Feb 26, 2026

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.

P2: This rebinds the existing K resize-pane shortcut, so pane resize up via Prefix+K stops working. Pick a different key or update the resize binding accordingly to avoid a regression.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/tmux/tmux.conf, line 152:

<comment>This rebinds the existing `K` resize-pane shortcut, so pane resize up via `Prefix+K` stops working. Pick a different key or update the resize binding accordingly to avoid a regression.</comment>

<file context>
@@ -148,6 +148,9 @@ bind W run-shell "tmux new-window 'fish -c _tsw_function'"
 bind H run-shell "tmux new-window 'fish -c _tsh_function'"
 
+# Kill sessions/windows via fzf
+bind K run-shell "tmux new-window 'fish -c _tsk_function'"
+
 # Extrakto (text extraction)
</file context>
Suggested change
bind K run-shell "tmux new-window 'fish -c _tsk_function'"
bind M run-shell "tmux new-window 'fish -c _tsk_function'"
Fix with Cubic

function _tsk_function --description "Kill tmux sessions or windows via fzf"
# Build list: sessions and windows
set -l items (begin
tmux list-sessions -F 'session #{session_name}' 2>/dev/null

@cubic-dev-ai cubic-dev-ai Bot Feb 26, 2026

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.

P2: Using a double-space delimiter is fragile, as session or window names containing double spaces will break the parsing. Consider using a more robust delimiter like a tab character (\t) in both the tmux format strings and the split logic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/fish/functions/_tsk_function.fish, line 4:

<comment>Using a double-space delimiter is fragile, as session or window names containing double spaces will break the parsing. Consider using a more robust delimiter like a tab character (`\t`) in both the tmux format strings and the split logic.</comment>

<file context>
@@ -0,0 +1,34 @@
+function _tsk_function --description "Kill tmux sessions or windows via fzf"
+  # Build list: sessions and windows
+  set -l items (begin
+    tmux list-sessions -F 'session  #{session_name}' 2>/dev/null
+    tmux list-windows -a -F 'window   #{session_name}:#{window_index}  #{window_name}' 2>/dev/null
+  end)
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant