proj · the agent-aware session picker
proj is a tmux session picker. You pick a project, then the agent and model to launch, and it opens a named session with them. It also lists your live sessions across per-project servers, each showing the agent running in it and any muster attention.
$ proj SESSIONS ──────────────────┬─ PREVIEW ───────────────── › web claude·run ✉ │ ~/src/web · 3 windows api codex·idle │ ● claude working — infra — │ "GET /users missing createdAt" dotfiles — │ muster: 1 reply · 2m ago ↑↓ move · ⏎ attach · / filter · q quit
what it shows
Open the picker with a bare proj. Every live tmux session across all per-project servers is listed as <project>/<work>, and each row carries the context you'd otherwise have to attach to discover.
Which agent is attached — pi, claude, cursor, or blank — and its state (claude·run, codex·idle), resolved live from the pane, not a stale cache.
A session waiting on muster mail glows with a ✉ flag, so the picker doubles as a glance at which work sessions need you.
The highlighted row previews to the right — working directory, windows, the agent's current activity — so you attach to the right session the first time.
proj runs one tmux server per project (the proj-<name> socket convention muster uses), so a crash in one project never takes down another. Scope the picker to a project or span them all.
Beside the agent pane, a sidebar of your choosing — scratch, a file explorer, a shell — built on new work and arranged the way your day runs.
Non-interactive verbs an agent can run without hijacking your terminal: proj list --json, proj current --json, and proj new <project>/<work> --agent <name> to spawn a detached session.
agent + model
Selecting + new work… in a project opens an inline prompt to name the session. While you type, Tab cycles the agent that will launch into it, and Shift-Tab opens a filterable list of that agent's models — the footer shows both. Change the agent and the model re-seeds to that agent's default.
Model menus are scoped to the agent, because agents don't share models. Claude Code only accepts Anthropic models, so its menu is a built-in list. pi can reach many providers, so its menu is discovered from pi --list-models, filtered to the providers you name in config, and offered as provider/id — launched as pi --model <provider/id>. Agents that take no model (cursor, none) simply don't show the list.
select model — type to filter claude-bridge/claude-opus-4-8 › openai-codex/gpt-5.6-sol openai-codex/gpt-6-astra ↑↓ move · ⏎ select · esc keep current
config
proj reads a roots file (which directories are projects) and an optional config.toml (defaults, the sidebar, model menus, per-project overrides). Unset keys fall back to built-in defaults.
One project root per line; blank lines and # comments ignored.
# work ~/GitHub/myapp ~/GitHub/infra # personal ~/GitHub/dotfiles
default_agent = "pi" # what new work launches; "none" for a plain shell
sidebar = true # auto-build the sidebar column on new work
[sidebar_layout]
panes = ["scratch", "yazi", "shell"] # top → bottom
sizes = { scratch = 12, shell = 10 } # rows; the middle pane fills
[model_providers] # pi's model menu = these providers' models
pi = ["claude-bridge", "openai-codex"]
[project."bettor-help"] # optional per-project overrides
default_agent = "claude"
default_model = "claude-sonnet-4-6" # pin this project's model
sidebar = false
pi's list is discovered from pi --list-models and cached ~24h; it refreshes on its own, or when you run pi update.
keys
| Key | In the list |
|---|---|
↑ ↓ | move the cursor |
⏎ | attach a session · drill into a project · start new work |
type / ⌫ | filter the list |
Tab | toggle folders ↔ live sessions |
^x | reap the highlighted session (confirm with a second ^x) |
esc / q | back out · quit |
| Key | Naming new work |
|---|---|
Tab | cycle the agent |
Shift-Tab | open the model list (type to filter, ⏎ pick, esc keep) |
^s | toggle the sidebar for this session |
⏎ / esc | create · cancel |
install
One command downloads proj, verifies its checksum, and puts it on your PATH (~/.local/bin). macOS and Linux, Apple silicon and x86-64.
$ curl -fsSL https://tackle.tools/install.sh | sh -s proj
Run it again to upgrade; check your version with proj version. Building from source instead? go install github.com/subaud-tools/tackle/cmd/proj@latest.