Architecture
System Overview
HerdOS has two halves: a local CLI (the Planner) and GitHub infrastructure (everything else). The CLI plans and dispatches. GitHub executes, tracks, and reports.
graph TD
subgraph Local["YOUR MACHINE"]
CLI["herd CLI (Planner)<br>Decomposes work<br>Creates issues<br>Dispatches workers<br>Monitors progress"]
end
subgraph Cloud["GITHUB"]
Issues["Issues<br>Work items with<br>labels & structure"]
Actions["Actions<br>Workers (agent)"]
BatchPR["Batch PR<br>Consolidated code<br>changes ready for review"]
Integrator["Integrator<br>Consolidate<br>Review & merge"]
Monitor["Monitor<br>(cron + on-demand)<br>Health monitoring"]
Milestones["Milestones<br>Batch tracking"]
Issues --> Actions
Actions --> BatchPR
BatchPR --> Integrator
Integrator ~~~ Monitor
Integrator ~~~ Milestones
end
subgraph RunnerEnv["YOUR MACHINE OR YOUR SERVER"]
Runner["Self-Hosted Runner<br>(optional)"]
end
CLI -->|GitHub API| Issues
Cloud ~~~ RunnerEnv
Data Flow
Default flow (plan, dispatch, land)
graph TD
A["User describes feature"] --> B["herd plan 'Add dark mode support'"]
B -->|"Interactive session: agent asks<br>questions, user refines, agent<br>produces plan"| C["User approves → creates GitHub Issues,<br>batch branch, dispatches Tier 0"]
C -->|"User walks away"| D["Workers execute on runners<br>Integrator consolidates worker branches<br>When a tier completes, dispatch next tier"]
D --> E["Cycle continues until all tiers done"]
E --> F["Batch PR opened, agent reviews,<br>human reviews (or auto-merge)<br>User notified"]
The entire flow after herd plan is self-driving. The Planner dispatches Tier 0 automatically, the Integrator advances tiers, and the user only intervenes if something fails or when the batch PR is ready for human review.
Review and Fix Details
Agent review collects /herd fix comments from the batch PR before reviewing, so user-requested fixes are not flagged as violations. It then classifies findings by severity (HIGH, MEDIUM, LOW). HIGH and MEDIUM severity findings trigger fix workers. LOW findings are included in the PR comment for reference but do not block merge or create fix issues.
Each review cycle creates at most one batch fix issue containing all HIGH findings, rather than one issue per finding. The agent submits a Request Changes review to block merge while fix cycles are active. When the review passes, the agent approves and posts a batch summary with statistics (files reviewed, findings by severity, fix cycles used).
Large PR review uses bounded diff input. HerdOS prefers local git diff data from the checkout, then falls back to GitHub raw PR diff, then to GitHub changed-file metadata and bounded patches when the raw diff is too large or unavailable. Generated, binary, very large, mode-only, or limit-exceeding file diffs may be omitted or truncated; HerdOS reports the diff source, included count, omitted count, truncated count, and affected paths/reasons when coverage is limited.
After Herd has posted an approved review result for a PR head SHA, later automatic review triggers for that same head skip the agent; a new commit or manual /herd review requests a fresh pass.
Workers run pre-push validation before pushing changes. For Go repositories, this includes go build, go test, go vet, and golangci-lint (if available); build and test disable Go VCS stamping. If validation fails, the agent is retried once with the error output. Workers post structured reports on their issues with files changed, a summary of work done, and validation results.
When the Integrator processes commands (Consolidate, Advance, AdvanceByBatch, CheckCI), it skips batches whose milestones are already closed, avoiding redundant work on completed batches.
Opening a batch PR is idempotent: if two concurrent integrator runs both attempt to create the PR, the second detects the existing one (via listing or by handling a 422 race) and returns the existing PR number.
The Integrator also guards against partial GitHub API responses: before opening the batch PR it verifies the milestone’s issue list is complete, and if the issue triggering an advance is not in any tier it treats the trigger as a no-op. Both cases log a warning and retry on the next advance rather than erroring or opening a premature PR.
Worker, Consolidate, PR flow
graph TD
A["Batch branch created from main"] --> B
subgraph B["Tier 0 — no dependencies"]
W1["Worker 1<br>Issue #42"]
W2["Worker 2<br>Issue #43"]
end
B --> C["Integrator consolidates<br>into batch branch"]
subgraph D["Tier 1 — dependencies done"]
W3["Worker 3<br>Issue #44<br>(depends on #42, #43)"]
end
C --> D
D --> E["Integrator consolidates<br>into batch branch"]
E --> F["Single PR: batch branch → main"]
F --> G["Agent reviews on the PR<br>(dispatches fix workers if needed)"]
G --> H["Human reviews (or auto-merge)<br>Issues closed, batch landed"]
Component Boundaries
Local (your machine)
| Component | Responsibility |
|---|---|
herd CLI | User interface. Plans work, creates issues, dispatches workers, shows status. |
| Planner logic | Work decomposition. Uses the configured agent locally to break features into issues. |
| Config | .herdos.yml — repo-level settings for workers, labels, runners. |
GitHub (cloud)
| Component | Implemented As | Responsibility |
|---|---|---|
| Work items | Issues + Labels | Track what needs doing, who’s doing it, what state it’s in. |
| Workers | Actions (workflow_dispatch) | Execute tasks. Each worker reads an issue, runs the agent in headless mode, pushes to a worker branch. |
| Integrator | Action (workflow_run + pull_request_review + issues) | Consolidate worker branches into batch branch, agent-review the result, open single batch PR, handle conflicts, merge after approval. |
| Monitor | Action (schedule + workflow_dispatch) | Health patrol. Detect stale issues, failed runs, stuck PRs. Triggered by cron and on-demand by workers on failure. |
| Batches | Milestones | Group related issues. Track delivery progress. |
Self-Hosted Runners
Workers need a runner with the agent CLI installed. Options:
- Self-hosted on your machine — free, uses your hardware
- Self-hosted on a cloud VM — scalable, costs money, good for teams
- GitHub-hosted runners — simplest setup, but need the agent CLI in the environment
The runner is where the agent actually executes. The Action workflow orchestrates the checkout, issue reading, and branch pushing around it.
What Runs Where
sequenceDiagram
participant Local
participant GitHub
participant Runner
Local->>GitHub: herd plan (Issues created, Tier 0 dispatched)
GitHub->>Runner: workflow_dispatch
Note over Runner: Worker starts<br>Agent runs<br>Commits pushed
Runner->>GitHub: pushes to worker branch
Note over GitHub: Integrator consolidates into batch branch<br>tier complete → dispatch next tier<br>all tiers done → batch PR opened<br>agent reviews on PR<br>batch PR merged → issues closed<br>Monitor patrols (cron or worker-triggered)
Local->>GitHub: herd status (reads Issues/PRs/Actions)
Key Design Decisions
- GitHub is the source of truth. No local database. All state lives in Issues, PRs, and Action logs.
- Event-driven, not polling. Workers trigger on
workflow_dispatch. Integrator triggers onworkflow_run. Monitor triggers onscheduleandworkflow_dispatch. No busy-waiting. - Workers are stateless. Each worker gets a fresh checkout of the batch branch, reads its issue, does work, and pushes to a worker branch. No persistent state between runs.
- The CLI is thin. It’s a GitHub API client that delegates to the configured agent for planning. All heavy lifting happens on GitHub.
- Fail-safe by default. Workers can’t push to main. All changes go through PRs. Branch protection enforced.
Abstraction Layers
HerdOS has two abstraction boundaries: the Platform (where work is tracked and executed) and the Agent (what does the thinking). Both are interfaces with swappable implementations.
graph TD
subgraph Top["CLI Commands (plan, dispatch, status)"]
CLI["Agnostic to both"]
end
subgraph Middle["Interfaces"]
AI["Agent Interface"]
PI["Platform Interface"]
end
subgraph Bottom["v1.0 Implementations"]
CC["Claude Code<br>OpenCode<br>Codex"]
GH["GitHub<br>(GitLab, Gitea — later)"]
end
Top --> AI
Top --> PI
AI --> CC
PI --> GH
The CLI does not hardcode GitHub API calls or agent invocations. All platform interactions go through a Platform interface. All agent interactions go through an Agent interface. Current implementations support GitHub plus Claude Code, OpenCode, and Codex agent providers. Other implementations can be added later without touching core logic.