> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Conversation Hub — conversation continuity across channels

> One conversation that crosses channels: a topic started on Telegram/Slack/WhatsApp continues in the notebook chatcli, and vice-versa, until you start a new session.

The **Conversation Hub** carries a conversation **across channels**. A topic started on Telegram continues when you open chatcli on your notebook; what you answer in the notebook becomes context on Telegram/Slack/WhatsApp. Both sides stay in sync — without you repeating anything.

<Note>
  The hub is a **momentary bridge**, not long-term memory. It keeps the **current** conversation in sync across channels, with a **bounded** database (automatic pruning). Persistent memory across projects/sessions is still the [memory system](/context/bootstrap-memory) (`/memory`) and [`/session save`](/context/session-management).
</Note>

## How it works

* **Principal**: the shared conversation identity. In single-user mode (the default), the local CLI and the gateway collapse to the same principal (`default` if you set nothing), so everything shares **with zero configuration**.
* **`hub.db`**: an append-only SQLite log (`~/.chatcli/hub.db`). The CLI and the gateway daemon open the **same file** — that is how they understand each other across processes.
* **Ephemeral per session**: opening chatcli starts a **fresh** conversation and the previous one is **pruned** — the database never grows and you don't load a giant history. Conversations idle past the TTL (`CHATCLI_HUB_TTL_HOURS`, default 24h) are swept.
* **Silent**: turns from other channels enter the model's context **without being printed** in your prompt (no noise, no "press Enter to continue").
* **`/newsession`** resets the shared conversation for every channel.

It works in **chat**, **`/agent`** and **`/coder`**: the request and the final answer cross channels (tool-execution detail stays local on each machine).

## Modes

<Tabs>
  <Tab title="Local (same machine)">
    The simplest case — chatcli + gateway on one notebook, **zero configuration** (the default principal is enough):

    ```bash theme={"system"}
    export CHATCLI_TELEGRAM_BOT_TOKEN=123:abc
    chatcli                 # opens the REPL (enters local hub mode)
    # inside it:
    /gateway start          # starts the daemon, inheriting the environment
    ```

    Talk on the notebook, then pick up the topic on Telegram → it has the context. Send on Telegram with the prompt open → it enters the context of the notebook's next turn.

    <Note>Cross-process, the notebook picks up context **on its next turn** (there is no live push into an already-open prompt). For real time, use the co-located mode below.</Note>
  </Tab>

  <Tab title="Co-located in the server (real time)">
    Runs the gateway **inside the server process**, sharing the in-memory broker — so a Telegram message reaches the connected CLI in real time:

    ```bash theme={"system"}
    CHATCLI_TELEGRAM_BOT_TOKEN=123:abc \
    CHATCLI_GATEWAY_IN_SERVER=true \
    chatcli server --port 50051

    # on the notebook (same or another machine):
    chatcli connect localhost:50051
    ```
  </Tab>

  <Tab title="Multi-user / public bot">
    For a bot serving several people, **isolate** each identity and map who is who:

    ```bash theme={"system"}
    export CHATCLI_HUB_ISOLATE=true
    export CHATCLI_HUB_BINDINGS="telegram:111=alice;telegram:222=bob"
    ```

    With `isolate`, unbound senders each get their own conversation (one user never sees another's thread). Explicit bindings collapse specific identities into a named principal.
  </Tab>
</Tabs>

## Commands

```text theme={"system"}
/hub whoami                         # your principal and the active conversation
/hub bind telegram 123 alice        # bind a channel identity to a principal
/hub bindings [principal]           # list channel→principal bindings
```

Hub **settings** are mutable at runtime and persist in `hub.db` (read live by the gateway, no restart):

```text theme={"system"}
/config hub                         # panel: effective value + source (setting/env/default)
/config hub set principal alice
/config hub set isolate on
/config hub set ttl_hours 72
/config hub reset principal         # back to env/default
```

Resolution precedence: **setting (db) > environment variable > default**.

## Shared identity (single-user vs multi-user)

| Scenario | Configuration | Result |
| - | - | - |
| Just you (notebook + personal bot) | nothing (or `CHATCLI_HUB_PRINCIPAL=me`) | everything collapses to one principal → one shared conversation |
| Multi-user/public bot | `CHATCLI_HUB_ISOLATE=true` (+ bindings) | each identity isolated; bindings merge whoever you choose |

With isolation on, the gateway also gives each principal its **own store set** — saved sessions, long-term memory, knowledge contexts, the CCR archive, cost snapshots, the transcript journal and the live conversation — rooted at `~/.chatcli/tenants/<principal>/`. The set is installed for that sender's turn and the shared set restored afterwards, so `/session list` from one chat never shows another user's sessions and one user's facts never surface in another's turn. `CHATCLI_GATEWAY_MAX_TENANTS` (16) caps how many sets stay resident; the least recently used are released and rebuilt from disk on their next turn. Parked runs (`/park`, `/resume`) and task-graph runs follow the tenant root too, and `CHATCLI_DAILY_BUDGET_USD` caps each tenant's spend per calendar day on its own. Everything derived from one conversation swaps with the set too: the session-start memory card, the undo stack of `/rewind compact`, the last auto-recall trace, the external memory provider's forward watermark, staged inbound images and the last agent reply; the base memory worker keeps reading the base history while a tenant's turn runs, and the MCP `memory_recall` / `memory_store` calls of an external provider carry a `tenant` argument. What stays process-wide is listed under "Shared across tenants" in `/config security`: hooks, the MCP manager (servers and OAuth), the reflexion runner, the REPL history file, the hub database and the scheduler — plus the squad board and the tokenizer vocabulary cache (public data).

## Relationship to memory and sessions

| Mechanism | For | Persistence |
| - | - | - |
| **Conversation Hub** | cross-channel context of the **current** conversation | ephemeral/bounded (prune + TTL) |
| [Memory](/context/bootstrap-memory) (`/memory`) | long-term facts/learnings | permanent |
| [Sessions](/context/session-management) (`/session save` / `attach`) | explicit conversation snapshot — or, while attached, the **durable cross-surface record** every surface writes through to | JSON file |

The hub is an **additive parallel rail**: local history, `/session save` and memory keep working exactly as before. For durable continuity of one named conversation across REPL, IDE, MCP and gateway, see [Cross-surface continuity](/context/session-management#cross-surface-continuity) — the hub remains the real-time bridge for the *current* turn.

## Observability — the hub never dies silently

Continuity depends on the hub being up, so every state it can be in is **explicit in the log**:

* **Hub active**: the daemon logs `gateway: conversation hub active (principal=…, isolate=…, idle_ttl=…)` at boot; the CLI logs `local hub mode enabled`.
* **Hub disabled**: a `Warn` names **the exact source of the decision** — `db setting enabled=false`, `env CHATCLI_HUB_ENABLED=false` or `default` — instead of simply making continuity vanish.
* **Daemon serving without the hub** (database unreachable): a once-per-run warning makes it clear replies have no cross-channel context.

<Warning>
  The daemon inherits the environment of the shell that ran `/gateway start`, and `.env` does **not** override already-exported variables. A forgotten `CHATCLI_HUB_ENABLED=false` in the shell kills continuity even with a correct `.env` — the provenance log above exists precisely to catch that (`ps eww <pid>` confirms the process's real environment).
</Warning>

## See also

* [Agent Squad](/agents/agent-squad) — squad mail and the live run registry ride this same hub: `/agents` sees (and cancels) runs in other processes, and `/mail send` reaches agents running in the gateway daemon
* [Chat Gateway](/gateway/chat-gateway) — exposes ChatCLI on messaging channels
* [Remote Server (/connect)](/server/remote-connect) — connect the CLI to a remote hub
* [Environment Variables](/reference/environment-variables#conversation-hub-cross-channel-continuity)
* [Command Reference](/reference/command-reference)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.