Skip to content

Generators

Plutonium's pu:* CLI generators. Discoverable via rails g pu:<tab>. Always pass --dest= to skip prompts.

Catalog

GeneratorPurpose
pu:core:installInitial Plutonium setup (base classes, config, layouts)
pu:core:assetsSet up custom Tailwind + Stimulus toolchain
pu:res:scaffoldNew resource (model, migration, controller, policy, definition)
pu:res:connConnect a resource to a portal
pu:pkg:packageNew feature package
pu:pkg:portalNew portal package
pu:rodauth:installInstall Rodauth base
pu:rodauth:accountBasic Rodauth account
pu:rodauth:adminHardened admin account (2FA, lockout, audit)
pu:saas:setupMeta — user + entity + membership + portal + profile + welcome + invites
pu:saas:userIndividual: SaaS user account
pu:saas:entityIndividual: entity model
pu:saas:membershipIndividual: membership join model
pu:saas:portalIndividual: entity-scoped portal
pu:saas:welcomeIndividual: onboarding / select-entity flow
pu:saas:api_clientAPI client for M2M auth
pu:profile:installProfile resource + security section
pu:profile:setupMeta — pu:profile:install + pu:profile:conn
pu:profile:connConnect profile to a portal as a singular resource
pu:invites:installUser invitations package
pu:invites:invitableMark a model as invitable
pu:eject:layoutEject base layout for customization
pu:eject:shellEject topbar/sidebar partials
pu:test:installInstall Plutonium::Testing scaffolding
pu:test:scaffoldScaffold integration tests per (resource × portal)
pu:core:updateUpdate plutonium gem + npm package
pu:skills:syncSync Plutonium Claude skills into the project

Unattended mode

All generators block on prompts by default. Pass --dest=, --auth=, --force, --skip-bundle, --quiet etc. to run in scripts/CI. See App › Unattended execution.


Resource generators

pu:res:scaffold

Generate a complete resource: model, migration, controller, policy, definition.

bash
rails g pu:res:scaffold Post user:belongs_to title:string 'content:text?' --dest=main_app
OptionDescription
--dest=NAMEDestination package (main_app or <package>) — required for unattended runs
--no-modelSkip model file (for existing models)
--no-migrationSkip migration (use with --no-model for existing schema)

Field type syntax — full reference in Resource › Model. Quick recap:

bash
'name:string'              # required string
'name:string?'             # nullable
'company:belongs_to'       # association
'parent:belongs_to?'       # nullable association
'email:string:uniq'        # with unique index
'amount:decimal{10,2}'     # decimal with precision
'status:string{default:draft}'   # with default value
'metadata:jsonb{default:{}}'     # JSON default

Quote any field containing ? or {} to prevent shell expansion.

pu:res:conn

Connect a resource to a portal. Generates portal-specific controller, policy, definition + route registration.

bash
rails g pu:res:conn Post Comment Tag --dest=admin_portal
rails g pu:res:conn Blogging::Post --dest=admin_portal      # namespaced
rails g pu:res:conn Profile --dest=customer_portal --singular  # singleton
OptionDescription
--dest=PORTALTarget portal (required)
--singularRegister as singular resource (/profile, no :id, no index)

Run after migrations

The generator reads model columns to seed the policy's permitted_attributes_for_*.

See Portals › Connecting resources for full details.


Package generators

pu:pkg:package

Feature package — models, policies, definitions, interactions.

bash
rails g pu:pkg:package blogging

See Packages › Feature packages.

pu:pkg:portal

Portal package — controllers, views, routes, auth.

bash
rails g pu:pkg:portal admin --auth=user
rails g pu:pkg:portal admin --auth=admin --scope=Organization
OptionDescription
--auth=NAMERodauth account to authenticate with
--publicPublic access (no auth)
--byoBring your own auth
--scope=CLASSEntity class for multi-tenancy

See Portals › Creating a portal.


Authentication generators

pu:rodauth:install

Install the Rodauth base — Roda app, base plugin, controller, layout, PostgreSQL extension migration.

bash
rails g pu:rodauth:install

pu:rodauth:account

Basic Rodauth account with configurable features.

bash
rails g pu:rodauth:account user                  # interactive
rails g pu:rodauth:account user --defaults       # standard features
rails g pu:rodauth:account user --kitchen_sink   # ALL features
rails g pu:rodauth:account api_user --api_only --jwt --jwt_refresh

For full option tables (features, defaults, individual feature flags) see Auth › Accounts.

pu:rodauth:admin

Hardened admin account — pre-configured with multi-phase login, required TOTP, recovery codes, lockout, active sessions, audit logging, role-based access, invite interaction, and no public signup.

bash
rails g pu:rodauth:admin admin
rails g pu:rodauth:admin admin --roles=super_admin,admin,viewer
rails g pu:rodauth:admin admin --extra-attributes=name:string,department:string
OptionDefaultDescription
--rolessuper_admin,adminComma-separated roles (positional enum, index 0 most privileged)
--extra_attributesAdditional model attributes

Creates a rake task for account creation:

bash
rails rodauth_admin:create[admin@example.com,password123]

SaaS generators

pu:saas:setup

Meta-generator. Creates the user + entity + membership trio AND runs:

  • pu:saas:portal → entity-scoped {Entity}Portal
  • pu:profile:setup → profile model + association
  • pu:saas:welcome → onboarding / select-entity flow
  • pu:invites:install → invitations package
bash
rails g pu:saas:setup --user Customer --entity Organization
rails g pu:saas:setup --user Customer --entity Organization --roles=member,admin
rails g pu:saas:setup --user Customer --entity Organization --no-allow-signup
rails g pu:saas:setup --user Customer --entity Organization \
  --user-attributes=name:string --entity-attributes=slug:string
OptionDefaultDescription
--user=NAME(required)User account model name
--entity=NAME(required)Entity model name
--allow-signuptrueAllow public registration
--rolesadmin,memberAdditional roles — owner always prepended as index 0
--skip-entitySkip entity model generation
--skip-membershipSkip membership model generation
--user-attributesAdditional user model attributes
--entity-attributesAdditional entity model attributes
--membership-attributesAdditional membership model attributes
--api_client=NAMEAlso generate an API client model
--api_client_rolesread_only,write,adminAPI client roles

Don't re-run pieces manually

pu:saas:setup chains four other generators. Don't re-run portal / profile / welcome / invites separately after this. Pass --force to re-run the whole thing.

Individual SaaS generators

For when you don't want the full pu:saas:setup meta-generator:

bash
rails g pu:saas:user Customer
rails g pu:saas:entity Organization --extra-attributes=slug:string
rails g pu:saas:membership --user Customer --entity Organization --roles=member,admin
rails g pu:saas:portal customer --entity Organization
rails g pu:saas:welcome --user Customer --entity Organization

pu:saas:api_client

API client account for machine-to-machine authentication. HTTP Basic Auth with auto-generated password.

bash
rails g pu:saas:api_client ApiClient
rails g pu:saas:api_client ApiClient --entity=Organization
rails g pu:saas:api_client ApiClient --entity=Organization --roles=read_only,write,admin
OptionDefaultDescription
--entity=NAMEEntity to scope API clients to
--rolesread_only,write,adminAvailable roles
--extra_attributesAdditional model attributes
--destmain_appDestination package

CLI creation:

bash
rake api_clients:create LOGIN=my-service
rake api_clients:create LOGIN=my-service ORGANIZATION=acme ROLE=write

Credentials shown once

The auto-generated password is displayed once at creation and cannot be retrieved later (SecureRandom.base64(32)).


Profile generators

See Auth › Profile for the full profile feature.

pu:profile:install

Generate the profile resource (model, migration, controller, policy, definition) and modify the user model to add has_one :profile.

bash
rails g pu:profile:install bio:text avatar:attachment 'timezone:string?' --dest=customer
rails g pu:profile:install AccountSettings bio:text --dest=main_app   # custom resource name
OptionDefaultDescription
--dest=DEST(prompts)Target package or main_app
--user-model=NAMEUserRodauth user model

pu:profile:setup

Meta — runs pu:profile:install + pu:profile:conn in one shot.

bash
rails g pu:profile:setup date_of_birth:date bio:text \
  --dest=competition \
  --portal=competition_portal

pu:profile:conn

Connect the profile resource to a portal as a singular resource (registers /profile and the profile_url helper).

bash
rails g pu:profile:conn --dest=customer_portal

Invite generators

See Tenancy › Invites for the full invitation system.

pu:invites:install

bash
rails g pu:invites:install
rails g pu:invites:install --entity-model=Organization --user-model=Customer --invite-model=OrganizationInvite
OptionDefaultDescription
--entity-model=NAMEEntityEntity model name
--user-model=NAMEUserUser model name
--invite-model=NAME<EntityModel><UserModel>InviteInvite class name
--membership-model=NAMEEntityUserMembership join model
--rolesmember,adminComma-separated
--rodauth=NAMEuserRodauth configuration for signup
--enforce-domainfalseRequire email domain to match entity

Multiple invite flows are supported — run pu:invites:install once per flow.

pu:invites:invitable

Mark an app model as invitable (gets notified when an invite is accepted via on_invite_accepted).

bash
rails g pu:invites:invitable Tenant
rails g pu:invites:invitable TeamMember --role=member
rails g pu:invites:invitable Tenant --dest=my_package
OptionDefaultDescription
--role=ROLEmemberRole to assign to invited users
--user-model=NAMEUserUser model
--membership-model=NAMEEntityUserMembership join model
--dest=PACKAGEmain_appDestination package
--[no-]email-templatestrueGenerate custom email templates

Core generators

pu:core:install

Initial Plutonium setup. Creates base classes, config initializer, layouts. Run once per app.

bash
rails g pu:core:install

pu:core:assets

Set up the custom Tailwind + Stimulus toolchain. Installs npm packages, creates tailwind.config.js, imports Plutonium CSS, registers Stimulus controllers.

bash
rails g pu:core:assets

See UI › Assets for what gets configured.

pu:core:update

Update the plutonium gem and npm package together.

bash
rails g pu:core:update

Eject generators

pu:eject:layout

Copy the base layout template into your portal for direct editing.

bash
rails g pu:eject:layout

pu:eject:shell

Copy the topbar/sidebar partials into your portal for direct editing.

bash
rails g pu:eject:shell --dest=admin_portal

See UI › Layouts.


Test generators

See Testing for the full testing toolkit.

pu:test:install

Install the testing scaffolding (require plutonium/testing in test_helper.rb; create test/support/plutonium_testing.rb for overrides). Run once.

bash
rails g pu:test:install

pu:test:scaffold

Scaffold integration tests — one file per (resource × portal) pairing.

bash
rails g pu:test:scaffold Blogging::Post --portals=admin,org
rails g pu:test:scaffold Blogging::Post --portals=admin --concerns=crud,policy,definition
rails g pu:test:scaffold Blogging::Post --portals=org --parent=organization --dest=blogging
OptionDefaultDescription
--portals=admin,org(required)Emit one file per portal
--concerns=...crud,policy,definitionConcerns to include (full list: crud,policy,definition,nested,model,interaction,portal_access)
--parent=organizationWires the NestedResource parent
--dest=...main_appOutput destination

Skill generators

pu:skills:sync

Sync Plutonium's Claude Code skills into the project (.claude/skills/). Run when upgrading the gem.

bash
rails g pu:skills:sync

Common workflows

Full app setup

bash
# 1. Plutonium template (greenfield) — does all initial setup
rails new myapp -a propshaft -j esbuild -c tailwind \
  -m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb

# Or for existing app:
rails generate pu:core:install
rails generate pu:rodauth:install

# 2. Account types
rails generate pu:rodauth:admin admin
# (or pu:saas:setup for multi-tenant)

# 3. Resources
rails generate pu:res:scaffold Post title:string body:text --dest=main_app
rails generate pu:res:scaffold Comment body:text post:belongs_to --dest=main_app

# 4. Portal
rails generate pu:pkg:portal admin --auth=admin

# 5. Connect resources
rails generate pu:res:conn Post Comment --dest=admin_portal

# 6. Migrate
rails db:migrate

# 7. Create the first admin
rails rodauth_admin:create[admin@example.com,password123]

Adding a new resource

bash
rails g pu:res:scaffold Product name:string price_cents:integer --dest=main_app
rails db:migrate
rails g pu:res:conn Product --dest=admin_portal

Adding a new portal

bash
rails g pu:pkg:portal customer --auth=user --scope=Organization
rails g pu:res:conn Order --dest=customer_portal
rails db:migrate

Undoing generators

bash
rails destroy pu:res:scaffold Post
rails destroy pu:pkg:portal admin

Troubleshooting

Generator not found

Ensure Plutonium is installed and bundle is up to date:

ruby
# Gemfile
gem "plutonium"
bash
bundle install

Package not found

Generators run from Rails root. Package names are case-sensitive.

Migration already exists

If a migration with the same timestamp exists, wait a second and retry — Rails generates timestamps to one-second resolution.

  • Packages — feature vs portal package structure
  • Portals — portal configuration and resource connection
  • Resource › Model — field-type syntax for pu:res:scaffold
  • Auth — account type configuration
  • Tenancy — multi-tenancy and invitations
  • Testing — test scaffolding

Released under the MIT License.