A tmux plugin that displays emoji status indicators in pane names when Claude Code finishes responding or sends notifications. The plugin tracks multiple Claude instances across different tmux panes and shows the appropriate emoji for each pane.
- β Stop Status: Shows checkmark emoji when Claude finishes responding
- π’ Notification Status: Shows notification emoji when Claude sends notifications
- β PreToolUse Status: Shows question mark emoji when Claude needs tool permission
- Multi-pane Support: Tracks multiple Claude instances across different tmux panes
- Smart Restoration: Automatically restores original pane names when user switches panes or presses Enter
- Pure Python: No external dependencies, uses only Python 3 standard library
- Python 3.6+ (required)
- tmux
- Claude Code with hooks support
-
Add the plugin to your
~/.tmux.conf:set -g @plugin 'leotomas/tmux-claude'
-
Press
prefix + Ito install the plugin.
-
Clone the repository:
git clone https://github.com/leotomas/tmux-claude.git ~/.tmux/plugins/tmux-claude -
Add to your
~/.tmux.conf:run-shell ~/.tmux/plugins/tmux-claude/tmux-claude.tmux -
Reload tmux configuration:
tmux source-file ~/.tmux.conf
For optimal plugin functionality, it's recommended to disable tmux's automatic window renaming. Add this to your ~/.tmux.conf:
# Disable automatic window renaming to preserve custom names with emoji status
set-option -g automatic-rename off
set-option -g automatic-rename-format ''This ensures that:
- Your custom window names are preserved when emoji prefixes are added
- The plugin doesn't conflict with tmux's automatic renaming
- Window names remain stable across different commands and processes
Note: The plugin will work with automatic renaming enabled, but your custom window names may be overridden by tmux's auto-generated names.
Add the following configuration to your ~/.claude/settings.json:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/tmux-claude/scripts/claude_tmux_hooks.py stop"
}
]
}
],
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/tmux-claude/scripts/claude_tmux_hooks.py notification"
}
]
}
],
"PreToolUse": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/tmux-claude/scripts/claude_tmux_hooks.py pretooluse"
}
]
}
]
}
}Important: Replace /path/to/tmux-claude/ with the actual path to your plugin installation.
Use the provided example-claude-settings.json as a template and adjust the paths according to your installation.
-
Start Claude in tmux panes: Run Claude Code in different tmux panes as usual.
-
Automatic status updates: The plugin automatically detects when Claude finishes or sends notifications and updates the pane names with appropriate emojis.
-
Restore original names: When you switch to a pane or press Enter, the original pane name is automatically restored.
-
View status: Check the status of all tracked panes:
~/.tmux/plugins/tmux-claude/scripts/pane_tracker.py status
Test the notification system:
./scripts/notification_handler.py testTest emoji status in current pane:
./scripts/claude_tmux_hooks.py stop
./scripts/claude_tmux_hooks.py notification
./scripts/claude_tmux_hooks.py pretooluseRestore original pane name:
./scripts/claude_tmux_hooks.py restoreList all tmux panes:
./scripts/tmux_integration.py list-panesFind panes running Claude:
./scripts/tmux_integration.py find-claudeView tracked panes status:
./scripts/pane_tracker.py status-
Hook Integration: Claude Code hooks trigger the plugin when Claude stops, sends notifications, or needs tool permission (PreToolUse).
-
Pane Detection: The plugin identifies which tmux pane the Claude instance is running in using the
$TMUX_PANEenvironment variable, ensuring the emoji appears on the correct pane even when you're working in a different pane. -
Emoji Prefixes: The plugin adds emoji prefixes to window names:
- β
when Claude finishes (
Stophook) - π’ when Claude sends notifications (
Notificationhook) - β when Claude needs tool permission (
PreToolUsehook)
- β
when Claude finishes (
-
Activity Monitoring: The plugin monitors pane activity and restores original names when users switch panes or press Enter.
-
State Management: Pane states are stored in temporary JSON files and cleaned up automatically.
-
Multi-Pane Support: Works correctly across multiple tmux panes running different Claude instances simultaneously.
tmux-claude/
βββ tmux-claude.tmux # Main plugin file
βββ scripts/
β βββ claude_tmux_hooks.py # Hook handler (Stop/Notification)
β βββ tmux_integration.py # Tmux pane management
β βββ pane_tracker.py # Pane activity monitoring
β βββ notification_handler.py # System notifications
βββ example-claude-settings.json # Example Claude configuration
βββ README.md # This file
The plugin includes comprehensive debug logging to help troubleshoot issues.
# Enable debug logging
./scripts/debug_logger.py enable
# Or set environment variable
export TMUX_CLAUDE_DEBUG=1# View all recent logs
./scripts/debug_logger.py view
# View logs for specific script
./scripts/debug_logger.py view claude_tmux_hooks
# View logs for specific script (other examples)
./scripts/debug_logger.py view tmux_integration
./scripts/debug_logger.py view pane_tracker
./scripts/debug_logger.py view notification_handler# Clear all log files
./scripts/debug_logger.py clear# Disable debug logging
./scripts/debug_logger.py disableDebug logs are stored in scripts/.logs/:
claude_tmux_hooks.log- Hook execution logstmux_integration.log- Tmux command logspane_tracker.log- Pane tracking and monitoring logsnotification_handler.log- Notification system logstmux_claude.log- Combined main log
- Ensure the plugin files are executable
- Check tmux configuration syntax
- Verify Python 3 is available
- Debug: Enable logging and check
tmux_claude.log
- Disable automatic renaming in
~/.tmux.conf(see Configuration section) - Check if you have custom window names set with
tmux rename-window - Debug: Check logs for "auto_rename_was_on" entries
- Verify the paths in
~/.claude/settings.jsonare correct - Check that Claude Code supports hooks
- Test the hook scripts manually
- Debug: Enable logging and run
./scripts/claude_tmux_hooks.py stopmanually
- Test notification system:
./scripts/notification_handler.py test - Ensure
notify_windowscommand is available - Check system notification settings
- Debug: Check
notification_handler.logfor error messages
- Verify terminal supports Unicode
- Check tmux pane name display settings
- Test manually:
./scripts/claude_tmux_hooks.py stop - Debug: Check
claude_tmux_hooks.logfor pane name setting errors
- The plugin uses
$TMUX_PANEenvironment variable to detect the correct pane - If testing manually, ensure you're in the correct pane context
- Debug: Check logs for "Got pane ID from TMUX_PANE" entries
- Fix: Use
TMUX_PANE=%X ./scripts/claude_tmux_hooks.py stopto specify pane
# Enable debug and test stop hook
./scripts/debug_logger.py enable
./scripts/claude_tmux_hooks.py stop
./scripts/debug_logger.py view claude_tmux_hooks
# Test notification system
./scripts/notification_handler.py test
./scripts/debug_logger.py view notification_handler
# Check pane tracking
./scripts/pane_tracker.py status
./scripts/debug_logger.py view pane_tracker
# Test pane detection
echo "Current pane: $(tmux display-message -p '#{pane_id}'), TMUX_PANE: $TMUX_PANE"
./scripts/claude_tmux_hooks.py stop
./scripts/debug_logger.py view claude_tmux_hooks | grep TMUX_PANESee licence.txt
[Add your license here]
[Add contribution guidelines here]