vde-tmux-manager
v0.0.24
Published
tmux utility CLI for session management and statusline helpers
Downloads
186
Readme
vde-tmux-manager
vde-tmux-manager is a tmux utility CLI for session operations and statusline rendering.
Features
- Interactive tmux session manager with fzf
- Category-aware tmux session grouping based on project paths
- Clean kill flows for sessions/windows/panes/server targets
- Category-scoped session cycling and statusline switching
- tmux statusline session segment renderer
- tmux statusline current-category segment renderer
- Clickable statusline session segments for session switching
- YAML-based configuration
- JSON Schema for YAML completion and validation
- Two executable names:
vde-tmux-managerandvtm - Configurable statusline fonts (prefix/suffix glyphs)
Requirements
- Node.js
>=22 - tmux
- fzf
ps/killcommands
fzf-tmux is optional. If present, it is used automatically inside tmux.
Installation
Global install:
npm install -g vde-tmux-manageror
pnpm add -g vde-tmux-managerCommands
vtm session-managervtm session-manager --popupvtm session-manager kill-window <target>vtm session-manager kill-pane <target>vtm project switch <path>vtm category use <name>vtm category nextvtm category prevvtm hooks on-client-session-changed [<client-name> <session-name>]vtm session-cycle nextvtm session-cycle prevvtm session set-category <session> <category>vtm sessions refresh-categoryvtm statusline-categoryvtm statusline-category switch 2vtm statusline-sessionsvtm statusline-sessions switch 2vtm --helpvtm --version
vde-tmux-manager is a full alias of vtm.
Session Manager Controls
Inside the selector:
Enter: switch/attach to selected targetCtrl-T: create new sessionCtrl-Q: clean kill selected target(s)Ctrl-R: rename selected sessionCtrl-D/Ctrl-U: preview page down/up
Configuration
Configuration file path:
$XDG_CONFIG_HOME/vde/tmux-manager/config.yml- fallback path when
XDG_CONFIG_HOMEis unset:~/.config/vde/tmux-manager/config.yml
Example:
# yaml-language-server: $schema=https://raw.githubusercontent.com/yuki-yano/vde-tmux-manager/refs/heads/main/schemas/config.schema.json
ghqRoot: "/Users/you/ghq"
sessionManager:
popup:
enabled: true
width: "50%"
height: "50%"
fzf:
prompt: "tmux> "
border: "rounded"
previewWidth: "65"
previewRefreshMs: 0
preview:
sessionCaptureLines: 15
paneCaptureLines: 16
kill:
sendCtrlC: true
termWaitMs: 300
killWaitMs: 300
statuslineCategory:
mode: current
format: "{category}"
prefix: ""
suffix: ""
bold: true
colors:
fg: "#1C1C1C"
bg: "#FAB387"
outerBg: "#352F63"
inactiveColors:
fg: "#C6D0F5"
bg: "#352F63"
outerBg: "#352F63"
statuslineSessions:
showIndex: false
current:
format: "{session}"
prefix: ""
suffix: ""
bold: false
colors:
fg: "#1E1E2E"
bg: "#B4BEFE"
outerBg: "#352F63"
other:
format: " {session} "
prefix: ""
suffix: ""
bold: false
colors:
fg: "#C6D0F5"
bg: "#352F63"
outerBg: "#352F63"
categories:
defaultCategory: work
displayNames:
work: Work
private: Private
oss: OSS
order:
work: 10
private: 20
oss: 30
rules:
- category: work
ghqPatterns:
- github.com/${WORK_GHQ_OWNER}/*
- github.com/${WORK_GHQ_OWNER}/**
- category: private
pathPatterns:
- ~/dotfiles
- ~/private/**
- /tmp/**
- category: oss
ghqPatterns:
- github.com/yuki-yano/**
sessionNameRules:
- category: private
patterns:
- dotfiles
- local-*Category resolution order:
- Session override metadata (
@category_override) - Path rules
- Session name rules
defaultCategory
Path rules use first-match-wins. For GHQ projects, matching is done against the GHQ-root-relative path such as github.com/org/repo. For non-GHQ projects, matching is done against the normalized absolute path, with ~ expanded to HOME.
ghqPatterns and pathPatterns support ${VAR_NAME} environment variable expansion at config load time. For example, with WORK_GHQ_OWNER=acme-inc, github.com/${WORK_GHQ_OWNER}/* resolves to github.com/acme-inc/*. Referencing an undefined environment variable is treated as a config error. Existing fixed-string patterns continue to work unchanged.
Unknown config keys are ignored during config loading so newer or extra keys do not make vtm fail at startup.
Category names remain strings. Use categories.order to assign integer ordering. vtm category next / vtm category prev and the category grouping inside vtm session-manager use that order.
When categories is omitted, every session belongs to one unnamed category. In that mode, session cycling and statusline session switching continue to operate across all sessions, similar to the pre-category behavior, and vtm statusline-category renders nothing.
Schema file:
tmux Integration
Enable mouse support (required for clickable statusline session switching):
set -g mouse onOpen session manager:
bind-key C-f run-shell 'vtm session-manager'Switch the current tmux client category:
bind-key C-w run-shell 'vtm category use work'
bind-key C-p run-shell 'vtm category use private'
bind-key ] run-shell 'vtm category next'
bind-key [ run-shell 'vtm category prev'vtm category use <name> changes the current category for that tmux client, then restores the last active session remembered for that client and category. If no remembered session exists, it switches to the first session in the category. If the category has no sessions, only the category is updated.
Last-active session timing:
- session switches triggered through
vtmupdate the remembered session immediately vtm category usefirst reconciles the tmux client's actual current session before switching away- to track plain tmux session switches as well, install the hook below
- client-scoped category state is stored in tmux server-scoped user options keyed by client name, so it survives session switches on the same client
statuslineCategory.format replaces {category} with the statusline display name. By default that matches the internal category name, and categories.displayNames lets you override it without changing tmux state or command names. mode: current renders only the active category. mode: list renders ordered categories horizontally, using colors for the active item and inactiveColors for the rest. prefix and suffix are rendered around each category body, and outerBg controls the background behind those edge glyphs. If the resolved category is unnamed, current mode prints an empty string and list mode skips unnamed categories.
statuslineSessions.current.format and statuslineSessions.other.format replace {session} with the rendered session label. When --show-index or showIndex: true is enabled, that label includes the 1-based index like 1 foo.
bind-key -n MouseDown1Status if-shell -F '#{m/r:^[0-9]+$,#{mouse_status_range}}' \
'run-shell "vtm statusline-category switch #{mouse_status_range}"' \
'switch-client -t ='Cycle sessions only inside the current category:
bind-key -n M-n run-shell 'vtm session-cycle next'
bind-key -n M-p run-shell 'vtm session-cycle prev'Use in statusline:
set -g status-left '#(vtm statusline-category) '
set -g status-right '#(vtm statusline-sessions) #[fg=colour250]| %Y-%m-%d %H:%M'Track standard tmux session changes so category restore follows the real last active session:
set-hook -g client-session-changed 'run-shell "vtm hooks on-client-session-changed #{client_name} #{session_name}"'Show 1-based indexes before session names when needed:
set -g status-right '#(vtm statusline-sessions --show-index) #[fg=colour250]| %Y-%m-%d %H:%M'Switch to a session by the displayed 1-based index:
vtm statusline-sessions switch 2Create or reuse a session from a project path and attach/switch to it:
vtm project switch ~/ghq/github.com/xxx-company/foo
vtm project switch /tmp/playground-repoExplicitly override a session category and refresh stored categories later:
vtm session set-category dotfiles private
vtm sessions refresh-categoryInternal client state:
@current_category: current category for the tmux client@category_last_session_<hex(category)>: last active session for each category, scoped to the tmux client
Simple right-click menu for kill actions:
bind-key -n MouseDown3Pane display-menu -T "Pane #{pane_index}" -t = -x M -y M \
"Kill Pane" X { run-shell "vtm session-manager kill-pane #{q:pane_id}" } \
"Kill Window" W { run-shell "vtm session-manager kill-window #{q:window_id}" }This replaces your existing right-click menu with a minimal kill-focused menu.
Troubleshooting
- If
session-managerdoes not open, verifytmuxandfzfare available inPATH. - If clean kill behavior is incomplete, verify
psandkillare available. - If repo metadata is empty in preview, verify the pane path is inside a Git repository.
- If your GHQ root is fixed, set
ghqRootin config to avoid callingghq rooton every command. - If category matching looks wrong, verify
ghqRoot/GHQ_ROOT/ghq root, then runvtm sessions refresh-category.
