用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/kemalcr/kemal --skill kemal-core命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Use when building, reviewing, debugging, testing, securing, or deploying web applications and HTTP APIs with the Kemal framework for Crystal. Covers Kemal routing, params, context, routers, filters, middleware, ECR, WebSockets, SSE, uploads, configuration, testing, and production concerns.
User authentication and session management in Kemal, following established project patterns.
Database initialization and interaction with SQLite and raw SQL in Kemal, following established project patterns.
正在显示 SKILL.md
| name | kemal-core |
| description | Core Kemal development (routing verbs, parameters, modular router, version gates, response helpers). |
| license | MIT |
This skill provides expert guidance on using the Kemal web framework for Crystal, with version notes for features that are not yet in a stable release.
Everything in this skill works on current Kemal unless marked otherwise.
QUERY method (RFC 10008) — query, before_query, after_query: Kemal master only, not yet in a stable release (on 1.12.0 and earlier, use post or get with query parameters).Kemal.config.max_ranges (Range request bounds): Kemal master only.env.json, env.status, env.html, env.text): since Kemal 1.10.Kemal::Router, mount, namespace: since Kemal 1.10.Kemal.config.max_request_body_size: since Kemal 1.9. Kemal.config.shutdown_timeout: since Kemal 1.10.1.Routing: Use top-level route methods (get, post, put, patch, delete, options) or modular routers (Kemal::Router).
HTTP QUERY Method (RFC 10008) — [Kemal master only]:
query for safe, read-only queries with complex request bodies (JSON or form-encoded):# Kemal master only (not yet in a stable release):
query "/search" do |env|
q = env.params.json["q"]?.as?(String)
halt env.status(:bad_request).json({error: "Query parameter 'q' required"}) unless q
results = Product.search(q)
env.json({results: results})
end
Note: A QUERY request carrying a body without a Content-Type header is rejected with 400 Bad Request. On 1.12.0 and earlier, use post or query parameters via get instead.
Modular Routers (Kemal 1.10+): Use Kemal::Router.new for namespaced routes, scoped middleware, and mounting under path prefixes:
api = Kemal::Router.new
api.namespace "/users" do
get "/" do |env|
env.json({users: %w[alice bob]})
end
get "/:id" do |env|
env.text "user #{env.params.url["id"]?}"
end
end
mount "/api/v1", api
Parameters: Match parameters to request encoding (they are not interchangeable):
env.params.url["id"] (raises on missing key) or env.params.url["id"]? (safe access)application/x-www-form-urlencoded or multipart): env.params.body["name"]??key=val): env.params.query["search"]?application/json): env.params.json["field"]?.as?(String)env.params.files["file"]env.params.raw_body (for multi-handler raw body access)Response Helpers: Use context response helpers (env.json, env.status, env.html, env.text, halt). For deep JSON API patterns and status helpers, refer to kemal-json.
Rendering: Use the render macro with view and optional layout paths (see kemal-view):
render "src/views/posts/index.ecr", "src/views/layouts/application.ecr"
Middleware Registration: Use use (Kemal 1.10+) or Kemal.config.add_handler (see kemal-middleware):
use "/api", [CORSHandler.new, AuthHandler.new]use MyHandler.newAlways use the safe pattern for URL parameters to handle missing or invalid IDs:
# Use the `?` accessor and `to_i64?` for IDs:
id = env.params.url["id"]?.try(&.to_i64?)
halt env.status(:bad_request).json({error: "Invalid ID"}) unless id
post = Post.find(id)
Always use safe access with try for body parameters:
title = env.params.body["title"]?.try(&.strip) || ""
body = env.params.body["body"]?.try(&.strip) || ""
# Access raw request body across multiple handlers:
raw = env.params.raw_body
Organize sub-systems cleanly using Kemal::Router:
require "kemal"
admin_router = Kemal::Router.new
admin_router.namespace "/posts" do
get "/" do |env|
posts = Post.all
env.json(posts.map(&.to_h))
end
get "/:id" do |env|
id = env.params.url["id"]?.try(&.to_i64?)
post = id ? Post.find(id) : nil
if post
env.json(post.to_h)
else
halt env.status(:not_found).json({error: "Post not found"})
end
end
# HTTP QUERY (Kemal master only):
query "/search" do |env|
term = env.params.json["term"]?.as?(String)
halt env.status(:bad_request).json({error: "Search term required"}) unless term
posts = Post.search(term)
env.json(posts.map(&.to_h))
end
end
mount "/admin", admin_router
public directory by default. Configure this via Kemal.config.public_folder.Kemal.config.max_request_body_size = 50 * 1024 * 1024 # 50 MB
Range request parts (default 16) to mitigate CVE-2011-3192 resource exhaustion:
# Kemal master only:
Kemal.config.max_ranges = 16 # set to 0 to ignore Range headers entirely
Kemal.config.shutdown_timeout = 10.seconds
Kemal::Router (Kemal 1.10+).get/post on 1.12.0 and earlier, or query on master).