Writing a Plugin¶
Checklist¶
- Implement
pluginrpc.Plugin(Configure,GetView,DoAction, …) - Entrypoint at
plugins/<name>/cmd/<name>callingpluginrpc.Serve(impl) - Return
ViewDatatables; leave rendering to the host - Register in
plugins.meta.yaml - Document KeePass fields exactly as
Configure/*_config.goread them - Prefer playground seeds over committing secrets
- Never call back into host secrets from inside
GetViewover nested RPC
Minimal shape¶
plugins/myplugin/
├── service.go # Plugin impl
├── service_views.go # ViewNav + actions + help
├── client.go # Talks to the real system
└── cmd/myplugin/
└── main.go # Serve
Metadata¶
func (s *Service) GetMetadata() (pluginapi.PluginMetadata, error) {
return pluginapi.PluginMetadata{
Name: "myplugin",
Description: "Short description for Package Manager",
}, nil
}
And in plugins.meta.yaml:
Views & actions pattern¶
Follow Redis / Docker:
viewNavBindings()→ digit keys 0–9- Optional
moreViewBindings()for overflow views - Per-view
*Actions()for the actions column helpSections()viapluginrpc.HelpNav(...)
Configure from KeePass¶
func (s *Service) Configure(req pluginrpc.ConfigureRequest) error {
s.host = req.Settings["url"]
s.port = req.Settings["port"]
s.password = req.Settings["password"]
// …
return nil
}
Document expected fields on the plugin's docs page under KeePass.
Local testing¶
Or use omo-playground for Docker-backed dependencies.
Reference implementations¶
| Plugin | Why study it |
|---|---|
plugins/redis/ |
Full views / actions / help pattern |
plugins/docker/ |
LogsBody, compose, destructive actions |
plugins/ssh/ |
ExternalSession (interactive shell) |
plugins/k8sportforward/ |
Long-running local tunnels |