-
-
Save elijahr/96b5c31e98a721326ad64735334186b1 to your computer and use it in GitHub Desktop.
Claude Session Manager - tmux session manager for Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Claude Session Manager for Git Worktrees (Zellij Edition) | |
| # Fork of tmux-based Claude Session Manager by nazq https://gist.github.com/nazq/3d179988627b15119944da573c91f1ab | |
| # Usage: cs [session_name] | |
| # See 'cs help' for details | |
| # Initialize Claude session if environment variable is set | |
| _cs_session_init() { | |
| if [[ -z "$CLAUDE_SESSION_ZELLIJ_INIT" ]]; then | |
| return 0; | |
| fi | |
| local session_data="$CLAUDE_SESSION_ZELLIJ_INIT" | |
| # Unset immediately to prevent nested initialization | |
| unset CLAUDE_SESSION_ZELLIJ_INIT | |
| # Parse session data (format: session_name|working_directory) | |
| local session_name="${session_data%%|*}" | |
| local working_dir="${session_data##*|}" | |
| # Change to working directory | |
| if [[ -n "$working_dir" && -d "$working_dir" ]]; then | |
| cd "$working_dir" | |
| fi | |
| echo "π€ Starting Claude Code session for: $session_name" | |
| echo "π Directory: $PWD" | |
| # Check if claude command exists | |
| if ! command -v claude >/dev/null 2>&1; then | |
| echo "β οΈ Warning: 'claude' command not found" | |
| echo " Make sure Claude Code is installed and in your PATH" | |
| echo " You can install it from: https://claude.ai/download" | |
| else | |
| # Start Claude | |
| echo "π Starting Claude Code..." | |
| claude | |
| fi | |
| } | |
| _cs_session_init | |
| # --- Core Utility Functions (Unix Philosophy) --- | |
| # Get a random animal name from the predefined list | |
| _cs_get_random_animal() { | |
| local animals=( | |
| "albatross" "alligator" "alpaca" "ant" "antelope" "ape" "armadillo" "donkey" | |
| "baboon" "badger" "bat" "bear" "beaver" "bee" "beetle" "binturong" | |
| "boar" "bobcat" "bull" "butterfly" "camel" "cardinal" "cat" "cattle" | |
| "cheetah" "chicken" "chimpanzee" "chinchilla" "chough" "cobra" "cockroach" "cod" | |
| "cormorant" "cow" "crab" "crane" "crocodile" "crow" "deer" "dog" | |
| "dogfish" "dolphin" "donkey" "dove" "duck" "dunlin" "eagle" "echidna" | |
| "eel" "elephant" "elk" "emu" "falcon" "ferret" "finch" "flamingo" | |
| "fly" "fox" "frog" "gecko" "gerbil" "panda" "giraffe" "gnat" | |
| "gnu" "goat" "goldfinch" "goosander" "goose" "gorilla" "goshawk" "grasshopper" | |
| "grouse" "guanaco" "guinea_fowl" "guinea_pig" "hamster" "hare" "hawk" "hedgehog" | |
| "heron" "herring" "hippopotamus" "hornet" "horse" "human" "hyena" "jaguar" | |
| "jay" "jellyfish" "junglefowl" "kangaroo" "kingbird" "kinkajou" "koala" "ladybug" | |
| "lapwing" "lark" "lemur" "leopard" "lion" "lizard" "llama" "lobster" | |
| "locust" "lyrebird" "mallard" "meerkat" "mole" "mongoose" "monkey" "moose" | |
| "mosquito" "moth" "mouse" "narwhal" "newt" "nightingale" "octopus" "opossum" | |
| "otter" | |
| ) | |
| # Seed random number generator with current time and process ID for better randomness | |
| RANDOM=$(( $(date +%s) + $$ + $(date +%N | sed 's/^0*//') )) | |
| local random_index=$(( RANDOM % ${#animals[@]} )) | |
| echo "${animals[$random_index]}" | |
| } | |
| # Get the current directory's session name pattern | |
| _cs_get_current_dir_pattern() { | |
| if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then | |
| local repo_name="" | |
| local remote_url=$(git remote get-url origin 2>/dev/null) | |
| if [[ -n "$remote_url" ]]; then | |
| repo_name=$(basename "$remote_url" .git) | |
| else | |
| repo_name=$(basename "$(git rev-parse --show-toplevel)") | |
| fi | |
| local branch_name=$(git branch --show-current 2>/dev/null) | |
| if [[ -z "$branch_name" ]]; then | |
| branch_name=$(git rev-parse --short HEAD 2>/dev/null || echo "detached") | |
| fi | |
| # Return sanitized pattern (same as session creation logic) | |
| echo "${repo_name}:${branch_name}" | sed 's/:/_/g' | sed 's/[^a-zA-Z0-9._-]/_/g' | |
| else | |
| # Return sanitized directory name pattern | |
| basename "$PWD" | sed 's/:/_/g' | sed 's/[^a-zA-Z0-9._-]/_/g' | |
| fi | |
| } | |
| # Generate an auto session name for current directory | |
| _cs_generate_auto_session_name() { | |
| local pattern=$(_cs_get_current_dir_pattern) | |
| local animal=$(_cs_get_random_animal) | |
| echo "${pattern}-${animal}" | |
| } | |
| # Sanitize a session name for zellij compatibility | |
| _cs_sanitize_session_name() { | |
| local name="$1" | |
| echo "$name" | sed 's/:/_/g' | sed 's/[^a-zA-Z0-9._-]/_/g' | |
| } | |
| # Check if a session exists (active or dead) | |
| _cs_session_exists() { | |
| local session_name="$1" | |
| zellij list-sessions | grep -q "^$session_name " | |
| } | |
| # Get all session names as an array | |
| _cs_get_all_sessions() { | |
| zellij list-sessions --short 2>/dev/null | cut -d' ' -f1 | tr -d "'" | sort | |
| } | |
| # Get session by index number | |
| _cs_get_session_by_number() { | |
| local number="$1" | |
| # Validate input | |
| if [[ -z "$number" ]]; then | |
| echo "β No session number provided" >&2 | |
| return 1 | |
| fi | |
| if ! [[ "$number" =~ ^[0-9]+$ ]]; then | |
| echo "β Invalid session number: '$number' (must be a positive integer)" >&2 | |
| return 1 | |
| fi | |
| local index_offset=0; [[ -z "$ZSH_VERSION" ]] && index_offset=1 | |
| local sessions=($(_cs_get_all_sessions)) | |
| if [[ ${#sessions[@]} -eq 0 ]]; then | |
| echo "β No active sessions found" >&2 | |
| return 1 | |
| fi | |
| if [[ "$number" -lt 1 || "$number" -gt ${#sessions[@]} ]]; then | |
| echo "β Invalid session number: $number (valid range: 1-${#sessions[@]})" >&2 | |
| echo "π Available sessions:" >&2 | |
| _cs_list_all_sessions >&2 | |
| return 1 | |
| fi | |
| echo "${sessions[$((number - index_offset))]}" | |
| } | |
| # List all sessions with numbers | |
| _cs_list_all_sessions() { | |
| echo "π Active Zellij sessions:" | |
| local sessions_info=$(zellij list-sessions --short 2>/dev/null | sort) | |
| if [[ -z "$sessions_info" ]]; then | |
| echo " No active sessions found" | |
| return 0 | |
| fi | |
| local i=1 | |
| while IFS= read -r session_line; do | |
| printf "%2d. %s\n" "$i" "$session_line" | |
| ((i++)) | |
| done <<< "$sessions_info" | |
| } | |
| # List sessions for current directory only | |
| _cs_list_current_dir_sessions() { | |
| local pattern=$(_cs_get_current_dir_pattern) | |
| local sessions_info=$(zellij list-sessions --short 2>/dev/null | sort) | |
| if [[ -z "$sessions_info" ]]; then | |
| echo "π No active sessions found" | |
| return 0 | |
| fi | |
| echo "π Sessions for current directory ($pattern):" | |
| local i=1 | |
| local found_any=false | |
| while IFS= read -r session_line; do | |
| local session_name=$(echo "$session_line" | cut -d' ' -f1 | tr -d "'") | |
| if [[ "$session_name" =~ ^${pattern}(-[a-z]+)?$ ]]; then | |
| printf "%2d. %s\n" "$i" "$session_line" | |
| found_any=true | |
| fi | |
| ((i++)) | |
| done <<< "$sessions_info" | |
| if [[ "$found_any" == false ]]; then | |
| echo " No sessions found for current directory" | |
| echo " Use 'cs la' to see all sessions" | |
| fi | |
| } | |
| # Resolve session identifier (number or name) to session name | |
| _cs_resolve_session_identifier() { | |
| local identifier="$1" | |
| if [[ -z "$identifier" ]]; then | |
| echo "β No session identifier provided" >&2 | |
| return 1 | |
| fi | |
| if [[ "$identifier" =~ ^[0-9]+$ ]]; then | |
| # Resolve by number | |
| _cs_get_session_by_number "$identifier" | |
| else | |
| # Resolve by name - validate it exists | |
| if _cs_session_exists "$identifier"; then | |
| echo "$identifier" | |
| else | |
| echo "β Session '$identifier' does not exist" >&2 | |
| return 1 | |
| fi | |
| fi | |
| } | |
| # Attach to a session by number or name | |
| _cs_attach_session() { | |
| local identifier="$1" | |
| local session_name | |
| session_name=$(_cs_resolve_session_identifier "$identifier") | |
| if [[ $? -ne 0 ]]; then | |
| echo "Use 'cs list' to see available sessions" >&2 | |
| return 1 | |
| fi | |
| echo "π Attaching to session: $session_name" | |
| exec zellij attach "$session_name" | |
| } | |
| # Kill a session by number or name | |
| _cs_kill_session() { | |
| local identifier="$1" | |
| local session_name | |
| session_name=$(_cs_resolve_session_identifier "$identifier") | |
| if [[ $? -ne 0 ]]; then | |
| echo "Use 'cs list' to see available sessions" >&2 | |
| return 1 | |
| fi | |
| echo "π Killing session: $session_name" | |
| if zellij kill-session "$session_name" 2>/dev/null; then | |
| echo "β Session killed successfully" | |
| return 0 | |
| else | |
| echo "β Failed to kill session '$session_name'" >&2 | |
| return 1 | |
| fi | |
| } | |
| # Kill all Claude-related sessions | |
| _cs_kill_all_sessions() { | |
| local all_sessions=$(zellij list-sessions -n --no-formatting 2>/dev/null) | |
| local claude_sessions="" | |
| while IFS= read -r session; do | |
| if [[ "$session" =~ (claude|_|-) ]]; then | |
| claude_sessions+="$session"$'\n' | |
| fi | |
| done <<< "$all_sessions" | |
| claude_sessions=$(echo -n "$claude_sessions") | |
| if [[ -n "$claude_sessions" ]]; then | |
| echo "π Found likely Claude sessions:" | |
| echo "$claude_sessions" | sed 's/^/ /' | |
| echo "" | |
| read -p "Kill these sessions? (y/N): " confirm | |
| if [[ "$confirm" =~ ^[Yy]$ ]]; then | |
| echo "$claude_sessions" | xargs -I {} zellij kill-session {} | |
| echo "β Sessions terminated" | |
| else | |
| echo "β Cancelled" | |
| fi | |
| else | |
| echo "βΉοΈ No Claude sessions to kill" | |
| fi | |
| } | |
| # Find an available session name (handles conflicts for auto-generated names) | |
| _cs_find_available_session_name() { | |
| local base_name="$1" | |
| local is_custom="$2" # "true" if custom name, "false" if auto-generated | |
| local session_name="$base_name" | |
| local attempt_count=0 | |
| local max_attempts=10 | |
| while [[ $attempt_count -lt $max_attempts ]]; do | |
| if _cs_session_exists "$session_name"; then | |
| if [[ "$is_custom" == "true" ]]; then | |
| # For custom names, prompt the user | |
| echo "β‘ Session '$session_name' already exists!" | |
| read -p "Do you want to [a]ttach or [k]ill and recreate? (a/k): " choice | |
| case $choice in | |
| a|A|"") | |
| _cs_attach_session "$session_name" | |
| return $? # This will exec, so we won't return normally | |
| ;; | |
| k|K) | |
| _cs_kill_session "$session_name" | |
| break | |
| ;; | |
| *) | |
| echo "β Invalid choice. Please choose 'a' to attach or 'k' to kill and recreate." | |
| ;; | |
| esac | |
| else | |
| # For auto-generated names, try a different animal | |
| ((attempt_count++)) | |
| echo "π Session '$session_name' exists, trying with different animal (attempt $attempt_count/$max_attempts)..." | |
| local new_animal=$(_cs_get_random_animal) | |
| # Extract the base pattern (everything before the last hyphen and animal) | |
| local pattern_part="${base_name%-*}" | |
| session_name="${pattern_part}-${new_animal}" | |
| fi | |
| else | |
| # Session name is available | |
| break | |
| fi | |
| done | |
| if [[ $attempt_count -ge $max_attempts ]]; then | |
| echo "β Could not find an available session name after $max_attempts attempts" >&2 | |
| return 1 | |
| fi | |
| echo "$session_name" | |
| } | |
| # Create and enter a new session | |
| _cs_create_session() { | |
| local session_name="$1" | |
| local use_exec="${2:-false}" | |
| shift 2 | |
| local zellij_args=("$@") # Additional arguments to pass to zellij | |
| # Validate input | |
| if [[ -z "$session_name" ]]; then | |
| echo "β No session name provided" >&2 | |
| return 1 | |
| fi | |
| echo "π Creating Zellij session: $session_name" | |
| echo "π Directory: $PWD" | |
| if [[ ${#zellij_args[@]} -gt 0 ]]; then | |
| echo "βοΈ Additional args: ${zellij_args[*]}" | |
| echo "π§ Command: zellij ${zellij_args[*]} --session $session_name" | |
| fi | |
| if [[ "$use_exec" == "true" ]]; then | |
| # Execute zellij session directly (this replaces current process) | |
| echo "π Replacing current shell with Zellij session..." | |
| if [[ ${#zellij_args[@]} -gt 0 ]]; then | |
| CLAUDE_SESSION_ZELLIJ_INIT="${session_name}|${PWD}" exec zellij "${zellij_args[@]}" --session "$session_name" | |
| else | |
| CLAUDE_SESSION_ZELLIJ_INIT="${session_name}|${PWD}" exec zellij --session "$session_name" | |
| fi | |
| else | |
| # Run zellij session normally (can be exited without closing parent) | |
| echo "π Starting Zellij session with CLAUDE_SESSION_ZELLIJ_INIT=${session_name}|${PWD}..." | |
| local exit_status=0 | |
| if [[ ${#zellij_args[@]} -gt 0 ]]; then | |
| CLAUDE_SESSION_ZELLIJ_INIT="${session_name}|${PWD}" zellij "${zellij_args[@]}" --session "$session_name" || exit_status=$? | |
| else | |
| CLAUDE_SESSION_ZELLIJ_INIT="${session_name}|${PWD}" zellij --session "$session_name" || exit_status=$? | |
| fi | |
| if [[ $exit_status -eq 0 ]]; then | |
| echo "π€ Exited Zellij session: $session_name with status $exit_status" | |
| return 0 | |
| else | |
| echo "β Failed to start Zellij session: $session_name (exit code $exit_status)" >&2 | |
| return 1 | |
| fi | |
| fi | |
| } | |
| # --- Help and Utility Functions --- | |
| # Show main help message | |
| _cs_help() { | |
| echo "cs - Claude Session Manager for Zellij" | |
| echo "" | |
| echo "Usage:" | |
| echo " cs [session_name] Create session with name (or auto-generate) and enter it" | |
| echo " cs replace [name] Create session and replace current shell (exec)" | |
| echo " cs list List sessions for current directory" | |
| echo " cs listall List all active sessions with numbers" | |
| echo " cs attach <number|name> Attach to session by number or name" | |
| echo " cs kill <number|name> Kill session by number or name" | |
| echo " cs killall Kill all Claude-related sessions" | |
| echo " cs help Show this help message" | |
| echo "" | |
| echo "Passing arguments to zellij:" | |
| echo " cs [session_name] -- [zellij_args] Pass additional args to zellij" | |
| echo " cs replace [name] -- [zellij_args] Pass additional args to zellij" | |
| echo "" | |
| echo "Short forms:" | |
| echo " cs l = cs list" | |
| echo " cs la = cs listall" | |
| echo " cs r = cs replace" | |
| echo " cs a N = cs attach N" | |
| echo " cs k N = cs kill N" | |
| echo " cs ka = cs killall" | |
| echo " cs h = cs help" | |
| echo "" | |
| echo "Session naming:" | |
| echo " - Auto-generated: REPO:BRANCH-ANIMAL or FOLDER-ANIMAL" | |
| echo " - If auto-generated name exists, tries different animals" | |
| echo " - If custom name exists, prompts to attach or recreate" | |
| echo "" | |
| echo "Examples:" | |
| echo " cs # Create session with auto-generated name" | |
| echo " cs my-project # Create session named 'my-project'" | |
| echo " cs r # Create session and replace current shell" | |
| echo " cs r my-project # Create 'my-project' session and replace shell" | |
| echo " cs l # List sessions for current directory" | |
| echo " cs la # List all sessions" | |
| echo " cs a 3 # Attach to session #3" | |
| echo " cs a my-session # Attach to session named 'my-session'" | |
| echo " cs k 2 # Kill session #2" | |
| echo " cs k my-session # Kill session named 'my-session'" | |
| echo " cs ka # Kill all Claude sessions" | |
| echo "" | |
| echo "Examples with zellij arguments:" | |
| echo " cs -- --new-session-with-layout compact # Create session with compact layout" | |
| echo " cs my-proj -- --new-session-with-layout /path/layout # Create 'my-proj' with custom layout" | |
| echo " cs r -- --config /path/config # Replace shell with custom config" | |
| } | |
| # Handle attach command with validation | |
| _cs_handle_attach() { | |
| local identifier="$1" | |
| if [[ -n "$identifier" ]]; then | |
| _cs_attach_session "$identifier" | |
| else | |
| echo "β Usage: cs attach <number|name>" | |
| echo "Use 'cs list' to see numbered sessions" | |
| return 1 | |
| fi | |
| } | |
| # Handle kill command with validation | |
| _cs_handle_kill() { | |
| local identifier="$1" | |
| if [[ -n "$identifier" ]]; then | |
| _cs_kill_session "$identifier" | |
| else | |
| echo "β Usage: cs kill <number|name>" | |
| echo "Use 'cs list' to see numbered sessions" | |
| return 1 | |
| fi | |
| } | |
| # Handle replace command | |
| _cs_replace() { | |
| local custom_name="$1" | |
| shift | |
| local zellij_args=("$@") | |
| local session_name | |
| local is_custom="false" | |
| if [[ -n "$custom_name" ]]; then | |
| # Custom session name provided | |
| session_name=$(_cs_sanitize_session_name "$custom_name") | |
| is_custom="true" | |
| echo "π― Using custom session name: $session_name" | |
| else | |
| # Auto-generate session name | |
| session_name=$(_cs_sanitize_session_name "$(_cs_generate_auto_session_name)") | |
| if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then | |
| echo "π Git worktree detected: $session_name" | |
| else | |
| echo "π Using directory name: $session_name" | |
| fi | |
| fi | |
| # Find available session name (handles conflicts) | |
| session_name=$(_cs_find_available_session_name "$session_name" "$is_custom") | |
| if [[ $? -ne 0 ]]; then | |
| return 1 | |
| fi | |
| # Create and replace with the session | |
| _cs_create_session "$session_name" "true" "${zellij_args[@]}" | |
| } | |
| # Handle session creation (default behavior) | |
| _cs_handle_new() { | |
| local custom_name="$1" | |
| shift | |
| local zellij_args=("$@") | |
| local session_name | |
| local is_custom="false" | |
| if [[ -n "$custom_name" ]]; then | |
| session_name=$(_cs_sanitize_session_name "$custom_name") | |
| is_custom="true" | |
| echo "π― Using custom session name: $session_name" | |
| else | |
| session_name=$(_cs_sanitize_session_name "$(_cs_generate_auto_session_name)") | |
| if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then | |
| echo "π Git worktree detected: $session_name" | |
| else | |
| echo "π Using directory name: $session_name" | |
| fi | |
| fi | |
| # Find available session name (handles conflicts) | |
| session_name=$(_cs_find_available_session_name "$session_name" "$is_custom") | |
| if [[ $? -ne 0 ]]; then | |
| return 1 | |
| fi | |
| # Create and enter the session (without exec) | |
| _cs_create_session "$session_name" "false" "${zellij_args[@]}" | |
| } | |
| # --- Main CS Command --- | |
| # Main cs function with subcommand support and session creation | |
| cs() { | |
| # Handle `--` separator for passing args to zellij | |
| local zellij_args=() | |
| local cs_args=() | |
| local found_separator=false | |
| # Split arguments at `--` | |
| while [[ $# -gt 0 ]]; do | |
| if [[ "$1" == "--" ]]; then | |
| found_separator=true | |
| shift | |
| break | |
| fi | |
| cs_args+=("$1") | |
| shift | |
| done | |
| # Everything after `--` goes to zellij | |
| if [[ "$found_separator" == "true" ]]; then | |
| zellij_args=("$@") | |
| fi | |
| # Process cs arguments | |
| set -- "${cs_args[@]}" | |
| case "${1:-}" in | |
| # List sessions for current directory | |
| l|list) | |
| _cs_list_current_dir_sessions | |
| ;; | |
| # List all sessions globally | |
| la|listall) | |
| _cs_list_all_sessions | |
| ;; | |
| # Attach to session by number or name | |
| a|attach) | |
| _cs_handle_attach "$2" | |
| ;; | |
| # Kill session by number or name | |
| k|kill) | |
| _cs_handle_kill "$2" | |
| ;; | |
| # Kill all sessions | |
| ka|killall) | |
| _cs_kill_all_sessions | |
| ;; | |
| # Replace current shell with new session (exec behavior) | |
| r|replace) | |
| _cs_replace "$2" "${zellij_args[@]}" | |
| ;; | |
| # Help | |
| h|help|--help|-h) | |
| _cs_help | |
| ;; | |
| # Default: create new session | |
| *) | |
| _cs_handle_new "$1" "${zellij_args[@]}" | |
| ;; | |
| esac | |
| } | |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Claude Session Manager Setup & Usage Guide (Zellij Edition)
π Quick Setup (for Bash and Zsh)
1. Download the script
2. Add to your shell's config file
Add the following line to your configuration file.
~/.zshrc(It doesn't matter that the script is in~/.bash_functions)~/.bashrcor~/.bash_profile3. Reload your shell
For Zsh:
For Bash:
π Usage
Core Commands
Session Creation
cs- Create a new Claude session with an auto-generated name (REPO:BRANCH-ANIMAL or FOLDER-ANIMAL)cs my-project- Create a session with a custom namecs replaceorcs r- Create session and replace current shell (exec behavior)cs r my-project- Create custom-named session and replace current shellSession Management
cs listorcs l- List sessions for current directory onlycs listallorcs la- List all active sessions with numberscs attach 3orcs a 3- Attach to session #3 from the listcs kill 2orcs k 2- Kill session #2 from the listcs killallorcs ka- Kill all Claude-related sessions (with confirmation)Help
cs helporcs h- Show detailed help messageSession Naming Logic
The script uses intelligent auto-naming with animal suffixes:
REPO:BRANCH-ANIMAL(e.g.,webapp:feature-auth-dolphin)FOLDER-ANIMAL(e.g.,my-notes-elephant)Animal Names
Sessions get random animal suffixes from a curated list of 80+ animals:
albatross,dolphin,elephant,falcon,giraffe,hedgehog,jaguar,koala,llama,octopus,penguin, etc.Examples
Short Forms
All commands have convenient short forms:
cs l=cs listcs la=cs listallcs r=cs replacecs a N=cs attach Ncs k N=cs kill Ncs ka=cs killallcs h=cs helpπ― Key Features
Smart Naming
Session Management
cs lshows only relevant sessionscs lashows all sessions with numbersExecution Models
cscreates session you can exit normallycs rreplaces current shell (exec behavior)Unix Philosophy Design
π Requirements
claudecommand)π‘ Pro Tips
Workflow Optimization
cs lfrequently to see sessions for your current projectcs lato get the big picture of all active sessionscs a 3,cs k 2) for speedcs rwhen you want to fully commit to a sessionNaming Strategy
cs l) keeps things organizedSession Lifecycle
cs kaperiodically to clean up unused sessionsTroubleshooting
zellijandclaudecommands are availablecs lato verify session state before operations