Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ that may never merge. They are not releases and are not listed here.

## Unreleased

- New `mapbox report "<message>"` sends feedback about the CLI itself to
the Mapbox CLI team, with the CLI's version and OS appended. It is filed
under Mapbox's account, not yours. It is sent with the CLI's own token,
so it needs no login and no `user-feedback:write` scope; your token
stands in while the CLI's can't be used (including when it is
rate-limited), or when you pass `--token` or `--use-login`, and the
request then carries your token.
`--category` is optional and defaults to `general`. Two new error codes
say why the CLI's token couldn't be used when you have no token either:
`cli_token_unavailable` and `cli_token_forbidden` (see
[Errors](docs/commands.md#errors)).

- The CLI's own token, used for telemetry when you have no token of your
own, is now fetched from `https://cli.mapbox.com/config/token.json` and
kept in `~/.mapbox/cli-token.json` instead of being built into the binary,
Expand Down
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ mapbox tilesets <operation>
```

`mapbox directions`, `mapbox isochrone`, `mapbox map-match`,
`mapbox matrix`, and `mapbox places` are the exceptions: each API has a
`mapbox matrix`, `mapbox places` and `mapbox report` are the exceptions: each API has a
single exposed operation, so there's a bare command with no subcommand at
all, the same shape `mapbox usage` already has, see
[docs/commands.md](./docs/commands.md) for their own parameters.
Expand Down Expand Up @@ -323,6 +323,21 @@ unexpectedly. It makes no request unless you pass `--verify`. See
[Config](./docs/commands.md#config) for details, and
[Command history](#command-history) below.

### Feedback about the CLI

```sh
mapbox report "I'd like support for optimization commands"
mapbox report "tilesets query hangs behind my proxy" --category bug
```

The message goes to the Mapbox CLI team, with the CLI's version and OS
appended, and is filed under Mapbox's account, not yours, so
`mapbox feedback list` won't show it. It is sent with the CLI's own token,
so it needs no login; yours stands in while the CLI's can't be used, or
when you pass `--token` or `--use-login`, and the request then carries your
token. See
[Report](./docs/commands.md#report).

### Shell completion

Homebrew installs completions for you. Otherwise, `mapbox completion`
Expand Down Expand Up @@ -476,9 +491,10 @@ and `--dry-run` show it alongside everything else on the request.

### The CLI's own requests

Requests the CLI makes for itself rather than for your commands use your own
token whenever you have one: `--token` or `MAPBOX_ACCESS_TOKEN`, then your
login. Only when you have none does it use the CLI's token:
The CLI has a token of its own, for requests it makes for itself. Telemetry
uses your own token whenever you have one: `--token` or
`MAPBOX_ACCESS_TOKEN`, then your login. Only when you have none does it use
the CLI's token:
`MAPBOX_CLI_TOKEN`, or a public token fetched from
`https://cli.mapbox.com/config/token.json` and kept in
`~/.mapbox/cli-token.json`. It is replaced only when the Tokens API says it
Expand All @@ -488,7 +504,9 @@ third in a row pauses telemetry's sending with it for an hour, as three
fetches in a row that find no usable token pause fetching. The token is
restricted to `https://cli.mapbox.com/`, so every request with it carries
that as its `Referer`. The CLI's token is only used for what
`src/cli_token.rs` lists for it, today just telemetry.
`src/cli_token.rs` lists for it: telemetry, and `mapbox report`, which is
the other way around: it prefers the CLI's token to yours and falls back to
yours while the CLI's can't be used.

### Proxies

Expand Down
77 changes: 77 additions & 0 deletions custom-openapi/report/openapi/report.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
openapi: "3.0.0"
# `parse_spec` turns `info.description` below into this service's clap
# `long_about`, so it also reaches `mapbox report --help`, `--schema` and
# `generate-skills` output. Keep it to API prose only — the provenance below
# is for whoever edits this file, not for a CLI user:
#
# An undocumented Feedback API endpoint the Feedback API team added for this
# CLI (AGI-1168): the same body as `POST /user-feedback/v1/feedback`, but
# filed under Mapbox's own `locationai-mapbox` account rather than the
# caller's, and needing no `user-feedback:write`. Not on docs.mapbox.com, so
# this file is the only description of it. See `custom-openapi/README.md` for
# how a file like this is wired in.
#
# One command, `mapbox report "<message>"`, via `FLATTENED_SERVICES`. The
# message is `POSITIONAL_BODY_FIELDS`'s one entry and `lat`/`lon` are
# `FIXED_BODY_FIELDS` (both in `src/spec.rs`): feedback about the CLI has no
# place, and the API still requires the pair. `id`, `feature` and
# `screenshot` are left out on purpose, so this command takes no `--data`.
info:
title: "Mapbox CLI feedback"
description: >-
Send feedback about the Mapbox CLI itself — a bug, a missing command, or
anything else — to the team that builds it. It goes to Mapbox, not to
your account, so `mapbox feedback list` will not show it.
version: "0.0.0"
servers:
- url: https://api.mapbox.com
description: Feedback API
paths:
/user-feedback/v1/cli-feedback:
post:
operationId: report
summary: Send feedback about the Mapbox CLI.
description: >-
Sends one message to the Mapbox CLI team, with the CLI's version and
OS appended. It is sent with a token the CLI provides, so it needs no
login; while that token can't be used, or with `--token` or
`--use-login`, it is sent with yours. Either way it is filed under
Mapbox's account, not yours. Any valid token works; no extra scope is
needed. There is no way to read it back or delete it afterward.
parameters:
- name: "access_token"
in: query
required: true
description: "Mapbox API Access Token"
schema:
type: string
minLength: 1
requestBody:
required: true
content:
application/json:
schema:
type: object
required: ["feedback", "lat", "lon", "category"]
properties:
feedback:
type: string
description: "What you want to tell the Mapbox CLI team."
lat:
type: number
description: "Latitude. Always 0: CLI feedback has no place."
lon:
type: number
description: "Longitude. Always 0: CLI feedback has no place."
category:
type: string
description: >-
What kind of feedback this is, such as `bug` or
`feature_request`. Free text.
responses:
"200":
description: The created feedback item.
"400":
description: Bad Request — a missing or invalid field.
"401":
description: Unauthorized
107 changes: 98 additions & 9 deletions docs/commands.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Implemented commands

Every command the CLI ships, including five auth commands, 40 API operations (35 across 9
command groups, plus `directions`, `isochrone`, `map-match`, `matrix` and
`places`), the tilesets-cli proxy, `completion` and `generate-skills`. Each is
Every command the CLI ships, including five auth commands, 41 API operations (35 across 9
command groups, plus `directions`, `isochrone`, `map-match`, `matrix`,
`places` and `report`), the tilesets-cli proxy, `completion` and `generate-skills`. Each is
shown in both of its renderings. Which one you get is decided by `--output`, whose default
(`auto`) reads stdout: a terminal gets the left column, a pipe or redirect
gets the right one. See
Expand Down Expand Up @@ -81,6 +81,8 @@ nests, and is typed `mapbox styles draft get`.

**[Places](#places)** — [places](#mapbox-places)

**[Report](#report)** — [report](#mapbox-report)

**[Search](#search)** — [search.forward](#mapbox-search-forward) ·
[search.reverse](#mapbox-search-reverse) ·
[search.category](#mapbox-search-category) ·
Expand Down Expand Up @@ -462,10 +464,11 @@ No stored profiles. Run `mapbox auth login` to create one.

## API command groups

35 operations across 9 command groups, plus five single-operation commands
with no group: `directions`, `isochrone`, `map-match`, `matrix` and `places`.
35 operations across 9 command groups, plus six single-operation commands
with no group: `directions`, `isochrone`, `map-match`, `matrix`, `places`
and `report`.
Seven groups are generated from the OpenAPI specs vendored in `openapi/`;
`search`, `feedback` and the five single commands are the exceptions —
`search`, `feedback` and the six single commands are the exceptions —
hand-authored specs versioned in this repo's own `custom-openapi/`, see
`custom-openapi/README.md`.

Expand All @@ -490,7 +493,7 @@ moved to `tilesets` or `static`.
| [`styles`](#styles) | **9** |
| [`tilesets`](#tilesets) | **3** |

The [Contents](#contents) list above names every one of the 40.
The [Contents](#contents) list above names every one of the 41.

**Everything else the Mapbox specs describe is not here at all.** Not
hidden, not shipped as a command that refuses: absent from the spec content
Expand Down Expand Up @@ -598,8 +601,8 @@ Three things worth knowing about the read forms:

A command that changes something takes `--dry-run`, which prints the request
it would send, on stdout, and sends nothing. Which commands those are is not
a list anyone keeps: it is every `POST`, `PUT`, `PATCH` and `DELETE` — 14 of
the 40 operations — plus `auth login`, `auth logout`, `auth refresh` and
a list anyone keeps: it is every `POST`, `PUT`, `PATCH` and `DELETE` — 15 of
the 41 operations — plus `auth login`, `auth logout`, `auth refresh` and
`generate-skills`. A read-only `GET` does not take it, so `mapbox styles
list --dry-run` is a usage error rather than a no-op. It rehearses
rather than describes: `--data` is parsed and every `--file` is read, so a
Expand Down Expand Up @@ -2002,6 +2005,90 @@ $ echo $?

---

## Report

Feedback about the CLI itself — a bug, a missing command, anything else —
sent to the Mapbox CLI team. It goes through an endpoint the Feedback API
added for this CLI and doesn't document on docs.mapbox.com, so this
section is its only description; see `custom-openapi/README.md` for how
that spec is wired in.

### `mapbox report`

Sends one message, with the CLI's version and OS appended to it
(`— mapbox-cli <version> on <os>`). It is filed under a Mapbox account, not
yours, so `mapbox feedback list` won't show it, and no `user-feedback:write`
scope is needed. There is no way to read it back or delete it, so
`--dry-run` shows the body, and which token it would go with, without
sending it.

It is sent with the CLI's own token, not yours, so it works without a
login. A typed `--token` or `--use-login` sends with yours instead, and the
CLI's is not tried. If this API refuses
the CLI's token, a fresh one is fetched there and then and the message sent
again with it, so a token that was republished or fixed works at once.
A `MAPBOX_CLI_TOKEN` override is sent as it is and never replaced.
When the CLI's token still can't be used — it can't be fetched, it is
revoked with no new one yet, this API refuses it, or it is rate-limited
(`429`) — your own token is used instead, so the request then carries
your token, though the message is still filed under Mapbox's account. With
none of your own, the command fails with `cli_token_unavailable` or
`cli_token_forbidden`, or with the `429` itself. Each run tries the CLI's
token again; nothing here is put off for later. Telemetry settings don't
apply: the token is shared and public, and fetching it sends nothing about
you.

#### Parameters

`<message>` (positional, required) — what you want to tell the team.
Quote it. An empty one is refused. One that starts with `-` goes after
`--`, with every flag before it: `mapbox report --category bug -- "-x is
ignored"`.

| Flag | Effect |
| --- | --- |
| `--category <category>` | What kind of feedback this is, such as `bug` or `feature_request`. Free text. Defaults to `general`. |

The API requires `lat` and `lon` as well; CLI feedback has no place, so
both are always sent as `0`. The command takes no `--data`.

#### Examples

```sh
mapbox report "I'd like support for optimization commands"
mapbox report "tilesets query hangs behind my proxy" --category bug
mapbox report "…" --dry-run
```

#### Outputs

One report, captured live on 2026-10-19 and shown both ways. `-o text`
shows only that it was sent, the message and its id; `-o json` is the
answer as the API sent it:

<table>
<tr><th width="50%">Terminal — <code>-o text</code></th><th width="50%">Agent — <code>-o json</code></th></tr>
<tr><td>

```text
Sent to the Mapbox CLI team.
feedback Test from mapbox-cli development (report). Please ignore.

— mapbox-cli 0.3.0 on macos
id 01a15503-8d64-75ed-aa9b-790ae4ba69a0
```

</td><td>

```json
{"category":"general","created_at":"2026-10-19T16:34:18.626Z","feedback":"Test from mapbox-cli development (report). Please ignore.\n\n— mapbox-cli 0.3.0 on macos","has_screenshot":false,"id":"01a15503-8d64-75ed-aa9b-790ae4ba69a0","location":{"lat":0,"lon":0},"received_at":"2026-10-19T16:34:18.626Z","status":"received","updated_at":"2026-10-19T16:34:18.626Z"}
```

</td></tr>
</table>

---

## Search

The public, non-interactive surface of the Search Box API: text search,
Expand Down Expand Up @@ -5082,6 +5169,8 @@ faults and are not:
| `binary_response` | The response was bytes and stdout is a terminal. Redirect it to a file. |
| `missing_subcommand` | A command group was named with no operation. |
| `cancelled` | A delete was declined at the confirmation prompt. Nothing was sent. |
| `cli_token_unavailable` | A command that prefers the CLI's own token (`report`) could not use it — it could not be fetched, or it is revoked and no new one is published yet — and you have no token of your own to fall back to. |
| `cli_token_forbidden` | This API refused the CLI's own token, even after fetching it afresh, and you have no token of your own to fall back to. |
| `usage` | Anything else clap rejected. Exit code 2, not 1. |
| `error` | Unclassified. |

Expand Down
Loading
Loading