A web-based orchestrator for Claude Code agents.
Welcome to vibe code hell.
Submit a feature spec, watch a Claude Code agent work through it step-by-step in your browser, answer its questions when it gets stuck, and end up with a merged PR. Litus handles the entire lifecycle ā from specification to CI green to merge ā so you can focus on the parts that actually need a human brain.
- Fully automated pipeline ā Describe a feature, hit start. Litus takes it from spec to merged PR without manual intervention ā specification, planning, implementation, code review, PR creation, CI monitoring, and merge all happen automatically.
- Epic decomposition ā Got a feature too big for a single pass? Submit it as an epic. Litus breaks it into individual specs with dependency tracking and runs them in the right order, parallelizing where possible.
- Human-in-the-loop when needed ā When the agent hits ambiguity, Litus detects the question and surfaces it in the UI. You answer, it resumes. Everything else runs hands-off.
- CI-aware ā Litus monitors GitHub Actions after PR creation. If CI fails, the agent reads the failure logs and fixes the issue ā no copy-pasting error output into a chat window.
- Git worktree isolation ā Every workflow runs in its own worktree. Your main branch stays clean, and multiple workflows can run in parallel without conflicts.
- Observable and configurable ā Real-time agent output streaming, periodic progress summaries, and per-step configuration for models, effort levels, prompts, and retry limits.
- Max plan justifier ā Finally a reason to upgrade to the Claude Max plan. Your unlimited-feeling usage won't feel so unlimited after a few epics.
| Tool | Why |
|---|---|
| Bun >= 1.3.11 | Runtime. Fast, TypeScript-native, no transpilation ceremony. |
| Claude Code | The CLI agent that does the actual work. Must be installed and authenticated. |
GitHub CLI (gh) |
PR creation, CI monitoring, merge operations. Must be authenticated with permission to merge PRs without reviews. |
| uv | Python package runner. Required so Litus can auto-install speckit skills into target repos that don't have them yet. Pre-installed in the Docker image. |
Litus runs Claude Code agents against a target repository ā the repo where you want code changes to happen. Before starting your first workflow, make sure the target repo is set up:
- Authenticate
ghā Rungh auth loginand make sure the CLI has access to the target repo. Litus usesghfor PR creation, CI polling, and merge. - Authenticate Claude Code ā Run
claudeonce in the target repo to ensure the CLI is authenticated and working. - Verify git access ā Litus creates worktrees inside the target repo. Make sure you have push access and the repo is cloned (not a shallow clone).
Note
Litus relies on speckit skills in the target repo. If they're missing, Litus
auto-installs them via uvx during setup ā just make sure uv is available on your PATH. In the Docker image,
this is already taken care of.
Caution
Litus runs Claude Code with --dangerously-skip-permissions, meaning the agent can read, write, and delete files
without asking. It also creates PRs and merges them to your main branch automatically. This can introduce bugs into
production systems or cause data loss. Only run Litus in sandboxed environments or against repositories where you
are comfortable with autonomous, unsupervised changes.
# Clone
git clone https://github.com/s-gehring/litus.git
cd litus
# Install dependencies
bun install
# Build client + start server with hot reload
bun run devOpen http://localhost:3000. Override with the PORT env var.
For production (client must be pre-built):
bun run startA pre-built image is published to GitHub Container Registry on every release.
docker run -d \
-p 3000:3000 \
-e ANTHROPIC_API_KEY \
-e GH_TOKEN \
-v litus-data:/home/litus/.litus \
-v /path/to/your/repo:/home/litus/repos/my-project \
ghcr.io/s-gehring/litus:latestLitus runs Claude Code agents against a target repository ā the repo where code changes happen. You must bind-mount each target repo into the container so the agent can access it:
-v /path/to/your/repo:/home/litus/repos/my-projectThe container path you choose (e.g. /home/litus/repos/my-project) is what you'll select in the Litus UI when starting
a workflow. You can mount multiple repositories:
-v ~/projects/frontend:/home/litus/repos/frontend \
-v ~/projects/backend:/home/litus/repos/backendThe container ships with Claude Code CLI installed globally. It needs valid credentials to call the Anthropic API.
Option A ā API key (recommended for containers)
Pass your key as an environment variable:
docker run -d \
-e ANTHROPIC_API_KEY="sk-ant-..." \
-e GH_TOKEN="ghp_..." \
-p 3000:3000 \
-v litus-data:/home/litus/.litus \
-v /path/to/your/repo:/home/litus/repos/my-project \
ghcr.io/s-gehring/litus:latestOption B ā Mount an existing Claude session
If you have already authenticated with claude on the host, bind-mount the credentials directory instead of
setting ANTHROPIC_API_KEY:
docker run -d \
-e GH_TOKEN="ghp_..." \
-v ~/.claude:/home/litus/.claude \
-p 3000:3000 \
-v litus-data:/home/litus/.litus \
-v /path/to/your/repo:/home/litus/repos/my-project \
ghcr.io/s-gehring/litus:latestNote
Mounting ~/.config/gh does not work for GitHub CLI authentication ā most gh installations store
the token in the OS keyring rather than in config files. Always use the GH_TOKEN environment variable.
| Variable | Default | Description |
|---|---|---|
ANTHROPIC_API_KEY |
ā | API key for Claude Code CLI (required unless you mount ~/.claude) |
GH_TOKEN |
ā | GitHub personal access token for gh CLI (required). GITHUB_TOKEN is also accepted. |
PORT |
3000 |
HTTP server listen port (inside the container) |
| Path | Purpose |
|---|---|
/home/litus/.litus |
Workflow state, epic definitions, app config, and audit logs. Mount a named volume or bind mount to persist data across container restarts. |
/home/litus/repos/<name> |
Target repository bind mounts. Mount one or more repos so the agent has something to work on. |
/home/litus/.claude |
Optional. Bind-mount an existing Claude Code session directory instead of using ANTHROPIC_API_KEY. |
The entrypoint automatically creates the required subdirectories (workflows/, audit/) and fixes ownership on bind mounts.
mkdir -p ./litus-data
docker run -d \
-e ANTHROPIC_API_KEY \
-e GH_TOKEN \
-p 3000:3000 \
-v ./litus-data:/home/litus/.litus \
-v ~/projects/my-app:/home/litus/repos/my-app \
ghcr.io/s-gehring/litus:latestNote
The container runs as a non-root user (litus, UID 1001). The entrypoint uses gosu to fix volume
permissions before dropping privileges ā no manual chown needed.
- You enter a feature spec in the browser and hit Start
- Litus creates a git worktree and spawns
claude -p <spec> --output-format stream-json - The agent works through the pipeline: specify ā clarify ā plan ā implement ā review ā PR ā CI ā merge
- When the agent asks a question, it's surfaced in the UI ā you answer, the session resumes
- When CI fails, the agent reads the logs and tries to fix it (up to your configured limit)
- When everything's green, Litus squash-merges the PR and cleans up
![]() |
![]() |
| Epic decomposition with dependencies | Creating a new specification |
![]() |
![]() |
| Pipeline in progress with live output | Agent asking a question |
Litus orchestrates a 13-step pipeline. Each step is either handled by Litus itself or delegated to a Claude Code agent.
| Step | Actor | What happens |
|---|---|---|
| Setup | Litus | Validates repo, git, GitHub CLI, auth, speckit skills |
| Specify | Claude | Formalizes your description into a structured spec |
| Clarify | Claude + Human | Resolves ambiguities in the spec |
| Plan | Claude | Creates a technical design |
| Tasks | Claude | Generates a task checklist |
| Implement | Claude | Writes the code |
| Review | Claude | Self-critiques the implementation |
| Fix Review | Claude | Addresses review findings (loops if critical/major) |
| Create PR | Claude | Commits, pushes, opens a GitHub PR |
| Monitor CI | Litus | Polls GitHub Actions with exponential backoff |
| Fix CI | Claude + Litus | Reads failure logs, attempts fixes (configurable retries) |
| Applying Feedback | Claude | Applies user-provided feedback (manual mode only, on-demand) |
| Merge PR | Litus | Squash-merges the PR (pauses for review in manual mode) |
| Sync Repo | Litus | Pulls changes and cleans up the worktree |
In Manual automation mode, Litus pauses before merging so you can review the PR. At that pause, you can:
- Resume ā merge the PR as-is.
- Provide Feedback ā type free-form feedback. Litus spins up a dedicated
feedback-implementeragent that reads your feedback, makes the requested changes, commits with Conventional Commit messages, and pushes. When the change is materially relevant to the PR outcome, the agent also losslessly augments the PR description on GitHub. - Abort ā stop the workflow entirely.
After a feedback iteration lands commits, CI re-runs, and you return to the same merge-pause with the same choices ā iterate as many times as you need.
The Provide Feedback button only appears in Manual mode. In Normal or Full Auto modes the workflow merges automatically and the button is never shown.
How feedback is applied to later agents. Every submitted feedback entry is persisted alongside the workflow and
injected as an authoritative "USER FEEDBACK (overrides spec/plan on any conflict)" block into every subsequent agent
prompt (including fix-ci and review iterations). If a later agent could otherwise undo your change to match the
original spec, the feedback block tells it to preserve your preference.
Semantics.
- Empty or whitespace-only feedback acts as Resume ā no entry is created, the iteration counter does not advance.
- Only one feedback iteration can run at a time per workflow.
- Pausing then aborting during a feedback run records the iteration as
cancelledand terminates the workflow. - Restarting the server during a feedback run records the iteration as
cancelledand rewinds to the merge-PR pause, so you can retry with the same or different feedback.
Iteration history ā text, timestamp, outcome badge, and any non-fatal warnings (e.g., PR description update failed) ā is always visible on the workflow detail view.
For features too large for a single workflow, Litus supports epics:
- Click New Epic and describe the feature at a high level
- Litus decomposes it into individual specs with dependency tracking
- Specs execute in dependency order and as parallel as possible ā downstream workflows wait for their blockers to complete
- The epic tree view shows the full dependency graph and per-spec status
Click the gear icon in the header to open the config panel. Everything is configurable per-step:
- Models ā Choose which Claude model to use for each pipeline step
- Effort levels ā
low,medium,high, ormaxper step - Prompts ā Customize question detection and review classification prompts
- Limits ā Max review iterations, CI fix attempts, merge retries
- Timing ā Poll intervals, idle timeouts, summary frequency
- Auto Mode ā Skip optional checks and auto-answer questions (for the brave)
Config is persisted to ~/.litus/config.json.
All data lives under ~/.litus/:
~/.litus/
config.json # App configuration
workflows/
index.json # Workflow index
{id}.json # Individual workflow state
epics.json # Epic definitions
audit/
events.jsonl # Audit log
| Layer | Technology |
|---|---|
| Runtime | Bun |
| Server | Bun.serve() ā built-in HTTP + WebSocket, no framework |
| Agent | Claude Code CLI via Bun.spawn ā no API key needed beyond what the CLI uses |
| Frontend | Vanilla TypeScript ā no React, no Vue, no regrets |
| Markdown | marked + DOMPurify |
| Linting | Biome |
| Testing | Bun test runner + happy-dom |
| CI | GitHub Actions |
Litus orchestrates a few external tools. Here's what they do and where to find them:
Anthropic's CLI for Claude. This is the actual agent that reads your code, writes implementations, and creates PRs.
Litus spawns it as a child process and communicates via --output-format stream-json. All AI interactions go through
the CLI ā Litus has zero direct API calls, so there's no extra API cost beyond your normal Claude Code usage. Think of
Litus as the control tower and Claude Code as the plane.
GitHub's official CLI. Litus uses it for PR creation, CI status polling, failure log retrieval, and squash-merge
operations. You'll need it installed and authenticated (gh auth login).
A set of Claude Code skills that power the
specify ā implement pipeline. These live in your target repository's .claude/skills/ directory and give the agent
structured prompts for each pipeline step. If speckit skills are missing from a target repo, Litus auto-installs them
via uvx during the setup step.
bun run dev # Build client + start server with --watchbun test # Run tests
bun run tsc --noEmit # Type check
bunx biome ci . # Lint & format (CI mode)
bunx biome check --write . # Auto-fix lint & format
bun audit # Dependency vulnerability scan- Fork the repo
- Create a feature branch (
feat/your-thing) - Make your changes ā keep commits atomic and small
- Follow Conventional Commits for all commit messages (CI enforces this on PRs)
- Run
bunx biome ci .andbun testbefore pushing - Open a PR against
master
Linting is enforced by Biome. CI will reject anything that doesn't pass biome ci, type checking, tests, or
conventional commit checks. Don't fight it.
This project is licensed under the GNU Affero General Public License v3.0.
This project utilizes AI products to generate code. The outputs of these tools are not covered by the AGPL license. The authors of this software do not claim any ownership rights over the code or other artifacts generated by the software.





