Communitygithub.com

d1-cli — 从命令行操作 Tiendas D1

从命令行搜索商品、查询最近门店、根据实时库存定价购物清单并获取配送报价,全面操作哥伦比亚 D1 超市(d1.com.co)。

d1-cli — 从命令行操作 Tiendas D1 是什么?

该技能基于 D1 超市的 VTEX IO 公共 API 构建,无需管理员密钥即可完全匿名访问商品目录和购物车功能。它自动处理两个会导致自动化出错的陷阱:库存是区域化的(未指定区域查询会返回全国目录,用户无法实际购买),价格以两种不同单位返回(搜索显示整数比索,结账显示百分之一比索,存在 100 倍差异)。技能支持构建和定价购物篮,但不能直接支付,而是输出结账 URL 由人工完成支付。同时提供智能替代商品推荐功能,当商品缺货时自动推荐同类商品并显示价格、规格和健康标签的差异。该技能专为 D1 超市设计,不适用于其他哥伦比亚零售商(如 Éxito、Jumbo、Ara、Alkosto)。支持多种 AI Agent 平台(如 Claude Code、Cursor、Codex),通过命令行接口提供所有功能,并输出结构化 JSON 供机器处理。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/broomva/skills/tree/HEAD/skills/commerce/d1-cli

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

d1-cli — 从命令行操作 Tiendas D1 是做什么的?

D1 是哥伦比亚最大的硬折扣连锁超市。其线上门店运行在 VTEX IO 上(账号 d1tiendas),这意味着网站的公开 API 就是集成界面——无需爬虫,无需管理员凭据。

调用

cd skills/commerce/d1-cli

# 1. 首先解析配送地点——其他所有操作都依赖于它
bun run src/cli.ts region --lat 4.6486 --lng=-74.0628

# 2. 然后搜索:价格和库存现在基于您的门店,而非全国
bun run src/cli.ts search leche entera --count 5
bun run src/cli.ts search --facets category-1/lacteos-y-huevos --sort price:asc

# 3. 在不修改购物车的情况下为购物篮定价
bun run src/cli.ts quote 262:2 892:1

# 3b. 或者让预算决定购物内容——按条件而非SKU
bun run src/cli.ts basket --budget 30000 arroz leche aceite huevos

# 4. 或者创建一个真实的购物车,然后交由人工支付
bun run src/cli.ts cart add 262 --qty 2
bun run src/cli.ts cart deliver-to
bun run src/cli.ts cart checkout      # 输出URL;不执行支付

在任何命令后添加 --json 可获取机器可读的输出。退出码是约定,以下列表是唯一副本:

代码含义是否重试?
0操作成功—
1D1 拒绝或无法访问——无法配送的地点、不可用或未知的SKU、服务中断是,可能有帮助
2命令调用错误重试无意义
3操作成功,但结果为空(substitute、basket)重试无意义

无法区分这些的智能体要么永远重试一个输入错误,要么在暂时性故障时放弃。3 存在是因为空类别既不是错误也不是正常结果。

注意 cart add 是设置该商品数量为 --qty,而不是增加。这是 D1 自身的语义,已通过实际测试验证。

导致简单 D1 自动化出错的两件事

库存是区域化的。 不指定区域查询商品目录,D1 会从全国目录返回结果,显示 10,000 件库存,卖家为虚拟的 1。将同一个SKU放到真实地址的结账模拟中,结果返回 withoutStock,因为实际负责配送的实体店没有该商品。始终先使用 d1 region;当显示全国价格时,CLI 会以纯文本形式发出警告。

解析区域也是 API 中最难以猜测的部分:坐标必须按 geoCoordinates={lon};{lat} 的格式传入——分号分隔,经度在前。使用逗号(VTEX 自己的 JSON 体中使用的同一对格式)会被拒绝并返回 CHK0119("地址必须包含邮政编码或地理坐标")——这条消息看起来像是参数缺失而非格式错误。test/region.test.ts 测试文件固定了此行为,防止后续清理时被意外修改。

价格以两种单位返回。 对于 SKU 262(Leche Entera Latti 900 ml,货架价 COP 3,500):

API字段值单位
intelligent-searchPrice3500整数比索
catalog_systemPrice3500.0整数比索
checkout orderFormsellingPrice350000百分之一比索

两者均未标注其单位。catalog.ts 在边界处将所有价格统一转换为百分之一,因此其余代码只使用一种单位,并且测试断言搜索来源的价格与结账来源的价格显示完全相同。

它不会做什么

d1 构建并定价购物篮。但不会支付。d1 cart checkout 输出一个 URL,人工审核总金额并完成支付。

该边界在 src/endpoints.ts 的一个列表中被两个地方检查:运行时,D1Client.request 在任何请求离开进程之前,如果解析后的 URL 不是 D1 自己的源且不属于 18 个已批准的路径之一,则会拒绝该请求;静态检查,test/safety.test.ts 会测试 src/ 下任何 /api/ 字面量是否未获得批准。添加端点(包括支付或其他)会失败,直到将其列入白名单,因此必须做出明确决策,而非默认生效。

运行时的检查是关键的,因为在审查后发现仅凭静态扫描是不够的:--facets '../../../..' 可以从搜索端点解析到订单结算,而所有源字面量仍然保持未批准状态。

准确地说,因为早期版本对此描述过于绝对:任何拥有写入权限的提交者都可以编辑白名单。仓库内的测试无法阻止这一点。

它存储的唯一凭证是店铺会话令牌——与登录后的浏览器持有的相同,范围限定为其所有者自己的订单和购物车——写入 ~/.config/d1-cli/session.json,权限为 0600。没有在任何地方读取 VTEX 管理员的 appKey/appToken。登录通过一次性邮件验证码进行;密码认证故意未实现。

结账关卡——始终以此结束

每次购物篮都应以 d1 cart checkout 结束,并根据其退出码采取行动。 这不是形式:它是唯一重新检查整个购物车与 D1 当前状态的命令,而购物车会在其他命令无法察觉的情况下过期。

0  所有商品均可配送——URL 可以安全交给用户
1  至少有一个商品无法配送;URL 已输出但购物车已损坏
2  命令调用错误

此行为的存在是因为在真实购物篮中每种情况都发生过:

  • 某个商品一夜之间售罄。 PAN ARTESANAL INTEGRAL 在添加后几小时变为 no tiene inventario。购物车仍然显示,仍然有总金额——一个悄悄少了 6.490 比索的总金额,因为失效的商品已从总额中剔除。
  • 地址更改导致所有商品无法配送。 九个商品返回 cannotBeDelivered,而每个商品仍携带有效的 SLA,购物车仍显示可支付的总金额。
  • 配送费被低估了 12 倍,因为按商品分配的配送费看起来像是总金额。

在所有三种情况下购物车看起来正常。会话早期获取的报价并不能代表购物车当前的状态,因此永远不要交出在最后一次修改之前获得的结账 URL——重新运行关卡。

当返回 1 时,--json 会提供 undeliverable[] 数组,列出无法配送的商品行,以及 readyToCheckout: false。删除或替换这些商品行,然后重新运行。

替换 D1 无法供应的商品

d1 substitute 192 --limit 5        # 从相同类别中排名有库存的商品

退出码 0 表示有可推荐的商品;3 表示没有——这是使用 3 的两个命令之一,另一个是 d1 basket。

使用 3 而非 1,这一区分是关键:1 在此 CLI 的其他地方均表示 "D1 拒绝或无法访问",并建议重试。空类别不会因重试而变成非空,因此采用重试-1 策略的智能体会永远循环下去。退出码 0 返回空列表是另一个错误答案——它看起来像成功,会被当作有效结果处理。

每个推荐商品都列出了变更内容:品牌、包装规格、每公斤/升价格、整包价格,以及任何新增或移除的 Ley 2120 警告标签。这是输出内容,而非评分。同样的 900 ml 规格、同样标签的商品降价 12% 与增加了 "Exceso en Azúcares" 警告标签的商品是不同的,只有差异才能区分它们。

推荐而非直接替换。 substitute 从不修改购物车——它输出 d1 cart add 命令供人工批准。这并非出于谨慎而谨慎:用户两次明确表示宁可删除商品也不要错误的替换,且两次都是正确的。呈现候选商品及其权衡;由用户决定,并愿意删除该商品。

三个值得关注的信息:

  • "该商品在您门店仍有库存。" 库存按门店划分,因此在其他地方缺货的商品在此处可能正常。在替换前先检查。如果没有提供 --lat/--lng,它会直接说明而不是猜测——因为没有门店可以做出按门店的声明。
  • "扩展到第 2 级(共 3 级)" ——最细粒度的类别中没有有库存的商品,因此推荐来自更宽泛的分类,相应地更加宽松。
  • "仅比较了 N 个商品" ——该类别大于一页。增加 --count 参数。这在返回空结果时也会输出,因为 "此处无任何商品有库存" 的断言基于部分扫描,更需要这一说明。

当需求模糊时查找商品

对于 "我们需要大米" 而非 "购买 SKU 1092",有两个维度很重要,但都不是默认选项:

按单价而非总价排序。 --sort per-unit 使用哥伦比亚法律要求 D1 发布的 PUM 数据。两种排序方式确实存在分歧:ARROZ ESTÁNDAR 500 GRS 是总价最便宜的,售价 $1.550,每公斤 $3.100,而同一搜索结果中最具性价比的是每公斤 $2.775——来自一包 $5.550 的袋子,它根本不会出现在总价前五名中。按总价排序会给出更差的答案,尽管看起来正确。

由于 D1 的搜索无法按此排序,--sort per-unit 仅对您已获取的页面进行排序,而非整个结果集。增加 --count(最大 50)以扩大范围。输出会明确说明这一点,而非暗示无法支持的绝对最优,并指出有多少结果未发布规格而无法比较。

多包装的声明规格是整包规格,而非单件规格——不要 "更正" 它。 对所有 1,600 种商品的普查发现,在名称可匹配的多包装中,D1 足以做出判断的 46 种里有 44 种声明的是整包总量。从产品名称中解析出 N UN 并乘以单件规格会损坏这 44 种以修复 2 种。名称中的数量并非 PUM 含义的证据。

因此,resolvePackSize 读取的是描述而非名称。在所有 1,548 种带有 PUM 的商品中,它对描述中同时说明了单件规格和包装数量的 10 种商品执行操作:三种被更正(SKU 718、510、1008),七种被确认为已正确声明整包规格,其余商品保持原样。

阅读警告标签。 产品带有哥伦比亚的前置包装警告(Exceso en Azúcares、Exceso en sodio、Exceso en grasas saturadas、Exceso en grasas trans、Contiene Edulcorantes),位于 --json 输出的 warnings[] 中。覆盖率不完整——按类别大约 70–90%——因此缺失意味着 "未声明",而非 "安全"。

然后在使用 d1 facets <query>(按类别、品牌、子类别统计数量)缩小范围后再进行分页:搜索最多 50 页,因此宽泛的查询最好通过分类来缩小,而非逐页浏览。

命令

命令功能
region --lat --lng解析并记住配送地点
search <query>查找商品(--facets --sort --count --page --available)
suggest <partial> · trending自动补全 · 哥伦比亚的热搜商品
categories · facets [query]部门树 · 查询的筛选条件
substitute <sku>推荐的替代商品及其变更(--limit --count)
quote <sku>[:qty]...为购物篮定价,不修改购物车
cart [show|add|set|clear|deliver-to|checkout]构建购物篮
login --email / --from-cookie · whoami · logout账户管理
orders · order <id>订单历史(详细信息被白名单限制;--raw 选择加入)
stores near附近的 D1 门店——仅限位置信息,D1 不提供自提服务

测试

bun test        # 货币单位、分号陷阱、报价中的数量、未知SKU的处理、
                # 购物车标准化、订单信息脱敏、以及限制支付范围的端点白名单
bun run lint && bun run typecheck

退出码是约定而非装饰——调用 部分下的表格是其唯一副本。

完整端点映射、配送层级行为以及公共 API 无法提供的内容,请参见 README.md。

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

broomva/skills

Local TTS, voice cloning, voice design, and video dubbing via the OmniVoice Studio MCP server (open-source ElevenLabs alternative; nothing leaves the machine, runs on MPS/CUDA/CPU). Use when: (1) generating speech from text in any of 646 languages, (2) cloning a voice from a 3-second reference clip, (3) designing a voice by gender/age/accent/pitch/style, (4) dubbing a video into another language, (5) listing voice profiles or personality presets, (6) producing narration where privacy, cost, or absent API keys matter, (7) non-English narration where Edge TTS/kokoro fall short, (8) batch audio for blog posts or content pipelines. Triggers: 'omnivoice', 'voice clone', 'clone this voice', 'tts', 'narrate', 'generate speech', 'voice synthesis', 'dub video', 'voice design', 'local tts', 'multilingual voice', 'narrate this post', 'elevenlabs alternative'.

broomva/skills

>- Speak an explanation out loud while working in any project — tiered text-to-speech with a pluggable backend (ElevenLabs by default and quota-guarded, macOS `say` via `--fast` for free instant local speech, local OmniVoice as an unlimited private tier). Markdown-aware, so code fences, URLs and deep paths collapse to short spoken placeholders instead of being dictated character by character, while snake_case identifiers survive intact so the listener can still search for them. Every utterance is saved to disk for later replay. Also carries a **talk mode** toggle: turn it on and the agent speaks a full readback of every turn, for as long as that session lasts — the whole response, not a summary of it, with `brief` and `marker` levels for when you want less. Talk mode is off by default and scoped to the single session that enabled it, so parallel agents in other worktrees stay silent. Use when the user asks to hear something rather than read it — an explanation of a change, a walkthrough of what just happen...

broomva/skills

Stateful, local-first household toxics inventory + swap engine. Identify the items in a home that carry endocrine disruptors and persistent chemicals (BPA/BPS, phthalates, PFAS/PTFE, parabens, flame retardants, VOCs, microplastics), score each by *real* exposure (severity x presence x how it's used x condition), and track the swap to a safer alternative from "flagged" -> "sourced" -> "swapped". Ships a grounded, cited knowledge graph of ~20 hazards, ~40 item-classes, and ~40 alternatives. Hands sourcing off to the `procurer` skill. The skill's state is the source of truth — the agent is the app.

broomva/skills

Tekton — the shared architecture-intent substrate for co-designing systems with the agent. One typed graph across six tiers (system / journey / data / infra / decisions / qualities); views are queries, not separate diagrams. The canonical artifact is a diff-friendly YAML model both human and agent read and write; it renders to Mermaid (agent-legible, GitHub-native) and a self-contained tabbed HTML viewer (human-visual). Cross-tier traceability (`tekton query <from> <to>`) answers "which infra does this user-journey step touch?" as a path query. USE WHEN: designing or thinking deeply about architecture, a system, a data model, user journeys/flows, or a technical plan WITH the agent; when a Category-C HTML doc isn't enough because you need to see AND edit AND traverse the design across tiers; "let's design X", "architect this", "model the system", "draw the flow", "how does this fit together", "diagram this", "/tekton". NOT FOR: a one-off throwaway diagram (use Mermaid inline); prose-only ADRs (write the ADR...

broomva/skills

Generate a polished Remotion video and X thread showcasing the full agent skills inventory. Use when creating social media content about skills, rendering category-based skill visualizations, or producing animated showcases of agent capabilities. Triggers on "skills video", "showcase skills", "skills thread", "render skills", "social content for skills", or requests to visualize the skills inventory.

broomva/skills

OpenCaptions extension for Content Engine — adds intent-driven CWI (Caption With Intent) captions to the post-production pipeline. Hooks into the grade → caption → final stage. Generates captions that understand video intent (pitch, volume, emotion, emphasis) and style themselves accordingly with variable font weight, size, and color. Uses the OpenCaptions CLI or MCP server. Triggers on: 'add captions', 'opencaptions', 'CWI captions', 'intent captions'.

broomva/skills

Produce polished product launch videos using the Liquid Glass aesthetic — dark void backgrounds, 3D perspective floating UI panels, particle effects, spring animations, and cinematic pacing. Built on Remotion with Imagen 4.0 for frames and Veo 3.1 for B-roll. Use when: (1) creating a product demo or launch video, (2) showcasing a UI/app/tool with cinematic polish, (3) building a social-ready video from screenshots and renders, (4) applying the liquid glass floating panel style, (5) composing Remotion videos with 3D transforms and spring animations. Triggers on: 'launch video', 'product video', 'liquid glass video', 'demo video', 'showcase video', 'remotion video', 'floating panel', 'glass aesthetic'.

相关技能