dark-factory

command module
v0.41.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2026 License: BSD-2-Clause Imports: 9 Imported by: 0

README ΒΆ

🏭 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/in-progress/  β”Œβ”€ watcher renames, processor executes
β”œβ”€β”€ write prompt 2  ──→  prompts/              β”‚  YOLO β†’ commit β†’ tag β†’ push
β”œβ”€β”€ move to queue   ──→  prompts/in-progress/  β”‚  YOLO β†’ commit β†’ tag β†’ push
└── go AFK                                     └─ idle, watching prompts/in-progress/
                                                    ↓
You come back                       ←── changes committed and pushed

Specs

Spec Problem
001-core-pipeline Running AI coding prompts requires babysitting: open terminal, paste prompt, wait, review, commit, repeat.
002-configuration All paths, image names, and settings are hardcoded.
003-filename-normalization Users create prompt files with arbitrary names (add-health-check.md, 9-fix-bug.md, my task.md).
004-directory-separation All prompts live in one directory.
005-instance-locking Running two dark-factory instances in the same project causes race conditions: both pick the same prompt, both try to commit, git conflicts.
006-crash-recovery If dark-factory crashes mid-execution, a prompt is left with status: executing β€” it's stuck.
007-git-direct-workflow After the Docker container makes changes, those changes need to be committed and pushed.
008-http-api When dark-factory runs unattended, there's no way to check progress without reading files directly.
009-cli-commands The only way to interact with dark-factory is to start the daemon.
010-pr-workflow Direct workflow commits to the current branch.
011-timestamp-frontmatter No visibility into when prompts were created, queued, started, or completed.
012-duplicate-frontmatter-handling Prompts created with empty frontmatter (---\n---) end up with a duplicate frontmatter block in the content body after the processor prepends real frontmatter.
013-configurable-github-identity Dark-factory creates PRs using the current user's gh auth.
014-pr-url-in-frontmatter When dark-factory creates a PR via the pr workflow, the PR URL is logged but not persisted in the prompt's frontmatter.
015-prompt-status-frontmatter Prompt lifecycle tracking relies solely on folder location (inbox/queue/completed).
016-auto-merge-and-release When workflow: pr or workflow: worktree is configured, dark-factory creates a PR and moves on.

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.2.5
  • 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/in-progress 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. Move to in-progress for execution
mv prompts/my-feature.md prompts/in-progress/

# 4. Start dark-factory (long-running, watches for new prompts)
dark-factory daemon

# 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
β”‚   β”œβ”€β”€ in-progress/          # 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

  1. Write a prompt in prompts/ (inbox β€” nothing happens automatically)
  2. When ready, move it to prompts/in-progress/
  3. Watcher detects the file, renames to NNN-name.md, sets status: queued in frontmatter
  4. Processor picks the lowest-numbered queued prompt
  5. Validates: correct number prefix, status is queued, all previous prompts completed
  6. Sets status: executing, spins up a claude-yolo Docker container
  7. On success: commits, tags, pushes, moves to prompts/completed/
  8. On failure: sets status: failed in frontmatter
Handling Failures

When a prompt fails (status: failed):

  1. Check the log: prompts/log/NNN-name.log
  2. Fix the prompt (clarify instructions, reduce scope, fix constraints)
  3. Reset status to queued in the frontmatter and move back to prompts/in-progress/
  4. 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

Prompt Format

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          # process all queued prompts and exit (one-shot)
dark-factory daemon       # watch for prompts and process continuously (long-running)
dark-factory status       # show queue, running prompt, completed count
dark-factory status -json # JSON output

REST API

Disabled by default (serverPort: 0). Set a port to enable:

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.

projectName: my-project                              # optional project identifier
github:
  token: ${DARK_FACTORY_GITHUB_TOKEN}                # default β€” reads from env var
workflow: direct                                     # "direct" (default), "pr", or "worktree"
autoMerge: false                                     # wait for PR approval and merge (requires workflow: pr or worktree)
autoRelease: false                                   # create release after merge (requires autoMerge: true)
prompts:
  inboxDir: prompts                                  # passive drop zone (default: prompts)
  inProgressDir: prompts/in-progress                 # watcher + processor dir (default: prompts/in-progress)
  completedDir: prompts/completed                    # archive dir (default: prompts/completed)
  logDir: prompts/log                                # execution logs (default: prompts/log)
specs:
  inboxDir: specs                                    # spec inbox (default: specs)
  inProgressDir: specs/in-progress                   # spec processing dir (default: specs/in-progress)
  completedDir: specs/completed                      # completed specs (default: specs/completed)
  logDir: specs/log                                  # spec logs (default: specs/log)
containerImage: docker.io/bborbe/claude-yolo:v0.2.5  # YOLO Docker image
model: claude-sonnet-4-6                             # Claude model (default: claude-sonnet-4-6)
debounceMs: 500                                      # watcher debounce in ms
serverPort: 0                                        # REST API port (0 = disabled)
GitHub Token

The optional github.token field allows dark-factory to use a specific GitHub identity for gh CLI operations (creating PRs, checking PR status, etc.). This is useful when you want dark-factory to create PRs under a bot account instead of your personal account.

  • Use ${VAR_NAME} syntax to reference environment variables
  • When set, all gh commands use this token via the GH_TOKEN environment variable
  • When not set or empty, gh uses its default authentication (from gh auth login)
  • Token must never be committed β€” use environment variable reference only
  • For security, ensure .dark-factory.yaml is not world-readable: chmod 600 .dark-factory.yaml

The inbox/in-progress/completed separation works out of the box with these defaults. You can customize any of these paths via .dark-factory.yaml. 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:

  1. Create the directory: mkdir -p ~/.claude-yolo/docs
  2. Add a CLAUDE.md with instructions for your YOLO agent (workflow rules, git constraints, verification steps)
  3. 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

Documentation ΒΆ

The Go Gopher

There is no documentation for this package.

Directories ΒΆ

Path Synopsis
Code generated by counterfeiter.
Code generated by counterfeiter.
pkg
cmd
Package cmd implements CLI commands for the dark-factory tool.
Package cmd implements CLI commands for the dark-factory tool.
config
Package config handles configuration loading and validation.
Package config handles configuration loading and validation.
executor
Package executor runs prompt files inside Docker containers.
Package executor runs prompt files inside Docker containers.
factory
Package factory wires all dependencies for the dark-factory application.
Package factory wires all dependencies for the dark-factory application.
generator
Package generator creates prompt files from spec definitions.
Package generator creates prompt files from spec definitions.
git
Package git provides version control operations for commits, tags, branches, and PRs.
Package git provides version control operations for commits, tags, branches, and PRs.
lock
Package lock provides file-based mutual exclusion for single-instance enforcement.
Package lock provides file-based mutual exclusion for single-instance enforcement.
processor
Package processor manages the prompt execution lifecycle.
Package processor manages the prompt execution lifecycle.
project
Package project defines project-level types and naming.
Package project defines project-level types and naming.
prompt
Package prompt handles prompt file loading, saving, and queue management.
Package prompt handles prompt file loading, saving, and queue management.
report
Package report generates and parses completion reports from prompt execution.
Package report generates and parses completion reports from prompt execution.
review
Package review implements automated PR review polling and fix prompt generation.
Package review implements automated PR review polling and fix prompt generation.
runner
Package runner orchestrates the main dark-factory event loop.
Package runner orchestrates the main dark-factory event loop.
server
Package server provides HTTP handlers for status, queue, and inbox endpoints.
Package server provides HTTP handlers for status, queue, and inbox endpoints.
spec
Package spec handles specification file loading, status management, and listing.
Package spec handles specification file loading, status management, and listing.
specnum
Package specnum provides spec number parsing utilities.
Package specnum provides spec number parsing utilities.
specwatcher
Package specwatcher watches spec files and triggers prompt generation on changes.
Package specwatcher watches spec files and triggers prompt generation on changes.
status
Package status aggregates and formats system status information.
Package status aggregates and formats system status information.
version
Package version provides build version information.
Package version provides build version information.
watcher
Package watcher monitors the prompts directory for file changes and normalizes filenames.
Package watcher monitors the prompts directory for file changes and normalizes filenames.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL