A command-line interface for Mapbox APIs. Commands are generated at build time from OpenAPI specs, so they always match the specs.
This is the buildable core, and building it is the primary way to get it from here. It needs Rust via rustup and nothing else: no second repository, no token, and no network beyond crates.io.
cargo build --release
./target/release/mapbox --helpThe OpenAPI specs the commands are generated from are vendored in
openapi/, so a clone compiles on its own.
Mapbox publishes signed builds for macOS, Linux and Windows from a separate
repository. The install script detects your platform, checks a SHA-256
checksum, and installs mapbox. No sudo, no admin rights:
curl -fsSL https://cli.mapbox.com/install.sh | shirm https://cli.mapbox.com/install.ps1 | iexscripts/install.sh and scripts/install.ps1 here are those installers'
sources; scripts/test-install.sh and scripts/test-install.ps1 exercise
them end to end without touching the network.
Run mapbox --help once it's on your PATH.
mapbox auth login # opens a browser (OAuth/PKCE)
mapbox auth logout # removes stored credentials
mapbox auth refresh # force-refreshes the access token
mapbox auth whoami # reports which token the next command will useCredentials live in ~/.mapbox as plain JSON with locked-down file
permissions. There is no OS keychain integration. Override them with
--token/--username or MAPBOX_ACCESS_TOKEN/MAPBOX_USERNAME, and set
MAPBOX_CONFIG_DIR to move the whole store, which a container usually
wants.
--profile <name> keeps a separate credential set per account:
mapbox auth login --profile android_app
mapbox --profile android_app styles listEach API is a top-level subcommand, one sub-subcommand per operation:
mapbox accounts *
mapbox fonts *
mapbox geocoder *
mapbox rasterarrays *
mapbox search *
mapbox sprites *
mapbox static-images *
mapbox static-tiles *
mapbox styles *
mapbox tilequery *
mapbox tilesets *A command group is not the same thing as a spec file: which one an operation
belongs to is decided per operation. So sprites and tilesets are each
assembled from operations declared by the Styles, Raster Tiles and Vector
Tiles specs. mapbox tilesets is also unrelated to mapbox tilesets-cli,
which proxies to the separate Python tool.
An operation can nest one level deeper where a group reads better, as in
mapbox styles draft get, draft update and draft delete.
For example:
mapbox styles get <STYLE_ID>
mapbox styles create --data '{"name": "My Style", "version": 8, ...}'docs/commands.md lists every command.
Every request sends User-Agent: mapbox-cli/<version> and nothing else
about you or your machine. MAPBOX_CLI_NO_TELEMETRY=1 keeps even future markers
out of that header.
mapbox agent-skills list # what's published, and what's installed here
mapbox agent-skills install # all 20, into whichever agents you have
mapbox agent-skills update # re-install what's here, report what changed
mapbox agent-skills uninstall <NAME>Installs the Mapbox Agent Skills: hand-written guidance for coding agents on cartography, token security, style quality, geospatial operations and the mobile and web SDKs. No token needed, and no Node. It's one tarball, extracted in the binary.
Fifteen agents are supported: Claude Code, Codex, Cursor, Cline, Gemini CLI, GitHub Copilot, Zed, OpenCode, Amp, Windsurf, Roo Code, Continue, Kiro CLI, Qwen Code and Goose. By default, skills are installed for whichever of them are found on the machine.
| Flag | What it does |
|---|---|
--agent <name> |
Install for one agent. Repeatable. |
--global |
Write to the agent's home directory instead of this project. |
--dir <path> |
Write to a directory you name, for a Dockerfile or a CI job. |
Most of these agents read the same .agents/skills directory, so asking for
several usually means a single write.
--ref <branch|tag|sha> installs a particular version and a SHA pins it;
--dry-run lists the files first. A skill directory that already exists stops
the install until --force, since it may hold your edits.
update compares what's installed with what's published, byte for byte, and
rewrites only what differs, including restoring a file you edited. It never
installs a skill that wasn't already there. uninstall <NAME> removes the
directory, asking first at a terminal; it makes no network request at all.
There's no lock file: one tarball arrives before any record could be
consulted, so comparing bytes answers exactly and leaves no state to keep in
step with another tool's.
Different command from generate-skills below, which
writes a skill describing this CLI. These are about using Mapbox.
mapbox completion bash | zsh | fish | powershellPrints a completion script on stdout. Nothing is written to disk, so put it where your shell looks:
mapbox completion bash > ~/.local/share/bash-completion/completions/mapbox
mapbox completion zsh > ~/.zfunc/_mapbox # a directory on $fpath
mapbox completion fish > ~/.config/fish/completions/mapbox.fish
source <(mapbox completion bash) # this shell onlymapbox completion powershell >> $PROFILEIt completes commands, subcommands and flag names, generated from this
binary's own command tree. So it matches the build that printed it, and
nothing about it is maintained by hand. Values (style ids, usernames) are not
completed: that would mean an API request mid-keystroke. --output does not
apply, because the script is the result.
mapbox generate-skillsWrites the whole command surface as an Agent
Skill: .claude/skills for
Claude Code, .agents/skills for Codex. --agent, --global, --dir,
and --service narrow it; --dry-run lists files without writing them.
mapbox tilesets-cli list <USERNAME>
mapbox tilesets-cli upload-source <USERNAME> <SOURCE_ID> data.geojson.ldForwards everything to the separately-installed Tilesets CLI:
pipx install mapbox-tilesets # Python 3.10+--output and --yes don't apply here. tilesets has its own flags, so use
--force/-f for its prompts. It needs a token too: mapbox auth login
covers it, or pass --token/MAPBOX_ACCESS_TOKEN the same way as every
other command. mapbox auth whoami shows which one is in play if a
tileset command answers for the wrong account.
These apply globally, across every command, not just the API ones above.
Every mutating command takes --dry-run: it prints the request instead of
sending it, checking --data/--file along the way.
$ mapbox styles delete zz-clitest-style --dry-run
Dry run — nothing was sent.
DELETE https://api.mapbox.com/styles/v1/you/zz-clitest-style?access_token=<redacted>Goes after the operation name (mapbox styles delete ID --dry-run),
not before. A read-only command rejects it.
| Request | Budget |
|---|---|
A normal request (GET, or a typed --data body) |
60 seconds |
A --file upload, or a --data @<path> / @- body |
15 minutes |
--timeout <SECONDS> overrides either, MAPBOX_TIMEOUT sets it for a
whole shell.
HTTPS_PROXY, HTTP_PROXY, ALL_PROXY and NO_PROXY are all honored, so
a CLI behind a corporate proxy needs no configuration of its own.
Two things are easy to lose an afternoon to:
HTTP_PROXYalone does not carry Mapbox requests. Every Mapbox base URL ishttps, and that variable applies tohttpURLs only. SetHTTPS_PROXY(orALL_PROXY) instead.- A SOCKS proxy is not supported.
ALL_PROXY=socks5://…fails the request rather than being ignored, and the failure saysunsupported scheme socks5. If you see that, it is the proxy and not the network.
--output/-o (or MAPBOX_OUTPUT) picks the shape:
| Value | Result |
|---|---|
auto (default) |
text at a terminal, json when piped |
text |
Pretty-printed, readable |
json |
Everything on stdout is JSON: one compact document per command |
json promises the shape, not the count. Every command today returns one
document. A command that streams would emit one per line (JSON Lines), but
that is a property of the command rather than of the flag, so there is no
-o jsonl. Nothing streams yet.
Errors always go to stderr and never appear in stdout. Under json they're
one flat object: code, message, plus fix, next_actions and docs
where there is advice to give. See docs/commands.md
for the list of codes.
mapbox <command> --schema describes a command as JSON instead of running
it: arguments, types, and the request it would make. Needs no token.
mapbox styles get --schema # one command
mapbox --schema # the whole CLIOnly DELETE commands ask for confirmation, and only at a terminal (both
stdin and stderr):
$ mapbox styles delete my-style
About to DELETE https://api.mapbox.com/styles/v1/me/my-style
Continue? [y/N] n--yes/-y/MAPBOX_YES=1 skips the question, which is what CI wants, or a
script deliberately run at a terminal. It does not apply to auth login, which always
needs a person.
mapbox can't update itself, so when a newer release exists it says so once
a day, on stderr, at a terminal:
A newer mapbox is available: 0.2.0 (this is 0.1.5).
Update: curl -fsSL https://cli.mapbox.com/install.sh | sh
Silence this: MAPBOX_NO_UPDATE_CHECK=1
This is the only request the CLI makes that you didn't ask for, so it is kept narrow:
| What it sends | A GET for the channel's latest/manifest.json, with no token, no account, no command, and nothing about you or your machine beyond User-Agent: mapbox-cli/<version> |
| When | At most once a day, and only when stderr is a terminal, so CI and piped runs never check and never print |
| Where | A detached background process. Your command never waits on it: offline, the timing is unchanged and nothing is printed |
| Off | MAPBOX_NO_UPDATE_CHECK=1, or MAPBOX_CLI_NO_TELEMETRY=1, which silences this too |
~/.mapbox/update-check.json (or $MAPBOX_CONFIG_DIR) holds the answer
between runs. A build that names no release channel never checks at all, and
cargo build produces one.
YOUR PRIVACY - COLLECTION OF TELEMETRY
Mapbox collects telemetry data from our CLIs to better understand how our tools are used and how to improve our products.
- What Telemetry Data We Collect: Usage metrics include installs, the
service a Mapbox API command belongs to (e.g.
stylesorgeocoder, never the operation or its arguments), CLI version, OS/architecture, whether stdin and stdout are attached to a terminal, an identifier for the detected AI coding agent (if any) running the command (based on signals such as the presence of theCLAUDECODEorCOPILOT_MODELenvironment variable; seeagent_detect.rsfor the complete, versioned list), and a boolean flag indicating whether the command was run in a CI environment. IP addresses necessarily accompany any request made to our server, but will not be retained and analyzed together with telemetry data. - Why We Collect It: For internal analytics by Mapbox to understand adoption, prioritize investments, and improve the reliability, performance, and developer experience of our CLIs.
- What We Do Not Collect: Code completion outputs, source code, project file names, directory contents, non-Mapbox API keys, or credentials.
- Who has Access: Telemetry data will not be disclosed to, or accessed by, third parties other than Mapbox affiliates and passive cloud storage and hosting providers necessary to maintain our infrastructure.
This also covers update notices above, since that check rides the same opt-out.
How to Opt Out: The collection of telemetry data is enabled by default. You can disable it at any time and without affecting the functionality of our CLIs by setting
MAPBOX_CLI_NO_TELEMETRY=1For additional information on our data processing activities and your related rights, please see our Mapbox Privacy Policy.
mapbox uninstallRemoves only the mapbox binary. Credentials, profiles, and the separate
tilesets binary are untouched. Run
mapbox auth logout first if you
want those gone too. Asks for confirmation like any destructive command
(--yes/MAPBOX_YES skips it); --dry-run previews without deleting.
Running the tests, the lints they have to pass, versioning rules and how specs become commands are in CONTRIBUTING.md.