Skip to main content

Multi-provider AI chatbot for the terminal

Project description

Inzen CLI Bot

PyPI Downloads PyPI Version Python Version

Building a Windows Executable & Installer

To create a standalone Windows EXE and one-click installer:

  1. Build the EXE:
  • Install PyInstaller: pip install pyinstaller
  • Run the build script: build_exe.bat
  • The EXE will appear in the dist/ folder.
  1. Create an Installer (optional):
  • Use Inno Setup or NSIS to package the EXE and any required files.
  • See installer.iss.example for a sample Inno Setup script (if present).

Note: The EXE includes Python and all dependencies—no Python install required for users.

Building Linux .deb and .rpm Packages

nfpm works cross-platform, so you can build Linux packages from Windows, macOS, or Linux without a VM.

1. Install nfpm (one-time)

Windows (PowerShell) — choose one:

# Scoop
scoop install nfpm

# Chocolatey
choco install nfpm

# winget
winget install GoReleaser.nfpm

# Direct download (no package manager required)
$tag = "v2.43.2"
$url = "https://github.com/goreleaser/nfpm/releases/download/$tag/nfpm_Windows_x86_64.zip"
Invoke-WebRequest $url -OutFile "$env:TEMP\nfpm.zip"
Expand-Archive "$env:TEMP\nfpm.zip" -DestinationPath "$env:LOCALAPPDATA\nfpm" -Force
$env:PATH += ";$env:LOCALAPPDATA\nfpm"  # add permanently via System Properties > Environment Variables

Linux / macOS:

# Homebrew
brew install nfpm

# Direct binary
curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh

2. Build the packages

Windows (PowerShell):

.\build_linux_packages.ps1

Linux / macOS:

./build_linux_packages.sh

This produces:

  • dist/linux/inzen-bot_<version>_<arch>.deb
  • dist/linux/inzen-bot_<version>_<arch>.rpm

The packages install the standalone binary under /opt/inzen-cli-bot/, expose both bot and inzen_cli_bot on the system PATH, include the project docs under /usr/share/doc/inzen-cli-bot/, and print a post-install reminder to run bot --setup.

On Git tags matching v*, GitHub Actions builds and attaches all release installers to the matching GitHub Release automatically:

  • Windows standalone EXE
  • Windows installer EXE
  • Linux .deb
  • Linux .rpm

Inzen CLI Bot one-shot response with token usage footer

No browser. No switching apps. Just ask and keep working.

Contents


Security & Secrets

  • Never commit real API keys or secrets. Only .env.example should be public.
  • The .gitignore excludes .env, .venv/, and build artifacts by default.


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 REPLbot --chat for a persistent conversation without re-typing flags
  • Token & cost tracking — per-message footer and a bot --usage summary 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?

Conversation history showing colour-coded USER and ASSISTANT turns

Common flags:

# Use a specific provider for one query
bot --provider openai explain RAID levels

# Run setup wizard again
bot --setup

# Update from latest GitHub release
bot --update

# Set local-provider endpoints without editing config.json
bot --set-ollama-url http://localhost:11434
bot --set-llamacpp-url http://localhost:8080

# 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

# Toggle insecure remote HTTP provider endpoints in config
bot --allow-insecure-http
bot --no-allow-insecure-http

# 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

bot --update checks the latest GitHub release and updates in place for Python installs, Linux .deb/.rpm package installs, and Windows installer-based installs.


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)

Interactive chat REPL showing multi-turn conversation and /help output


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.

Session list showing provider, message count, and preview

Session export to markdown


Token Usage

Every response includes a per-message token and cost footer. Run bot --usage to see cumulative totals across all providers:

Token usage summary across multiple 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.

Configured providers list with active provider marked

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/passwd are rejected at the CLI boundary.
  • Safe exports--output writes are restricted to allowed directories by default; use --unsafe-output to bypass for one command.
  • Secrets redaction — use --redact-secrets to mask common key/token patterns in --history and --export output.
  • Network guardrails — provider base_url values 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 --purge to 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 provider
  • openai — OpenAI and llama.cpp providers
  • rich — terminal rendering
  • click — 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

Current automated release flow

From v0.3.6 onward, releases are published through GitHub Actions and include:

  • PyPI package publish (inzen-bot)
  • Windows installer EXE
  • Linux .deb
  • Linux .rpm

The release pipeline validates that the Git tag version matches pyproject.toml before assets are published.

Recommended: one-click release (workflow dispatch)

Use the Cut Release workflow in GitHub Actions:

  1. Open ActionsCut Release.
  2. Click Run workflow on main.
  3. Choose release_type (patch, minor, or major).
  4. Optional: set version (for explicit version, e.g. 0.3.7).

What this workflow does automatically:

  1. Bumps version in pyproject.toml (and bump-my-version metadata).
  2. Runs release checks:
  • uv run pytest -v
  • uv run ruff check .
  • uv lock --check
  • uv run pip-audit
  1. Regenerates CHANGELOG.md with git-cliff.
  2. Commits release files to main.
  3. Creates and pushes tag vX.Y.Z.
  4. Triggers:
  • publish.yml to publish on PyPI
  • release-assets.yml to publish Windows/Linux assets

Manual fallback (if needed)

# 1) Bump version without auto-commit/tag
uv run bump-my-version bump patch --no-commit --no-tag

# 2) Regenerate changelog
uv run git-cliff --output CHANGELOG.md

# 3) Run release checks
uv run pytest -v
uv run ruff check .
uv lock --check
uv run pip-audit

# 4) Commit and tag
git add pyproject.toml uv.lock CHANGELOG.md
git commit -m "chore: bump version to <version>"
git tag -a v<version> -m "v<version>"

# 5) Push
git push origin main
git push origin v<version>

Required repository secret for publish:

  • PYPI_API_TOKEN

License

GPL-3.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

inzen_bot-0.3.7.tar.gz (51.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

inzen_bot-0.3.7-py3-none-any.whl (41.2 kB view details)

Uploaded Python 3

File details

Details for the file inzen_bot-0.3.7.tar.gz.

File metadata

  • Download URL: inzen_bot-0.3.7.tar.gz
  • Upload date:
  • Size: 51.7 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

Hashes for inzen_bot-0.3.7.tar.gz
Algorithm Hash digest
SHA256 ca23dd6be5b07840c8573c0fa65a2a1d0b262bafb9f36137e06b59d5fccb84ff
MD5 8482827a87b2887d445278a68f75bbde
BLAKE2b-256 aafc5facc0ff5d291270e719b322ad73480570bf0ca62dfc7c6a613f350b417f

See more details on using hashes here.

File details

Details for the file inzen_bot-0.3.7-py3-none-any.whl.

File metadata

  • Download URL: inzen_bot-0.3.7-py3-none-any.whl
  • Upload date:
  • Size: 41.2 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

Hashes for inzen_bot-0.3.7-py3-none-any.whl
Algorithm Hash digest
SHA256 f6a57d62305db0888c614f30edb97afb3eef66dc88b059ce87342b83d4abce85
MD5 74264903d0890ac829b27499e5a9a44a
BLAKE2b-256 df17ad95624e1d900d249a993bd5056285e180ad3874f35577b57f499371b18a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page