Ofertas de Fin de Verano

Todos los planes rebajados hasta el 31 de agosto.

Ver planes
00 Días
00 Horas
00 Minutos
00 Segundos

Ofertas de Fin de Verano

Precios rebajados en todos los planes, para nuevas suscripciones y renovaciones. Solo hasta el 31 de agosto.
Ver planes
Saltar al contenido

cpx es a Composer lo que npx es a npm: ejecuta un comando de cualquier paquete sin que ese paquete esté instalado en tu proyecto. La herramienta la creó Liam Hammett hace un par de años, y la versión 2.0 es una reescritura completa que ha pasado a ser paquete de primera parte, laravel/cpx, con varios contribuidores del equipo de Laravel. Taylor la enseñó en el keynote del primer día de Laracon US 2026.

El problema que resuelve lo conoces si alguna vez has hecho composer global require de dos herramientas y te has encontrado con un conflicto de dependencias entre ellas. cpx instala cada paquete en su propio directorio, separado tanto de las dependencias de tu proyecto como de tu Composer global, y ejecuta el comando desde ahí. Las siguientes ejecuciones de la misma versión reutilizan esa instalación, y cpx comprueba actualizaciones por el camino.

Requisitos

  • PHP 8.3 o superior.

  • El directorio bin global de Composer en tu PATH. Lo puedes localizar con composer global config bin-dir --absolute.

composer global require cpx/cpx

La versión actual es la 2.1.0. Para actualizar:

composer global update cpx/cpx

Si en lugar de instalarlo con Composer usas el PHAR suelto, se actualiza solo con cpx self-update, que se descarga la última release de GitHub.

Si venías de la rama 1.x, esa serie está congelada y ya no tiene soporte. Hay una guía de actualización en el repositorio, y el salto se hace con composer global require cpx/cpx:^2.0.

Ejecutar un paquete que no tienes instalado

Se pasa el nombre del paquete, el comando y sus argumentos. El nombre es el mismo que pondrías en tu composer.json, y admite restricciones de versión:

cpx friendsofphp/php-cs-fixer php-cs-fixer fix ./src
cpx friendsofphp/php-cs-fixer:^3.0 php-cs-fixer fix ./src

Cuando el paquete tiene un único binario, o su binario coincide con el nombre del paquete, puedes omitir el comando:

cpx friendsofphp/php-cs-fixer fix ./src

Si tiene varios binarios y no indicas ninguno, la 2.0 te pregunta cuál quieres.

También acepta un directorio en lugar de un nombre de paquete, algo cómodo mientras desarrollas un paquete propio:

cpx ../mi-paquete --version

Ese directorio necesita un composer.json válido y sus dependencias instaladas en vendor/autoload.php. cpx ejecuta el binario declarado directamente desde ahí; no lo copia, ni lo cachea, ni lo gestiona.

Los binarios locales tienen prioridad

Este es el cambio de comportamiento que más se nota si vienes de la 1.x. Antes de instalar una copia aislada, cpx busca el binario en tu proyecto. Sube desde el directorio actual hasta encontrar el proyecto Composer más cercano y ejecuta el binario correspondiente desde su bin-dir configurado:

cpx pint                 # ejecuta vendor/bin/pint si el proyecto lo tiene
cpx phpunit --filter=Foo # ejecuta vendor/bin/phpunit si está presente
cpx laravel/pint:^2.0    # usa el pint local solo si cumple ^2.0

Dentro de un proyecto, cpx pint ejecuta la versión que tu proyecto tiene fijada y no la más nueva que exista. Eso es lo que quieres cuando cada proyecto pinta con reglas distintas. Si no hay binario local que encaje, cpx cae en instalar y ejecutar una copia aislada. Para forzar esa copia, el flag va antes del paquete:

cpx --skip-local laravel/pint --version

Los alias los defines tú

La 1.x traía una lista fija de atajos para paquetes populares, así que cpx phpstan y cpx laravel funcionaban de fábrica. Esa lista ha desaparecido en la 2.0 y ahora los defines tú:

cpx alias phpstan/phpstan phpstan
cpx alias laravel/pint

Si omites el nombre del alias, se usa el nombre corto del paquete, de modo que la segunda línea crea pint. Los dos argumentos son opcionales: si dejas fuera cualquiera de ellos, cpx te lo pregunta. Los alias se guardan en ~/.cpx/, cpx aliases los lista y cpx unalias <nombre> elimina uno. También puedes crear un alias sobre un binario concreto de un paquete que tenga varios.

Tres comandos de gestión más que conviene conocer. cpx installed lista los paquetes que has ejecutado con cpx y tienes instalados. cpx clean elimina los que no has usado últimamente, y con --all los borra todos. Y cpx update actualiza a la última versión, dentro de sus restricciones, todos los paquetes que hayas ejecutado con cpx; también acepta un vendor o un paquete concreto para limitar el alcance. Ojo con cpx list, que en la 2.0 muestra los comandos disponibles de cpx, como es habitual en cualquier consola, y ya no los paquetes instalados.

Scripts sueltos, gists y REPL

cpx exec y cpx tinker cubren los archivos de prueba y las ejecuciones rápidas:

cpx exec script.php
cpx exec -r 'echo PHP_VERSION;'
cpx exec https://gist.github.com/usuario/id
cpx tinker

Con un gist, cpx descarga el archivo y lo ejecuta contra tu directorio actual. Si el gist tiene varios archivos PHP te pregunta cuál, o puedes añadir el ancla del archivo para saltarte la pregunta. Añadiendo un SHA fijas una revisión concreta, y con la variable GITHUB_TOKEN te libras del límite de peticiones de GitHub. Los enlaces en crudo del gist también funcionan.

Un detalle: cpx exec es la única forma de ejecutar un archivo. Un cpx script.php a secas no se enruta ahí.

Los dos comandos hacen algo de trabajo antes de ejecutar tu código. Detectan el autoloader de Composer en el directorio actual o en uno superior, y alias las clases que uses sin importar cuando encuentran una coincidencia. En un proyecto Laravel arrancan la aplicación completa, con configuración, facades, .env y $app disponibles; en uno de Symfony arrancan el kernel y exponen $kernel y $container. Con --no-boot te saltas ese arranque. Tu código corre en su propio proceso PHP, así que no puede chocar con las dependencias internas de cpx, y los códigos de salida de exit() se propagan.

Dentro de esos scripts, cpx_require() trae un paquete bajo demanda:

<?php

cpx_require('nesbot/carbon');

echo Carbon\Carbon::now();

En un proyecto Laravel que tenga laravel/tinker instalado, cpx tinker delega en el php artisan tinker del propio proyecto y le reenvía argumentos como --execute. En cualquier otro sitio abre una consola PsySH con el proyecto arrancado.

Salida pensada para agentes

cpx detecta cuándo no está conectado a un terminal interactivo. Eso incluye la entrada estándar redirigida, el paso de --no-interaction o -n, y la ejecución dentro de un agente de IA, que identifica mediante laravel/agent-detector.

En ese modo, los procesos hijos no reciben TTY, las preguntas se resuelven con su valor por defecto y los comandos de gestión (installed, aliases, alias, unalias, clean y update) devuelven una única línea de JSON:

{
    "success": true,
    "errors": [],
    "summary": {
        "packages": [
            { "name": "laravel/pint", "last_run": "2024-01-02 03:04:05" }
        ]
    }
}

Las ejecuciones de paquetes muestran solo la salida de la herramienta subyacente, sin el progreso propio de cpx. Los fallos del propio cpx, como un comando desconocido o un paquete que no se puede instalar, también se reportan en JSON. Con --json obtienes esa misma salida desde un terminal interactivo. Sobrescribir un alias existente de forma no interactiva requiere --force.

Dónde encaja esto

El caso claro es todo lo que hoy tienes instalado globalmente solo porque lo usas de vez en cuando: un formateador, un analizador estático, el instalador de Laravel, alguna herramienta de migración. Sacarlos del Composer global elimina la clase de conflicto que aparece cuando dos de ellos quieren versiones distintas de la misma librería. Y dentro de un proyecto sigues ejecutando el binario que el proyecto fija, que es exactamente el comportamiento que quieres en un equipo.

school Curso completo

Curso Laravel 12
Completo 2026

El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.

access_time 8 horas de contenido
layers 4 tecnologías en 1
update 100% actualizado
code Proyectos prácticos
Ver Curso Laravel 12 arrow_forward

star Incluido en cualquier suscripción

Rutas de aprendizaje