Drush forma parte de casi todos los proyectos Drupal con cierto peso: reconstruye cachés, ejecuta actualizaciones de base de datos, importa configuración y gestiona despliegues. Con Drupal 11.4, el core incluye su propia herramienta de línea de comandos, dr, y la iniciativa detrás de ella apunta abiertamente a, con el tiempo, acabar reemplazando a Drush completamente. La herramienta todavía es experimental, pero el cambio ha comenzado, y no todas las partes de los flujos de trabajo diario que dependen de Drush, especialmente los pipelines de CI/CD y las operaciones remotas, se desarrollarán al mismo ritmo. Conocer el estado actual evitará disgustos más adelante.
Drupal ha dependido de una herramienta externa para sus operaciones diarias a un precio
Drush es el CLI de facto de Drupal. Todas las operaciones de CLI (reconstruir cachés, ejecutar actualizaciones de base de datos, importar configuración, gestionar despliegues) pasan por él, y se mantiene fuera de core. El script ofrecido por el core, core/scripts/drupal, añadido en 2018 (#2911319), no era extensible y solo incluía tres comandos: quick-start, install y generate-theme.

La visibilidad es uno de los problemas: el CLI de Drupal solo está disponible tras requerir el paquete drush/drush, por lo que no resulta obvio que exista una herramienta de línea de comandos, especialmente para quien llega de nuevas a Drupal. Pero el coste real es mantener dos proyectos separados sincronizados, Drush y Drupal core. Cada actualización de Symfony en core forzaba una nueva versión de Drush y rompía las actualizaciones de Composer, como ocurrió con Drupal 8.4 y Symfony 3, y de nuevo con Drupal 9 y Symfony 4. Los sitios tenían que esperar a que Drush se pusiera al día.
Un CLI interno sería fácil de encontrar por cualquiera y elimina el problema de sincronización de versiones. Como señaló catch, un committer del core, en el comentario #47 de «CLI entry point in Drupal Core»: «drush also has to support multiple versions of core, but a command in core only has to support the version it's in (e.g. an command in 11.x doesn't need to work with 12.x or 10.x).» Los comandos en core también siguen las políticas de testeo y compatibilidad con versiones anteriores de core. Además, el CLI del core ofrece una forma estándar de proveer comandos, en lugar de tener que elegir entre Drush o scripts personalizados (o Drupal Console cuando aún se usaba).
El contraargumento también tenía sentido. Drush está probado y es ampliamente usado, ¿para qué rehacerlo? «Instead of reinventing the wheel we could promote Drush instead or even include it in our composer.json as a requirement», escribió hchonov en 2019 (#3089277).
Al final, core se decidió por su propio CLI porque una dependencia de Composer en Drush crea una dependencia bidireccional: los cambios en core pueden romper Drush, y Drush tiene que seguir las versiones de Symfony de core. Los comandos en core solo dependen de core.
Llegar a ese acuerdo, sin embargo, llevó bastante tiempo.
Diez años del mismo debate
El primer intento (#2242947) se inició en 2014 y acumuló 214 comentarios antes de cerrarse como obsoleto en 2026. El segundo (#3089277) se abrió en 2019 en la cola de Ideas y acabó en «the same kind of inertia».
Ambos quedaban bloqueados por los mismos problemas recurrentes, y cada postura era razonable por entonces:
- Solapamiento con Drush: core no quería dos enfoques, y Drush no se había comprometido a usar un CLI de core.
- Calendario de lanzamientos: el trabajo se aplazó a 8.1.x para no interrumpir el lanzamiento de Drupal 8, y luego fue aplazado de versión menor en versión menor.
- El nombre: el binario
drupalya estaba cogido por Drupal Console, que no podía renombrarse sin romper su uso para sus usuarios. - Bootstrap: los comandos tenían que ejecutarse con y sin un Drupal arrancado, y el kernel estaba estrechamente acoplado a la capa HTTP.
- Descubrimiento: el diseño nunca convergió entre plugins, servicios, contenedores separados y
extrade Composer. - Responsabilidad: había acuerdo general de que era una buena idea, pero no había quien la implementara e impulsara.
En 2022, incluso Moshe Weitzman, el principal mantenedor de Drush, abogaba por incluir Drush en las plantillas del proyecto en lugar de un CLI en core. Cuatro años después, cada uno de estos bloqueos tenía respuesta.
Qué cambió en 2026
Moshe probablemente puso la primera piedra con su post Drush's Final Act en febrero. Dijo que «attempts stalled due to debates about command name or bootstrap details or numerous other bikeshed details».
Hizo explícita la presión competitiva: «I think it is vital for Drupal from a competitive perspective to get to a full featured CLI quickly». También declaró su objetivo para la herramienta que mantenía: «My end goal here is the death of Drush. It has served an incredibly long and useful life. Its death will be its most impactful and generous act».
Los bloqueos técnicos se resolvieron primero. Drush convirtió todos sus comandos a Symfony Console puro, por lo que cualquier aplicación Symfony Console puede descubrirlos. Drupal Console se dio por finalizado oficialmente en abril de 2025, lo que eliminó definitivamente la segunda opción de herramienta. Sus mantenedores describieron el cierre como un éxito, ya que Drush absorbió sus funciones interactivas y los componentes modernos de Symfony: «So the project is sunsetting, not because it failed, but because it succeeded» (página del proyecto Drupal Console), algo con lo que se puede estar de acuerdo.

El bootstrap también dejó de ser un problema. Solo unos pocos comandos, como site:install, necesitan un sitio sin arrancar, y se pensaba que dar soporte a eso requeriría mucha complejidad. Sin embargo, greg.1.anderson demostró que sobrescribir Application::find(), unas doce líneas con el mismo enfoque que Drush usa desde Drush 9, permite que los comandos con y sin bootstrap compartan un mismo script, evitando esa complejidad. Core también adoptó symfony/runtime (#3313404), que traslada la configuración del entorno fuera de DrupalKernel a una capa reutilizable compartida entre los puntos de entrada HTTP y CLI, reduciendo el código de bootstrap personalizado que cada uno debía mantener por separado.
El descubrimiento se resolvió con un mecanismo estándar de Symfony: un compiler pass recoge las clases en src/Command/ con #[AsCommand], sin necesidad de más código específico.
Finalmente, la gente se puso de acuerdo. En la incidencia sobre tener un CLI en el core, Dries Buytaert confirmó el consenso: «There is agreement that a system-wide CLI would be a good thing for Drupal.» La CLI in Core community initiative (#3582246, #cli-in-core en Drupal Slack) se creó en torno a ese acuerdo, con el líder de Drush, los committers de core y una hoja de ruta.
Siguieron surgiendo desacuerdos, y cada uno se resolvió por su cuenta. Moshe propuso inicialmente depender de Drush de forma temporal para avanzar rápido. catch señaló el riesgo de quedar atascados a mitad del camino con una dependencia bidireccional, Moshe aceptó descartarla y el plan pasó a ser incorporar los comandos esenciales en core uno a uno. El nombre, con dex, drupal y dr sobre la mesa, se trasladó a su propia incidencia sobre una política (#3583795) para que no bloqueara el código. El resultado fue dr, en línea con CLI cortos como wp, ng o gh.
Otra cuestión fue el momento del lanzamiento. Publicarlo en 11.x se impuso frente a esperar a Drupal 12. En palabras de longwave (#125), publicarlo antes significa «users can slowly migrate to dr commands while keeping the drush fallback for the time being, and secondly, that adding the CLI in 11.x inspires people to open MRs to add their favourite/most used commands in time for Drupal 12».
La cronología muestra lo rápido que se movieron las cosas una vez que las piezas encajaron. dpi abrió la incidencia (#3453474) en junio de 2024. El trabajo se inició, pero la incidencia estuvo parada cerca de 18 meses. Moshe la retomó en febrero de 2026, y larowlan la integró en junio en main, 11.x y 11.4.x: «Committed to main and 11.x. Backported to 11.4.x. Congrats all!» (#144).
Qué incluye dr en Drupal 11.4
El nuevo CLI se ejecuta como vendor/bin/dr, implementado en core/scripts/dr. En DDEV, ddev exec dr funciona porque vendor/bin está en el PATH del contenedor web. Encuentra los comandos Symfony Console de core y contrib a través del componente Symfony Runtime, por lo que las cachés se pueden reconstruir y el cron puede ejecutarse sin Drush. core/scripts/drupal queda obsoleto en favor de vendor/bin/dr.
Los comandos principales disponibles en 11.4.0 son los que proporcionaba el script anterior de core: generate-theme, install y quick-start, junto con cache:rebuild, content:export, system:cron, system:status y los comandos de recetas (recipe:apply y recipe:info). Varios se corresponden directamente con comandos conocidos de Drush:
drush cr → dr cr # Alias of cache:rebuild
drush cron → dr cron # Alias of system:cron
drush status → dr status # Alias of system:status
drush si → dr install # install using a profile or a recipe
drush recipe → dr recipe # Alias of recipe:apply
dr está marcado como @internal y experimental en el change record, y la hoja de ruta hacia la versión estable (#3606055) sigue activa. Drush seguirá funcionando durante la transición, lo que dará tiempo a los módulos contrib a adaptarse.
Opciones de los comandos de contrib
La escritura y migración de comandos ya está documentada en la guía oficial de migración de comandos Drush al nuevo CLI dr de Drupal core y en el change record. El modelo a seguir cabe en una línea: un comando Symfony Console simple, una clase con #[AsCommand] en el directorio src/Command/ del módulo, autodescubierta por el core, sin drush.services.yml.
Hay dos formas de dar soporte a ambas herramientas durante la transición. La primera es un comando Symfony Console simple, que tanto Drush como dr descubren. Las versiones recientes de Drush ya usan comandos Symfony Console, así que muchos necesitarán poco o ningún trabajo. La segunda es el patrón Service Wrapper, para los comandos que dependen de funcionalidades de Drush como los formateadores de salida (--format). La lógica de negocio va en un servicio de Drupal. Dos sencillas clases de comando la invocan: una para dr (un comando Symfony Console simple en src/Command/, autodescubierto) y una para Drush (en src/Drush/Commands/, registrada en drush.services.yml). Ninguno de los dos wrappers contiene lógica, así que no hay duplicación.
Eso sí, los comandos locales son la parte fácil.
Gestión remota de sitios
La mayor diferencia respecto al modelo Drush es dónde está el sitio gestionado: dr solo funciona con la instancia local de Drupal. No tiene alias de sitio, y la hoja de ruta hacia la versión estable no incluye ningún comando remoto. Dado que los comandos remotos dependen de los alias de sitio, y los alias no están previstos, es muy probable que dr tampoco cubra los comandos remotos.
Moshe, que también es el responsable técnico de la iniciativa, espera que los alias desaparezcan: «Along the way, we may lose some niceties like Drush config and Site aliases. Platforms already have solutions for replacements aliases such as Lagoon (Amazee), Terminus (Pantheon), acli (Acquia), etc». También apunta a herramientas genéricas como Pssh, Fabric o ash, una herramienta de alias centrada en Drush de jonpugh.
La gestión de sitios remotos probablemente necesitará un cambio o adaptación en el flujo de trabajo o las herramientas, por ejemplo, ejecutando dr dentro de cada entorno por SSH, en el contenedor o a través del CLI de la plataforma de hosting o de un módulo o herramienta del espacio contrib, en lugar de acceder a él desde una máquina local a través de un alias. El trabajo diario de CI/CD se ve directamente afectado: drush sql:dump y drush sql:sync entre entornos son pasos habituales en los pipelines. Los comandos sql:* solo aparecen en la hoja de ruta, sin incidencia abierta todavía, y una sincronización entre dos sitios es por naturaleza una operación remota. Cómo resolverá la comunidad la gestión remota no está claro todavía, y es probablemente un tema para otro artículo.
Los despliegues siguen necesitando Drush
Más allá de la gestión remota, el propio pipeline de despliegue tiene carencias a nivel de comandos. Los despliegues se enfrentan a una brecha más concreta: varios comandos de los que dependen aún no están en dr. En octubre de 2026, solo 4 de los 14 comandos de la hoja de ruta hacia la versión estable (#3606055) están disponibles en 11.4.0, y site:install solo con limitaciones. Sin embargo, algunos otros ya están marcados como «Fixed» y cabe esperarlos en una próxima versión estable. La siguiente tabla cubre los comandos de la hoja de ruta más algunos otros mencionados en esta u otras incidencias:
| Comando Drush | Estado en dr | Incidencia |
|---|---|---|
cache:rebuild | Incluido en 11.4.0 | |
core:cron | Incluido en 11.4.0 (system:cron) | |
core:status | Incluido en 11.4.0 (system:status) | |
site:install | Incluido (install), con limitaciones. Instalar con cualquier driver de BD: se necesita trabajar en ello | #3594342, #3594320 |
user:login | Resuelto en rama dev (11.x) | #3594332 |
pm:install | Resuelto en rama dev (11.x) | #3594334 |
pm:uninstall | Resuelto en rama dev (main) | #3594335 |
pm:list | Resuelto en rama dev (main) | #3594336 |
config:export | Resuelto en rama dev (main) | #3594337 |
config:import | Necesita revisión | #3594338 |
config:status | Activo (pospuesto por otra incidencia) | #3594339 |
updatedb | Activo | #3594333 |
updatedb:status | Activo | #3594340 |
sql:drop, sql:query | En la hoja de ruta, sin incidencia abierta | |
watchdog:show | En la hoja de ruta, sin incidencia abierta | |
deploy | Mencionado como ausente por longwave (#125), sin incidencia abierta |
Con updatedb, config:import y deploy aún no presentes, el enfoque práctico es mantener Drush en los scripts de despliegue por ahora y usar dr junto a él. Tampoco todos los comandos de Drush se trasladarán a core, ya que implementar todos los comandos de Drush aparece como «Not in scope» en la iniciativa (#3582246). Drush se queda para el resto, y los comandos de contrib necesitan migración, o simplemente el descubrimiento de Symfony, para funcionar con dr.
Otras carencias siguen abiertas: todavía no hay un estándar de formato para tablas (#3611694), la ayuda de los comandos disponibles no muestra cómo usarlos (#3606744), los comandos en subdirectorios con un punto en el nombre no se descubren (#3594184), hay una regresión en el logger en 11.4.4 (#3612206) y la documentación de la guía de usuario está pendiente (#3625734). La hoja de ruta apunta que los comandos esenciales estarán para Drupal 12.0.0, con el conjunto completo de funcionalidades previsto con más probabilidad para una versión menor en 2027.
Conclusión
Un CLI en core elimina una dependencia de una década en una herramienta externa para las operaciones básicas. Esta vez las condiciones están dadas: Drush está listo para dejar paso al CLI de core, los committers de core están alineados, los bloqueos antiguos tienen respuesta y el código ya está disponible.
La transición ha comenzado, y conocerlo ahora evita verse a contrapié, especialmente en las operaciones remotas. dr funciona en local y los alias de sitio no están previstos, así que los flujos de trabajo basados en alias y sql:sync van a necesitar más que sustituir drush por dr. Mientras tanto, Drush sigue siendo necesario para el trabajo remoto y los despliegues. Lo que llegue después depende del uso y los comentarios de la comunidad.
Nosotros hemos llegado a todo esto por una razón práctica: estamos añadiendo soporte para dr en nuestros propios módulos, y ese trabajo todavía está en marcha. Entender qué estaba pasando implicó bucear en incidencias de drupal.org con cientos de comentarios, un change record, una guía de migración, posts de blog y diez años de historia. Hemos usado LLM para ayudar a recopilar y leer todo eso. Después de seguir esa historia y ver que este es el intento definitivo, decidimos compartirlo.
Empieza a migrar tus módulos contrib a dr, explóralo en proyectos reales y comparte las necesidades urgentes que encuentres en el canal #cli-in-core de Slack o en la iniciativa CLI in Core, porque Drupal avanza con la ayuda de la comunidad.