作者让Agent克隆并运行unshutter项目,全程自主完成Cloudinary Claimable Cloud、Neon Postgres和Stripe沙箱的配置,整个过程无需人工注册。
Here's a build log that would have been impossible a year ago.
我告诉一个 Agent 去克隆 unshutter 并让它跑起来。
它配置了一个 Cloudinary Claimable Cloud、一个 Neon Postgres 数据库和一个 Stripe 沙箱,全程没有让我创建过一个账户。
它配置了媒体管线,然后跑了一个真实的端到端购买测试:水印预览 → Stripe Checkout → 签名下载原图。
它给了我两个 claim URL,然后停下了。
我以审查 PR 的方式去认领这些环境:先看到运行结果,再做确认。

这个 storefront 只是个演示。我真正想聊的是整个供应(provisioning)过程。
Agent 评估产品的方式和我们不一样。它们不会去读 landing page 或者比较定价表。它们想直接上手:把东西跑起来、对着它开发、看运行结果、再做判断。
直到最近,每个平台都还有一步死死挡在那条路上:创建账户。注册表单、邮件确认、从 dashboard 里捞 API key——十分钟的人工点击,横亘在数小时的自主工作之前。
现在,这一步在这个技术栈里已经消失了:
npx @cloudinary/cloud # Claimable Cloud → CLOUDINARY_URL in .env, claim URL, 24h
npx neon-new --yes # Claimable Postgres → connection string, claim URL, 72h
stripe sandbox create # anonymous sandbox → working test keys
三条命令、零注册,每个都返回可用的凭证加一个 claim 链接。
Cloudinary 的版本返回类似这样的内容:
CLOUD_NAME=a1b2c3d4
API_KEY=123456789012345
API_SECRET=«redacted»
CLOUDINARY_URL=cloudinary://123456789012345:«redacted»@a1b2c3d4
EXPIRES_AT=2026-08-06T08:29:07Z
CLAIM_URL=https://cloudinary.com/users/agent_email_confirmation?token=«redacted»
它把 CLOUDINARY_URL 直接写进 .env,从第一次调用起整个平台就上线了:上传、转换、AI 插件、CDN 分发。没有带队列的试用 tier 卡在前面。
有两个属性对后续很重要:
未认领状态下,24 小时后过期。认领它(在那条 URL 上做邮件确认)会把它转成一个永久免费账户,云名不变、凭证不变、所有已上传的资源也完整保留。
未认领状态下,媒体分发锁定在一个公网 IP,默认是运行命令的那台机器。可以在供应时通过重复 --ip 最多指定三个地址,对笔记本加一个预览 host 够用,但对公网不够。
第二个属性才是有趣的地方:claim 就是"对外开放"的开关。
Agent 的构建从它被供应时指定的 IP 出发可以正常工作。认领才是它能向任何人、分发媒体的时刻。这就是为什么 Agent 在一个能跑的本地站点停下来而不是直接部署:不认领就部署,你发布的东西对每个访客看起来都是坏的,只有你自己能看。应该先 claim,再部署。

unshutter(v.: 打开百叶窗;让光进来)是一个库存媒体 storefront,销售照片、视频和photoset。Next.js 16、Payload CMS、Neon、Stripe、Cloudinary,MIT 许可。下面的每个机制都链向实现它的文件,欢迎来查我的代码。
原图作为 restricted 资源上传,图片用 type: private,视频用 type: authenticated(uploadOriginal.ts)。CDN 拒绝分发未签名的资源。
开启 Strict Transformations 后,只有白名单内的转换才能公开解析(PreviewImage.tsx 是唯一被允许渲染它们的组件)。没有能拼凑出无水印版本的 URL,公众能看到的内容是刻意降级的:水印、q_auto:low、限制尺寸。
付费后生成一个约 10 分钟有效期的签名下载链接(buildDownloadUrl.ts)。Stripe 的支付记录就是 entitlement,每次访问通过一次实时 API 调用验证(verifySession.ts)。没有 user 表,没有 entitlement 表。
视频依赖 e_preview 来获取一段 AI 精选的五秒片段加六张胶片静帧(videoTransformations.ts)。Photoset 把一个文件夹作为一个产品销售,以签名、有有效期的 zip 形式交付,由 generate_archive 实时组装(buildPhotosetZipUrl.ts,ingest 脚本)。
这个项目值得一读,即使你从不运行它:
src/lib/cloudinary/README.md:这一节的诚实版本。每个命名转换及其精确配方,f_auto 为什么必须链在命名转换外部,以及我接受而非解决的权衡。每个 URL builder 都放在 src/lib/cloudinary/ 下,旁边是单元测试。
docs/ARCHITECTURE.md:Payload、Neon、Stripe 和 Cloudinary 如何分工,加上 src/collections/ 里在保存时上传、删除时销毁的 CMS hooks。
src/site.config.ts 和 unshutter-tokens.css:把它重新品牌化为自己的 storefront 只需要改这两个文件,不需要动任何组件。
读代码:github.com/cloudinary-devs/unshutter
以上每一个机制都是必须存在于媒体账户内的配置:命名转换、strict-mode 白名单、分发类型、签名归档。这才是对匿名供应环境真正的考验。
供应一个空环境只是容易的那半。真正的问题是 Agent 能否把上面那些一次性全搞定:
它配置了管线。通过 Admin API 创建了四个命名转换(水印链、OG 图片、AI 视频预览、胶片静帧),每个都标记了 allowed_for_strict: true。没有 console,没有点击。
它验证了安全模型,而不是假设备份。上传了测试媒体,然后请求了一个未签名的原始 URL,确认了 401。这个检查很关键:如果 Strict Transformations 恰好被关掉了,水印就可以被绕过,上面的一切就只是表演。所以 Agent 证明了这一点并报告了它的发现。
它跑了钱路。Browse → cart → Stripe Checkout,卡号 4242 4242 4242 4242 → webhook → /download → 签名 URL → 磁盘上的无水印原图。
然后它停下来,告诉我什么已存在、什么需要认领。
所有这些都是跑在真实基础设施上而非 mock 上的。当它需要当前事实而非训练数据里的东西时,它读了 Cloudinary 的 agent 文档和机器可读的 llms.txt,这两个入口任何 Agent 都可以加载。
单独看中间那一行:邮件确认没有消失,只是不再是第零步了。同样的点击,只是换到了流程末尾。等你做的时候,你是在确认你已经看过运行的东西。
人工操作不仅缩减了,还移到了工作之后,在那里它们感觉像是决策而非琐事。剩下的就是拥有权、基础设施和判断力,这差不多就是本来应该需要人来做的事情了。
这一切都不是完全没有摩擦的,但 Agent 能够绕过去。有些东西在你尝试之前值得了解:
Claimable Cloud 让供应一个可用环境变得容易,但认领一个意味着确认一个邮件地址。如果那个地址已经属于一个 Cloudinary 账户,claim 页面会拒绝它。所以你为真正的工作供应的 claimable cloud 无法合并到你已有的账户里。
如果你已经是客户,直接把自家账户的凭证交给 Agent 就行了。
未认领的 cloud 只向供应时指定的 IP 分发媒体,默认只是运行命令的那台机器。本地一切完美;部署上去网站对你能用、对所有人都是坏的。可以在供应时通过重复 --ip 最多允许三个地址(方便笔记本加一个预览 host,requester_ip 被接受为字面值),但要正式公网化就得认领,认领会完全解除限制。所以:部署前先 claim,如果你要脚本化,就让 Agent 大声报告 claim URL 而不是把它埋在总结里。
在普通分发 URL 里请求它,你会得到 HTTP 423,直到衍生资源存在为止。必须在上传时用 eager_async: true 主动生成,还要有一个签名验证的 webhook 来在 Cloudinary 完成后翻转 previewReady 标志。另外:源视频需要比摘录更长,所以三秒的片段会静默失败。
这意味着"预览就绪"回调在本地开发期间永远不会触发。要么 tunnel(ngrok/cloudflared),要么手动翻转标志;仓库把后者作为一个有文档的 dev fallback 实现了。
Strict Transformations 和 AI 插件注册都是账户姿态设置,要在 console 里 toggle。插件不会阻塞任何操作:图片摄入重试没有它们也能落地,只是图片没有标签。但 strict mode 确实重要,所以 Agent 会测试它而不是信任它。
Clone cloudinary-devs/unshutter,用 claimable 环境让它在本地跑起来。不要问我要凭证,不要部署到任何地方。给我本地 URL 和 claim URL,完成了就告诉我。
或者自己跑那三个命令,然后跟着 quick start 走。
cloudinary-devs / unshutter
Photography paywall storefront. An open-source showcase demonstrating Cloudinary in a modern full-stack app - Cloudinary + Next.js 16 + Payload CMS + Neon + Stripe + Vercel
unshutter (v.): to open the shutters; to let the light in.
一个 AI Agent 可以从 git clone 到跑起一个可验证的商店——媒体、数据库、支付——无需任何人工注册的全栈媒体 storefront。技术栈里的每个平台都支持供应"后认领"环境(npx @cloudinary/cloud、npx neon-new、stripe sandbox create),所以人工操作移到了它们该在的地方:认领一个已经能跑的东西。把 Agent quick start 粘贴给你的 Agent,然后看着它跑。
Built on Next.js 16 + Payload CMS + Neon + Stripe + Vercel, with Cloudinary as the media layer. Sibling to kickoff-cards (Cloudinary + Supabase).

三种产品形态:
Photos — 浏览水印预览、高度压缩的 Previews;付费后 unshutter 以限时的签名链接解封全尺寸 Original
Videos — 一段 AI 精选的五秒水印低分辨率预览片段(Cloudinary e_preview)加六张自动提取的水印静帧;购买后…
这个仓库携带了让 Agent 构建在这种精密技术栈上可行的护栏:AGENTS.md 工作协议、一个列出每个人工操作的供应演练,以及实现所依赖的已验证平台事实。同一个思路的姐妹项目,用 Supabase:Kickoff Cards。
Further reading: Claimable Cloud provisioning · Agents, start here
大部分媒体管道工作现在都是 Agent 的活了。留给我的是决定要不要保留它构建的东西。