pipic CLI · 为 AI 而生

一条命令压缩图片。

和网站同一个压缩引擎,装进你的终端、构建流程与 agent。需要 Node 20 或更高版本,零遥测,图片压完即从服务器删除。

100每月免费张数
5,000Pro 档位
Claude CodeCodexCursor+70

让你的 agent 帮你装

把这句话发给 Claude Code、Codex 或任意编码 agent —— 它会读这份文档并自己装好。

照这份文档帮我装一下 pipic CLI,装完告诉我怎么登录:https://pipic.cc/cli

为什么用 CLI

为 agent 而生的输出

NDJSON 加上稳定的退出码,agent 可以直接据此分支 —— 而不是去猜一段自然语言。

一条命令,一整个文件夹

就地替换或输出到新目录 —— 本地批量与构建产物都一样。

登录一次

此后脚本、CI(通过 PIPIC_TOKEN)与 agent 全程无人值守,不需要再批准任何东西。

默认安全

不显式给 --replace 或 -o 就什么都不动,写入是原子的,压不小的文件原样保留。

快速上手

agent · 先装 skill

skill 装一次,你的 agent 自己就能找到 pipic —— 你再也不用点名这个工具,也不用重复那些参数。

1

安装 CLI

需要 Node 20 或更高版本
$ npm i -g @pipic/cli
不想全局安装?npx @pipic/cli <paths…> 效果完全一样。
2

安装 skill

Claude Code、Codex、Cursor 等 70 多个 agent
$ npx skills add PiPic-cc/pipic-cli -g
npx skills add PiPic-cc/pipic-cli -g -a claude-code -a codex -a cursor -y
不带参数时会问你要装到哪些 agent 里;上面那行参数可以跳过这一步。之后用 npx skills update 更新。
3

批准登录

每台机器批准一次
$ pipic login
Opening your browser…
✓ Signed in as you@example.com
第一次用到时,agent 会引导你执行 pipic login —— 打开浏览器链接,无图形界面时改用设备码。它不会替你登录,而这次保存下来的凭证覆盖之后每一次运行。
4

之后直接说

不用报工具名,也不用带参数
「把 ./assets 里的图片压一下。」
「这些截图太大了,就地压小。」
「构建前把 public/ 里的图片都优化掉。」
skill 教了你的 agent 什么
  • 绝不自己去跑 pipic login —— 把批准这一步交回给用户。
  • skipped 不是失败 —— 它带着原因,比如这张图本来就够小了。
  • 部分失败后只重跑失败的那几个文件 —— 整批重跑会把配额花两遍。
没有 skill 支持?改用粘贴

一次性任务,或者不支持 skill 的 agent —— 直接把命令给它。完整契约在下面一节:

Use the pipic CLI to compress the images in ./assets, replacing them in place:

  pipic ./assets --replace --json

Run `pipic -h` for more.
查看完整契约 →

agent 跑在读不到你 ~/.config 的容器或沙箱里?改为在账号页创建一个 token,并在那个环境里设置 PIPIC_TOKEN。

自己动手跑

人 · 脚本 · CI

安装

需要 Node 20 或更高版本
$ npm i -g @pipic/cli
$ pipic login
Opening your browser…
✓ Signed in as you@example.com
全局装一次、浏览器批准一次 —— 之后在任何 shell 里跑都已经是登录状态。

什么都不想装

npx
npx @pipic/cli ./assets --replace
不用全局安装也能跑 —— 但那次一次性的 pipic login 仍然需要。

没有浏览器 —— SSH、容器

device code
$ pipic login --no-browser
Open https://pipic.cc/cli/authorize
Enter this code: PXBQ-GTZM
Expires in 10 minutes · waiting…
无图形界面的环境会自动切到设备码流程 —— 换任意一台设备批准即可。

CI 与沙箱

PIPIC_TOKEN
export PIPIC_TOKEN=pipic_xxx
优先级高于凭证文件。token 在账号页创建与撤销 —— CLI 永远不会自己铸出新 token。

命令

pipic <路径…>压缩文件或目录。这是默认命令。
pipic login [--no-browser]通过浏览器或设备码授权这台机器。
pipic logout登出并撤销这台机器的凭证。
pipic whoami显示当前登录的账号与档位。
pipic quota显示本月还剩多少配额。
pipic token list列出你的 token,附前缀与最近使用时间。
pipic token create打印一个网页链接去创建 —— 出于安全考虑,创建 token 只能在网页上完成,CLI 本身不会创建。
pipic token revoke <id>撤销一枚你自己名下的 token,通常一分钟内生效。

login、logout、whoami、quota、token 会被优先当作子命令匹配,而不是路径。如果你恰好有一个同名文件夹想压缩,写成 ./login 或 login/ —— 只要带路径分隔符,就会走压缩命令而不是子命令。

压缩选项

--replace

就地覆写原图 —— 原子替换,保留权限,解引用软链接。

-o, --out <目录>

把结果写到这个目录,而不是就地覆写。

--json

NDJSON 输出,一行一个文件 —— 供脚本与 Agent 解析。

--concurrency <n>

并发上传数,默认 4。

--replace 与 -o 必须二选一 —— 两者互斥,且都不是默认行为;不给任何一个,pipic 会以用法错误(退出码 2)退出。

你可能想知道

  • 只有压缩结果确实变小才会写回 —— 已经优化过的图片会被跳过,并给出原因。-o 模式下这张图仍会被原样复制到输出目录,所以输出目录永远是一份完整集合。
  • --replace 会先写临时文件再原子改名,Ctrl-C 中断也不会留下半个文件。
  • 超过 8 MB 的文件会被跳过并给出明确原因,不会被静默丢弃。
  • 支持 JPG、PNG、WebP 和 AVIF,不会发送任何遥测数据。
  • 在 -o 模式下,两个来自不同子目录、文件名相同的文件会撞车:pipic 会把两张都报错,而不是替你猜该保留哪一张。

JSON 输出契约

--json 会按文件逐行打印一个 JSON 对象,固定六个字段:

$ 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"}
file你传入的路径,原样返回。
status"ok"、"skipped" 或 "error" —— 不会有其他取值。
before原始体积,单位字节。
after压缩后体积,单位字节 —— skipped/error 行为 0。
saved省下的字节数(before 减 after),不是百分比。
error只在 skipped 与 error 行出现 —— 一句人能看懂的原因,不是错误码。

退出码

0全部成功
1部分失败
2用法错误
3需要登录
4配额用尽

这是一份稳定的契约:脚本与 Agent 应该按 status 与退出码分支处理 —— 绝不要匹配 error 的文本内容。

HTTP API

不能跑 Node?直接用 HTTP 调用同一个压缩引擎——每次请求一张图,不需要 SDK,也不用 multipart 表单。

POSThttps://pipic.cc/compress/image
请求
AuthorizationBearer <token> —— 每次请求都必须带上。
Content-Typeimage/png、image/jpeg、image/webp 或 image/avif —— 必填,且必须与实际发送的字节匹配。
X-Original-Name可选。先做 URL 编码——响应里只会原样带回 encodeURIComponent 允许的字符集。
Body裸图片二进制,不是 multipart/form-data。一次请求一张图,最大 8MB。
$ 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
200 OK · same format in, same format out

响应

200 OK 的响应体就是压缩后的图片——同格式进,同格式出。Content-Type 反映压缩后的格式;能拿到时也会带上 Content-Length 与 X-Original-Name。

获取 token

API 与 CLI 共用同一套 Personal Access Token。用 GitHub 或 Google 登录后,在账号页创建一枚——明文 token 只显示这一次,请妥善保存。

创建 token

错误

非 200 的响应都会带这样一个 JSON 错误信封。请按 code 字段分支处理,不要匹配 message 文本——下面是一个真实的例子:

{"success":false,"code":"MONTHLY_QUOTA_EXCEEDED","message":"Monthly compression quota reached, try again next month"}
400INVALID_TYPE —— Content-Type 缺失或不是图片类型;NO_FILE —— 请求体为空
401UNAUTHORIZED、TOKEN_EXPIRED 或 TOKEN_REVOKED —— 重新登录,或新建一枚 token
413FILE_TOO_LARGE —— 超过 8MB
415UNSUPPORTED_TYPE —— 我们不压缩的 image/* 类型(只支持 PNG、JPEG、WebP、AVIF)
429RATE_LIMITED(看 Retry-After 头)或 MONTHLY_QUOTA_EXCEEDED —— 本月额度已用完
502UPSTREAM_ERROR —— 压缩后端拒绝了这张图,原样重试只会得到同样的结果。这次尝试会退回配额
503UPSTREAM_ERROR 或 ALL_KEYS_EXHAUSTED —— 后端暂时没有容量,可退避后重试。这次尝试会退回配额

你可能想知道

  • 一次请求在被我们接受进入压缩流程的那一刻就会计入配额——即使它随后以 400、413 或 415 失败也一样。在那之前就被拒绝的请求不计数:任意 401、429 RATE_LIMITED,以及仅凭声明的 Content-Length 头就被拒的文件。如果失败原因在我们这边(502/503),这次尝试会被自动退回。

想要每个请求头、每个错误码的完整机读清单: /openapi.json

常见问题

Agent 会不会动我没让它动的文件?

不会 —— pipic 要求显式给出 --replace 或 -o <目录>,不给就直接拒绝执行,而且在报这个错误之前不会发起任何请求。

我登录一次,Agent 就能一直用下去吗?

是的。凭证保存在这台机器的 ~/.config/pipic/config.json,任何以你身份运行的工具都能读到它 —— 每个 Agent 都不需要单独再批准一次。

Agent 说它没有登录,该怎么办?

多半是跑在读不到你 ~/.config 的容器或沙箱里。去账号页建一个 token,把它设成那个环境里的 PIPIC_TOKEN 即可。

免费额度用完会怎样?

pipic 会以退出码 4 退出,绝不会自动扣费。Free 每月 100 张,Pro 提升到每月 5,000 张。

我的图片会被保存吗?

不会 —— 压缩完成的那一刻就会从服务器删除,不做任何长期留存。

每月免费压缩 100 张图片。

不用绑卡,没有遥测,网页版压缩始终不限量。

登录以获取 token