A bash-native AI agent that builds its own toolkit
Project description
Binsmith
An AI agent that works by running shell commands and writing scripts. Tools it creates persist across sessions.
The idea
Most AI agents are stateless. They solve problems, then forget everything. Binsmith takes a different approach: when it does something useful, it writes a script. That script goes into a persistent toolkit.
Ask Binsmith to fetch a webpage, and it writes fetch-url. Ask it to convert
HTML to markdown, and it writes html2md. A week later, when you ask for
a daily briefing, it composes them:
$ brief
# News
- AI lab announces new model...
- Tech company acquires startup...
# Weather
San Francisco: 62°F, partly cloudy
# Your todos
- [ ] Review PR #42
- [ ] Write README improvements
That brief command didn't exist until you needed it. Now it does, and it
builds on tools that already existed.
Binsmith uses a server/client architecture. The TUI runs with an in-process server by default, or can connect to a standalone server. The web UI connects to a standalone server.
Requirements
- uv — used both to run Binsmith and by the scripts it creates
- Python 3.14+ (uv will install this automatically)
- An API key for at least one LLM provider (Gemini, Anthropic, or OpenAI)
Quick start
uvx binsmith
Or clone and run locally:
uv sync
binsmith
This starts the TUI, which runs a local in-process server by default.
Set GEMINI_API_KEY for the default model (Gemini Flash), or ANTHROPIC_API_KEY
/ OPENAI_API_KEY for alternatives. See Models.
CLI
binsmith # Run the TUI (default)
binsmith tui # Run the TUI explicitly
binsmith server # Run the API server
binsmith tui
--server <url> Connect to a running Binsmith server (default: $BINSMITH_SERVER_URL)
--allow-cross-project Allow connecting to a localhost server from a different project
binsmith server
--host <host> Host interface to bind (default: 127.0.0.1)
--port <port> Port to bind (default: 8000)
--reload Enable auto-reload
--workspace Workspace mode: local | central
What the agent builds
After a few days of use, a toolkit might look like:
~/.binsmith/workspace/bin/
fetch-url # Fetch a URL, handle retries, extract text
html2md # Convert HTML to clean markdown
news # Top stories from news sources
weather # Weather for a location
todo # Manage a simple todo list
brief # Daily briefing (composes news, weather, todo)
code-map # Map out a codebase structure
code-ref # Find references to a symbol
Each tool is a standalone, self-contained script that works for both you and
Binsmith. Python scripts use inline script metadata
so dependencies are declared in the file itself — just run the script and uv
handles the rest. No virtualenv, no pip install.
Run todo add "buy milk" yourself, or let Binsmith do it — same interface, same tool.
Tools are symlinked to ~/.local/bin (or $BINSMITH_GLOBAL_BIN) so they're
available everywhere, not just inside Binsmith. They pipe into each other
and compose naturally.
How it works
Binsmith has one tool: bash. It runs commands in your project directory with
the workspace bin/ on the PATH. The workspace persists:
.binsmith/
workspace/
bin/ # Scripts the agent creates
data/ # Persistent data
tmp/ # Scratch space
binsmith.db # Conversation history
On each run, the agent sees its current toolkit and is prompted to use existing tools before writing one-off commands.
Architecture
┌──────────────────────────────────────────┐
│ Clients │
│ TUI / Web UI / (API) │
└─────────────────┬────────────────────────┘
│ HTTP + AG-UI streaming
▼
┌──────────────────────────────────────────┐
│ Binsmith Server │
│ FastAPI · SQLite · Session management │
└─────────────────┬────────────────────────┘
│ pydantic-ai
▼
┌──────────────────────────────────────────┐
│ Agent │
│ Dynamic prompt · bash tool · Toolkit │
└─────────────────┬────────────────────────┘
│ subprocess
▼
┌──────────────────────────────────────────┐
│ File System │
│ Scripts as files · Git-friendly │
└──────────────────────────────────────────┘
The TUI and web UI are interchangeable clients. Both talk to the same server, share the same history, and see the same toolkit.
Models
Default: google-gla:gemini-3-flash-preview
export GEMINI_API_KEY=... # Google
export ANTHROPIC_API_KEY=... # Anthropic
export OPENAI_API_KEY=... # OpenAI
Switch models in the TUI with /model set <name> or via the web UI sidebar.
Run /model list to see available models.
Web UI
cd frontend
npm install
npm run dev
Connects to http://localhost:8000 by default. Override with
VITE_BINSMITH_SERVER_URL in frontend/.env.local.
TUI commands
/help Show help
/threads List threads
/thread <id> Switch to a thread
/thread new [id] Create a new thread
/thread delete <id> Delete a thread
/clear Clear current thread
/model Show current model
/model list [filter] List models
/model set <name> Set model
/model default Reset to default
/quit Exit
Configuration
| Variable | Default | Description |
|---|---|---|
BINSMITH_MODEL |
google-gla:gemini-3-flash-preview |
Default model |
BINSMITH_WORKSPACE_MODE |
local |
local (per-project) or central (~/.binsmith) |
BINSMITH_SERVER_URL |
(unset) | Server URL for clients that connect over HTTP |
BINSMITH_LOGFIRE |
0 |
Enable Logfire telemetry |
Running the server directly
binsmith server
# or
uvicorn binsmith.server.asgi:app --reload --port 8000
Run the server separately if you want the web UI (or multiple clients) to connect over HTTP.
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 binsmith-0.3.0.tar.gz.
File metadata
- Download URL: binsmith-0.3.0.tar.gz
- Upload date:
- Size: 169.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","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 |
15ad400f22281e69cb506a422def69e3530f16f84ba6c2dc7333cd55339b35f9
|
|
| MD5 |
bfc399f1608413910a537c98c4f92da4
|
|
| BLAKE2b-256 |
4cbebd047d0a18e7da46bb6ff5853894a4a3fa91a6b10332d1209b2e4313fa98
|
File details
Details for the file binsmith-0.3.0-py3-none-any.whl.
File metadata
- Download URL: binsmith-0.3.0-py3-none-any.whl
- Upload date:
- Size: 38.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","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 |
55bf7f777d3ca15ee1e380133d4cd9d6f3ad505082b68121c94530465c5df80e
|
|
| MD5 |
4e901db8565a37d4b3664bc5f2fe5d32
|
|
| BLAKE2b-256 |
b245f9a2b6ae1e91d5273c1764a115aedc4a8b4cb72e95bc34e1323b50897edb
|