Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (climaybe) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
climaybe
Shopify CLI for theme CI/CD (GitHub Actions, branches, multi-store config) and light app repo setup. Same install works in theme or app repositories.
Built by Electric Maybe — a Shopify-focused product and development studio.
Commit linting and Cursor bundle (optional in both flows):
- Conventional commit linting: During
climaybe theme initorclimaybe app init, you can install commitlint and Husky for Conventional Commits. - Cursor bundle (rules + skills + subagents): Opt in to Electric Maybe’s bundled Cursor files under
.cursor/rules/,.cursor/skills/, and.cursor/agents/(themes, JS, a11y, commits, changelog, Linear, theme-translator for locale sync, etc.).
Command layout (Shopify CLI–style)
climaybe theme <command>— canonical commands for theme repos (workflows, stores, branches).- Same commands at the top level —
climaybe initis the same asclimaybe theme init(backward compatible). climaybe app init— app repos only: writesproject_type: "app"inclimaybe.config.json, optional commitlint + Cursor bundle. Does not install theme GitHub Actions or store/branch setup.climaybe setup-commitlintandclimaybe add-cursor— always at the top level (stack-agnostic).
Theme-only commands refuse to run when climaybe.config.json → project_type is app.
Install
cd your-shopify-theme-repo # or app repo
npm install -D climaybeRun commands with npx climaybe (or add scripts to your package.json).
When a newer climaybe is available, the CLI can prompt at startup to update. Press Enter to accept the update (npm install -g climaybe@latest) or type n to skip.
Quick Start (theme)
cd your-shopify-theme-repo
npm install -D climaybe
npx climaybe init
# equivalent: npx climaybe theme initThe interactive setup will ask for your store URL(s) and configure everything automatically.
Quick Start (app)
cd your-shopify-app-repo
npm install -D climaybe
npx climaybe app initInstalls optional commitlint/Husky and the Cursor bundle (rules, skills, agents). Use Shopify CLI for app development and deployment.
Commands
climaybe init / climaybe theme init
Interactive setup that configures your repo for CI/CD.
- Prompts for your store URL (e.g.,
voldt-staging.myshopify.com) - Extracts subdomain as alias, lets you override
- Asks if you want to add more stores
- Asks whether to enable optional preview + cleanup workflows (default: yes)
- Asks whether to enable optional build + Lighthouse workflows (default: yes)
- Asks whether to enable commitlint + Husky (enforce conventional commits on
git commit) - Asks whether to install the Cursor bundle (
.cursor/rules/,.cursor/skills/,.cursor/agents/) — Electric Maybe conventions for themes and AI workflows - Based on store count, sets up single-store or multi-store mode
- Writes
climaybe.config.json - Scaffolds GitHub Actions workflows
- Creates git branches and store directories (multi-store)
- Optionally installs commitlint, Husky, and the Cursor bundle (rules, skills, agents)
climaybe app init
Interactive setup for a Shopify app repository: optional commitlint + Husky, optional Cursor bundle, and project_type: "app" in package.json config. No theme workflows, stores, or staging/live branches.
climaybe add-store / climaybe theme add-store
Add a new store to an existing setup.
npx climaybe add-store- Prompts for new store URL + alias
- Creates
staging-<alias>andlive-<alias>branches - Creates
stores/<alias>/directory structure - If store count goes from 1 to 2+, automatically migrates from single to multi-store mode
climaybe switch <alias> / climaybe theme switch
Switch your local dev environment to a specific store (multi-store only).
npx climaybe switch voldt-norwayCopies stores/<alias>/ JSON files to the repo root so you can preview that store locally, and sets default_store in climaybe.config.json so climaybe serve / shopify theme dev targets that store. If your current git branch is staging-<alias> or live-<alias>, climaybe serve uses that store’s domain from config (even if default_store differs), matching CI preview behavior.
climaybe sync [alias] / climaybe theme sync
Sync root JSON files back to a store directory (multi-store only).
npx climaybe sync voldt-norwayIf no alias is given, syncs to the default store.
climaybe ensure-branches / climaybe theme ensure-branches
Create missing branches from your current branch (usually main). In single-store mode, this creates staging only. In multi-store mode, this creates staging plus per-store branches (staging-<alias>, live-<alias>). Use when the repo only has main (e.g. after a fresh clone) so the configured sync flow can run.
npx climaybe ensure-branches
git push origin --allclimaybe update / climaybe theme update
Refresh all climaybe-managed project files from your installed CLI version:
- GitHub workflows
- root dev-kit files (
.theme-check.yml,.shopifyignore,.prettierrc,.lighthouserc.js,.gitignore) package.jsonmanaged deps (climaybe,tailwindcss)- optional
.vscode/tasks.json(if enabled) - optional commitlint + Husky files (if enabled)
- optional Cursor bundle files (if enabled)
npx climaybe updateupdate-workflows still works as a backward-compatible alias.
climaybe setup-commitlint
Set up only commitlint + Husky (conventional commits enforced on git commit). Use this if you skipped it at init or want to add it later.
npx climaybe setup-commitlintclimaybe add-cursor
Install Electric Maybe Cursor rules, skills, and subagents into .cursor/rules/, .cursor/skills/, and .cursor/agents/ (including theme-translator for theme/locales/). Use this if you skipped the bundle at init or want to refresh from the version of climaybe you have installed.
npx climaybe add-cursorThe previous command name add-cursor-skill still works as an alias. Re-running replaces the bundled rules, skills, and subagent files with the copies shipped by your installed climaybe version (same idea as update).
Configuration
The CLI writes config into climaybe.config.json:
{
"port": 9295,
"default_store": "voldt-staging.myshopify.com",
"preview_workflows": true,
"build_workflows": true,
"commitlint": true,
"cursor_skills": true,
"stores": {
"voldt-staging": "voldt-staging.myshopify.com",
"voldt-norway": "voldt-norway.myshopify.com"
}
}Workflows read this config at runtime — no hardcoded values in YAML files.
Branch Strategy
Single-store
staging → mainstaging— development branchmain— production branch
Multi-store
staging → main → staging-<store> → live-<store>staging— development branchmain— shared codebase (not live)staging-<store>— per-store staging with store-specific JSON datalive-<store>— per-store production
Direct pushes to staging-<store> or live-<store> are automatically synced back to main (no PR; multistore-hotfix-to-main merges the branch into main).
Workflows
Shared (both modes)
| Workflow | Purpose |
|---|---|
ai-changelog.yml |
Reusable workflow. Sends commits to Gemini API, returns classified changelog. |
version-bump.yml |
Reusable workflow. Bumps version in settings_schema.json, creates git tag. |
Single-store
| Workflow | Trigger | What it does |
|---|---|---|
release-pr-check.yml |
PR from staging to main |
Finds latest tag on main, AI changelog to PR head, creates pre-release patch tag (e.g. v3.1.13) to lock state; posts changelog comment |
post-merge-tag.yml |
Push to main (merged PR) |
Staging→main only: minor bump from latest tag (e.g. v3.1.13 → v3.2.0). No version in PR title |
nightly-hotfix.yml |
Cron 02:00 US Eastern | Collects commits since latest tag (incl. hotfix backports), ignores no-op/empty-tree commits, generates AI changelog, patch bump and tag |
Multi-store (additional)
| Workflow | Trigger | What it does |
|---|---|---|
main-to-staging-stores.yml (main-to-staging-<store>) |
Push to main |
Merges main into each staging-<alias>; root JSONs ignored. Skips no-op sync when branch tree already matches main. For hotfix-backport: if source is staging-<alias>, that same staging branch is skipped; if source is live-<alias>, staging-<alias> is also synced. Skips only on pure store-sync. |
stores-to-root.yml |
Push to staging-* |
From main merge: stores→root. From elsewhere (e.g. Shopify): root→stores |
pr-to-live.yml |
After stores-to-root | Opens PR from staging-<alias> to live-<alias> |
root-to-stores.yml |
Push to live-* |
From main merge: stores→root. From elsewhere: root→stores (same as stores-to-root on staging-*) |
multistore-hotfix-to-main.yml |
Push to staging-* or live-* (and after root-to-stores) |
Merges store branch into main (no PR). Skips when push is a merge from main (avoids loop) and skips no-op backports when source and main trees are identical |
Optional preview + cleanup package
Enabled via climaybe init prompt (Enable preview + cleanup workflows?; default: yes).
| Workflow | Trigger | What it does |
|---|---|---|
pr-update.yml |
PR opened/synchronize/reopened (base: main, staging, develop, staging-, live-) | Shares draft theme, renames with -PR<number>, comments preview + customize URLs; uses default store for main/staging/develop, or the store for staging-<alias>/live-<alias>. Path filter: runs only when the PR changes theme paths (assets/, blocks/, config/, layout/, locales/, sections/, snippets/, templates/, _scripts/, _styles/, shopify.theme.toml, stores/**); docs-only or tooling-only PRs skip preview work. |
pr-close.yml |
PR closed (same branch set) | Deletes matching preview themes and comments deleted count + names |
reusable-share-theme.yml |
workflow_call | Shares Shopify draft theme and returns theme_id |
reusable-rename-theme.yml |
workflow_call | Renames shared theme to include PR<number> (fails job on rename failure) |
reusable-comment-on-pr.yml |
workflow_call | Posts preview comment including Customize URL |
reusable-cleanup-themes.yml |
workflow_call | Deletes preview themes by PR number and exposes cleanup outputs |
reusable-extract-pr-number.yml |
workflow_call | Extracts padded/unpadded PR number outputs for naming and API-safe usage |
Optional build + Lighthouse package
Enabled via climaybe init prompt (Enable build + Lighthouse workflows?; default: yes).
When enabled, builds are resilient:
- If
_scripts/*.jsor_styles/main.cssare missing, the build workflow skips those steps and continues. initmay offer to create entrypoints; default answer is No.- Script bundling preserves comments/spacing and emits bundles only for root entry files (files imported by other top-level
_scripts/*.jsare inlined, not emitted separately). - Script bundles are written to
assets/*.js(readable by default; useclimaybe build-scripts --minifyif you want minified output). - Live minified
assets/*changes are intentionally excluded from hotfix backports tomain(no branch-specific.gitignoresplit required).
Build workflows install deps with npm ci and run npx --no-install climaybe build-scripts plus npx --no-install climaybe build, so CI uses lockfile-pinned versions (no @latest drift).
| Workflow | Trigger | What it does |
|---|---|---|
build-pipeline.yml |
Push to any branch (ignores docs-only/tooling-only paths; see CI/CD reference) | Runs reusable build; skips entirely on live-* when the pusher is a GitHub [bot] user; Lighthouse only on branch staging, when a build ran, and secrets allow |
reusable-build.yml |
workflow_call | Path-filtered build-scripts / Tailwind (climaybe build), then commits compiled assets when changed |
create-release.yml |
Push tag v*, or workflow_run after Post-Merge Tag / Nightly Hotfix Tag succeed on main |
Builds release archive and creates GitHub Release notes from commits since the previous tag. It filters repetitive automation subjects (main→staging syncs, store/root sync chores, bot merge noise) before generating notes. If remaining subjects are low-signal and GEMINI_API_KEY exists, it uses Gemini to generate cleaner merchant-facing notes. Also covers tags created by workflows with GITHUB_TOKEN, which may not trigger tag-push workflows. |
Optional theme dev kit package
During climaybe init, you can enable the Electric Maybe theme dev kit (default: yes). This installs local
dev config defaults (.theme-check.yml, .shopifyignore, .prettierrc,
.lighthouserc.js), writes climaybe.config.json, appends a managed .gitignore block, and optionally adds
.vscode/tasks.json (default: yes) wired to run climaybe dev commands.
Local serve commands keep Theme Check disabled by default for faster startup. Enable it explicitly with
climaybe serve --theme-check or climaybe serve:assets --theme-check.
You can create optional build entrypoints later with:
climaybe create-entrypoints
If these files already exist, init warns that they will be replaced.
Section schema builder
Build Shopify section schemas dynamically from JavaScript or JSON files using climaybe build-schemas. Works directly in sections/ — no separate source folder, no sync issues with the theme editor.
How it works: Add an inline-comment marker at the end of any sections/*.liquid or blocks/*.liquid file. Shopify treats {% # ... %} as a comment and ignores it. The builder finds the marker, resolves the schema from _schemas/, and writes the generated {% schema %}...{% endschema %} block below it. The marker is never removed, so rebuilds always work — even after Shopify theme editor edits.
<section class="hero">{{ section.settings.title }}</section>
{% # schema 'hero-banner' %}
{% schema %}
{
"name": "Hero Banner",
"settings": [...]
}
{% endschema %}On rebuild, only the generated {% schema %} block is replaced. Everything above the marker (including theme editor changes) is preserved.
Supported patterns:
- Shared schemas — one schema file reused across multiple sections
- Partials —
require()shared settings arrays into multiple schemas - Common fieldsets — spread partial arrays into settings (
...linkSettings) - Looping fieldsets — factory functions that generate repeated field groups
- Section-specific overrides — export a function receiving
(filename, inlineContent)to customise per section - Inline JSON overrides — add
{% # { "name": "Custom" } %}below the marker
npx climaybe build-schemas # generate schemas in sections/
npx climaybe build-schemas --dry-run # preview without writing files
npx climaybe build-schemas --list # list schema files and markersSchemas also rebuild automatically during climaybe serve and climaybe serve:assets — the watcher monitors _schemas/ for changes and rebuilds on save, tagged [schema] in green. climaybe build includes schemas alongside scripts and Tailwind.
Example _schemas/hero-banner.js:
const createLinks = require('./partials/create-links');
module.exports = {
name: 'Hero Banner',
settings: [
{ label: 'Title', id: 'title', type: 'text' },
...createLinks(2)
]
};Full examples: See Schema Builder Examples for working code covering every pattern.
You can install/update this later with:
climaybe add-dev-kit (or climaybe theme add-dev-kit)
Versioning
- Version format: Always three-part (e.g.
v3.2.0). No version in code or PR title; the system infers from tags. - No tags yet? The system uses
theme_versionfromconfig/settings_schema.json(theme_info), creates that tag on main (e.g.v1.0.0), and continues from there. - Staging → main: On PR, a pre-release patch tag (e.g. v3.1.13) locks the current minor line; on merge, minor bump (e.g. v3.1.13 → v3.2.0).
- Non-staging to main (hotfix backports, direct commits): Patch bump only, via nightly workflow at 02:00 US Eastern (not at commit time). No-op/empty-tree commits are ignored.
- Version bump runs only on main (post-merge-tag and nightly-hotfix). Main-to-staging-stores merges main into each
staging-<alias>on every push (version bumps and hotfixes). For hotfix-backport, only astaging-<alias> -> mainsource skips syncing back to the same staging branch; alive-<alias> -> mainsource still syncs intostaging-<alias>. - Version bumps update
config/settings_schema.jsonand, when present,package.jsonversion. - Safety: The version-bump workflow fails if the new tag would not be strictly higher than the latest merged release tag (semver), so the release line cannot step backward.
Full specification: For detailed versioning rules, local dev flow, hotfix behavior, and alignment with the external CI/CD doc, see CI/CD Reference.
File Sync Rules (Multi-store)
Synced between root and stores/<alias>/:
config/settings_data.jsontemplates/*.jsonsections/*.json
NOT synced (travels via branch history):
config/settings_schema.jsonlocales/*.json
Recursive Trigger Prevention
- Hotfix sync merge commits (multistore-hotfix-to-main) contain
[hotfix-backport]in the message - Store sync commits contain
[stores-to-root]or[root-to-stores] - Version bump commits contain
chore(release): bump version - All workflows check for these flags and skip accordingly
GitHub Secrets
Add the following secrets to your GitHub repository (or use GitLab CI/CD variables if you use GitLab). You can configure them during climaybe init via the GitHub or GitLab CLI.
| Secret | Required | Description |
|---|---|---|
GEMINI_API_KEY |
Optional | Google Gemini API key for AI-generated release notes fallback |
SHOPIFY_STORE_URL |
Set from config | Store URL is set automatically from the store domain(s) you add during init (no prompt). |
SHOPIFY_THEME_ACCESS_TOKEN |
Optional* | Theme access token for preview workflows (needed only when you want preview theme publish/cleanup to run). |
SHOP_ACCESS_TOKEN |
Optional* | Required only when optional build workflows are enabled (Lighthouse) |
LHCI_GITHUB_APP_TOKEN |
Optional* | Required only when optional build workflows are enabled (Lighthouse) |
SHOP_PASSWORD |
Optional | Used by Lighthouse action when your store requires password auth |
Prompting behavior: During climaybe init (or add-store), every GitHub/GitLab secret prompt is skippable. Add values later in CI settings if you prefer.
Store URL: During climaybe init (or add-store), store URL secret(s) are set from your configured store domain(s); theme tokens are optional prompts.
Multi-store: Per-store secrets SHOPIFY_STORE_URL_<ALIAS> and SHOPIFY_THEME_ACCESS_TOKEN_<ALIAS> — the URL is set from config; you must provide the theme token per store. <ALIAS> is uppercase with hyphens as underscores (e.g. voldt-norway → SHOPIFY_STORE_URL_VOLDT_NORWAY). Preview and cleanup: for PRs targeting main, staging, or develop the workflows use the default store (from config.default_store or first in config.stores); for PRs targeting staging-<alias> or live-<alias> they use that store’s credentials. Set either the plain SHOPIFY_* secrets or the _<ALIAS> pair for each store you use in preview.
Directory Structure (Multi-store)
├── assets/
├── config/
├── layout/
├── locales/
├── sections/
├── snippets/
├── templates/
├── stores/
│ ├── voldt-staging/
│ │ ├── config/settings_data.json
│ │ ├── templates/*.json
│ │ └── sections/*.json
│ └── voldt-norway/
│ ├── config/settings_data.json
│ ├── templates/*.json
│ └── sections/*.json
├── _schemas/ (optional: JS/JSON schema definitions for build-schemas)
│ ├── hero-banner.js
│ └── partials/
│ └── link.js
├── package.json
└── .github/workflows/Releases and versioning
- Branch: Single default branch
main. Feature branches open as PRs intomain. - Versioning: SemVer. Versions are bumped automatically when PRs are merged to
mainusing conventional commits:fix:→ patch,feat:→ minor,BREAKING CHANGEorfeat!:→ major. - Flow: Merge to
main→ Release version runs semantic-release (bumpspackage.json, creates GitHub Release notes, publishes to npm, pushes tag). Optional: tag push runs Verify release tag for an extra test pass and tag vspackage.jsoncheck (no publish). We publish to npmjs.com only (not GitHub Packages). Prefer npm Trusted Publisher (workflow filerelease-version.yml) so no long-livedNPM_TOKENis needed for CI; see CONTRIBUTING.md. Do not create tags manually; only the Release version workflow creates tags so that tag and package version stay in sync. - CI: Every PR and push to
mainruns tests on Node 20 and 22 (CI workflow).
See CONTRIBUTING.md for branch, PR, and conventional-commit details.
License
MIT — Electric Maybe