Skip to main content
A plugin with code doesn’t draw its page. It describes it, as parts Lumovi has, and Lumovi draws them: the same tables, tiles and cards its own pages are made of, in its own type, colors and spacing, on the desktop and on a phone. Its code runs in a sealed box, and everything it says passes through Lumovi’s door, which checks each part against what’s on this page. This is the reference for the parts, for what a page can ask of Lumovi, and for its limits. To start a plugin of your own with code, use the template in Lumovi-plugins, and see Your own plugins with code. What a plugin’s file can say is in the plugin format.

What a page is

  • A page is made only of Lumovi’s parts. Where you need one Lumovi doesn’t have, ask for it in an issue: a plugin can’t draw its own. There’s no HTML, no CSS and no canvas, and no width, gap or position is a plugin’s to give.
  • Every text is drawn as text. A name, a word, a line or a server’s error is the plugin’s, and Lumovi draws it as its characters: never as a link, a class or markup, and a character that can’t be seen, or that would turn a line round, shows as a placeholder.
  • Levels and icons are Lumovi’s. A status is one of healthy, progressing, warning, critical and neutral, with the plugin’s word beside it. An icon is one of the icons a view picks from.
  • Times are said by Lumovi. A moment is given as RFC 3339 text, and Lumovi says how long ago or how soon, and keeps it current.
  • What’s pressed opens Lumovi’s own. A row, a card or a tile that opens something names an object Lumovi handed the page, or a list of a kind its file says its pages open, and Lumovi opens it.

The parts

Three arrangements hold the rest, and nothing else does: And the parts they hold:

Every part, exactly

What each part takes, as Lumovi’s door checks it. A property not listed here stops the page, as a part Lumovi doesn’t have does. Properties starting with on are what the page is told: a row opened, a button pressed, a pick.

A table’s cells

A column has a name, a kind, a width (narrow, normal, wide or text) and whether it sorts. A cell’s kind is its column’s: A row has one tooltip, and it’s Lumovi’s own, under the pointer and on the row the keyboard is on. It says, in this order and only what there is to say: where the row goes, if it goes to an object’s Logs tab, its Shell tab or Port forward, and Lumovi offers that place here; its name, the words beside it and the line under it, whole, where any of the three is cut; and the columns that gave way, each with its heading and its value. Where a table is too narrow for its columns, some give way whole, so none is squeezed. A cell that’s only cut by its column’s width has a tooltip of its own under the pointer; on the keyboard’s row, the row’s tooltip says it too. A screen reader is read where the row goes, and the columns that gave way, after the row. Under a finger there’s no tooltip. Beside a name, the words take the room the name leaves. Where the two don’t fit, the words give way first, down to about five characters, and only then does the name lose its middle. A table can have a filter bar, Lumovi’s own: search, a field that keeps the rows whose name, or the words beside it, has what’s typed, and up to 8 filters, each with a key of up to 40 characters. A filter is a menu of the values the rows give it in their facets (up to 32 a row), with how many have each, or of the rows’ own levels: Failing, Warning, In progress, Healthy, Inactive. Values in one filter are either; filters together are all. The bar says how many rows show, like “2 of 5”, and each filter that’s set as a chip, “Take off Status: Failing”. On a phone, the filters are behind Filters. Nothing typed, picked or ticked there reaches the plugin: Lumovi picks the rows. With ticks, a person can select the rows that open an object, one by one, every row shown at once, or with Space, and Lumovi’s own bar offers the file’s actions that say bulk for them, as Lumovi’s own lists do for several at once. The plugin’s code picks no row, starts nothing, and is told nothing of what’s selected or done. A link to one of the plugin’s own pages, { page }, can set that page’s filters and search, as a row, a tile or a count’s row opens it: { page: applications, filters: { status: [Failing] } }. It names a page by its id under the file’s pages, and a link to any other goes nowhere. A count’s row that opens is pressed whole, and Lumovi opens where it says, as a tile does. A table’s status cell can say since, and Lumovi counts how long, “Syncing 1m 05s”, as a header’s second status does. A graph’s card can be marked, drawn with an edge in the warning colour and said in the legend’s marked words, which it then has to give. It can be shown for context, dashed and quiet, opening nothing. And where the page holds no token for its object, it can say where it goes, a list or place of Lumovi’s own as a table’s row does, with its kind’s own icon. A card opens an object or goes somewhere, not both. A run’s steps run from 2 to 12 steps, each with a key of its own; a screen reader hears each as done, running now, to come, or failed. In place of rows, a table (or a graph, or a pick list) can give a state: busy while it reads, failed with a title and what the cluster said, and Try again, empty with a title and a line, or quiet, one calm line. Where a table’s rows come from a read Lumovi cut at its limit, the table names that read’s cut, and Lumovi says so above the rows, from its own numbers.

A Secret, shown and not held

Where a plugin’s file says its pages show a Secret that its own kind names (showsSecrets), a Secret part shows it: Lumovi’s own card, captioned “Shown by Lumovi. Toys can’t see it.” for a plugin named Toys, with a row for each key, hidden until Reveal, and Copy without revealing.
  • It takes a token, never a Secret. secret is the token Lumovi handed the page with the object that names the Secret, at the path the file declares. keys can only narrow the keys the file names: one outside them stops the page. A token the page doesn’t hold shows a card that says “This object names no Secret.”, and nothing is read.
  • Lumovi reads it as you, on your press, and never before. Each read is in the audit log as secret.read, naming the plugin.
  • Nothing goes back to the plugin’s code. The part holds nothing and tells the page nothing: not a value, its length, or that it was revealed, copied or refused.
  • Only on a page whose code Lumovi handed over. Anywhere else, the same part shows its title and no Secret.
  • Where your organization’s policy says pluginSecrets: off, the card says “Your organization’s policy doesn’t let plugins show what’s in Secrets.”, and nothing is read.
A page has at most 20 of them, each with at most 20 keys. None of the plugins Lumovi comes with shows a Secret yet.

A card’s about

A card can say where its data comes from, when its title and note can’t say it: up to 240 characters, shown quietly under the title, two lines at most, the rest in its tooltip. Under a finger, where there’s no tooltip, it wraps whole. Put what matters most first: on a narrow card, two lines hold about 60 characters.

A header’s buttons

A button has a key and a name, and may say:
  • changes: true: the button changes something. Only its press lets the page propose a change, which waits for the person in Lumovi’s dialog. A proposal after any other press is refused. Of a header’s buttons, the last that changes something is drawn last, filled; one that only reads or goes never is. A phone doesn’t draw a button that changes something, and says where it is.
  • asks: true: it asks before it does anything, so its name ends in ”…”.
  • note: what it does, up to 120 characters, under the buttons.
  • off: why it can’t be pressed now, up to 80 characters. It’s drawn off, with this as its tooltip. Under a finger, the reason stands under the buttons, before the note, as “Back up now is off: A backup is running.”
  • busy: what it’s busy with, { word, since }: drawn where it was, with Lumovi’s turning mark, the word, and how long since since where it’s given, counted by Lumovi. It can’t be pressed, its tooltip says “Syncing for 1m 05s. Sync can be pressed again when it’s done.”, and a screen reader hears “Sync, busy: syncing, 1 minute”, in whole minutes. A busy button can’t also be off or goes. And after a change its press proposed is made, Lumovi holds that button busy as “Sent”, with no time, until the page draws again with the changed object, 10 seconds at most: “Sent. Sync can be pressed again when it’s done.” Nothing is held after Cancel, a refusal or a failure.
  • goes: where it goes, in place of telling the page it was pressed: one of Lumovi’s own places for an object the page was handed (a pod’s Logs or Shell tab, Port forward), where the file’s links say so, or a list of Lumovi’s own. It changes nothing and asks nothing first.

A header’s second status

Beside its status, a header can say a second one, secondStatus: a level and a word for what’s happening to it now, with how long since since, where it’s given, counted by Lumovi. Its detail, where it has one, is the line under the header, in place of the first’s: “Sync running: waiting for healthy state of apps/Deployment/storefront”.

What a page can ask for

A page’s code asks Lumovi, and Lumovi reads as the person, within their access:
  • A list of a kind, or one object: its own kinds whole, and of Kubernetes’ own only the kinds Lumovi lets a plugin read (Pods, Nodes and ReplicaSets), each only the fields its file’s reads names. A list can be picked by labels and by the fields Lumovi picks a kind by, and can ask for each object’s live usage. Lumovi keeps a list up to date, and hands each object with a token: what the page names when a row opens it.
  • An object’s warning events, where its file’s read of the kind says events: true: of an object the page holds, by its token, kept up to date as the object is. Lumovi picks them by the object’s uid, so an object made again under the same name isn’t handed the old one’s, and hands the newest 50, each only its reason, its message, how many times, and when first and last. A message is cut where it would carry what only a person may read, and says “(the rest left out by Lumovi)” there: at the API server’s Invalid value:, Unsupported value:, Duplicate value:, Not found: and Forbidden:, at a probe’s probe failed: or probe errored:, at a lifecycle hook’s lifecycle hook (, and at an admission webhook’s denied the request:. Then it’s cut at 500 characters. That narrows what a message can carry; it doesn’t make every message safe to hand.
  • A pod’s last log lines, once, where its file says logs: read. See Logs on a plugin’s page.
  • A path of its tool’s own server, once, where its file says server. See A plugin’s own server.
  • A change, proposed after a press of a button that says changes: true: of its own kinds, as its file’s changes say. See Changes a page proposes. Its dialog can ask the person things first, up to 24 fields: text, numbers and choices; a check, yes or no; picks, several of a list, like the resources to sync; and a switch, yes or no, which can show the fields after it only while it’s on (shows), fill in values of its own off and on (values), and give the button its word while it’s on (verb, like Dry run). Past a few, they stand under section headings. A page can add harms of its own to what its file says a change does, never take one away: see What a change harms.
A read Lumovi refuses is answered with why, in a word and a sentence of Lumovi’s, and the page goes on. An ask that isn’t written as one, or that goes past a limit, stops the page.

What a page can’t do

Its code runs in Lumovi’s sealed box, where it has:
  • no network: nothing reaches out, whatever it tries;
  • no WebAssembly, and no more code: no workers, no import(), no eval;
  • no crypto.subtle, in any browser or on the desktop: hashing, signing and verifying are Lumovi’s. Random numbers are there, from crypto.getRandomValues;
  • no storage that another plugin, another of its pages, or Lumovi can reach;
  • nothing of Lumovi’s page, its cookies or its credentials.
A plugin of your own may be at most 2 MB of code.

Limits

A page past any of these is stopped, and says why in its place. The rest of Lumovi goes on. One more isn’t a stop. A plugin’s pages read at most 200 different things in 10 minutes in one cluster: objects, logs and asks of its server together. The same read again doesn’t count. Past that, a new read is refused as too-many-reads until the ten minutes end, and the answer says how many minutes are left; what the page already reads goes on. So everything a plugin’s code reads as you is in the audit history, or it isn’t read. In the desktop app, Lumovi also stops a page that uses more memory than a plugin may, or more than half of a processor core over half a minute.

What needs which Lumovi

Everything on this page comes with Lumovi 1.22.0, the first with plugins’ pages. A plugin’s needs.lumovi is at least the first Lumovi that carries everything it uses: the checks in Lumovi-plugins read that from the Lumovi they pin, and refuse a plugin whose file says an older one.

Plugins

Pages drawn by a plugin’s code, and what each plugin asks for.

Plugin format

Every field a plugin’s file can have.