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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ that may never merge. They are not releases and are not listed here.

## Unreleased

## 1.1.1 - 2026-10-22

- The update check now runs in published builds. 0.3.0 through 1.1.0 were
built with it off, so they never said a newer version existed. At a
terminal, at most once a day, `mapbox` now prints a notice on stderr when
one does; `MAPBOX_NO_UPDATE_CHECK=1` or
`mapbox config set update-check off` turns it off. Nothing reaches stdout,
and piped or CI runs never check.
- `install.sh`/`install.ps1`: the MCP question no longer waits several
seconds before it appears. The installer asks whenever it found a coding
agent or VS Code, and only after a yes does it look for Claude Code, Codex, VS Code
and Cursor and check what each already has. A reinstall therefore asks
again even when every server is registered; a yes then reports each one
as already there.

## 1.1.0 - 2026-10-22

- `mapbox workflow` (beta): install and run workflows, which are named,
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mapbox-cli"
version = "1.1.0"
version = "1.1.1"
edition = "2021"
description = "A command-line interface for Mapbox APIs, with commands generated at build time from OpenAPI specs."
repository = "https://github.com/mapbox/mapbox-cli"
Expand Down
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ taking the newest, with or without the leading `v`, so the version
`mapbox --version` prints can be pasted straight in:

```sh
curl -fsSL https://cli.mapbox.com/install.sh | MAPBOX_CLI_VERSION=1.1.0 sh
curl -fsSL https://cli.mapbox.com/install.sh | MAPBOX_CLI_VERSION=1.1.1 sh
```

```powershell
$env:MAPBOX_CLI_VERSION = '1.1.0'; irm https://cli.mapbox.com/install.ps1 | iex
$env:MAPBOX_CLI_VERSION = '1.1.1'; irm https://cli.mapbox.com/install.ps1 | iex
```

Both scripts put the install directory on your `PATH`: `install.sh` adds a
Expand All @@ -105,9 +105,11 @@ or run the script somewhere with no terminal to ask on (CI, a container), and
it does neither, printing the two commands to run by hand instead.

It then asks, separately, whether to add the [Mapbox MCP servers](#mcp-servers)
to each coding agent it finds that can take one (Claude Code, Codex, VS Code,
Cursor), the same thing `mapbox mcp install --global` does. It asks only when
there is something left to add, with the same rules: no terminal means no.
to your coding agents, the same thing `mapbox mcp install --global` does: a
yes adds them to whichever of Claude Code, Codex, VS Code and Cursor are
installed, and skips any that already have them. It asks whenever it found a
coding agent above or VS Code is installed, with the same rules: no terminal
means no.
Set `MAPBOX_CLI_NO_AGENT_SETUP=1` to skip both questions.

On macOS and Linux, `install.sh` also offers to install the
Expand Down Expand Up @@ -141,7 +143,7 @@ Six targets are published: `aarch64-apple-darwin`, `x86_64-apple-darwin`,
then extract:

```sh
version=v1.1.0
version=v1.1.1
file=mapbox-${version}-aarch64-apple-darwin.tar.gz

curl -fsSLO "https://cli.mapbox.com/${version}/${file}"
Expand All @@ -156,7 +158,7 @@ On Windows the archive is a `.zip`, and PowerShell can read the manifest
directly:

```powershell
$version = 'v1.1.0'
$version = 'v1.1.1'
$target = 'x86_64-pc-windows-msvc'

$manifest = Invoke-RestMethod "https://cli.mapbox.com/$version/manifest.json"
Expand Down
153 changes: 83 additions & 70 deletions scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ Windows 11 on Arm has and Windows 10 on Arm does not.
)
}

$agentsFound = $false
if ($AgentSetupAllowed) {
# A child writing to stderr is a terminating NativeCommandError in
# Windows PowerShell under $ErrorActionPreference = 'Stop' (set
Expand All @@ -765,6 +766,7 @@ Windows 11 on Arm has and Windows 10 on Arm does not.
try {
$checkOut = (& $destination generate-skills --global --dry-run -o json 2>$null) -join ''
if ($LASTEXITCODE -eq 0) {
$agentsFound = $true
$agentNames = Get-AgentName $checkOut
Write-Ok "Coding agents found: $agentNames."
$doAgentSetup = $false
Expand Down Expand Up @@ -838,85 +840,96 @@ Windows 11 on Arm has and Windows 10 on Arm does not.
#
# A separate question from the skill above: this registers a hosted
# server in the coding agent's own config, next to servers the user
# added, rather than writing a directory this CLI owns. `mapbox mcp
# install` never replaces an entry that is already there (src/mcp.rs),
# so on a reinstall it is only offered when something is left to
# register. Same opt-out and same no-console rule as the skill.
if ($AgentSetupAllowed) {
# added, rather than writing a directory this CLI owns. Asked only
# when the skill step above found a coding agent, or VS Code is
# there, with the same opt-out and no-console rule. VS Code takes an
# MCP server but no skill, so the skill step can't find it;
# ~/.vscode is where it keeps extensions on every OS.
#
# Nothing here checks which clients are installed or what they
# already have, for the reason install.sh gives: that check runs each
# client's own CLI and took seconds with nothing on screen. `mapbox
# mcp install` tries each client itself once someone says yes, so a
# reinstall asks again, a yes reports what was already there, and a
# no is reported as skipped.
if ($AgentSetupAllowed -and ($agentsFound -or (Test-Path -LiteralPath (Join-Path $HOME '.vscode') -PathType Container))) {
$previousErrorAction = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
try {
# Fails with mcp_client_not_found when no supported client is
# installed, which is most machines: nothing to offer, so
# nothing is said.
$mcpCheck = (& $destination mcp install --global --dry-run -o json 2>$null) -join ''
if ($LASTEXITCODE -eq 0) {
$clientLabels = @{
'claude-code' = 'Claude Code'; 'codex' = 'Codex'
'vscode' = 'VS Code'; 'cursor' = 'Cursor'
$clientLabels = @{
'claude-code' = 'Claude Code'; 'codex' = 'Codex'
'vscode' = 'VS Code'; 'cursor' = 'Cursor'
}
$doMcpSetup = $false
if (-not [Console]::IsInputRedirected) {
Write-AskTitle 'Add the Mapbox MCP servers to your coding agents?'
Write-AskNote @('This runs ', 'mapbox mcp install --global', ', now or any time later.')
$answer = Read-AskAnswer 'Add them now?'
$Layout.Indent = ' '
if ($answer -match '^(?i:y|yes)$') { $doMcpSetup = $true }
}
if ($doMcpSetup) {
# Each client's own CLI does the registering, and
# Codex's can stop to print a sign-in URL, so
# stderr - where mapbox forwards what they print -
# is left on the console, live. No spinner: a
# second writer to the console is not worth it
# here without a terminal to test it on.
Write-Part $Layout.Indent
Write-Part '...' 'Cyan'
Write-Host ' Adding the Mapbox MCP servers'
# stderr is passed through as it arrives and kept
# too, for the error code a failure carries.
$mcpErr = ''
$mcpOut = (& $destination mcp install --global -o json 2>&1 | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
$line = $_.ToString()
[Console]::Error.WriteLine($line)
$mcpErr += $line
} else { $_ }
}) -join ''
$mcpOk = $LASTEXITCODE -eq 0
# One line per server and outcome, clients joined,
# so a server added just now reads differently from
# one that was already there.
$serverLabels = @{ 'mapbox' = 'Mapbox MCP'; 'mapbox-devkit' = 'Mapbox DevKit MCP' }
$rows = @()
try { $rows = @(($mcpOut | ConvertFrom-Json).results) } catch { $rows = @() }
$groups = [ordered]@{}
foreach ($row in $rows) {
$what = if ($serverLabels.ContainsKey($row.server)) { $serverLabels[$row.server] } else { $row.server }
$who = if ($clientLabels.ContainsKey($row.client)) { $clientLabels[$row.client] } else { $row.client }
$key = "$($row.status)|$what"
if (-not $groups.Contains($key)) { $groups[$key] = @() }
$groups[$key] += $who
}
$mcpClients = @(($mcpCheck | ConvertFrom-Json).results |
Where-Object { $_.status -eq 'would_install' } |
ForEach-Object { $_.client } | Select-Object -Unique |
ForEach-Object { if ($clientLabels.ContainsKey($_)) { $clientLabels[$_] } else { $_ } }) -join ', '
if ($mcpClients) {
$doMcpSetup = $false
if (-not [Console]::IsInputRedirected) {
Write-AskTitle "Add the Mapbox MCP servers to ${mcpClients}?"
Write-AskNote @('This runs ', 'mapbox mcp install --global', ', now or any time later.')
$answer = Read-AskAnswer 'Add them now?'
$Layout.Indent = ' '
if ($answer -match '^(?i:y|yes)$') { $doMcpSetup = $true }
foreach ($key in $groups.Keys) {
$status, $what = $key -split '\|', 2
$who = $groups[$key] -join ', '
switch ($status) {
'installed' { Write-Ok "Added $what to $who" }
'already_installed' { Write-Skip "$what was already in $who" }
'installed_login_incomplete' { Write-Warn "Added $what to $who, but sign-in did not finish" }
'client_not_found' { Write-Warn "Skipped $what for ${who}: CLI not on PATH" }
'config_unreadable' { Write-Warn "Skipped $what for ${who}: config could not be read" }
default { Write-Warn "Could not add $what to $who" }
}
if ($doMcpSetup) {
# Each client's own CLI does the registering, and
# Codex's can stop to print a sign-in URL, so
# stderr - where mapbox forwards what they print -
# is left on the console, live. No spinner: a
# second writer to the console is not worth it
# here without a terminal to test it on.
Write-Part $Layout.Indent
Write-Part '...' 'Cyan'
Write-Host ' Adding the Mapbox MCP servers'
$mcpOut = (& $destination mcp install --global -o json) -join ''
$mcpOk = $LASTEXITCODE -eq 0
# One line per server and outcome, clients joined,
# so a server added just now reads differently from
# one that was already there.
$serverLabels = @{ 'mapbox' = 'Mapbox MCP'; 'mapbox-devkit' = 'Mapbox DevKit MCP' }
$rows = @()
try { $rows = @(($mcpOut | ConvertFrom-Json).results) } catch { $rows = @() }
$groups = [ordered]@{}
foreach ($row in $rows) {
$what = if ($serverLabels.ContainsKey($row.server)) { $serverLabels[$row.server] } else { $row.server }
$who = if ($clientLabels.ContainsKey($row.client)) { $clientLabels[$row.client] } else { $row.client }
$key = "$($row.status)|$what"
if (-not $groups.Contains($key)) { $groups[$key] = @() }
$groups[$key] += $who
}
foreach ($key in $groups.Keys) {
$status, $what = $key -split '\|', 2
$who = $groups[$key] -join ', '
switch ($status) {
'installed' { Write-Ok "Added $what to $who" }
'already_installed' { Write-Skip "$what was already in $who" }
'installed_login_incomplete' { Write-Warn "Added $what to $who, but sign-in did not finish" }
'client_not_found' { Write-Warn "Skipped $what for ${who}: CLI not on PATH" }
'config_unreadable' { Write-Warn "Skipped $what for ${who}: config could not be read" }
default { Write-Warn "Could not add $what to $who" }
}
}
if (-not $mcpOk) {
if ($rows.Count -eq 0) { Write-Warn 'Could not add the Mapbox MCP servers.' }
Write-Detail "Run 'mapbox mcp install --global' to see why and try again."
}
}
if (-not $mcpOk) {
if ($mcpErr -match '"code"\s*:\s*"mcp_client_not_found"') {
# The agent found above takes skills but not
# an MCP server this CLI can register.
Write-Skip 'No Claude Code, Codex, VS Code or Cursor here to add them to.'
} else {
Write-Skip "Mapbox MCP servers not added to $mcpClients. Run this any time:"
Write-Detail 'mapbox mcp install --global'
if ($rows.Count -eq 0) { Write-Warn 'Could not add the Mapbox MCP servers.' }
Write-Detail "Run 'mapbox mcp install --global' to see why and try again."
}
$Layout.Indent = ' '
}
} else {
Write-Skip 'Skipped the Mapbox MCP servers. Run this any time:'
Write-Detail 'mapbox mcp install --global'
}
$Layout.Indent = ' '
} finally {
$ErrorActionPreference = $previousErrorAction
}
Expand Down
Loading
Loading