Generators & CLI
Protege ships Rails generators for everything you scaffold — the initial install, each extension type, and the self-hosted mail server — plus one rake task. This page is the reference for each.
protege:install
The one command that takes a host app from gem "protege" to a runnable dashboard.
bin/rails g protege:installIt does the wiring it can do safely, and prints the rest as next steps. Specifically, it:
- Installs the Rails frameworks Protege builds on — Active Storage (attachments) and Action Mailbox (inbound mail; this also creates
app/mailboxes/application_mailbox.rb). - Writes
config/initializers/protege.rb— a fully-documented initializer with ENV-backed defaults. - Mounts the engine at
/protege, with a loudTODOto wrap the mount in your own authentication — the engine ships none. - Wires the Loop's recurring tick into
config/recurring.yml(protege_responsibility_tick, every minute) for bothproductionanddevelopment. Idempotent — a second run is a no-op. - Scaffolds a starter
Agentpersona so there's something to route mail to.
The steps it deliberately leaves to you — running migrations, wrapping the mount in auth, setting provider credentials, enabling eager_load in development — are printed at the end.
Extension generators
Four generators scaffold the extension surfaces. Each writes a correctly-shaped starter file into the configured path and applies the type suffix idempotently (see below).
protege:tool
bin/rails g protege:tool lookup_orderScaffolds a Protege::Tool subclass into config.tools_path (default app/tools). Tools are auto-discovered, so the new tool is live as soon as it loads — no wiring.
protege:resolver
bin/rails g protege:resolver customer_contextScaffolds a Protege::Resolver subclass into config.resolvers_path (default app/resolvers). Resolvers are not auto-discovered — add the new one to a persona's chain.
protege:hook
bin/rails g protege:hook refund_auditScaffolds a Protege::Hook subclass into config.hooks_path (default app/hooks). Hooks are auto-discovered and wired to the event bus at boot.
protege:provider
bin/rails g protege:provider scoop_llmScaffolds a Protege::Provider subclass into config.providers_path (default app/providers), with a protege_id derived from the name. Activate it by pointing config.provider_id at that id.
protege:persona
bin/rails g protege:persona customer_serviceScaffolds a Protege::Persona subclass into config.personas_path (default app/personas). Remember the class is the role — customer_service becomes CustomerServicePersona — and the individual agent (Sundae) is a record you create from it. See Personas.
The type-suffix rule
The extension generators apply their type suffix idempotently, so you can name a generation however reads best and get the same result. All three of these produce class SendEmailTool in send_email_tool.rb:
bin/rails g protege:tool send_email
bin/rails g protege:tool SendEmail
bin/rails g protege:tool SendEmailToolThe same holds for Resolver, Hook, Provider, and Persona suffixes.
protege:postfix
Scaffolds a self-hosted Postfix + OpenDKIM mail server you run yourself, for hosts that want no email provider in the loop.
bin/rails g protege:postfixIt vendors the container build into deploy/mail/ (Dockerfile, Postfix/OpenDKIM/OpenDMARC config, the provisioning listener, and a full MAIL.md deploy guide), plus a Kamal accessory example and a GitHub Actions workflow to build the image. The files are copied verbatim — runtime values are substituted at container start. See Mail transport for the full deployment path.
rake protege:css:build
bin/rails protege:css:buildRebuilds the engine's compiled Tailwind CSS (app/assets/builds/protege.css) from the engine's views and helpers. It needs tailwindcss-rails in the host. You only need this if you're modifying the engine's own views — a normal host app never runs it.
Related
- Extensions — what each extension generator scaffolds.
- Configuration — the initializer
protege:installwrites. - Mail transport — deploying what
protege:postfixscaffolds.

