35 KiB
Session Registry Reference
This document provides comprehensive documentation for the tmux skill session registry system.
Table of Contents
- Overview
- Architecture
- Registry File Format
- Tool Reference
- Session Resolution
- Troubleshooting
- Migration Guide
- Best Practices
- Advanced Patterns
Overview
The session registry is an automatic session tracking system that eliminates ~80% of boilerplate when working with tmux sessions. Instead of repeatedly specifying socket paths and targets, sessions are registered once and can be referenced by name.
Key Benefits
- Reduced boilerplate: No more repeating
-S socket -t targeton every command - Automatic discovery: Tools auto-detect single sessions when no name specified
- Health tracking: Built-in integration with pane health checks
- Activity tracking: Automatic timestamps for cleanup decisions
- Backward compatible: All existing workflows continue to work
Quick Example
Before (manual approach):
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
SESSION="my-python"
tmux -S "$SOCKET" new -d -s "$SESSION" -n shell
tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 'PYTHON_BASIC_REPL=1 python3 -q' Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 'print("hello")' Enter
tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 'print("world")' Enter
After (registry approach):
./tools/create-session.sh -n my-python --python
./tools/safe-send.sh -s my-python -c 'print("hello")' -w ">>>"
./tools/safe-send.sh -c 'print("world")' -w ">>>" # Auto-detects single session
Architecture
Components
The session registry consists of:
-
Registry Library (
tools/lib/registry.sh)- Core CRUD operations
- Portable file locking
- JSON validation
- Activity tracking
-
Registry File (
$CLAUDE_TMUX_SOCKET_DIR/.sessions.json)- JSON database of registered sessions
- Atomic updates with write-then-move
- Human-readable format
-
Management Tools
create-session.sh- Create and register sessionslist-sessions.sh- View all sessions with health statuscleanup-sessions.sh- Remove dead/old sessions
-
Enhanced Tools
safe-send.sh- Send commands by session namewait-for-text.sh- Wait for patterns by session name (planned)pane-health.sh- Check health by session name (planned)
File Locking Mechanism
The registry uses portable locking to ensure atomic operations:
On Linux (flock available):
- Uses kernel-level
flockfor fast, reliable locking - Lock file:
$CLAUDE_TMUX_SOCKET_DIR/.sessions.lock - Timeout: 5 seconds (configurable via
LOCK_TIMEOUT)
On macOS (flock not available):
- Falls back to mkdir-based locking (atomic directory creation)
- Lock directory:
$CLAUDE_TMUX_SOCKET_DIR/.sessions.lock/ - Contains owner info for debugging
- Same timeout behavior as flock
Lock acquisition:
# Try to acquire lock with timeout
registry_lock || return 75 # Exit code 75 = lock timeout
# ... perform registry operations ...
# Always release lock
registry_unlock
Atomic Updates
All registry modifications use an atomic write-then-move pattern:
- Lock - Acquire registry lock
- Read - Load current registry data
- Modify - Make changes to in-memory copy
- Write - Write to temporary file
- Validate - Verify JSON with
jq - Move - Atomically move temp file to registry (if valid)
- Unlock - Release registry lock
This ensures the registry is never corrupted, even if a process crashes mid-update.
Registry File Format
Location
The registry file is located at:
$CLAUDE_TMUX_SOCKET_DIR/.sessions.json
Where CLAUDE_TMUX_SOCKET_DIR defaults to:
${TMPDIR:-/tmp}/claude-tmux-sockets
JSON Schema
The registry is a JSON file with the following structure:
{
"sessions": {
"session-name": {
"socket": "/path/to/socket",
"target": "session:window.pane",
"type": "python-repl|debugger|shell",
"pid": 12345,
"created_at": "2025-11-23T10:30:00Z",
"last_active": "2025-11-23T12:45:00Z"
}
}
}
Field Descriptions
| Field | Type | Description |
|---|---|---|
socket |
string | Absolute path to tmux socket file |
target |
string | Tmux target in format session:window.pane |
type |
string | Session type: python-repl, debugger, shell |
pid |
number | Process ID of the pane (if available) |
created_at |
string | ISO8601 timestamp of session creation |
last_active |
string | ISO8601 timestamp of last use |
Example Registry File
{
"sessions": {
"claude-python": {
"socket": "/tmp/claude-tmux-sockets/claude.sock",
"target": "claude-python:0.0",
"type": "python-repl",
"pid": 45678,
"created_at": "2025-11-23T10:00:00Z",
"last_active": "2025-11-23T15:30:00Z"
},
"debug-api": {
"socket": "/tmp/claude-tmux-sockets/claude.sock",
"target": "debug-api:0.0",
"type": "debugger",
"pid": 45789,
"created_at": "2025-11-23T11:00:00Z",
"last_active": "2025-11-23T14:20:00Z"
}
}
}
Tool Reference
create-session.sh
Create and register new tmux sessions with automatic registry integration.
Usage
./tools/create-session.sh -n <name> [options]
Options
| Flag | Description |
|---|---|
-n, --name <name> |
Session name (required) |
-S, --socket <path> |
Custom socket path (optional, uses default) |
-w, --window <name> |
Window name (default: "shell") |
--python |
Launch Python REPL with PYTHON_BASIC_REPL=1 |
--gdb |
Launch gdb debugger |
--shell |
Launch bash shell (default) |
--no-register |
Don't add to registry |
-h, --help |
Show help message |
Session Types
--shell (default)
- Launches bash shell
- General-purpose interactive environment
- Type recorded as:
shell
--python
- Launches Python REPL with
PYTHON_BASIC_REPL=1set - Critical for compatibility with tmux send-keys
- Disables fancy prompt/highlighting that interferes with automation
- Type recorded as:
python-repl
--gdb
- Launches gdb debugger
- Automatically sets
set pagination offrecommended - Type recorded as:
debugger
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Invalid arguments |
| 2 | Session already exists |
| 3 | Tmux command failed |
| 4 | Registry operation failed |
JSON Output
Returns session information as JSON:
{
"name": "my-python",
"socket": "/tmp/claude-tmux-sockets/claude.sock",
"target": "my-python:0.0",
"type": "python-repl",
"pid": 12345,
"window": "shell",
"registered": true
}
Examples
Create Python REPL session:
./tools/create-session.sh -n claude-python --python
Create gdb session:
./tools/create-session.sh -n debug-app --gdb
Create session with custom socket:
./tools/create-session.sh -n isolated-session -S /tmp/custom.sock --shell
Create without registering (one-off session):
./tools/create-session.sh -n temp-work --shell --no-register
Create with custom window name:
./tools/create-session.sh -n data-analysis -w "jupyter" --python
When to Use
- With registration (default): Interactive development, debugging, exploration
- Without registration (
--no-register): Temporary sessions, scripts that manage cleanup, CI/CD
list-sessions.sh
List all registered sessions with health status information.
Usage
./tools/list-sessions.sh [--json]
Options
| Flag | Description |
|---|---|
--json |
Output as JSON instead of table format |
-h, --help |
Show help message |
Output Formats
Table format (default):
NAME SOCKET TARGET STATUS PID CREATED
claude-python claude.sock :0.0 alive 1234 2h ago
debug-api claude.sock :0.0 dead - 1h ago
Total: 2 | Alive: 1 | Dead: 1
JSON format (--json):
{
"sessions": [
{
"name": "claude-python",
"socket": "/tmp/claude-tmux-sockets/claude.sock",
"socket_basename": "claude.sock",
"target": "claude-python:0.0",
"type": "python-repl",
"status": "alive",
"pid": 1234,
"created_at": "2025-11-23T10:00:00Z"
}
],
"total": 2,
"alive": 1,
"dead": 1
}
Health Statuses
| Status | Meaning | Exit Code from pane-health.sh |
|---|---|---|
alive |
Session is running and healthy | 0 |
dead |
Pane is marked as dead | 1 |
missing |
Session/pane not found in tmux | 2 |
zombie |
Process exited but pane exists | 3 |
server |
Tmux server not running | 4 |
unknown |
pane-health.sh not available | - |
Examples
List sessions in table format:
./tools/list-sessions.sh
List sessions as JSON for scripting:
./tools/list-sessions.sh --json | jq '.sessions[] | select(.status == "alive")'
Count alive sessions:
./tools/list-sessions.sh --json | jq '.alive'
Get all Python sessions:
./tools/list-sessions.sh --json | jq '.sessions[] | select(.type == "python-repl")'
When to Use
- Check what sessions are currently registered
- Verify session health before operations
- Monitor session activity and age
- Identify dead sessions before cleanup
- Generate reports or dashboards
cleanup-sessions.sh
Remove dead or old sessions from the registry.
Usage
./tools/cleanup-sessions.sh [options]
Options
| Flag | Description |
|---|---|
--dry-run |
Show what would be cleaned without removing |
--all |
Remove all sessions (even alive ones) |
--older-than <duration> |
Remove sessions older than threshold |
-h, --help |
Show help message |
Duration Format
Supported units: s (seconds), m (minutes), h (hours), d (days)
Examples:
30m- 30 minutes2h- 2 hours1d- 1 day3600s- 3600 seconds (1 hour)
Cleanup Modes
Default mode (no flags):
- Removes only dead/missing/zombie sessions
- Safest option
- Preserves all healthy sessions
Age-based mode (--older-than):
- Removes sessions older than specified duration
- Based on
created_attimestamp - Can combine with default mode (dead OR old)
All mode (--all):
- Removes all sessions regardless of health
- Use with caution
- Good for "clean slate" scenarios
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Invalid arguments |
Examples
Remove dead sessions (safe default):
./tools/cleanup-sessions.sh
Dry-run to preview cleanup:
./tools/cleanup-sessions.sh --dry-run
Remove sessions inactive for more than 1 hour:
./tools/cleanup-sessions.sh --older-than 1h
Remove sessions older than 2 days:
./tools/cleanup-sessions.sh --older-than 2d
Remove all sessions (clean slate):
./tools/cleanup-sessions.sh --all
Combine dry-run with age filter:
./tools/cleanup-sessions.sh --dry-run --older-than 1d
When to Use
- Manual cleanup: After finishing work with sessions
- Periodic cleanup: Cron job to remove old sessions
- Aggressive cleanup: Before starting new work session
- Debugging: Dry-run to see what's stale
Automation Examples
Daily cleanup via cron:
# Remove sessions older than 1 day, runs daily at 3am
0 3 * * * cd /path/to/tmux/tools && ./cleanup-sessions.sh --older-than 1d
Pre-work cleanup script:
#!/bin/bash
# Clean slate before starting work
./tools/cleanup-sessions.sh --all
./tools/create-session.sh -n work-python --python
./tools/create-session.sh -n work-gdb --gdb
safe-send.sh (Session Registry Features)
The safe-send.sh tool has been enhanced with session registry support.
Session Resolution Options
Three ways to specify the target:
- Session name (
-s): Look up socket/target from registry - Explicit (
-S+-t): Specify socket and target directly (backward compatible) - Auto-detect: Omit all flags, auto-detect single session
Priority Order
When multiple options are provided, they are resolved in this order:
- Explicit flags (
-Sand-t): Highest priority, backward compatible - Session name (
-s): Look up in registry - Auto-detect: If no flags provided and exactly one session exists
New Flags
| Flag | Description |
|---|---|
-s, --session <name> |
Session name (looks up socket/target in registry) |
All other flags remain the same (see SKILL.md for full reference).
Examples
Using session name:
./tools/safe-send.sh -s claude-python -c "print('hello')" -w ">>>"
Auto-detect single session:
./tools/safe-send.sh -c "print('world')" -w ">>>"
Explicit (backward compatible):
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
./tools/safe-send.sh -S "$SOCKET" -t "my-session:0.0" -c "ls"
Activity Tracking
When using -s flag or auto-detect, the session's last_active timestamp is automatically updated. This helps cleanup-sessions.sh make better decisions about session age.
Error Messages
Session not found:
Error: Session 'my-session' not found in registry
Use 'list-sessions.sh' to see available sessions
Multiple sessions (auto-detect fails):
Error: Multiple sessions found (3 total)
Please specify session name with -s or use -t/-S explicitly
Use 'list-sessions.sh' to see available sessions
No sessions registered:
Error: No sessions found in registry
Create a session with 'create-session.sh' or specify -t and -S explicitly
Session Resolution
Resolution Algorithm
The session resolution logic determines which tmux session and socket to use:
if (socket AND target specified):
use explicit values (backward compatible)
elif (session name specified with -s):
lookup in registry
if not found:
error: session not found
else:
extract socket and target
update last_active timestamp
elif (no flags provided):
count sessions in registry
if count == 1:
auto-use the single session
update last_active timestamp
elif count == 0:
error: no sessions
else:
error: multiple sessions, specify -s
Decision Tree
┌─────────────────────────────┐
│ Parse command-line flags │
└──────────┬──────────────────┘
│
▼
┌──────────────┐
│ -S and -t ? │──Yes──► Use explicit socket/target
└──────┬───────┘ (backward compatible)
│
No
│
▼
┌──────────────┐
│ -s flag ? │──Yes──► Look up session in registry
└──────┬───────┘ Update last_active
│ Error if not found
No
│
▼
┌──────────────────┐
│ Count sessions │
└──────┬───────────┘
│
▼
┌──────────────────┐
│ count == 1 ? │──Yes──► Auto-use single session
└──────┬───────────┘ Update last_active
│
No
│
▼
┌──────────────────┐
│ count == 0 ? │──Yes──► Error: No sessions
└──────┬───────────┘
│
No (multiple)
│
▼
Error: Multiple sessions,
specify -s or -t/-S
Examples
Scenario 1: Single session exists
# Create one session
./tools/create-session.sh -n my-python --python
# These all work the same way:
./tools/safe-send.sh -s my-python -c "print(1)" # Explicit name
./tools/safe-send.sh -c "print(1)" # Auto-detect
Scenario 2: Multiple sessions exist
# Create multiple sessions
./tools/create-session.sh -n python-1 --python
./tools/create-session.sh -n python-2 --python
# Must specify which one:
./tools/safe-send.sh -s python-1 -c "print(1)" # ✓ Works
./tools/safe-send.sh -c "print(1)" # ✗ Error: multiple sessions
Scenario 3: Backward compatibility
# Old-style explicit socket/target still works:
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
./tools/safe-send.sh -S "$SOCKET" -t "my-session:0.0" -c "ls" # ✓ Always works
Troubleshooting
Common Errors
Error: Session not found in registry
Message:
Error: Session 'my-session' not found in registry
Use 'list-sessions.sh' to see available sessions
Causes:
- Session was never created
- Session was removed from registry
- Typo in session name
Solutions:
# List all registered sessions
./tools/list-sessions.sh
# Create the session if it doesn't exist
./tools/create-session.sh -n my-session --python
# Check for typos in session name (case-sensitive)
Error: Failed to acquire lock
Message:
registry: Failed to acquire lock after 5s
Causes:
- Another process is performing a registry operation
- Previous lock wasn't released (crash/kill)
- Very slow filesystem (rare)
Solutions:
1. Wait and retry (usually self-resolves):
# Wait a few seconds and try again
sleep 2
./tools/safe-send.sh -s my-session -c "command"
2. Check for stuck lock:
# Check if lock exists
ls -la "$CLAUDE_TMUX_SOCKET_DIR/.sessions.lock"*
# If flock-based (file):
ls -la "$CLAUDE_TMUX_SOCKET_DIR/.sessions.lock"
# If mkdir-based (directory):
ls -la "$CLAUDE_TMUX_SOCKET_DIR/.sessions.lock/"
cat "$CLAUDE_TMUX_SOCKET_DIR/.sessions.lock/owner" # See who owns it
3. Manual lock removal (last resort):
# Remove stuck lock (use with caution!)
rm -rf "$CLAUDE_TMUX_SOCKET_DIR/.sessions.lock"
# Then retry your operation
Prevention:
- Don't kill registry operations with
kill -9 - Let operations complete normally
- Increase
LOCK_TIMEOUTfor slow filesystems:export LOCK_TIMEOUT=10 # Increase to 10 seconds ./tools/safe-send.sh -s my-session -c "command"
Error: Multiple sessions found
Message:
Error: Multiple sessions found (3 total)
Please specify session name with -s or use -t/-S explicitly
Use 'list-sessions.sh' to see available sessions
Cause:
- Auto-detect only works when exactly one session exists
- You have multiple registered sessions
Solution:
# List sessions to see what's registered
./tools/list-sessions.sh
# Specify which session to use
./tools/safe-send.sh -s specific-session -c "command"
# Or clean up unused sessions
./tools/cleanup-sessions.sh
Error: Pane not ready
Message:
Error: Pane not ready (health check failed with exit code 1)
Causes:
- Session crashed or was killed
- Pane is marked as dead by tmux
- Process inside pane exited
Solutions:
1. Check session health:
./tools/list-sessions.sh
# Look for status: dead, zombie, or missing
2. Check pane directly:
./tools/pane-health.sh -s my-session
3. Recreate session:
# Remove dead session from registry
./tools/cleanup-sessions.sh
# Create fresh session
./tools/create-session.sh -n my-session --python
4. Debug manually:
# Get session details from registry
./tools/list-sessions.sh --json | jq '.sessions["my-session"]'
# Try to attach to see what happened
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
tmux -S "$SOCKET" attach -t my-session
Stale Registry Entries
What are stale entries?
Stale entries occur when:
- Sessions are in the registry but tmux session is gone
- Tmux server was killed without cleanup
- Registry was manually edited incorrectly
How to detect
Check health status:
./tools/list-sessions.sh
# Look for: dead, missing, zombie, server
Check with health tool:
./tools/pane-health.sh -s session-name
# Non-zero exit code means unhealthy
How to fix
Automatic cleanup (recommended):
# Remove all dead/missing/zombie sessions
./tools/cleanup-sessions.sh
# Preview what would be removed
./tools/cleanup-sessions.sh --dry-run
Manual removal:
# Remove specific session
cd plugins/tmux/tools
source lib/registry.sh
registry_remove_session "session-name"
Nuclear option (clean slate):
# Remove ALL sessions from registry
./tools/cleanup-sessions.sh --all
# Or delete registry file entirely
rm "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json"
Prevention
Use cleanup tools regularly:
# At end of work session
./tools/cleanup-sessions.sh
# Automated daily cleanup (cron)
0 3 * * * /path/to/tools/cleanup-sessions.sh --older-than 1d
Kill sessions properly:
# ✓ Good: Kill session, then cleanup registry
tmux -S "$SOCKET" kill-session -t my-session
./tools/cleanup-sessions.sh
# ✗ Bad: Kill tmux server without cleanup
tmux -S "$SOCKET" kill-server # Leaves stale registry entries
Registry Corruption
What is corruption?
Registry corruption occurs when .sessions.json contains invalid JSON.
How it happens (rare)
- Disk full during write
- Process crash during write (atomic write-then-move prevents this)
- Manual editing with syntax errors
- Filesystem corruption
How to detect
Symptoms:
- Registry operations fail with jq errors
- Tools report "invalid JSON" errors
Verify registry:
# Check if registry is valid JSON
jq empty "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json"
# Exit code 0 = valid, non-zero = invalid
How to fix
1. Backup current registry:
cp "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json" \
"$CLAUDE_TMUX_SOCKET_DIR/.sessions.json.backup"
2. Try to salvage data:
# View the file to see what's wrong
cat "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json"
# Try to fix with jq (if minor issue)
jq '.' "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json.backup" > \
"$CLAUDE_TMUX_SOCKET_DIR/.sessions.json"
3. Rebuild registry (if salvage fails):
# Remove corrupted registry
rm "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json"
# Registry will be recreated on next operation
./tools/list-sessions.sh
# Shows: No sessions registered
# Re-register active sessions manually
./tools/create-session.sh -n my-session --python
4. Recover from tmux sessions:
# List actual tmux sessions
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
tmux -S "$SOCKET" list-sessions
# Re-register them manually
./tools/create-session.sh -n session-name --shell --no-register
# Note: --no-register prevents duplicate registration check
Prevention
- Don't edit
.sessions.jsonmanually (use tools instead) - Monitor disk space (atomic writes fail gracefully if disk full)
- Use the tools (they validate JSON before writing)
- Regular backups (if registry is critical):
# Backup registry (cron) 0 * * * * cp "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json" \ "$HOME/.sessions.json.$(date +%Y%m%d%H)"
Migration Guide
From Manual Socket Management
Before: Manual Approach
Typical manual workflow with repetitive boilerplate:
# Setup (every session)
SOCKET_DIR=${TMPDIR:-/tmp}/claude-tmux-sockets
mkdir -p "$SOCKET_DIR"
SOCKET="$SOCKET_DIR/claude.sock"
SESSION="my-python"
# Create session
tmux -S "$SOCKET" new -d -s "$SESSION" -n shell
tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 \
'PYTHON_BASIC_REPL=1 python3 -q' Enter
# Use session (repeat socket/target every time)
tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 'print("hello")' Enter
./tools/wait-for-text.sh -S "$SOCKET" -t "$SESSION":0.0 -p '>>>'
tmux -S "$SOCKET" send-keys -t "$SESSION":0.0 'import numpy' Enter
./tools/wait-for-text.sh -S "$SOCKET" -t "$SESSION":0.0 -p '>>>'
# Cleanup
tmux -S "$SOCKET" kill-session -t "$SESSION"
Problems:
- Repetitive
-S "$SOCKET" -t "$SESSION":0.0on every command - Must track socket/session variables across script
- No automatic session discovery
- No built-in health tracking
After: Registry Approach
Same workflow with ~80% less boilerplate:
# Create session (auto-registered)
./tools/create-session.sh -n my-python --python
# Use session (auto-detects socket/target)
./tools/safe-send.sh -s my-python -c 'print("hello")' -w '>>>'
./tools/safe-send.sh -c 'import numpy' -w '>>>' # Auto-detect single session
# Cleanup
./tools/cleanup-sessions.sh
Benefits:
- No socket/target repetition
- Auto-detection for single sessions
- Built-in health tracking
- Centralized session management
Step-by-Step Migration
1. Install new tools (already available in tools/)
- ✓
create-session.sh - ✓
list-sessions.sh - ✓
cleanup-sessions.sh - ✓
safe-send.sh(enhanced)
2. Start using registry for new sessions:
# Instead of:
# tmux -S "$SOCKET" new -d -s my-session -n shell
# Do:
./tools/create-session.sh -n my-session --shell
3. Replace socket/target with session name:
# Instead of:
# ./tools/safe-send.sh -S "$SOCKET" -t "$SESSION":0.0 -c "command"
# Do:
./tools/safe-send.sh -s my-session -c "command"
4. Use auto-detect for single sessions:
# If only one session exists:
./tools/safe-send.sh -c "command" # Omit -s entirely
5. Use registry for cleanup:
# Instead of:
# tmux -S "$SOCKET" kill-session -t "$SESSION"
# Do:
./tools/cleanup-sessions.sh
Gradual Migration Strategy
You can use both approaches simultaneously during migration:
Phase 1: New sessions only
- Create new sessions with
create-session.sh - Keep existing manual sessions as-is
- Learn the registry workflow
Phase 2: Mixed usage
- Use registry for new sessions
- Continue manual approach for existing sessions
- Both work side-by-side (backward compatible)
Phase 3: Full adoption
- Migrate remaining manual sessions
- Clean up old manual scripts
- Standardize on registry approach
Best Practices
When to Use Registry vs Manual
Use Registry When:
✓ Interactive development
- Debugging applications
- Exploring code in REPLs
- Running ad-hoc commands
- Frequent context switching
✓ Multi-session workflows
- Managing multiple Python/gdb sessions
- Switching between different projects
- Parallel debugging tasks
✓ Learning and experimentation
- Testing new tools
- Prototyping workflows
- Educational contexts
Use Manual When:
✓ Automation scripts
- CI/CD pipelines
- Deployment scripts
- Automated testing
- Scripts run by other users
✓ Precise control needed
- Custom socket paths for isolation
- Multiple sessions with same name on different sockets
- Temporary sessions that shouldn't be tracked
✓ One-off operations
- Quick debugging session
- Single command execution
- Script that manages its own cleanup
Hybrid Approach:
Use --no-register flag for one-off sessions:
# Create session without registering
./tools/create-session.sh -n temp-debug --gdb --no-register
# Use it manually
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
tmux -S "$SOCKET" send-keys -t temp-debug:0.0 "break main" Enter
# Kill when done
tmux -S "$SOCKET" kill-session -t temp-debug
Session Naming Conventions
Good Session Names
✓ Descriptive and specific:
claude-python # Python REPL for Claude agent
debug-api-server # Debugging API server
test-database-queries # Testing database operations
dev-frontend # Frontend development
✓ Use hyphens (not spaces):
my-python-session # ✓ Good
my_python_session # ✓ OK
my python session # ✗ Bad (spaces cause issues)
✓ Keep it short:
api-debug # ✓ Good (concise)
debugging-the-new-api # ✗ Too long
✓ Use prefixes for grouping:
# Project-based prefixes
proj-backend-api
proj-frontend-dev
proj-database-debug
# Type-based prefixes
python-data-analysis
python-ml-training
gdb-core-dump
gdb-memory-leak
# Environment prefixes
dev-api-server
test-integration
prod-hotfix-debug
Avoid These Patterns
✗ Generic names:
session1, session2, test, temp, debug
# Hard to remember what they're for
✗ Special characters:
my@session, session#1, session.test
# May cause issues with shell parsing
✗ Very long names:
my-very-long-session-name-for-debugging-the-authentication-module
# Tedious to type, hard to remember
Cleanup Strategies
Manual Cleanup
After each work session:
# Remove dead sessions
./tools/cleanup-sessions.sh
# Or preview first
./tools/cleanup-sessions.sh --dry-run
When switching projects:
# Clean slate for new work
./tools/cleanup-sessions.sh --all
Automated Cleanup
Daily cleanup via cron:
# Remove sessions older than 1 day (runs at 3am)
0 3 * * * cd /path/to/tmux/tools && ./cleanup-sessions.sh --older-than 1d
Weekly cleanup via cron:
# Aggressive cleanup once a week (Sunday 2am)
0 2 * * 0 cd /path/to/tmux/tools && ./cleanup-sessions.sh --all
Pre-work cleanup script:
#!/bin/bash
# ~/bin/start-work.sh
# Clean up old sessions
cd ~/tmux-skill/tools
./cleanup-sessions.sh --older-than 12h
# Create fresh sessions for today
./create-session.sh -n work-python --python
./create-session.sh -n work-gdb --gdb
echo "Work environment ready!"
./list-sessions.sh
Conditional Cleanup
In shell scripts:
# Cleanup only if more than N sessions exist
session_count=$(./tools/list-sessions.sh --json | jq '.total')
if [[ $session_count -gt 5 ]]; then
echo "Too many sessions ($session_count), cleaning up..."
./tools/cleanup-sessions.sh --older-than 2h
fi
Cleanup based on disk usage:
# Cleanup if disk usage high (rare scenario)
disk_usage=$(df /tmp | tail -1 | awk '{print $5}' | sed 's/%//')
if [[ $disk_usage -gt 90 ]]; then
echo "Disk usage high, cleaning up sessions..."
./tools/cleanup-sessions.sh --all
fi
Best Practices
✓ Preview first (dry-run before aggressive cleanup):
./tools/cleanup-sessions.sh --dry-run --all
✓ Keep recent sessions (use time-based cleanup):
./tools/cleanup-sessions.sh --older-than 1d # Keep today's work
✓ Document your strategy:
# Add comment in crontab
# Cleanup old tmux sessions daily at 3am
0 3 * * * /path/to/cleanup-sessions.sh --older-than 1d
✗ Don't cleanup aggressively during active work:
# Bad: Cron job every hour during work hours
0 9-17 * * * cleanup-sessions.sh --all # ✗ Will kill active sessions
Advanced Patterns
Multiple Sessions on Same Socket
You can have multiple registered sessions sharing a single socket file:
# All use default socket: /tmp/claude-tmux-sockets/claude.sock
./tools/create-session.sh -n python-1 --python
./tools/create-session.sh -n python-2 --python
./tools/create-session.sh -n gdb-debug --gdb
# Each session has unique target (session:window.pane)
# python-1 → python-1:0.0
# python-2 → python-2:0.0
# gdb-debug → gdb-debug:0.0
# Use sessions independently
./tools/safe-send.sh -s python-1 -c "print(1)"
./tools/safe-send.sh -s python-2 -c "print(2)"
./tools/safe-send.sh -s gdb-debug -c "break main"
# List all sessions on default socket
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
tmux -S "$SOCKET" list-sessions
Benefits:
- Easier session discovery (all on one socket)
- Simplified cleanup (kill-server removes all)
- Lower resource usage (one tmux server)
When to use:
- Multiple debugging contexts in one project
- Parallel Python REPLs for different experiments
- Related sessions that should be grouped together
Custom Socket Paths for Isolation
Use custom sockets to isolate sessions by project or environment:
# Project A sessions
./tools/create-session.sh -n proj-a-python \
-S /tmp/project-a.sock --python
./tools/create-session.sh -n proj-a-gdb \
-S /tmp/project-a.sock --gdb
# Project B sessions
./tools/create-session.sh -n proj-b-python \
-S /tmp/project-b.sock --python
# Sessions are isolated by socket
./tools/list-sessions.sh
# Shows all sessions across all sockets
# Can still use session names
./tools/safe-send.sh -s proj-a-python -c "print('Project A')"
./tools/safe-send.sh -s proj-b-python -c "print('Project B')"
Benefits:
- Clean separation between projects
- Can kill entire project's sessions:
tmux -S /tmp/project-a.sock kill-server - Prevents naming conflicts across projects
- Easier project-based cleanup
When to use:
- Multiple long-running projects
- Client work requiring isolation
- Different tmux configurations per project
CI/CD Integration
Use registry for debugging but not for automated pipelines:
Option 1: Don't Register CI Sessions
#!/bin/bash
# ci-test.sh - CI/CD test script
# Create unregistered session
./tools/create-session.sh -n ci-test-$$ \
--shell --no-register
# Use explicit socket/target (bypass registry)
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
TARGET="ci-test-$$:0.0"
# Run tests
./tools/safe-send.sh -S "$SOCKET" -t "$TARGET" \
-c "pytest tests/" -w "passed"
# Cleanup (explicit kill, no registry)
tmux -S "$SOCKET" kill-session -t "ci-test-$$"
Why:
- CI sessions are ephemeral
- No need to track them in registry
- Explicit socket/target gives full control
Option 2: Use Registry with Auto-Cleanup
#!/bin/bash
# ci-test-with-registry.sh
# Create registered session
./tools/create-session.sh -n ci-test-$$ --python
# Use session name
./tools/safe-send.sh -s ci-test-$$ \
-c "import pytest; pytest.main(['tests/'])" -w "passed"
# Cleanup via registry
./tools/cleanup-sessions.sh
Why:
- Easier debugging (can inspect sessions)
- Automatic cleanup with registry tools
- Good for hybrid local/CI workflows
Best Practice for CI
Use environment variable to decide:
#!/bin/bash
# Smart CI/local script
if [[ -n "$CI" ]]; then
# CI: Use explicit approach, no registry
SESSION="ci-test-$$"
./tools/create-session.sh -n "$SESSION" --python --no-register
SOCKET="/tmp/claude-tmux-sockets/claude.sock"
./tools/safe-send.sh -S "$SOCKET" -t "$SESSION:0.0" -c "pytest"
tmux -S "$SOCKET" kill-session -t "$SESSION"
else
# Local: Use registry for convenience
./tools/create-session.sh -n local-test --python
./tools/safe-send.sh -s local-test -c "pytest"
# Manual cleanup when done
fi
See Also
- SKILL.md - Quick reference and common usage
- tmux man page - Official tmux documentation
- Implementation Tracker - Development status and roadmap