setup-embedded-app-ver…
One-time setup for the Shopify embedded-app verify loop in a project. Use when the user asks to set up / configure the verify loop, or when the…
Verify a Shopify embedded-app change by driving the real, authenticated Shopify admin in the developer's browser. Use after changing app code when the user asks to verify, check, or test the change in the browser/admin, or asks to run the verify loop.
$ npx -y skills add mrmarufpro/shopify-embedded-app-verify --skill run-embedded-app-verify --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/run-embedded-app-verifyContext preview
The summary Claude sees to decide when to auto-load this skill.
Verify a Shopify embedded-app change by driving the real, authenticated Shopify admin in the developer's browser. Use after changing app code when the user asks to verify, check, or test the change in the browser/admin, or asks to run the verify loop.
name: run-embedded-app-verify description: Verify a Shopify embedded-app change by driving the real, authenticated Shopify admin in the developer's browser. Use after changing app code when the user asks to verify, check, or test the change in the browser/admin, or asks to run the verify loop.
Closed loop: preflight → dedicated verify window → navigate the embedded app → interact → assert against the plan → report. On mismatch: fix the code and loop.
Hard rules:
probe it — do not curl the `application_url` from `shopify.app.toml` or any tunnel URL: `shopify app dev` mints a fresh tunnel URL per run, so the toml value may not be the one actually serving. Judge dev-server health only by what the app iframe renders (step 4). If it is down, tell the user and stop.
the browser belongs to the developer.
Read `.claude/shopify-verify.json` in the project root:
{ "appHandle": "...", "storeDomain": "...", "iframeSelector": "iframe[name=\"app-iframe\"]" }If the file is missing, run the `setup-embedded-app-verify` skill flow first (same plugin), then continue.
1. Determine the verification URL first — the preflight opens the browser directly on it when it has to launch one: `https://admin.shopify.com/store/<storeDomain>/apps/<appHandle>/<page-path>` (`<page-path>` = the app route relevant to the change being verified). 2. Run:
node ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-browser.mjs --browser "${user_config.browser}" --mode "${user_config.mode}" --port "${user_config.cdp_port}" --url "<the verification URL>"(The `${user_config.*}` values are substituted into this skill at load time; blank or literal placeholders are fine — the script defaults to chrome / profile / 9222.)
`launched-at-url`, `launched`, or `reused` — step 3 branches on it.
(`CDP_BLOCKED_DEFAULT_PROFILE` means: tell the user to switch the plugin's mode option to "profile" via /plugin → configure. `BROWSER_MISMATCH` means: a browser other than the configured one owns the CDP port — the user must quit it or change the browser/cdp_port option.) Do NOT probe the dev server or any tunnel URL here (hard rule above) — the app iframe render in step 4 is the only dev-server health check.
Keep the developer's windows untouched.
**Preflight said `BROWSER_STATE: launched-at-url`** (profile mode): the browser opened directly at the verification URL — its only tab IS the verify window. `browser_tabs` (action: list), select that tab, grab its targetId with `browser_run_code_unsafe`, and skip to step 4:
async (page) => {
const session = await page.context().newCDPSession(page);
const { targetInfo } = await session.send("Target.getTargetInfo");
await session.detach();
return targetInfo.targetId;
}**Preflight said `BROWSER_STATE: launched` or `reused`**: the browser's tabs belong to the developer (an attach-mode relaunch restores their session — those tabs are NOT yours, whatever they show). `browser_tabs` (action: list), then:
**Case A — the list shows only blank tabs** (`about:blank` / `chrome://new-tab-page` — a browser nobody is using): reuse that startup window instead of opening a second one. Select it, grab its targetId with `browser_run_code_unsafe`:
async (page) => {
const session = await page.context().newCDPSession(page);
const { targetInfo } = await session.send("Target.getTargetInfo");
await session.detach();
return targetInfo.targetId;
}then `browser_navigate` it to the verification URL.
**Case B — any non-blank tabs exist** (attach mode / browser already in use): open a dedicated verify window directly at the verification URL — no `about:blank` hop — with `browser_run_code_unsafe` (the code is invoked with the current page as its single argument):
async (page) => {
const session = await page.context().newCDPSession(page);
const { targetId } = await session.send("Target.createTarget", {
url: "<the verification URL above>",
newWindow: true,
});
await session.detach();
return targetId;
}Then `browser_tabs` (action: list) and select the newly added entry — the tab that was not in the list before creation (new tabs are appended at the end). Do not pick the first URL match: the developer may already have a tab open on the same admin page.
**In all cases: save the targetId — step 6 closes the window with it.** Every subsequent navigation/interaction happens in this tab only.
1. The verify window already loads the verification URL from step 3 — wait for it. On later loop iterations, reload / `browser_navigate` this same tab instead of opening a new window. 2. If the URL redirects to `accounts.shopify.com`: the Shopify session expired.
to log in there once, wait for their confirmation, retry. 3. Wait for the app iframe (`iframeSelector` from config), then take an iframe-scoped `browser_snapshot`. If it shows a tunnel/connection error instead of the app UI — "server IP address could not be found", `ERR_NAME_NOT_RESOLVED`, `ERR_CONNECTION_REFUSED`, a Cloudflare tunnel error page (e.g. error 1033), or a bare "can't be reached" page — the app's dev server is not running or not reachable. Report exactly that to the user, ask them to check that their
A Claude Code plugin that closes the verification loop for agentic Shopify embedded-app development: the agent changes code, then drives your **real, authenticated** Shopify admin — in your own browser — to check the result against the plan, repeating until
Repo: mrmarufpro/shopify-embedded-app-verify
One-time setup for the Shopify embedded-app verify loop in a project. Use when the user asks to set up / configure the verify loop, or when the…