Skip to content

Commands and options

With no subcommand, ddev-sync plans and runs a sync:

Terminal window
ddev sync --target production --steps db,files,sanitize

Leaving out --target or --steps makes it ask, provided you are in a terminal; ddev sync passes the terminal through, so the pickers appear. In a script or a CI job there is nothing to ask, so pass both — the run tells you so rather than waiting.

CommandWhat it does
initSets the project up by asking: it confirms the detected project type, asks what a sanitize rule needs (the production URL), where the remote’s environment file is, which detected features to keep, then the target’s name, connection and stage — and finally, if the credentials do not resolve, for them. The target goes into the project’s .ddev/ddev-sync.yaml; credentials you type go into .ddev/ddev-sync/local.yaml, never into the committed file. Nothing is written until every question has an answer, so stopping part-way leaves your configuration as it was. Then it runs doctor. Needs a terminal: there are no flags that answer its questions.
doctorChecks a target without changing anything: SSH, the deploy path, local disk space, whether the configured credential source really yields credentials, and whether the tables your sanitize rules require exist on the remote. Under provider: docker the first rows name the sync endpoint rather than the host, say that the path was read inside it, and add whether the endpoint can read its mounts. Under the add-on it also checks that the project’s web container answers (which covers the Docker socket) and that DDEV’s forwarded ssh agent is usable. Exits non-zero when a check fails.
targetsLists every target you have defined and which configuration layer defined it.
buildRuns only the setup work a detected feature contributed — a frontend build, typically — without the rest of a sync.
helpPrints exactly what ddev sync --help prints. Given a command name — ddev sync help doctor — it prints that command’s help instead. A name that is not a command says so and then prints the full help.
OptionEffect
--target NAMEWhich target to pull from. Asked interactively when omitted, and skipped entirely when you have only one.
--steps LISTComma-separated: db, files, s3, sanitize, setup. Only the steps your project has work for are accepted; see which steps are offered. Asked interactively when omitted.
--dry-runPrint the plan and execute nothing. Touches no file and does not connect to the remote. A target that takes its connection from Deployer is the one exception: it is resolved first, which runs dep config in the web container.
--yesAssume every default and skip the prompts, including the confirmation before the local database is dropped.

A step is offered when it would contribute at least one entry to the plan, and the planner itself answers that, rather than a separate rule about what a project contains. A project with no S3 configuration is therefore not asked about s3, and --yes does not select it.

Naming a step that is not available is an error, and the message lists what is available. An empty --steps "" is refused for the same reason, and so is pressing Enter at the interactive picker with nothing ticked: a selection of no steps would plan nothing but the preflight check and then report a successful sync, which is the one outcome worse than an error.

One consequence of filtering is worth knowing before it looks like a bug. --yes selects what is available, so on a project with no sanitize rules it no longer selects sanitize — it never had anything to do there — and the run therefore ends with data from production is on your machine and was not sanitized. Earlier versions selected sanitize, ran it against nothing, and said nothing. The warning is the honest answer: the copy really is unsanitized. Either configure sanitize rules for the project (see Configuration) or treat the copy as production data.

A misspelled step name is a different problem and gets a different message, which says the step is unknown. If you see that one, check the spelling; if you see the list of available steps, the name was right and the project has nothing for it.

A group whose configuration is broken still counts as available: it is configured, just wrongly. It appears in the menu, and its error appears when that group is actually planned, not when you asked for an unrelated one.

OptionEffect
--features LISTUse exactly these features, instead of detecting them.
--no-featuresDetect nothing for this run.
--only-feature-setupRestrict the setup step to commands that came from features, leaving the profile’s own out.
OptionEffect
--type NAMEOverride the project type from .ddev/config.yaml.
--framework-version NOverride the detected major version, which is what picks a profile variant such as typo3@12.
OptionEffect
--project-root PATHThe project to sync. Defaults to /var/www/html, where DDEV mounts it, which is also the working directory under the add-on, so you will not normally set it.
--home PATHWhere to look for the global configuration, for testing a different one.
--profile-root PATH, --feature-root PATHWhere the shipped profiles and features live. You will not normally set these.
OptionEffect
--versionPrint the version and exit.
-h, --helpHelp for the whole tool, or for a subcommand: ddev sync doctor --help. ddev sync help and ddev sync help doctor print the same two texts.

ddev sync doctor shows OK in green and FAIL in red, and only when its output goes to a terminal. Piped into a file or another command, it stays plain text.

Under the add-on, colour follows the terminal and nothing else: NO_COLOR and FORCE_COLOR set in your own shell are not passed through to ddev sync. Run from a checkout as ddev-sync, both are honoured: a non-empty NO_COLOR turns colour off, FORCE_COLOR turns it on without a terminal (FORCE_COLOR=0 turns it off), and TERM=dumb turns it off.

CodeMeaning
0Everything selected ran, or doctor found nothing wrong.
1A step failed, a check failed, or something needed was not configured. The message says which.
2The command line itself was wrong — an unknown option, or one placed after the subcommand when it belongs before it.
130You interrupted the sync with Ctrl-C, at a prompt or while it ran. 130 is the conventional code for a process ended by SIGINT. The message says where it stopped and what that leaves behind; see When something goes wrong. Cancelling an interactive picker with Ctrl-C, or interrupting while the configuration is read or the plan is built, also exits 130, saying “Interrupted.”

These are the engine’s own codes. ddev sync collapses them to 0 or 1: whatever non-zero code the engine returned, the shell sees 1. The real code is visible only in DDEV’s own message, exit status 2, so read that message rather than $? when you need to tell a wrong command line from a failed step. By that rule, 130 is what the engine returns for an interrupt, and under the add-on your shell will see 1, with exit status 130 in DDEV’s message.

All options belong to the tool, not to its subcommands, so they go before the subcommand name:

Terminal window
ddev sync --target production doctor # right
ddev sync doctor --target production # wrong — "no such option"

The error for the second form says so explicitly, because the difference is easy to miss.