The mf CLI
mf is the official managed.dev command-line client. Every command is a thin
shell over a public API endpoint, so the CLI never
does anything the API can’t — what it can do is governed by your
API key’s scopes and your role.
The CLI is free on every plan.
This page is the task-oriented walkthrough: install, sign in, the everyday deploy loop, and scripting. The exhaustive command-group reference lives at the CLI reference.
install
Section titled “install”mf is a single Go binary:
go install terriblegit.com/terrible/mf/cmd/mf@latestmf version# mf 0.2.0sign in
Section titled “sign in”mf login verifies an API key and stores it in the CLI’s
config file. There is no browser flow — you paste a key you minted in the
dashboard (or via POST /v1/api-keys), and the prompt reads it with echo
disabled so it never lands in your shell history:
mf login# Paste your API key: (hidden)The recommended practice is to not store that key at all — pass --mint and
mf login uses it once to mint a narrower, shorter-lived key, then stores
that instead:
mf login --mint --scopes sites:read,deployments:write,jobs:read --ttl 24h--ttl is rounded up to whole days; without it the server default of 90 days
applies. mf logout removes the stored key.
For CI, skip mf login entirely and pass the key through the environment:
export FORGE_TOKEN="mfk_live_…"mf sites listthe deploy loop
Section titled “the deploy loop”mf deploy build kicks off a build — an async job
— and by default auto-deploys the resulting artifact. Async commands accept
--wait (poll quietly to completion) or --follow (stream progress); with
neither, they print the job id and return immediately. Either way the command
exits non-zero if the job fails, so it drops cleanly into a pipeline step:
mf deploy build --builder wordpress --ref feature/checkout --followmf deploy targets the production environment by default; pass --env for
anything else. If a release goes wrong, roll back to a previous deployment:
mf deploy deployments # find the deployment to return tomf deploy rollback dep_01J9… --waitDay-to-day you’ll still deploy most changes with
git push managed — mf deploy is for scripting,
re-deploys, and CI.
manage environments
Section titled “manage environments”mf envs reads the site from --site or the config’s default_site:
mf envs create --type branch --branch feature/checkout --waitmf envs delete env_01J8C4RX --waitPromoting a staging environment to production is mf envs push:
mf envs push env_01J8C4RX --mode full --followSee environment lifecycle for how creation, refresh,
and teardown work, and promote & rollback
for what push does under the hood.
run WP-CLI on an environment
Section titled “run WP-CLI on an environment”mf envs exec runs a WP-CLI command inside an environment and
streams the output — the same surface as an SSH shell, but driven by the API
and gated by the wp.cli:exec scope:
mf envs exec env_01J8C4RX -- wp plugin list --status=activemf envs exec env_01J8C4RX -- \ wp search-replace 'staging.example.com' 'example.com' --dry-runread logs
Section titled “read logs”Logs come from the observability endpoints. There is no
live tail -f-style stream — you query a window and re-run (or script it):
mf insights logs --hours 2mf insights logs is per-site (capped at 200 lines per query); mf obs logs
is the account-wide view with more filters:
mf obs logs --hours 1 --severity error --limit 100forward events to localhost
Section titled “forward events to localhost”mf listen polls your account’s events feed and
forwards each new event to a local URL, so you can develop a
webhook handler without exposing a public endpoint.
It baselines on startup and forwards only events that happen after it —
no history replay:
mf listen --forward-to http://localhost:4000/webhooksmf listen --type deploy.completed --forward-to http://localhost:4000/webhooksscripting with –json
Section titled “scripting with –json”Every command accepts --json (anywhere in the argv) and prints machine-stable
output: 2-space-indented JSON, with empty lists normalized to []. Errors come
back as the full API error envelope — type, code,
message, doc_url, request_id, and retry_after_s where relevant —
instead of a formatted message.
Exit codes are a contract you can branch on:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Runtime or API error (including a failed job under --wait/--follow) |
2 |
Usage error — bad flags or arguments |
130 |
Interrupted (Ctrl-C) |
mf jobs list --status failed --json | jq -r '.[].id'functions and agents
Section titled “functions and agents”Two more surfaces ship inside the same binary:
mf fn— local development for hosted functions:mf fn setupinstalls the builder images, andmf fn devbuilds, serves, and watch-rebuilds a function on your machine before you deploy it withmf functions.mf mcp— the official MCP server over stdio, so an AI agent can drive the API with the same scoped, job-returning surface you do. Register it withclaude mcp add forge -- mf mcp.