Command line¶
meridian is Open Meridian's command line. It brings a deployment up where you have a terminal, signs you in to one that is already running, and brings plugins into it: uploading, launching, stopping, and developing them live.
Nothing in a cloud install depends on it. A marketplace listing's form and the deployment's own wizard are the whole path there; meridian makes the same things convenient from a terminal.
This page describes release 0.1.14 of the command line. meridian --version says which one you have. For installing it, see Install a deployment.
Synopsis¶
meridian doctor
meridian up --id <id> [options]
meridian down [--release <name>] [--delete-namespace]
meridian upgrade-deployment [--release <name>] [--chart-version <v>] [options]
meridian connect [<address>]
meridian sign-out [<address>]
meridian plugin new <name> [--into <dir>]
meridian plugin check [--dir <dir>] [--run-tests] [--json]
meridian plugin upload [--dir <dir>]
meridian plugin list
meridian plugin launch <name> <version> --instance <id> [--yes]
meridian plugin stop <id>
meridian plugin dev --instance <id> [--dir <dir>] [--yes] [--json] [--release]
meridian plugin logs --instance <id> [--since <revision>] [--json]
meridian plugin events --instance <id> [--since <revision>] [--follow] [--json]
meridian plugin open --instance <id> [--print <path>] [--json]
meridian upgrade [--to <version>]
meridian uninstall [--yes]
meridian --version
meridian --help
How arguments are read¶
- A flag that takes a value may be written either way:
--params first-run.yamlor--params=first-run.yaml. - An unknown flag is refused, not ignored, and so is a stray word after a command that takes none.
meridian up --no-docterexits 2 rather than installing without the checks. - A flag given with nothing after it is refused rather than defaulted.
- When a flag is given twice, the last one counts. The exception is
-f/--values: every one is kept, in the order given. --releasemeans two different things. Afterup,downorupgrade-deploymentit takes a value, the Helm release's name. Afterpluginit takes none, andplugin dev --releasereleases the code as a version.
Global options¶
These are read before any command runs.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
-n, --namespace |
<name> |
meridian |
The Kubernetes namespace the deployment goes in. Used by doctor, up, down and upgrade-deployment. |
--platform |
<url> |
https://open-meridian.com |
The platform the deployment reports to. Used by doctor and up. up passes it to the chart only when you give it. |
--image |
<ref> |
ghcr.io/open-meridian/meridian-runtime:latest |
The runtime image. Used by doctor and up. up passes it to the chart only when you give it. |
-h, --help |
Print the usage text and exit 0. | ||
-v |
Reserved for verbose output, which is not built yet. It prints a note saying so and is otherwise ignored. |
Exit codes¶
Every command exits 0 when it succeeds. What a non-zero code means depends on the command:
| Code | Meaning |
|---|---|
0 |
Done. |
1 |
Refused or failed. The reason is on stderr. |
2 |
Asked wrongly: an unknown command or flag, a missing argument, or an argument of the wrong form. Nothing was done. |
3 |
plugin commands that act on a deployment (upload, list, launch, stop, dev, logs, events, open): there is no session, or it has lapsed. The message names the meridian connect to run. |
A plugin command exits 3 in two cases:
- when no session is held for the deployment, or you hold several and
--deploymentdoes not pick one; - when the deployment answers
401 Unauthorized: the session lapsed, was ended, or is one the deployment does not know, as after its dashboard restarted. That includes the deployment's registry, whichplugin uploadpushes through. The message says which, and ends with themeridian connectto run, for examplehttp://meridian.localhost does not know your session; it may have restarted: `meridian connect` to sign in again. Before CLI 0.1.15,plugin uploadreported a lapsed session met at the registry asthe registry did not start an upload: 401 Unauthorized: invalid_tokenand exited 1.
A script or an AI agent should treat 3 as "ask the person to connect again". Retrying won't help.
--json
The CLI README says every command takes --json. The parser does accept --json on every command, but only plugin check, plugin dev, plugin logs, plugin events and plugin open change their output for it. Every other command prints text whether or not you pass it.
meridian doctor¶
Checks whether this machine and this cluster can run a deployment. It changes nothing.
The checks run in this order:
- Helm is present and recent enough.
- The cluster is reachable, and you have the rights to install into the namespace.
- There is a storage class for the deployment's key.
- The runtime image can be pulled from here.
- The platform is reachable, and this machine's clock is within the tolerance a signed assertion allows.
Each result is one of:
| Result | Meaning |
|---|---|
ok |
Nothing to do. |
stops |
Would stop an install. Printed with its fix. |
worth |
Worth knowing, and not in the way. |
unknown |
Could not be checked from here. This does not mean it passed. |
A right the cluster refuses is stops, naming the right to ask for. kubectl auth can-i answers "no" by exiting 1, and from CLI 0.1.15 that is read as the refusal it is rather than as unknown; unknown is left for a question kubectl could not answer.
Exit codes: 0 when nothing would stop an install, 1 when at least one check says stops.
meridian up¶
Installs the deployment's Helm chart into the cluster, waits for the dashboard, and prints the wizard's address. It runs doctor first unless you pass --no-doctor. It drives your own helm and kubectl and prints the commands it used.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
--id |
<id> |
none (required) | This deployment's identifier, exactly as the platform shows it: DEP- then 26 characters from 0-9 and A-Z without I, L, O or U. Any other shape is refused before anything is installed. |
--enrolment-code |
<c> |
the value of MERIDIAN_ENROLMENT_CODE |
The one-time code the deployment enrols its key with. Required, from one or the other. Prefer the variable: a flag is written to shell history. |
--release |
<name> |
meridian |
The Helm release name. |
--chart |
<ref> |
oci://ghcr.io/open-meridian/charts/meridian-runtime |
The chart to install. |
--chart-version |
<v> |
not passed to Helm | Which version of the chart. |
-p, --params |
<file> |
none | Answer the wizard from a file instead of a browser (see below). |
--first-run-code |
<c> |
the value of MERIDIAN_FIRST_RUN_CODE |
The claim code that --params redeems. |
-f, --values |
<file> |
none | Helm-style chart values, passed straight through. May be repeated. |
--host |
<name> |
meridian.localhost |
The name the deployment is reached by through the cluster's ingress controller. A name under .localhost is plain HTTP on this machine. Any other name is reached over HTTPS, with its certificate Secrets named in a values file (-f). |
--no-ingress |
off | Reach the deployment through a port-forward that this command holds, as on a cluster with no ingress controller. | |
--development |
off | Install for development. The deployment may run plugin code while it is being written, and every page says so. plugin dev needs this. See Development deployments. |
|
--port |
<n> |
8443 |
The local port a port-forward uses. |
--timeout |
<d> |
10m |
How long Helm is given. |
--no-doctor |
off | Skip the doctor checks. |
Plus the global options -n, --platform and --image.
Answering the wizard from a file¶
--params posts your answers to the wizard's own endpoints, behind the same first-run code a browser redeems. The file holds the wizard's answers and no credential. Every field the wizard asks for as a password is read from an environment variable, MERIDIAN_<FIELD>, instead. A file that names such a field is refused, and the refusal names the variable to use. Field names are the wizard's own, and a misspelled one is refused against the real form.
db_host: postgres.internal
db_port: 5432
db_name: meridian
db_serving_role: meridian_app
db_migrating_role: meridian_migrate
backend: ldap
ldap_servers: ldaps://ldap.firm.internal:636
ldap_base_dn: ou=people,dc=firm,dc=internal
ldap_bind_dn: cn=meridian,ou=services,dc=firm,dc=internal
admin_group: meridian-admins
dashboard_url: https://meridian.firm.example
export MERIDIAN_ENROLMENT_CODE=…
export MERIDIAN_FIRST_RUN_CODE=…
export MERIDIAN_DB_SERVING_PASSWORD=…
export MERIDIAN_DB_MIGRATING_PASSWORD=…
export MERIDIAN_LDAP_BIND_PASSWORD=…
meridian up --id DEP-01M3GZ8K4Q7T2V9W6X5Y3R1N0P --params first-run.yaml
Exit codes:
| Code | When |
|---|---|
0 |
Installed. |
1 |
A doctor check said stops (nothing is installed), or the install failed. |
2 |
--id is missing or malformed, there is no enrolment code, or --port is not a port number. Nothing is installed. |
meridian down¶
Uninstalls the release. It asks no question, because running down is the decision.
By default the namespace is kept, and with it the database the deployment brought and the deployment's own key. Running meridian up again picks both back up.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
--release |
<name> |
meridian |
The Helm release to uninstall. |
--delete-namespace |
off | Remove the namespace too. That removes the database the deployment brought, with all its data, which nothing backs up. It also removes the deployment's key, after which the platform won't give the deployment a new enrolment code until the key is revoked there. The cluster itself is never touched. | |
-n, --namespace |
<name> |
meridian |
The namespace. |
Either way, the deployment still exists on the platform. Retiring it there is what revokes its key. Not to be confused with meridian uninstall, which removes the command line itself.
Exit codes: 0 done, 1 failed, 2 given a word it does not take.
meridian upgrade-deployment¶
meridian upgrade-deployment [--release <name>] [-n <name>] [--chart <ref>] [--chart-version <v>] [--timeout <d>] [--yes]
Moves a running deployment to a newer version of its chart, in place, with your own cluster rights. Not to be confused with meridian upgrade, which replaces the command line itself. For the whole task, and for upgrading from your own pipeline instead, see Upgrade a deployment.
It works in four steps, and stops at the step that fails.
-
Check. It changes nothing if any of these fails, and says which and what to do:
helmis 3.14 or newer, for--reset-then-reuse-values;- the cluster is reachable, and you may patch Deployments and create and delete Jobs in the namespace;
- the release exists and Helm holds it as
deployed. Afailedorpending-…release is refused with how to recover it; - the chart version is published, and it is the chart the release was installed from;
- it is not older than the installed version. If it is the same, it says so and exits 0.
Two more are printed as
unknownevery time, because they are not built: whether the upgrade is within the skip policy, which is not ruled yet, and whether every installed plugin's runtime floor is met, which nothing declares yet.unknowndoes not stop it, and does not mean it passed.If the deployment's own values set
image.tag, it says so asworth: the upgrade keeps that tag rather than moving to the chart's. -
Show and ask. It prints the release, the namespace, the version and image it is on, the version and image it moves to, and the
helm upgradeit will run, then asksUpgrade it?. Anything butyoryesis no. With no terminal to ask at, it is refused unless you pass--yes. -
Apply and wait. It runs
helm upgrade <release> <chart> --version <v> --namespace <ns> --reset-then-reuse-values --timeout <d>, never--wait. Then it waits, up to--timeout, for the new revision's migration Job to complete, every Deployment and StatefulSet of the release to roll out, and every one of their pods to run the image its template names. It prints each thing it is waiting for once, when it first sees it. -
Clean up and report. It deletes the finished Jobs of this release from earlier revisions, found by the release's label, and nothing else. Old ReplicaSets are left to the chart's
revisionHistoryLimit. It then prints the versions it moved between, each component's images and readiness, every container that restarted during the upgrade with the reason Kubernetes gives, and what it cleaned up.
It never prints the deployment's values, which hold its enrolment code. The one thing it reads from them is image.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
--release |
<name> |
meridian |
The Helm release to upgrade. |
--chart |
<ref> |
oci://ghcr.io/open-meridian/charts/meridian-runtime |
The chart the release was installed from. |
--chart-version |
<v> |
the latest published | The version to move to. It is resolved once, and that version is what is checked and applied. |
--timeout |
<d> |
10m |
How long to wait for the migration and every component, and what Helm is given. Written as Helm writes a duration: 10m, 90s, 1h30m. |
--yes |
off | Upgrade without being asked. For a script that has already read the plan. | |
-n, --namespace |
<name> |
meridian |
The namespace. |
Exit codes:
| Code | When |
|---|---|
0 |
Upgraded, or already at that version. |
1 |
A check stopped it (nothing was changed), it was not approved, Helm refused it, the migration failed, or the wait timed out. What is still waited for is listed, and nothing is rolled back. |
2 |
Asked wrongly, for example a --timeout Helm would not read. Nothing was done. |
meridian connect¶
Signs you in to a deployment's dashboard in your browser, however that deployment signs people in, and keeps the session on this machine. It never takes a password.
With no address it signs in to http://meridian.localhost, the deployment meridian up installs on this machine by default. Give an address for any other.
<address> is the dashboard's address alone, with no path:
https://<host>;http://only for this machine:127.0.0.1,[::1],localhost, or a name under.localhostsuch ashttp://meridian.localhost.
Plain HTTP to any other machine is refused, because it would send your session in the clear.
The command prints the sign-in link and opens it in your browser, then waits up to 5 minutes for the sign-in to come back. A session lasts 30 minutes unused, and ends at a fixed time at the latest; the command prints that time. The README gives the maximum as 12 hours.
This machine holds one session per deployment. Connecting again ends the earlier one at the deployment. Sessions are kept in files readable only by you, in $XDG_CONFIG_HOME/meridian/sessions, %APPDATA%\meridian\sessions, or ~/.config/meridian/sessions, whichever is found first.
Exit codes: 0 connected; 1 the sign-in was declined, timed out, or failed, or the session could not be kept; 2 no address, or an address of the wrong form.
meridian sign-out¶
Ends a session at the deployment and forgets it here. With no address, it signs out of the one deployment you are connected to. If you are connected to more than one, it lists the commands to run and exits 2.
If the deployment can't be reached, the session is still forgotten here and lapses there within 30 minutes.
Exit codes: 0 signed out, or not connected to begin with; 1 the session file could not be removed; 2 a malformed address, more than one address, or no address when several sessions are held.
meridian plugin new¶
Writes a working plugin to start from: the Python SDK's reference plugin, renamed to <name>. It needs no network, because the template is compiled into the binary. It writes the plugin's code and page, a Dockerfile, pyproject.toml, .dockerignore, .gitignore, README.md, AGENTS.md, CLAUDE.md, and a develop-live skill for Claude Code, then prints the next steps. See Your first plugin.
<name> must be lowercase letters, digits and single hyphens, starting with a letter. It becomes the package name, and, with hyphens as underscores, the module name.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
--into |
<dir> |
./<name> |
Where to write it. Never somewhere that already exists. |
Exit codes: 0 written, 1 refused (bad name, or the directory exists), 2 asked wrongly.
meridian plugin check¶
From CLI 0.1.15. Holds the plugin in --dir to the framework's rules: the rules every plugin is built to, so that plugins written by different people and different coding agents look and behave alike, and a change to what plugins call can be applied to all of them. It needs no deployment and no session, changes nothing, and reads nothing outside the directory. Run it while you work, and in the plugin's own CI.
Each failure names the rule, the file and line, and what to write instead, so that a coding agent can fix it without asking. The rules are compiled into the binary: the check a plugin meets is the one of the meridian that runs it.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
--dir |
<dir> |
. |
The plugin's directory. |
--run-tests |
off | Also run the plugin's tests with pytest: .venv/bin/python -m pytest when the plugin has a .venv, otherwise python3 -m pytest, which must have the plugin and pytest installed. No cache or bytecode is written. |
|
--json |
off | One JSON object on stdout instead of the report. |
The rules¶
| Rule | Holds | Fails on |
|---|---|---|
template-shape |
The project keeps the template's shape. | No pyproject.toml, or one with no plugin name or version; the SDK not pinned exactly (open-meridian==<version>); no Dockerfile, or one not built on ghcr.io/open-meridian/plugin-python:<the pinned version>; no src/<module>/__main__.py; nothing calling meridian.connect(); no AGENTS.md; a CLAUDE.md that does not begin from @AGENTS.md; a .dockerignore that does not name AGENTS.md and .meridian. |
tool-meridian |
[tool.meridian] names roles from the fixed list, and no tags. |
No [tool.meridian]; a role not in the deployment's list (ccm, compliance, custody, dgm, ems, match, oms, operations, portfolio, reporting, servicing, settlement, signal); tags, empty or not; an interface that is not true or false. |
kit-linked |
Every page links the kit from /.meridian/ui/, and the plugin holds no copy of it. |
A file that writes a document (<!doctype html>, <html> or <head>) with no link to /.meridian/ui/…/meridian.css; a file named meridian.css or meridian.js in the plugin. |
no-raw-colour |
No raw colour in a page or its styles. | A hex colour where a colour goes, rgb(), rgba(), hsl(), hsla(), hwb(), oklch() or oklab(), or a CSS colour name as the value of a colour property (color, background, border, fill, stroke and the like), a colour attribute (fill="…") or a script's .style.…Color. A fallback in var(--x, #fff) is a raw colour too. |
own-origin |
A page loads nothing from another origin. | An absolute or protocol-relative address (https://…, //…, wss://…) as a script's, stylesheet's, image's or frame's source, in @import or url(), or given to fetch, EventSource, WebSocket or import. A link people follow (<a href>) is not loading. |
settings-declared |
Settings are declared to the SDK, not read from the environment. | os.environ, os.getenv, getenv( or environ[…]. One name is allowed: a variable ending _PAGE_PORT, where the page listens on loopback for its sidecar, as the template's does. That is the plugin's own wiring, which nobody configures. |
secrets-kept |
No secret setting's value is logged or put in a page. | For each meridian.Setting(…, secret=True), by its name or the constant that names it: its value (values[NAME], .get(NAME), .name, {name}) in a logging call, print, a raise, or a statement that writes HTML. Its name alone, as in "waiting for broker_api_key", is not its value. |
through-the-sdk |
The deployment is reached only through the SDK. | Importing nats, psycopg, psycopg2, asyncpg, sqlalchemy, pg8000, aiopg, grpc, kubernetes, or the sidecar's raw *_pb2_grpc stubs; naming nats://, postgres://, a cluster service (*.svc, *.svc.cluster.local), meridian.localhost, a dashboard /terminal/ path, or MERIDIAN_SIDECAR_ADDRESS. |
tests-exist |
The plugin has tests. | No test_*.py or *_test.py with a def test_… in it. |
tests-pass |
Its tests pass. | With --run-tests: pytest exits non-zero, collects nothing, or is not installed. Without it the rule is reported as not run, and does not fail. |
The page rules read HTML, CSS, SVG, script and templates, and the Python that renders a page, so they hold for a plugin in any language. The rules about the plugin's code read Python, the one SDK there is. Tests (tests/, test_*.py, conftest.py) are not held to the page and code rules: a test may name a colour to assert it is absent. Comments are not read, so a colour in a comment is on no page.
The rules match what can be decided from the text: the obvious forms, not every form. A secret copied into another variable before it is logged, or a colour built from parts in a script, gets past them. They are the floor, not the review.
What it cannot check¶
These stay advice, in the template's AGENTS.md, because deciding them takes judgement:
- which of the kit's components or classes fits what the page shows;
- the page's layout, and whether it draws only its content, with no header bar, navigation, sign-in or theme switch of its own;
- custom properties the kit does not define, other than the page's own layout ones (the check does not know the kit's list);
- that prices and quantities reach the page as decimal strings and are never parsed as floats;
- names: of the plugin, its settings, its pages and its tests;
- whether the tests test what matters.
Output¶
In text, one line per rule, and under a failed one each place it failed and what to write instead:
meridian plugin check: ., by the rules of meridian 0.1.15
ok template-shape the project keeps the template's shape
ok tool-meridian [tool.meridian] names roles from the fixed list, and no tags
ok kit-linked every page links the kit from /.meridian/ui/, and holds no copy of it
FAIL no-raw-colour no raw colour: no hex, rgb(), hsl() or colour name in a page or its styles
src/my_plugin/page.py:41: `#c0ffee` is a raw colour, which no scheme can change
instead: the kit's custom property for what the colour means, as var(--name): …
ok own-origin a page loads nothing from another origin
ok settings-declared settings are declared to the SDK, not read from the environment
ok secrets-kept no secret setting's value is logged or put in a page
ok through-the-sdk the deployment is reached only through the SDK
ok tests-exist the plugin has tests
-- tests-pass its tests pass: --run-tests runs them
1 of 10 rules failed, 1 place(s) in all. Fix each as it says, then check again.
With --json, one object. line is null when the failure is a whole file, or a file that is missing:
{
"dir": ".",
"meridian": "0.1.15",
"passed": false,
"rules": [{"rule": "no-raw-colour", "holds": "no raw colour: …", "outcome": "failed"}, …],
"failures": [
{"rule": "no-raw-colour", "file": "src/my_plugin/page.py", "line": 41,
"found": "`#c0ffee` is a raw colour, which no scheme can change",
"instead": "the kit's custom property for what the colour means, as var(--name): …"}
]
}
outcome is passed, failed, or skipped for tests-pass without --run-tests.
A freshly scaffolded plugin
From CLI 0.1.16, the plugin meridian plugin new writes keeps every rule, with its own tests and a CI workflow (.github/workflows/check.yaml) that runs meridian plugin check --run-tests. At 0.1.15 it failed tests-exist until you added a test.
Exit codes: 0 every rule holds; 1 at least one does not; 2 asked wrongly, or --dir is not a directory.
Plugin commands on a deployment¶
plugin upload, list, launch, stop, dev, logs, events and open act through the session meridian connect keeps. The deployment answers upload, list, launch, stop, dev, logs and events for a deployment admin only. It answers open for anybody who holds access on that plugin. See Access.
These flags are shared among them:
| Flag | Argument | Default | Used by | Meaning |
|---|---|---|---|---|
--deployment |
<addr> |
the one deployment connected | all | Which connected deployment, when you hold sessions with more than one. |
--dir |
<dir> |
. |
upload, dev |
The plugin's directory. Its image is built with docker, from its own Dockerfile. |
--instance |
<id> |
none (required) | launch, dev, logs, events, open |
The instance's name. Its page is found by it. Lowercase letters, digits and single hyphens, starting with a letter, at most 63 characters. |
--yes |
off | launch, dev |
Approve the roles the version asks for without being asked. For a script that has already shown them to a person. | |
--json |
off | dev, logs, events, open |
JSON on stdout: one object, or one per line for dev and --follow. Progress goes to stderr. |
|
--release |
off | dev |
Upload the plugin as it is now as a version, and run that version in place of the live instance. | |
--since |
<revision> |
none | logs, events |
Only what came after that revision, a whole number. |
--follow |
off | events |
Keep reporting events as they happen, until interrupted. | |
--print |
<path> |
none | open |
The page at that path on the plugin's host, as you are served it, instead of a link. |
Exit codes for all of them: 0 done, 1 refused or failed, 2 asked wrongly, 3 no session or it has lapsed.
meridian plugin upload¶
Builds the plugin's image on this machine and puts it in the deployment's catalogue as a version. The steps:
- Read
pyproject.tomland check its plugin manifest. From CLI 0.1.14, a[tool.meridian]that declarestagsis refused here, before anything is built: a plugin declares none, since access to a plugin isreadorwritein the deployment's access groups. - Build the image with
docker build, taggedmeridian-plugin/<name>:<version>. - Read the image back with
docker save. - Push it into the deployment's registry through the dashboard. A layer the registry already holds is not sent again, and one another plugin's repository holds is mounted from there.
- Send the manifest's metadata with the image's digest. The deployment records the version.
A version is recorded once and never replaced: uploading a name and version already in the catalogue is refused. On success it prints Uploaded to <address>, as sha256:<digest>.
meridian plugin list¶
Prints the catalogue: every version uploaded, with its roles, whether it serves a page, and the SDK version it pins, and every launch, with its instance, version and state (launched, stopped or failed, with the failure). Because it needs a live session, it is also the way to check you are connected: it exits 3 when you aren't.
meridian plugin launch¶
Runs a recorded version as an instance. It first prints the roles the version declares, then asks Launch it as <id>, with these?. Anything but y or yes is no. With no terminal to ask at, it is refused unless you pass --yes.
The deployment runs the instance with exactly the roles it declares; an approval that names anything else is refused. On success it prints the instance's page address, <address>/plugins/<id>. See Plugins, roles and grants.
meridian plugin stop¶
Stops a launched instance. The instance is named as a word here, not with --instance.
meridian plugin dev¶
meridian plugin dev --instance <id> [--dir <dir>] [--yes] [--json] [--deployment <addr>]
meridian plugin dev --release --instance <id> [--dir <dir>] [--yes] [--json] [--deployment <addr>]
Runs the plugin live on a development deployment: each save is sent as it is made, and the plugin's process restarts on it in the same pod, with the same sidecar and the same grants. A deployment not installed with --development refuses it. See Development deployments.
Without --release, it does the following:
- It reads
pyproject.tomlin--dirfor the plugin's name and version. - If the instance is already running live, it sends the directory to it and asks nothing. If the instance is running a version rather than live, it refuses: stop it first or choose another
--instance. - Otherwise it uploads the plugin, unless that name and version are already in the catalogue. In that case the uploaded version runs, with the directory's files sent over it. It then launches the instance live, after the same approval as
plugin launch. - It watches the directory until you press Ctrl-C, sending each change and reporting every event with its revision. The instance keeps running after Ctrl-C.
The directory is scanned four times a second, and events are polled twice a second. Some files are never sent:
.git,__pycache__,.venv,venv,.mypy_cache,.pytest_cache,.ruff_cache,build,dist,.meridian,.DS_Store,*.egg-infoand*.pyc;- whatever the plugin's
.dockerignorenames. Negations and patterns with wildcards other than a leading*are not read, and a pattern that can't be read is sent rather than guessed at.
One change may carry at most 11 MiB before encoding.
A change to the plugin's dependencies or roles needs a new version. The live code runs on the image the instance was launched from.
With --release, it does the following:
- It uploads the directory as it is, as the version in
pyproject.toml. A version already recorded is refused: raiseversionfirst. - It asks for approval of the roles.
- It stops the instance if one is running.
- It launches the new version in its place, not live.
The result is an ordinary version in the catalogue.
Output. In text, one line per event, with its revision first:
r1 sent (9 files, 0 deleted)
r1 synced (9 sent, 0 deleted)
r1 restarted
r1 ready
r2 sent (1 files, 0 deleted)
r2 crashed, exit 1
Traceback (most recent call last):
...
With --json, one JSON object per line on stdout. Each event is described in plugin dev events. With --release --json, one object:
meridian plugin logs¶
Prints what a live plugin printed, one line each. With --since, only lines from revisions after that one. Without it, everything kept, which is up to about 1 MiB of output.
With --json, one object:
revision is the revision the instance is on now.
meridian plugin events¶
meridian plugin events --instance <id> [--since <revision>] [--follow] [--json] [--deployment <addr>]
Prints what happened to a live plugin: synced, restarted, ready, crashed, exited, refused, each with its revision. With --since, only events from revisions after that one. With --follow, it keeps polling and printing new events until interrupted.
With --json and no --follow, one object: {"revision": <now>, "events": [ … ]}. With --json --follow, one event object per line. The events are described in plugin dev events.
meridian plugin open¶
Without --print, it prints a link to the plugin's page. The first browser that opens the link, within a minute, is signed in to that plugin's page alone, for as long as your terminal session lasts. Run open again for another browser. With --json:
With --print <path>, it prints the page at that path on the plugin's host, as you would be served it, instead of a link:
<path>starts with a single/, and may not be under/.meridian.- A page is at most 8 MiB, and redirects are not followed.
- It exits 1 when the plugin answers with a status outside 200–299, after printing what the plugin answered.
With --json, one object:
{"instance_id": "my-plugin", "status": 200, "content_type": "text/html; charset=utf-8", "body": "…"}
A body that is not UTF-8 text comes as body_base64 instead of body.
meridian upgrade¶
Replaces this binary with the latest release, or with the release --to names, older or newer. It upgrades the command line, not a deployment: that is meridian upgrade-deployment. Releases come from https://github.com/open-meridian/meridian-cli/releases, or from MERIDIAN_RELEASES, which must be HTTPS unless it is this machine. The download is checked against the .sha256 published beside it. This catches a broken download, not a compromised release; signing is not built yet.
It never looks for a newer release on its own.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
--to |
<version> |
the latest release | A named release. A leading v is optional. |
Exit codes: 0 replaced, or already that version; 1 failed, for example when the binary's directory is not writable. That check happens before anything is downloaded.
meridian uninstall¶
Removes the command line. It lists what it will remove and asks first:
- Every session it holds, ended at each deployment. A session with a deployment it can't reach is forgotten here and lapses there within 30 minutes.
- The sessions directory.
- The binary.
| Flag | Argument | Default | Meaning |
|---|---|---|---|
--yes |
off | Remove without being asked. With no terminal to ask at, it is refused without this. |
Exit codes: 0 removed, 1 not approved or failed. If the binary's directory is not writable, it stops before ending any session.
meridian --version¶
Prints meridian <version> (<target>; meridian-core <revision>). meridian version is the same.
Environment variables¶
| Variable | Read by | Meaning |
|---|---|---|
MERIDIAN_ENROLMENT_CODE |
up |
The enrolment code, when --enrolment-code is not given. |
MERIDIAN_FIRST_RUN_CODE |
up --params |
The first-run claim code, when --first-run-code is not given. |
MERIDIAN_<FIELD> |
up --params |
Each credential field the wizard asks for, by its field name in capitals. |
MERIDIAN_RELEASES |
upgrade |
Where releases are fetched from, in place of GitHub. |
XDG_CONFIG_HOME, APPDATA, HOME |
session commands | Where the sessions directory is. |
MERIDIAN_INSTALL_DIR, MERIDIAN_VERSION |
install.sh |
Where the install script puts the binary (default ~/.local/bin), and which release it installs. |