Shopify CLI theme workflow: local development done properly
The admin code editor has no history and no way back. Here is the local workflow that does.
7 min read · Themes & storefront ·
The Shopify admin has a code editor. It has no version history worth the name, no diff, no branches, and no way for two people to work without overwriting each other. The CLI exists so you never have to use it.
Getting set up
Install the CLI, then authenticate against the store:
``bash npm install -g @shopify/cli shopify theme list --store your-store.myshopify.com ``
Pull an existing theme down into a folder:
``bash shopify theme pull --store your-store.myshopify.com ``
Commit that immediately, before you change anything. That commit is your baseline and the thing you diff against when someone asks what changed.
The dev server
``bash shopify theme dev --store your-store.myshopify.com ``
This serves the theme locally against the store's real data — real products, real collections, real settings — with hot reloading. It creates a temporary development theme behind the scenes, so nothing you do here is visible to customers.
Two things worth knowing. Changes to Liquid and assets reload immediately; changes to {% schema %} blocks usually need a restart. And because it uses live store data, editing a product to test something changes it for real customers — the isolation is on the theme, not the data, which is the point covered in development stores and staging.
Pushing and pulling
``bash shopify theme push --unpublished --theme "Feature: filters" # new unpublished theme shopify theme push --theme 123456789 # to a specific theme shopify theme pull --theme 123456789 --only config/ # bring back merchant settings ``
That last one matters. Merchants change settings in the admin, and those live in config/settings_data.json and templates/*.json on the store, not in your repository. Push blindly and you overwrite their work.
The safe pattern: pull config/ and templates/ before you push, or exclude them from the push entirely:
``bash shopify theme push --theme 123456789 --ignore config/settings_data.json --ignore templates/*.json ``
A deployment routine that doesn't lose work
- Pull the live theme's settings so your local copy matches what the merchant has configured.
- Push to a new unpublished theme, named with a date and a purpose.
- Review it with a preview link. Test on a phone.
- Publish from the admin.
- Leave the previous theme unpublished for a week as a one-click rollback.
Step five costs nothing and is the only rollback plan you'll ever need.
Version control
Treat the theme like any other codebase: a branch per piece of work, a pull request if more than one person is involved, and commit messages that say why rather than what.
Two things to add to .gitignore: nothing from config/settings_data.json should be treated as authoritative if the merchant edits it live, and any local environment file the CLI creates.
Having the theme in a repository is also what makes it genuinely yours. A theme that exists only in a Shopify admin isn't an asset you own — it's a handover conversation you haven't had yet.
Useful extras
One of these deserves its own treatment: Theme Check catches missing translation keys, invalid schema and the Liquid patterns that make stores slow.
``bash shopify theme check # linter for Liquid, schema and common mistakes shopify theme share # a preview link without publishing shopify theme package # a .zip for distribution ``
theme check is worth running in CI. It catches unused snippets, missing translation keys, deprecated tags and Liquid patterns that will be slow — several of which are on the performance checklist.
The CLI's real value isn't hot reloading. It's that every change is a commit, and every mistake is one command away from being undone.
Is this the problem you’re looking at?
Send me the link to your store and a line about what is going wrong. You get a straight answer within one business day — no pitch, no obligation.
[email protected]Or see what I do around Shopify: services, work beyond the theme, selected work.