## link ```bash mercemur link --store acme.mercemur.com ``` Writes `.mercemur.json` so every command in this directory knows which store it acts on, **after checking** that the store answers and the key works. The check is the point. Writing a config that turns out to be wrong moves the failure to the next command, where the message is about that command rather than about the link. ## env pull ```bash mercemur env pull mercemur env pull --force # replace values already set ``` Fills `.env.local` with what the CLI can prove: the store id, the API base, the storefront URL and the default locale. **It cannot supply a publishable key.** Keys are minted from the dashboard and are not on the public API, so the file records the variable with a note rather than leaving a name you discover from a stack trace. Run `mercemur open apikeys`. Existing values are kept unless you pass `--force`: a local override is usually deliberate. Unrelated variables and key order are preserved, so a pull is a small diff rather than a rewrite. ## translations ```bash mercemur translations locales mercemur translations export -o strings.csv mercemur translations export -o fr.csv --locale fr --resource-type product mercemur translations import strings.csv --dry-run mercemur translations import strings.csv ``` Columns are `locale, resource_type, resource_id, field, value`, with the value last because it is the only one a translator edits. The API scopes a translation list to **one resource** on purpose, so an export walks them and reports how many reads that took. A store with ten thousand products should see what the export costs before it is surprised by it. Reading `product` requires `read_products`, and so on for each type walked. Import sends only the values that **differ**, so re-importing an unchanged export writes nothing. Leading and trailing space is preserved: it belongs to the translator, and stripping it changes the rendered copy. ## redirects ```bash mercemur redirects export -o redirects.csv mercemur redirects import redirects.csv --dry-run mercemur redirects import redirects.csv ``` Columns are `from_path, to_path, status_code`. A status must be 301, 302, 307 or 308; anything else is refused rather than guessed at. **Import only adds and updates.** A redirect missing from the file is left alone, because a shorter file is far more often a partial export than an instruction to delete the rest, and removing a live redirect breaks a URL somebody has indexed. A file that redirects the same path twice is refused, naming both rows: that is a merge accident, and applying both silently leaves whichever landed last. ## seo ```bash mercemur seo list mercemur seo audit ``` `audit` reports the mistakes a search result makes visible: a duplicate title across two pages, a description too long to survive truncation, one too short to say anything. It audits **what is set**, not what is missing. A resource with no override falls back to its own catalogue title, which is usually correct, and reporting every one of those would bury the findings that matter. Exits non-zero on a duplicate title, which is the one finding here that is unambiguously wrong: two pages competing for the same query is a decision nobody made. Length findings are warnings, because those limits are conventions that move. ## metafields ```bash mercemur metafields definitions mercemur metafields export -o metafields.jsonl mercemur metafields import metafields.jsonl --dry-run mercemur metafields import metafields.jsonl ``` One JSON object per line, not CSV. **A metafield's value is typed by its definition**: a number, a boolean, an object, a list of references. CSV stringifies all of it, so `420` comes back as `"420"` and nothing reports it until a template renders the quotes. JSONL keeps the type and still gives a diff of one line per field. Values are compared as **canonical JSON**, so the same object with its keys in another order is the same value and a reformatted file is not mistaken for a store-wide edit. A line with no `definition_id` is refused rather than guessed at: the definition is what decides the value's type, and writing one without it stores a shape the storefront cannot read. Run `mercemur metafields definitions` to see them. A malformed line names its own line number, because "invalid character" in a file of several thousand is a search rather than a fix. ## A header with no rows Every import here treats a header-only CSV as zero rows rather than an error. That file is exactly what an export of a store with none of these produces, and erroring on it would break the round trip at its emptiest point. A file with no header at all names no columns and is refused.