le.
- Routine Deployments: Use
--allow-updates. This covers adding new extensions, updating existing ones, and modifying app configurations.
- Destructive Operations: Use
--allow-deletes. This should be reserved for explicit cleanup jobs or manual interventions where extension removal is intentional.
Implementation Example:
Instead of a monolithic deploy command, structure your CI workflow to handle updates and deletes separately. This prevents a standard merge from triggering deletions.
#!/bin/bash
# deploy_pipeline.sh
# New approach: Separate update and delete logic
DEPLOY_ENV="${1:-development}"
ACTION="${2:-update}"
if [ "$ACTION" == "update" ]; then
echo "Executing standard deployment with update permissions..."
shopify app deploy \
--env "$DEPLOY_ENV" \
--allow-updates \
--no-update-url
elif [ "$ACTION" == "cleanup" ]; then
echo "Executing cleanup deployment with delete permissions..."
# Restrict this action to protected branches or manual triggers
shopify app release \
--env "$DEPLOY_ENV" \
--allow-deletes \
--allow-updates
else
echo "Error: Unknown action '$ACTION'. Use 'update' or 'cleanup'."
exit 1
fi
Step 2: Replace Deprecated Commands
CLI 4.0 removes five legacy command shapes. These must be updated in all scripts, package.json files, and documentation. The replacements are backward-compatible with CLI 3.x, allowing you to refactor commands before bumping the version.
| Deprecated Command (Pre-4.0) | Replacement Command (4.0+) | Context |
|---|
shopify webhook trigger | shopify app webhook trigger | App-scoped webhook management. |
shopify theme serve | shopify theme dev | Theme development server. |
shopify app generate schema | shopify app function schema | Function schema generation. |
shopify app webhook trigger --shared-secret | shopify app webhook trigger --client-secret | Flag rename for clarity. |
shopify app generate extension --type | shopify app generate extension --template | Flag rename for consistency. |
Refactoring Script:
Use a repository-wide search to identify and replace these patterns. Pay special attention to package.json scripts, which often harbor legacy aliases like "theme:serve": "shopify theme serve".
{
"scripts": {
"dev:theme": "shopify theme dev",
"trigger:webhook": "shopify app webhook trigger --client-secret",
"gen:function": "shopify app function schema",
"create:extension": "shopify app generate extension --template"
}
}
CLI 4.0 introduces automatic upgrades for local installations. The CLI detects newer minor or patch versions via the package manager and upgrades on the next invocation. This behavior is disabled by default in CI environments, project-local installs, and across major versions.
Local Development Configuration:
For teams that prefer deterministic local environments, you can disable auto-upgrades globally or per-project.
# Disable auto-upgrade globally for the current user
shopify config autoupgrade off
# Verify configuration
shopify config get autoupgrade
CI/CD Version Pinning:
While CI runners skip auto-upgrades by default, it is best practice to pin the CLI version in your project manifest. With SemVer adoption, pinning to ^4.0.0 ensures you receive bug fixes and features without risking breaking changes.
{
"dependencies": {
"@shopify/cli": "^4.0.0"
}
}
Step 4: Sequence the Migration
To minimize blast radius, follow this migration order:
- Audit: Scan all CI/CD definitions, npm scripts, and documentation for
--force and deprecated commands.
- Refactor: Update commands and flags while still on CLI 3.x. Since replacements are backward-compatible, this validates syntax without risking runtime errors.
- Bump: Update
package.json to ^4.0.0 and install the new version.
- Validate: Run a dry-deploy against a development store. Verify that
--allow-updates functions as expected and that auto-upgrade behavior aligns with team preferences.
- Rollout: Merge changes to the main branch and monitor the next CI/CD execution.
Pitfall Guide
1. The --force Trap in CI Pipelines
Explanation: Failing to replace --force in CI scripts results in immediate pipeline failure with an "unrecognized flag" error. This blocks all deployments until fixed.
Fix: Perform a regex search for --force across all configuration files. Replace with --allow-updates for standard flows and --allow-deletes only where destruction is intentional.
2. Silent Breakage of theme serve
Explanation: The rename from shopify theme serve to shopify theme dev often hides in package.json scripts. Developers may not notice the breakage until they attempt to start the theme server, causing confusion and lost time.
Fix: Run grep -r "theme serve" . in the repository. Update all aliases immediately. Add a pre-commit hook or lint rule to flag deprecated commands.
3. Auto-Upgrade Drift in Local Environments
Explanation: Developers working on different machines may inadvertently run different CLI versions due to auto-upgrades, leading to "works on my machine" discrepancies.
Fix: Disable auto-upgrade for teams requiring strict version parity using shopify config autoupgrade off. Alternatively, enforce version checks in the CI pipeline to ensure all contributors use the pinned version.
4. Misusing --allow-deletes in Automation
Explanation: Applying --allow-deletes to every CI run negates the safety benefit of the flag split. This allows automated pipelines to remove production extensions if the local state is out of sync.
Fix: Restrict --allow-deletes to manual triggers, protected branches, or dedicated cleanup jobs. Standard merge pipelines should only use --allow-updates.
5. Ignoring AI Agent and MCP Integrations
Explanation: AI coding agents or custom MCP servers configured with pre-4.0 command shapes will fail when interacting with the CLI. These integrations may not be obvious during a manual audit.
Fix: Review all AI agent prompts, scripts, and MCP tool definitions. Update command invocations to use the new syntax. Test agent-driven deployments in a sandbox environment before production use.
6. Assuming Major Version Jumps are Safe
Explanation: With SemVer, major version changes (e.g., 4.0 to 5.0) will introduce breaking changes. Teams accustomed to seamless upgrades may be caught off guard by future major releases.
Fix: Treat major version upgrades as significant engineering tasks. Monitor the Shopify Dev changelog for migration guides and plan upgrades during low-traffic windows. Auto-upgrade skips major versions, so explicit opt-in is required.
7. Overlooking Flag Renames in Webhook Triggers
Explanation: The --shared-secret flag for webhook triggers has been renamed to --client-secret. Scripts using the old flag will fail or behave unexpectedly.
Fix: Update all webhook trigger commands to use --client-secret. Verify that secrets are passed correctly and that webhook registrations succeed in the development store.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Single App, Frequent Deploys | Pin ^4.0.0; Use --allow-updates only in CI. | SemVer ensures stability; granular flags prevent accidental deletions. | Low; migration is mechanical and fast. |
| Multi-Store, Complex CI | Pin exact version 4.0.x; Separate cleanup jobs with --allow-deletes. | Reduces risk across diverse environments; isolates destructive operations. | Medium; requires CI refactoring and job separation. |
| Local Dev with AI Agents | Disable auto-upgrade; Audit agent prompts. | Ensures deterministic behavior; prevents agent failures due to syntax changes. | Low; configuration change and prompt update. |
| Legacy Theme Projects | Replace theme serve with theme dev; Update npm scripts. | Prevents silent breakage; aligns with current CLI standards. | Low; simple string replacement. |
Configuration Template
Use this template to standardize your project configuration for CLI 4.0.
package.json Snippet:
{
"name": "shopify-app-production",
"version": "1.0.0",
"scripts": {
"dev": "shopify app dev",
"deploy": "shopify app deploy --allow-updates",
"deploy:cleanup": "shopify app release --allow-deletes --allow-updates",
"theme:dev": "shopify theme dev",
"webhook:trigger": "shopify app webhook trigger --client-secret"
},
"dependencies": {
"@shopify/cli": "^4.0.0"
}
}
CI/CD Workflow Snippet (GitHub Actions Example):
name: Deploy Shopify App
on:
push:
branches: [main]
workflow_dispatch:
inputs:
action:
description: 'Deployment action'
required: true
default: 'update'
type: choice
options:
- update
- cleanup
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Run Deployment
run: |
if [ "${{ github.event.inputs.action }}" == "cleanup" ]; then
npm run deploy:cleanup
else
npm run deploy
fi
env:
SHOPIFY_API_KEY: ${{ secrets.SHOPIFY_API_KEY }}
SHOPIFY_API_SECRET: ${{ secrets.SHOPIFY_API_SECRET }}
Quick Start Guide
- Update Dependencies: Run
npm install @shopify/cli@^4.0.0 to upgrade the CLI in your project.
- Refactor Scripts: Replace all instances of
--force with --allow-updates in your deployment scripts. Update deprecated commands using the replacement table.
- Test Locally: Run
shopify app deploy --allow-updates against a development store to verify the new flag behavior.
- Commit and Push: Merge changes to your repository. Monitor the next CI/CD run to ensure the pipeline executes successfully with the updated configuration.
- Configure Local Settings: If desired, run
shopify config autoupgrade off to disable automatic upgrades on your local machine for version stability.