droost / workflow
droost: a Drupal codebase's knowledge read from files (code:wiki, code:tree, search:arch) and the phased, gated pipeline an agent runs to change it. Framework-free: no Drupal is booted and drush is never called.
Requires
- php: ^8.3
- ext-pdo_sqlite: *
- droost/engine: ^1.0
- symfony/yaml: ^6.4 || ^7.0 || ^8.0
Requires (Dev)
- drupal/coder: ^8.3.31
- phpstan/phpstan: ^2.2.14
- phpstan/phpstan-phpunit: ^2.0.18
- phpunit/phpunit: ^10.5 || ^11.5 || ^12.0
- sirbrillig/phpcs-variable-analysis: ^2.13.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 1.2.0
- 1.1.0
- 1.0.0
- 0.18.4
- 0.18.3
- 0.18.2
- 0.18.1
- 0.18.0
- 0.17.0
- 0.16.1
- 0.16.0
- 0.15.0
- 0.14.19
- 0.14.18
- 0.14.17
- 0.14.16
- 0.14.15
- 0.14.14
- 0.14.13
- 0.14.12
- 0.14.11
- 0.14.10
- 0.14.9
- 0.14.8
- 0.14.7
- 0.14.6
- 0.14.5
- 0.14.4
- 0.14.3
- 0.14.2
- 0.14.1
- 0.14.0
- 0.13.12
- 0.13.11
- 0.13.10
- 0.13.9
- 0.13.8
- 0.13.7
- 0.13.6
- 0.13.5
- 0.13.4
- 0.13.3
- 0.13.2
- 0.13.1
- 0.13.0
- 0.12.0
- 0.11.13
- 0.11.12
- 0.11.11
- 0.11.10
- 0.11.9
- 0.11.8
- 0.11.7
- 0.11.6
- 0.11.5
- 0.11.4
- 0.11.3
- 0.11.2
- 0.11.1
- 0.11.0
- 0.10.47
- 0.10.46
- 0.10.45
- 0.10.44
- 0.10.43
- 0.10.42
- 0.10.41
- 0.10.40
- 0.10.39
- 0.10.38
- 0.10.37
- 0.10.36
- 0.10.35
- 0.10.34
- 0.10.33
- 0.10.32
- 0.10.31
- 0.10.30
- 0.10.29
- 0.10.28
- 0.10.27
- 0.10.26
- 0.10.25
- 0.10.24
- 0.10.23
- 0.10.22
- 0.10.21
- 0.10.20
- 0.10.19
- 0.10.18
- 0.10.17
- 0.10.16
- 0.10.15
- 0.10.14
- 0.10.13
- 0.10.12
- 0.10.11
- 0.10.10
- 0.10.9
- 0.10.8
- 0.10.7
- 0.10.6
- 0.10.5
- 0.10.4
- 0.10.3
- 0.10.2
- 0.10.1
- 0.10.0
- 0.9.11
- 0.9.10
- 0.9.9
- 0.9.8
- 0.9.7
- 0.9.6
- 0.9.5
- 0.9.4
- 0.9.3
- 0.9.2
- 0.9.1
- 0.9.0
- 0.8.0
- 0.7.0
- 0.6.17
- 0.6.16
- 0.6.15
- 0.6.14
- 0.6.13
- 0.6.12
- 0.6.11
- 0.6.10
- 0.6.9
- 0.6.8
- 0.6.7
- 0.6.6
- 0.6.5
- 0.6.4
- 0.6.3
- 0.6.2
- 0.6.1
- 0.6.0
- 0.5.3
- 0.5.2
- 0.5.1
- 0.5.0
- 0.4.7
- 0.4.6
- 0.4.5
- 0.4.4
- 0.4.3
- 0.4.2
- 0.4.1
- 0.4.0
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.0
- v0.1.1
- v0.1.0
- dev-off-drupal
This package is auto-updated.
Last update: 2026-10-30 21:48:14 UTC
README
droost is the command-line half of Droost: it gives an AI coding agent a map of your Drupal codebase (the brain), and takes every change it makes through plan → code → test → complete, with checks at each step (the workflow). It is a framework-free PHP package: not a Drupal module, and it never boots Drupal.
The Droost ecosystem
| Project | What it is | Where |
|---|---|---|
| droost/workflow (this repository) | The droost command: the brain and the workflow. |
GitHub · Packagist |
| droost/engine | The engine under the command: the code index, the wiki and search cores, the agent harness installers. | GitHub · Packagist |
Droost (drupal/droost) |
The Drupal module: the agent asks the live site about itself, and changes it through tools a person switches on. | drupal.org |
| Droost CMS | A Drupal CMS recipe for a site an agent builds: the module's content tools, Droost Theme, UI Patterns. | drupal.org |
| Droost Theme | A base theme for agents: Tailwind v4 and daisyUI, design tokens in one file, Canvas-ready components. | drupal.org |
| Droost UI Kit | Manage Display built from Single Directory Components, on UI Patterns 2. | drupal.org |
| Droost Framework | The map of all of these on drupal.org. | drupal.org |
Documentation, the FAQ and the agent-readable docs (llms.txt) are at droost.org.
What it does
- The brain.
droost code:wiki,code:treeandsearch:archanswer from the project's files: every installed module and theme, your custom code, your notes. No Drupal, no drush; it answers while the site is broken. - The workflow. Every change runs plan → code → test → complete. Each
phase ends with gates (phpcs, phpstan, PHPUnit, Playwright and more), set
by one level from
lowtomax. Plan cannot close until the agent has looked things up. - The guard. A hook that stops the agent skipping a phase, editing the rules mid-run, or running the commands that are the operator's.
It works with any agent that can run commands: droost init writes the
instructions for Claude Code, Codex, Gemini, opencode and Qwen. The guard is
Claude Code's today; on other agents the gates still hold the run, and the
report says enforcement was advisory.
Install
Let your agent do it:
Read https://droost.org/agents.md and follow it to install droost in this project.
Or by hand, in its own Composer project so the site's dependencies can never break it:
mkdir -p tools/droost composer init -d tools/droost -n --name=local/droost-tools composer config -d tools/droost platform.php 8.3.0 # the PHP droost runs under (the site's) composer require -d tools/droost 'droost/workflow:^1.0' tools/droost/vendor/bin/droost init # the pack, the guard's hooks, AGENTS.md, droost/droost.yml tools/droost/vendor/bin/droost code:index # the code index the brain reads
Pin platform.php to the PHP droost will run under: installed from a host
with a newer PHP, Composer otherwise picks dependencies the site's container
cannot load. On DDEV, run Composer on the host and droost in the container
(ddev exec tools/droost/vendor/bin/droost …). Then start a new agent
session, so the hooks and skills load.
Configure
init writes droost/droost.yml, the one file that says what a run is held
to. It is committed, so loosening a gate shows up in review, and the guard
refuses edits to it during a run. The main lever is the level:
| Level | What a run is held to |
|---|---|
low |
basic static checks, no tests; the one level that may turn a required gate off (and records it as off, never passed) |
medium |
phpcs, phpstan level 2 and the browser check; a changed class needs a changed test |
high |
phpstan 6 and unit tests; the guard's enforcement is hard |
xhigh |
adds coverage, mutation testing and the front-end linters |
max |
everything, strict; the test suites must exist |
custom |
your own gates: block is the truth (what init writes) |
The level is the operator's to set, from their own terminal:
droost workflow:effort <level> (--preview shows what it would change).
Every gate, threshold and option is in Configuration.
Use
Ask your agent for a change. In Claude Code, /droost:workflow:start <what you want>; any other agent finds the same procedure through AGENTS.md.
The agent researches, writes a spec, builds, tests and completes, and the
run stops at whatever a gate refuses.
droost workflow:status where the run is
droost workflow:report each phase, each gate's verdict and why
droost every command, one line each
droost <command> help one command's arguments
| Command | What it answers |
|---|---|
code:wiki [page] |
the wiki (droost/wiki), and a page per installed contrib module and theme: its version (composer.lock), what it needs and provides (its YAML), whether the last configuration export enabled it. code:wiki status checks each page against its sources (the wiki_fresh gate); code:wiki stamp re-records a page's source hashes |
code:tree [module|path] |
modules and themes, their files, classes, functions and methods, and each module's hooks, services and routes |
search:arch <words> |
plain text over the documentation: the wiki, the inventory, each extension's README and docs |
code:symbol <name> |
where a class, interface, trait, function or method is defined |
code:graph <symbol> |
what it calls, what calls it, what it injects and implements (service:<id>, route:<name>, hook:<name> too) |
search:code <query> |
symbol names and wiki text, lexically; the nearest code chunks too when search.embeddings names an endpoint |
code:docs, code:deprecations |
module documentation; Drupal core's deprecations, offline |
brief |
the project in one answer, from its files |
code:index [--full] |
builds or refreshes the code index |
workflow:<verb> |
the run: workflow:run, workflow:status, workflow:criteria, … (below) |
init, migrate, doctor |
install, move an old lever file, report what droost can see |
guard <verb> |
the guard a harness's hooks call; not for typing |
The commands that loosen the rules are the operator's alone: effort,
gate-waive, bypass, writing a baseline, ticket move, intake answer
and intake abandon. The guard refuses them from the agent's shell and hands
back the command for the operator to run in a terminal of their own, and
making a run autonomous (lead autonomous) needs that terminal too
(The guard).
Documentation
On droost.org: Getting started · How it works · On an existing site · Your first run · Commands · Troubleshooting · FAQ
The reference, in this repository:
| Topic | What it covers |
|---|---|
| Configuration | droost/droost.yml: the levels, every gate and its options, storage, the wiki and semantic search |
| A project's own rules | a baseline for existing problems; the project's own gates, hooks and walls; house rules |
| Gates, criteria and the feedback loop | which gate runs at which phase, how each requirement is matched to its proof, what happens when a gate fails |
| The intake | a site from a design, planned and approved before it is built; who finishes a run |
| Tickets | work items from a folder of Markdown tickets, or from a cockpit |
| Run state and run events | what a run records, and the events other tools can read |
| The pack and the run panel | what init installs for each agent harness; the run panel beside the chat |
| The guard | what it refuses, the operator's commands, which harnesses it covers |
Design notes: design · enforcement · adoption baseline · effort presets · cockpit provider API.
Requirements
PHP 8.3+ with pdo_sqlite. Runtime dependencies: symfony/yaml and
droost/engine (the code index, the wiki and search cores, the harness
installers), which brings nikic/php-parser. No Drupal
bootstrap is needed for anything: the levers, the run state, the code index
and the wiki are files.
Development
composer install scripts/lint # phpcs, phpstan (level max), phpunit scripts/lint src/Config # scope phpcs to a subset
All three legs are hard. A missing binary fails the gate rather than skipping it and says which invocation it could not run — an environment that cannot run a gate is a broken environment, not a gate that does not apply.
License
GPL-2.0-or-later.