| name | update-microsoft-store-listing |
| description | Read or change FeedFlow's Microsoft Store listing with pcenter — listing text, screenshots, locales, submissions and rollouts. Use when inspecting live Store copy, syncing listing text from assets/storecopy, replacing Store screenshots, adding or removing a Store listing language, or rescuing a stuck submission or package rollout. |
Update the Microsoft Store listing
The Store is driven by pcenter, which replaced the
PowerShell scripts that used to live in .github/scripts/. Install locally with
brew install prof18/tap/pcenter.
Before anything else
- Reading is free and changes nothing. Start here:
pcenter listing show --locale en-us,
pcenter locales list, pcenter submission status, pcenter rollout status,
pcenter app info, pcenter reviews list --from 2026-01-01 --all.
- Credentials live in
~/.config/pcenter/credentials.env locally — set up with
pcenter auth login, checked with pcenter auth doctor. Never commit them. CI passes
MS_STORE_* from repository secrets instead.
- Only one pending submission can exist per app. If a command reports one, inspect it
with
pcenter submission status before doing anything. --replace-pending deletes
whatever draft is there, including one a human left for inspection.
Where the copy lives
assets/storecopy/<locale>/ — microsoft_store_description.md plus the microsoft_store_*
keys of store_listing.json — is the source of truth, maintained through the translation
pipeline. Nothing pcenter writes is authoritative.
.pcenter/ is a gitignored scratch directory, the same idea as .asc. It is a snapshot
of what the Store currently holds: regenerate it with pcenter listing pull --dir .pcenter,
never commit it, and never hand-edit it expecting the edit to survive.
Release notes are separate and committed:
assets/storecopy/microsoft-store-release-notes.json, owned by the
update-store-release-notes skill. A Store locale missing from that file fails the publish
rather than shipping an empty changelog.
Changing listing text
Generate the listing files rather than editing them:
pcenter listing pull --dir .pcenter
.scripts/generate-microsoft-store-listing.py --dir .pcenter --dry-run
.scripts/generate-microsoft-store-listing.py --dir .pcenter
pcenter listing push --dir .pcenter --dry-run
The generator skips locales the Store does not serve, and locales whose source is still the
English base text — it measures word overlap against base, because several
microsoft_store_description.md files are English with only a heading or two translated and
an equality check misses them. It never writes title for an existing locale.
listing push requires exactly one mode:
| Mode | Effect |
|---|
--dry-run | Prints the diff, creates nothing. Safe even with a draft pending. |
--skip-commit | Creates an inspectable draft in Partner Center. |
--yes | Creates and commits — goes live after certification. |
Always run --dry-run first, and never --yes unless the user explicitly asks.
Screenshots
One English set is shared by every language; the Windows Store does not need localized ones.
.scripts/generate-microsoft-store-listing.py --dir .pcenter --screenshots ~/path/to/shots
It deletes each locale's existing screenshots and uploads the new set, preserving the
StoreLogoSquare and the en-US captions. Image binaries cannot be downloaded from the
API, so the source PNGs must come from outside the repo — keep them somewhere findable.
Requirements: PNG, ≥1366×768, ≤50 MB, ≤10 per locale.
Adding or removing a listing language
--add <locale> creates a listing file for a language the Store does not serve yet. It
copies the reserved product name into title, which is required: a listing language the
packages do not include has no package to draw its name from, and omitting it fails the whole
submission with MissingTitle.
A language is "additional" in Partner Center when the MSIX does not declare it — the package
languages come from .github/msix-resources-template.xml. Add a language there to make it
package-supported on the next Windows release.
Removing a locale needs --allow-locale-removal on top of the mode flag, so a deleted file
cannot silently drop a Store language.
Store limits pcenter checks before creating a submission
shortDescription ≤ 500 characters — Microsoft's published docs wrongly say 1,000.
- At most 21 locales may carry keywords at all. Not per locale, not a keyword total: a
22nd locale with keywords is rejected outright, so one must be cleared to make room.
description ≤ 10,000; features ≤ 20 items.
When something is stuck
- Rollout (the 2026-07-08 class of failure):
pcenter rollout status, then
pcenter rollout finalize. Every mutation verifies the resulting state, because the Store
API returns 504 for operations that in fact succeeded.
- A failed submission (
CommitFailed, CertificationFailed) still occupies the single
pending slot. pcenter submission delete-draft --yes clears it.
- Watching:
pcenter submission watch. Running out of poll attempts is not a failure —
certification takes hours — it reports in-progress and exits 0.
Exit codes
2 fix the invocation or config · 3 credentials rejected · 4 invalid for the current
state, never retry unchanged · 5 throttled. Output is JSON when piped.
Full reference: pcenter docs.
Guardrails
- Do not push listing changes or commit a submission unless the user explicitly asks.
- Never
--yes without an explicit request; --skip-commit leaves a draft they can review.
- Do not translate store copy. If a locale's source is still English, report it — the
generator will refuse it anyway.