Tringify CLI

Install the tringify command and sign in; build themes and apps, push to development stores and publish versions.

The Tringify CLI is the tringify command for building themes and apps. For themes, it creates a theme from the starter, previews and validates it, adds it to a development store and publishes versions to your theme listing. For apps, it creates the app, starts a project from the app starter, keeps the app's configuration in tringify.app.json and releases versions. It signs in with your Tringify account and is open source at github.com/tringify/cli.

On the approval screen, Tringify’s own tools, including the Tringify CLI, show “Verified by Tringify”. Other tools show “This name was provided by the tool. Tringify hasn’t verified it.” Check the prominent domain as well as the name: it comes from the tool’s client metadata address or its registered return addresses. Local loopback addresses appear as “This computer”. Only continue if you recognize the tool and intended access. The CLI’s server-defined client ID is https://api.tringify.com/oauth/connectors/clients/tringify-cli.

Install#

On macOS or Linux, run:

bash
curl -fsSL https://raw.githubusercontent.com/tringify/cli/main/install.sh | sh

The installer downloads the release for your platform, verifies it against the published SHA256SUMS, and installs tringify in ~/.local/bin. On Windows, run this in PowerShell:

powershell
irm https://raw.githubusercontent.com/tringify/cli/main/install.ps1 | iex

It verifies the download the same way, installs tringify.exe in %LOCALAPPDATA%\Programs\tringify and adds that folder to your path; open a new terminal afterwards. Releases cover macOS (Apple silicon and Intel), Linux (x86-64 and ARM64) and Windows (x86-64, which also runs on Windows on Arm). Set TRINGIFY_CLI_VERSION to install a specific release. Run tringify version to confirm.

The CLI is a single program and needs nothing else installed: no Python, Node.js or other runtime. The first time you check, package or preview a theme, it downloads the theme validator (themecheck) and preview renderer (theme-preview-render) from the theme tools release for your platform, verifies them against that release's SHA256SUMS, and keeps them in your user cache folder:

System

Folder

macOS

~/Library/Caches/tringify/theme-tools

Linux

~/.cache/tringify/theme-tools, or under $XDG_CACHE_HOME

Windows

%LocalAppData%\tringify\theme-tools

The CLI looks for a newer theme tools release at most once a day and keeps working offline with the one it has. Set TRINGIFY_THEME_TOOLS_VERSION to use a specific release, TRINGIFY_THEME_TOOLS_HOME to keep the two programs in another folder, or TRINGIFY_THEME_CHECK and TRINGIFY_THEME_PREVIEW to use copies you already have.

Commands#

Command

What it does

tringify login

Signs in to a developer organization in your browser.

tringify login --store

Signs in to a store. theme push, theme dev and theme pull start this for you when needed.

tringify logout

Signs out of the developer organization and revokes the CLI's access. --store ID signs out of one store; --all signs out everywhere.

tringify whoami

Shows the organization and stores you are signed in to and the access each login currently has.

tringify store list

Lists your organization's development stores and their IDs.

tringify store create --name NAME --country CC --currency CUR

Creates a development store and waits until it is ready. --subdomain, --timezone and --billing-currency are optional.

tringify theme init [DIR] [--name NAME] [--from SOURCE]

Creates a theme from the starter theme, or from a local theme folder with --from, then builds and validates it. DIR must not exist; nothing is created if validation fails.

tringify theme preview [DIR] [--port 9292] [--preset NAME] [--host ADDRESS]

Serves a live preview with sample content and rebuilds when you save a file. A failed edit shows the error and keeps the last good page.

tringify theme dev --store ID [--storefront ID] [--theme ID] [--with-demo] [DIR]

Adds the theme to a store as an unpublished theme, then builds it and uploads it into that theme through the store's code-save door every time you save (validated, render-checked and recorded in the theme's code history). The store's live theme never changes. --with-demo also adds the theme's demo products and collections that a development store does not have yet.

tringify theme build [DIR]

Compiles src/sections/<name>/ into sections/<name>.vasc and updates the section list in theme.json.

tringify theme check [DIR] [--mode sealed|development]

Validates the compiled theme, as it is, with the same rules used on upload. Run build first after editing sources. Sealed mode, the default, also needs a non-empty template for every page, including the Gift Card page (templates/gift_card.json); --mode development leaves that out while you build one page at a time.

tringify theme package [DIR] [OUTPUT]

Builds and validates in a temporary copy and writes an upload-ready ZIP, by default dist/<theme>.zip. A failed validation never replaces an existing package.

tringify theme context [DIR] --page PAGE [--entity HANDLE] [--preset NAME]

Prints the sample data a preview page receives.

tringify theme contract

Prints the theme author contract as JSON: data roots and fields, editor setting types and hosted form actions.

tringify theme push --store ID [--storefront ID] [DIR]

Adds the theme to a store as a new, unpublished theme. The live theme does not change.

tringify theme pull --store ID --theme ID [DIR]

Downloads a store theme's published files into a new folder. Without --theme it lists the storefront's themes.

tringify theme pull --listing ID [--version X.Y.Z] [DIR]

Downloads the exact package a version of your listing was published with into a new folder. Without --version it takes the newest published version.

tringify theme diff --listing ID [--version X.Y.Z] [DIR]

Packages the theme and lists the files publishing would add (+), change (~) or remove (-) compared with a published version of your listing, by default the newest.

tringify theme listings

Lists your organization's theme listings and their IDs.

tringify theme create --name NAME --slug SLUG [--support-url URL] [--terms-url URL]

Creates a free theme listing in your developer organization and prints its ID. --slug is its URL name: lowercase letters, numbers and hyphens.

tringify theme categories

Lists the Theme Store categories, for theme update --category.

tringify theme update --listing ID [--name N] [--tagline T] [--description D | --description-file FILE] [--category SLUG] [--support-url URL] [--terms-url URL] [--screenshot FILE]... [--style-cover STYLE=FILE]...

Changes a listing's text, category, links, screenshots and style covers; only the parts you pass change. Screenshots and covers are 1280×720 PNG, JPEG or WebP. Passing --screenshot replaces all screenshots, in the order given; passing --style-cover replaces all covers, where STYLE is the style preset name.

tringify theme submit --listing ID

Submits the listing for Theme Store review.

tringify theme publish --listing ID --version X.Y.Z [--notes TEXT] [--breaking] [--install-store ID] [--yes] [DIR]

Shows what changes compared with the newest published version, asks, then publishes the theme as a new version of the listing. --yes publishes without asking, for example in CI.

tringify app list

Lists your organization's apps and their IDs.

tringify app categories [--type standard|sales_channel] [--json]

Lists the category and subcategory IDs for app create. It reads a public list, so it works without signing in. A sales channel app's subcategory sets its channel type.

tringify app create --name NAME [--handle HANDLE] --type standard|sales_channel --distribution private|marketplace [--category ID --subcategory ID] [--description TEXT] [--json]

Creates an app and prints its ID, handle, client ID and client secret; the secret is shown only once. Sales channel apps need --category and --subcategory. --json prints the result for scripts, for example to pipe into a secret store.

tringify app init --app ID [DIR]

Creates a project from the app starter: a TypeScript Cloudflare Worker with an embedded admin page, signed webhook handling and Store API calls. It writes the app's configuration to tringify.app.json, with block sources in blocks/, including an example template block.

tringify app config pull [--app ID] [--file PATH] [--yes]

Writes the app's draft configuration to tringify.app.json, with each app block's source in blocks/<key>.vasc. If the files exist and differ, it shows what would change and asks first; --yes overwrites without asking.

tringify app config check [--file PATH]

Checks tringify.app.json and the block sources it names without changing the draft: the app blocks first, then the whole file, which the Developer API checks exactly as a push would (event delivery and its server_events.attribution click IDs and cookies, scopes, origins and the rest). Each problem is printed with the field it concerns, such as server_events.attribution.cookies.

tringify app config push [--file PATH] [--yes]

Replaces the app's draft configuration with tringify.app.json and the block sources it names. It runs tringify app config check first and pushes nothing if that finds a problem, then shows what changes and asks first. Fields left out of the file are cleared. The draft goes live only when you release it.

tringify app block check [--file PATH]

Checks the app's blocks with the rules applied when the configuration is pushed: each declaration (mode, pages, surface), and each source compiled as a block that reads only the data its mode allows and writes only the markup app blocks may use. Problems are printed as FILE:LINE: message. config push and release run this check first.

tringify app block context [--page product] [--theme DIR] [--entity HANDLE] [--preset NAME]

Prints the sample data each block receives on a page: the page's sample data cut to the ctx_needs roots the block declares. --page is product, collection, cart, page, account, blog or home. Uses the built-in sample catalog, or a theme's demo content with --theme.

tringify app block preview [--theme DIR] [--page product] [--after TYPE] [--port 9292] [--host ADDRESS] [--preset NAME]

Serves a local preview of the app's blocks inside a theme, rendered as a store renders them, in the page's app block slot after the theme block named by --after (default price). Uses the starter theme unless --theme names another, and rebuilds when tringify.app.json, a block source or the theme changes.

tringify app install-link [--store DOMAIN] [--draft] [--expires CHOICE] [--uses N]

Creates a link that installs the app. A private app installs its current draft; a marketplace app installs its published version, or with --draft its draft, which only your organization's development and transfer stores can install. --store binds the link to one store; --uses 0 allows unlimited installs.

tringify app release [--bump patch|minor|major] [--notes TEXT]

Marketplace app: checks the blocks and submits the draft for review as a new version, increasing the part of the version number you name in --bump; major marks the version as breaking.

tringify app release [--store ID|DOMAIN]... [--all] [--notes TEXT] [--yes]

Private app: sends the draft as an update to the installed stores you name with --store, or with --all to every installed store that does not have it yet. Each store accepts it in its admin. --yes sends without asking.

tringify app versions

Lists the app's versions, newest first. For a private app, each shows how many stores accepted it, have it waiting or got a later version instead, and its release notes.

tringify app publish VERSION

Publishes an approved marketplace version so stores can install or update to it.

tringify app listing show [--app ID]

Shows the app's App Store listing and what it still needs before a marketplace submit.

tringify app listing update [--icon FILE] [--screenshot FILE]... [--tagline T] [--short-description D] [--description D | --description-file FILE] [--support-email EMAIL]

Changes the App Store listing; only the parts you pass change. The icon is a 512×512 PNG, JPEG or WebP; passing --screenshot replaces all screenshots, in the order given. The change reaches the App Store with the next app release and app publish.

tringify app privacy push [--file privacy.md] [--submit] [--app ID]

Saves the Markdown file as the draft of the app's privacy policy, hosted by Tringify. --submit also submits it for review; once approved it is published as a new version and stores that installed the app are notified.

tringify app terms push [--file terms.md] [--submit] [--app ID]

The same for the app's terms of service.

tringify app docs push [--dir docs] [--submit] [--app ID]

Saves the .md files directly in the folder as the draft of the app's documentation, one page per file: the file name is the page address, and front matter gives its title: and, optionally, its order:.

tringify app privacy|terms|docs status [--app ID]

Shows the document's public address, its published version with the date and whether it is live, the submission in review, the draft and the latest review decision.

tringify app webhook test

Sends a signed app.test webhook to the app's webhook URL and reports the answer.

tringify app webhook rotate-key [--pipe-to COMMAND | --json]

Issues a new webhook signing secret. For 72 hours, requests also carry a second signature made with the previous secret; the output says exactly when that stops. --pipe-to hands the new secret to your secret store on its standard input without printing it.

tringify app webhook finish-rotation [--yes]

Stops signing requests with the previous webhook signing secret now, instead of when its 72 hours end.

tringify app secret rotate [--pipe-to COMMAND | --json]

Issues a new client secret. For 72 hours the previous secret keeps working too; the output says exactly when it stops. Rotating again during that time stops the oldest secret at once. The new secret is shown only in the output, or with --pipe-to handed to your secret store without being shown.

tringify app secret finish-rotation [--yes]

Stops accepting the previous client secret now. Run it once the new secret is deployed everywhere, or right away if the previous one was exposed.

tringify app deliveries [--data] [--status STATUS] [--event-type TYPE] [--store STORE] [--delivery ID] [--event ID] [--limit 20] [--cursor CURSOR]

Lists webhook deliveries to the app, newest first: lifecycle deliveries, or with --data store data deliveries. --store takes a store ID, domain or part of its name; --event (data deliveries only) an event ID. Pass the printed cursor to --cursor for the next page (at most 100 per page). When some stores can't be reached, stderr says so.

tringify app retire [--json]

Shows whether the app can be retired and why, then opens its Danger zone in the Developer Portal to confirm.

tringify app delete [--json]

Shows whether the app can be deleted (only when it was never used), then opens its Danger zone in the Developer Portal to confirm.

Build an app#

bash
tringify app categories --type standard   # category and subcategory IDs (no sign-in needed)
tringify app create --name "My app" --type standard --distribution private
# prints the app ID, handle, client ID and client secret (the secret is shown once)
tringify app init --app APP_ID my-app   # project from the app starter
tringify app webhook rotate-key         # webhook signing secret for .dev.vars
# edit tringify.app.json: scopes, webhook URL, admin URL, events
tringify app block preview              # the example app block in the starter theme
tringify app config check               # the platform's checks, without saving
tringify app config push                # replaces the app's draft
tringify app install-link --store my-store.mytringify.com
tringify app release                    # marketplace: a new version; private: an update

The app's handle, its unique name in App Store URLs and the default directory of app init, is made from --name unless you choose it with --handle; it is checked before the app is created and cannot change later. tringify app categories reads a public list, so it works without signing in. --type sales_channel creates a sales channel app and needs --category and --subcategory (listed by tringify app categories --type sales_channel); --distribution marketplace lists it in the App Store. App commands that act on one app take --app ID, or read app_id from tringify.app.json (another file with --file). Run tringify app <command> --help for every flag. For a step-by-step walkthrough, see Build your first app.

tringify app retire and tringify app delete show what applies to the app before anything changes: delete only when it was never used on any store, otherwise retire, with the reasons, and says when some stores could not be checked. Both need the Delete Apps permission (apps:delete; run tringify login again if you signed in before these commands existed). Confirming takes your email code or passkey, so the command opens the app's Danger zone in the Developer Portal to finish. See Retire or delete an app.

tringify app install-link takes its --expires choices and the defaults of --expires (7 days) and --uses (1 install) from the Developer API, so they always match the Developer Portal; an unknown --expires is refused with the list of choices.

For a private app, tringify app release --all sends the draft to every installed store that doesn't have it yet; --store takes a store ID or domain and can be repeated. tringify app versions shows each private version's accepted, waiting and replaced counts and its notes. Both say when some stores could not be reached, so a missing store is never silent. See Releases and install links.

For a marketplace app, tringify app release refuses a version identical to the published (or approved) one, since a version is only for configuration or listing changes, and refuses an incomplete listing: tringify app listing show lists what the listing still needs (icon, a screenshot, a support email, a published privacy policy and terms of service). Write the privacy policy, terms and docs in Markdown in your repository and publish them with app privacy push, app terms push and app docs push; see Privacy, terms and docs for your app. tringify app secret rotate issues a new client secret; the previous one keeps working for 72 hours, and tringify app secret finish-rotation revokes it sooner.

Edit sections in src/sections/<name>/ as body.html, style.css and schema.json, and keep src/.generated-sections.json in version control: it records which compiled files build generated, so removing a section's source also removes its compiled file, and a compiled file you edited by hand is never deleted. If you used the tringify-theme command from the theme tools, each of its commands is available as tringify theme <command> with the same rules and output, on the same theme files.

Publish a version#

Create the listing first, with tringify theme create or in the Developer Portal under Themes; the listing holds the name, pricing and review details. Describe it with tringify theme update and send it for review with tringify theme submit. Then publish from a clean git checkout:

bash
tringify theme listings
tringify theme diff --listing LISTING_ID
tringify theme publish --listing LISTING_ID --version 1.2.0 --notes "New header layout"

diff shows the files that change compared with the newest published version. publish refuses to run when the git work tree has uncommitted or untracked changes, so every version matches a commit. It shows the same comparison and asks before publishing; pass --yes to skip the question, for example in CI. It then packages the theme, uploads and validates it, publishes the version, and adds Source commit: <sha> to its release notes. Add --install-store STORE_ID to also install the new version, unpublished, into one of your organization's development stores. A published version cannot change; publish a new version number for every update, and use tringify theme pull --listing LISTING_ID --version X.Y.Z to get any published version back exactly.

Develop against a store#

bash
tringify store create --name "Theme Lab" --country GB --currency GBP
tringify theme dev --store STORE_ID

theme dev adds the theme to the store's primary storefront as an unpublished theme, then watches your files. Every time you save, it builds the theme and uploads it into that theme through the store's code-save door, usually in a few seconds: the same checks as a theme upload, the code-edit rules (the store's buy, cart, checkout and gift card forms and their fields, the theme editor's reveal listeners, transparent overlay roots that respect [hidden], no focus rings, stable colour scheme IDs) and a render of every page the change touches. Refresh the theme preview in Store Admin to see the change. A change that fails prints the error and changes nothing. Each sync is one change in the theme's code history, so you and the merchant can see and undo it in Store Admin. The theme it uses is remembered in .tringify/dev.json, so the next run continues with the same theme; keep .tringify/ out of git. Use --storefront to choose another storefront and --theme to sync into another theme, such as a copy of a Theme Store theme. A sync into the store's live theme never reaches shoppers directly: it goes to the CLI's pending copy of the live theme, which the merchant reviews and publishes or discards in Store Admin (Online Store › Themes, Theme changes to review). Develop on a theme that is not live.

push adds a separate copy each time it runs. pull downloads a store theme, for example one changed in the Store Admin code editor, into a new folder; the files are compiled, so sections are .vasc files rather than src/ folders.

Add sample products#

A theme can ship a demo catalog: demo/catalog.json and the images in demo/images, the same pack the Theme Store uses for its previews. --with-demo adds it to a development store so you can build against the catalog the theme was designed around. It uploads the images to the store's Media, then creates the products with their options, variants and vendors, priced in the store's currency, and turns each demo collection into a tag on its products and a collection for that tag.

bash
tringify theme dev --store STORE_ID --with-demo

It runs on development stores only. Products and collections whose handle the store already has are left as they are, and only the images of the ones it adds are uploaded, so running it again adds only what is missing and never changes or duplicates anything. Products appear under Products within a minute. The first run with the flag asks you to approve product and file access for that store.

Sign-in and access#

tringify login uses OAuth with PKCE and a one-time listener on 127.0.0.1; your password never passes through the CLI. On the approval screen you choose the developer organization, or the store for login --store, and see exactly what the CLI asks for:

Login

Access

Developer organization

organization:themes:read and organization:themes:write: list your theme listings, upload bundles, publish versions and install them into development stores. organization:dev_stores:read and organization:dev_stores:write: list and create development stores. organization:apps:read and organization:apps:write: list apps and their versions, deliveries and private updates, create apps and check and replace the configuration file. organization:apps:release: submit releases, publish versions, send private updates and create install links. organization:apps:credentials: regenerate the client secret and rotate the webhook signing key. organization:apps:delete: check whether the app can be retired or deleted. Each is granted only if your own role holds the matching permission (see Organization team permissions).

Store

store:online_store.storefronts:read and store:online_store.storefronts:write: list storefronts and themes, add a theme as unpublished, upload into a theme and download a theme. With theme dev --with-demo only, store:products:write and store:files:write: upload the demo images and add the demo products and collections.

The CLI never has more access than your own role, and it follows changes to your role. It cannot make a theme live, delete stores, create paid listings or change pricing, and it retires or deletes an app only after you confirm in the Developer Portal. If you signed in before development store access was added, run tringify login again to use the store commands. Tokens are stored only in your system keychain: the macOS Keychain, Windows Credential Manager, or the Secret Service on Linux (GNOME Keyring or KWallet). Without one, sign-in stops and says so. If the keychain does not answer, for example a locked Secret Service over SSH where it cannot show its unlock prompt, the CLI says it is waiting after a few seconds and stops after two minutes with an explanation instead of hanging. Access tokens last 15 minutes and are refreshed automatically; refresh tokens rotate on every use. Uploads, publishes, installs and new development stores are recorded in your organization's activity log as Connected tool: Tringify CLI.

See and disconnect the CLI in your Tringify account under Connected tools, or run tringify logout. Over SSH, set TRINGIFY_NO_BROWSER=1 and open the printed sign-in URL on a machine that can reach the CLI's 127.0.0.1 listener, for example through port forwarding. AI agents can use the same operations through MCP; see Connect an AI assistant.