cli

command
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

README

mxd

mxd is the command line client for a metaxisdata server. It is built for agents: every command writes exactly one JSON document to stdout, and progress, warnings and errors go to stderr. Failures carry a stable code and a stable exit status, so a caller can decide what to do next without parsing prose.

Install and sign in

$ make build-cli                 # produces ./build/mxd
$ mxd auth login --server https://mx.example.com

The command prints a URL and a code. The URL already carries the code, so opening it goes straight to the confirmation screen; mxd polls until you decide, then stores the token in ~/.config/metaxisdata/config.json (mode 0600). Pass --no-prefill-url to print the bare page address instead, for a workflow where the code has to be typed.

The confirmation screen always shows the code next to the client name and version, the source address and the time, and always requires an explicit decision, so a request you did not start is still recognisable.

The address comes from the workspace's external URL setting. A fresh or locally run workspace usually has none, and rather than leave you with nothing to open, mxd falls back to <server>/device. That is correct whenever the server also serves the web application; if you run the SPA separately (the usual local setup, where Vite serves it on :3000), set the workspace external URL to that address and the server will name the right page itself.

The server address is saved with the token, because a token is issued by one server; later commands do not need --server again. mxd auth logout revokes the token and keeps the address.

--login-timeout (default 10m) bounds the wait for that approval. It is separate from --timeout (default 30s), which bounds a single request: the approval waits for a person, not for a server.

To keep several identities on one machine, point each one at its own file:

$ METAXISDATA_CONFIG=/tmp/agent-a/mxd.json mxd auth login --server https://mx.example.com

For CI, mxd auth login --service-account <email> exchanges a service account's key, read from METAXISDATA_SERVICE_KEY, for an API token. That token lasts an hour, so a long-lived job should inject METAXISDATA_TOKEN instead.

Analysis scopes

A SQL statement cannot be resolved without a database context: the statement names an object down to database.schema.table at most, and never names the instance. Every lineage sql call therefore needs at least one scope.

Scopes are read from METAXISDATA_SCOPES, only for the duration of the command:

$ export METAXISDATA_SCOPES='dev=1;shop,prod=9;shop;public'

Each entry is either a bare GUID or name=guid. --scope narrows the selection for one call; it accepts a configured name, a GUID, or all.

Scopes are never written to a file. Several agents can share a machine while serving different projects, and a remembered scope set would be silently overwritten by whichever agent ran last. Which scopes a project uses is a per-project decision: keep the list in that project's own documentation and export it before invoking mxd.

A scope is resolved against every listed scope independently, and the results are reported per scope. Selecting several scopes does not merge contexts and does not discover cross-environment relations that are absent from the metadata.

Where the GUIDs come from

Do not construct a GUID by hand: the segment layout differs per engine (the MySQL-family schema segment is empty, PostgreSQL needs it). Copy the values the server reports.

$ mxd database list --instance 1          # each row carries "guid", e.g. "1;shop"
$ mxd meta list '1;shop;' --type SCHEMA   # each row carries "guid", e.g. "1;shop;public"

Commands

mxd auth login [--server <url>] [--no-browser] [--no-prefill-url] [--login-timeout 10m]
mxd auth status
mxd auth logout

mxd config show          # effective server, credential source and scopes
mxd config path

mxd instance list
mxd database list [--instance <id>]

mxd meta list <parent-guid> [--type TABLE]
mxd meta get <guid> [--type]
mxd meta search <keyword> [--type] [--parent-guid-prefix]
mxd meta ddl <guid> [--type]

mxd lineage sql [--scope <name|guid|all>]... --file <path|-> [--depth N] [--include-temp]
mxd lineage graph <guid> [--depth N] [--direction up|down|both] [--column <name>]

mxd skill install [--dir <path>]
mxd skill show

mxd version
Teaching your agent

mxd carries an agent skill and installs it for you:

$ mxd skill install
{"changed": true, "name": "mxd-cli", "path": "/home/u/.agents/skills/mxd-cli/SKILL.md"}

The skill is embedded in the binary, so a machine that has mxd needs no checkout to give its agent the same instructions. It lands in ~/.agents/skills/mxd-cli/SKILL.md, where the agent runtime discovers it; --dir targets another location, such as ~/.claude/skills or a project's own .agents/skills. An existing file is replaced, so re-running it after an upgrade is how a machine picks up new wording.

mxd skill show prints the same document as JSON, for a harness that would rather capture it than read it from a file.

The skill also covers the case where the deployment serves the same capabilities over the Model Context Protocol: an MCP-capable harness should use those tools instead of shelling out. The rules are the same, with the analysis scope passed as a tool argument rather than read from METAXISDATA_SCOPES, and objects addressed by name rather than by GUID.

mxd config show is the way to answer "which configuration is this process actually using": it reports every effective value together with the layer it came from (flag, env:..., file:..., or none).

Listings page through every response. When a listing hits --max-items (default 1000) the envelope says "truncated": true and carries "nextPageToken". meta list without --type is the one exception: its response carries a page token per meta type rather than one for the whole response, so walking further needs --type.

Reading the output

$ mxd lineage sql --file etl.sql --depth 2
{
  "results": [
    {
      "scopeName": "dev",
      "scopeGuid": "1;shop",
      "relations": [
        {"sourceGuid": "1;shop;;orders", "sourceColumn": "amount",
         "targetGuid": "1;shop;;order_daily", "targetColumn": "amount",
         "isTemp": false}
      ],
      "graphs": [{"rootGuid": "1;shop;;order_daily", "nodes": [], "edges": []}],
      "warnings": []
    }
  ],
  "warnings": []
}

The result is grouped by scope even for a single scope, so a caller never has to branch on how many scopes it asked for.

Temporary relations are hidden by default. Such a relation's target only exists inside the statement. It matters in exactly one situation: when the statement's result is not written anywhere, which is every bare SELECT. As soon as the statement has a real target — a view, a table it inserts into — the synthetic relations are duplicates of that target and the server drops them, so nothing is hidden.

That means the default can leave a scope with no relations to show. When it does, the entry carries "tempRelationsHidden": N and a warning naming the flag, so an empty list never reads as "this statement has no lineage":

{"results": [{"scopeName": "dev", "scopeGuid": "1;shop", "relations": [],
              "tempRelationsHidden": 2,
              "warnings": ["all 2 relations of this scope are temporary: ... pass --include-temp to see them"]}],
 "warnings": []}

--include-temp reports them; targetGuid is then empty and targetColumn is the query's output alias. The flag only affects what is shown: the --depth expansion never followed a temporary target, because a target that exists only inside the statement has no graph to walk.

The JSON shape

Protobuf messages are rendered with protojson, the same encoding the REST gateway and the audit log use, so field names are lowerCamelCase (sourceGuid, not source_guid) and enums are names ("TABLE", not 4). Unset fields are emitted rather than omitted — an absent list is [], an unset string is "", a false flag is false — so the shape of the document does not change with the data and a caller never has to tell "missing" from "empty".

Exit codes

Code Meaning What to do
0 Success —
1 Bad input: flags, an empty statement, server_required, scope_required, config_invalid Fix the invocation; the error carries a hint
2 Not authenticated: the token is missing, expired or revoked, or the device login session is gone or was denied mxd auth login
3 Not found Check the GUID
4 Permission denied Ask an administrator
5 Could not complete: unavailable (the server was not reachable), resource_exhausted, or a server fault Retry, then check that the server is running and read its logs
6 Timeout or cancellation, local or remote, including --login-timeout running out Retry, or raise --timeout / --login-timeout

The error envelope also carries a code string, which is finer grained than the exit status: server_required, scope_required and config_invalid all exit 1 but name different fixes, and a server that is not reachable reports unavailable rather than the internal a fault of its own would give.

Notes

  • mxd talks ConnectRPC with a bearer token, so it is unaffected by the cookie-based CSRF protection the web session uses.
  • --ca-cert <pem> trusts an extra certificate for a self-signed deployment; --insecure skips verification and prints a warning.
  • The token is stored in clear text. It is equivalent to a seven day session; the CLI never prints it.

Documentation

Overview

Command mxd is a client for a metaxisdata server, built for agents: every command writes one JSON document to stdout and reports progress on stderr.

Directories

Path Synopsis
Package authflow drives the device login: it asks the server for a request, tells the person where to approve it, and polls until the server has an answer.
Package authflow drives the device login: it asks the server for a request, tells the person where to approve it, and polls until the server has an answer.
Package client builds the ConnectRPC clients the CLI talks through and maps failures onto the exit codes an agent branches on.
Package client builds the ConnectRPC clients the CLI talks through and maps failures onto the exit codes an agent branches on.
Package cmd wires the mxd command tree.
Package cmd wires the mxd command tree.
Package config reads and writes the CLI's credentials file.
Package config reads and writes the CLI's credentials file.
Package env reads the METAXISDATA_* environment, which is where a project's analysis scopes come from.
Package env reads the METAXISDATA_* environment, which is where a project's analysis scopes come from.
Package output renders command results.
Package output renders command results.
Package skill carries the agent-facing skill that ships inside the mxd binary.
Package skill carries the agent-facing skill that ships inside the mxd binary.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL