Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

75 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

tact

tact

Terminal-first AI coding agent. Built in Rust. MIT licensed.

Quick Start Β· Features Β· Architecture Β· Configuration

Rust MIT License Version Platform


What is tact?

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.


Quick Start

1. Install

Linux / macOS

curl -fsSL https://raw.githubusercontent.com/rust-infra/tact/main/scripts/install.sh | bash

Or from a clone:

./scripts/install.sh --from-source

Windows (PowerShell)

irm https://raw.githubusercontent.com/rust-infra/tact/main/scripts/install.ps1 | iex

Or from a clone:

.\scripts\install.ps1 -FromSource

The 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 -- --release

Install 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-dev
git 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 --help

Via Cargo (coming soon to crates.io):

cargo install --path crates/tact-ui   # or: cargo install -p tact-ui from the repo root

Binary 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.8

GitHub Actions (.github/workflows/release.yml) uploads tact-ui-v<version>-<target-triple>.tar.gz / .zip plus SHA256SUMS.

2. Configure

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 = 1800

CLI 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

3. Run

# 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"

Features

🧠 Intelligent Agent Loop

Multi-turn conversation loop with progressive context management:

  1. Large-output spill β€” oversized tool results land on disk with a short preview in context
  2. Micro-compact β€” before each LLM call, stub old tool results (keep the last 12 intact)
  3. Full compact β€” when reported/estimated tokens hit ~80% of model_context_window, on prompt-too-long recovery, or via a successful compact tool: 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.

πŸ”§ Built-in Tools

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.

πŸ” Three Permission Modes

default   β†’  Ask before every tool call (safe)
plan      β†’  Plan first, then ask once
auto      β†’  Auto-approve all actions (CI / trusted repos)

πŸͺ Hooks & Skills

  • Pre/Post hooks β€” intercept tool calls before/after execution. Run linters, format code, log usage.
  • Skills β€” SKILL.md playbooks under <workdir>/.tact/skills/, ~/.tact/skills/, ~/.agents/skills/, .claude/skills/, and optional [agent].skill_dirs (summaries in the system prompt; full body via load_skill or TUI /skill-name).
  • Cron β€” schedule recurring prompts. The agent checks in on your project automatically.

🧩 Plugin Marketplace

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.

πŸ‘₯ Sub-agents & Team

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.

🌳 Git Worktree Isolation

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.

πŸ”Œ MCP Support

Native Model Context Protocol client. Connect any MCP server and its tools become available to the agent at runtime.

πŸ“‘ TUI & Headless

  • 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

πŸ–ΌοΈ Image attachments (vision)

Attach workspace images with @path/to.png or ![alt](path). 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.

πŸ’Ύ Persistent State

Transcripts, tool results, memories, cron jobs, and task state all persist to ~/.tact/ and <project>/.tact/. Pick up where you left off.


Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     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:

  1. Optionally auto-compacts old history (reserving space for the incoming user turn), then appends the turn
  2. Builds the system prompt from role, guidelines, constraints, memory, and dynamic context
  3. Micro-compacts old tool results; auto-compacts again if the window is still over the threshold
  4. Sends the conversation to the LLM with tool definitions
  5. Processes streaming responses: text β†’ display, tool calls β†’ execute
  6. Checks permissions for each tool call
  7. Runs pre/post hooks on tool execution
  8. Writes results back to the conversation history; a successful compact tool then rewrites context
  9. 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).


Built-in Tools

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)

Configuration

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.

Config file locations (auto-discovered)

<project>/.tact/config.toml      # project-level
<project>/config.toml             # project-level (alt)
~/.tact/config.toml               # user-level

Full config reference

[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

CLI flags (override config)

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

Project Structure

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

Roadmap

  • 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

Contributing

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.


License

MIT β€” do whatever you want, just keep the copyright notice.


Built with πŸ¦€ by Rg0x80

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages