A small, extensible coding agent for your terminal.
Small enough to read end to end. Stubborn enough to .
$ curl -fsSL https://tapir.dev/install.sh | sh
$ tapir tapir · claude-sonnet-4-6 · ~/src/acme › add a --version flag to the CLI and a test for it ⟳ grep "struct Args" src/ ⟳ read src/cli.rs ⟳ edit src/cli.rs @@ struct Args @@ - // TODO: --version + /// Print version and exit + #[arg(long)] + version: bool, ⟳ write tests/cli_version.rs ⟳ bash cargo test --test cli_version Added a `--version` flag and a test asserting it prints the crate version. cargo test — 7 passed, 0 failed. › /model claude-haiku
A Tapir session: edits the CLI, writes a test, runs it, switches model.
A core small enough to trust
The core stays deliberately small —
read, bash, edit, write —
and everything past it is something you bolt on: tools, providers, skills,
plugins. Tapir bends to the habits you already have instead of teaching you
new ones.
It ships as one self-contained binary on a Tokio async runtime — nothing to install but the file itself. It cold-starts in milliseconds, streams as it thinks, and leaves your terminal the way it found it.
Every model behind one flag
Anthropic, Google, OpenAI (Responses) and any OpenAI-compatible endpoint —
OpenRouter, DeepSeek, local servers. Authenticate with API keys, or with
OAuth for Claude Pro/Max (tapir --login anthropic) and skip the
key entirely.
Pick per run, by fuzzy name, with a thinking level:
$ tapir --provider google --model gemini-2.5-flash -p "..."
$ tapir --model claude-sonnet-4-6:medium -p "..."
Switch mid-session with /model, or list the whole catalog with
tapir --list-models:
$ tapir --list-models
anthropic claude-opus-4-8 claude-sonnet-4-6 claude-haiku-4-5
google gemini-2.5-pro gemini-2.5-flash
openai gpt-5.4 gpt-4.1
openrouter deepseek/deepseek-chat # …and any OpenAI-compatible model
- Anthropic
- OpenAI (Responses)
- OpenRouter
- DeepSeek
- local servers
- OAuth · Claude Pro/Max
Every session is a file you can rewind
Conversations persist as JSONL under ~/.tapir/sessions/ and
reload with context intact. Resume the last one with --continue,
branch with --fork, or pick any with --session <id>.
--no-session when you want it ephemeral.
Long runs compact themselves: as the context nears the model
window, older turns are summarized and dropped, so --continue
keeps working. In the TUI, /tree walks the whole history,
/share and /export get it out, /compact
trims it by hand.
You own the context window
Tapir keeps a minimal system prompt and hands you the levers that decide what goes into the window.
AGENTS.md / CLAUDE.md: project instructions from the
current directory and its ancestors, injected at startup (disable with
--no-context-files).
Compaction: automatic, structured summaries of older turns.
Tune the reserve and keep windows with TAPIR_COMPACT_RESERVE and
TAPIR_COMPACT_KEEP.
Skills: drop a SKILL.md in
~/.tapir/skills/<name>/; Tapir surfaces it and loads it on
demand when the task matches.
Prompt templates: Markdown files become /name
commands with $1, $@ and $ARGUMENTS
substitution.
New tricks without a recompile
Built-in tools — read, bash, edit,
write, plus grep, find and
ls. Search is native (no rg/fd
download) and respects .gitignore.
Tool plugins: any executable in
~/.tapir/plugins/ adds a tool via a tiny protocol —
describe prints a JSON schema, call reads args on
stdin. Any language, no recompile.
MCP servers: configure mcpServers and Tapir
spawns each over stdio (JSON-RPC), adapting its tools as
mcp__<server>__<tool>.
Bundle your setup, ship it anywhere
Bundle skills, prompts, themes and plugins as a package and install it from
a git URL, an owner/repo, or a local path:
$ tapir install owner/repo
$ tapir install https://git.tapir.dev/tapir.git/
Everything is tracked in tapir.toml. List what's installed with
tapir list, drop one with tapir remove <name>.
Four ways in
Interactive: the full TUI — streaming output, slash commands and themes, rendered inline in your terminal (no alternate screen).
Print: tapir -p "query" for one-shots and
scripts.
JSON: --mode json streams structured events as
JSONL.
RPC: a JSON protocol over stdin/stdout to embed Tapir in other tools.
Small core, sharp edges
Tapir stays small on purpose. Everything past the core is a tool, a skill, a plugin or a package you opt into — so it stays something you reach for, not a framework you live inside.
Safe by default: a native permission gate blocks
catastrophic bash — rm -rf /, fork bombs, mkfs,
dd to a device — and you extend it with denyBash in
settings.
Yours to look at: ships with tapir,
claude, dark and light themes —
switch live with /theme.
Download & verify
Every release lives in its own directory, mirror-style. The latest is
0.1.0. Grab a prebuilt binary or build
from source — then verify it with signify before you run it.
- ANNOUNCEMENT Release notes & changes
- SHA256 Checksums for every file below
- SHA256.sig The checksum list, signed with signify
- tapir.pub signify public key (verify the signature)
- tapir-0.1.0.tar.gz Source
- tapir-0.1.0-x86_64-linux-gnu.tar.gz Linux x86-64 (glibc)
- tapir-0.1.0-aarch64-linux-gnu.tar.gz Linux ARM64 (glibc)
- tapir-0.1.0-x86_64-linux-musl.tar.gz Linux x86-64 (musl, static)
- Soon tapir-0.1.0-x86_64-openbsd.tar.gz — OpenBSD x86-64 (once the local QEMU build lands)
Fetch the public key once, then check the signed checksum list (and every file in the directory) against it:
$ signify -C -p tapir.pub -x SHA256.sig
To check a single artifact, name it explicitly:
$ signify -C -p tapir.pub -x SHA256.sig \
tapir-0.1.0-x86_64-linux-gnu.tar.gz
Send patches by email
Tapir takes contributions the old, durable way: git send-email.
No account, no pull request — just a patch in your maintainer's inbox.
Patches go to [email protected].
Get the source — no account needed. Clone over HTTPS, or anonymously over SSH (anoncvs-style: no key, no password — read-only):
$ git clone https://git.tapir.dev/tapir.git
# …or anonymously over SSH (read-only, public repos):
$ git clone ssh://[email protected]/tapir.git
Browse it in the web UI at git.tapir.dev.
Point send-email at the maintainer once for this repo, then send:
$ git config sendemail.to "[email protected]"
$ git send-email HEAD^ # last commit
$ git send-email origin/main.. # a series
Reply to feedback with a new revision via git send-email -v2.
New to this flow?
git-send-email.io
walks through the one-time setup.