Metadata-Version: 2.4
Name: meridian-governance-cli
Version: 0.2.0
Summary: Command-line client for Meridian Governance Router — not the unrelated 'meridian-cli' package also on PyPI
License-Expression: MIT
Project-URL: Homepage, https://github.com/knjpollard/meridian
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: meridian-client
Requires-Dist: requests>=2.28.0
Dynamic: license-file

# meridian-governance-cli

Scriptable command-line client for [Meridian Governance Router](https://dev-meridian.mytrustworthy.ai/), over [`meridian-client`](https://pypi.org/project/meridian-client/). Installs as the `meridian` command.

Not to be confused with the unrelated `meridian-cli` package also on PyPI.

Closer in spirit to the `aws` or `stripe` CLIs than to an app's own CLI:
subcommands over an API, scriptable, mostly no interactive loop required —
with one exception. `chat` absorbed
[Local-AI](https://github.com/knjpollard/Local-AI)'s reference
implementation upstream (`meridian-agent-v1.0.py`, decided 2026-10-18) so
customers get one governed resolve -> dispatch -> audit loop from Meridian
itself, interactively or scripted, rather than writing that sequence
themselves against the SDK.

## Install

```bash
pip install meridian-governance-cli
```

## Get credentials

```bash
meridian signup          # new org — prompts for org name, email, password
# or
meridian login           # existing account — authenticates, mints a new key
meridian whoami           # confirm what's saved
```

Credentials live in `~/.meridian/config.json` (mode 600 — `api_key` is in
there in plaintext, same tradeoff `mta-cli` makes for its own token). Override
the location with `MERIDIAN_CLI_HOME` if you want more than one profile.

## Commands

```bash
meridian resolve my_agent [--project-id ID] [--json]
meridian explain ROUTING_LOG_ID
meridian audit ROUTING_LOG_ID --input-tokens N --output-tokens N

meridian projects create --name NAME [--quality Q] [--cost C] [--risk R]
meridian projects list

meridian agents create PROJECT_ID AGENT_NAME [--pinned-model M] [--quality-override Q] [--allowed-hubs h1,h2]
meridian agents list PROJECT_ID

meridian keys list [--json]
meridian keys create [--name NAME]
meridian keys revoke KEY_ID

meridian catalog
meridian logout

meridian chat [--agent NAME] [--project-id ID] [--max-tokens N]
meridian chat --one-shot "message" [--json] [--max-tokens N]
meridian chat --daemon [--host HOST] [--port PORT] [--refresh-interval SECS]
```

Every data-returning command without a dedicated human-readable format
(`explain`, `audit`, `catalog`, `projects list`, `agents list`) prints raw
JSON — pipe into `jq`.

### `chat`

Per-turn flow: `resolve(agent)` -> catalog/hubs join -> dispatch to the
chosen hub's OpenAI-compatible endpoint -> `audit`. Routing, scoring and
governance all live in Meridian; `chat` just drives the loop. OpenAI-compat
hubs only for now (vLLM, Ollama, OpenAI-shaped endpoints) — bedrock/
anthropic/etc. need a protocol translator, not yet added.

- No args: interactive REPL. `/help` inside it for slash commands
  (`/catalog`, `/hubs`, `/refresh`, `/history`, `/export`, `/window`, …).
- `--one-shot "message"`: single turn, prints the response, exits.
  `--json` emits structured output (`response`, `model`, `hub`,
  `routing_log_id`, `latency_ms`, `usage`) instead of plain text.
- `--daemon`: long-lived local OpenAI-compatible endpoint (`POST
  /v1/chat/completions`, `GET /v1/models`, `GET /health`) — point an
  existing OpenAI-SDK-based app at `http://127.0.0.1:8700` and it works
  unchanged, with Meridian's governance and audit trail in the middle. The
  F9 "broker" shape from Local-AI's feedback. Stateless across requests,
  same as the real OpenAI API: your app holds history and sends the full
  `messages` array each call.
- `--max-tokens`: reasoning models can need a *much* larger budget than the
  default (8192) just to reach visible content — confirmed live against a
  real deployment where the same five-word prompt burned anywhere from
  ~2400 to the full 8192-token budget purely on reasoning, before any
  answer. If a response comes back as a token-budget notice instead of
  text, raise this.

## What this deliberately doesn't do

- No hub/model/deployment registration commands yet. The routes themselves
  are tenant-scoped (fixed 2026-10-18 — `POST /api/v1/hubs` and
  `/api/v1/backends` both correctly bind the caller's org now), so this is
  purely "not built yet," not "would 403." Tracked separately.
