# A CLAUDE.md for Drupal 11 projects that actually matches your repo

> Source: <https://dev.to/beingrealfrank/a-claudemd-for-drupal-11-projects-that-actually-matches-your-repo-139j>
> Published: 2026-11-14 02:16:07+00:00

Most project instructions for coding agents are copied from a template. The commands in them often don't exist in your repo, so the agent runs them, fails, and guesses. For Drupal this is worse than usual, because "a Drupal project" can mean three very different things: a full site, a single contrib module, or a distribution. This post shows how to write a `CLAUDE.md` (or `AGENTS.md`) by reading the repository first, using two real public repos:

`2.2.x`)

```
grep -n '"type"' composer.json
ls -a | head -40
```

In `localgov_directories`, `composer.json` says `"type": "drupal-module"` and the root holds `localgov_directories.info.yml`. There is no `web/` directory, no `vendor/`, no Drush. In `drupal/cms` there is a `.ddev/` directory, a `web` docroot setting in `.ddev/config.yaml`, and `drush/drush` in `composer.json`.

That one check changes every command you write. A module repo cannot run its own tests: they need a full Drupal codebase around the module. If your instructions say `vendor/bin/phpunit -c web/core ...` for a module repo, the agent will fail on the first try.

Don't assume DDEV. The `drupal/cms` `AGENTS.md` makes this explicit: check for a `.ddev/` directory *and* `ddev` on the `PATH`; otherwise fall back to local Composer, and use `vendor/bin/drush` only if it exists. Steal that idea:

```
ls -d .ddev 2>/dev/null
command -v ddev
test -x vendor/bin/drush && echo "project drush"
```

Then write the commands with the right prefix once, instead of leaving the agent to decide each time.

Every command in the file should come from somewhere you can name: a `composer.json` script, the DDEV config, the CI workflow, or the official docs. For Drupal the commands that matter are small in number:

`drush cache:rebuild` (`drush updatedb`
`drush config:status` (`drush config:import --diff` (`vendor/bin/phpunit -c web/core path/to/Test.php` (
Notice what is *not* on the list: `drush config:import --yes`. The `drupal/cms` agent file lists it as a normal workflow, which is reasonable for a fresh local site. On a site with real active config, the `--yes` flag applies the import without asking, so in your own file you may want "show the diff first" instead.

In the module repo, CI runs the tests through a shared workflow that installs the module at `web/modules/contrib/localgov_directories` inside a full site. So the honest instruction there is one sentence: "tests run inside a full Drupal site; the module path is `web/modules/contrib/localgov_directories`", not a made-up local command.

The part agents most need is what *not* to touch. A short list works better than a long one:

`web/modules/custom` and `web/themes/custom`.` vendor/`, `settings.local.php`, `.env`, or uploaded files under `web/sites/*/files`.
The `drupal/cms` file has this section too, and it is the most reusable part of it.

If a `CLAUDE.md` or `AGENTS.md` exists, add a clearly marked section instead of rewriting it. Other people (and other tools) rely on the original lines.

Ask three questions of every line: where does this command come from, does it work from this directory, and what happens if it is wrong? If you can't answer the first, delete the line. A shorter file made of true statements beats a long one the agent has to second-guess.

*Written with AI assistance. Every command and example here was run against the public repositories named above.*
