CLI Reference
On this page
Table of Contents#
Overview#
Magic Payments ships a CLI on top of fluttersdk_artisan, the same substrate magic_notifications
and magic_social_auth use. Every command runs through:
dart run magic_payments <command> [options]
lib/cli.dart is a separate entry point from lib/magic_payments.dart deliberately, so an app that
never touches the CLI does not pay for the command tree in its runtime build; it imports nothing from
Flutter or dart:ui.
install#
Sets up the package in a consuming app: creating the config file, registering
PaymentsServiceProvider and wiring the config factory into main.dart, the same shape as
magic_notifications install.
dart run magic_payments install
Safe to run more than once: a second run is idempotent and changes nothing it has already put in place.
configure#
Reads or updates individual settings without re-running the full install step.
dart run magic_payments configure [options]
As of this version, payments.* defines no keys of its own (see
Configuration), so configure has little to configure yet.
Expect this command's surface to grow alongside the store rail.
doctor#
A health check over the plugin's installation and configuration state, in the same spirit as
magic_notifications doctor: it validates what is present rather than mutating anything.
dart run magic_payments doctor
dart run magic_payments doctor --verbose
dart run magic_payments doctor --json
Five checks, each of which reads a file in your project and can come back false, then the config state it actually read:
Magic Payments, doctor report
==================================================
Dependency declared: ✓
Dependency resolved: ✓
Config published: ✓
Provider registered: ✓
Config factory wired: ✓
Config state:
driver: 'platform'
store rail key: blank
note: iOS and Android builds read 'payments.revenuecat.public_sdk_key' and
throw at purchase time without it. Web and desktop builds never read it.
✓ Every check passed.
--verbose adds the path and the requirement behind each check, so a false line names the file to
open rather than leaving you to guess which of the five it meant.
--json: the report for an agent#
--json prints exactly one JSON object and nothing else (no banner, no prose), and exits with the
same code as the human report: 0 when nothing is an error, 1 otherwise.
{
"ok": false,
"checks": [
{"id": "dependency_declared", "status": "ok", "message": "magic_payments is declared in pubspec.yaml"},
{"id": "config_factory_wired", "status": "error", "message": "lib/main.dart does not pass paymentsConfig to configFactories", "fix": "run `dart run <app>:artisan payments:install`"},
{"id": "store_rail_key", "status": "warn", "message": "payments.revenuecat.public_sdk_key: blank", "fix": "set payments.revenuecat.public_sdk_key in lib/config/payments.dart; ..."}
]
}
id |
What it reads |
|---|---|
dependency_declared |
pubspec.yaml lists magic_payments |
dependency_resolved |
.dart_tool/package_config.json carries it |
config_published |
lib/config/payments.dart exists |
config_valid |
that file declares the payments root and a served driver |
provider_registered |
lib/config/app.dart registers PaymentsServiceProvider |
config_factory_wired |
lib/main.dart passes paymentsConfig to configFactories |
store_rail_key |
the store rail's public_sdk_key, as present, absent or blank |
status is ok, warn or error; fix appears on every check that is not ok. store_rail_key
can only be ok or warn, for the reason in the next section, so a warn never turns ok false.
A key is only ever reported as present, absent or blank. Its value is never read into the
output, so the JSON is safe to paste into a ticket or hand to an agent.
The store rail key is REPORTED, not enforced#
store rail key answers absent, blank or declared, and none of them fails the command.
That is deliberate rather than lenient. This command runs on your laptop and cannot know which platform you will ship: a web-only or desktop-only app is CORRECT without the key, and failing on it would turn a sound project red. But the alternative measured on a real consumer was worse, because the driver throws under a customer's finger on the purchase sheet when the key is missing, and doctor used to pass in silence while that was true. So it reports, with the consequence attached.
absentmeans norevenuecatblock was published at all.blankmeans the block is there with every platform arm empty, which is the state a project ships in first.declared(presentin--json) means at least one arm carries a value. One is enough: a project that filled in iOS and not Android has configured the key, and which arms it needs is not this command's business.
The value is read as TEXT, with comments stripped first, and never evaluated. The published stub
resolves the key per platform through defaultTargetPlatform (see
Configuration), so what sits on disk is Dart source rather
than a literal.
What it deliberately does NOT report#
It does not say which RAIL your builds can serve. That answer lives behind a conditional import, so
the only value a pure-Dart CLI process could read is the one for its OWN compilation, which is the
dart:io arm every time regardless of what you build for. Printing that would be a confident wrong
answer about the one thing this package exists to get right, so it is absent rather than
approximated. See Drivers.
MCP Exposure#
Only doctor is exposed as an MCP tool. install and configure both mutate a consuming project's
files, and this ecosystem's CLI providers deliberately do not expose a mutating command as an MCP
tool: an agent can ask whether a project's billing setup is healthy, but installing or reconfiguring
it stays a command a human runs.
Related