一键导入
hanami-workflow
Hanami framework workflow guidelines. Activate when working with Hanami projects, Hanami CLI, or Hanami-specific patterns.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Hanami framework workflow guidelines. Activate when working with Hanami projects, Hanami CLI, or Hanami-specific patterns.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Language-agnostic API design patterns covering REST and GraphQL, including resource naming, HTTP methods, status codes, versioning, pagination, filtering, authentication, error handling, and schema design. Activate when working with APIs, REST endpoints, GraphQL schemas, API documentation, OpenAPI/Swagger, JWT, OAuth2, endpoint design, API versioning, rate limiting, or GraphQL resolvers.
Git workflow and commit guidelines. Trigger keywords: git, commit, push, .git, version control. MUST be activated before ANY git commit, push, or version control operation. Includes security scanning for secrets (API keys, tokens, .env files), commit message formatting with HEREDOC, logical commit grouping (docs, test, feat, fix, refactor, chore, build, deps), push behavior rules, safety rules for hooks and force pushes, and CRITICAL safeguards for destructive operations (filter-branch, gc --prune, reset --hard). Activate when user requests committing changes, pushing code, creating commits, rewriting history, or performing any git operations including analyzing uncommitted changes.
Testing workflow patterns and quality standards. Activate when working with tests, test files, test directories, code quality tools, coverage reports, or testing tasks. Includes zero-warnings policy, targeted testing during development, mocking patterns, and best practices across languages.
Ansible automation workflow guidelines. Activate when working with Ansible playbooks, ansible-playbook, inventory files (.yml, .ini), or Ansible-specific patterns.
Claude Code AI-assisted development workflow. Activate when discussing Claude Code usage, AI-assisted coding, prompting strategies, or Claude Code-specific patterns.
Guidelines for containerized projects using Docker, Dockerfile, docker-compose, container, and containerization. Covers multi-stage builds, security, signal handling, entrypoint scripts, and deployment workflows.
| name | hanami-workflow |
| description | Hanami framework workflow guidelines. Activate when working with Hanami projects, Hanami CLI, or Hanami-specific patterns. |
| location | user |
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
| Task | Tool | Command |
|---|---|---|
| Lint | StandardRB | bundle exec standardrb |
| Test | RSpec | bundle exec rspec |
| Console | Hanami CLI | bundle exec hanami console |
| Server | Hanami CLI | bundle exec hanami server |
| Generate | Hanami CLI | bundle exec hanami generate <type> |
| DB Migrate | Hanami CLI | bundle exec hanami db migrate |
| Routes | Hanami CLI | bundle exec hanami routes |
Hanami applications MUST be organized into isolated slices (slices/admin/, slices/api/, slices/main/).
lib/ or app/ (application layer)# slices/admin/config/slice.rb
module Admin
class Slice < Hanami::Slice
import keys: ["persistence.rom"], from: :main
end
end
Hanami uses dry-system for dependency injection. All dependencies MUST be injected, not hardcoded.
module Main::Actions::Books
class Show < Main::Action
include Deps["repositories.book_repository"]
def handle(request, response)
book = book_repository.find(request.params[:id])
response.body = book.to_json
end
end
end
include Deps[...] for injecting dependenciesHanami uses ROM (Ruby Object Mapper) for persistence.
Entities MUST be simple domain objects without persistence logic.
module MyApp::Entities
class Book < Hanami::Entity
attribute :id, Types::Integer
attribute :title, Types::String
end
end
Relations MUST define the database schema mapping.
module MyApp::Relations
class Books < Hanami::DB::Relation
schema :books, infer: true do
associations { belongs_to :author; has_many :reviews }
end
end
end
Repositories MUST encapsulate all persistence operations.
module MyApp::Repositories
class BookRepository < Hanami::DB::Repo
def find(id) = books.by_pk(id).one
def published = books.where { published_at <= Date.today }.to_a
def create(attrs) = books.changeset(:create, attrs).commit
end
end
infer: true when schema matches databaseInput validation MUST use dry-validation contracts.
module Main::Contracts::Books
class Create < Hanami::Action::Contract
params do
required(:title).filled(:string, min_size?: 1)
required(:author).filled(:string)
optional(:published_at).maybe(:date)
end
rule(:title) do
key.failure("must be unique") if BookRepository.new.exists?(title: value)
end
end
end
Actions MUST be single-purpose request handlers.
module Main::Actions::Books
class Create < Main::Action
include Deps["repositories.book_repository"]
contract Contracts::Books::Create
def handle(request, response)
result = request.params
if result.valid?
book = book_repository.create(result.to_h)
response.status = 201
response.body = book.to_json
else
response.status = 422
response.body = { errors: result.errors.to_h }.to_json
end
end
end
end
Views MUST separate presentation logic from templates.
module Main::Views::Books
class Show < Main::View
expose :book do |book:|
BookPresenter.new(book)
end
end
end
<%# slices/main/templates/books/show.html.erb %>
<article>
<h1><%= book.title %></h1>
<p>By <%= book.author %></p>
</article>
expose for passing data to templates# config/app.rb
module MyApp
class App < Hanami::App
config.actions.content_security_policy[:script_src] = "'self'"
config.logger.level = :info
end
end
# slices/api/config/slice.rb
module Api
class Slice < Hanami::Slice
config.actions.format :json
config.actions.default_response_format = :json
end
end
# Action test - mock dependencies
RSpec.describe Main::Actions::Books::Show do
subject(:action) { described_class.new(book_repository: repository) }
let(:repository) { instance_double(BookRepository) }
it "returns book" do
allow(repository).to receive(:find).with(1).and_return(Book.new(id: 1))
expect(action.call(id: 1).status).to eq(200)
end
end
# Repository test - real database
RSpec.describe BookRepository, type: :database do
it "finds published" do
subject.create(title: "Old", published_at: Date.today - 30)
expect(subject.published.map(&:title)).to eq(["Old"])
end
end
module MyApp::Interactors::Books
class Publish
include Deps["repositories.book_repository", "events.publisher"]
def call(book_id)
book = book_repository.find(book_id) or return Failure(:not_found)
updated = book_repository.update(book_id, published_at: Date.today)
publisher.publish("book.published", book_id: book_id)
Success(updated)
end
end
end
halt for error responses