# Guides

## Upgrading

```bash
uv tool upgrade ccbot                # uv (recommended)
pipx upgrade ccbot                   # pipx
brew upgrade ccbot                   # Homebrew
```

## CLI Reference

```
ccbot                        # Start the bot
ccbot status                 # Show running state (no token needed)
ccbot doctor                 # Validate setup and diagnose issues
ccbot doctor --fix           # Auto-fix issues (install hook, kill orphans)
ccbot hook --install         # Install Claude Code hooks (7 event types)
ccbot hook --uninstall       # Remove all hooks
ccbot hook --status          # Check per-event hook installation status
ccbot --version              # Show version
ccbot -v                     # Run with debug logging
```

## Local Dev in tmux

Recommended local development model:

- Run ccbot in a dedicated control window `ccbot:__main__`.
- Keep agent windows in the same `ccbot` tmux session.
- Restart by sending Ctrl-C to the control pane.

Use the helper script:

```bash
./scripts/restart.sh start      # fresh start; creates ccbot:__main__ if missing
./scripts/restart.sh status     # show current command + last logs
./scripts/restart.sh restart    # sends Ctrl-C to control pane (supervisor restarts)
./scripts/restart.sh stop       # sends Ctrl-\ to control pane (supervisor exits)
```

Direct key behavior in the control pane (`ccbot:__main__`):

- `Ctrl-C`: restart ccbot.
- `Ctrl-\`: stop the local dev supervisor loop.

### Fresh Start Guide

If you are starting from scratch:

1. `cd /path/to/ccbot`
2. `./scripts/restart.sh start`
3. `tmux attach -t ccbot`
4. In another terminal (or another pane), open your agent windows in the same tmux session.

The `start` command creates the tmux session/window if they do not exist, so no manual tmux bootstrap is required.

## Configuration

All settings accept both CLI flags and environment variables. CLI flags take precedence. `TELEGRAM_BOT_TOKEN` is env-only for security (flags are visible in `ps`).

| Variable / Flag                                | Default           | Description                                          |
| ---------------------------------------------- | ----------------- | ---------------------------------------------------- |
| `TELEGRAM_BOT_TOKEN`                           | _(required)_      | Bot token from @BotFather (env only)                 |
| `ALLOWED_USERS` / `--allowed-users`            | _(required)_      | Comma-separated Telegram user IDs                    |
| `CCBOT_DIR` / `--config-dir`                   | `~/.ccbot`        | Config and state directory                           |
| `TMUX_SESSION_NAME` / `--tmux-session`         | `ccbot`           | tmux session name                                    |
| `CCBOT_PROVIDER` / `--provider`                | `claude`          | Default agent provider (`claude`, `codex`, `gemini`) |
| `CCBOT_<NAME>_COMMAND`                         | _(from provider)_ | Per-provider launch command (env only, see below)    |
| `CCBOT_GROUP_ID` / `--group-id`                | _(all groups)_    | Restrict to one Telegram group                       |
| `CCBOT_INSTANCE_NAME` / `--instance-name`      | hostname          | Display label for this instance                      |
| `CCBOT_LOG_LEVEL` / `--log-level`              | `INFO`            | Logging level (DEBUG, INFO, WARNING, ERROR)          |
| `MONITOR_POLL_INTERVAL` / `--monitor-interval` | `2.0`             | Seconds between transcript polls                     |
| `AUTOCLOSE_DONE_MINUTES` / `--autoclose-done`  | `30`              | Auto-close done topics after N minutes (0=off)       |
| `AUTOCLOSE_DEAD_MINUTES` / `--autoclose-dead`  | `10`              | Auto-close dead sessions after N minutes (0=off)     |

## Auto-Close Behavior

CCBot automatically closes Telegram topics when sessions end, reducing clutter:

- **Done topics** (`--autoclose-done`, default: 30 min) — When Claude finishes a task and the session completes normally, the topic auto-closes after 30 minutes.
- **Dead sessions** (`--autoclose-dead`, default: 10 min) — When a Claude process crashes or the tmux window is killed externally, the topic auto-closes after 10 minutes.

Set to `0` to disable:

```bash
ccbot --autoclose-done 0 --autoclose-dead 0
```

## Multi-Instance Setup

Run multiple ccbot instances on the same machine, each owning a different Telegram group. All instances can share a single bot token.

**Example: work + personal instances**

Instance 1 (`~/.ccbot-work/.env`):

```ini
TELEGRAM_BOT_TOKEN=same_token_for_both
ALLOWED_USERS=123456789
CCBOT_GROUP_ID=-1001111111111
CCBOT_INSTANCE_NAME=work
CCBOT_DIR=~/.ccbot-work
TMUX_SESSION_NAME=ccbot-work
```

Instance 2 (`~/.ccbot-personal/.env`):

```ini
TELEGRAM_BOT_TOKEN=same_token_for_both
ALLOWED_USERS=123456789
CCBOT_GROUP_ID=-1002222222222
CCBOT_INSTANCE_NAME=personal
CCBOT_DIR=~/.ccbot-personal
TMUX_SESSION_NAME=ccbot-personal
```

Run both:

```bash
CCBOT_DIR=~/.ccbot-work ccbot &
CCBOT_DIR=~/.ccbot-personal ccbot &
```

Each instance uses a separate tmux session, config directory, and state. When `CCBOT_GROUP_ID` is set, an instance silently ignores updates from other groups.

Without `CCBOT_GROUP_ID`, a single instance processes all groups (the default).

> To find your group's chat ID, add [@RawDataBot](https://t.me/RawDataBot) to the group — it replies with the chat ID (a negative number like `-1001234567890`).

## Creating Sessions from the Terminal

Besides creating sessions through Telegram topics, you can create tmux windows directly:

```bash
# Attach to the ccbot tmux session
tmux attach -t ccbot

# Create a new window for your project
tmux new-window -n myproject -c ~/Code/myproject

# Start any supported agent CLI
claude     # or: codex, gemini
```

The window must be in the ccbot tmux session (configurable via `TMUX_SESSION_NAME`). For Claude, the SessionStart hook registers it automatically. For Codex and Gemini, CCBot auto-detects the provider from the running process name. In both cases, the bot creates a matching Telegram topic.

This works even on a fresh instance with no existing topic bindings (cold-start).

## Session Recovery

When an agent session exits or crashes, the bot detects the dead window and offers recovery options via inline buttons:

- **Fresh** — Kill the old window, create a new one in the same directory
- **Continue** — Resume the last conversation (all providers support this)
- **Resume** — Browse and select a past session to resume from

The buttons shown adapt to each provider's capabilities. All three providers (Claude, Codex, Gemini) support Fresh, Continue, and Resume.

## Provider Support

CCBot supports multiple agent CLI backends. Each Telegram topic can use a different provider — you choose when creating a session via the directory browser.

### Supported Providers

| Provider    | CLI Command | Hook Events         | Status Detection                   |
| ----------- | ----------- | ------------------- | ---------------------------------- |
| Claude Code | `claude`    | Yes (7 event types) | Hook events + pyte VT100 + spinner |
| Codex CLI   | `codex`     | No                  | pyte VT100 interactive UI + transcript activity heuristic |
| Gemini CLI  | `gemini`    | No                  | Pane title + interactive UI        |

### Choosing a Provider

**From Telegram**: When you create a new topic and select a directory, a provider picker appears with Claude (default), Codex, and Gemini options.

**From the terminal**: If you create a tmux window manually and start an agent CLI, CCBot auto-detects the provider from the running process name.

**Default provider**: Set `CCBOT_PROVIDER=codex` (or `gemini`) to change the default. Claude is the default if unset.

### Provider Differences

**Claude Code** has the richest integration — 7 hook event types (SessionStart, Notification, Stop, SubagentStart, SubagentStop, TeammateIdle, TaskCompleted) provide instant session tracking, interactive UI detection, done/idle detection, subagent activity monitoring, and agent team notifications. The bot also uses a pyte VT100 screen buffer as fallback for terminal status parsing. Multi-pane windows (e.g. from agent teams) are automatically scanned for blocked panes and surfaced as inline keyboard alerts.

**Codex CLI** and **Gemini CLI** lack a session hook, so session tracking relies on auto-detection from running processes. Codex interactive prompts (question lists, permission prompts, and other selection UIs) are detected from terminal screen content via pyte and shown with inline keyboard controls. For edit-approval prompts, CCBot reformats dense terminal diffs into a compact summary with a short preview while keeping the Yes/No confirmation choices and bottom action hints intact. Gemini sets pane titles (`Working: ✦`, `Action Required: ✋`, `Ready: ◇`) that CCBot reads for status, and its `@inquirer/select` permission prompts are detected as interactive UI.

### Codex Edit Approval Formatting

When Codex asks for approval on file edits, terminal output can include dense side-by-side diff lines that are hard to read in Telegram. CCBot reformats that content before sending the interactive prompt:

- Keeps the approval controls and action hints intact (`Yes/No`, `Press enter`, `Esc`).
- Adds a compact summary (`File`, `Changes: +N -M`).
- Adds a short preview of parsed changed lines when available.
- Omits unreadable wrapped diff blobs instead of forwarding noisy raw text.

Typical output shape:

```text
Do you want to make this edit to src/ccbot/example.py?
File: src/ccbot/example.py
Changes: +1 -1
Preview:
  - return old_value
  + return new_value

› 1. Yes, proceed (y)
  2. Yes, and don't ask again for these files (a)
  3. No, and tell Codex what to do differently (esc)
Press enter to confirm or esc to cancel
```

### Custom Launch Commands

Override the CLI command used to launch each provider via `CCBOT_<NAME>_COMMAND` env vars:

```ini
CCBOT_CLAUDE_COMMAND=ce --current
CCBOT_CODEX_COMMAND=my-codex-wrapper
CCBOT_GEMINI_COMMAND=/opt/gemini/run
```

`<NAME>` is uppercase: `CLAUDE`, `CODEX`, `GEMINI`. Defaults to the provider's built-in command (`claude`, `codex`, `gemini`) when unset. New providers automatically support `CCBOT_<NAME>_COMMAND` without code changes.

### Provider-Specific Commands

Each provider exposes its own slash commands to the Telegram menu. Examples:

- **Claude**: `/clear`, `/compact`, `/cost`, `/doctor`, `/permissions`...
- **Codex**: `/model`, `/mode`, `/status`, `/diff`, `/compact`, `/mcp`...
- **Gemini**: `/chat`, `/clear`, `/compress`, `/model`, `/memory`, `/vim`...

For Codex, `/status` now sends a transcript-based fallback snapshot in Telegram
(session/cwd/token/rate-limit summary) because some Codex builds render status
in the terminal UI without emitting a transcript assistant message.

## Data Storage

All state files live in `$CCBOT_DIR` (`~/.ccbot/` by default):

| File                 | Description                                                 |
| -------------------- | ----------------------------------------------------------- |
| `state.json`         | Thread bindings, window states, display names, read offsets |
| `session_map.json`   | Hook-generated window → session mappings                    |
| `events.jsonl`       | Append-only hook event log (read incrementally by monitor)  |
| `monitor_state.json` | Byte offsets per session (prevents duplicate notifications) |

Session transcripts are read from provider-specific locations (read-only): `~/.claude/projects/` (Claude), `~/.codex/sessions/` (Codex), `~/.gemini/tmp/` (Gemini). The bot never writes to agent data directories.

## Running as a Service

For persistent operation, run ccbot as a systemd service or under a process manager:

```bash
# systemd user service (~/.config/systemd/user/ccbot.service)
[Unit]
Description=CCBot - Command & Control Bot for AI coding agents
After=network.target

[Service]
ExecStart=%h/.local/bin/ccbot
Restart=on-failure
RestartSec=5
Environment=CCBOT_DIR=%h/.ccbot

[Install]
WantedBy=default.target
```

```bash
systemctl --user enable ccbot
systemctl --user start ccbot
```

On macOS, you can use a launchd plist or simply run in a detached tmux session:

```bash
tmux new-session -d -s ccbot-daemon 'ccbot'
```
