关于 shoplazza-common
shoplazza-common 为使用 Shoplazza CLI 的 Agent 提供跨模块基础规则,涵盖命令选择、输出处理、认证、模式查询和安全操作流程。
主要功能
- 01三级命令选择规则
- 02结构化输出与 jq 指引
- 03认证与配置档案设置
- 04模式查询
- 05Dry-run 安全指引
- 06筛选列表结果验证
适用场景
- 01为操作选择合适的 CLI 命令
- 02验证筛选列表结果
- 03设置店铺访问与配置档案
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ shoplazza/ shoplazza-cli --skill shoplazza-common安装后在 Claude Code 中输入/shoplazza-common确认已加载。
详细介绍
shoplazza CLI — 共享基础(shoplazza-common)
此技能是每个领域技能(shoplazza-discounts、shoplazza-products,……)的基础:它负责所有跨领域的机制,因此领域技能无需重复这些内容;每个领域技能都会在开头要求先阅读此文件。命令和参数的权威来源是 shoplazza <svc> <cmd> --help 和 shoplazza schema——此文件讲解使用机制,不会记忆各个标志。
使用用户所用的语言回复。 技能说明使用英文,但这并不决定你的回复语言——应与用户的语言一致(中文提问 → 中文回答),包括反问、复述写入确认内容和解释错误时。CLI 命令、标志和字段名称保持原样(不翻译)。
访问层级
每次操作都从最符合需求的最高层级开始,一旦某个层级能够表达需求就停止:
| 层级 | 形式 | 适用场景 |
|---|---|---|
| 1. 快捷方式 | shoplazza <svc> +<verb> [named flags] | 首选。具名标志、智能默认值、结构化错误。 |
| 2. 规格叶节点 | shoplazza <svc> <cmd> --params '{…}' [--data '{…}'] | 没有快捷方式的端点;每个端点对应一条命令。 |
| 3. api rest | shoplazza api rest <METHOD> <PATH> | 原始回退方式,覆盖范围完整。仅在前两种方式无法表达需求时使用。 |
在 shoplazza <svc> --help 中,以 + 开头的条目是快捷方式;其他条目是规格叶节点。
输出封装(.data 包装层)
所有命令都遵循统一的结构化输出约定:
- 成功 → stdout:
{"ok":true,"data":<body>} - 失败 → stderr:
{"ok":false,"error":{"type":…,"message":…}},并以非零状态码退出。
响应正文嵌套在 .data 下,因此所有 jq 路径都从 .data 开始(例如 .data.products[].id)。忘记加上 .data 前缀是最常见的提取错误。
例外——本地命令没有封装层。 auth status / auth scopes /
profile list 会在顶层直接输出对象(没有 {ok,data},也不支持 --jq);
直接读取字段(例如 logged_in)。
常用标志
| 标志 | 说明 |
|---|---|
--dry-run | 打印将要发送的请求,但不发送。对于破坏性操作、批量操作或涉及花费资金的写入,务必先使用 --dry-run。读取命令和快捷方式也支持此标志。 |
-q, --jq <expr> | 使用 jq 表达式筛选 JSON 输出。默认输出原始标量(不带引号,只在末尾添加换行符)——不要添加 -r:cobra 会将 -r 解析为单独的标志并拒绝该命令。此标志仅接受单个字符串。 |
--fields <f1,f2,…> | 仅少数快捷方式支持响应字段投影——已验证:products +search(逗号分隔:products +search --fields id,title)。并非通用标志——大多数命令不支持 --fields;使用前请检查 <shortcut> --help。名称对应响应键;服务端仍可能返回额外的基础字段,并会静默忽略未知名称。 |
--page-limit <n> | 列表快捷方式的页面大小,范围为 1–250。API 默认值为 10——请参阅下文“读取筛选列表”。 |
--format json|pretty|table | 输出格式,默认为 json。脚本和 jq 使用 json,面向人类阅读时使用 pretty / table。全局标志。 |
--profile <name> | 本次调用使用的配置文件(参阅“配置文件”)。全局标志。 |
字段投影:少数搜索快捷方式接受 --fields(请使用 --help 确认);其他情况下,请使用 --jq 进行投影或筛选。
阅读经过筛选的列表
读取返回 {"ok":true,…},并不能证明你得到的筛选结果或页面就是你请求的结果。有两种失败模式不会提示,而且都会给出一个看似可信的错误答案,而不是报错:
1. 截断——默认页面大小为 10。 列表端点默认返回 10 条记录,除非另行指定 --page-limit(最大为 250);其余记录由 has_more / cursor 标记。has_more 可能返回 null 而不是 false,因此应将“不是 true”视为结束。只要答案取决于完整性——例如“有多少”“有哪些”“所有 X”,或你自行计算的任何总数——就传入 --page-limit 250 并跟进游标。若只需计数,优先使用该领域的 +count 快捷方式,而不是逐行计数。
2. 筛选条件被静默丢弃——API 会忽略它无法识别的查询参数。 它不会返回 400。参数名已变更的标志会返回 200 和未筛选的结果,看起来就像“这位客户确实有这么多订单”。
因此,在将筛选读取结果作为答案或用于写入之前,请确认筛选条件已生效:
shoplazza <svc> +search --<filter> <value> --dry-run # 1. which param actually goes on the wire
shoplazza <svc> +count # 2. unfiltered total, for comparison
shoplazza <svc> +count --<filter> <value> # 3. filtered total — must be < the unfiltered one
筛选结果与未筛选总数相同,就是警示信号。 通过抽查返回的记录是否确实符合筛选条件(对筛选字段使用 --jq)来确认。如果筛选条件被丢弃,schema <svc>.<cmd> --view request 会列出该端点实际接受的参数——请使用规范中的具体叶节点,或使用带文档所述参数的 api rest。
精确度阶梯——如果端点提供多种方式来筛选同一内容,应优先使用范围最窄的方式:专用的精确匹配参数(通常是数组,例如 customer_emails、skus、order_tags)优于通用的关键词搜索,而关键词搜索又优于使用 --jq 在完整页面上手动筛选。精确参数会明确说明匹配内容;关键词搜索可能匹配到你无意查找的字段。
选择哪一层级——看用户的动词。 用户的措辞会说明他们指的是完整值还是片段,据此决定使用精确匹配还是关键词搜索:
| 用户的信号 | 含义 | 层级 |
|---|---|---|
「是 / 为 / 等于 / =」、「编号 / 号码 / 值 is X」,或可自我标识的完整字符串(完整邮箱、完整 SKU,例如 ABC-001、完整电话号码) | 完整值 | 精确匹配数组参数 |
「包含 / 含 / 像 / 类似 / 以…开头 / 前缀 / 片段 / 部分」、X*、contains / starts-with / like | 片段 | 关键词搜索 |
「是 / equals」是具有决定性的精确匹配信号,即使它紧挨着字段名称也是如此——应匹配完整值,不要进行模糊搜索。
说明依据,而不只是数字。 根据列表读取结果作答时,请说明使用了哪个筛选条件,以及完整性依据是什么(“3 条中的 3 条,未筛选总数为 18”)。这样就能让被丢弃的筛选条件对用户可见,而非悄无声息。
先定位,再操作。 写入操作通过记录的 id 定位,但用户会用其他信息来指明记录(订单号、代码、邮箱、标题)。先读取并解析目标,再根据匹配数量采取相应操作:
- 0 条匹配 → 停止并说明情况;不要改用更宽泛的写入方式,也不要臆造 id。
- 恰好 1 条 → 继续操作(若涉及破坏性操作 / 金钱操作,仍需使用
--dry-run并复述确认)。 - 2 条或更多匹配 → 列出候选项并询问用户要选哪一个。绝不要猜测,也不要默默对“第一条”采取操作。
数字不是 id(例如订单号与内部的 order_id 并不相同)——在需要另一种值的地方使用它,会操作错误的记录或导致报错。通过读取结果解析,不要想当然。
Schema 自省
调用任何规范叶节点或 api rest 之前,请检查 schema,以确认参数 / 请求体 / 响应的形状——不要猜测字段:
shoplazza schema # list all modules
shoplazza schema discounts # list a module's commands
shoplazza schema discounts.get # a command's params / body / response
shoplazza schema orders.create --view request # request side only (--view all|request|response)
REST API 回退
仅在前两个层级无法表达时使用。填写解析后的真实 URL(而非 {…} 模板):
shoplazza api rest GET /openapi/2026-01/products
shoplazza api rest GET /openapi/2026-01/products/gid_123 --params '{"page_size":10}'
shoplazza api rest POST /openapi/2026-01/discounts/automatic --data @body.json
支持 --params / --data(包括用 - 表示标准输入、用 @file 表示文件)、--dry-run、-q/--jq。
大整数 ID → 在 JSON 中加引号。 在 --params / --data 中,将较大的数字 ID 作为字符串传入({"id":"669923000979557666"}),不要使用裸数字——裸的大整数会被转换为浮点数(→ 6.69…e+17),导致请求被拒绝。适用于所有超过约 15 位的 ID(例如 shop redirects)。
安装
CLI 预检查
如果找不到 shoplazza(command not found),或 shoplazza --version 执行失败,则表示尚未安装 CLI。安装会更改用户的计算机:说明你将使用哪种方式,并等待用户同意。根据计算机上已有的工具选择安装方式:
| 方式 | 命令 | 适用情况 |
|---|---|---|
| npm(推荐) | npm install -g shoplazza-cli | 已安装 Node.js ≥ 16(node -v) |
| Homebrew | brew install Shoplazza/tap/shoplazza-cli | 使用 brew 的 macOS / Linux |
| 安装脚本 | curl -fsSL https://raw.githubusercontent.com/Shoplazza/shoplazza-cli/main/install.sh | bash | 未安装 Node 的 macOS / Linux;安装到 /usr/local/bin(使用 INSTALL_DIR=<dir> 更改) |
| Release 二进制文件 | 从 https://github.com/Shoplazza/shoplazza-cli/releases 下载 | 其他平台;将其放到 PATH 中 |
然后用 shoplazza --version 确认,并继续执行下方的登录流程。如果安装失败——例如沙盒阻止安装、权限遭拒,或需要 sudo——请停止操作,并将确切的命令交给用户,让其在自己的终端中运行。
- 只能使用一种安装方式。 安装两次会导致
PATH中出现两个运行不同版本的shoplazza二进制文件;which -a shoplazza可列出它们。请保留一个。 - 使用原安装方式更新。
shoplazza update总是通过 npm 重新安装——如果之前使用 Homebrew 或脚本安装,就会多出第二个副本。请改用brew upgrade shoplazza-cli或重新运行安装脚本。
首次设置,全流程
shoplazza --version # installed?
shoplazza auth login -s my-store.myshoplazza.com --domain products,orders # login + bind a store
shoplazza auth status # logged_in: true, the store under profiles
在后台运行登录流程,并将授权 URL 提供给用户(见下方的 Agent 驱动登录流程)。询问用户需要哪个商店和哪些模块;不要猜测商店域名。
身份验证(auth)
登录状态预检查
在会话中首次操作商店前,运行 shoplazza auth status(本地执行,即时返回,无需 envelope)。以下两项必须同时满足:
logged_in: true——存在账户凭据。如果为false→ 运行下方的登录流程。profiles非空——已绑定商店。即使logged_in: true,若profiles: [],仍无法访问任何商店 API;询问用户要连接哪个商店,并运行auth login -s <store> --domain <modules>。
如果跳过预检查,未通过身份验证的业务命令会快速失败并返回 validation 错误——包含 "no profile configured" 以及说明修复方法的 hint。按同样方式处理:不要重试,应先引导用户完成登录。
登录
授权分为两个层级:账户级(auth login 获取账户凭据)和商店级(为特定商店交换商店令牌,并将其存储在配置文件中)。
# Account-level login (no store bound)
shoplazza auth login --domain products,orders # or --scope read_product,write_product
# Store-level login (select a store; an interactive login with -s must also pass --scope or --domain)
shoplazza auth login -s my-store.myshoplazza.com --domain discounts
--domain <module,…>:按顶层命令名称授权;CLI 会将每个名称扩展为相应模块所需的 OAuth 作用域。选项:app, billing, checkout, customers, discounts, orders, products, shop, themes, webhook, all。优先使用——无需记忆具体的作用域字符串。--scope <literal,…>:指定细粒度的 OAuth 作用域(例如read_product,write_product),遵循最小权限原则。- 重新登录会替换原有授权(已通过实时验证:拥有 22 个作用域的授权在仅使用一个作用域重新授权后,只返回了一个作用域)。要补充权限?传入
--merge-scopes以保留原有授权(较旧版本的 CLI 不支持此标志——请通过auth scopes自行合并作用域;--domain和--scope可在同一次登录中组合使用)。仅当用户明确希望缩小权限范围时才省略此标志。
Agent 驱动的登录流程
作为 AI Agent 为用户登录时:在后台运行 auth login(它会阻塞并轮询,直到用户完成授权或超时——参见 --poll-interval / --timeout,默认值为 2s / 300s),从输出中提取授权 URL 并交给用户;用户授权后,命令会自行返回。
有终端时,缺少的标志会变成屏幕上的问题。 仅当 stdin 和 stderr 都是真实终端,且未设置 SHOPLAZZA_CLI_NO_INTERACTIVE 或 CI(存在且非空即视为已设置)时,auth login(以及 app init)才会询问你遗漏的内容;否则,缺少标志会报错并指出对应标志。为子进程分配 pty 的测试框架会通过该检查,命令会等待一个永远不会到来的按键——如果你的测试框架也会这样做,请在整个会话中导出一次 SHOPLAZZA_CLI_NO_INTERACTIVE=1。
它只会关闭交互式提问。没有 --interactive 标志,也没有强制开启交互的环境变量——这是刻意设计的,因为在没有终端时强制交互会导致程序永久挂起。
重新登录以获取缺少的作用域?传入 --merge-scopes。 作用域会被替换,而非合并(参见上文“登录”);如果只请求缺少的作用域,就会在任务进行中丢失其他所有作用域。如果不支持该标志(旧版 CLI),则改为构建并集:先运行 auth scopes 获取已授权的作用域,再在一次登录中同时请求已授权的作用域和新作用域。
非交互式快速路径(UAT)
如果你已在另一台机器上运行过 auth login,并拥有账户 UAT,可以跳过浏览器:
shoplazza auth login --uat <UAT> # or set env SHOPLAZZA_UAT=<UAT>
无论终端状态如何,--uat 都不会触发提示——它是在上述条件之外,另一个作用于整条命令的关闭开关。通过分配 pty 的测试框架驱动浏览器登录时,仍需设置 SHOPLAZZA_CLI_NO_INTERACTIVE=1。
切换商店和查看状态
shoplazza auth status # auth state / identity / current store
shoplazza auth scopes # supported scopes + scopes granted to the account
shoplazza auth store use -s another-store.myshoplazza.com [--scope …] # exchange a token for that store, set as current profile
shoplazza auth logout # log out of the current store
切换商店的命令:
| 需求 | 命令 |
|---|---|
| 我当前使用的是哪个商店? | auth status — 查看 current: true 的配置(store_domain) |
| 之前用过的商店(已有配置) | profile list → profile use --name <name>(使用 --previous 可切回上一个商店) |
| 尚无配置的商店 | auth store use -s <store-domain> — 创建或复用其配置,并将其设为当前配置 |
| 针对另一个商店运行单条命令 | 为该命令添加 --profile <name>;当前配置保持不变 |
auth store use 和 profile add 需要先登录账户,且配置的作用域必须是账户授权范围的子集——若缺少作用域,运行 auth login --domain <module> --merge-scopes,然后再次切换。
处理权限不足
写入操作返回 401/403 时,错误封装中的 hint 会说明缺少什么权限。按提示授予权限:运行 shoplazza auth login --domain <that module>(或 --scope <missing scope>),然后重试。先运行 auth scopes,查看已授予的权限。
配置(多租户)
一个配置 = 一个商店执行上下文(其商店令牌和作用域)。切换配置即可管理多个商店:
shoplazza profile add --name prod-us -s my-store.myshoplazza.com [--scope …] [--use]
shoplazza profile list
shoplazza profile use --name prod-us # or --previous to switch back to the last one
shoplazza profile info [--name prod-us] # defaults to the current profile
shoplazza profile rename --from old --to new
shoplazza profile remove --name prod-us
shoplazza profile update --name prod-us --scope … # adjust a profile's scopes
每次调用时的覆盖设置:全局标志 --profile <name> 的优先级高于环境变量 SHOPLAZZA_CLI_PROFILE 和当前配置。
更新通知
CLI 运行后检测到新版本时,会向 stderr 输出一行通知(⚡ shoplazza-cli X is available …)。它绝不会出现在 stdout 的 JSON 中。不要默默忽略此通知:完成用户当前请求后,告知他们当前/最新版本,并询问是否要更新:
shoplazza update # update via npm (--check only reports versions, no install)
# or: npm install -g shoplazza-cli@latest
通过 Homebrew 或安装脚本安装的?请使用相同方式更新(参见 Installation)。
(设置 SHOPLAZZA_CLI_NO_UPDATE_CHECK 可禁用检查。)
update 会执行三项操作,并在 JSON 正文中分别报告:
| 字段 | 含义 |
|---|---|
updated | 已重新安装二进制文件。false = 已是最新版本,并非失败 |
meta_updated / meta_revision | API 元数据缓存已重写,以及对应的修订版本 |
skill_installed | Agent Skills 已安装——仅此而已 |
skill_installed 表示“是否已安装”,而不是“是否刚刚刷新”:当它为 true 时,shoplazza update 会刷新这些技能,但 update --check 也会报告相同的 true,却不会刷新任何内容;即使刷新失败,该字段仍会报告 true(并在 stderr 中显示警告)。切勿仅凭此字段告诉用户技能已更新——请读取 stderr 行(✓ Refreshed N skill(s))确认。
这些技能需要主动选择安装:false 表示用户从未安装过这些技能,update 因此不会安装它们。安装方法:
npx skills add Shoplazza/shoplazza-cli -g
(设置 SHOPLAZZA_CLI_SKIP_SKILLS=1 可跳过技能步骤;此时该字段会从正文中完全消失——字段缺失表示“已跳过”,false 表示“未安装”。)
安全协议
shoplazza-cli 没有类似 Lark 的 exit-10 高风险写入门控,也没有 --yes 确认标志。不要臆造确认流程。 安全模式为 --dry-run → 重述 → 等待用户同意:
- 对破坏性(取消/删除)、批量或资金转移(账单扣款)操作,先运行
--dry-run:打印将要发送的请求,重述请求,然后立即停止并结束本轮回复。对于通过+shortcut创建实体/营销活动(例如创建折扣),请遵循相应领域技能——+shortcuts采用结构化方式,一旦确认了必填且影响金额的值(绝不可捏造),即可直接运行;只有用户提出要求时才使用--dry-run。 - 同意必须来自用户消息,而非你自己的判断。 展示 dry-run 不代表同意;你自行审查也不代表同意。只有在用户明确同意后的轮次中,才可运行实际命令(例如“确认”/“yes / go ahead”)。在同一轮中先运行 dry-run 再执行实际写入,违反协议,即使 dry-run 输出完全正确也不例外。
- 执行 dry-run 时重述用户意图:用浅白语言说明涉及哪个商店、执行什么操作以及关键参数,让用户确切知道自己同意的内容。
- 不要捏造会花费资金的值(折扣金额/上限/价格)——默认值可省略,否则应询问;请参阅各领域技能中的必填项与询问项说明。
- 仅在 dev / stg 商店中演练写入操作;绝不可在 prod 上练习。
命令发现
shoplazza --help # top-level modules
shoplazza <svc> --help # a module's shortcuts + spec leaves
shoplazza <svc> <cmd> --help # a command's flags
shoplazza schema <svc>.<cmd> # params / body / response shape