Metadata-Version: 2.4
Name: bantubyte
Version: 1.2.6
Summary: AI-powered coding assistant CLI — powered by Kimi K2.6 via the BantuByte platform (more models coming)
Project-URL: Homepage, https://bantubyte.dev
Project-URL: Documentation, https://docs.bantubyte.dev
Project-URL: Repository, https://gitlab.com/pilartes/bantubyte
Project-URL: Issues, https://gitlab.com/pilartes/bantubyte/-/issues
Author-email: BantuByte <support@bantubyte.dev>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: bashlex<1,>=0.18
Requires-Dist: click<9,>=8.1
Requires-Dist: httpx[http2]<1,>=0.27
Requires-Dist: jsonschema<5,>=4.20
Requires-Dist: pathspec<2,>=1.0
Requires-Dist: pillow<13,>=12.2.0
Requires-Dist: prompt-toolkit<4,>=3.0
Requires-Dist: psutil<8,>=5.9
Requires-Dist: pydantic<3,>=2.0
Requires-Dist: pymupdf<2,>=1.26.7
Requires-Dist: rich<14,>=13.0
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# BantuByte CLI

AI-powered coding assistant CLI, currently powered by **Kimi K2.6** via the
BantuByte backend (the model layer is provider-pluggable — more models will be
selectable in future releases).  Comparable in scope and surface to Claude Code
and Aider — streaming chat, file editing, shell execution, sub-agents, and
dynamic [Model Context Protocol (MCP)](https://modelcontextprotocol.io)
integration so the model can talk to filesystems, databases, and anything else
the community ships an MCP server for.

---

## Quick start

### 1. Install

```bash
pip install bantubyte
```

For an editable / development install from a clone:

```bash
git clone https://gitlab.com/pilartes/bantubyte
cd bantubyte-cli
pip install -e .
```

### 2. Authenticate

```bash
bantubyte login
```

This opens your browser, runs the OAuth2 PKCE flow, and stores the
resulting tokens at `~/.bantubyte/auth.json` with permission `0600`
(owner-only) on POSIX.  The CLI refreshes tokens automatically before
they expire.

### 3. Start chatting

```bash
bantubyte                       # interactive REPL
bantubyte --resume              # pick a previous session from a list
bantubyte --resume <session-id> # resume a specific session
```

The REPL accepts:
- Plain text — sent to the model as a user message.
- `/<command>` — a slash command (see below).
- Multi-line input via Esc-Enter (single Enter submits when there's no newline yet).

---

## Slash commands

| Command | Description |
|---|---|
| `/help` | List all commands. |
| `/clear` | Start a fresh session in the same REPL. |
| `/exit`, `/quit` | Exit the REPL cleanly. |
| `/login`, `/logout` | Re-auth or revoke credentials. |
| `/config` | Browse and edit `~/.bantubyte/config.json`. |
| `/model` | Switch between Kimi and Moonshot models. |
| `/theme` | Switch between dark and light themes. |
| `/permissions` | Edit per-tool allow/deny lists for the project. |
| `/session` | Browse, resume, or delete past sessions. |
| `/usage` | Token usage + monthly quota for your plan. |
| `/cost` | Estimated cost for the current session. |
| `/compact` | Force a context compaction pass. |
| `/mcp ...` | Manage MCP servers — see the next section. |

---

## MCP — Model Context Protocol integration

MCP lets you plug external tool servers into the CLI without modifying
bantubyte itself.  The community publishes servers for filesystems,
git, postgres, sqlite, GitHub, Puppeteer, Slack, and many more — see
the [official catalogue](https://github.com/modelcontextprotocol/servers).

### Configuring servers

Create `~/.bantubyte/mcp.json` with an `mcpServers` map.  Each entry
declares how to spawn one server and how long bantubyte should wait
for it.

```jsonc
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "${HOME}/Projects"
      ],
      "timeout_ms": 15000,
      "tool_timeout_ms": 60000
    },

    "time": {
      "command": "uvx",
      "args": ["mcp-server-time"]
    },

    "postgres": {
      "command": "uvx",
      "args": ["mcp-server-postgres", "--dsn", "${DATABASE_URL}"],
      "env": {
        "PGCLIENTENCODING": "UTF8"
      }
    },

    "experimental-disabled": {
      "command": "uvx",
      "args": ["some-experimental-server"],
      "enabled": false
    }
  }
}
```

Field reference:

| Field | Default | Notes |
|---|---|---|
| `command` | required | Executable name (resolved via `PATH`, including `.cmd`/`.bat` on Windows) or absolute path. |
| `args` | `[]` | Arguments passed to `command`. |
| `env` | `{}` | Extra env vars merged on top of the CLI's environment. |
| `enabled` | `true` | Set to `false` to skip this server at startup. |
| `timeout_ms` | `10000` | Handshake + `tools/list` timeout (max 120 s). |
| `tool_timeout_ms` | `1800000` (30 min) | Per-call timeout for `tools/call`. Range: 1 s – 4 h. |

`${VAR}` expansion is supported in `command`, `args`, and `env` values
with the syntax `${VAR}` (errors if unset) and `${VAR:-default}` (uses
the default when unset).

### Project-scoped overrides

Drop a `.bantubyte/mcp.json` in any project directory.  The CLI walks
up from the current directory looking for one and merges it on top of
the global config.  The walk stops at:
- the user's home directory (so the global config never gets re-read),
- a `.git` boundary (so unrelated parent projects are ignored),
- the filesystem root.

Project entries override global entries with the same server name.

### Managing servers from the REPL

```text
/mcp                          # alias for /mcp list
/mcp list                     # show every server with status, version, tool count
/mcp info <name>              # full detail: instructions, timeouts, tool list
/mcp logs <name>              # last 64 KB of stderr from that server
/mcp reload                   # re-read mcp.json and restart everything
/mcp enable <name>            # set enabled=true and reload
/mcp disable <name>           # set enabled=false and reload
/mcp prompts [server]         # list prompt templates
/mcp prompt <server> <name> [key=value ...]
                              # render a prompt and submit it as your next message
```

Two global helper tools are also published whenever at least one MCP
server is healthy:

- `mcp__list_resources` — list resources from one or all servers.
- `mcp__read_resource`  — fetch the content of a single resource by URI.

### Resilience

The MCP subsystem is built to keep the REPL alive through normal
breakage:

- **Auto-reconnect** — when a server's subprocess crashes mid-session,
  the registry classifies the error and either reconnects (transient
  errors: ECONNRESET, EPIPE, EOF, …) with exponential backoff
  (1s → 2s → 4s → 8s → 16s, capped at 30s, 5 attempts max) or marks
  the server `degraded` (fatal errors: command not found, permission
  denied, protocol violations).
- **Graceful shutdown ladder** — stdin close → SIGINT/CTRL_BREAK_EVENT
  → SIGTERM → SIGKILL, with sub-second waits between each.  No stuck
  subprocesses on `/exit`.
- **Cancel propagation** — Ctrl-C on a long tool call sends
  `notifications/cancelled` so the server can stop work instead of
  burning CPU after the result is no longer needed.
- **Tool list change notifications** — when a server's catalogue
  changes, bantubyte re-publishes the tools to the model atomically
  (no window where the old tool still exists alongside the new one).
- **Connection batching** — at most 3 servers are spawned in parallel
  during startup/reload to avoid fork/exec contention.
- **Large output spillover** — tool results above 50 000 chars are
  written to `~/.bantubyte/mcp_outputs/<YYYY-MM-DD>/` and replaced
  with a 2 KB preview + filepath, so long queries never blow past
  the model's context window.
- **Unicode sanitisation** — every tool description and server
  instruction is run through an NFKC + dangerous-codepoint filter
  (defends against the Unicode Tag attack reported in HackerOne
  #3086545).

---

## Configuration

Settings live in three places, with `env > project > user > defaults`
precedence:

| Layer | File | Purpose |
|---|---|---|
| Defaults | code | Hardcoded sensible defaults. |
| User | `~/.bantubyte/config.json` | Per-user preferences (theme, model, etc.). |
| Project | `<cwd>/.bantubyte/config.json` | Project-scoped tool allow/deny lists. |
| Env | `BANTUBYTE_*` env vars | Override at process start. |

Notable env vars:

- `BANTUBYTE_API_URL` — backend URL (default `https://bantubyte.dev`).
- `BANTUBYTE_MODEL` — override the default model.
- `BANTUBYTE_VERBOSE=1` — enable debug-level logging to file.
- `BANTUBYTE_TOOL_PERMISSION_MODE` — one of `default`, `auto-allow`,
  `always-ask`.
- `BANTUBYTE_CONFIG_DIR` — override `~/.bantubyte/`.

### Local development against the dockerised backend

The `docker-compose.yml` at the repo root uses shifted host ports to
avoid clashing with other projects:

| Service  | Host port | Container port |
|----------|-----------|----------------|
| postgres | `15432`   | `5432`         |
| redis    | `16379`   | `6379`         |
| backend  | `18000`   | `8000`         |
| nginx    | `18080`   | `80`           |
| nginx    | `18443`   | `443`          |

To point the CLI at the local backend (skipping nginx):

```bash
export BANTUBYTE_API_URL=http://localhost:18000
bantubyte login
```

Or persist it once:

```json
// ~/.bantubyte/config.json
{ "api_base_url": "http://localhost:18000" }
```

To go through nginx (closer to production routing) use
`http://localhost:18080` instead.

---

## Sessions

Every conversation is a session, persisted as JSONL at
`~/.bantubyte/sessions/<id>.jsonl`.  Resume with `bantubyte --resume`
to pick from a list, or `bantubyte --resume <id>` to jump directly.

Session corruption (one bad line, truncated tail, manually edited
file) does not break load — the CLI logs every dropped entry and
continues with the recovered messages.  The `/session` command and
the resume picker mark damaged sessions with a `⚠` glyph and the
``corruption_warning`` so you can decide whether to keep using them.

A session file is hard-capped at 50 MB; once reached, further writes
are refused and the user is prompted to start a fresh session with
`/clear`.  Crash markers under `~/.bantubyte/sessions/` track which
sessions did not exit cleanly so the next launch can offer to resume
them.

---

## Logs and storage

```
~/.bantubyte/
├── config.json            # user-level settings
├── auth.json              # OAuth tokens (chmod 0600 on POSIX)
├── mcp.json               # MCP server declarations
├── sessions/              # JSONL transcripts, one per session
│   └── <session-id>.jsonl
├── mcp_outputs/           # spilled MCP tool results (>50 KB)
│   └── <YYYY-MM-DD>/
├── logs/                  # rotating debug logs
│   └── bantubyte.log
├── history                # REPL input history
└── background/            # SQLite registry for background tools
```

Every directory is created lazily with restrictive permissions
(`0700` on POSIX; on Windows the user-profile ACLs are inherited).

---

## Troubleshooting

### Authentication

> `Not authenticated. Run 'bantubyte login' first.`

Your token expired or was never created.  Run `bantubyte login`.  If
the browser does not open, copy the URL printed in the terminal.

### MCP server stuck on "reconnecting"

Run `/mcp logs <name>` to see the server's stderr.  Common causes:
- Missing argument (the server printed a usage error and exited).
- Wrong command path on Windows — bantubyte resolves `.cmd`/`.bat`
  via `PATHEXT`, but custom shells may need an absolute path.
- Server's own dependency download timed out — bump `timeout_ms` to
  60000 or more.

### MCP server marked "degraded" with "missing environment variable"

The expansion of a `${VAR}` placeholder failed.  Either set the
variable in your shell before launching bantubyte, or supply a
default with `${VAR:-fallback}` syntax in `mcp.json`.

### "Resumed session has minor corruption"

A previous run wrote a partial JSONL line (usually due to a process
crash mid-write).  The CLI dropped the bad lines and recovered the
rest.  The session is still usable; the ``/session`` listing shows
`⚠` next to damaged sessions.

### Where are the logs?

`~/.bantubyte/logs/bantubyte.log` — rotated daily.  Set
`BANTUBYTE_VERBOSE=1` for `DEBUG` granularity.

---

## Compatibility

- **Python**: 3.10 – 3.13.
- **OS**: macOS, Linux, Windows.
- **MCP transports** (v1): stdio.  HTTP / SSE / WebSocket are planned
  for v2.

---

## License

MIT.
