Skip to main content

mal-plugin — CLI for MyAppsLibrary plugins

Scaffold and publish MyAppsLibrary plugins to the marketplace from the terminal — no browser needed except for the one-time GitHub sign-in.

mal-plugin login              # sign in with GitHub (Device Flow)
mal-plugin new                # scaffold a plugin project (feature or translation)
cd my-plugin-id
mal-plugin publish            # validate, package, submit, and wait for the scan result

Why a separate identity from the web session

An admin login is a wholly separate identity in this marketplace (see the root README) — the CLI isn't that, it's the same GitHub-authenticated developer identity the web app uses, just reached a different way. GitHub's OAuth Device Authorization Flow (the same mechanism gh auth login uses) lets the CLI sign in without a browser-embedded redirect or a locally-listening HTTP server: it shows a short code, you enter it at a URL GitHub gives you, and the CLI polls until you've approved it. The CLI then exchanges the resulting GitHub token for the marketplace's own long-lived bearer token (POST /api/auth/cli/exchange — see backend/app/routers/auth.py), stored locally and never touching a browser cookie.

That bearer token is visible and revocable from the web at any time — sign in on the marketplace site and go to Account → Active CLI sessions.

Install

pip install mal-plugin-cli   # or: pipx install mal-plugin-cli (recommended — isolated environment)

(Not published yet while this is under active development — for now, install from source: see "Development setup" below.)

Configuration

Two environment variables, both optional (defaults point at localhost for local development against this repo's own backend/frontend):

Variable Default Purpose
MAL_PLUGIN_API_BASE_URL http://localhost:8000 The marketplace backend to talk to
MAL_PLUGIN_MARKETPLACE_URL http://localhost:5173 Used only to print the live plugin URL after publish
MAL_PLUGIN_GITHUB_CLIENT_ID (none) Required for login — see below

mal-plugin login requires a GitHub OAuth App with Device Flow enabled

A GitHub OAuth App's client id is not a secret (it's meant to be embedded in a public/native client like this one — see GitHub's Device Flow docs), but it does have to correspond to a real App:

  1. github.com/settings/developersNew OAuth App. The callback URL field is irrelevant to Device Flow — anything valid works.
  2. In the App's settings, check "Enable Device Flow".
  3. export MAL_PLUGIN_GITHUB_CLIENT_ID=<the App's Client ID>

This is a one-time setup step, independent of the backend's own GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET (used for the web Authorization Code flow, see backend/README.md) — the CLI never needs a client secret, since Device Flow's token exchange doesn't require one.

Commands

Command What it does
mal-plugin login Sign in with GitHub (Device Flow)
mal-plugin whoami Show the currently signed-in account
mal-plugin logout Sign out and revoke this CLI session
mal-plugin new [--dir PATH] Scaffold a new plugin project (prompts for type/id/name/description/category)
mal-plugin publish [--dir PATH] Validate, package, submit, and wait for the scan result — requires mal-plugin login first

Only publish requires being signed in (it's the only command that talks to an authenticated /api/dev/* endpoint) — new doesn't, since fetching categories and downloading a boilerplate are both public endpoints. You can scaffold a plugin, poke around, edit plugin.py, all before ever running login; you just won't be able to publish until you have.

new downloads the exact same boilerplate the web /tutorial//docs pages link to (GET /api/boilerplate/download) — there's a single source of truth for what a starter plugin looks like. It also writes a .mal-plugin.json sidecar file next to plugin.toml — marketplace-only bookkeeping (category, short description, the draft's id once created) kept out of plugin.toml itself, since that file's schema is the desktop app's contract, not the marketplace's.

publish runs a local pre-check (a hand-synced subset of the backend's real scan — see mal_plugin/validate.py's docstring) before ever making a network call, then walks the same steps the web wizard does: create-or-reuse draft → set presentation → upload version → submit → poll the automated scan to a result.

Development setup

cd cli
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Point it at your local backend (see ../backend/README.md for getting that running):

export MAL_PLUGIN_API_BASE_URL=http://localhost:8000
export MAL_PLUGIN_MARKETPLACE_URL=http://localhost:5173

Run the tests (no server or network needed — the API client and device flow are mocked):

pytest

Lint:

ruff check mal_plugin tests

Distribution

Not published yetmal-plugin-cli is confirmed available on PyPI (checked, not registered by anyone else) but no release has been built or uploaded. Until then, install from source (see "Development setup" above).

The intended path once it's ready: build and publish to PyPI as mal-plugin-cli — a separate, public registry unrelated to this repo's visibility (cli/'s own scoped pyproject.toml means only this directory's contents would ever leave the repo, regardless of whether the monorepo itself is public or private):

cd cli
python -m build          # generates dist/*.whl + dist/*.tar.gz
twine upload dist/*      # requires a PyPI account + API token

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mal_plugin_cli-0.1.1.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mal_plugin_cli-0.1.1-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

Details for the file mal_plugin_cli-0.1.1.tar.gz.

File metadata

  • Download URL: mal_plugin_cli-0.1.1.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for mal_plugin_cli-0.1.1.tar.gz
Algorithm Hash digest
SHA256 5eb6d5a2c71c256e85b4747d8f7a64339b6c13e7752d95c0e5f5e914cb5b5491
MD5 b7bf57b1d13a65b4df4fd44452f5ca9d
BLAKE2b-256 7b122715240ffacd87d47e8a62963d7e8799eabb3f0109f184c12f408140f696

See more details on using hashes here.

File details

Details for the file mal_plugin_cli-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: mal_plugin_cli-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 18.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for mal_plugin_cli-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 60880132e9dd6cfa39bb26a5bbbb05c539432df4e0e8a775c44194a66f50a077
MD5 396b1b206cdde7e4b1573808a8defe70
BLAKE2b-256 ed654edd096b975797e0ef932b3f94a29a9d2a4e3da6e36ec4e4257eb45bdb1a

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.3

2 files

0.1.2

2 files

This release

0.1.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page