tam-worktree 0.3.4

Git worktree management and project discovery library
Documentation

Manage units of work, not just processes.

TAM manages tasks — named units of work that bind a directory to a series of AI agent runs. It unifies git worktree management and agent process supervision into a single tool.

Running multiple AI coding agents means juggling tmux panes, manual worktree creation, and remembering which session to resume. TAM replaces that with a single abstraction: create a task, and it gets a worktree, a branch, and an agent — all under one name. Status is always derived from reality (daemon, git, filesystem), never stored, so it can't drift.

Quick start

# One-time: configure Claude Code hooks for state detection
tam init --agent claude

# Create a task — this creates branch "fix-auth" and worktree "myapp--fix-auth"
tam new fix-auth -w

# Start an agent and attach to it (full-screen, like tmux)
tam run fix-auth

# Detach with ctrl-] — the agent keeps running in the background
# Check all tasks at a glance
tam ps

# Or open the interactive TUI dashboard
tam

Key concepts

Task — a named unit of work binding a directory to agent runs. Tasks have two flavors:

  • Owned: TAM creates a git worktree for the task. The task name becomes the branch name. tam drop cleans up both.
  • Borrowed: TAM tracks agents in an existing directory without touching the filesystem.

Status is always derived, never stored. TAM checks the daemon (is an agent running?), the filesystem (does the worktree exist?), git (does the branch exist?), and activity timestamps (is the task stale?) every time you look.

Status Meaning
● run Agent producing output
▲ input Agent waiting for user prompt
▲ block Agent waiting for permission
○ idle No agent running, task exists
◌ stale No activity for 30 days
✗ gone Worktree or branch deleted externally

Features

  • Task = worktree + agenttam new feat -w creates a branch, a worktree, and optionally starts an agent, all under one name
  • Derived status — never stores lifecycle state; computes it from the daemon, git, and filesystem every time you look
  • TUI dashboard — real-time task table with peek mode (scrollback preview without attaching)
  • Session resume — pick up where you left off or start fresh; session history is tracked in an append-only ledger
  • Auto-daemon — the daemon starts on first command and shuts down after 30s idle; no manual management
  • Per-repo init.tam.toml copies untracked files and runs setup commands in new worktrees
  • Desktop notifications — configurable alerts when agents need input or hit permission prompts
  • Custom TUI commands — bind keys to shell commands (open editor, run tests, etc.)

Commands

Task lifecycle

tam new NAME                   Create task bound to current directory
tam new NAME -w                Create task with its own worktree
tam new NAME -w -s REF         Worktree branched from a specific ref

tam run NAME                   Start/resume an agent in the task
tam run NAME --new-session     Start a fresh session

tam stop NAME                  Kill the agent (task persists)
tam stop                       Resolve task from current directory

tam attach NAME                Full-screen attach to running agent
tam attach                     Resolve from current directory

tam drop NAME                  Kill agent + remove task (+ delete worktree if owned)
tam drop NAME -b               Also delete the git branch

Observing

tam ps                         Task table with computed status
tam ps --json                  Machine-readable output

tam ls                         Discover projects and worktrees
tam ls PATH                    Discover under a specific directory

tam pick                       Fuzzy project picker (prints selected path)
tam pick -F "dmenu -l 20"     Use a custom finder instead of fzf

TUI

Running tam with no arguments opens the dashboard:

┌────────────────────────────────────────────────────────────────────────────┐
│  tam — 4 tasks (1 needs input)                                             │
├────────────────────────────────────────────────────────────────────────────┤
│  STATUS    REPO     TASK          AGENT   OWN  DIR                   CTX   │
│  ● run     myapp    feat          claude   ✔   ~/wt/myapp--feat      34%   │
│▸ ▲ input   myapp    fix-nav       claude   ✔   ~/wt/myapp--fix-nav   67%   │
│  ○ idle    myapp    refactor      -        ✔   ~/wt/myapp--refac     -     │
│  ◌ stale   other    old-thing     -        ✘   ~/projects/other      -     │
├────────────────────────────────────────────────────────────────────────────┤
│  enter:attach  n:new  r:run  s:stop  d:drop  p:peek  q:quit                │
└────────────────────────────────────────────────────────────────────────────┘

Keys: j/k navigate, enter attaches, n creates a task, r runs an agent, s stops, d drops, p toggles peek (scrollback preview), / filters, q quits. When attached to an agent, ctrl-] detaches and returns to the dashboard.

Tasks are sorted by repository name, then by status priority (blocked → input → running → idle → stale → gone), then by task name.

Setup

tam init --agent claude        Configure Claude Code hooks
tam shutdown                   Stop all agents and kill the daemon
tam status                     Check if the daemon is running

Configuration

TAM reads ~/.config/tam/config.toml:

[spawn]
default_agent = "claude"

[worktree]
root = "~/worktrees"
auto_init = true              # run .tam.toml after worktree creation

[discovery]
max_depth = 5
ignore = [".*", "node_modules", "target"]

[daemon]
scrollback = 1048576

[notify]
command = "notify-send 'tam: {task}' '{status}'"
on_states = ["input", "blocked"]

[session]
finder = "fzf"

[[tui.commands]]
name = "open in editor"
key = "o"
command = "code {dir}"

Per-repo worktree initialization is configured via .tam.toml at the project root. When tam new NAME -w creates a worktree, it copies files matching include globs from the main checkout (useful for untracked secrets or editor config) and runs commands inside the new worktree:

[init]
include = [".env", ".claude/**"]
commands = ["npm install"]

Agent providers

Provider State detection Context tracking Setup
Claude Code Hook-based (immediate) Reads session JSONL for token usage tam init --agent claude
Codex PTY heuristic (5s idle) Reads session JSONL None
Any CLI PTY heuristic (5s idle) None None

Claude Code uses hooks (~/.claude/settings.json) to report state changes instantly — TAM knows the moment an agent needs input or hits a permission prompt. Other providers fall back to a PTY idle-time heuristic. Any command-line program can be used as a provider: tam run feat -a my-tool.

Install

Requirements: git is required at runtime for all worktree and branch operations.

Pre-built binaries

Download a binary for your platform from GitHub Releases (Linux x86_64/aarch64, macOS x86_64/aarch64).

Cargo

cargo install tam-cli

Nix

nix run github:ComeBertrand/tam

Shell completions and man page

The build generates completions for bash, zsh, and fish, plus a man page (tam.1). When installing via cargo install, these are not placed automatically. After building from source, find them under the build output directory:

cargo build --release
find target/release/build/tam-cli-* -name 'completions' -o -name 'man'

Contributing

Contributions are welcome — open an issue or submit a pull request. For the full design rationale and architecture, see tam_manifesto.md.

License

MIT