Conversation
A workflow is a workflow.yaml of command and script steps, installed from a local directory or a GitHub repository's workflow/<stage>/<name>/ into ~/.mapbox/workflows/, then run by name. Command steps run this binary again with --output json, so they resolve credentials, timeouts and path encoding exactly as a typed command does. The first published workflow is workflow/beta/copy-style, which copies a style between accounts using two credential profiles.
Every workflow subcommand now says on stderr that the feature is beta, in development and not recommended for use, as do --help, the docs and the changelog. Workflows live at a fixed workflow/beta/<name>/ rather than under a variable stage directory, so the stage list, the stage recorded at install and the Stage shown by list and show are gone.
The beta/ level no longer means anything now that the stage concept is gone, so copy-style moves up to workflow/copy-style and install looks for workflow/<name>/ in a repository.
mapbox/cli redirects to a different repository on GitHub, so the default source never held this repository's workflows.
The notice is one short line with a bold label, paths under the home directory read as ~/..., list and show lay their fields out in aligned columns, and the next command to run is a tip on stderr rather than part of the result. Step progress is colored at a terminal. JSON is unchanged.
install takes a path, so uninstall ./workflow/copy-style is the natural undo; it now names the workflow by that directory's name. Only an installed workflow under ~/.mapbox/workflows/ is ever removed, as before. The already-installed error now gives the install line to retry with --force.
show lays every workflow out the same way: name and summary, the description, inputs, steps, then where the installed copy came from. The description is read as a small Markdown subset: paragraphs are reflowed, indented lines are highlighted commands, '- ' lines are a list, and code spans are highlighted. copy-style's description uses it.
mapbox workflow run copy-style --style-id <id> --from-profile source --to-profile target, in place of repeated --input KEY=VALUE. Before the parse, the named installed workflow is attached under `run` as a real subcommand whose inputs are typed, required flags, so --help, a missing input and a misspelled flag behave as on every other command. Every other command line sees the tree unchanged. An input may not take a global option's name. The run record keeps the path as `workflow run`, without the workflow's name, and the generated agent skill leaves `workflow` out, since it is not recommended for use.
The test matched the install line in stderr's raw text, but the error is JSON there and JSON escapes a Windows path's backslashes, so it failed on windows-2022 only. It now parses the error and compares next_actions.
Every top-level command needs an example line in the README, which the docs contract now checks.
zmofei
force-pushed
the
feat/workflows
branch
from
September 30, 2026 10:17
355d0b0 to
2dc0609
Compare
zmofei
changed the base branch from
feat/terminal-styling
to
feat/styles-download
September 30, 2026 10:17
A step marked dry_run runs during a dry run with MAPBOX_WORKFLOW_DRY_RUN=1 and the promise to write nothing, so the plan can show real data. Only a script can be marked, and a marked step reads only marked steps.
Download the style's ZIP as the source account, then upload new fonts, create the style, upload its icons in batches of 25 and point its sprite and glyphs at the target account. Both steps support --dry-run. A partial failure lists what was created and the commands that remove it.
--use-login keeps a MAPBOX_ACCESS_TOKEN from outranking the profile, but a MAPBOX_USERNAME still named the account, so a request could carry one account's token to another's path and be refused. Pass --username with the login's own account. Also check the target before downloading, and show a failed command's message and fix rather than its JSON.
The Styles API refuses a new style whose sprite the target account cannot read, which a private sprite of another account is. Create the copy with no sprite and its glyphs already on the target, then set its own sprite after the icons are uploaded.
At a terminal a step is its title, the details its script reports on stderr, and a status line: a spinner beside the latest ::progress line while it runs, then a check or a cross and the time it took. Off a terminal it stays one [n/total] line, details follow, and progress lines are dropped. Any workflow's script steps get this; copy-style now reports each font, the created style and the icon batches. A workflow's result also stops claiming its JSON is what an API sent.
A script's ::warn line is shown under its step and listed again after the last one. --quiet keeps each step's title, outcome and warnings and drops its details. A workflow's optional result template is what text mode prints instead of the outputs as fields; -o json still prints the outputs. copy-style uses all three, and every workflow can.
A command step can now keep its stdout as a file with save, in a working directory removed when the run ends, which is how a style's ZIP reaches a later step; and it can be marked dry_run when its command changes nothing. copy-style checks both logins, downloads the style and lists the target's fonts as command steps, and keeps a script only for the copy's loops.
It is public, so installing from it needs no token. Show the token with a private --repo instead.
On Windows the working directory's path is full of backslashes, which the script wrote into its own JSON unescaped, so its output parsed as text. Take the path through outputs instead, which the runner encodes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #66. It uses the
src/output/layout and the--quietbanner flag from that PR, so review it after #66 and retarget tomainonce #66 merges.What
mapbox workflow, a command for multi-step recipes ofmapboxcommands and scripts, defined in aworkflow.yaml. It is beta, in development and not recommended for use. Every subcommand says so on stderr, and so do--help, the docs and the changelog:installcopies one from a local directory, or from a GitHub repository'sworkflow/<name>/(defaultmapbox/mapbox-cli@main), into~/.mapbox/workflows/<name>/.runruns only what is installed.installchecks the directory layout, the yaml and every command step against this build's command tree.--output json, so credentials, timeouts, path encoding and history behave exactly as for a typed command. Script steps getargs,stdin, andMAPBOX_CLIfor calling the CLI themselves.runtakes each input as a flag (--style-id). The installed workflow is attached as a real subcommand before parsing, so--help, missing inputs and typos behave like any other command. Every other command line sees the tree unchanged. History recordsworkflow runwithout the workflow's name, andgenerate-skillsleavesworkflowout.${{ inputs.x }}and${{ steps.id.output.a[0] }}.workflow/copy-style. It reads a style with one profile, strips the fields the Styles API sets itself, and creates it with another profile. Every sprite, font, tileset and import that belongs to the source account is listed inwarnings, because none of them is copied.The schema and the layout rules are in
workflow/README.md, and the commands are documented indocs/commands.md#workflows.Guards
every_published_workflow_is_validholdsworkflow/to the same rulesinstallapplies. I checked that it fails on a stray file.workflow/store.rsis added toMAY_DELETEandNO_REQUEST_ID_TO_CARRY, with reasons. The requests go to GitHub, not Mapbox.tests/workflow.rsruns real child processes: values pass between command and script steps, only the result reaches stdout, a failed step stops the run,--dry-runruns nothing, and install,--forceand uninstall behave correctly on disk. I checked that the token-forwarding assertion fails when the forwarding is removed.Not checked
copy-stylehas not been run end to end against the real API.styles getandprepare.pywere run on a real style, butstyles createwas not, because it would create a style on a real account.install copy-style --ref feat/workflowswith a token downloaded, checked and installed it. Without a token it returns 404 and the error explains why. The default repository ismapbox/mapbox-cli, becausemapbox/cli(theREPO_URLinmain.rs) redirects tomapbox/cli-opensource-preview.REPO_URLitself is left alone here.copy-styleneedspython3onPATH.