npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@magda/mgd

v6.1.0

Published

MAGDA local command-line interface

Downloads

428

Readme

@magda/mgd — MAGDA Command-Line Interface

mgd is the local command-line interface for the MAGDA data catalog platform, developed as part of epic #3648. It lets you work with a MAGDA catalog from your terminal — or from an AI coding assistant — without cloning the repository or running anything inside the cluster. With it you can:

  • authenticate with an API key and manage multiple site profiles;
  • search the catalog by keyword or semantic similarity;
  • inspect and download datasets, distributions and files (including large ones);
  • create and edit dataset records, upload files, and manage custom aspects;
  • call any MAGDA REST endpoint directly.

mgd is designed to be script- and agent-friendly: results go to stdout, progress/diagnostics go to stderr, machine output is available via --json / --jsonl, and it uses stable exit codes. It ships with an assistant "skill" so coding agents such as Claude Code can drive it — see Using mgd with a coding agent.

See also: How to create an API key.

Installation

Choose the installation path that suits you.

Install with a coding agent — easiest

Copy the prompt for your coding agent and paste it into a new task. The agent will guide you through installing both the mgd CLI and its MAGDA skill.

Help me install and configure the MAGDA mgd CLI for use with Claude Code.

1. Detect my operating system and check `node --version` and `npm --version`.
   mgd requires Node.js 22 or newer. If Node.js is missing or too old, explain
   the recommended installation or upgrade and ask for my confirmation before
   changing my system. Prefer my existing version manager or an official
   Node.js distribution. Do not use sudo, change my shell configuration, or
   execute a remote installation script without explicit approval.
2. Install the CLI with `npm install -g @magda/mgd`, then verify it with
   `mgd --version`. If npm reports a permissions problem, explain it and
   recommend a user-level Node.js/npm setup instead of escalating privileges.
3. Install only the Claude Code skill with
   `mgd skills install --agent claude`. Tell me if I need to start a new Claude
   Code session before the skill will be discovered.
4. When I am ready to configure MAGDA access, offer to open a new visible,
   interactive terminal window and start `mgd profile create default`. Ask
   before opening it. Launch only that command: do not automate keystrokes,
   capture the terminal contents, or inspect credential entry. If you cannot
   open a suitable terminal, give me the exact command to run myself.
5. Never ask me to paste an API key into chat and never put credentials in
   command arguments, source files, or shell history. I will enter the site URL,
   API-key ID, and masked API key directly in the interactive terminal. Empty
   key fields should configure anonymous access.
6. After I confirm that profile setup finished, run `mgd auth status` and report
   whether installation and connection succeeded. If any step fails, stop and
   explain the failed command and the next action; do not claim completion.
Help me install and configure the MAGDA mgd CLI for use with Codex.

1. Detect my operating system and check `node --version` and `npm --version`.
   mgd requires Node.js 22 or newer. If Node.js is missing or too old, explain
   the recommended installation or upgrade and ask for my confirmation before
   changing my system. Prefer my existing version manager or an official
   Node.js distribution. Do not use sudo, change my shell configuration, or
   execute a remote installation script without explicit approval.
2. Install the CLI with `npm install -g @magda/mgd`, then verify it with
   `mgd --version`. If npm reports a permissions problem, explain it and
   recommend a user-level Node.js/npm setup instead of escalating privileges.
3. Install only the Codex skill with `mgd skills install --agent codex`. Tell me
   if I need to start a new Codex session before the skill will be discovered.
4. When I am ready to configure MAGDA access, offer to open a new visible,
   interactive terminal window and start `mgd profile create default`. Ask
   before opening it. Launch only that command: do not automate keystrokes,
   capture the terminal contents, or inspect credential entry. If you cannot
   open a suitable terminal, give me the exact command to run myself.
5. Never ask me to paste an API key into chat and never put credentials in
   command arguments, source files, or shell history. I will enter the site URL,
   API-key ID, and masked API key directly in the interactive terminal. Empty
   key fields should configure anonymous access.
6. After I confirm that profile setup finished, run `mgd auth status` and report
   whether installation and connection succeeded. If any step fails, stop and
   explain the failed command and the next action; do not claim completion.
Help me install and configure the MAGDA mgd CLI for use with opencode.

1. Detect my operating system and check `node --version` and `npm --version`.
   mgd requires Node.js 22 or newer. If Node.js is missing or too old, explain
   the recommended installation or upgrade and ask for my confirmation before
   changing my system. Prefer my existing version manager or an official
   Node.js distribution. Do not use sudo, change my shell configuration, or
   execute a remote installation script without explicit approval.
2. Install the CLI with `npm install -g @magda/mgd`, then verify it with
   `mgd --version`. If npm reports a permissions problem, explain it and
   recommend a user-level Node.js/npm setup instead of escalating privileges.
3. Install only the opencode skill with
   `mgd skills install --agent opencode`. Tell me if I need to start a new
   opencode session before the skill will be discovered.
4. When I am ready to configure MAGDA access, offer to open a new visible,
   interactive terminal window and start `mgd profile create default`. Ask
   before opening it. Launch only that command: do not automate keystrokes,
   capture the terminal contents, or inspect credential entry. If you cannot
   open a suitable terminal, give me the exact command to run myself.
5. Never ask me to paste an API key into chat and never put credentials in
   command arguments, source files, or shell history. I will enter the site URL,
   API-key ID, and masked API key directly in the interactive terminal. Empty
   key fields should configure anonymous access.
6. After I confirm that profile setup finished, run `mgd auth status` and report
   whether installation and connection succeeded. If any step fails, stop and
   explain the failed command and the next action; do not claim completion.

For skill installation locations, project-scoped installs, refreshes and removal, see Installing the skill.

Install manually

mgd requires Node.js ≥ 22. Install it globally so the mgd command is on your PATH:

npm install -g @magda/mgd
mgd --version

Or run it without installing:

npx @magda/mgd <command>

Global installation is recommended when using mgd with a coding agent because the installed skill expects the command to remain available on your PATH.

The package is self-contained (one runtime dependency) and ships the assistant skill files under skills/.

Quick start

# 1. Create a profile (prompts for site URL, API key ID and key; or pass them as flags)
mgd profile create default

# 2. Confirm who you are and where
mgd auth status

# 3. Search
mgd search datasets "climate temperature"
mgd search semantic "rainfall impact on crop yield"    # if semantic search is available

# 4. Inspect and download
mgd dataset get magda-ds-<uuid>
mgd dataset distributions magda-ds-<uuid> --jsonl
mgd dist download magda-dist-<uuid> -o data.csv

Authentication and profiles

Setting up a profile

Create an API key in the MAGDA web UI first (Settings → API Keys), then create a profile:

mgd profile create default
# or non-interactively:
mgd profile create default --url https://dev.magda.io --key-id <id> --key <key>
  • The profile <name> is required — there is no implicit target, so you can't accidentally set up the wrong profile.
  • --url accepts either a site URL (https://dev.magda.io) or a full API base URLmgd normalises it by probing <url> first, then <url>/api, so non-standard gateway mounts work.
  • Any of --url / --key-id / --key you don't pass is prompted for (the key is entered hidden). Credentials are verified against the API before saving.
  • Leave the API key ID empty to configure anonymous access (MAGDA supports anonymous read access to public data).
  • create refuses to overwrite an existing profile — use profile update to change one, or profile remove to delete it first.

Managing profiles

Credentials are stored per named profile in ~/.config/mgd/config.json (respecting $XDG_CONFIG_HOME), with restrictive permissions (0600 file, 0700 directory). The default profile is named default. Every profile subcommand except list takes a required positional <name>.

mgd profile create prod --url https://prod.example.com   # create a new profile
mgd profile update prod --key-id <id> --key <key>        # patch only the given fields
mgd profile list                                         # list profiles
mgd profile use prod                                     # switch the active profile
mgd profile remove prod                                  # delete a profile
mgd auth status                                          # who am I, where
  • profile update <name> changes only the fields you pass (--url / --key-id / --key); it does not prompt, errors if you pass no field, and errors if the profile doesn't exist. Handy for rotating a key.
  • profile remove <name> deletes the profile; if it was the active one, the active profile resets to default.
  • mgd auth login is a deprecated alias of profile create (it keeps its --profile <name> flag, defaulting to default) and prints a notice. mgd auth logout has been removed — use mgd profile remove <name>.

mgd auth status reports the active profile, base URL and the identity returned by the server; it shows anonymous when no credentials are configured.

The active profile is whichever mgd profile use <name> last selected (saved as activeProfile in the config). For any command, the profile is resolved in this order of precedence:

  1. MGD_PROFILE (environment) — use this named profile for a single invocation, overriding the active profile;
  2. the active profile set by mgd profile use;
  3. the profile literally named default.

Independently of which profile is selected, MGD_BASE_URL / MGD_API_KEY_ID / MGD_API_KEY override the corresponding fields of the resolved profile — and when all three are set, no config file is read or written (see below).

Environment variables (CI / agents)

Environment variables override the stored profile and are ideal for CI or ephemeral containers. When all three of MGD_BASE_URL, MGD_API_KEY_ID and MGD_API_KEY are set, no config file is read or written:

| Variable | Purpose | | ---------------- | ------------------------------------------- | | MGD_BASE_URL | Site or API base URL | | MGD_API_KEY_ID | API key ID | | MGD_API_KEY | API key value | | MGD_PROFILE | Select a stored profile by name | | NO_COLOR | Disable ANSI colour (also via --no-color) |

export MGD_BASE_URL="https://dev.magda.io/api"
export MGD_API_KEY_ID="…"
export MGD_API_KEY="…"
mgd auth status

Output modes, scripting and exit codes

  • stdout carries the result; stderr carries progress, warnings and error details. Suppress diagnostics with 2>/dev/null.
  • --json prints one pretty JSON document. --jsonl prints one JSON object per line for list results — ideal for streaming into jq, grep, xargs, etc.
  • Read and list commands emit their data as JSON. The aspect/record mutations (aspect create, dataset aspect set/delete, dataset/dist update) print a compact {…, "ok": true} result in --json mode, while aspect get / dataset aspect get emit JSON already (the flag is optional there). Downloads write the file itself and take no --json.
  • In --json/--jsonl mode, errors are emitted to stderr as a structured object {"error":{"code","message","status","hint"}} so agents can parse failures.
# titles of the first 20 datasets matching a query
mgd search datasets "water quality" --limit 20 --jsonl | jq -r '.title'

Exit codes

| Code | Meaning | | ---- | -------------------------------------------------- | | 0 | Success | | 1 | General runtime / API error | | 2 | Usage error (bad argument, flag or env var) | | 3 | Authentication error (missing/invalid credentials) | | 4 | Not found (record or object does not exist) |

Searching the catalog

MAGDA offers two complementary search modes:

# Keyword / faceted search — best for known terms, filters, pagination
mgd search datasets "rainfall" --limit 10 --offset 0

# Semantic (embedding) search — best for conceptual, natural-language queries
mgd search semantic "impact of drought on crop yield"

Use keyword search when you know the vocabulary; use semantic search when the wording differs from the dataset's metadata. Semantic search requires a deployment with the semantic-search components installed — on sites without it, mgd search semantic returns a clear semantic-search-unavailable error (a non-zero exit) rather than failing silently, so you can fall back to keyword search. A useful recipe is to run both with --jsonl and merge/de-duplicate by dataset ID.

Inspecting datasets and distributions

mgd dataset get magda-ds-<uuid>                       # dataset record
mgd dataset get magda-ds-<uuid> --json                # full record as JSON
mgd dataset get magda-ds-<uuid> --aspect <aspectId>   # just one aspect
mgd dataset distributions magda-ds-<uuid> --jsonl     # its distributions
mgd dist get magda-dist-<uuid> --json                 # a single distribution

--json returns the complete record with every aspect attached to it, including any custom aspects you have set (mgd aspect create + --aspect / mgd dataset aspect set). Human-mode output shows the curated highlights only; pass --json (and pipe through jq) to see everything.

Distribution records carry metadata under aspects such as dcat-distribution-strings (title, format, downloadURL/accessURL). Use --jsonl + jq to pull out just the fields you need.

Downloading data

mgd dist download magda-dist-<uuid> -o data.csv         # to a file
mgd dist download magda-dist-<uuid> -o - | head         # stream to stdout
mgd file download magda-datasets/<datasetId>/<distId>/<fileName> -o data.csv   # by bucket/key

mgd dist download resolves the distribution's downloadURL: MAGDA-hosted magda://storage-api/… URLs are fetched through the gateway (with your credentials); plain http(s):// URLs are fetched directly (no MAGDA auth headers sent to third-party hosts). For large files, downloads use HTTP Range requests and support --resume to continue an interrupted transfer:

mgd dist download magda-dist-<uuid> -o big.tif --resume

Creating and editing datasets

mgd reproduces the same end-state record operations as the web "Add Dataset" wizard, so datasets you create or edit with the CLI remain fully editable in the web UI. New datasets are created as drafts unless you pass --publish.

# 1. Create a draft dataset
mgd dataset create \
  --title "River gauge readings 2025" \
  --desc "Daily river height and flow measurements." \
  --json                                              # -> magda-ds-<uuid>

# 2. Upload a file and attach it as a distribution
mgd dataset add-file magda-ds-<uuid> ./readings.csv --title "2025 readings" --format csv

# 3. Register a link-only distribution (no upload)
mgd dataset add-file magda-ds-<uuid> --access-url https://example.org/data.csv --title "Source data"

# 4. Update metadata
mgd dataset update magda-ds-<uuid> --title "River gauge readings (2025, v2)"

# 5. Replace the file behind a distribution (adds a new version entry)
mgd dist replace-file magda-dist-<uuid> ./readings-corrected.csv

# 6. Publish — cascades to the dataset's distributions (--without-distributions to opt out)
mgd dataset publish magda-ds-<uuid>          # unpublish the same way
mgd dist publish magda-dist-<uuid>           # or flip a single distribution

Datasets created by the CLI are stamped with a source aspect ({"id":"magda","name":"Magda CLI (mgd)","type":"internal","url":<site>}) — the same id the web client uses, so they show up as editable records in the web metadata tools, with a distinct name marking their CLI provenance.

Publishing is a deliberate step. Create as a draft, review, then publish explicitly. add-file / replace-file are multi-step operations; if a step fails after the upload, mgd rolls back the uploaded object where it can and prints the exact commands to finish or undo — it never leaves silent partial state.

Versioning. The CLI maintains the application-managed version aspect automatically: dataset create / add-file seed and tag the initial version, and dataset update, dist update, dist replace-file, add-file and dist remove bump the changed record's version (tagged with the registry event id, so past versions work with the registry's time-travel API). publish / unpublish don't bump versions (lifecycle state, not content). Don't hand-edit the version aspect; dataset aspect set / aspect patch / aspect delete are the manual escape hatch and never auto-bump.

Common aspects

Records carry data in named aspects. The ones the CLI reads or writes most:

| Aspect | Record | Holds / notes | | --- | --- | --- | | dcat-dataset-strings | dataset | title, description, keywords, themes, languages, issued/modified | | dcat-distribution-strings | distribution | per-file title, format, downloadURL, accessURL, byteSize | | publishing | dataset & distribution | { "state": "draft" \| "published" } — use publish/unpublish, don't hand-edit | | dataset-distributions | dataset | { "distributions": [<distId>, …] } — CLI-managed by add-file/dist remove; don't hand-edit | | version | dataset & distribution | CLI-managed history — don't hand-edit | | access-control | dataset | ownerId, orgUnitId, constraintExemption | | source | dataset | provenance (id: "magda", name: "Magda CLI (mgd)", type, url) | | dataset-publisher | dataset | { "publisher": "<organisation record id>" } — publishing org shown in the web UI; the CLI does not set it yet (#3715) | | temporal-coverage | dataset | optional{ "intervals": [{ "start", "end" }] }; set manually when the data spans a time range | | spatial-coverage | dataset | optional — bounding box / named region; set manually when the data has a spatial extent |

Custom aspects

The registry supports user-defined aspects with JSON-schema validation. mgd exposes them (the web UI does not):

# aspect definitions
mgd aspect list
mgd aspect get <aspectId>
mgd aspect create <aspectId> --name "My Aspect" --schema @schema.json
mgd aspect delete <aspectId>                     # only if no record data references it

# aspect data on any record (dataset or distribution)
mgd dataset aspect get    magda-ds-<uuid> <aspectId>
mgd dataset aspect set    magda-ds-<uuid> <aspectId> @data.json    # full replace: inline JSON, @file, or - for stdin
mgd dataset aspect patch  magda-ds-<uuid> <aspectId> '{"keywords":["a","b"]}'  # partial: merge these fields, keep the rest
mgd dataset aspect delete magda-ds-<uuid> <aspectId>

Use set to replace the whole aspect and patch to change only the supplied fields (a server-side deep merge via the registry's ?merge=true, so untouched fields survive). For advanced RFC 6902 operations (remove/test/move), call the raw endpoint: mgd api request PATCH /v0/registry/records/<id>/aspects/<aspectId> --body @patch.json.

Every mutation command also accepts repeatable --aspect <id>=<json|@file|-> to attach custom aspect data at create/update time.

Uploading files directly to storage

mgd file upload ./big.tif --bucket magda-datasets --key path/to/big.tif --record-id magda-ds-<uuid>

Files at or above 16 MB automatically use resumable multipart upload (one bounded part at a time, constant memory); smaller files use a single request. Multipart needs a deployment that exposes the multipart storage endpoints (/v0/storage/multipart/{initiate,part,complete,abort}); older deployments fall back to single-shot upload automatically (--single-shot forces it). Pass --record-id <datasetId> so record-linked storage authorization applies.

Raw API access

For endpoints without a curated command, call the REST API directly — with your credentials and structured error handling:

mgd api request GET /v0/registry/records/<id> --query aspect=dcat-dataset-strings --json
mgd api request POST /v0/registry/records --body-file record.json
echo '{"active":true}' | mgd api request PUT /v0/some/endpoint --body -

Command reference

| Command | Description | | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | profile create <name> / update <name> / remove <name> | Create / patch / delete a site profile | | profile list / profile use <name> | List / switch profiles | | auth status | Show the active profile and authenticated user | | auth login | Deprecated alias of profile create (--profile) | | search datasets <query> | Keyword dataset search | | search semantic <query> | Semantic (embedding) search | | dataset get <id> | Fetch a dataset record | | dataset distributions <id> | List a dataset's distributions | | dataset create | Create a dataset (draft by default) | | dataset update <id> | Update dataset metadata | | dataset add-file <id> [file] | Upload/attach a distribution (or --access-url) | | dataset aspect get/set/patch/delete <recordId> <aspectId> | Read/write custom aspect data on any record (set=replace, patch=merge) | | dist get <id> / dist update <id> | Inspect / edit a distribution | | dist download <id> | Download a distribution's file (--resume) | | dist replace-file <id> <file> | Replace a distribution's file, bump version | | dist remove <id> | Remove a distribution from its dataset (deletes record + stored files; --keep-files to keep them) | | file upload <file> / file download <bucket/key> | Direct storage transfer | | aspect list / get <id> / create <id> / delete <id> | Manage aspect definitions | | api request <method> <path> | Call any MAGDA API endpoint | | skills install [--agent <name>] | Install the agent skill (all agents, global by default) | | skills uninstall [--agent <name>] | Remove the agent skill |

Run mgd --help or mgd <command> --help for full option documentation.

Using mgd with a coding agent

mgd ships with a tool-agnostic assistant skill so an LLM coding agent can drive the catalog safely. The skills/ folder contains:

  • mgd-workflows.md — command usage, output modes, search strategy, recipes, the create → enrich → add-file → publish workflow, a common-aspects reference, safety rules and error triage;
  • dataset-elicitation.md — "metadata consultant" behaviour for guided dataset creation (infer before asking, quick vs guided path, confirm-then-write);
  • SKILL.md — the standard Agent-Skill wrapper (name + description frontmatter pointing at the two files above); auto-discovered by Claude Code, Codex and opencode.

Installing the skill

Install it with the built-in installer. By default it installs for all three agents, globally, so the skill is available from any working directory:

mgd skills install

This drops the skill into each agent's native skills directory:

| Agent | Global (default) | With --project [dir] | | ----------- | -------------------------------------- | ----------------------------------- | | Claude Code | ~/.claude/skills/magda-mgd/ | <dir>/.claude/skills/magda-mgd/ | | Codex | ~/.codex/skills/magda-mgd/ | <dir>/.agents/skills/magda-mgd/ | | opencode | ~/.config/opencode/skills/magda-mgd/ | <dir>/.opencode/skills/magda-mgd/ |

All three natively auto-discover SKILL.md skills and load the instructions on demand when a task matches the skill's description.

mgd skills install --agent codex        # just one agent
mgd skills install --project            # into ./ (current repo) instead of globally
mgd skills install --project ../app     # into a specific project directory
mgd skills uninstall                    # remove (all agents, global) — --agent/--project mirror install

Installs are idempotent — re-running refreshes the managed magda-mgd/ folder. Make sure mgd is on the agent's PATH and that credentials are configured (a saved profile, or the MGD_* environment variables; check with mgd auth status) before starting the agent.

Troubleshooting

  • Authentication error (exit 3) — no or invalid credentials. Recreate the profile with mgd profile create <name> (or update it with mgd profile update <name> --key-id … --key …), or check MGD_API_KEY_ID / MGD_API_KEY.
  • semantic-search-unavailable (exit 1) — the target site doesn't have the semantic-search components installed; use mgd search datasets instead.
  • Not found (exit 4) — the record or storage object doesn't exist (or your key can't see it).
  • A large upload is rejected — the deployment may lack the multipart storage endpoints and hit an ingress body-size limit on single-shot upload; upload against a deployment with multipart support.
  • Parsing output in scripts — always pass --json / --jsonl and rely on the documented exit codes rather than scraping human-readable text.

Development

This package lives in the packages/mgd/ subdirectory of the Magda monorepo.

yarn build       # TypeScript → ESM via esbuild, output to bin/
yarn test        # unit tests (Mocha + tsx)
yarn typecheck   # type-check without emitting

Node.js ≥ 22 is required (set in engines in package.json).

License

Apache 2.0