Three autonomous coding agents — Bob, Kevin, and Stuart — that form a complete development pipeline. They run in Apple Containers, use Codex CLI as their coding engine, and interact with GitLab through its API.
Each agent has a "brain" — a Git repository (rules) containing its tasks, guardrails, memory, and configuration. The operator defines tasks, and the agents execute them autonomously within strict permission boundaries.
Inspired by Minions: Stripe's one-shot, end-to-end coding agents — but built as a scrappy, self-hosted alternative using shell scripts, Docker containers, and Codex CLI instead of a large internal platform.
The key insight: autonomous agents need structure (tasks, permissions, memory) more than they need sophisticated frameworks. A well-designed rules repo gives an LLM everything it needs to operate safely.
┌─────────────-┐ ┌────────────-─---─┐ ┌──────────────┐
│ Bob │ │ Kevin │ │ Stuart │
│ (Analysis) │────▶│ (Implementation) |────▶│ (Review) │
└──────┬───────┘ └──────┬──────---─-┘ └──────┬───────┘
│ │ │
│ creates issues │ writes code │ reviews MRs
│ │ creates MRs │ approves/feedback
▼ ▼ ▼
┌────────────────────────────────────────--─────────────┐
│ GitLab API │
└──────────────────────────────────────────--───────────┘
- Analyzes code and creates GitLab issues
- Output: issue drafts in
output/<ID>/issue.md - Safety: issues only created after MR approval
- Single-run: processes one task, then exits
- Takes GitLab issues and resolves them with code
- Auto-syncs assigned issues from GitLab into his task list
- Creates branches, implements changes, opens MRs
- Two-phase approval: rules MR first, then code MR
- Responds to review feedback by re-running Codex
- Reviews open MRs targeting
develop - Auto-syncs open MRs from GitLab into his task list
- Autonomy rules: small MRs → acts alone, large MRs → requires approval
- Runs as a daemon during working hours (Mon-Fri 7:00-18:30)
- Produces structured reviews (
review.json+review.md)
Each agent has a rules/ directory that serves as its centralized brain:
rules/
├── AGENTS.md # Operating instructions (the agent reads this first)
├── GUARDRAILS.md # Permissions, prohibited actions, workflow
├── TASKS.md # Task queue with priorities and status
├── REPOSITORIES.md # Known repos with access levels
├── MEMORY.md # Persistent memory across sessions
├── output/ # Task deliverables (issues, reports, reviews)
├── logs/ # Structured activity log (JSONL)
└── docs/ # Operator-provided context (Bob only)
This pattern means the agent's "intelligence" lives in Git, not in the container. You can review what it knows, what it's done, and what it's allowed to do — all through merge requests.
minions/
├── bob/
│ ├── agent/ # Container + orchestration
│ │ ├── .env.example
│ │ ├── container/
│ │ │ ├── Dockerfile
│ │ │ ├── entrypoint.sh
│ │ │ └── agent.sh
│ │ └── README.md
│ └── rules/ # Bob's brain
├── kevin/
│ ├── agent/
│ │ └── ...
│ └── rules/
├── stuart/
│ ├── agent/
│ │ └── ...
│ └── rules/
├── README.md
└── LICENSE
- Docker or Apple Containers
- A GitLab instance (self-hosted or gitlab.com)
- A Codex-compatible API (OpenAI, or a proxy like codex-proxy)
- GitLab personal access tokens for each agent
Copy .env.example to .env for each agent and fill in your values:
cp bob/agent/.env.example bob/agent/.env
cp kevin/agent/.env.example kevin/agent/.env
cp stuart/agent/.env.example stuart/agent/.envEach agent needs its own rules repository on your GitLab instance. Push the contents of each rules/ directory:
cd bob/rules && git init && git add -A && git commit -m "init" && git remote add origin <your-url> && git push -u origin master# Build
container build -t bob:latest bob/agent/container/
container build -t kevin:latest kevin/agent/container/
container build -t stuart:latest stuart/agent/container/
# Run (each agent processes tasks independently)
container run --rm --env-file bob/agent/.env bob:latest
container run --rm --env-file kevin/agent/.env kevin:latest
container run --rm --env-file stuart/agent/.env stuart:latest- Define tasks — Add entries to an agent's
TASKS.md(or let Kevin/Stuart auto-sync from GitLab) - Agent runs — The container starts, clones its rules repo, picks the highest-priority pending task
- Codex executes — The agent builds a prompt with full context and runs Codex CLI
- Human reviews — The agent creates MRs for approval before taking irreversible actions
- Feedback loop — If the reviewer comments, the agent re-runs Codex with feedback and pushes revisions
- Completion — Once the MR is merged or closed, the agent updates its task status and exits
- Shell scripts over frameworks: The agents are ~500-900 line bash scripts. No Python, no LangChain, no agent framework. Shell is universal in containers, easy to debug, and keeps the moving parts visible.
- Git as state: All agent state (tasks, memory, output) lives in Git repos. This gives you version history, merge request workflows, and familiar tooling for free.
- Approval gates: No agent can take irreversible actions (creating issues, pushing code, approving MRs) without human approval via merge request. The rules repo pattern makes this natural.
- Codex CLI: Using
codex execgives each agent a full coding environment with file access, not just chat. The--dangerously-bypass-approvals-and-sandboxflag is intentional — the container IS the sandbox.
- codex-proxy — Lightweight proxy that lets Codex CLI work with any OpenAI-compatible API. Used to route agents through a custom model provider.
- theo — Theo manages the lifecycle of these agents: scheduling runs, monitoring health, and providing an interface for the operator.
MIT