Comprime imágenes con un solo comando — en tu terminal, tu build o tu agente.

La CLI de PiPic lleva la misma compresión del sitio web a scripts, pipelines de CI y agentes de codificación con IA. Requiere Node 20 o superior. Sin telemetría. Las imágenes se eliminan en cuanto se comprimen.

$ pipic ./assets --replace
✓ 38 images compressed — 24.1 MB → 5.8 MB (−76%)
3 already optimized, left unchanged

Código fuente: GitHub · npm

¿Por qué pipic CLI?

  • Nativo para agentes: salida NDJSON y códigos de salida estables que un agente de IA puede analizar y usar para ramificar, sin tener que adivinar a partir de un texto.
  • Un solo comando comprime una carpeta entera — en el sitio o en un directorio nuevo — igual de bien para lotes locales que para artefactos de build.
  • Inicia sesión una vez y a partir de ahí funciona sin supervisión: scripts, CI (mediante PIPIC_TOKEN) y agentes lo usan todos sin volver a aprobar nada.
  • Sin telemetría, nunca. Las imágenes se eliminan del servidor en el instante en que termina la compresión.

Requisitos

Node 20 o superior. El comando se llama pipic.

Inicio rápido (persona)

Una sola vez

pipic login abre tu navegador para aprobar la solicitud. Una vez aprobada, las credenciales se guardan en esta máquina — cualquier herramienta que se ejecute como tú, incluido un agente de codificación con IA, puede usar pipic sin volver a iniciar sesión.

$ npm i -g @pipic/cli
$ pipic login
Opening your browser…
✓ Signed in as you@example.com

¿Sin navegador? SSH, contenedores, CI

pipic login --no-browser — o un entorno que la CLI detecte como headless (SSH, CI, un contenedor) — recurre a un código de dispositivo que apruebas desde cualquier otro dispositivo con navegador.

$ pipic login --no-browser
Open https://pipic.cc/cli/authorize
Enter this code: PXBQ-GTZM
Expires in 10 minutes · waiting…

Inicio rápido (agente de IA)

Cada vez

¿Ya está instalado y con la sesión iniciada en esta máquina? Pega esto tal cual a tu agente de codificación:

Use the `pipic` CLI to compress the images in ./assets.
It's already installed and signed in — do not install it or run
`pipic login` yourself.

  pipic ./assets --replace --json

It prints one JSON object per file:
  {"file":"a.png","status":"ok","before":102400,"after":41000,"saved":61400}
status is "ok", "skipped" or "error". "skipped" is not a failure — it
carries an `error` string explaining why (e.g. already small enough).

Exit 0 = all good, 1 = some files failed, 3 = not signed in,
4 = monthly quota exhausted.
Don't retry on exit 2 (usage error), 3 or 4 — on 3, stop and tell the
user to sign in. On exit 1, re-run only the paths whose rows had status
"error": a full re-run re-uploads every file and spends quota again.

¿El agente se ejecuta en un contenedor o sandbox que no ve tu ~/.config? Crea un token en tu página de cuenta y configúralo como PIPIC_TOKEN en ese entorno.

Comandos

pipic <rutas…>Comprime archivos o un directorio. Es el comando predeterminado.
pipic login [--no-browser]Autoriza esta máquina mediante el navegador o con un código de dispositivo.
pipic logoutCierra la sesión y revoca el token de esta máquina.
pipic whoamiMuestra la cuenta con la que has iniciado sesión y su plan.
pipic quotaMuestra cuánta cuota te queda este mes.
pipic token listLista tus tokens con su prefijo y último uso.
pipic token createImprime un enlace para crear uno en el sitio web — por seguridad, crear un token siempre ocurre ahí, nunca en la CLI.
pipic token revoke <id>Revoca un token tuyo, normalmente efectivo en menos de un minuto.

login, logout, whoami, quota y token se reconocen como subcomandos antes de tratarse como rutas. Para comprimir una carpeta que comparta uno de esos nombres, escribe ./login o login/ — cualquier ruta con un separador de directorio llega al comando de compresión en su lugar.

Opciones de compresión

--replaceSobrescribe los originales en el sitio — reemplazo atómico, permisos conservados, symlinks resueltos.
-o, --out <dir>Escribe los resultados en este directorio en su lugar.
--jsonSalida NDJSON, una línea por archivo — para scripts y agentes.
--concurrency <n>Subidas en paralelo. El valor por defecto es 4.

Debes indicar exactamente una de --replace o -o — son mutuamente excluyentes y ninguna es la opción por defecto. Sin ninguna de las dos, pipic termina con un error de uso (código 2).

Cosas que conviene saber

  • Los archivos solo se reescriben cuando el resultado es realmente más pequeño — las imágenes ya optimizadas se omiten, indicando el motivo. Con -o el original se copia igualmente, así que el directorio de salida siempre es un conjunto completo.
  • --replace escribe en un archivo temporal y luego lo renombra, así que un Ctrl-C nunca deja un archivo a medio escribir.
  • Los archivos de más de 8 MB se omiten con un motivo claro, nunca se descartan en silencio.
  • Se admiten JPG, PNG, WebP y AVIF. Nunca se envía telemetría.
  • Con -o, dos archivos que comparten nombre —de subcarpetas distintas, por ejemplo— colisionan: pipic reporta un error para ambos en lugar de adivinar cuál conservar.

Contrato de salida JSON

--json imprime un objeto JSON por línea, uno por archivo, con seis campos fijos:

pipic ./assets --json --replace
{"file":"/p/hero.png","status":"ok","before":2411233,"after":486201,"saved":1925032}
{"file":"/p/notes.txt","status":"skipped","before":0,"after":0,"saved":0,"error":"unsupported file type"}
fileLa ruta que indicaste, sin cambios.
status"ok", "skipped" o "error" — ningún otro valor.
beforeTamaño original en bytes.
afterTamaño comprimido en bytes — 0 en filas skipped/error.
savedBytes ahorrados (before menos after) — nunca un porcentaje.
errorPresente solo en filas skipped y error — un motivo legible, no un código.

Códigos de salida

0Todos los archivos se procesaron con éxito
1Algunos archivos fallaron
2Error de uso
3Requiere iniciar sesión
4Cuota agotada

Es un contrato estable: haz que tus scripts y agentes ramifiquen según status y el código de salida — nunca según el texto de error.

API HTTP

¿Sin Node? Llama directamente al mismo motor de compresión por HTTP — una imagen por solicitud, sin SDK ni formularios multipart.

POST https://pipic.cc/compress/image

Consigue un token

La API usa los mismos Personal Access Tokens que la CLI. Inicia sesión con GitHub o Google y crea uno desde tu página de cuenta — el token en texto plano solo se muestra una vez, guárdalo en un lugar seguro.

Crear un token

Solicitud

AuthorizationBearer <token> — obligatorio en cada solicitud.
Content-Typeimage/png, image/jpeg, image/webp o image/avif — obligatorio, y debe coincidir con los bytes que envías.
X-Original-NameOpcional. Codifícalo con URL primero — solo se devuelven los caracteres válidos para encodeURIComponent.
BodyLos bytes crudos de la imagen, no multipart/form-data. Una imagen por solicitud, hasta 8 MB.
curl
$ curl -X POST https://pipic.cc/compress/image \
  -H "Authorization: Bearer $PIPIC_TOKEN" \
  -H "Content-Type: image/png" \
  --data-binary @photo.png \
  -o photo-compressed.png

Respuesta

200 OK devuelve la imagen comprimida como cuerpo de la respuesta — mismo formato de entrada y salida. Content-Type refleja el formato comprimido; Content-Length y X-Original-Name también llegan cuando están disponibles.

Errores

Cualquier respuesta distinta de 200 devuelve este sobre JSON de error. Decide en tu código según el campo code, no según el texto de message — aquí tienes un ejemplo real:

{"success":false,"code":"MONTHLY_QUOTA_EXCEEDED","message":"Monthly compression quota reached, try again next month"}
400INVALID_TYPE — falta el Content-Type o no es de imagen; NO_FILE — el cuerpo está vacío
401UNAUTHORIZED, TOKEN_EXPIRED o TOKEN_REVOKED — inicia sesión de nuevo o crea un token nuevo
413FILE_TOO_LARGE — supera los 8 MB
415UNSUPPORTED_TYPE — un tipo image/* que no comprimimos (solo PNG, JPEG, WebP, AVIF)
429RATE_LIMITED (mira la cabecera Retry-After) o MONTHLY_QUOTA_EXCEEDED — se agotó la cuota de este mes
502UPSTREAM_ERROR — nuestro backend rechazó esta imagen; reintentar los mismos bytes falla igual. El intento se devuelve a tu cuota
503UPSTREAM_ERROR o ALL_KEYS_EXHAUSTED — sin capacidad temporalmente; puedes reintentar con backoff. El intento se devuelve a tu cuota

Cosas que conviene saber

  • Una solicitud cuenta para tu cuota en cuanto la aceptamos para comprimir — incluidas las que después fallan con 400, 413 o 415. Las rechazadas antes de ese punto nunca cuentan: cualquier 401, un 429 RATE_LIMITED y un archivo rechazado solo por su cabecera Content-Length declarada. Si el fallo es nuestro (502/503), ese intento se reembolsa automáticamente.

Todas las cabeceras y códigos de error, en un solo archivo legible por máquina: /openapi.json

Preguntas frecuentes

¿Puede un agente tocar archivos que no le pedí?

No — pipic exige indicar explícitamente --replace o -o <dir>. Sin ninguno de los dos se niega a ejecutarse, y nunca envía ni una sola solicitud antes de reportar ese error.

Inicié sesión una vez, ¿un agente puede seguir usando pipic para siempre?

Sí. La credencial vive en esta máquina, en ~/.config/pipic/config.json, y cualquier herramienta que se ejecute como tú puede leerla — no hace falta aprobar cada agente por separado.

Un agente dice que no ha iniciado sesión, ¿qué hago?

Lo más probable es que esté en un contenedor o sandbox que no ve tu ~/.config. Crea un token en tu página de cuenta y configúralo como PIPIC_TOKEN en ese entorno.

¿Qué pasa cuando se agota la cuota gratuita?

pipic termina con el código 4 y nunca se cobra nada automáticamente. Free incluye 100 imágenes al mes; Pro lo eleva a 5.000.

¿Se guardan mis imágenes en algún sitio?

No — se eliminan del servidor en cuanto termina la compresión, y nada se almacena a largo plazo.

Privacidad

Sin telemetría, nunca. Las imágenes se eliminan del servidor en cuanto termina la compresión — nada se almacena a largo plazo.

Lee la política de privacidad completa