γ Corvi, “the wing”

Run plugins outside the host process.

Gienah gives Ruby applications a small plugin boundary: child processes, framed RPC, explicit activation, capability checks, and bounded failure.

  • RuntimeRuby ≥ 3.1
  • Release0.1.0
  • LicenseMIT
example.plugin ready

Plugin process

pid 9134
  • exports: refresh
  • activation: onStartup
  • shared memory: none

Capabilitygate

  1. buffer.readallow
  2. ui.commandallow
  3. process.execdeny

Ruby host

api version 1
  • Content-Length RPC
  • request timeout: 2,000 ms
  • restart budget: 3
Only declared capabilities cross the process boundary. Dangerous access requires a Saiph sandbox.

A narrow contract between code you own and code you load.

Gienah keeps the host’s application model private. Plugins receive protocol messages, not Ruby objects, and every host method can require a declared capability.

Request lifecycleFail-closed result
Manifest

Validate before launch

Reject unknown capabilities, invalid limits, unsupported API versions, and unsafe entry paths.

accepted / rejected
Activation

Start only on a matching reason

Discover plugins up front, then create a process only when its activation pattern matches.

inactive / ready
Dispatch

Check every host call

Deny undeclared methods at the gate; bound message size, request time, and concurrent work.

allow / deny
Failure

Restart within a budget

Back off after crashes and disable a plugin when repeated failures exhaust the restart window.

restart / disable

Gienah owns the boundary.

  • Manifest discovery and validation
  • Plugin lifecycle and restart policy
  • Framed request, response, and cancellation
  • Capability enforcement and sandbox handoff

Your application owns the product.

  • The host methods plugins may call
  • Activation reasons and contributions
  • Error reporting and user experience
  • Which plugins are installed and trusted

Open the smallest useful door.

Register application-specific methods, discover manifests, and activate a plugin only when its reason occurs.

View on RubyGems
host.rbRuby
$ bundle add gienah

require "gienah"

host = Gienah::Host.new(api_version: 1)
host.expose("workspace/notify") { |params|
  puts params.fetch("message")
}

host.discover(["plugins"])
plugin = host.activate("example", reason: "onStartup")
plugin&.call("refresh", {}).await(timeout: 2)