Gienah
Run Ruby plugins outside your host process.
Website · Features · Installation · Quick start · Capability gates · Development
Gienah is a small, Canopus-independent plugin host for Ruby applications. It launches each plugin in a separate Ruby process and communicates over Content-Length-framed JSON-RPC 2.0, keeping plugin failures and permissions outside the application core.
The name comes from Gienah (γ Corvi), the IAU-approved star name derived from Arabic al-janāḥ — “the wing”.
Features
- Process isolation — plugins run outside the host process.
- Capability gates — host methods are denied unless the plugin declares the required capability.
- Lifecycle management — activation events, graceful shutdown, bounded restart attempts, and crash disabling.
- Bounded RPC — startup and request deadlines, cancellation, and message-size limits.
-
Portable manifests — recursive discovery of
plugin.jsonandplugin.jsoncfiles. - Small plugin SDK — export methods, handle events, and call back into the host.
- OS sandbox policies — dangerous filesystem, network, and process capabilities are delegated to Saiph.
Installation
Add Gienah to your bundle:
bundle add gienahOr install it directly:
gem install gienahGienah requires Ruby 3.1 or newer. When an OS sandbox is unavailable, plugins requesting write, network, or process-execution capabilities fail closed before startup.
Quick start
Create a plugin manifest at plugins/hello/plugin.json:
{
"id": "hello",
"name": "Hello",
"version": "1.0.0",
"api_version": 1,
"entry": "main.rb",
"activation": ["onStartup"],
"capabilities": []
}Add the plugin entrypoint at plugins/hello/main.rb:
require "gienah"
Gienah::Plugin.export("greet") do |params|
{"message" => "Hello, #{params.fetch("name")}!"}
end
Gienah::Plugin.runDiscover and activate it from the host:
require "gienah"
host = Gienah::Host.new(api_version: 1)
begin
host.discover("plugins")
plugin = host.activate("hello", reason: "onStartup")
result = plugin.call("greet", {"name" => "Ruby"}).await
puts result.fetch("message")
ensure
host.shutdown
endHello, Ruby!
Capability gates
The host decides which application methods a plugin may call:
host.expose("workspace/name", capability: "workspace.read") do
{"name" => "my-project"}
endThe call is accepted only when the plugin manifest declares workspace.read.
Unknown capabilities are rejected while loading the manifest.
| Capability form | Scope |
|---|---|
buffer.read, workspace.read, ui.command
|
Built-in host capabilities |
fs.read:<path>, fs.write:<path>
|
Filesystem paths or globs |
net:<host-pattern> |
Network hosts |
process.exec, exec
|
Process execution |
Lifecycle
-
Host#discoverloads manifests and their contributions. -
Host#activatestarts a plugin only when its activation reason matches. - Host and plugin exchange an initialization handshake with the API version and granted capabilities.
- Calls return a
Gienah::Future; deadlines and cancellation keep requests bounded. - Failed plugins restart with bounded backoff and are disabled after repeated crashes.
Call Host#shutdown to stop every active plugin cleanly.
Development
bundle install
bundle exec rakeContributing
Bug reports and pull requests are welcome on GitHub.
License
Gienah is available under the MIT License.