> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lumovi.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins for everyone

> Give the custom resources your team uses better columns, statuses, links and actions, and its tools an entry in the sidebar, for everyone who signs in.

A [plugin](/custom-resources/plugins) tells Lumovi how to show the kinds of a tool: under `views:`, which columns matter for a kind, how to tell whether an object is healthy, which facts to show, what it links to and what belongs to it, and which changes people make to it; and, with a place in the sidebar, an entry that leads to all the tool's kinds on one page. Lumovi comes with plugins for popular tools; see [Included plugins](/custom-resources/included-plugins).

In your cluster, the plugins everyone sees go in the chart's `plugins` value, one entry per file name:

```yaml values.yaml theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
plugins:
  queues.yaml: |
    apiVersion: lumovi.dev/v1beta1
    kind: Plugin
    metadata: { name: queues }
    spec:
      version: 1.0.0
      needs:
        lumovi: 1.22.0
      groups: [messaging.example.com]
      views:
        - kinds: [{ group: messaging.example.com, kind: Queue }]
          columns: [{ name: Depth, path: .status.depth, type: number }]
  platform.yaml: |
    apiVersion: lumovi.dev/v1beta1
    kind: Plugin
    metadata: { name: platform }
    spec:
      version: 1.0.0
      needs:
        lumovi: 1.22.0
      groups: [platform.example.com]
      label: Platform
      kinds: [{ group: platform.example.com, kind: Database }]
```

Each entry is a file, named with `.yaml` or `.yml` at the end, holding one plugin, exactly as you'd write it for the desktop app. See [Write a plugin](/custom-resources/write-a-plugin), [Plugins](/custom-resources/plugins) and the [plugin format](/reference/plugin-format).

## How it works

* The chart puts the files in a ConfigMap, and mounts it at `/etc/lumovi/plugins`, where Lumovi reads them (`LUMOVI_PLUGINS_DIR`). Kubernetes mounts each file as a link, which Lumovi follows.
* A kind is one plugin's. These plugins show kinds no other plugin has; one with the name of one of Lumovi's, like `flux` or `cert-manager`, is used in its place, all of it, and **All plugins** says so to everyone on its row.
* They're held as Lumovi's own are: a tool's kinds in the groups the plugin names, none of Kubernetes' own but the few it may [show](/reference/plugin-format#kubernetes’-own-kinds), and nothing created but the plugin's own kinds.
* A change to `plugins` rolls out a new pod, which reads them. People stay signed in, as across any restart, and open pages reconnect.
* Without the chart, put the files in the folder `LUMOVI_PLUGINS_DIR` names. Lumovi reads it again whenever a page loads, so people see a change when they reload.
* These plugins are the server's, for everyone. What goes here is described, never code: only the plugins Lumovi comes with have code. People can't add their own from a browser.
* In a [fleet](/server/fleet), they're for every cluster: a view of a kind is used in each cluster that has that kind, and a plugin's place in the sidebar shows in each cluster that serves one of its kinds.

## Check them

**All plugins**, under **Plugins** in the sidebar (or <kbd>⌘</kbd><kbd>K</kbd>, <kbd>Ctrl</kbd><kbd>K</kbd> on Windows and Linux), lists [every plugin](/custom-resources/plugins#every-plugin-on-one-page): Lumovi's and this server's, each with what it asks for, and **This server’s** on the ones from the folder. One with a problem isn't used at all: its file is a row that says **Not in use**, with each problem under it and where in the file it is. A file that can't be read, or is larger than 256 KB, is a row too, like `It couldn't be read: …`, and the other files load. Lumovi reads up to 200 files, in order of name. At the foot, the page says where this server's are, like *This server’s are in /etc/lumovi/plugins*. **API resources** says what shows each kind, under **Shown by**, and how many plugins there are: *32 plugins from Lumovi, 2 from this server.*

Plugins in files are data only. Their views read fields with JSONPath, and change objects only with the patches and new objects they spell out. Their actions go through the same checks as Lumovi's own: the cluster is asked first whether the person may make the change, the equivalent `kubectl` command is shown, and a read-only Lumovi stays read-only.

## Plugins' code

Four of the plugins Lumovi comes with, Karpenter, Argo CD, CloudNativePG and Prometheus Operator, draw [pages of their own](/custom-resources/plugins#pages-drawn-by-a-plugin’s-code) with their code, in a sealed box. On a server, their code is handed to a person's browser only where all of these hold:

* **`LUMOVI_URL` is set**, so the box has an address of its own, at `plugin-box/box.html` below it, beside the check's own frame at `plugin-box/check.html`. See [The page](/server/security#the-page).
* **The browser's requests are held to Lumovi's own page**, as [`auth.secFetchSite`](/server/security#requests-from-lumovi’s-own-page) does by default. Behind a sign-in proxy, only where `auth.proxy.secFetchSite` says the proxy passes the header through.
* **Lumovi has checked that browser.** The first time someone opens such a page, Lumovi checks that their browser keeps a plugin's code in its box: that it can't reach the network, Lumovi's page, cookies or storage, or another plugin's box. A browser that fails isn't handed any plugin's code, and the page says so, like "Lumovi checked this browser and it didn’t pass, so it doesn’t run plugins’ code in this browser. Another browser may pass the check." Each check is in the [audit log](/audit/events#access-access) as `plugin.box-check`.

  The check asks Lumovi at `box-check/` below `LUMOVI_URL`, from sealed frames in the browser. So whatever stands in front of Lumovi (an ingress that lists its paths, a firewall for web requests, a sign-in proxy) must pass everything there on, as it passes the rest, including these, which come from no site of their own: requests that say `Origin: null`; requests that say no origin and don't come from Lumovi's own page; and WebSocket upgrades that say `Origin: null`. None of them carries the sign-in proxy's cookie. Where they don't arrive, no plugin's code runs in that browser. The page says "Lumovi couldn’t check this browser: its own test request didn’t reach this server, so it can’t tell what a plugin’s box lets out here.", and Lumovi's log says which didn't arrive.
* **This server runs that plugin's code**, as `pluginCode` says.

Wherever its code doesn't run, a plugin's kinds, lists and actions stay, and Karpenter's page is Lumovi's own overview.

`pluginCode` decides whose code runs here:

```yaml values.yaml theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
pluginCode: true                  # every plugin's, the default
# pluginCode: false               # none
# pluginCode: [karpenter, argo-cd]  # only these
```

Off for a plugin, its pages and tabs say "This server doesn’t run plugins’ code. Whoever runs Lumovi can turn it on." (or "this plugin’s code"), no browser is checked for them, and each person's **Run its code** switch is off and locked, with **Turned off on this server.** Without the chart, set [`LUMOVI_PLUGIN_CODE`](/server/configuration#what-people-can-do) to `on`, `off`, or plugins' names separated by commas.

Each person can also turn a plugin's code off for themselves, with **Run its code** on its entry under **All plugins**. Their switch is theirs alone, kept with their other settings.

<Columns cols={2}>
  <Card title="Write a plugin" icon="layout-template" href="/custom-resources/write-a-plugin">
    A step-by-step guide, from columns to actions.
  </Card>

  <Card title="Plugin format" icon="book-open" href="/reference/plugin-format">
    Every field a plugin can have.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.