Files
gh-dashed-claude-marketplac…/references/session-registry.md
2025-11-29 18:17:58 +08:00

1485 lines
35 KiB
Markdown

# Session Registry Reference
This document provides comprehensive documentation for the tmux skill session registry system.
## Table of Contents
1. [Overview](#overview)
2. [Architecture](#architecture)
3. [Registry File Format](#registry-file-format)
4. [Tool Reference](#tool-reference)
5. [Session Resolution](#session-resolution)
6. [Troubleshooting](#troubleshooting)
7. [Migration Guide](#migration-guide)
8. [Best Practices](#best-practices)
9. [Advanced Patterns](#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 target` on 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):**
```bash
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):**
```bash
./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:
1. **Registry Library** (`tools/lib/registry.sh`)
- Core CRUD operations
- Portable file locking
- JSON validation
- Activity tracking
2. **Registry File** (`$CLAUDE_TMUX_SOCKET_DIR/.sessions.json`)
- JSON database of registered sessions
- Atomic updates with write-then-move
- Human-readable format
3. **Management Tools**
- `create-session.sh` - Create and register sessions
- `list-sessions.sh` - View all sessions with health status
- `cleanup-sessions.sh` - Remove dead/old sessions
4. **Enhanced Tools**
- `safe-send.sh` - Send commands by session name
- `wait-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 `flock` for 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:**
```bash
# 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:
1. **Lock** - Acquire registry lock
2. **Read** - Load current registry data
3. **Modify** - Make changes to in-memory copy
4. **Write** - Write to temporary file
5. **Validate** - Verify JSON with `jq`
6. **Move** - Atomically move temp file to registry (if valid)
7. **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:
```bash
$CLAUDE_TMUX_SOCKET_DIR/.sessions.json
```
Where `CLAUDE_TMUX_SOCKET_DIR` defaults to:
```bash
${TMPDIR:-/tmp}/claude-tmux-sockets
```
### JSON Schema
The registry is a JSON file with the following structure:
```json
{
"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
```json
{
"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
```bash
./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=1` set
- 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 off` recommended
- 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:
```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:**
```bash
./tools/create-session.sh -n claude-python --python
```
**Create gdb session:**
```bash
./tools/create-session.sh -n debug-app --gdb
```
**Create session with custom socket:**
```bash
./tools/create-session.sh -n isolated-session -S /tmp/custom.sock --shell
```
**Create without registering (one-off session):**
```bash
./tools/create-session.sh -n temp-work --shell --no-register
```
**Create with custom window name:**
```bash
./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
```bash
./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`):**
```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:**
```bash
./tools/list-sessions.sh
```
**List sessions as JSON for scripting:**
```bash
./tools/list-sessions.sh --json | jq '.sessions[] | select(.status == "alive")'
```
**Count alive sessions:**
```bash
./tools/list-sessions.sh --json | jq '.alive'
```
**Get all Python sessions:**
```bash
./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
```bash
./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 minutes
- `2h` - 2 hours
- `1d` - 1 day
- `3600s` - 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_at` timestamp
- 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):**
```bash
./tools/cleanup-sessions.sh
```
**Dry-run to preview cleanup:**
```bash
./tools/cleanup-sessions.sh --dry-run
```
**Remove sessions inactive for more than 1 hour:**
```bash
./tools/cleanup-sessions.sh --older-than 1h
```
**Remove sessions older than 2 days:**
```bash
./tools/cleanup-sessions.sh --older-than 2d
```
**Remove all sessions (clean slate):**
```bash
./tools/cleanup-sessions.sh --all
```
**Combine dry-run with age filter:**
```bash
./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:**
```bash
# 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:**
```bash
#!/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:**
1. **Session name** (`-s`): Look up socket/target from registry
2. **Explicit** (`-S` + `-t`): Specify socket and target directly (backward compatible)
3. **Auto-detect**: Omit all flags, auto-detect single session
#### Priority Order
When multiple options are provided, they are resolved in this order:
1. **Explicit flags** (`-S` and `-t`): Highest priority, backward compatible
2. **Session name** (`-s`): Look up in registry
3. **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:**
```bash
./tools/safe-send.sh -s claude-python -c "print('hello')" -w ">>>"
```
**Auto-detect single session:**
```bash
./tools/safe-send.sh -c "print('world')" -w ">>>"
```
**Explicit (backward compatible):**
```bash
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**
```bash
# 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**
```bash
# 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**
```bash
# 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:**
```bash
# 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):
```bash
# Wait a few seconds and try again
sleep 2
./tools/safe-send.sh -s my-session -c "command"
```
**2. Check for stuck lock:**
```bash
# 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):
```bash
# 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_TIMEOUT` for slow filesystems:
```bash
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:**
```bash
# 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:**
```bash
./tools/list-sessions.sh
# Look for status: dead, zombie, or missing
```
**2. Check pane directly:**
```bash
./tools/pane-health.sh -s my-session
```
**3. Recreate session:**
```bash
# Remove dead session from registry
./tools/cleanup-sessions.sh
# Create fresh session
./tools/create-session.sh -n my-session --python
```
**4. Debug manually:**
```bash
# 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:**
```bash
./tools/list-sessions.sh
# Look for: dead, missing, zombie, server
```
**Check with health tool:**
```bash
./tools/pane-health.sh -s session-name
# Non-zero exit code means unhealthy
```
#### How to fix
**Automatic cleanup (recommended):**
```bash
# Remove all dead/missing/zombie sessions
./tools/cleanup-sessions.sh
# Preview what would be removed
./tools/cleanup-sessions.sh --dry-run
```
**Manual removal:**
```bash
# Remove specific session
cd plugins/tmux/tools
source lib/registry.sh
registry_remove_session "session-name"
```
**Nuclear option (clean slate):**
```bash
# 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:**
```bash
# 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:**
```bash
# ✓ 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:**
```bash
# 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:**
```bash
cp "$CLAUDE_TMUX_SOCKET_DIR/.sessions.json" \
"$CLAUDE_TMUX_SOCKET_DIR/.sessions.json.backup"
```
**2. Try to salvage data:**
```bash
# 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):**
```bash
# 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:**
```bash
# 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.json` manually** (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):
```bash
# 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:
```bash
# 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.0` on 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:
```bash
# 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:**
```bash
# 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:**
```bash
# 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:**
```bash
# If only one session exists:
./tools/safe-send.sh -c "command" # Omit -s entirely
```
**5. Use registry for cleanup:**
```bash
# 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:
```bash
# 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:**
```bash
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):**
```bash
my-python-session # ✓ Good
my_python_session # ✓ OK
my python session # ✗ Bad (spaces cause issues)
```
✓ **Keep it short:**
```bash
api-debug # ✓ Good (concise)
debugging-the-new-api # ✗ Too long
```
✓ **Use prefixes for grouping:**
```bash
# 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:**
```bash
session1, session2, test, temp, debug
# Hard to remember what they're for
```
✗ **Special characters:**
```bash
my@session, session#1, session.test
# May cause issues with shell parsing
```
✗ **Very long names:**
```bash
my-very-long-session-name-for-debugging-the-authentication-module
# Tedious to type, hard to remember
```
---
### Cleanup Strategies
#### Manual Cleanup
**After each work session:**
```bash
# Remove dead sessions
./tools/cleanup-sessions.sh
# Or preview first
./tools/cleanup-sessions.sh --dry-run
```
**When switching projects:**
```bash
# Clean slate for new work
./tools/cleanup-sessions.sh --all
```
#### Automated Cleanup
**Daily cleanup via cron:**
```bash
# 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:**
```bash
# Aggressive cleanup once a week (Sunday 2am)
0 2 * * 0 cd /path/to/tmux/tools && ./cleanup-sessions.sh --all
```
**Pre-work cleanup script:**
```bash
#!/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:**
```bash
# 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:**
```bash
# 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):
```bash
./tools/cleanup-sessions.sh --dry-run --all
```
✓ **Keep recent sessions** (use time-based cleanup):
```bash
./tools/cleanup-sessions.sh --older-than 1d # Keep today's work
```
✓ **Document your strategy:**
```bash
# 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:**
```bash
# 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:
```bash
# 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:
```bash
# 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
```bash
#!/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
```bash
#!/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:
```bash
#!/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](../SKILL.md) - Quick reference and common usage
- [tmux man page](https://man.openbsd.org/tmux.1) - Official tmux documentation
- [Implementation Tracker](../../notes/tmux/session-registry-implementation.md) - Development status and roadmap