Installation
One generator wires everything, and the same generator is the upgrade path: every step is idempotent, so re-running it on a years-old app is always safe.
Install
gem "poetry-core"
gem "poetry-ui"
gem "poetry-lucide" # default icon set
gem "poetry-agent" # the MCP server exe + the WebMCP runtime
# gem "poetry-charts" # optional
bundle install
bin/rails g poetry:install --theme default
The installer copies the vendored CSS set under
app/assets/tailwind/poetry/ (tokens, the Tailwind theme
mapping, the animation layer, your chosen
visual theme, the class safelist, the
app-owned typeset.css), injects the Tailwind entry
imports line by line, registers the Stimulus controllers, mounts the
engine (llms.txt), and writes the AGENTS.md section and
the Claude Code skills. Add --charts to wire
poetry-charts. File creations skip what exists; injections append
only missing lines.
Upgrade an existing app
The install generator is the upgrade path, not a one-shot.
Gem-owned code (components, templates, controllers, the registry and
MCP surface) upgrades with bundle update alone. The
vendored CSS files and the safelist upgrade only when the generator
re-runs: new components ship their theme rules and classes there, so
skipping the re-run leaves them unstyled.
bundle update poetry-core poetry-ui poetry-lucide poetry-charts
bin/rails g poetry:install # your theme choice sticks; --theme switches
bin/rails tailwindcss:build # or your CSS build
bin/rails test # confirm the app still renders
A plain re-run keeps the theme already installed (it reads the
fragment header back); passing --theme is how you
switch. Files you own (base.css,
typeset.css, the initializer, the component manifest,
and everything copied in) are never rewritten.
The three ownership tiers
| Tier | Examples | Upgrades via |
|---|---|---|
| Gem-owned | components, controllers, registry, MCP, llms.txt | bundle update |
| Vendored into the app | app/assets/tailwind/poetry/*, safelist.txt |
bin/rails g poetry:install |
| App-owned copy-ins | poetry:add components, blocks, base.css, typeset.css, initializer |
you; poetry:diff reports |
Copy-ins: poetry:diff
Components copied in with poetry:add and blocks copied
with poetry:block are yours: nothing ever rewrites
them. Every poetry:add records the gem version it
copied from in config/poetry_components.yml, and the
read-only drift report shows where your copies stand after an
upgrade:
bin/rails g poetry:diff # read-only: copied at / gem ships / file-by-file drift
bin/rails g poetry:add button # adds newly-shipped files; never overwrites yours
Blocks are starting points meant to be edited, so the report treats a differing block as normal, not drift; it simply points at the gem's current template for reference.
Scaffold templates
Rails lets an app override its generator templates from
lib/templates/; Poetry ships a set that renders with
the library. After installing them, the standard scaffold generator
produces a DataTable index with sanitized URL state (sortable
columns, filter, pagination and a matching controller),
Field-composed forms mapped from attribute types, and a MetadataList
show page:
bin/rails g poetry:scaffold_templates
bin/rails g scaffold Post title:string body:text published:boolean
The copies under lib/templates/ are app-owned: edit
them freely, and re-runs never overwrite. The templates are
lint-gated in the gem's own suite, so generated views pass
poetry:check by construction.