# Mercemur CLI
The Mercemur CLI exists for the work an API cannot do: reading and watching files on
your own machine.
Everything reachable over HTTP is already served by the [API](/api-reference/introduction).
The CLI deliberately does not mirror it. There is no `mercemur products list`, because
`GET /api/v1/products` already exists and a second spelling of it would only drift.
What the CLI adds is the local half:
Templates on disk, in your editor, in your own git history alongside the rest of
your work.
Save a file, see the change in a preview link, without publishing anything to
shoppers.
## Install
On macOS and Linux:
```bash
curl -fsSL https://cli.mercemur.com/install.sh | sh
```
The script picks the right build for your machine, checks it against a published SHA-256
before unpacking it, and refuses to install anything that does not match. It installs to
`/usr/local/bin`; set `MERCEMUR_INSTALL_DIR` to put it somewhere else.
On Windows, or to pin a version, download it directly from
[cli.mercemur.com](https://cli.mercemur.com). Builds are published for macOS, Linux and
Windows on both amd64 and arm64, with checksums beside them.
```bash
mercemur version
```
It is a single static binary. There is no runtime to install beside it and no dependency
tree to keep patched, which is the point: a tool that holds a write-scoped API key should
not also drag a package manager onto the machine that reads that key.
There is no Homebrew formula or npm package yet, so anything claiming to be one is not
ours. Verify downloads came from `cli.mercemur.com`.
## Log in
The CLI authenticates with the same [API key](/authentication/api-keys) everything else
does. Create one in **Settings, API keys** with the `read_storefront` and
`write_storefront` scopes, then:
```bash
mercemur login --store your-store.mercemur.com
```
The key is read without echoing and stored in your operating system's keychain, not in
a file. It never enters your shell history and never appears in the CLI's output or its
error messages.
A key with `write_storefront` can change what every shopper of your store sees. Grant
it only to keys you intend to publish with, and use `mercemur logout` on any machine
you no longer control. Logging out removes the local copy; it does **not** revoke the
key. If a key may have been exposed, rotate it in the dashboard as well.
On a machine with no keychain, such as a CI runner, set `MERCEMUR_TOKEN` in the
environment instead of running `login`.
## Point it at a store
Every command needs to know which store it is talking to. Four places are checked, and
the first one that names a value wins, **per setting**:
| Order | Source | Example |
|---|---|---|
| 1 | Flag | `--store acme.mercemur.com`, `--api https://...` |
| 2 | Environment | `MERCEMUR_STORE`, `MERCEMUR_API` |
| 3 | Project file | `.mercemur.json` in the working directory |
| 4 | Global config | your user config directory |
Per setting rather than per layer: a project file naming the API base is still used when
you pass `--store` on the command line.
```json .mercemur.json
{
"store": "acme.mercemur.com"
}
```
Never put an API key in `.mercemur.json`. It is a file people commit. Keys live in the
keychain, which is why the CLI has no config field for one.
## Scripting it
Every command accepts `--json` and emits a single machine-readable document with no
human-readable lines mixed in, so it composes:
```bash
mercemur theme pull --json | jq -r '.templates'
```
Exit codes distinguish the cases a script has to treat differently:
| Code | Meaning | What to do |
|---|---|---|
| `0` | Success | |
| `1` | Failure | Read the message |
| `2` | Wrong invocation | Fix the command |
| `3` | Key rejected or missing | Do not retry, replace the key |
| `4` | Something changed under you | Pull and re-apply, do not retry |
| `5` | Not found | |
A retry loop that treats every failure alike will spin forever on a revoked key. That is
why `3` and `4` are separate from `1`.
## Next
Pull your storefront to disk, edit with live preview, and publish.