Your first plugin¶
A plugin is your own code running inside your deployment: a tool, a bot, an analytic, a connector. It runs beside a sidecar and reaches nothing else. What it may do comes from the roles it asks for, once a deployment admin approves them. See Plugins, roles and grants.
This page makes a plugin from the reference plugin, puts it in your deployment and opens its page. It works on any deployment. For the faster loop where each save runs at once, see Build with an AI agent.
Before you start¶
- A deployment you installed with Install a deployment.
- You hold deployment admin on it. Only a deployment admin brings plugins in.
- Docker on this machine.
meridian plugin uploadbuilds the plugin's image here, from its ownDockerfile.
1. Sign the CLI in¶
With no address it signs in to the deployment on this machine, http://meridian.localhost. For any
other, give its address: meridian connect https://meridian.firm.example. Your browser opens the
deployment's sign-in. The CLI keeps the session: 30 minutes idle, 12 hours at most.
2. Make the plugin¶
Expected output:
Made my-plugin in my-plugin, on the Python SDK (open-meridian).
cd my-plugin
meridian plugin upload
meridian plugin launch my-plugin 0.1.0 --instance my-plugin
Upload builds its image here and puts it in the catalogue of the deployment
`meridian connect` signed you in to; launch shows the roles its
pyproject.toml asks for, and runs it once you approve them. It reaches its
sidecar and nothing else.
On a deployment installed for development, run it as you write it instead:
meridian plugin dev --instance my-plugin
AGENTS.md teaches your coding agent that loop, whichever agent it is;
CLAUDE.md and the develop-live skill lead Claude Code to it. Commit them
with the plugin, so whoever works on it next has them too.
A plugin name is lowercase letters, digits and single hyphens, starting with a letter. --into <dir>
writes it somewhere other than ./my-plugin. It never writes over a directory that exists.
3. Look at what you got¶
| File | What it is |
|---|---|
src/my_plugin/__main__.py |
Connects to the sidecar, logs who it was launched as and what it may do, serves the page, and reports itself healthy. |
src/my_plugin/page.py |
The page people see through the dashboard. It shows who is asking, and the accounts they may read or write through the plugin. |
pyproject.toml |
The package, pinned to the SDK (open-meridian). Its [tool.meridian] table declares the plugin's roles and whether it serves a page. |
Dockerfile |
Builds on the SDK's base image. |
AGENTS.md, CLAUDE.md, .claude/skills/develop-live/ |
Instructions for coding agents. .dockerignore keeps them out of the image. |
README.md, .gitignore, .dockerignore |
The usual. |
The reference plugin asks for no roles:
That is a plugin admitted with no topics. It can serve a page and read who is asking, and nothing
more. Who may use it is not declared here: a person's access to a plugin is read or write, the
same for every plugin, and a deployment admin grants it (see
Give people access). See Plugin manifest for every key.
4. Upload it¶
It builds the image with Docker and sends its layers to the deployment's own catalogue. Layers the deployment already holds are not sent again. It ends with a line like:
5. Launch it¶
The CLI shows what this version asks for and waits for your answer:
Type y. Anything else is no.
Launched my-plugin: my-plugin 0.1.0.
Its page, if it serves one: http://meridian.localhost/plugins/my-plugin
--instance names this running copy. You use the same name to open, stop and grant access to it.
Note
--yes approves without asking. It is for a script that has already shown a person the
roles. Do not use it to skip a question nobody has answered.
6. Check what is running¶
Versions:
my-plugin 0.1.0 roles: none page: yes SDK 0.3.0
Launches:
my-plugin my-plugin 0.1.0 launched
7. Open its page¶
In the dashboard, the home page, Your plugins, lists it. Choose my-plugin. Its page opens
inside the dashboard, at http://meridian.localhost/plugins/my-plugin, served from its own name,
http://my-plugin.plugins.meridian.localhost/. The breadcrumb reads Plugins / and the plugin's
name; the arrow beside the name opens the page in a window of its own.
The page shows who you are signed in as and a table headed What you may see here. It is empty because nobody has been granted any part of this plugin yet.
From a terminal you can also run:
It prints a link that signs one browser in to this plugin's page alone. The link works once, within a minute.
8. Stop it¶
The version stays in the catalogue. Launch it again whenever you like.
Next steps¶
- Build with an AI agent: change the plugin with a coding agent, live.
- Give people access: give your firm's people read or write on a plugin.
- Release a plugin version: ship a change as a new version.
- Python SDK: what a plugin can call.