Skip to content

muxso/Shepherd

Repository files navigation

Shepherd 🐑

Let AI write the code; you stay in charge of what ships.

Rust License status   ·   简体中文 | English

Shepherd is an early-stage platform for supervising AI-driven development. The idea is simple: AI can write code now, but it won't judge whether it actually finished the requirement, and it won't be accountable for the result. So instead of building yet another "smarter agent," Shepherd is the layer around the agent — it breaks requirements down for AI executors to work on, then puts a human approval step at two points (design and verification), and keeps a record of the whole thing.

Status: v0.0.1, experimental, and something we currently dogfood ourselves. The full loop works, but it's not production-ready and there's no public benchmark. Don't treat it as a finished tool.

How it works

A requirement roughly travels like this:

you file a requirement → AI drafts a design →(you approve)→ split into a task DAG → internal executors claim and work
                                                                                              │
you sign off ←(verification gate)← adjudication ← deliverable (diff / PR) ←────────────────────┘

The design gate and the verification gate are hard steps in the flow, not optional prompts. However fast the AI runs, nothing reaches your main branch until it clears a gate. That's basically the problem Shepherd is trying to solve: letting you put AI to work at scale because the output is reviewable and accountable.

Why the fleet pulls instead of being pushed to

This is the part of the project I find most interesting.

The AI tools in a company (Claude Code, Codex, and friends) usually run on internal dev machines or CI — boxes with no public inbound. The server, on the other hand, has a public address. So the server can't push work to an executor; it has to be the other way around: executors reach out and long-poll to claim work. Plenty of orchestration frameworks assume they can reach the agent, and that assumption falls apart on a real internal network.

  • Single host: an in-process queue is enough, no external dependencies.
  • Multiple hosts: set SHEPHERD_FLEET_REDIS to switch to Redis Streams consumer groups — exactly-once claim, ack on terminal state, and timeout-based reclaim when an executor dies.

The executor itself (agent-runtime) is plain Rust: concurrency is bounded by a semaphore, it drains in-flight tasks on shutdown, and each task runs in its own git worktree so they don't step on each other. GET /agent/work/stats shows per-capability backlog, in-flight, and oldest-stuck. Adding a new kind of executor means implementing one CliAgentBackend (a single execute(prompt, cwd, sink) method) and registering an enum variant.

        (public)                            (internal, no inbound)
 ┌────────────┐  enqueue ┌──────────────┐  ←claim─ ┌──────────────────┐
 │  Shepherd  │─────────▶│  WorkQueue   │          │  agent-runtime   │
 │   server   │          │ in-mem/Redis │  ─spec→  │  spawn claude /  │
 │ (dispatch/ │◀─────────│  Streams grp │          │  codex / opencode│
 │   gates)   │ callback └──────────────┘ register/└──────────────────┘
 └────────────┘                           heartbeat per-task worktree isolation

Running it

# 1) A Postgres; migrations are applied automatically on startup
docker run -d --name shep-pg \
  -e POSTGRES_USER=msuser -e POSTGRES_PASSWORD=mspass -e POSTGRES_DB=mstest \
  -p 55432:5432 postgres:16-alpine

# 2) Start the server (the root sets default-members, so plain `cargo run` works)
DATABASE_URL=postgres://msuser:mspass@localhost:55432/mstest \
SHEPHERD_ADMIN_PASSWORD=s3cret \
cargo run                       # → http://localhost:8088
# Log in for a token
curl -s localhost:8088/auth/login -H 'content-type: application/json' \
  -d '{"username":"admin","password":"s3cret"}'

The web console, and starting an executor on an internal machine:

cd web && npm install && npm run dev          # Vite console

SHEPHERD_AGENT_FLEET=1 cargo run              # server in fleet mode
SHEPHERD_BASE=http://<server>:8088 SHEPHERD_CAPS=CLAUDE_CODE cargo run -p agent-runtime

Prefer one command? docker compose -f deploy/docker/docker-compose.yml up --build brings up the whole stack (server + agent-runtime + web + Postgres + Redis) — see the usage guide and deployment guide.

What's in here

Each business module is its own crate, laid out hexagonally: domain / ports / application are pure logic with no IO by default, while the database and HTTP live in adapters behind feature flags. tests/architecture.rs scans the source and fails the build if a pure layer ever imports an IO crate like sqlx or axum — that keeps the layering from quietly eroding over time.

Working today: auth / RBAC / OIDC (Feishu, WeCom), projects, versioned requirements, the task DAG, the design approval gate, fleet dispatch and reclaim, MCP tools (POST /mcp), Skill orchestration, plus a test-management suite (cases / bugs / plans / API and scenario tests / Mock).

Not done yet: the verification gate is still heavier to use than I'd like; shepherd-cli is half-built; finer fleet metrics (e.g. claim-latency distribution) aren't there; and more executor backends (such as wiring OpenHands in as one) are on the list.

Full crate tree
crates/
  kernel/          shared kernel (pagination / PermissionSet)
  webauth/         shared auth primitives (AuthUser / SessionStore + axum extractors)
  system-setting/  users · orgs · roles · auth (local + OIDC)
  project/  requirement/  task/  orchestrator/    project · requirements (versioned) · task DAG · orchestration
  design/          design stage (OpenSpec/BMAD, human approval gate)
  delivery/        AI executor dispatch & delivery + fleet queue
  agent-runtime/   pure-Rust executor (CLI spawn + event streaming + worktree isolation)
  verification/    integrity verification + verification gate
  mcp/  skill/     MCP tools + Skill orchestration
  case/ bug/ test-plan/ api-test/ api-scenario/   test management
  api-definition/ api-runner/ runner/ probe/ perf/ comment/ follow/ environment/ mock-runtime/ …
  migrate/         versioned migrations (sqlx migrate! + uniqueness guard)
  server/          composition root = the single binary (typed config + domain-grouped routes)
  shepherd-cli/    CLI (still being built)
web/               React + antd frontend
Main environment variables

Server (consolidated into a typed ServerConfig):

Variable Default Meaning
DATABASE_URL local mstest PG connection string
SHEPHERD_BIND 0.0.0.0:8088 main API listen address
SHEPHERD_ADMIN_PASSWORD admin admin password upserted idempotently on boot
SHEPHERD_AGENT_FLEET set to enable fleet mode
SHEPHERD_FLEET_REDIS set to use a Redis distributed queue / registry
SHEPHERD_FEISHU_* / SHEPHERD_WECOM_* OIDC third-party login

Executor agent-runtime:

Variable Default Meaning
SHEPHERD_BASE http://127.0.0.1:9180 server address
SHEPHERD_CAPS CLAUDE_CODE comma-separated capabilities (which tasks to claim)
AGENT_CONCURRENCY 1 max concurrent tasks
CLAUDE_BIN / CODEX_CMD / OPENCODE_CMD claude / codex exec / opencode run each CLI invocation
AGENT_MOCK set to use the mock backend (no real CLI)

Documentation

How it compares

vs. agent harnesses — Claude Code, Codex, OpenCode, OpenHands, Aider. A harness wraps an LLM and runs the agentic loop (tools, context, turn by turn) to get one task done well. Shepherd is the layer above that: it doesn't run the loop — it decides what the tasks are, dispatches them, gates them on human approval, and verifies they were actually done. The harness is a swappable executor: agent-runtime literally shells out to claude / codex / opencode and streams their events back. So OpenCode isn't a competitor — it's one of the executors you hang on Shepherd's fleet (OPENCODE_CMD=opencode run).

vs. multi-agent frameworks — AutoGen, CrewAI. Most take the autonomy route: let agents loop until done, compete on benchmarks. Shepherd's focus is governance — approval and verification are steps you can't route around, not prompts you interrupt in a chat, and the deployment model is a central server plus internal executors that pull work outbound. Those frameworks are the agent; Shepherd is the supervisor above swappable agents.

One concrete boundary: Shepherd speaks MCP as a server (it exposes shepherd_* tools so an agent can drive the requirement→verify lifecycle), while coding agents like OpenCode speak MCP as a client. They compose in both directions rather than overlap.

Tests

cargo test --workspace                      # everything; non-integration runs in seconds
cargo test --workspace -- --ignored         # real-database integration tests

866 tests; the integration ones run against a real server + PG / Redis / MySQL. Besides the architecture guard there's a migration-uniqueness guard: a duplicate migration version number fails CI (sqlx silently drops duplicates — we hit that once and it cost us a missing-column 500).

More background in ARCHITECTURE.md, ROADMAP.md, and the fleet design notes.

Contributing

Issues and PRs welcome. A few conventions:

  • Follow the hexagonal layering: business logic in domain / application, IO in adapters, and no IO crates in the pure layers (tests/architecture.rs will catch it).
  • Include tests; cargo test --workspace and cargo clippy --workspace (-D warnings) need to be green.
  • New migrations use a unique, increasing version number: NNNN_description.sql.
  • Write commit messages that explain why, not just what changed.

License

GPL-2.0, see LICENSE.

About

Shepherd is a Rust-native development platform that supervises AI coding agents (Claude Code, Codex) and verifies requirement completeness—》HumanInTheLoop

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors