Metadata-Version: 2.5
Name: botable-dev
Version: 0.3.2
Summary: Botable CLI: build, deploy and run Telegram bots from your terminal, Claude Code, Codex or Cursor
Project-URL: Homepage, https://botable.dev
Author-email: Botable Team <hello@botable.dev>
License-Expression: MIT
License-File: LICENSE
Keywords: ai,aiogram,bot,chatbot,cli,generator,telegram
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
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 :: Communications :: Chat
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: openai>=1.0
Requires-Dist: python-dotenv>=1.0
Requires-Dist: rich>=13.0
Requires-Dist: tomli-w>=1.0
Requires-Dist: tomli>=2.0; python_version < '3.11'
Requires-Dist: typer>=0.15
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.11; extra == 'dev'
Requires-Dist: twine>=6.0; extra == 'dev'
Requires-Dist: watchfiles>=1.0; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.0; extra == 'mcp'
Description-Content-Type: text/markdown

# ⚡ Botable CLI

> **Generate Telegram bots with AI — from idea to running bot in 3 minutes.**

[![PyPI](https://img.shields.io/pypi/v/botable-dev?color=blue)](https://pypi.org/project/botable-dev/)
[![Python](https://img.shields.io/pypi/pyversions/botable-dev)](https://pypi.org/project/botable-dev/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)

## Quick Start

```bash
pip install "botable-dev[mcp]"
botable login
botable mcp install

# Create a project
botable init my-bot
cd my-bot

# Add your keys to .env
echo "BOT_TOKEN=your-telegram-token" >> .env
echo "OPENAI_API_KEY=sk-..." >> .env

# Generate a bot from a description
botable generate "a FAQ bot for my restaurant with menu and hours"

# Run locally
botable dev
```

**That's it.** Your bot is running in under 3 minutes.

## Commands

### Local Development

| Command | Description |
|---------|-------------|
| `botable init [name]` | Scaffold a new bot project |
| `botable generate "description"` | Generate bot from natural language |
| `botable dev` | Run bot locally with live output |
| `botable dev --watch` | Run with hot reload on file changes |
| `botable version` | Show CLI version and effective API URL |

### Cloud Deployment

| Command | Description |
|---------|-------------|
| `botable login [--no-browser]` | Sign in through the browser |
| `botable login --api-key KEY [--api-url URL]` | Save an existing API key and API URL |
| `botable mcp install [--target claude\|codex\|cursor\|all] [--scope user\|project]` | Configure agent MCP clients |
| `botable logout` | Remove stored authentication |
| `botable deploy` | Deploy to Botable cloud |
| `botable logs [project_id]` | Show the current bot status snapshot |
| `botable bots list` | List all deployed bots |
| `botable bots stop {id}` | Stop a running bot |

## Deploy to Cloud

Cloud deployment is in **closed beta and requires an invitation** from the Botable team. Accounts without access receive an invitation message and a nonzero exit status; retrying or signing in again does not grant access.

```bash
botable login

# Deploy your bot
botable deploy

# Check status
botable bots list
botable logs
```

## Configuration

Botable uses a 3-layer config system:

| File | Scope | Purpose |
|------|-------|---------| 
| `botable.toml` | Project | Bot name, template, branding (committed to git) |
| `.env` | Project | Secrets: BOT_TOKEN, API keys (NOT committed) |
| `~/.config/botable/config.toml` | User | Global defaults, auth token |

`botable login --api-url URL` saves the API URL. `BOTABLE_API_URL` overrides it for the current process; otherwise the default is `https://api-staging.botable.dev` (staging, until the CLI routes reach production). Run `botable version` to see the effective URL.

## Use Botable from Claude Code / Codex

In Botable's **Code** tab, export your bot project. The export contains `botable.toml` with the project ID. Edit the files locally, then run `botable deploy` from that directory to deploy the same project. The CLI deployment routes currently work on staging, which is the default API URL:

```bash
botable login
botable mcp install
botable version
cd path/to/exported-bot
botable deploy
botable bots list
botable logs PROJECT_ID
```

**`botable deploy` uploads the project's `.env` file**, including any secrets in it. Check its contents before deployment. `botable logs` currently returns a status snapshot; runtime log lines and live streaming are not available through the CLI API yet.

`botable mcp install` defaults to `--target all`: it attempts Claude Code and writes Codex configuration, and configures Cursor only when `~/.cursor` exists (dangling directory symlinks are skipped). Use `--target cursor` to create Cursor configuration explicitly even if that directory is absent. Claude uses its `claude mcp add` command when installed; without Claude, `--scope project` writes project `.mcp.json` (the default user scope requires Claude). Codex configuration goes in `~/.codex/config.toml`, and Cursor configuration goes in `~/.cursor/mcp.json`. Empty or whitespace-only JSON is treated as an empty config, and UTF-8 BOMs are accepted. Invalid Cursor JSON is left untouched. Under `all`, invalid Cursor JSON and any Cursor filesystem error (read, directory creation, or write) produce a warning, succeeding if another client was configured; explicit `--target cursor` fails. Errors for other clients still fail the command, except unavailable clients under `all` when another client was configured.

After fully writing the temporary file and before replacing an existing config, the installer creates a unique timestamped `.bak` file beside its resolved target; project-scope Claude backups go in `~/.config/botable/` to keep them out of the bot repository. New files need no backup, and earlier backups are preserved. It writes atomically, preserving existing symlinks and file permissions. Cursor requires an installed `botable-mcp` executable so its config can use an absolute path; discovery checks PATH, the active Python's directory, and Python's regular and user scripts directories. Check with `claude mcp list`, `codex mcp list`, or Cursor Settings > Tools & MCP.

The MCP server exposes project creation, generation, templates, local development, deployment, bot listing, status, and the available status snapshot through its logs tool. Its former SSH staging status tool was removed because it requires operator access and is unrelated to customer bots. The MCP server uses the API URL and key saved by `botable login` (or the `BOTABLE_API_URL` environment override).

The MCP server instructions and deploy tool description require the agent to show the project name/id and upload filenames, compare against your bot list, confirm an existing bot update or new bot, explain the `.env` upload, and obtain an explicit yes before deployment. They also prohibit printing secrets. These instructions remain available when the agent restarts.

### Branding

Every generated bot includes a `# Built with Botable` comment. Customize or disable it:

```toml
# In botable.toml (per-project)
[branding]
enabled = true
text = "Built with Botable (botable.dev)"
style = "comment"  # "comment" | "docstring" | "none"
```

To disable globally:

```toml
# In ~/.config/botable/config.toml
[branding]
enabled = false
```

## How It Works

1. **`botable init`** — creates project structure with `botable.toml` + `.env`
2. **`botable generate`** — calls OpenAI to generate aiogram bot code, validates syntax, writes `main.py` + `requirements.txt`
3. **`botable dev`** — creates a venv, installs deps, runs your bot with live output
4. **`botable deploy`** — packages project, uploads to Botable cloud, deploys automatically

Generated bots use [aiogram](https://docs.aiogram.dev/) (MIT license) — async-native, production-ready.

## Development

```bash
git clone https://github.com/Botable-dev/cli.git
cd cli
pip install -e ".[dev]"
pytest
```

## License

MIT — see [LICENSE](LICENSE) for details.

---

⚡ Built with [Botable](https://botable.dev)
