The mf CLI
mf is the command-line client for the
managed.dev API. Every command is a thin shell
over a /v1 endpoint — it’s built on the Go SDK, which is
generated from the same OpenAPI spec as the API
itself, so the tool doesn’t drift from the platform. The CLI is free on every
plan — it’s just a client; what it can do is bounded by your
key’s scopes and your team role.
go install terriblegit.com/terrible/mf/cmd/mf@latestcommand groups
Section titled “command groups”Each group inherits the required scope of the endpoints it calls. Async
commands accept --wait (poll to completion) or --follow (stream the
job); without either they print the job id and
return. All of them exit non-zero on job failure.
| Group | Representative commands | Endpoint(s) | Scope |
|---|---|---|---|
mf sites |
list, get, create, delete --confirm-domain, restart, php-version, config, redirects, tls, transfer, audit |
GET/POST /v1/sites, POST …/restart, POST …/php-version, … |
sites:read / sites:write / sites:admin |
mf envs |
list, create --type staging|branch, delete, refresh, reset, push, suspend, resume, exec, cache-purge |
GET/POST …/environments, POST …/{envID}/{action}, POST …/exec, POST …/cache/purge |
environments:read/write; wp.cli:exec for exec; cache:write for cache-purge |
mf deploy |
build --builder, deployments, artifacts, releases, create, promote --to, rollback |
GET/POST …/builds, …/deployments, POST …/promote, POST …/rollback |
deployments:read / deployments:write |
mf backups |
status, create, snapshots, restore --yes |
GET /v1/backups/status, POST …/backup, POST …/snapshots/{id}/restore |
backups:read / backups:write |
mf jobs |
list, get, watch (alias follow) |
GET /v1/jobs, GET /v1/jobs/{id}, GET /v1/jobs/{id}/stream |
jobs:read |
mf events |
list [--type T] |
GET /v1/events |
events:read |
mf webhooks |
list, create --url, update, delete, roll, deliveries, replay, event-types |
GET/POST /v1/webhook-endpoints, POST …/roll, …/deliveries |
webhooks:read / webhooks:write |
mf teams |
list, create, plan, insights, members, invites, projects, audit |
/v1/teams, …/members, …/invites, …/projects |
teams:read / teams:write |
mf projects |
list, create, rename, assign, remove |
/v1/projects, …/sites |
sites:read / sites:write |
mf keys |
list, create --scopes, update, revoke, roll |
GET/POST /v1/api-keys, POST …/roll |
keys:read / keys:write (isolated — never in a wildcard) |
mf access |
ssh-keys, credentials, reset-password --yes, magic-link |
…/ssh-keys, …/credentials, …/magic-link |
credentials:read / credentials:write (isolated) |
mf insights |
summary, timeseries --metric, pages, logs, traces, requests |
…/insights/* per site |
observability:read |
mf security |
summary, malware overview|scans|scan, vulns |
…/security/*, …/malware/* |
security:read/write; vulnerabilities:read for vulns |
mf obs |
logs, log-volume, traces, metrics --name, usage |
GET /v1/logs, /v1/metrics, /v1/traces, /v1/usage/storage |
observability:read |
mf functions |
list, create, build, deploy, rollback |
/v1/functions, POST …/build, …/deploy, …/rollback |
functions:read / functions:write |
mf fn |
setup, dev — local, docker-based function dev |
none (runs locally) | — |
mf listen |
--forward-to URL [--type T] |
polls GET /v1/events |
events:read |
mf mcp |
stdio MCP server; --tools lists tools |
the read + safe-write subset | inherits the key’s scopes |
mf account |
get, update, audit |
GET/PATCH /v1/account, GET /v1/account/audit |
account:read/write; audit:read |
mf ratelimits |
live bucket state | GET /v1/rate-limits |
any authenticated key |
mf runtimes / mf capabilities |
runtime catalog / one site’s entry | GET /v1/runtimes, GET /v1/sites/{id}/capabilities |
sites:read |
Run mf <group> --help for the full flag list, or mf help for the top-level
command tree. Global flags everywhere: --json, --token, --base-url. Exit
codes: 0 success, 1 runtime/API error, 2 usage error, 130 interrupted.
sign in
Section titled “sign in”mf login verifies and stores an API key — there is no browser flow. Omit
--token and it prompts with echo disabled. With --mint it uses the key you
provide to mint a narrower one (via POST /v1/api-keys) and stores that
instead:
mf login --mint --scopes sites:read,deployments:write,jobs:read --ttl 24hFor CI, skip login and set FORGE_TOKEN in the environment:
export FORGE_TOKEN="mfk_live_…"mf sites listbuild, deploy, follow
Section titled “build, deploy, follow”mf deploy build calls POST …/builds and gets back a 202 with a
job. --follow streams the job to a terminal
state and exits non-zero if it fails, so it drops cleanly into a pipeline step:
~/acme-store ❯ mf deploy build –builder wordpress –ref feature/checkout –follow job_01J9F2KQ8M3T build.run queued job_01J9F2KQ8M3T build.run running job_01J9F2KQ8M3T build.run succeeded ✓ build succeeded — artifact art_01J9F3XW, deployed to env_01J8C4RXhttps://acme-store-feature-checkout-9a3f.preview.managed.dev
Without --wait or --follow the command prints the job id and returns —
resolve it later with mf jobs watch job_01J9F2KQ8M3T. Roll a bad release back
with mf deploy rollback <deploymentID>.
manage environments
Section titled “manage environments”mf envs reads its site from --site or the config’s default_site:
mf envs create --type branch --branch feature/checkout --waitmf envs delete env_01J8C4RX --waitBoth call the environments endpoints and return jobs. See environment lifecycle for what creation, refresh, and teardown do.
run a command on an environment
Section titled “run a command on an environment”mf envs exec calls POST …/environments/{envID}/exec — the same surface as a
WP-CLI shell, but driven by the API and gated by the
wp.cli:exec scope. Output streams back as the job runs:
mf envs exec env_01J8C4RX -- \ wp search-replace 'staging.example.com' 'example.com' --dry-runpurge a cache
Section titled “purge a cache”mf envs cache-purge calls POST …/cache/purge (cache:write) — everything,
one URL, or a surrogate tag:
mf envs cache-purge env_01J8C4RX --url https://acme-store.com/pricingforward events to localhost
Section titled “forward events to localhost”mf listen polls GET /v1/events and forwards each new event to a local URL —
useful for developing a webhook handler without a
public endpoint. It forwards only events that occur after it starts:
mf listen --type deploy.completed --forward-to http://localhost:4000/webhooksEach event is posted as raw JSON with a Forge-Event-Type header. It is not a
signed webhook delivery — your
Forge-Signature verification path isn’t
exercised; test that against a real endpoint with a delivery replay.
mint keys and reach credentials
Section titled “mint keys and reach credentials”mf keys create mints a scoped key (keys:write — an
isolated scope, never granted by a wildcard). Pin it to a
single site with a resource constraint; the secret prints exactly once:
mf keys create --name deploy-bot \ --scopes sites:read,deployments:write,jobs:read \ --resource-type site --resource-id site_01J7QZ3M \ --ttl 720hmf access covers the credential-grade surface (credentials:read/write,
also isolated): SSH keys, SFTP/DB credentials, admin-password reset, and
one-time magic links into wp-admin:
mf access magic-link --site site_01J7QZ3MSecrets from keys and access commands are printed exactly once — pipe them
straight into your secret store.