Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@pmxt/cli

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pmxt/cli - npm Package Compare versions

Comparing version
2.46.0
to
2.46.1
+4
-1
cli/base-command.js

@@ -17,5 +17,8 @@ "use strict";

json: core_1.Flags.boolean({ description: "Output raw response data as JSON." }),
"base-url": core_1.Flags.string({ description: "PMXT API base URL. Defaults to the hosted PMXT API." }),
local: core_1.Flags.boolean({ description: "Use a local PMXT instance." }),
hosted: core_1.Flags.boolean({ description: "Use the hosted PMXT API." }),
"base-url": core_1.Flags.string({ description: "Advanced: override the PMXT API base URL." }),
"pmxt-api-key": core_1.Flags.string({ description: "PMXT API key. Precedence: flags > env > auth store. Env: PMXT_API_KEY." }),
"auth-store": core_1.Flags.string({ description: "Path to a PMXT CLI auth store JSON file." }),
"no-suggest-hosted": core_1.Flags.boolean({ description: "Do not show hosted PMXT suggestions when using local mode." }),
};

@@ -22,0 +25,0 @@ exports.credentialFlags = {

+11
-2

@@ -18,2 +18,7 @@ "use strict";

MODES
Hosted PMXT is used when an API key is configured.
Without hosted auth, commands use a local PMXT instance.
Use --hosted or --local to force a mode.
COMMON COMMANDS

@@ -37,7 +42,9 @@ pmxt <exchange> markets Search markets

pmxt enterprise Run Enterprise matched-market and SQL commands
pmxt server Manage an installed local pmxt-core sidecar
pmxt server Manage a local PMXT instance
FLAGS
--pmxt-api-key <key> One-shot hosted PMXT API key
--base-url <url> Override PMXT API base URL
--local Use a local PMXT instance
--hosted Use the hosted PMXT API
--base-url <url> Advanced PMXT API base URL override
--json Print raw JSON

@@ -48,2 +55,4 @@ --help Show command help

pmxt polymarket markets --query Trump --limit 5
pmxt polymarket markets --local --query Trump --limit 5
pmxt polymarket markets --hosted --query Trump --limit 5
pmxt kalshi events --query "NBA" --limit 5 --json

@@ -50,0 +59,0 @@ pmxt polymarket orderbook <outcome-id> --limit 20

@@ -48,6 +48,7 @@ "use strict";

const constants_js_1 = require("./constants.js");
const server_manager_js_1 = require("./server-manager.js");
exports.ALLOWED_EXCHANGES = new Set([
"polymarket", "kalshi", "kalshi-demo", "limitless", "probable", "baozi",
"myriad", "opinion", "metaculus", "smarkets", "polymarket_us",
"gemini-titan", "hyperliquid", "mock", "router",
"gemini-titan", "hyperliquid", "suibets", "mock", "router",
]);

@@ -282,4 +283,14 @@ exports.ALLOWED_VENUE_METHODS = new Set([

const pmxtApiKey = firstString(flags["pmxt-api-key"], env.PMXT_API_KEY, store.pmxtApiKey, store.pmxt?.apiKey);
const baseUrl = trimTrailingSlash(firstString(flags["base-url"], env.PMXT_BASE_URL, store.baseUrl, store.pmxt?.baseUrl) ?? constants_js_1.HOSTED_URL);
return { baseUrl, exchange, pmxtApiKey, credentials: resolveCredentials(flags, env, store, exchange, options) };
const explicitBaseUrl = firstString(flags["base-url"], env.PMXT_BASE_URL, store.baseUrl, store.pmxt?.baseUrl);
const local = Boolean(flags.local);
const hosted = Boolean(flags.hosted);
if (local && hosted) {
throw new Error("Choose either --local or --hosted, not both.");
}
if (explicitBaseUrl && (local || hosted)) {
throw new Error("Use either --base-url or --local/--hosted, not both.");
}
const mode = explicitBaseUrl ? "custom" : local ? "local" : hosted || pmxtApiKey ? "hosted" : "local";
const baseUrl = trimTrailingSlash(explicitBaseUrl ?? (mode === "local" ? constants_js_1.LOCAL_URL : constants_js_1.HOSTED_URL));
return { baseUrl, exchange, mode, pmxtApiKey, credentials: resolveCredentials(flags, env, store, exchange, options) };
}

@@ -293,3 +304,10 @@ function assertAllowedMethod(method, allowed, label) {

function authHeaders(config) {
return config.pmxtApiKey ? { Authorization: `Bearer ${config.pmxtApiKey}` } : {};
const headers = {};
if (shouldSendHostedAuth(config)) {
headers.Authorization = `Bearer ${config.pmxtApiKey}`;
}
if (config.localAccessToken) {
headers["x-pmxt-access-token"] = config.localAccessToken;
}
return headers;
}

@@ -303,15 +321,117 @@ function responseErrorMessage(parsed, fallback) {

const message = responseErrorMessage(parsed, response.statusText);
if (config.mode === "local") {
return [
`Local PMXT rejected the request: ${message ?? "missing or invalid local access token"}.`,
"",
`Endpoint: ${config.baseUrl}`,
"",
"Try restarting the local PMXT instance:",
" pmxt server restart",
"",
"Or use hosted PMXT:",
" pmxt auth login --api-key <pmxt_api_key>",
" pmxt <exchange> <command> --hosted",
].join("\n");
}
const heading = config.mode === "hosted"
? "Hosted PMXT needs an API key"
: "PMXT endpoint needs authentication";
return [
`Unauthorized: ${message ?? "the PMXT API key was missing or rejected"}.`,
`${heading}: ${message ?? "the key was missing or rejected"}.`,
"",
`Endpoint: ${config.baseUrl}`,
"",
"Fix one of these ways:",
"Hosted:",
" pmxt auth login --api-key <pmxt_api_key>",
" PMXT_API_KEY=<pmxt_api_key> pmxt <exchange> <command>",
" pmxt <exchange> <command> --pmxt-api-key <pmxt_api_key>",
" pmxt <exchange> <command> --hosted --pmxt-api-key <pmxt_api_key>",
"",
"Check current auth with: pmxt auth status",
"Local:",
" pmxt <exchange> <command> --local",
" npm install -g pmxt-core",
"",
"Check auth with: pmxt auth status",
].join("\n");
}
function hostedMissingAuthMessage(config) {
return authErrorMessage({ statusText: "missing api key" }, { error: { message: "missing api key" } }, config);
}
function localUnavailableMessage(error) {
const detail = error instanceof Error ? error.message : String(error);
return [
"Local PMXT instance is not available.",
"",
detail,
"",
"Use hosted PMXT instead:",
" pmxt auth login --api-key <pmxt_api_key>",
" pmxt <exchange> <command> --hosted",
"",
"Hosted PMXT is faster for indexed search, router matches, and enterprise data.",
].join("\n");
}
function isLoopbackUrl(baseUrl) {
try {
const parsed = new URL(baseUrl);
return parsed.protocol === "http:"
&& (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "::1");
}
catch {
return false;
}
}
function shouldSendHostedAuth(config) {
if (!config.pmxtApiKey || config.mode === "local")
return false;
return config.mode === "hosted" || !isLoopbackUrl(config.baseUrl);
}
async function prepareRuntimeConfig(config, flags = {}, env = process.env) {
if (config.mode === "hosted" && config.baseUrl === constants_js_1.HOSTED_URL && !config.pmxtApiKey) {
throw new Error(hostedMissingAuthMessage(config));
}
if (config.mode === "local") {
const manager = new server_manager_js_1.ServerManager();
try {
await manager.ensureServerRunning();
}
catch (error) {
throw new Error(localUnavailableMessage(error));
}
maybeSuggestHosted(flags, env);
return {
...config,
baseUrl: `http://localhost:${manager.getRunningPort()}`,
localAccessToken: manager.getAccessToken(),
};
}
return config;
}
function shouldSuggestHosted(flags = {}, env = process.env) {
if (flags.json || flags["no-suggest-hosted"])
return false;
if (env.CI || env.PMXT_NO_SUGGEST_HOSTED || env.PMXT_CLI_NO_SUGGEST_HOSTED)
return false;
return Boolean(process.stderr.isTTY);
}
function maybeSuggestHosted(flags = {}, env = process.env) {
if (!shouldSuggestHosted(flags, env))
return;
const hintPath = path.join(env.HOME || os.homedir(), ".pmxt", "cli-hints.json");
try {
const parsed = fs.existsSync(hintPath) ? JSON.parse(fs.readFileSync(hintPath, "utf8")) : {};
if (parsed.suggestedHosted)
return;
fs.mkdirSync(path.dirname(hintPath), { recursive: true, mode: 0o700 });
fs.writeFileSync(hintPath, `${JSON.stringify({ ...parsed, suggestedHosted: new Date().toISOString() }, null, 2)}\n`, { mode: 0o600 });
}
catch {
// Hint persistence is best-effort.
}
process.stderr.write([
"Using local PMXT instance.",
"Hosted PMXT is faster for indexed search, router matches, and enterprise data:",
" pmxt auth login --api-key <pmxt_api_key>",
"",
].join("\n"));
}
function throwForResponse(response, parsed, config) {

@@ -390,5 +510,5 @@ if (response.status === 401 || response.status === 403) {

assertAllowedMethod(method, exports.ALLOWED_VENUE_METHODS, "venue");
const config = resolveRuntimeConfig(flags, process.env, undefined, {
const config = await prepareRuntimeConfig(resolveRuntimeConfig(flags, process.env, undefined, {
ignoreAmbientCredentials: PUBLIC_READ_METHODS.has(method) && !hasExplicitCredentialInput(flags),
});
}), flags);
return postJson(`${config.baseUrl}/api/${config.exchange}/${method}`, { args, credentials: config.credentials }, config);

@@ -398,3 +518,3 @@ }

assertAllowedMethod(method, exports.ALLOWED_ROUTER_METHODS, "router");
const config = resolveRuntimeConfig(flags, process.env, "router");
const config = await prepareRuntimeConfig(resolveRuntimeConfig(flags, process.env, "router"), flags);
return postJson(`${config.baseUrl}/api/router/${method}`, { args, credentials: config.credentials }, config);

@@ -405,7 +525,7 @@ }

throw new Error(`Enterprise path must start with /v0/: ${path}`);
const config = resolveRuntimeConfig(flags);
const config = await prepareRuntimeConfig(resolveRuntimeConfig(flags), flags);
return getJson(`${config.baseUrl}${path}`, params, config);
}
async function runEnterpriseSql(query, flags = {}) {
const config = resolveRuntimeConfig(flags);
const config = await prepareRuntimeConfig(resolveRuntimeConfig(flags), flags);
return postJson(`${config.baseUrl}/v0/sql`, { query }, config);

@@ -412,0 +532,0 @@ }

@@ -6,5 +6,5 @@ "use strict";

const { existsSync, readFileSync, unlinkSync } = require("node:fs");
const { accessSync, constants: fsConstants, existsSync, readFileSync, unlinkSync } = require("node:fs");
const { homedir } = require("node:os");
const { dirname, join } = require("node:path");
const { delimiter, dirname, join } = require("node:path");
const { spawn } = require("node:child_process");

@@ -96,2 +96,5 @@

const launcherPath = this.resolveLauncherPath();
if (!launcherPath) {
throw new Error(localInstallMessage());
}
const spawnCmd = launcherPath.endsWith(".js") ? process.execPath : launcherPath;

@@ -101,4 +104,10 @@ const spawnArgs = launcherPath.endsWith(".js") ? [launcherPath] : [];

try {
const proc = spawn(spawnCmd, spawnArgs, { detached: true, stdio: "ignore" });
proc.unref();
await new Promise((resolve, reject) => {
const proc = spawn(spawnCmd, spawnArgs, { detached: true, stdio: "ignore" });
proc.once("error", reject);
proc.once("spawn", () => {
proc.unref();
resolve();
});
});
await this.waitForServer();

@@ -108,5 +117,5 @@ } catch (error) {

throw new Error([
`Failed to start PMXT local server: ${detail}`,
`Failed to start local PMXT instance: ${detail}`,
"",
"Local server commands require pmxt-core to be installed.",
"Local PMXT commands require pmxt-core to be installed.",
"Install it with: npm install -g pmxt-core",

@@ -127,3 +136,3 @@ "Or use the hosted API with: pmxt auth login --api-key <pmxt_api_key>",

}
return launcherName;
return findExecutableOnPath(launcherName);
}

@@ -221,2 +230,38 @@

function findExecutableOnPath(command) {
const pathValue = process.env.PATH || "";
const extensions = process.platform === "win32"
? (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";")
: [""];
const candidates = process.platform === "win32" && !/\.[^\\/]+$/.test(command)
? extensions.map((ext) => `${command}${ext}`)
: [command];
for (const dir of pathValue.split(delimiter)) {
if (!dir) continue;
for (const name of candidates) {
const candidate = join(dir, name);
try {
accessSync(candidate, fsConstants.X_OK);
return candidate;
} catch {
// Keep searching.
}
}
}
return undefined;
}
function localInstallMessage() {
return [
"Local PMXT is not installed.",
"",
"Install the local runtime:",
" npm install -g pmxt-core",
"",
"Or use hosted PMXT:",
" pmxt auth login --api-key <pmxt_api_key>",
" pmxt <exchange> <command> --hosted",
].join("\n");
}
exports.ServerManager = ServerManager;

@@ -37,19 +37,19 @@ "use strict";

case "start":
return "PMXT server started";
return "Local PMXT instance started";
case "stop":
return "PMXT server stopped";
return "Local PMXT instance stopped";
case "restart":
return "PMXT server restarted";
return "Local PMXT instance restarted";
case "status":
return formatStatus(result);
case "health":
return result.healthy ? "PMXT server healthy" : "PMXT server unhealthy";
return result.healthy ? "Local PMXT instance healthy" : "Local PMXT instance unhealthy";
case "logs":
return result.lines.length > 0
? result.lines.join("\n")
: "No PMXT server logs found";
: "No local PMXT logs found";
}
}
function formatStatus(status) {
const lines = [`PMXT server ${status.running ? "running" : "stopped"}`];
const lines = [`Local PMXT instance ${status.running ? "running" : "stopped"}`];
if (status.pid !== null)

@@ -56,0 +56,0 @@ lines.push(`pid: ${status.pid}`);

@@ -42,5 +42,11 @@ "use strict";

"base-url": core_1.Flags.string({
description: "PMXT API base URL",
description: "Advanced: override the PMXT API base URL",
env: constants_js_1.ENV.BASE_URL,
}),
local: core_1.Flags.boolean({
description: "Use a local PMXT instance",
}),
hosted: core_1.Flags.boolean({
description: "Use the hosted PMXT API",
}),
"pmxt-api-key": core_1.Flags.string({

@@ -50,2 +56,5 @@ description: "Hosted PMXT API key",

}),
"no-suggest-hosted": core_1.Flags.boolean({
description: "Do not show hosted PMXT suggestions when using local mode",
}),
};

@@ -142,2 +151,4 @@ exports.feedHttpFlags = {

baseUrl: runtime.baseUrl,
mode: runtime.mode,
noSuggestHosted: Boolean(flags["no-suggest-hosted"]),
...(runtime.pmxtApiKey ? { pmxtApiKey: runtime.pmxtApiKey } : {}),

@@ -148,6 +159,25 @@ ...(options.targetKind === "exchange" && runtime.credentials ? { exchangeCredentials: runtime.credentials } : {}),

async function fetchPmxtData(pathname, credentials, query = {}) {
const resolved = (0, constants_js_1.resolvePmxtBaseUrl)({
let resolved = (0, constants_js_1.resolvePmxtBaseUrl)({
baseUrl: credentials.baseUrl,
pmxtApiKey: credentials.pmxtApiKey,
});
let localAccessToken;
if (credentials.mode === "hosted" && resolved.isHosted && !resolved.pmxtApiKey) {
throw new Error(authErrorMessage("missing api key", resolved.baseUrl, credentials.mode));
}
if (resolved.baseUrl === constants_js_1.LOCAL_URL || credentials.mode === "local") {
const manager = new server_manager_js_1.ServerManager();
try {
await manager.ensureServerRunning();
}
catch (error) {
throw new Error(localUnavailableMessage(error));
}
resolved = {
...resolved,
baseUrl: `http://localhost:${manager.getRunningPort()}`,
isHosted: false,
};
localAccessToken = manager.getAccessToken();
}
const url = new URL(pathname, ensureTrailingSlash(resolved.baseUrl));

@@ -160,3 +190,6 @@ for (const [key, value] of Object.entries(query)) {

const response = await fetch(url, {
headers: resolved.pmxtApiKey ? { Authorization: `Bearer ${resolved.pmxtApiKey}` } : {},
headers: {
...(shouldSendHostedAuth(resolved, credentials.mode) ? { Authorization: `Bearer ${resolved.pmxtApiKey}` } : {}),
...(localAccessToken ? { "x-pmxt-access-token": localAccessToken } : {}),
},
signal: AbortSignal.timeout(30_000),

@@ -167,3 +200,3 @@ });

if (response.status === 401 || response.status === 403) {
throw new Error(authErrorMessage(errorMessage(body) || response.statusText, resolved.baseUrl));
throw new Error(authErrorMessage(errorMessage(body) || response.statusText, resolved.baseUrl, credentials.mode));
}

@@ -281,3 +314,3 @@ throw new Error(errorMessage(body) || response.statusText);

if (!resolved.pmxtApiKey) {
throw new Error(authErrorMessage("missing api key", resolved.baseUrl));
throw new Error(authErrorMessage("missing api key", resolved.baseUrl, credentials.mode));
}

@@ -288,5 +321,10 @@ return {

}
if (resolved.baseUrl === constants_js_1.LOCAL_URL) {
if (resolved.baseUrl === constants_js_1.LOCAL_URL || credentials.mode === "local") {
const manager = new server_manager_js_1.ServerManager();
await manager.ensureServerRunning();
try {
await manager.ensureServerRunning();
}
catch (error) {
throw new Error(localUnavailableMessage(error));
}
const token = manager.getAccessToken();

@@ -298,3 +336,7 @@ const baseUrl = `http://localhost:${manager.getRunningPort()}`;

}
return { url: buildWebSocketUrl(resolved.baseUrl) };
return {
url: buildWebSocketUrl(resolved.baseUrl, shouldSendHostedAuth(resolved, credentials.mode)
? { name: "apiKey", value: resolved.pmxtApiKey }
: undefined),
};
}

@@ -310,2 +352,17 @@ function clean(value) {

}
function isLoopbackUrl(baseUrl) {
try {
const parsed = new URL(baseUrl);
return parsed.protocol === "http:"
&& (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "::1");
}
catch {
return false;
}
}
function shouldSendHostedAuth(resolved, mode) {
if (!resolved.pmxtApiKey || mode === "local")
return false;
return resolved.isHosted || !isLoopbackUrl(resolved.baseUrl);
}
function envPrefix(value) {

@@ -324,16 +381,49 @@ return (value || "EXCHANGE").replace(/[^a-zA-Z0-9]/g, "_").toUpperCase();

}
function authErrorMessage(message, baseUrl) {
function authErrorMessage(message, baseUrl, mode = "hosted") {
if (mode === "local") {
return [
`Local PMXT rejected the request: ${message || "missing or invalid local access token"}.`,
"",
`Endpoint: ${baseUrl}`,
"",
"Try restarting the local PMXT instance:",
" pmxt server restart",
"",
"Or use hosted PMXT:",
" pmxt auth login --api-key <pmxt_api_key>",
" pmxt <exchange> <command> --hosted",
].join("\n");
}
const heading = mode === "hosted" ? "Hosted PMXT needs an API key" : "PMXT endpoint needs authentication";
return [
`Unauthorized: ${message || "the PMXT API key was missing or rejected"}.`,
`${heading}: ${message || "the key was missing or rejected"}.`,
"",
`Endpoint: ${baseUrl}`,
"",
"Fix one of these ways:",
"Hosted:",
" pmxt auth login --api-key <pmxt_api_key>",
" PMXT_API_KEY=<pmxt_api_key> pmxt <exchange> <command>",
" pmxt <exchange> <command> --pmxt-api-key <pmxt_api_key>",
" pmxt <exchange> <command> --hosted --pmxt-api-key <pmxt_api_key>",
"",
"Check current auth with: pmxt auth status",
"Local:",
" pmxt <exchange> <command> --local",
" npm install -g pmxt-core",
"",
"Check auth with: pmxt auth status",
].join("\n");
}
function localUnavailableMessage(error) {
const detail = error instanceof Error ? error.message : String(error);
return [
"Local PMXT instance is not available.",
"",
detail,
"",
"Use hosted PMXT instead:",
" pmxt auth login --api-key <pmxt_api_key>",
" pmxt <exchange> <command> --hosted",
"",
"Hosted PMXT is faster for indexed search, router matches, and enterprise data.",
].join("\n");
}
function getStoreBuckets(store, profile, options) {

@@ -340,0 +430,0 @@ const buckets = [];

@@ -8,4 +8,4 @@ "use strict";

static enableJsonFlag = true;
static summary = "Check PMXT sidecar server health";
static description = "Check whether the PMXT sidecar server is healthy without starting it.";
static summary = "Check local PMXT instance health";
static description = "Check whether the local PMXT instance is healthy without starting it.";
async run() {

@@ -12,0 +12,0 @@ await this.parse(ServerHealth);

@@ -8,4 +8,4 @@ "use strict";

static enableJsonFlag = true;
static summary = "Show PMXT sidecar server logs";
static description = "Show recent PMXT sidecar server log lines.";
static summary = "Show local PMXT instance logs";
static description = "Show recent local PMXT instance log lines.";
static flags = {

@@ -12,0 +12,0 @@ lines: core_1.Flags.integer({

@@ -8,4 +8,4 @@ "use strict";

static enableJsonFlag = true;
static summary = "Restart the PMXT sidecar server";
static description = "Stop the current PMXT sidecar server, then start it again.";
static summary = "Restart the local PMXT instance";
static description = "Stop the current local PMXT instance, then start it again.";
async run() {

@@ -12,0 +12,0 @@ await this.parse(ServerRestart);

@@ -8,4 +8,4 @@ "use strict";

static enableJsonFlag = true;
static summary = "Start the PMXT sidecar server";
static description = "Start the PMXT sidecar server if it is not already running.";
static summary = "Start the local PMXT instance";
static description = "Start the local PMXT instance if it is not already running.";
async run() {

@@ -12,0 +12,0 @@ await this.parse(ServerStart);

@@ -8,4 +8,4 @@ "use strict";

static enableJsonFlag = true;
static summary = "Show PMXT sidecar server status";
static description = "Show the current PMXT sidecar server status without starting it.";
static summary = "Show local PMXT instance status";
static description = "Show the current local PMXT instance status without starting it.";
async run() {

@@ -12,0 +12,0 @@ await this.parse(ServerStatus);

@@ -8,4 +8,4 @@ "use strict";

static enableJsonFlag = true;
static summary = "Stop the PMXT sidecar server";
static description = "Stop the PMXT sidecar server and clean up the server lock file.";
static summary = "Stop the local PMXT instance";
static description = "Stop the local PMXT instance and clean up the server lock file.";
async run() {

@@ -12,0 +12,0 @@ await this.parse(ServerStop);

{
"name": "@pmxt/cli",
"version": "2.46.0",
"version": "2.46.1",
"description": "Command-line interface for PMXT prediction market APIs",

@@ -41,3 +41,3 @@ "author": "PMXT Contributors",

"server": {
"description": "Manage an installed local pmxt-core sidecar."
"description": "Manage a local PMXT instance."
},

@@ -58,3 +58,3 @@ "watch": {

"prepack": "npm run build",
"test": "node scripts/validate.js && node scripts/verify-argv-alias-normalizer.js && node scripts/verify-root-help.js && node scripts/verify-runtime-errors.js"
"test": "node scripts/validate.js && node scripts/verify-argv-alias-normalizer.js && node scripts/verify-root-help.js && node scripts/verify-runtime-errors.js && node scripts/verify-feed-cli.js && node scripts/verify-enterprise-cli.js && node scripts/verify-production-copy.js"
},

@@ -61,0 +61,0 @@ "keywords": [

@@ -19,3 +19,3 @@ # @pmxt/cli

Hosted PMXT API calls require a PMXT API key:
PMXT uses hosted mode when an API key is configured. Without hosted auth, commands use a local PMXT instance.

@@ -54,10 +54,13 @@ ```bash

PMXT_API_KEY=pmxt_... pmxt markets --limit 5
pmxt markets --pmxt-api-key pmxt_... --limit 5
pmxt markets --hosted --pmxt-api-key pmxt_... --limit 5
```
Local sidecar usage is explicit:
Local usage is explicit when you want to force it:
```bash
npm install -g pmxt-core
pmxt server status
pmxt markets --base-url http://localhost:3847 --limit 5
pmxt markets --local --limit 5
```
Use `--base-url` only for custom PMXT deployments.