Online store
Sellify CLI
Build themes in your own editor: pull a theme, edit locally and see every save on a preview link. Start and run apps locally, and run Admin API queries from the terminal.
Install & log in
npm install -g sellify-cli # Node 20+, no other dependencies
sellify login # opens your browser- 1Your browser opens the Sellify admin. Sign in (password or Google) if you aren't already, and pick the store.
- 2Check the computer name and click Allow.
- 3The terminal says you're logged in. The token went straight from the browser to the CLI and is saved in
~/.config/sellify/config.json, readable only by you. You never see or copy it.
A browser login acts as you with theme access only (plus your own apps in the Partner dashboard, for sellify app), and needs Online store edit access. It stops working if that access is removed, and the store owner can sign it out under Apps → Develop apps → Sellify CLI logins. Under the hood this is OAuth for native apps: a one-off listener on 127.0.0.1, a one-time code and a PKCE verifier only the CLI knows.
Pass --store mystore to skip the store picker, --url for another Sellify deployment (default https://admin-sellifyhq.vercel.app) and --no-browser to print the link instead (for SSH sessions).
Theme development
mkdir my-theme && cd my-theme
sellify theme pull # download the live theme
sellify theme dev # sync every save to a development theme; prints a preview link
sellify theme push --unpublished # upload as a new unpublished theme
sellify theme publish --theme <id> # make it livetheme dev uploads to a theme named Development (your computer), never the live theme unless you pass --theme. Refresh the preview after saving. Each file is checked like in the code editor (Liquid syntax, section schemas, JSON templates); a file with errors is reported and skipped while the rest keep syncing.
--allow-live skips the question.Commands
| Command | What it does |
|---|---|
theme list | Themes in the store, live theme first, with their ids |
theme pull [--theme id|live] [--only prefix] [--nodelete] | Download changed files. Local theme files that no longer exist remotely are removed unless --nodelete |
theme push [--theme id|live] [--unpublished] [--publish] [--only prefix] [--nodelete] | Upload files whose checksum changed and delete remote files you removed (required files are always kept) |
theme dev [--theme id] | Push once, then upload each save |
theme open [--theme id] | Preview link (signed, 4 hours, for unpublished themes) and code editor link |
theme publish --theme id | Make a theme live |
theme delete --theme id [--force] | Delete an unpublished theme |
whoami / logout | Show or forget the saved login |
The commands use the Admin API theme fields: themes, theme(id) with files (path, size, MD5 checksum, content), and the mutations themeCreate, themeFilesUpsert (up to 50 files, 5 MB per call), themeFilesDelete, themePublish and themeDelete.
App development
Build a public app without setting up OAuth by hand. The starter app has no dependencies (Node 20+): it installs with OAuth, shows a page built with the Admin API and receives signed webhooks.
sellify app init order-pinger # new folder from the starter template
cd order-pinger
sellify app dev # creates the app in your Partner dashboard, runs it, prints an install link- 1
app devcreates the app on first run (or links an existing one withsellify app link) and saves its client ID and secret to.env, readable only by you. - 2It starts
server.mjs, points the app's URL, redirection URL, scopes and app/uninstalled webhook at it, and printsInstall …/install?store=yourstore. - 3Open the install link, click Install app, and you land on the app's page. Saving a file restarts the app.
Webhooks need a public URL. If cloudflared is installed, app dev opens a free tunnel for you; or pass your own with --tunnel-url https://… (ngrok and similar). Without one, installs and API calls work and webhooks are off.
| Command | What it does |
|---|---|
app init [dir] [--name name] | New app folder from the starter template |
app dev [--port 3456] [--tunnel-url url] [--no-tunnel] | Run the app locally with the right URLs and credentials, and print an install link |
app link [--app id|client_id] [--create] | Connect the folder to one of your apps (or a new one) and write its credentials to .env |
app deploy | Point the app's URLs, scopes and uninstall webhook at application_url (your https production URL) |
app info / app list | The linked app's settings / all your apps |
Settings live in sellify.app.json: name, scopes, webhook_topics (subscribed by the app after each install), redirect_path, webhook_path, dev_command, dev_port, application_url, embedded and embeds (below).
app dev refuses to change it (merchants' installs would point at your computer). Develop against a second app: sellify app link --create.Inside the Sellify admin (embedded apps)
With "embedded": true in sellify.app.json (the starter's default) merchants use your app inside Sellify at Apps → your app, not in a new tab. Sellify loads your app URL in an iframe with the signed launch link plus embedded=1, admin (the admin origin) and id_token. After the OAuth callback, send merchants to {admin}/store/{store}/apps/open/{client_id}.
<script src="https://admin-sellifyhq.vercel.app/app-bridge.js"></script>
<script>
Sellify.toast("Saved"); // admin toast ({ error: true } for red)
Sellify.setTitle("Settings"); // title in the admin's app bar
Sellify.navigate("/orders"); // open an admin page
const token = await Sellify.idToken(); // fresh session token for your API calls
</script>The session token is a JWT signed with HS256 and your client secret, valid 5 minutes: verify the signature and exp, check aud is your client ID, then store is the store handle and sub the staff member. Browsers block ordinary cookies inside iframes, so use the token, or cookies with SameSite=None; Secure; Partitioned. OAuth can't run in the iframe: call Sellify.redirect(yourInstallUrl) to restart it at the top level.
App embeds (storefront scripts)
To run a script on the storefront, declare an app embed instead of editing themes. Merchants switch it on in Online Store → Themes → Customize → App embeds; Sellify then adds your script to every page while the app is installed, and removes it when they switch it off or uninstall.
"embeds": [{
"handle": "widget",
"name": "My widget",
"description": "Shown in the theme editor",
"src": "{app_url}/widget.js",
"target": "body",
"attributes": { "data-theme": "light" }
}]Sellify renders <script src="…" defer data-shop="{storefront host}" data-store="{store}" …attributes>. {app_url} becomes your app's URL (the tunnel in app dev, application_url in app deploy). Up to 3 embeds, data-* attributes only. Changing embeds or embedded on a listed app sends it back to review.
Admin API from the terminal
sellify graphql '{ shop { name } products(first: 5) { nodes { title } } }'
sellify graphql --file query.graphql --variables '{"id":"gid://sellify/Product/…"}'Throttled requests (HTTP 429) are retried after the Retry-After delay.
CI and scripts
CI has no browser, so use a custom app token with read_themes and write_themes. Set SELLIFY_STORE, SELLIFY_TOKEN and SELLIFY_URL (or run sellify login --store mystore --token sfat_…), and pass --allow-live for unattended deploys. Custom app tokens can also carry other scopes for sellify graphql.
SELLIFY_STORE=mystore SELLIFY_TOKEN=$THEME_TOKEN sellify theme push --theme live --allow-live