# Update Microsoft Store Listing

> 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.

- Skill: `prof18/update-microsoft-store-listing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add prof18/update-microsoft-store-listing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/prof18/update-microsoft-store-listing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: prof18 (https://skillmd.com/u/prof18)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/prof18/update-microsoft-store-listing

---


# Update the Microsoft Store listing

The Store is driven by [`pcenter`](https://github.com/prof18/pcenter-cli), 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:

```bash
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.

```bash
.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](https://github.com/prof18/pcenter-cli/tree/main/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.

