Terminal-first AI coding agent. Built in Rust. MIT licensed.
Quick Start Β· Features Β· Architecture Β· Configuration
tact is a terminal-first AI coding agent that lives inside your terminal. It reads your codebase, understands your intent, and executes β editing files, running commands, searching code, and coordinating with sub-agents.
- π¦ Written in Rust β a single small binary, no Electron, no Node.js runtime
- π Fully self-hosted β your code never leaves your machine (only LLM API traffic)
- π MIT licensed β open source
- π§© Extensible β MCP plugins, custom skills, hooks, and tool macros
$ tact-ui headless "Add a --verbose flag to the CLI and update the README"
That's it. Configure a provider, open a terminal, and prompt.
Linux / macOS
curl -fsSL https://raw.githubusercontent.com/rust-infra/tact/main/scripts/install.sh | bashOr from a clone:
./scripts/install.sh --from-sourceWindows (PowerShell)
irm https://raw.githubusercontent.com/rust-infra/tact/main/scripts/install.ps1 | iexOr from a clone:
.\scripts\install.ps1 -FromSourceThe installer prefers a matching GitHub release asset when one exists, otherwise
builds tact-ui from source (requires Rust 1.85+ / edition 2024; installs
rustup if needed). Pass --from-source / -FromSource to skip the release
download, or --release / -Release to prefer a pre-built binary with source
fallback:
curl -fsSL https://raw.githubusercontent.com/rust-infra/tact/main/scripts/install.sh | bash -s -- --releaseInstall options:
| Platform | Flag | Meaning |
|---|---|---|
| Unix | --install-dir DIR |
Install location (default: ~/.local/bin) |
| Unix | --system |
Install to /usr/local/bin |
| Unix | --from-source |
Build from source only |
| Unix | --release |
Prefer GitHub release, fall back to source |
| Unix | --release-only |
Require a GitHub release (no source fallback) |
| Windows | -InstallDir PATH |
Install location (default: %USERPROFILE%\.local\bin) |
| Windows | -FromSource |
Build from source only |
| Windows | -Release |
Prefer GitHub release, fall back to source |
| Windows | -ReleaseOnly |
Require a GitHub release (no source fallback) |
Manual build from source
Linux: install SQLite build dependencies first (required by sqlx / session store).
Building from source requires Rust 1.85+ (edition 2024):
sudo apt-get update
sudo apt-get install -y libsqlite3-dev pkg-config clang libclang-devgit clone https://github.com/rust-infra/tact.git
cd tact
rustup toolchain install stable # if needed; rustc >= 1.85
cargo build --release --locked -p tact-ui
./target/release/tact-ui --helpVia Cargo (coming soon to crates.io):
cargo install --path crates/tact-ui # or: cargo install -p tact-ui from the repo rootBinary releases: push a version tag to publish pre-built binaries for Linux (x86_64 / ARM64), macOS (x86_64 / ARM64), and Windows (x86_64):
git tag v1.0.8
git push origin v1.0.8GitHub Actions (.github/workflows/release.yml) uploads tact-ui-v<version>-<target-triple>.tar.gz / .zip plus SHA256SUMS.
Create config.toml in your project root (or ~/.tact/config.toml for user-level defaults):
[llm]
provider = "anthropic" # "anthropic" | "openai" | "deepseek" | "kimi"
model = "claude-sonnet-4-20250514"
api_key = "sk-ant-..."
base_url = "https://api.anthropic.com" # required for anthropic
[permission]
mode = "default" # "default" | "plan" | "auto"
[agent]
model_context_window = 200000
snapshot_max_items = 80
micro_compact_enabled = true
notifications_enabled = true
[ui]
theme = "retro" # retro | brutal | nord | dark | auto ...
[tools]
# Bash wall-clock timeout in seconds (default: 1800; 0 disables timeout)
bash_timeout_secs = 1800CLI flags override the config file (e.g. --model, --api-key, --theme).
Optional agent settings (config file or CLI):
| Setting | CLI flag | Default | Description |
|---|---|---|---|
snapshot_max_items |
--snapshot-max-items |
80 |
Max entries in the system-prompt Project structure snapshot |
model_context_window |
--model-context-window |
200000 |
Model context window in tokens (80% auto-compact + TUI usage meter) |
micro_compact_enabled |
--no-micro-compact |
true |
Stub old tool results before each LLM call |
# Interactive TUI (default)
tact-ui
# Headless single-shot task
tact-ui headless "Fix all clippy warnings in src/ and run cargo test"
# With specific model
tact-ui headless --model "claude-sonnet-4-20250514" "Refactor the error handling in lib.rs"
# Plan-only mode (review before execution)
tact-ui -m plan headless "Add rate limiting to the API client"Multi-turn conversation loop with progressive context management:
- Large-output spill β oversized tool results land on disk with a short preview in context
- Micro-compact β before each LLM call, stub old tool results (keep the last 12 intact)
- Full compact β when reported/estimated tokens hit ~80% of
model_context_window, on prompt-too-long recovery, or via a successfulcompacttool: write a JSONL transcript, summarize, and rebuild as recent real user turns + handoff summary
The entry path reserves the incoming user turn before push, so a large prompt cannot overflow immediately after append. Failed compact tool calls leave history intact.
Details: book/05_chapter_compact.md (δΈζ), docs/compaction.md.
| Category | Tools |
|---|---|
| File System | read_file, write_file, edit_file, apply_patch |
| Shell | bash, background_run, check_background, sleep |
| Task Management | task_create, task_get, task_list, task_update |
| Team & Sub-agents | spawn_subagent, spawn_teammate, list_teammates, send_message, broadcast, read_inbox |
| Memory & Knowledge | save_memory, load_skill, compact |
| Git & Worktree | worktree_create, worktree_list, worktree_status, worktree_run, worktree_events |
| Scheduling | cron_create, cron_list, cron_delete |
| Interaction | ask_user, plan_approval, shutdown_request, shutdown_response |
In the interactive TUI, a running bash tool shows a bounded five-line live
tail. stdout and stderr are merged in the order Tact observes their pipe reads,
with stderr styled as warning text. Tact does not add a PTY, rewrite commands,
or bypass buffering owned by the command or pipeline. Headless mode remains
final-result-only.
default β Ask before every tool call (safe)
plan β Plan first, then ask once
auto β Auto-approve all actions (CI / trusted repos)
- Pre/Post hooks β intercept tool calls before/after execution. Run linters, format code, log usage.
- Skills β
SKILL.mdplaybooks under<workdir>/.tact/skills/,~/.tact/skills/,~/.agents/skills/,.claude/skills/, and optional[agent].skill_dirs(summaries in the system prompt; full body viaload_skillor TUI/skill-name). - Cron β schedule recurring prompts. The agent checks in on your project automatically.
Tact installs skill-only plugins natively. The built-in claude-plugins-official marketplace is available in every installation:
/plugin install superpowers@claude-plugins-official
/superpowers:brainstorming
Add another marketplace with /plugin marketplace add <source>. A source may be a GitHub shorthand such as owner/repository, a Git URL, or a remote marketplace.json URL. Tact derives the marketplace name from the source's final path component; use that name with /plugin marketplace update <name>, /plugin marketplace remove <name>, and /plugin install <plugin>@<name>.
In the TUI, /plugin list and /plugin marketplace list render as titled tables (one row per plugin or marketplace). /plugin reload refreshes discovered plugin skills.
Tact owns marketplace state, checkouts, and revision-locked plugin caches under ~/.tact/plugins/. It loads only skills/*/SKILL.md from an installed plugin; plugin hooks, agents, MCP servers, commands, LSPs, monitors, and executables are not loaded or run. Installed skills use /plugin:skill (for example /superpowers:brainstorming); standalone skills keep the unprefixed /skill form.
Spawn isolated sub-agents for parallel work. Coordinate via message-passing inboxes. Each sub-agent gets a sandboxed toolset (bash + file R/W). Use plan_approval / shutdown_request protocols for structured handoffs.
Each task can run in its own git worktree lane. No branch switching, no stash dancing. Agents work in parallel without stepping on each other.
Native Model Context Protocol client. Connect any MCP server and its tools become available to the agent at runtime.
- TUI mode (
tact-ui) β streaming output, syntax-highlighted diffs, interactive permission dialogs - Headless mode (
tact-ui headless) β CI/CD pipelines, scripts, or non-interactive workflows
Attach workspace images with @path/to.png or . Raster files are optionally compressed via [ui.vision_image] before base64 attachment.
Requires a vision-capable model/endpoint. OpenAI-compatible providers send images as image_url content parts; text-only models or gateways that only accept text reject the request (HTTP 400, e.g. unknown variant image_url, expected text). Use a multimodal model (e.g. Claude vision, GPT-4o), or omit image attachments on text-only models.
Transcripts, tool results, memories, cron jobs, and task state all persist to ~/.tact/ and <project>/.tact/. Pick up where you left off.
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β tact β
β β
β βββββββββββ ββββββββββββ βββββββββββββββββ β
β β Agent β β Tool β β Permission β β
β β Loop ββββ Router ββββ Manager β β
β ββββββ¬βββββ ββββββ¬ββββββ βββββββββ¬ββββββββ β
β β β β β
β ββββββ΄βββββ βββββββ΄βββββββ ββββββββ΄ββββββββ β
β β Context β β MCP Router β β Hook Engine β β
β β Compact β β (external) β β (pre/post) β β
β βββββββββββ ββββββββββββββ ββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β LLM Client β β
β β Anthropic Β· OpenAI Β· Compatible β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββ ββββββββββββ βββββββββββββββββ β
β β Sub- β β Worktree β β Memory / β β
β β Agents β β Lanes β β Skills β β
β βββββββββββ ββββββββββββ βββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
The agent loop:
- Optionally auto-compacts old history (reserving space for the incoming user turn), then appends the turn
- Builds the system prompt from role, guidelines, constraints, memory, and dynamic context
- Micro-compacts old tool results; auto-compacts again if the window is still over the threshold
- Sends the conversation to the LLM with tool definitions
- Processes streaming responses: text β display, tool calls β execute
- Checks permissions for each tool call
- Runs pre/post hooks on tool execution
- Writes results back to the conversation history; a successful
compacttool then rewrites context - Continues until the model stops requesting tools (or recovery exhausts)
See ARCHITECTURE.md for a deeper dive, and the book for chapter-length walkthroughs (compaction, recovery, tools, agent loop).
| Tool | Description |
|---|---|
read_file |
Read file contents with optional offset/limit; default page is 2000 lines / ~25k approx tokens with a PARTIAL continuation marker |
write_file |
Write or overwrite a file |
edit_file |
Replace exact text in a file (first match, or all with replace_all) |
apply_patch |
Apply unified diff patches |
bash |
Run a shell command |
background_run |
Run a command in the background |
check_background |
Check background task status |
sleep |
Wait for N milliseconds |
spawn_subagent |
Spawn a sub-agent with fresh context |
task_create |
Create a persistent task |
task_get |
Get task details by ID |
task_list |
List all tasks with status |
task_update |
Update task status, owner, dependencies |
spawn_teammate |
Create a named teammate |
list_teammates |
List all teammates |
send_message |
Send a message to a teammate |
broadcast |
Broadcast to all teammates |
read_inbox |
Read teammate inbox |
plan_approval |
Send a plan approval message |
shutdown_request |
Request shutdown |
shutdown_response |
Respond to shutdown request |
save_memory |
Save persistent memory across sessions |
load_skill |
Load a named skill |
compact |
Request conversation summarization (rewrites history only on success) |
worktree_create |
Create a git worktree lane |
worktree_list |
List tracked worktrees |
worktree_status |
Show git status in a worktree |
worktree_run |
Run a command inside a worktree |
worktree_events |
List worktree lifecycle events |
cron_create |
Create a scheduled prompt |
cron_list |
List scheduled prompts |
cron_delete |
Delete a scheduled prompt |
ask_user |
Ask the user (TUI popup; multi_select for checkboxes) |
tact merges config from two sources (priority: high β low):
CLI args > config.toml
Use --config /path/to/config.toml to point at a specific file instead of auto-discovery.
<project>/.tact/config.toml # project-level
<project>/config.toml # project-level (alt)
~/.tact/config.toml # user-level
[llm]
provider = "anthropic" # "anthropic" | "openai" | "deepseek" | "kimi"
model = "claude-sonnet-4-20250514"
api_key = "sk-ant-..."
base_url = "https://..." # proxy or compatible endpoint
max_tokens = 8000
thinking_budget = 32000
[permission]
mode = "default" # "default" | "plan" | "auto"
[agent]
model_context_window = 200000 # tokens; 80% auto-compact + TUI meter
snapshot_max_items = 80
micro_compact_enabled = true # stub old tool results before each LLM call
notifications_enabled = true
[ui]
theme = "retro" # or "auto"
# vision_image.* only reduces tokens for attached images; does not enable vision
# vision_image.compress = true
# vision_image.max_edge = 1280
# vision_image.jpeg_quality = 80
[tools]
bash_timeout_secs = 1800 # wall-clock seconds; 0 disables timeout| Flag | Description |
|---|---|
--config |
Path to config file |
--provider |
LLM provider |
--model |
Model name |
--api-key |
API key |
--base-url |
API base URL |
--max-tokens |
Max tokens per LLM call |
--thinking-budget |
Extended thinking budget |
--permission-mode / -m |
Permission mode |
--theme |
TUI theme |
--snapshot-max-items |
Project structure snapshot size |
--no-micro-compact |
Disable micro-compaction |
--tokio-console |
Enable tokio-console debugging |
crates/
βββ protocol/ # Shared wire types (AgentUpdate, UserCommand, β¦)
βββ tact/ # Agent runtime library: loop, tools, hooks, permissions, MCP, LSP
βββ tact-ui/ # CLI binary (TUI + headless); wires tact + tui
βββ tact_llm/ # LLM provider adapters
βββ tui/ # Terminal UI (ratatui)
βββ tool_refactor_macros/ # #[tool] proc macro
- Publish to crates.io
- Pre-built binary releases (GitHub Actions)
- Web dashboard for task/tool monitoring
- More MCP transports (SSE, WebSocket)
- Llama / Ollama support for fully local operation
- VS Code extension (bridge to TUI)
- Multi-user team server
tact is early stage and welcomes contributions! Some good places to start:
- π Bug reports β open an issue
- π‘ Feature requests β open a discussion
- π§ PRs β pick up a
good-first-issue
Before opening a PR, run ./scripts/check-rust.sh (fmt + clippy -D warnings + tests),
or format only with ./scripts/fmt-rust.sh. Install hooks with
./scripts/install-git-hooks.sh to run the full check on push.
See ARCHITECTURE.md for an overview of the codebase.
MIT β do whatever you want, just keep the copyright notice.
Built with π¦ by Rg0x80
