L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Use when a project has a .ddev/ folder or needs one: DDEV setup on a new machine, version pinning, config.local.yaml and .ddev/.env files, database import, snapshots, ddev pull and sanitised data, slow Mutagen or WSL2 sites, add-ons (Redis, Solr, cron), commands and hooks, Vite ports, Xdebug, ddev share, port conflicts, several git worktrees at once, script…
Independent GitHub snapshot · Automated classification · Original documentation governs
name: ddev-ops
description: "Use when a project has a .ddev/ folder or needs one: DDEV setup on a new machine, version pinning, config.local.yaml and .ddev/.env files, database import, snapshots, ddev pull and sanitised data, slow Mutagen or WSL2 sites, add-ons (Redis, Solr, cron), commands and hooks, Vite ports, Xdebug, ddev share, port conflicts, several git worktrees at once, scripting DDEV (describe -j), disk cleanup, upgrades and troubleshooting. Audits .ddev/ for team-breaking mistakes."
license: MIT
allowed-tools: "Read Edit Write Bash Glob Grep"
metadata:
author: claude-mods
related-skills: "craftcms-ops, security-ops, frontend-upgrade-ops, docker-ops, web-perf-ops, package-manager-ops"
DDEV Operations
Why: DDEV is the local stack behind most PHP agency sites, and it fails quietly: a
default that moved under an unpinned project, a key it silently ignores, one developer's
setting committed for the whole team.
Versions verified 2026-10-05 against DDEV v1.25.4. Fast-moving facts (defaults, PHP and
Node.js end-of-life floors, built-in command names) live once in
assets/ddev-facts.json; scripts/check-ddev-facts.py --offline fails if this skill's
prose and that file disagree, and --live (weekly) fails when DDEV moves.
Start here
Read the project before changing it:.ddev/config.yaml, any config.*.yaml,
ls -a .ddev/, then ddev describe (URLs, ports, services) and ddev version.
Audit it. From the skill folder (the launcher finds a working Python 3.8+, which
matters on Windows where python3 is often a Store stub):
Exit 10 means findings, sorted high to low (severity, check, file, detail); 0 means
clean. --ignore <check> documents a deliberate exception.
Run everything through DDEV - ddev composer, ddev php, ddev npm,
ddev exec - so commands use the container's PHP and Node, not the host's.
Snapshot before anything risky, with a unique name:
ddev snapshot --name=before-<task>-$(date +%Y%m%d%H%M%S). A reused name saves
nothing and still exits 0.
Ask before destroying data (Hard rule 11).
Hard rules
Rules 2, 3, 4, 6, 8 and 12 were each seen in a 2026-10-05 read of 36 DDEV-based agency
repositories; the rest are quiet failures DDEV's own docs and source describe.
Pin php_version and database to production. Unpinned projects follow DDEV's
defaults, which move: v1.25.0 switched PHP 8.3 to 8.4 and MariaDB 10.11 to 11.8.
Also pin nodejs_version and composer_version: "2".
Per-developer settings never go in config.yaml.
That means performance_mode, router_http_port/router_https_port,
xdebug_enabled: true, bind_all_interfaces and host_db_port.
They belong in .ddev/config.local.yaml or ddev config global.
Project values beat global ones, so a committed value pins every teammate.
Git ignores the .local files only after DDEV has run in that checkout, because
its .ddev/.gitignore isn't committed. Add .ddev/config*.local.y*ml and
.ddev/.env*.local to the project root's .gitignore.
Retired keys do nothing. DDEV loads config non-strictly:
mutagen_enabled: false and nfs_mount_enabled are ignored, not obeyed.
upload_dirs resolve from the docroot. With docroot: web, storage means
web/storage; folders beside the docroot are ../storage and ../node_modules.
Setting the list replaces the type's defaults; override files append to it.
No secrets in committed .ddev/.env* files. Use the .local twin
(.ddev/.env.web.local, v1.25.4+), kept out of git as rule 2 says. Commit a
.example with git add -f, since DDEV's .gitignore hides *.example.
Never forward the host SSH agent into containers. Every process in them -
Composer and npm scripts included - could sign with every key the agent holds. Load
one scoped key with ddev auth ssh -f <key>.
Pull sanitised data; never push to production.
Anonymise where the data lives and pull the result. No raw production personal data
on laptops.
Delete db_push_command/files_push_command from your own recipes that can reach
production.
A files_pull_command that fetches nothing makes ddev pull empty the upload
directory, and the pull still exits 0. Omit the stanza instead.
Don't keep project copies of DDEV's built-in commands (craft, npm,
artisan, wp...). A project command shadows the built-in and freezes an old
version. Command files must have LF endings: DDEV skips CRLF ones with only a warning.
Review an add-on before installing it. Its Bash install actions run on your
machine. Prefer official ddev/ add-ons and pin --version.
On Windows, keep projects inside the WSL2 filesystem, never under /mnt/c.
Confirm with the user before destroying data. These destroy data:
ddev import-db and ddev import-files, which empty their target first;
docker volume prune -a, which deletes stopped projects' databases.
ddev poweroff stops everyone's projects.
Several checkouts need distinct project names. A committed name: makes every git
worktree claim the same project. Omit it, or override it in config.local.yaml.
Driving DDEV from a script or agent
Never run bare ddev (it opens a dashboard) or flagless ddev config (it asks
questions). Pass --file/--source to imports and -y to anything that prompts.
Read state as JSON:ddev describe -j | jq -r '.raw.primary_url' (also
.raw.status, .raw.dbinfo.published_port); ddev list -j;
ddev launch --print-url.
Single-quote ddev exec commands that contain $, pipes or redirects, so they
expand inside the container.
Exit 0 isn't always success: a duplicate ddev snapshot name and
ddev add-on remove leaving files behind both exit 0.
folders and commands: upload-dir-misplaced, upload-dir-outside,
shadowed-command, crlf-command;
safety: ssh-agent-forwarded, provider-push, provider-files-noop,
committed-secret, local-file-committed (reads git's index; never runs a git or
fsmonitor command the audited repository supplies).
Install commands, lockfiles, .nvmrc/engines agreeing with DDEV's Node and PHP
package-manager-ops
Compose syntax for a hand-written extra service; Dockerfiles generally
docker-ops
Page speed of the site itself
web-perf-ops
Never write a real-looking project hostname in examples: say "the project URL from
ddev describe".
Sources
DDEV docs: docs.ddev.com, source docs/content/users/ at tag v1.25.4.
DDEV release notes: v1.25.0-v1.25.4.
DDEV source:pkg/ddevapp/ (config.go, provider.go, ddevapp.go,
upload_dirs.go, craftcms.go), pkg/settings/viper.go and
cmd/ddev/cmd/commands.go.
Also: the add-on registry (addons.ddev.com) and endoflife.date.
Read 2026-10-05 and re-checked by an independent accuracy review on 2026-10-06. What
the references mark "Observed" was reproduced that day in throwaway projects on DDEV
v1.25.4 (Docker Desktop, WSL2). DDEV
publishes no agent skill for its users; its own repository's AGENTS.md and .claude/
serve people contributing to DDEV.