Disco

Run a sale. End it cleanly.

A discount and price management CLI for Shopify. Plans are explicit and editable, every write previews before it runs, writes are reversible, and recovery is a documented procedure rather than operator memory. Base prices and market price lists.

Language
Python 3.12+
Licence
Proprietary
Runs
Your machine

Starting a sale is easy. Ending one exactly is not.

A sale touches the price and compare-at price of every variant, in your base currency and in every market price list. Products already marked down get discounted twice. Broken compare-at prices hide the strikethrough.

When the sale ends, someone has to put every price back exactly as it was. Usually that means a spreadsheet and a good memory.

The whole sale, start to finish.

  1. 01

    backup

    Snapshot a collection: base prices and every market price list, each entry in its own currency.

  2. 02

    generate

    Build an editable plan from the backup. Set a base discount, scope by colour, give outliers a deeper markdown, prune what shouldn't be on sale.

  3. 03

    apply

    Preview every variant, then confirm. Products already on sale are skipped, never stacked. Broken compare-at prices are healed and flagged.

  4. 04

    unwind

    Write the plan's captured baseline back, variant by variant, base and market. The sale ends where it started.

$ disco --dry-run apply price_plans/summer.json
14 on sale, 2 skipped, 1 healed · 5 product(s) · 2 market(s)
  SKIPPED (already on sale): Field Jacket [Olive] compareAt 240.00 > price 180.00
  SKIPPED (already on sale): Field Jacket [Navy] compareAt 240.00 > price 180.00
  ! Merino Crew [Fog] EU Retail compare-at inverted -> healed (price 92.00, was 78.00)
full preview → price_previews/summer-20260601T091244Z.json

$ disco apply price_plans/summer.json
14 on sale, 2 skipped, 1 healed · 5 product(s) · 2 market(s)
  SKIPPED (already on sale): Field Jacket [Olive] compareAt 240.00 > price 180.00
  SKIPPED (already on sale): Field Jacket [Navy] compareAt 240.00 > price 180.00
  ! Merino Crew [Fog] EU Retail compare-at inverted -> healed (price 92.00, was 78.00)
full preview → price_previews/summer-20260601T091312Z.json
apply these changes? [y/N] y
auto_backup_id: backup-20260601T091318Z
succeeded: 6  failed: 0
ok  gid://shopify/Product/7517161062482  Merino Crew
ok  gid://shopify/Product/7517161095250  Trail Pant
ok  gid://shopify/Product/7517161128018  Camp Mug
ok  gid://shopify/Product/7517161160786  Wool Beanie
ok  price_list  gid://shopify/PriceList/19342164057  EU Retail
ok  price_list  gid://shopify/PriceList/19342164312  UK Retail

It refuses to write when it shouldn't.

Know the edges before you rely on it.

For teams who run sales often and end them on time.

Brands selling in more than one currency. Merchandisers who want an uneven sale without a spreadsheet. Agencies who have been asked, once too often, what the prices were before the promotion.

Disco is available by request while the code is private.

Write with a line about your store and how you would use it. Messages are read by the person who builds the tools.

Request access