PushMetrics CLI (pm)
pm is the command-line client for PushMetrics. It talks to the same REST API the web app uses, with the same permissions: you see the reports, databases and users you have access to, in one workspace, nothing more.
Use it to run and debug reports, keep report definitions in git, feed CI pipelines, or give an AI coding agent a scriptable handle on your workspace. Every command has a --json mode.
The complete user guide is on the website: PushMetrics CLI.
Install
PLACEHOLDER (D1). The install command depends on the distribution channel and is filled in at release time.
# PLACEHOLDER (D1): install command goes here
pm --version
Requires Python 3.9 or newer. Runs on macOS, Linux and Windows.
Quick start
-
In the PushMetrics app, open Settings → Access Tokens (
/a/tokens), click New token, and copy thepmpat_...value. It is shown once, and it is bound to the workspace that was active when you created it. -
Log in with the token.
pmreads it from a hidden prompt, or from stdin when piped, and stores it in your OS credential store:pm login --token pm whoami
-
Use it:
pm report list pm report get <report-uid> pm report run <report-uid> --send-to-me pm run list --last-days 2 --status failed pm run logs <run-uid> --level ERROR pm report list --json
In CI, skip pm login and set PM_API_TOKEN instead.
PLACEHOLDER (D2). Browser login (
pm loginwithout--token, Auth0 device flow) is documented here only if it ships in the first release.
Commands
pm --help lists every command. pm <group> --help lists a group's actions, pm <group> <action> --help the options, and pm help <group> shows a compact page with examples.
Account:
login Log in with a personal access token.
logout Log out and forget the stored token or session.
whoami Show who you are logged in as, and the workspace.
token Personal access tokens for API / CLI authentication.
config Profiles: which PushMetrics server pm talks to.
Commands:
block Blocks of any type.
chart Charts (Plotly blocks).
database Databases, their schemas and tables.
email Email blocks.
explore Explore blocks (saved data views).
favorite Your favorite reports and other objects.
folder Folders that organize reports.
help Show compact help for a group, with examples.
integration Connected services (Slack, Tableau, Google Drive, ...).
metrics-view Metrics views (the semantic layer).
organization Your organization (the owner of workspaces).
recipient Recipients: who reports are delivered to.
report Reports and their runs.
role Roles and groups in the current workspace.
run Report runs: status, results and logs.
saved-block Saved blocks (reusable block templates).
sftp SFTP upload blocks.
slack Slack message blocks.
slides Google Slides blocks.
sql SQL query blocks.
tableau Tableau view blocks.
user Users in the current workspace.
webhook Webhooks that trigger report runs.
workspace Workspaces you belong to.
The ones most people need:
| Command | What it does |
|---|---|
pm whoami |
Your user and the token's workspace. |
pm report list |
Reports in the workspace. --name filters by name, --limit caps the rows. |
pm report get <uid> |
One report. Full record with --json. |
pm report yaml <uid> |
The report's full YAML configuration, to stdout. |
pm report apply <file> --uid <uid> |
Write a YAML file back to a report. --dry-run shows the diff without saving. |
pm report run <uid> |
Start a run and print its uid. --send-to-me sends the email blocks to you and skips every other destination; --email <address> previews as a saved recipient. |
pm run list |
Recent runs, newest first. --report <uid>, --last-days N, --status failed, --limit N. |
pm run get <run-uid> |
A run's status and timing. |
pm run logs <run-uid> |
A run's log lines. --level ERROR keeps only errors. |
pm run results <run-uid> |
What each block of the run produced. |
pm token list / create <name> / revoke <id> |
Manage your personal access tokens. |
pm config list |
Profiles and the environment overrides in effect. |
--json works before or after the action (pm --json report list and pm report list --json). Data goes to stdout; messages and errors go to stderr. pm exits with 0 on success, 1 when a command fails and 2 when the command line is wrong.
Global options
| Option | Meaning |
|---|---|
--json |
Print JSON instead of tables. |
--quiet |
Suppress informational messages on stderr. Errors still print. |
-v, --verbose |
Log each request, its status and timing to stderr; response bodies on errors only. Tokens are never logged. |
--profile <name> |
Use a profile other than default. |
--api-url <url> |
Talk to a different PushMetrics address for one command. |
--version |
Print the version and exit. |
Environment variables
| Variable | Purpose |
|---|---|
PM_API_TOKEN |
A personal access token. Wins over a token stored by pm login --token. For CI and agents. |
PM_PROFILE |
Profile to use when no --profile is given. |
PM_API_URL |
Talk to this address instead of the profile's. |
PM_CONFIG_HOME |
Where configuration and fallback credential files live. Default: ~/.pm. |
Several workspaces
A token works in one workspace. To work in a second one, create a token there and give it its own profile:
pm config set acme api_url https://pushmetrics.io
pm --profile acme login --token
pm --profile acme report list
pm workspace switch is for browser login only; with a token, the token decides the workspace.
Where credentials live
pm login --token stores the token in the OS credential store (macOS Keychain, Windows Credential Manager, Linux Secret Service) under the service name pushmetrics-cli-pat, one entry per profile. Without a usable credential store it falls back to ~/.pm/tokens.json, mode 0600.
pm also caches the short-lived access token it exchanges from your personal access token, under the service name pushmetrics-cli-jwt or in ~/.pm/jwt_cache.json with mode 0600.
pm logout removes both for the active profile. It does not revoke the token on the server; use pm token revoke or the Access Tokens page for that.
pm never takes a token on the command line and never prints one, in -v output or in errors. It only sends tokens over https://, except to localhost.
Troubleshooting
Not logged in. Run pm login --token with a personal access token, or set PM_API_TOKEN. Nothing stored for the active profile and PM_API_TOKEN unset. Tokens are stored per profile: check pm config list.
That does not look like a personal access token… What was pasted, piped or set in PM_API_TOKEN is not a pmpat_... value. Copy it again exactly.
Personal access token rejected (invalid, expired, or revoked). Create a new token and log in again.
Could not reach https://... (ConnectionError)… Network, or the wrong address: pm config list shows it.
Unknown profile: 'acme'… or Profile 'acme' has no api_url… Each message ends with the pm config set command that fixes it; see also Several workspaces.
API ... failed: 403 / 404 with a Hint: line. The hint names the next step: permissions in the token's workspace, or an id that is not visible there.
Anything else. Re-run with pm -v ... and look at the response status and body.
The website guide lists every error with its fix.
Contributing
The CLI lives in the cli/ directory of the PushMetrics monorepo and must not import anything from the backend packages (superset/, prefect/); a test enforces this. To work on it:
cd cli
python -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]' # contributors only; users install the released package
pytest tests/ -v
ruff check .
Tests mock HTTP with the responses library and never reach a real backend. tests/repo_only/ holds tests that read files outside cli/, such as test_docs_commands_exist.py, which checks every pm command written in this README and in the website guide against the real command tree; they run from a checkout and are not shipped in the sdist. CI runs the suite on every pull request that touches cli/.
When you run a real pm process during development, set PM_CONFIG_HOME to a scratch directory and PYTHON_KEYRING_BACKEND=keyring.backends.fail.Keyring. PM_CONFIG_HOME alone does not isolate credentials: the OS keyring is keyed by profile name, so a scratch run would read, and pm logout would delete, your real stored token.
Adding a resource. For anything with the standard CRUD shape (/<resource>/ list, /<resource>/<uid> single, plus POST/PUT/DELETE):
- Model in
pm/models/<resource>.py: a PydanticBaseModelwithextra="allow"; re-export frompm/models/__init__.py. - Client in
pm/client/<resource>.py: subclassCrudClient[Model], setbase_pathandmodel. Register it on thePMClientfacade inpm/client/__init__.py. - Commands in
pm/commands/<resource>.py: aclick.group(cls=AliasedGroup, aliases={"ls": "list"})withlist/get/create/update/delete; useparse_dataandmerge_fieldsfrompm/commands/_helpers.pyfor the--data '<json>'pattern. Skip verbs the backend does not support. - Wire it in
pm/cli.pywithcli.add_command(...). - Tests in
tests/test_client_<resource>.py, asserting on model attributes. - Docs: add the command to the website guide (
website/content/posts/docs/admin/2026-10-12-cli.md); the docs test fails if a documented command does not exist.
Endpoint paths to mirror live in frontend/src/shared/services/*.ts; the frontend prefixes everything with /api/v1.
The PMClient facade is reusable from Python without the command layer:
from pm.client import PMClient
from pm.config import get_profile
client = PMClient.from_profile(get_profile("default"))
for report in client.reports.list():
print(report.uid, report.name)
Authentication resolution order inside PMSession.from_profile: PM_API_JWT (a delegation JWT the PushMetrics AI agent sets, used as-is) > personal access token (PM_API_TOKEN or stored, exchanged at /api/v1/security/exchange for a short-lived workspace-scoped JWT) > Auth0 session cookies from a browser login. Bearer JWTs carry a workspace_id claim that the backend installs as the request's workspace, so a pure Bearer client has full workspace context; cookies are the interactive path only.
Metadata
Release files for pushmetrics-cli 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pushmetrics_cli-0.1.0.tar.gz | 192.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pushmetrics_cli-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 334.8 kB
Release files / pushmetrics_cli-0.1.0.tar.gz
| Download URL | pushmetrics_cli-0.1.0.tar.gz |
|---|---|
| Size | 192.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a29824711097d55219fc28294bea01eb522f0038caccb4ca80396d18ed2b34c7
|
|
BLAKE2b-256 checksum How to use checksums |
cdcb987710cd018b34e06e0a6666527f69474184858a2ed83ced6830a882b3b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / pushmetrics_cli-0.1.0-py3-none-any.whl
| Download URL | pushmetrics_cli-0.1.0-py3-none-any.whl |
|---|---|
| Size | 142.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
46bb6fff0890fbd5edf20961c881a0d0ea27a5b2662e8c1df3ac7dd14aeebb51
|
|
BLAKE2b-256 checksum How to use checksums |
d700fbb19717c00ea306382c1a14ec3e6c71b4b353c40e7916933816746f462e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency log