# claude-tmux ## Purpose Spawn a detached `tmux` session running Claude Code (via `claude-profile`) with Remote Control enabled, in a project's directory, with the session named after the project so it is easy to `tmux attach` to and easy to identify in the Claude app. ## Usage ``` claude-tmux [PROJECT] [OPTIONS] ``` ### Arguments | Argument | Default | Description | |----------|---------|-------------| | `PROJECT` | *(prompt if TTY)* | Project name (folder under `~/dev/claude` or `~/dev/claude/projects`), or an explicit path to a directory | ### Flags | Flag | Default | Description | |------|---------|-------------| | `--mode ` | profile's `last-mode`, else `quick` | Engagement mode passed to `claude-profile` | | `--profile ` | `oreillyit-anthropic` | Claude Code profile (resolves to `~/.claude-`, or `~/.claude` for `default`) | | `--name ` | Title-cased project name | Override the session / Remote-Control name | | `--attach` | off | Attach (or `switch-client` if already inside tmux) after spawning | | `--dryrun`, `-n` | off | Preview all actions without creating anything | | `--help`, `-h` | | Show usage information | ## Behaviour 1. Resolve the profile directory (`~/.claude-`, or `~/.claude` for `default`). Error if it does not exist. 2. Resolve the project. If `PROJECT` is empty and stdin is a TTY, prompt for it; if empty and not a TTY, error. Resolve the folder by trying, in order: an existing path, `~/dev/claude/`, `~/dev/claude/projects/`. Error if none exist. 3. Resolve the engagement mode. If `--mode` is not given, read the profile's `last-mode` file, falling back to `quick`. The mode is **always** resolved explicitly and passed to `claude-profile` — the launcher must never leave `claude-profile` to show its interactive mode picker, because Remote Control only registers in the app once `claude` is actually running. 4. Derive the base session name: Title-Case the project folder basename (`agent-runtimes` → `Agent Runtimes`), unless `--name` overrides it. 5. Auto-increment: if a tmux session with the base name already exists, append ` #2`, ` #3`, … until a free name is found. The first session gets no suffix. 6. Create a detached tmux session named after the resolved name, with its working directory set to the project folder. 7. Send the launch command into the session's pane (sent literally, followed by Enter): `claude-profile --mode --project -- --remote-control ""` 8. Print the attach hint and the Remote-Control name. If `--attach` is set, attach (or `switch-client` when already inside tmux). `claude-profile` is located via `PATH`, falling back to a sibling of this script. ## Dryrun Behaviour When `--dryrun` / `-n` is passed, no tmux session is created and nothing is sent. Output (values substituted): ``` [dryrun] Project: agent-runtimes (/home/paul/dev/claude/projects/agent-runtimes) [dryrun] Profile: oreillyit-anthropic (/home/paul/.claude-oreillyit-anthropic) [dryrun] Mode: deep [dryrun] Session name: Agent Runtimes [dryrun] Would run: tmux new-session -d -s "Agent Runtimes" -c "/home/paul/dev/claude/projects/agent-runtimes" [dryrun] Would send: claude-profile oreillyit-anthropic --mode deep --project agent-runtimes -- --remote-control Agent\ Runtimes [dryrun] Attach with: tmux attach -t "Agent Runtimes" ``` ## Edge Cases | Case | Handling | |------|----------| | No PROJECT and stdin is a TTY | Prompt `Project name:` | | No PROJECT and not a TTY (e.g. run by an agent) | Error: "No project given…", exit 1 | | Project folder not found | Error naming the searched locations, exit 1 | | Profile directory not found | Error, exit 1 | | Session name already taken | Auto-increment with ` #N` suffix | | Project name has underscores | Treated like hyphens for Title-Casing | | `claude-profile` not found | Error, exit 1 | | Two concurrent sessions on the same profile | Both work: `claude-profile` rewrites the shared `active-mode.env`, but each session's **cwd takes precedence** for project auto-selection, so the correct project is still picked | ## Examples ```bash # Spawn a Remote-Control session for agent-runtimes (Title-cased, mode from last-mode) $ claude-tmux agent-runtimes Spawned tmux session: Agent Runtimes attach: tmux attach -t "Agent Runtimes" # A second one auto-increments $ claude-tmux agent-runtimes Spawned tmux session: Agent Runtimes #2 # Override the mode, and attach immediately $ claude-tmux cluster-bootstrap --mode deep --attach # Preview only $ claude-tmux dns-manager --dryrun ```