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

# Local (Terminal) Channel

> Chat with your gateway agent from your own terminal — no tokens, no webhooks, no allowlist

The local channel lets you talk to your gateway agent from your own terminal — the same live session your Telegram or Discord users reach.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Local Terminal Channel"
        Stdin[⌨️ stdin] --> Local[💻 LocalBot]
        Local --> Session[🧠 Shared Session]
        Session --> Agent[🤖 Agent]
        Agent --> Session
        Session --> Stdout[📺 stdout]
        Session -.same session.-> Remote[📱 Telegram / Discord]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Stdin,Stdout input
    class Local,Session process
    class Agent agent
    class Remote output
```

## Quick Start

<Steps>
  <Step title="Chat in two lines">
    The local channel is owner-trusted — no token, no webhook, no setup.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent
    from praisonai_bot.bots import BotOS

    agent = Agent(name="assistant", instructions="Be helpful")
    BotOS(agent=agent, platforms=["local"]).run()
    ```
  </Step>

  <Step title="Custom prompt">
    Set your own input prompt in Python or `gateway.yaml`.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent
    from praisonai_bot.bots import BotOS

    agent = Agent(name="assistant", instructions="Be helpful")
    BotOS(agent=agent, platforms={"local": {"prompt": ">>> "}}).run()
    ```

    ```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # gateway.yaml
    channels:
      local:
        prompt: ">>> "
    ```
  </Step>

  <Step title="Terminal + remote in one process">
    One process, two surfaces, one shared session — chat locally while Telegram users reach the same agent.

    ```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # gateway.yaml
    channels:
      local: {}
      telegram: { token: "${TELEGRAM_BOT_TOKEN}" }
    agents:
      assistant:
        instructions: "You are a helpful assistant."
    ```

    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai-bot gateway start
    ```

    <Note>
      `channels: local: {}` is legal without a `token:`. The `local` channel is on the gateway's **token-free allowlist** (`email`, `agentmail`, `signal`, `local`), so it starts cleanly at launch **and** after a `gateway reload` — the config validator never marks it *degraded* for a missing token. See [Degraded Channel Isolation](/docs/features/gateway-degraded-channels).
    </Note>
  </Step>
</Steps>

***

## User Interaction

Type a line, get a reply. `Ctrl-D` exits cleanly; built-in commands start with `/`.

```
$ praisonai-bot gateway start
Local channel reading from stdin (Ctrl-D to exit; /stop cancels the current run)
you> hi
Hello! How can I help?
you> /status
Bot: assistant · channel: local · uptime: 12s · running
you> /new
Session reset. Send a message to start a new conversation.
you> ^D
Local channel stopped
$
```

The terminal also survives a config reload — a `gateway reload` keeps the `local` channel healthy instead of dropping it into a degraded state:

```
$ praisonai-bot gateway reload
INFO  Channel 'local' hot-reloaded (token-free)
you> still here?
Yes, still here.
```

***

## How It Works

Each line of stdin becomes one agent turn through the shared `BotSessionManager`, and the reply is written to stdout.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant LocalBot
    participant Session as Shared Session
    participant Agent

    User->>LocalBot: types a line (stdin)
    LocalBot->>Session: chat(local-operator, text)
    Session->>Agent: run turn
    Agent-->>Session: reply
    Session-->>LocalBot: response
    LocalBot-->>User: writes to stdout
    Note over LocalBot,Session: same session id is reachable<br/>as deliver="local:local"
```

The read loop runs on a dedicated daemon thread so other channels keep running while it waits for input.

### When does it exit?

| Signal         | Behaviour                                                     |
| -------------- | ------------------------------------------------------------- |
| `Ctrl-D` / EOF | Clean end of the terminal session                             |
| `/stop`        | Cancels the *current* agent run, keeps the read loop alive    |
| `/new`         | Resets the local session; next line starts a new conversation |
| Blank line     | Ignored                                                       |

***

## Built-in Commands

| Command   | Description                                           |
| --------- | ----------------------------------------------------- |
| `/status` | Show bot status and info (agent, uptime, running)     |
| `/new`    | Reset conversation session                            |
| `/help`   | Show the help message (including any custom commands) |
| `/stop`   | Cancel the current agent run                          |

***

## Configuration Options

The local channel is token-free and declares a single config field.

| Option   | Type  | Default   | Description           |
| -------- | ----- | --------- | --------------------- |
| `prompt` | `str` | `"you> "` | Terminal input prompt |

Constructor kwargs on `LocalBot`: `token=""` (unused, kept for parity), `agent`, `config`, `prompt`.

<CardGroup cols={2}>
  <Card icon="code" href="/docs/sdk/reference/python/classes/LocalBot">
    Python adapter class
  </Card>

  <Card icon="list" href="/docs/sdk/reference/python/classes/PlatformCapabilities">
    The capability flags a local channel declares
  </Card>
</CardGroup>

***

## Capabilities

The local channel declares a TTY-honest capability set so shared engines degrade correctly.

| Capability         | Value   | Why                                                                              |
| ------------------ | ------- | -------------------------------------------------------------------------------- |
| `supports_edit`    | `False` | A printed TTY line is not edited in place; streaming falls back to plain appends |
| `supports_typing`  | `False` | No "typing…" indicator in a terminal                                             |
| `needs_rate_limit` | `False` | No provider quota to respect                                                     |
| `accepts_webhooks` | `False` | Pull-based, not push                                                             |
| `supports_media`   | `False` | Text only                                                                        |

The channel's `system_prompt_hint` tells the agent about these constraints: *"You are replying in a local terminal: keep replies plain text; there is no markdown rendering, no message editing and no rate limit."*

<Card icon="sliders" href="/docs/features/bot-platform-capabilities">
  How capabilities drive uniform chunking, streaming, and rate limiting
</Card>

***

## Trust Model

The local operator is owner-trusted: it bypasses pairing and allowlists because it's your own machine — which is why no token is needed. Remote channels, by contrast, require pairing before a stranger can talk to your agent.

* `local` is on the gateway's **token-free allowlist** (`email`, `agentmail`, `signal`, `local`) — a `local` channel without a `token:` is fully healthy, **not** degraded, both at launch and after hot reload.

The terminal maps to a stable `local-operator` user id and `local` chat id, so it resolves to one durable session across restarts.

***

## Cross-Channel Continuity

A message begun in the terminal continues on a remote platform under one resolved session id via the shared identity resolver and delivery router.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Terminal as 💻 Terminal
    participant Resolver as 🧠 Identity Resolver
    participant Agent
    participant Telegram as 📱 Telegram

    Terminal->>Resolver: message (local-operator)
    Resolver->>Agent: resolved session id
    Agent-->>Telegram: reply on the same session
    Note over Resolver,Telegram: StoreBackedIdentityResolver +<br/>DeliveryRouter unify both surfaces
```

<CardGroup cols={2}>
  <Card icon="link" href="/docs/features/gateway-session-continuity">
    Gateway Session Continuity
  </Card>

  <Card icon="arrow-left-right" href="/docs/features/cross-platform-mirror">
    Cross-Platform Mirror
  </Card>
</CardGroup>

### `deliver="local"` — routing outbound to the terminal

Any scheduled job, hook, or agent tool that emits `deliver="local:local"` writes to the terminal exactly like `deliver="telegram:12345"` writes to Telegram.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
await botos._delivery_router.deliver("local:local", "proactive-ping")
```

<CardGroup cols={2}>
  <Card icon="paper-plane" href="/docs/features/proactive-delivery">
    Proactive Delivery
  </Card>

  <Card icon="clock" href="/docs/features/scheduler-delivery">
    Scheduler Delivery
  </Card>
</CardGroup>

***

## Common Patterns

1. **Dev / smoke-test** a gateway agent before wiring any remote channel.
2. **Single-user personal agent** on your own box — no bot registration.
3. **Start-here, continue-there** — chat locally at your desk, keep the same session going from your phone via Telegram.
4. **Proactive terminal notice** — a scheduled job that pings `deliver="local:local"` prints straight into the operator's terminal.

***

## Best Practices

<AccordionGroup>
  <Accordion title="Prefer gateway start for cross-channel continuity">
    `praisonai-bot gateway start` joins the gateway's live multiplexed session, identity resolver, and delivery router. `praisonai chat` runs a *separate* process with a *separate* session and does not.
  </Accordion>

  <Accordion title="Use /new to reset — not restart">
    Resetting the session is cheaper than restarting the process, and any other running channels stay live.
  </Accordion>

  <Accordion title="Keep replies plain text in local-only agents">
    A TTY has no markdown rendering. If you also serve remote channels from the same agent, the `system_prompt_hint` already tells the agent this.
  </Accordion>

  <Accordion title="Ctrl-D is the clean way to exit">
    The read loop is intentionally not supervised (`supervised_inbound = False`), so EOF ends cleanly and the process exits without a reconnect storm.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Gateway & Control Plane" icon="network-wired" href="/docs/gateway">
    The gateway the local channel joins
  </Card>

  <Card title="Channels Gateway" icon="comments" href="/docs/features/channels-gateway">
    Connect agents to every built-in channel
  </Card>

  <Card title="Multi-Channel Bots" icon="users" href="/docs/features/multi-channel-bots">
    Run local + remote channels together
  </Card>

  <Card title="Bot Chat Commands" icon="terminal" href="/docs/features/bot-commands">
    `/status`, `/new`, `/help`, `/stop`
  </Card>
</CardGroup>
