---
title: sloop
description: >-
  A local-first control layer above your AI coding CLIs: one canonical AGENTS.md
  per repo, one cross-repo fleet view of every agent you're running.
url: 'https://stroops.tech/sloop'
last_updated: '2026-07-01'
---
# sloop: A Local-First Fleet Manager for AI Coding Agents

I run more than one AI coding CLI at a time, and usually across more than one repo. Claude
Code in one pane, Codex in another, Cursor's CLI somewhere else, all working, all waiting on
me at different moments. Before sloop, keeping track of which agent needed me meant tabbing
through a wall of terminal panes and reading scrollback to figure out if anything had actually
finished. That's the friction sloop exists to remove. It doesn't replace any of these tools or
proxy their models. It's a single, CGO-free Go binary that sits above them.

Three problems, specifically:

- **Agents scattered across terminals.** No single place to see what's waiting on you.
- **Per-tool instruction drift.** `CLAUDE.md` here, `GEMINI.md` there, each one slightly out of
  sync with the others.
- **Ad-hoc per-provider setup.** Every new CLI meant hand-rolling its own config again.

sloop is local-first on purpose: no daemon, no cloud, no bundled LLM. State stays on your
machine.

---

## The wedge: `sloop ps`

This is the command I open first every morning. It's a cross-repo fleet board: every agent
you're running, across every repo, in one view, with the ones waiting on you floated to the
top.

```sh
sloop ps
```

```text
  #  workspace   tool     status
  1  api         claude   waiting  "run the migration? (y/n)"
  2  web         cursor   waiting
  3  api         codex    working
  4  infra       gemini   working
  5  docs        claude   idle
```

sloop reads each waiting agent's question straight from its own tmux pane, no LLM call, no
API involved. From here you can move with `↑`/`↓`, jump into a session with `Enter`, reply
inline with `s`, or kill one with `x`. Add `-f`/`--watch` to keep it live with a bell on state
changes, or `--all` to also show idle registered workspaces.

I was skeptical this would beat just tiling tmux panes and reading them myself. In practice
the difference is triage: with five agents running, "which one actually needs me right now"
is a real question, and `sloop ps` answers it in one glance instead of five.

## Portable context: one `AGENTS.md`, not five

Before sloop, every tool wanted its own memory file, and they drifted. sloop's answer: write
`AGENTS.md` once, and it gets delivered to every tool, either natively (tools that already
read `AGENTS.md`) or via a thin pointer file (`CLAUDE.md` → `@AGENTS.md`, `GEMINI.md` →
`@AGENTS.md`) for tools that don't.

```sh
sloop init      # once per repo: creates AGENTS.md, .sloop/config.yaml, .sloop/skills/
sloop sync      # (re)deliver context to every detected tool; create-if-missing, never deletes
```

`sloop sync --repair` moves a conflicting file aside as `*.sloopbak` instead of overwriting
it. sloop never touches the `AGENTS.md` content itself, only how it's delivered.

Skills follow the same idea. A skill is a Markdown prompt or workflow in
`.sloop/skills/*.md`, symlinked into every tool's own skills directory. Write or import a
skill once, every CLI sees it.

```sh
sloop skills new code-review        # scaffold + symlink into every tool
sloop skills add <github-blob-url>  # import (auto-converts to raw)
sloop skills update                 # re-fetch imported skills
```

Imported skills are recorded in `.sloop/skills.lock` (name, source, content hash) so a team
gets reproducible skills, not "whatever version I happened to import."

## Launching an agent

```sh
sloop run claude              # sync, then launch Claude Code in a managed tmux session
sloop run codex -m o4 -e high # pick a model and effort level
sloop run --split              # coder + reviewer, side by side in one pane
```

Each session is named `<workspace>__<tool>`, one session per agent, so `claude@review` for a
second Claude instance in the same repo is just another named session. The model string is
forwarded as-is and never validated. If a model alias is wrong, the underlying CLI is the one
that tells you, not sloop.

## Adapter manifests: adding a CLI is adding a file

The rule sloop holds itself to: every piece of per-provider knowledge, how to detect a tool,
how to launch it, how it reads context, how its hooks install, lives in one declarative YAML
manifest under `internal/adapter/builtin/<tool>.yaml`. No feature in the codebase hardcodes a
tool's name. Adding support for a new AI CLI means writing one manifest, not editing Go.

User overrides or brand-new tools go in `~/.sloop/adapters/<tool>.yaml`; the same key
overrides a built-in value, a new key adds one. Verify a manifest with:

```sh
sloop tools                # capability matrix across every known CLI
sloop hooks print codex    # show how to wire hooks for a tool by hand
```

## Where I hit a real limit: hook install strategies

Status detection is precise when a tool's own hooks are installed, and only a heuristic
fallback otherwise (matching things like `(y/n)` prompts or `esc to interrupt` banners in
`internal/tmux/status.go`). Claude Code and Gemini CLI auto-install hooks by merging their
JSON settings idempotently; Cursor gets its own flatter `.cursor/hooks.json` writer. Copilot
and Codex don't have an auto-installer yet. Their hook configs need per-OS shell matchers
(Copilot) or single-payload routing through one TOML `notify` field (Codex), and I didn't want
to guess at a matcher model that might clobber a user's existing hooks. So today those two are
copy-paste instructions from `sloop hooks print`, not an automatic install. It's an honest gap,
not a hidden one: `sloop ps` for those tools falls back to heuristics until that's solved.

## Architecture, briefly

One Cobra binary, no daemon, no gRPC, every command runs to completion over plain files plus a
local SQLite database (`~/.sloop/sloop.db`, WAL mode). `AGENTS.md` and `.sloop/config.yaml` /
`.sloop/skills/` are meant to be committed; `.sloop/vault/` is gitignored. The multiplexer is a
seam, not a hard dependency: tmux today, psmux on native Windows, `SLOOP_MUX` to override, and
plain `sloop run` still works with no multiplexer at all (you just lose `ps`, `send`, and the
rest of the orchestration commands).

Provider-respecting is a hard rule, not a slogan: sloop never intercepts a tool's API calls or
injects into its process, it only reads a tool's own hooks or non-invasive signals like
`tmux capture-pane`.

## Install

```sh
brew install stroops/tap/sloop
# or
go install github.com/stroops/sloop/cmd/sloop@latest
```

```sh
sloop doctor      # verify detected tools + multiplexer
sloop update      # upgrade via however you installed it
```

## What's next

Current release is v0.1.2. The five pillars (launch, portable context, skills, cross-repo
fleet, hooks) are either shipped or shipping incrementally; v0.2.0 turns hooks from
status-reporting into a portable workflow-automation library, format-on-edit, commit-policy,
shell-guard, prompt-rule, authored once and installed into whichever tool's own hook config
actually needs it. That one is security-sensitive, so it gets a design doc
(`docs/design/hooks.md`) before any code.

If you're already juggling more than one AI CLI across more than one repo, `sloop ps` is the
single command worth trying first:

```sh
sloop init
sloop run claude
sloop ps
```

sloop is open source under MIT at
[`github.com/stroops/sloop`](https://github.com/stroops/sloop).
