一条命令压缩图片。
和网站同一个压缩引擎,装进你的终端、构建流程与 agent。需要 Node 20 或更高版本,零遥测,图片压完即从服务器删除。
让你的 agent 帮你装
把这句话发给 Claude Code、Codex 或任意编码 agent —— 它会读这份文档并自己装好。
照这份文档帮我装一下 pipic CLI,装完告诉我怎么登录:https://pipic.cc/cli为什么用 CLI
为 agent 而生的输出
NDJSON 加上稳定的退出码,agent 可以直接据此分支 —— 而不是去猜一段自然语言。
一条命令,一整个文件夹
就地替换或输出到新目录 —— 本地批量与构建产物都一样。
登录一次
此后脚本、CI(通过 PIPIC_TOKEN)与 agent 全程无人值守,不需要再批准任何东西。
默认安全
不显式给 --replace 或 -o 就什么都不动,写入是原子的,压不小的文件原样保留。
快速上手
agent · 先装 skillskill 装一次,你的 agent 自己就能找到 pipic —— 你再也不用点名这个工具,也不用重复那些参数。
安装 CLI
需要 Node 20 或更高版本安装 skill
Claude Code、Codex、Cursor 等 70 多个 agent批准登录
每台机器批准一次之后直接说
不用报工具名,也不用带参数- 绝不自己去跑 pipic login —— 把批准这一步交回给用户。
- skipped 不是失败 —— 它带着原因,比如这张图本来就够小了。
- 部分失败后只重跑失败的那几个文件 —— 整批重跑会把配额花两遍。
一次性任务,或者不支持 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 或更高版本什么都不想装
npx没有浏览器 —— SSH、容器
device codeCI 与沙箱
PIPIC_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 <目录>把结果写到这个目录,而不是就地覆写。
--jsonNDJSON 输出,一行一个文件 —— 供脚本与 Agent 解析。
--concurrency <n>并发上传数,默认 4。
--replace 与 -o 必须二选一 —— 两者互斥,且都不是默认行为;不给任何一个,pipic 会以用法错误(退出码 2)退出。
你可能想知道
- 只有压缩结果确实变小才会写回 —— 已经优化过的图片会被跳过,并给出原因。-o 模式下这张图仍会被原样复制到输出目录,所以输出目录永远是一份完整集合。
- --replace 会先写临时文件再原子改名,Ctrl-C 中断也不会留下半个文件。
- 超过 8 MB 的文件会被跳过并给出明确原因,不会被静默丢弃。
- 支持 JPG、PNG、WebP 和 AVIF,不会发送任何遥测数据。
- 在 -o 模式下,两个来自不同子目录、文件名相同的文件会撞车:pipic 会把两张都报错,而不是替你猜该保留哪一张。
JSON 输出契约
--json 会按文件逐行打印一个 JSON 对象,固定六个字段:
file你传入的路径,原样返回。status"ok"、"skipped" 或 "error" —— 不会有其他取值。before原始体积,单位字节。after压缩后体积,单位字节 —— skipped/error 行为 0。saved省下的字节数(before 减 after),不是百分比。error只在 skipped 与 error 行出现 —— 一句人能看懂的原因,不是错误码。退出码
这是一份稳定的契约:脚本与 Agent 应该按 status 与退出码分支处理 —— 绝不要匹配 error 的文本内容。
HTTP API
不能跑 Node?直接用 HTTP 调用同一个压缩引擎——每次请求一张图,不需要 SDK,也不用 multipart 表单。
AuthorizationBearer <token> —— 每次请求都必须带上。Content-Typeimage/png、image/jpeg、image/webp 或 image/avif —— 必填,且必须与实际发送的字节匹配。X-Original-Name可选。先做 URL 编码——响应里只会原样带回 encodeURIComponent 允许的字符集。Body裸图片二进制,不是 multipart/form-data。一次请求一张图,最大 8MB。响应
200 OK 的响应体就是压缩后的图片——同格式进,同格式出。Content-Type 反映压缩后的格式;能拿到时也会带上 Content-Length 与 X-Original-Name。
获取 token
API 与 CLI 共用同一套 Personal Access Token。用 GitHub 或 Google 登录后,在账号页创建一枚——明文 token 只显示这一次,请妥善保存。
错误
非 200 的响应都会带这样一个 JSON 错误信封。请按 code 字段分支处理,不要匹配 message 文本——下面是一个真实的例子:
400INVALID_TYPE —— Content-Type 缺失或不是图片类型;NO_FILE —— 请求体为空401UNAUTHORIZED、TOKEN_EXPIRED 或 TOKEN_REVOKED —— 重新登录,或新建一枚 token413FILE_TOO_LARGE —— 超过 8MB415UNSUPPORTED_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 张。
我的图片会被保存吗?
不会 —— 压缩完成的那一刻就会从服务器删除,不做任何长期留存。