π VibeCoder
Create GitHub issues from your phone, get PRs (Pull Requests) automatically, review and request fixes with a thumbs up.
VibeCoder is an automated GitHub issue worker driven by a coding-agent CLI. It monitors your repositories, picks up issues, writes code, runs quality checks, and opens pull requests β all without you touching a keyboard.
It is provider agnostic: claude
(Claude Code) is the default,
and codex (the OpenAI Codex CLI), gemini (the Gemini CLI) and deepseek
(DeepSeek, served through the Claude Code CLI) are built in and chosen by
configuration β see Choose your coding agent.
π How It Works
sequenceDiagram
actor You
participant Worker as π€ VibeCoder Worker
participant Agent as π§ Coding agent
participant GitHub as π GitHub
You->>GitHub: Create issue (from phone)
GitHub->>Worker: Detect & self-assign
Worker->>Worker: Create feature branch
Worker->>Agent: Work on issue
Agent->>Worker: Code changes
Worker->>Worker: Run quality checks
Worker->>GitHub: Create PR
GitHub->>You: PR appears for review
You->>GitHub: Leave feedback (thumbs up)
GitHub->>Worker: Fix feedback & push
Worker->>Agent: Apply feedback
Agent->>Worker: Updated code
Worker->>GitHub: Updated PR ready
You->>GitHub: Approve & merge
π Choose your coding agent
The coding agent is a separable layer β every workflow above is the worker's, not the vendor's, so swapping the agent changes which CLI writes the code and nothing else. Four providers are built in:
| Provider id | Agent | Credential file |
|---|---|---|
claude (default) |
Claude Code | claude/provider.env |
codex |
Codex CLI | codex/provider.env |
gemini |
Gemini CLI | gemini/provider.env |
deepseek |
DeepSeek (Claude Code CLI) β Anthropic's CLI pointed at DeepSeek's Anthropic-compatible endpoint | deepseek/provider.env |
deepseek is the one row that needs a word of explanation: DeepSeek ships no
CLI of its own, so the provider installs Anthropic's CLI under the deepseek
command and points it at https://api.deepseek.com/anthropic. Its credential
is therefore a DeepSeek key, and Anthropic's own credentials are withheld
from it β no vendor's secret reaches another vendor's agent.
One credential file per vendor is the rule, with one optional exception: a host
holding several Claude subscriptions may add claude/provider-2.env,
provider-3.env and so on by hand, and each run starts on whichever of them
has the most budget left, naming its choice in the startup log. Nothing changes
for a host with a single credential
(Several Claude tokens).
Select one with the agent_provider key in .config.json:
{
"agent_provider": "codex",
"agent_providers": ["codex"]
}
Mixed Claude/Codex hosts can opt into quota-aware selection before each work item. Only credentials proved to be fixed-price subscriptions are candidates; API-key and unknown-billing accounts are never selected:
{
"agent_provider_mode": "auto",
"agent_provider": "claude",
"agent_providers": ["claude", "codex"]
}
In auto mode, agent_provider is the preference tie-break. An explicit
per-invocation provider remains absolute, and VIBE_AGENT_PROVIDER can pin an
enabled provider for that process. If every eligible subscription is exhausted
or unavailable, the worker waits instead of falling through to metered usage.
agent_providers lists every provider enabled for a run: each gets its own
credential file, its own startup preflight and its own read-only container
mount, so no vendor's secret reaches another vendor's agent. It must include
the active provider. VIBE_AGENT_PROVIDER and VIBE_AGENT_PROVIDERS
(comma-separated) still select a provider on a host whose configuration file
names none, but they no longer override the file β the file wins, as it does
for every other setting
(1.4.0).
An id that is set but not registered fails loudly at startup with the supported ids named β the worker never silently falls back to the default and runs an agent you did not choose.
The default container image installs Claude Code alone, and the launcher builds
the image with whatever agent_providers lists β it passes the set as
--build-arg AGENT_PROVIDERS and mixes it into the image tag, so a Codex-only
host builds and runs a Codex image rather than reusing the default one.
- Container Image β the coding-agent provider layer β how the seam works, what the image installs, and how to add the next provider.
- Configuration Reference β the provider-selection keys in full.
- Setup Guide β provisioning each vendor's credentials.
- Quorum β running several providers at once, so two agents draft a plan and a third judges it.
- Model Selection, Sessions & Caching β provider applicability β which documented model, session and caching behaviours you still get under each provider, and what the others do instead.
β¨ Key Features
- Issue-to-PR pipeline β Write an issue, get a PR. The worker handles branching, coding, testing, and PR creation.
- Review feedback loop β Leave comments on the PR, thumbs-up to trigger fixes. The worker responds to feedback and pushes updates.
- Clarification & refinement β If the issue is unclear, the worker asks questions before starting. You can also refine issues collaboratively.
- Planning mode β Add the
planninglabel to get task breakdowns and sub-issues instead of direct implementation. - Question answering β Add the
questionlabel to get answers about the codebase without implementation. The worker reads the issue and comments, posts an answer, removes thequestionlabel, and addsneeds-humanto signal it is your turn. Addquestionagain to ask a follow-up. - Spelling auto-fix β Failed spelling checks on PRs are automatically corrected.
- CI failure auto-fix β Failed CI (Continuous Integration) or integration checks on open PRs are automatically diagnosed and fixed.
- Idle-task framework β When no claimable work exists, the worker files a
lowest-priority
idle-taskissue and runs one of the registered background templates (security, best-practices, test-audit, dependency, and documentation scans, among others), picked at random. Seedocs/IDLE-TASK-FRAMEWORK.mdfor the full catalogue. - Security scans β When the worker has no claimable work, it idle-runs a
four-phase security scan against the least-recently-scanned monitored repo and
files findings as
security-labelled issues. Seedocs/SECURITY-SCAN.mdfor the operator manual. - Priority-based work queue β PR feedback first, then spelling fixes, CI failure remediation, branch updates, auto-merge, branch cleanup, issue closure, milestone completion (with tracking issue), issue refinement, question answering, planning, then new issues (globally oldest across repos).
- Cost optimisation β Phase-based model selection (Opus 5.5 for complex work, with effort as the main lever; Haiku for routine tasks β see Model, Caching & Batching for the full routing rationale), SHA-based prompt compilation cache, prompt structure optimisation for Claude prompt caching, and per-issue token usage tracking. (The Anthropic Batch API was evaluated but deliberately not wired in β its async turnaround is incompatible with the worker's bounded interactive run; see Model, Caching & Batching.)
- Post-run callbacks β Optional
success/failure/alwaysexecutables run after a terminal issue run, plus an optionalcycleheartbeat at the end of every scan loop and an optionalhost_failurehook the host launcher runs while a host-level failure persists, following thesuccess / failure / alwaysoutcome semantics familiar from CI pipelines. The public extension point for fleet-specific reporting; a hook failure never rewrites the run's own result. The contract β ordering, the versioned context, the security boundary, portable examples and a conformance fixture an extension can run against its own hooks β is Post-Run Callbacks. - Per-repo configuration β Operator-side
repo_configin.config.jsoncustomises worker behaviour per repository (e.g., skip screenshots for CLI-only projects). Configuration is operator-side only β target repos carry no worker configuration. - Milestone enhancements β Progress notifications, configurable issue ordering within milestones, periodic branch sync with the default branch, automatic roll-back of a stuck milestone branch (reverted children are reopened and re-queued; a roll-back with nothing left escalates once), with a rebuild from the base tip first once a roll-back has already been spent on the branch (Issue #4328), and milestone health diagnostics.
- Self-healing β Shadow-copy execution, automatic repo resets, disk cleanup, failure recovery, rate-limit handling, and crash resilience keep the worker running unattended. See Resilience & Concurrency for the full behaviour.
- Safe by default β Only processes issues from allowed authors with configured labels.
- Extendable β Add new functionality via Deno/TypeScript commands without modifying shell scripts.
π‘οΈ Quality and control (for managers and tech leads)
The Vibe Coder is a fast, capable assistant β but nothing goes to the default branch (prod) without your review. No rogue merges, no surprises. Same as for human developers: every change arrives as a PR; you review, request fixes, and approve before merge. The "loss of control" worry is addressed by design: the worker never bypasses your gates.
flowchart LR
subgraph worker ["π€ Worker"]
W1["TDD, KISS, DRY"]
W2["Opens PR"]
W3["Runs quality.sh"]
W1 --> W2 --> W3
end
subgraph gate ["π‘οΈ Your gate"]
R["Review & approve"]
end
subgraph result ["β
Result"]
D[(Default / prod)]
end
worker --> R --> D
style gate fill:#2d6a4f,stroke:#1b4332,color:#fff
style result fill:#40916c,stroke:#2d6a4f,color:#fff
Productivity with quality: The worker is told to follow TDD (Test-Driven
Development), KISS (Keep It Simple), DRY (Don't Repeat Yourself), and
the rest of the playbook β and every PR runs the full quality gate
(./quality.sh: deno test, deno lint, deno check, deno fmt --check,
and semgrep over the changed files).
Have your cake and eat it too: more throughput, same (or better) gates. Full
coding standards: Coding Standards.
Note for team leads and managers: The productivity gains are real, but you are now deploying code that you didnβt write and may not fully understand. Thatβs why the review gate exists: treat every PR as code youβre taking ownership of. Review, ask for changes, and only merge when youβre comfortable maintaining what lands on the default branch.
π Quick Start
macOS / Linux
# Clone the repository
gh repo clone <your-org>/VibeCoder
cd VibeCoder
# Configure via environment variables (when run in a terminal, setup may optionally prompt for service-account paths)
VIBE_ALLOWED_AUTHOR=myusername \
VIBE_REPOS="myorg/repo1,myorg/repo2" \
./setup.sh
# Start the worker
./run.sh
# Move this host onto the newest release (setup pins a new host to a release;
# a frozen host logs a WARNING at each launch when a newer one exists). Rewrites
# the pins in .config.json and nothing else β the next launch installs exactly them.
./run.sh upgrade
See Configuration β The upgrade loop for the notice, what the command changes, and the hand-edited pin.
Windows (PowerShell)
# Clone the repository
gh repo clone <your-org>/VibeCoder
cd VibeCoder
# Configure (same environment variables)
$env:VIBE_ALLOWED_AUTHOR = "myusername"
$env:VIBE_REPOS = "myorg/repo1,myorg/repo2"
.\setup.ps1 # PowerShell only β no bash, WSL or Git Bash needed
# Start the worker
.\run.ps1
setup.ps1 is the twin of setup.sh: it delegates every
platform-neutral step to the same Deno setup CLI and adds only the interactive
layer β the prompts, the credential flow (gh identity copy plus
claude setup-token, each proven with a live call), and the offer to register
the Task Scheduler entry that replaces the macOS LaunchAgent. Missing host
tools are offered one at a time via winget. A parity test compares the two
scripts, so neither can quietly drop a setup step the other keeps.
That is the whole deployment story: git clone β configure credentials and
repos β ./run.sh (or run.ps1). From then on the machine operates
unattended β it self-heals, rebuilds its container when the definition changes,
and is steered entirely through GitHub.
π‘ An unattended appliance, controlled through GitHub
A Vibe Coder host is an appliance, not a workstation. The worker runs inside a least-privilege container that sees four explicit host mounts, two named volumes, and no other host data (Containment). The trade is deliberately asymmetric β generous resources, strict boundary: inside the container the worker gets all the memory, CPU and disk the host can give (it is sized to the host, not rationed), while the boundary around it is absolute (see Design Principles). GitHub is the sole normal remote control plane: issues, comments, labels, repositories, commits and pull requests. Humans steer the worker by labelling and commenting; the worker reports progress, escalations and crashes the same way.
SSH, Remote Desktop, screen sharing, a management UI and terminal access to
the host are not required for normal operation. No inbound port is opened.
Local logs (the host log directory) remain useful for diagnosis, and a failure
inside a run is still reported through GitHub. A host-level failure β the
launcher crash-looping, the checkout update failing run after run β happens
before any issue is claimed, so it is reported through the deployment's own
callbacks.host_failure hook,
or, when none is configured, to the host log and the self-heal events. It is
never filed as an issue on a public repository.
For production, run via cron (macOS/Linux) or Task Scheduler (Windows) every 5 minutes:
# Linux (cron) β on macOS use ~/Library/Logs/vibe-coder/cron.log
*/5 * * * * /path/to/VibeCoder/run.sh >> ~/.local/state/vibe-coder/cron.log 2>&1
See the Deployment Guide for systemd, launchd, Task Scheduler, and other options.
ποΈ Architecture
The worker uses a thin launcher + Deno TypeScript architecture. Entry points are minimal shell/PowerShell scripts that delegate to Deno for all business logic. Cross-platform: macOS, Linux, and Windows.
run.sh and run.ps1 launch the worker inside the
container image: both ask the same Deno container-launch-plan command what to
run, so the mounts and privilege flags are identical on every host. Containment
is mandatory (Issue #4): container is the only run mode β the former native
and macOS seatbelt opt-ins were removed, a run_mode (or VIBE_RUN_MODE)
that still names one fails loud with the removal explained, and a missing container runtime is a
loud failure with no host fallback. See
Container Image for the mount set and privilege flags,
Containment for the boundary, and
Configuration for the setting.
graph TD
A["π¦ run.sh / run.ps1 β Thin launcher (cron/launchd/Task Scheduler)"]
C["π³ vibe-coder container β least-privilege mounts, no host access"]
B["π Deno run-entrypoint β Worker driver (PID guard β bootstrap β housekeeping β loop)"]
D["π¦ worker/deno/ β All business logic (commands, libraries, tests)"]
A -->|run container| C -->|exec deno| B --> D
style A fill:#2d6a4f,stroke:#1b4332,color:#d8f3dc
style C fill:#1b4332,stroke:#081c15,color:#d8f3dc
style B fill:#40916c,stroke:#2d6a4f,color:#d8f3dc
style D fill:#74c69d,stroke:#52b788,color:#081c15
The thin launcher execs Deno directly on the run-entrypoint command β there
is no bash on the runtime path, so the worker runs natively on Windows
. Because Deno loads its modules at process start, the running
driver is immune to any mid-run change to the checkout β the same property the
old worker/.run_core.sh shadow-copy provided.
Resilience features: The worker is built to run unattended β a host-side update of the checkout to the default branch before each launch (with the driver immune to it), shallow clones with on-demand history deepening, repo self-healing and startup sweeps, two-tier disk cleanup, PID locking, time-limited runs, timeout wrappers, rate-limit awareness with model fallback, crash-surviving failure state, and multi-worker coordination. For the full detail see Resilience & Concurrency, Worker Internals, and Lessons learnt.
π Requirements
The worker runs inside the container image β container is the default and
the only run mode (Issue #4) β so the host needs a container runtime and the
launcher, not the worker's toolchain: