A workflow layer for AI-assisted development — structured docs, a task triage loop backed by Dark Flow's own store, and an installer that sets it all up in minutes.
When Claude Code (or any AI agent) works on your project, it generates insights and recommendations — but they evaporate between sessions. There's no handoff from "observation" to "approved task" to "merged change."
Dark Flow installs:
- A two-layer docs structure (
state/= how things are now ·logs/= what happened) with clear read/write rules for the agent - A task triage loop — agent creates
proposedtasks from its findings via the~/.darkflow/dfCLI, human approves or rejects, agent picks upapprovedtasks automatically - A set of task fields (
status,source,priority,scheduledFor) so you can filter with~/.darkflow/df task list --status approvedor snooze a task until a date - Agent-workflow rules baked into
docs/agent-workflow.md(referenced from CLAUDE.md)
Open Claude Code in your project directory and paste this message:
Install Dark Flow workflow from https://github.com/alifanov/darkflow
Run the installer:
curl -fsSL https://raw.githubusercontent.com/alifanov/darkflow/main/install.sh -o /tmp/darkflow-install.sh && bash /tmp/darkflow-install.sh
Ask me which optional modules I want (analytics, observability, SEO, ads, Coolify, architecture review, design),
then run the installer with the appropriate flags.
After install, show me the routines I need to set up in Claude Code → Routines.
The agent will fetch the installer, ask about your stack, run it with the right flags, and walk you through setting up Routines.
- Asks which optional modules apply to your project (analytics, observability, SEO, ads, Coolify, architecture review, docs audit, design, mailbox)
- Creates
docs/folder structure with template files - Writes
.darkflow.d/claude.mdwith the Dark Flow agent workflow and adds a single@.darkflow.d/claude.mdreference toCLAUDE.md - Installs
/darkflowand/darkflow:*slash commands for Claude Code - Creates (or updates) a
Makefilewithdf-*shortcut targets - Verifies the installation against
checklist.ymland auto-fixes any missing artifacts
Dark Flow ships a built-in web dashboard for reviewing and triaging tasks without leaving your terminal setup.
The webapp runs as a host process so it can launch host-side cmux + Claude
sessions straight from the UI (the "Fix in cmux" button on needs-human tasks).
Only Postgres runs in Docker.
Start the server:
# 1. Copy the env templates
cp .env.example .env
cp webapp/.env.example webapp/.env
# 2. Start Postgres (published on localhost:5432)
make up
# 3. Build and run the webapp on the host
make web # http://localhost:5555Open http://localhost:5555 — you'll see all projects that have synced with the worker.
Prefer everything in Docker (no cmux launch button)? Run make docker-up →
the webapp comes up in a container on the same http://localhost:5555.
| Make target | What it does |
|---|---|
make up |
Start Postgres in the background |
make web |
Build & run the webapp on the host (port 5555) |
make web-screen |
Same, but detached in a screen session with an auto-restart loop — survives closing the tab; deaths logged to ~/.darkflow/web-exit.log |
make web-screen-stop |
Stop the detached webapp and its restart loop |
make docker-up |
Start Postgres + webapp in Docker (port 5555) |
make down |
Stop Docker services |
make logs |
Stream Docker logs (Ctrl-C to stop) |
make restart |
Restart Docker services |
make ps |
Show container status |
make db-shell |
Open psql inside the Postgres container |
make reload |
Load (first run) or restart (afterwards) webapp + worker under launchd — auto-restart, survives reboot |
make web-stop / worker-stop |
Stop one of the two launchd-supervised services |
make web-status / worker-status, make web-logs / worker-logs |
Check status / tail logs for one service |
Tasks live entirely in Dark Flow's own Postgres database — no external app or token is needed for Approve / Reject.
The worker registers projects automatically on first sync. No manual setup needed beyond starting Postgres.
docs/
├── README.md ← manifest of all files + reading order
├── agent-workflow.md ← rules: when agent reads / writes each layer
├── tasks.md ← task field taxonomy + triage loop spec
│
├── state/ ← HOW THINGS ARE RIGHT NOW — overwritten in place
│ ├── arch.md ← system map + ## Decisions (why it is shaped this way)
│ ├── hypotheses.md ← bet → evidence → verdict ledger
│ ├── product/ ← what, why, for whom — quarterly
│ └── spec/ ← flows, screens, data model — weekly
│
├── logs/ ← WHAT HAPPENED — appended, never rewritten
│ └── YYYY-MM-DD.md ## Security, ## Analytics, ## Changes, …
│
└── _archive/ ← superseded documents — one archive, never under state/
state/ and logs/ are the whole idea: a routine that observes something appends to
logs/; a routine that learns the system changed rewrites state/. Neither touches the
other's ground, so neither can quietly overwrite the other's work.
Re-running install.sh on a project laid out by an older version brings it forward: the old
top-level spec/ · product/ · design/ move under state/, the retired insights/ and
decisions/ folders move to _archive/, and metrics files no routine writes any more are
deleted. Documents are only ever moved — git status shows every one of them before you
commit.
Agent runs an audit → appends to docs/logs/YYYY-MM-DD.md
→ creates task with status=proposed
Human reviews
→ sets status=approved or status=rejected
Agent starts next session
→ ~/.darkflow/df task list --status approved --state open
→ picks up matching tasks
→ sets status=in-progress, comments with branch name
→ closes after landing the fix (direct commit to the base branch by default, or PR referencing "Task #N" if PR mode is enabled)
Some categories skip the human review step — security fixes, Dependabot dependency updates, and additive database index additions are created directly as status=approved and flow straight to fix-issues. See docs/auto-approve.md for the full allowlist.
The loop runs automatically — see Routines below.
The real power comes from scheduling Claude agents that run the loop automatically. Dark Flow ships a self-hosted dispatcher — no Claude Code Routines UI required.
Which routines exist, whether they're on, and on what schedule — all of that lives in
the Web UI (Settings → Routine schedule), per project. Defaults come from the catalog
in webapp/src/lib/routines.ts; each routine's prompt is
its command file in templates/.claude/commands/darkflow/.
There is deliberately no table here — a hand-written one goes stale the moment a schedule
changes in the UI, which is exactly what happened to the one this replaced.
Two routines have no command file — they are pure bash inside the worker, no agent and no token cost, because neither needs any reasoning:
- ci-watch — red or stuck CI → a
source:citask - housekeeping — stuck tasks, stuck
HEAD, worktree and branch cleanup
Cron times are in the machine's local timezone.
A single global worker (~/.darkflow/darkflow-run.sh) services every project on
the machine. You start it manually (no auto-start), and it runs until you stop it:
nohup bash ~/.darkflow/darkflow-run.sh >/dev/null 2>> ~/.darkflow/worker.err.log & # start
pkill -f ~/.darkflow/darkflow-run.sh # stopIt discovers projects from the web UI (each project's Local path), so a project appears once it has synced.
Run routines manually at any time (from inside the project directory):
~/.darkflow/darkflow-run.sh fix-issues # run one routine now (cwd's project)
~/.darkflow/darkflow-run.sh --list # show status table (cwd's project)
~/.darkflow/darkflow-run.sh --dry-run # preview what's due (cwd's project)See docs/agent-workflow.md for how a routine run is put together.
The installer creates (or updates) a Makefile with df-* targets so you don't have to remember the full command paths:
make df-help # list all df-* targets
make df-run # start the dispatcher loop (every 60s)
make df-sync # push tasks + project metadata to the web UIIf your project already has a Makefile, the installer appends the df-* block between # darkflow:start / # darkflow:end markers — your existing targets are untouched. Running install.sh again regenerates only that block.
Daily
8:00 analytics-review → proposed tasks + analytics snapshot → syncs to web UI
8:30 observability-check → proposed tasks
9:00 coolify-check-deployment → deploy status, critical task on failure
*/4h uptime-check → DNS + HTTP + page-load; site down → status=approved critical task
Weekly
Mon 8:00 seo-check (SEO + GSC) → proposed tasks
Mon 8:00 ads-review → proposed tasks + ads snapshot (optional)
Sun 2:00 architecture-review → proposed tasks (Opus) + arch snapshot → syncs to web UI
Sun 3:00 security-audit → GitHub alerts + code review → auto-approved tasks (Opus) → syncs to web UI
Sun 4:00 build-optimization → proposed tasks (Opus) + build snapshot
Sat 10:00 check-design → visual quality, UI perf, production readiness (optional)
Sat 11:00 check-ux → key flows walked in a real browser, mobile + desktop (optional)
Continuous
:00 fix-issues (hourly) → picks up an approved task → implements → commits directly (PR mode optional)
Human
Reviews proposed tasks in web UI (localhost:5555) → Approve / Reject
or: ~/.darkflow/df task set-status N approved
These are the defaults. The real schedule is per project, in the Web UI.
- Run
install.sh - Verify
gh auth statusworks in the project folder (only needed forsecurity-audit's GitHub alert reads, and forgh pr createif a project opts into PR mode) - Configure required MCP servers (see each routine's page for details)
- Run
~/.darkflow/darkflow-run.sh --dry-runfrom the project to confirm the worker works
All /darkflow:* commands are installed automatically and available inside Claude Code.
| Command | What it does |
|---|---|
/darkflow |
Health check: docs structure, task fields, approved queue |
/darkflow:add-issue [title] |
Create a task for a manually identified item |
/darkflow:update |
Update Dark Flow to the latest version |
/darkflow:install |
Re-run the Dark Flow installer |
/darkflow:checklist-review [group] |
Score the product against the readiness checklists → docs/state/readiness.md. Report only — files no tasks. Run by hand; never scheduled |
/darkflow:submit-to-directories [n|name] |
Submit the product to the directory catalog in ~/.darkflow/directories.csv through a real browser → docs/state/directories.md. Never pays, never invents an identity. Run by hand; never scheduled |
| Command | What it does |
|---|---|
/darkflow:fix-issues |
Pick up one approved task, implement, close |
/darkflow:analytics-review |
Funnel WoW/DoD, why the worst step drops, commits + hypotheses → tasks + snapshot |
/darkflow:observability-check |
Errors / slow queries / latency → tasks |
/darkflow:seo-check |
Technical + on-page SEO audit, plus Google Search Console data → tasks |
/darkflow:coolify-check-deployment |
Deployment status check → critical task on failed deploy |
/darkflow:architecture-review |
Module boundaries + fallow code health → tasks + architecture snapshot |
/darkflow:security-audit |
GitHub alerts (Dependabot, code + secret scanning) + code review → tasks + security snapshot |
/darkflow:build-optimization |
Build + deploy pipeline analysis → optimization tasks |
/darkflow:uptime-check |
DNS + HTTP + page-load check → auto-approved critical task if the site is down |
/darkflow:check-design |
Visual quality, UI performance, production readiness → tasks (optional) |
/darkflow:check-ux |
Key flows walked in a real browser, mobile + desktop → tasks (optional) |
Routine commands automatically call bash ~/.darkflow/get-config.sh before running — this fetches the latest project settings (branch, language, merge strategy, modules, routine schedule) from the Web UI Settings tab into .darkflow.d/state/config.json. If the server is unreachable, commands fall back to the last fetched copy silently.
To edit project settings: open the Web UI → project detail → Settings tab. Changes take effect the next time a routine or command runs. The database is the single source of truth — projects no longer carry a .darkflow config file.
checklist-review scores a product against a versioned set of checklists in
~/.darkflow/checklists/ — eight groups (code, architecture, ux, seo, ads,
security, analytics, ops), each item carrying the lesson or the project where the
defect was originally paid for. They are global, not per project: one list scores the
whole portfolio.
Each group holds two lists. items is what must hold. never_flag is the other half —
findings that audits keep raising and that were verified not worth fixing, so they are
suppressed instead of being re-raised. A rule that lives only in a lesson gets re-discovered
forever; putting it here is what stops that.
/darkflow:checklist-review # all groups
/darkflow:checklist-review seo # one groupThis is a manual command, not a routine — there is no schedule and no catalog entry, and the worker never dispatches it. Run it when you want to know where a product stands: before a launch, when picking up a project that has been quiet, or after a batch of fixes.
The audit routines hunt for new findings. This one asks whether the product still gets wrong
the things already learned the expensive way. It files no tasks — it writes
docs/state/readiness.md and prints a score.
~/.darkflow/directories.csv is the vetted list of product directories worth a submission —
name, URL, Ahrefs DR, link type, price, traffic. Global and versioned, like the checklists:
one list, the whole portfolio submitted from it.
/darkflow:submit-to-directories # next 5 free candidates by DR
/darkflow:submit-to-directories 10 # bigger batch
/darkflow:submit-to-directories DevHuntThe command drives a real browser: it assembles one submission kit (tagline, descriptions,
logo, screenshots, UTM-tagged URL), fills the forms, verifies each submission actually went
through, and records the result in the project's docs/state/directories.md.
Two things it never does: pay (a paid listing comes back as a recommendation with its
price) and invent an identity (real project email only — no throwaway addresses, no made-up
company details, no fabricated MRR). Anything needing a card, a captcha, an OAuth session or an
unreadable mailbox is reported as blocked, with what would unblock it.
Manual command, not a routine — directory forms mean accounts and email confirmations, so a
human is in the loop by definition. checklist-review's seo group scores what is still
missing from the catalog.
Run the same install command — it detects your installed version and updates automatically:
Update Dark Flow in this project:
curl -fsSL https://raw.githubusercontent.com/alifanov/darkflow/main/install.sh -o /tmp/darkflow-install.sh && bash /tmp/darkflow-install.sh
After updating, commit the changes.
The installer:
- Compares your installed version (from
.darkflow) against the latest and shows the changelog - Smart-updates template files: skips unchanged, warns + shows diff if locally modified
- Regenerates
.darkflow.d/claude.md(Dark Flow instructions for Claude) - Regenerates the
df-*block inMakefilebetween# darkflow:start/endmarkers - Bumps the version in
.darkflow - Runs the built-in checklist against the latest
checklist.yml— interactively restores any missing artifacts
If already on the latest version, the installer exits immediately with "Already up to date." Use --force to re-apply all templates regardless.
If something is missing or broken, run the installer with --force:
curl -fsSL https://raw.githubusercontent.com/alifanov/darkflow/main/install.sh -o /tmp/darkflow-install.sh && bash /tmp/darkflow-install.sh --forceThe installer verifies every artifact defined in checklist.yml and auto-fixes what's missing.
After install, edit:
docs/agent-workflow.md— add project-specific read/write rulesdocs/tasks.md— adjust the task field taxonomy if needed
git— any versiongh(GitHub CLI) — forsecurity-audit's Dependabot/code-scanning/secret-scanning alert reads, and forgh pr createif a project opts into PR mode; installyq— YAML parser used by the routine dispatcher;brew install yq/ installpython3— used by the routine dispatcher to isolate process groups and clean up dev servers after each run- Claude Code — the workflow is designed around it, but works with any AI agent that follows markdown instructions