Bantam icon

bantam

tiny, powerful, DIY AI agent

Bantam is a minimalist, dependency-light AI agent. It gives an LLM an agentic loop and exactly three tools - and that is enough to handle tasks of any complexity. Named after the Victorinox Bantam Alox, a small, lightweight Swiss army knife.

What it is

bash

Run shell commands. Anything the OS can do is one call away.

read

Inspect files and directories, paged with offset and limit.

write

Overwrite, append, replace exact text, or splice by line or byte.

Three tools, an agentic loop, and any OpenAI-compatible /chat/completions API.

  • Lean: only libcurl (HTTP) and GNU readline (line editing) - JSON parsing and Markdown rendering are implemented natively, no extra libraries.
  • Portable: modern C++20, builds on Linux, FreeBSD, macOS and Haiku with any POSIX make and a C++20 compiler.
  • Reimplementable: a plain algorithm description lets anyone rebuild it from scratch.
  • Resilient: Fibonacci backoff (1,1,2,3,5,8,13,21,34) on network and 5xx errors.
  • Streaming: real-time SSE reasoning and output, markdown + box-drawing tables to terminal width.
  • Sessionful: autosaved conversations, summaries, and one-command compaction.
  • Safe by default: tool args and results are sanitized against indirect prompt injection; file content is written verbatim (CRLF, BOM and Unicode preserved).

Get Bantam

  • Get the C++ version: git clone https://code.luxferre.top/luxferre/bantam-cpp
  • Build and install it: cd bantam-cpp && make && sudo make install
  • Configure .bantam.cfg with your endpoint, model and API key.
endpoint=https://api.kilo.ai/api/openrouter
model=openrouter/free
temperature=0.7
stream=true
reasoning_effort=high

C++20libcurlGNU readlineDependency-light: standard library plus two system libraries.


The loop, in one breath

prompt -> append message -> call API -> stream reasoning
       -> tool_calls? execute bash | read | write
          -> append tool result -> loop
       -> done: report tokens, offer compaction

On every turn Bantam prints token usage and context utilization:

[openrouter/free: 1420 prompt (1000 cached, 420 uncached) + 85 completion | context: 1420/200000 (0.7%)]

Editing files

The write tool has one unambiguous job per call. With just filePath and content it overwrites the whole file exactly; for a selective edit you pick exactly one mode:

{"filePath":"f", "content":"new text", "find":"old text"}
{"filePath":"f", "content":"last line", "append":true}
{"filePath":"f", "content":"replacement", "lineOffset":3, "delLines":1}
{"filePath":"f", "content":"X", "byteOffset":2, "delBytes":1}

find replaces a unique exact snippet with no line numbers at all - the recommended way to change an existing line. To replace a line by number you must set delLines:1; omitting it inserts a new line and keeps the original. The tool reports what happened in line numbers and adds a hint when an insertion looks like a duplicate. Mixing modes, a lineOffset of 0, or a deletion without a position is an instructive error, never a silent surprise.


Slash commands

  • /continue - resume this project's autosaved session
  • /save [name] / /list / /load <id> - save, browse and load sessions
  • /clear - reset the conversation
  • /compact - summarize and shrink the context
  • /cfg / /model / /endpoint - tweak config live
  • /skill - load a skill, /models - list available models
  • !<cmd> - run a shell command without touching context
  • /help - list commands, /quit - exit

Credits