π Dark Factory
Autonomous coding pipeline β drop prompts in, get commits out.
One factory per project, sequential prompt processing, zero human intervention between spec and commit.
How It Works
You (fast) Factory (slow, unattended)
βββ write prompt βββ prompts/ (inbox, passive)
βββ ready to go βββ prompts/queue/ ββ watcher renames, processor executes
βββ write prompt 2 βββ prompts/ β YOLO β commit β tag β push
βββ move to queue βββ prompts/queue/ β YOLO β commit β tag β push
βββ go AFK ββ idle, watching prompts/queue/
β
You come back βββ changes committed and pushed
Prerequisites
- Go 1.24+ β to build dark-factory
- Docker β to run claude-yolo containers
- claude-yolo image β
docker pull docker.io/bborbe/claude-yolo:v0.0.7
- Anthropic API key β set
ANTHROPIC_API_KEY environment variable (passed to container)
- ~/.claude-yolo/ β Claude Code config for the YOLO agent (see YOLO Container Configuration)
Installation
go install github.com/bborbe/dark-factory@latest
Or build from source:
git clone https://github.com/bborbe/dark-factory.git
cd dark-factory
make install # installs to $GOPATH/bin
Quick Start
# 1. Set up your project
cd ~/Documents/workspaces/your-project
mkdir -p prompts/queue prompts/completed
# 2. Write a prompt
cat > prompts/my-feature.md << 'EOF'
# Add health check endpoint
## Goal
Add a `/health` endpoint that returns 200 OK.
## Constraints
- Run `make precommit` for validation only
- Do NOT commit, tag, or push
EOF
# 3. Queue it for execution
mv prompts/my-feature.md prompts/queue/
# 4. Start dark-factory
dark-factory
# 5. Watch it work β watcher renames to 001-my-feature.md, processor executes
# When done, prompt moves to prompts/completed/001-my-feature.md
# Logs at prompts/log/001-my-feature.log
Directory Structure
your-project/
βββ .dark-factory.yaml # optional config
βββ CHANGELOG.md # optional β enables auto-versioning with tags
βββ prompts/ # inbox (passive, drop prompts here)
β βββ my-new-feature.md # draft, nothing happens
β βββ queue/ # watcher watches here, processor executes
β β βββ 001-my-task.md # will be picked up and executed
β βββ completed/ # done prompts archived here
β β βββ 001-my-task.md
β βββ log/ # execution logs
β βββ 001-my-task.log
βββ ...
Workflow
- Write a prompt in
prompts/ (inbox β nothing happens automatically)
- When ready, move it to
prompts/queue/
- Watcher detects the file, renames to
NNN-name.md, sets status: queued in frontmatter
- Processor picks the lowest-numbered queued prompt
- Validates: correct number prefix, status is queued, all previous prompts completed
- Sets
status: executing, spins up a claude-yolo Docker container
- On success: commits, tags, pushes, moves to
prompts/completed/
- On failure: sets
status: failed in frontmatter
Handling Failures
When a prompt fails (status: failed):
- Check the log:
prompts/log/NNN-name.log
- Fix the prompt (clarify instructions, reduce scope, fix constraints)
- Reset status to
queued in the frontmatter and move back to prompts/queue/
- Dark-factory will retry it
Versioning
If your project has a CHANGELOG.md, dark-factory automatically:
- Determines version bump (patch/minor) from changes
- Updates CHANGELOG.md with new version
- Creates a git tag (e.g.,
v0.3.4)
- Pushes both commit and tag
Without CHANGELOG.md, dark-factory commits and pushes without tagging.
Writing Good Prompts
A prompt is a markdown file that tells the YOLO agent what to build. Structure:
# Short title describing the change
## Goal
One paragraph: what should change and why.
## Current Behavior (optional)
What happens now, if fixing a bug or changing existing code.
## Expected Behavior (optional)
What should happen after this prompt is executed.
## Implementation
Step-by-step plan. Be specific β the agent follows this literally:
### 1. Create/modify package X
Code examples, interface definitions, function signatures.
### 2. Update wiring
Where and how to connect the new code.
### 3. Tests
List specific test cases (valid input passes, invalid input fails, edge cases).
## Constraints
- Run `make precommit` for validation only
- Do NOT commit, tag, or push (dark-factory handles git)
- Follow specific coding guides (reference by path)
- Coverage β₯80% for changed packages
Tips:
- Be specific β "add a Validate() method" beats "add validation"
- Include code examples β show interfaces, function signatures, expected behavior
- Reference coding guides β
~/.claude-yolo/docs/go-patterns.md etc.
- Always include constraints β especially "do NOT commit" (dark-factory handles git)
- One concern per prompt β smaller prompts succeed more often than large ones
Frontmatter is managed by dark-factory (you don't need to add it):
| Status |
Who |
What |
| (none) |
Human |
Drafting in inbox |
queued |
Factory |
Ready for execution |
executing |
Factory |
YOLO container running |
completed |
Factory |
Done, in completed/ |
failed |
Factory |
Needs manual fix |
Commands
dark-factory # run (default) β watch and process prompts
dark-factory run # same as above
dark-factory status # show queue, running prompt, completed count
dark-factory status -json # JSON output
REST API
Runs on port 8080 (configurable via serverPort):
| Endpoint |
Description |
GET /health |
Health check |
GET /status |
Current processing status |
GET /queue |
Queued prompts |
GET /completed |
Completed prompts |
Configuration
Optional .dark-factory.yaml in project root. Without it, dark-factory uses defaults.
workflow: direct # "direct" (default) or "pr"
inboxDir: prompts # passive drop zone (default: prompts)
queueDir: prompts/queue # watcher + processor dir (default: prompts)
completedDir: prompts/completed # archive dir (default: prompts/completed)
containerImage: docker.io/bborbe/claude-yolo:v0.0.7 # YOLO Docker image
debounceMs: 500 # watcher debounce in ms
serverPort: 8080 # REST API port
Important: Without a config file, queueDir defaults to prompts (not prompts/queue). Create a .dark-factory.yaml to use the inbox/queue separation. See example/ for a complete setup.
YOLO Container Configuration
Dark-factory executes prompts inside a claude-yolo Docker container. The container gets its Claude Code configuration from ~/.claude-yolo/ on the host, mounted as /home/node/.claude inside the container.
~/.claude-yolo/
βββ CLAUDE.md # instructions for the YOLO agent
βββ docs/ # coding guides (go-patterns.md, go-testing.md, ...)
βββ commands/ # custom slash commands
βββ agents/ # custom agents
Set up ~/.claude-yolo/ before first use:
- Create the directory:
mkdir -p ~/.claude-yolo/docs
- Add a
CLAUDE.md with instructions for your YOLO agent (workflow rules, git constraints, verification steps)
- Add coding guides in
docs/ for project-specific conventions the AI wouldn't know
The docs teach YOLO conventions like custom library patterns, naming rules, and linter limits. See ~/.claude-yolo/docs/README.md for details on writing effective guides.
Design Principles
- YOLO has NO git access β all git ops happen on the host
- Sequential processing β prompts execute in number order
- Validation before execution β prompt must have valid status, number prefix, and all predecessors completed
- Instance lock β only one dark-factory per project (flock + PID file)
- Fresh context per prompt β no context rot
- Frontmatter = state β no database
- Version tracked β each completed prompt records the dark-factory version
License
BSD-2-Clause