Multi-provider AI chatbot for the terminal
Project description
Inzen CLI Bot
Building a Windows Executable & Installer
To create a standalone Windows EXE and one-click installer:
- Build the EXE:
- Install PyInstaller:
pip install pyinstaller - Run the build script:
build_exe.bat - The EXE will appear in the
dist/folder.
- Create an Installer (optional):
- Use Inno Setup or NSIS to package the EXE and any required files.
- See
installer.iss.examplefor a sample Inno Setup script (if present).
Note: The EXE includes Python and all dependencies—no Python install required for users.
No browser. No switching apps. Just ask and keep working.
Contents
Security & Secrets
- Never commit real API keys or secrets. Only
.env.exampleshould be public. - The
.gitignoreexcludes.env,.venv/, and build artifacts by default.
- Install
- Setup
- Usage
- Interactive Mode
- Named Sessions
- Token Usage
- Providers
- Configuration
- Security
- Requirements
- Contributing
- Releasing to PyPI
Features
Code Style
- Use ruff for linting:
uv run ruff check . - Use black for formatting:
uv run black . - Add type hints to all functions.
- Named sessions — keep separate threads for different projects, all stored locally
- Interactive REPL —
bot --chatfor a persistent conversation without re-typing flags - Token & cost tracking — per-message footer and a
bot --usagesummary table across all providers - Session export — dump any session to markdown or plain text
- Secure by default — local data files are user-only (600/700), session names are validated against path traversal
Install
pip install inzen-bot
Or with uv:
uv add inzen-bot
Setup
1. Run interactive setup (recommended)
bot --setup
This wizard will:
- Ask which providers you want to use
- Ask for model/base URL where needed
- Store API keys securely in your OS keyring (when available)
- Save provider settings to
~/.bot/config.json
2. Or set API keys manually
Inzen CLI Bot reads your API keys from environment variables.
Linux / macOS — add to your ~/.bashrc or ~/.zshrc:
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..." # optional
Then reload:
source ~/.bashrc
Windows (PowerShell) — set permanently:
[System.Environment]::SetEnvironmentVariable("ANTHROPIC_API_KEY", "sk-ant-...", "User")
Restart your terminal after running this.
For Ollama and llama.cpp no API key is needed — just make sure the local server is running before use.
2. Verify it works
bot hello
You should see a streamed response from Claude with a token usage footer. If you get an error, check your API key:
# Linux / macOS
echo $ANTHROPIC_API_KEY
# Windows PowerShell
echo $env:ANTHROPIC_API_KEY
Usage
Ask anything — history is automatic so you can follow up naturally:
bot how do I format a drive in Ubuntu?
bot step 2?
bot step 3?
Common flags:
# Use a specific provider for one query
bot --provider openai explain RAID levels
# Run setup wizard again
bot --setup
# See API key status (keyring/env)
bot --credentials-list
# Update or remove a stored API key
bot --credentials-update anthropic
bot --credentials-remove anthropic
# Switch default provider permanently
bot --set-provider ollama
# Switch model
bot --set-model claude-opus-4-5
# View conversation history
bot --history
# Purge data older than the configured retention window
bot --purge
# Clear history
bot --clear
# List all configured providers
bot --providers
# Override the system prompt for one query
bot --system "You are a Python expert" explain decorators
# Redact likely secrets in history/export output
bot --history --redact-secrets
# Export outside safe directories (disabled by default for safety)
bot --export myproject --output /tmp/myproject.md --unsafe-output
Interactive Mode
Use --chat for a persistent REPL — no need to retype flags between messages.
# Start a persistent chat session
bot --chat
# Start with an opening message, then continue the conversation
bot --chat explain how systemd services work
# Use a named session in interactive mode
bot --session myproject --chat
Inside the chat session the following slash commands are available:
| Command | Description |
|---|---|
/help |
Show available commands |
/history |
Print the conversation so far |
/clear |
Clear conversation history for this session |
/exit |
Exit chat mode (also: /quit, q) |
Named Sessions
Named sessions let you maintain separate, persistent conversation threads — useful for keeping different projects or topics isolated.
# Start or continue a named session
bot --session myproject what is a venv
# Pick up where you left off
bot --session myproject how do I activate it
# List all saved sessions
bot --sessions
# Export a session to markdown
bot --export myproject
# Export to a file
bot --export myproject --output myproject.md
# Delete a session
bot --clear-session myproject
Sessions are stored as JSON files in ~/.bot/sessions/ and are independent of provider — you can switch providers mid-session.
Token Usage
Every response includes a per-message token and cost footer. Run bot --usage to see cumulative totals across all providers:
# View cumulative usage across all providers
bot --usage
Providers
| Provider | Requires | Notes |
|---|---|---|
anthropic |
ANTHROPIC_API_KEY |
Default. Claude models. |
openai |
OPENAI_API_KEY |
GPT models. Also works for Groq, Together, etc. |
ollama |
Ollama running | Local inference. Free to run. |
llamacpp |
llama.cpp running | Local inference via OpenAI-compatible server. |
Ollama quickstart
# Install from https://ollama.ai, then:
ollama pull llama3
ollama serve
bot --set-provider ollama
bot hello from the terminal
llama.cpp quickstart
# Build llama.cpp from https://github.com/ggerganov/llama.cpp, then run the server:
./server -m your-model.gguf --port 8080
bot --set-provider llamacpp
bot what is quantisation
Using Groq or other OpenAI-compatible APIs
Point the OpenAI provider at any compatible endpoint via ~/.bot/config.json:
{
"providers": {
"groq": {
"model": "llama-3.3-70b-versatile",
"api_key_env": "GROQ_API_KEY",
"base_url": "https://api.groq.com/openai/v1"
}
}
}
Configuration
Config and history live in ~/.bot/, with user-only file permissions on Linux and macOS:
~/.bot/ (chmod 700)
├── config.json (chmod 600) — provider settings and defaults
├── history_anthropic.json (chmod 600) — conversation history per provider
├── history_openai.json (chmod 600)
├── history_ollama.json (chmod 600)
├── usage_anthropic.json (chmod 600) — cumulative token/cost data
└── sessions/ (chmod 700)
└── myproject.json (chmod 600)
History is capped at 50 message pairs per provider. You can edit ~/.bot/config.json directly to customise models, add providers, or set custom base URLs.
Security-related defaults in config.json:
{
"security": {
"safe_output": true,
"redact_secrets": false,
"warn_dangerous_commands": true,
"allowed_export_dirs": ["."],
"allowed_hosts": [],
"allow_insecure_http": false,
"request_timeout_seconds": 30,
"max_retries": 2,
"retention_days": 30
}
}
Security
- File permissions —
~/.bot/and all data files are created with user-only permissions (700/600) on Linux and macOS so other users on the same machine cannot read your history, API keys, or session data. - Session name validation — session names are validated against a strict allowlist (letters, numbers,
.,_,-) to prevent path traversal attacks. Names like../etc/passwdare rejected at the CLI boundary. - Safe exports —
--outputwrites are restricted to allowed directories by default; use--unsafe-outputto bypass for one command. - Secrets redaction — use
--redact-secretsto mask common key/token patterns in--historyand--exportoutput. - Network guardrails — provider
base_urlvalues are validated (https by default for non-local hosts), with configurable host allowlists, timeouts, and retry limits. - Outbound warning guardrail — bot warns before printing responses that appear to contain dangerous shell command suggestions.
- Retention controls — use
--purgeto delete history, usage, and session files older than the configured retention window. - Security log — export, clear, purge, and config changes are recorded in a local redacted JSONL audit log at
~/.bot/security.log. - Security policy — see SECURITY.md for reporting guidance and supported-version details.
- Threat model — see THREAT_MODEL.md for threat boundaries, mitigations, and residual risks.
- API keys — keys are never written to disk; they are read only from environment variables at runtime.
Requirements
- Python 3.12+
anthropic— Anthropic/Claude provideropenai— OpenAI and llama.cpp providersrich— terminal renderingclick— CLI framework
Cross-platform
Works on Linux, macOS, and Windows. Config and history paths resolve correctly on all platforms via Path.home(). File permission hardening applies on Unix only; Windows uses its own ACL-based access controls.
Built by
Inzen — AI consulting and LLM application development.
Contributing
git clone https://github.com/benwalkerai/bot
cd bot
uv sync --group dev
uv run pytest # run tests
uv run ruff check . # lint
CI runs automatically on every push and pull request via GitHub Actions — tests and ruff must pass before merging.
Releasing to PyPI
-
Update the changelog from conventional commits:
uv run git-cliff --output CHANGELOG.md git add CHANGELOG.md git commit -m "docs: update changelog"
-
Bump the version — updates
pyproject.toml, creates a commit, and tags it automatically:# patch: 0.2.1 → 0.2.2 | minor: 0.2.1 → 0.3.0 | major: 0.2.1 → 1.0.0 uv run bump-my-version bump patch
-
Push the commit and tag — the tag triggers the PyPI publish workflow:
git push && git push --tags
The publish.yml GitHub Actions workflow runs the tests, builds the package, and publishes to PyPI automatically via the PYPI_API_TOKEN secret.
License
GPL-3.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inzen_bot-0.3.3.tar.gz.
File metadata
- Download URL: inzen_bot-0.3.3.tar.gz
- Upload date:
- Size: 45.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a1fe4c0e9cd5e43cd12af02b26d74a3c363660524b642d1350bff2acd55243b
|
|
| MD5 |
654a8c8388e7f3c4e39c4531560e5c63
|
|
| BLAKE2b-256 |
706012ae343375e4ac324d1e14f7b549ae31f280f315c5d2b381736fe74268a6
|
File details
Details for the file inzen_bot-0.3.3-py3-none-any.whl.
File metadata
- Download URL: inzen_bot-0.3.3-py3-none-any.whl
- Upload date:
- Size: 36.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab96b58fc6c518d0fd16367cf5f27a2ff953eef3775ad2932ebb8ba58dbd851c
|
|
| MD5 |
69830364b3055a8252228b455894686c
|
|
| BLAKE2b-256 |
a8a6e9321d3071933da18334ffbd9e7e9a54c5352899d102f5f941839a92a12f
|