Use Yaak
mountain-loop/yaak
A skill your agent uses when the user mentions Yaak, a Yaak workspace, or the yaak command, or asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API requests for reuse or manual…
Guide for building web applications with the Kui framework. An agent skill from abersheeran/kui.
$ npx skills add abersheeran/kui --skill kui-framework -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install abersheeran/kui kui-framework --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/abersheeran/kui.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/kui-framework .claude/skills/kui-framework && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "kui-framework" agent skill from https://github.com/abersheeran/kui/tree/master/skills/kui-framework into .claude/skills/kui-framework/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "kui-framework", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/abersheeran/kui/tree/master/skills/kui-frameworkType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add abersheeran/kui --skill kui-framework -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install abersheeran/kui kui-framework --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/abersheeran/kui.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/kui-framework .agents/skills/kui-framework && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "kui-framework" agent skill from https://github.com/abersheeran/kui/tree/master/skills/kui-framework into .agents/skills/kui-framework/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "kui-framework", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add abersheeran/kui --skill kui-framework -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install abersheeran/kui kui-framework --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/abersheeran/kui.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/kui-framework .cursor/skills/kui-framework && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "kui-framework" agent skill from https://github.com/abersheeran/kui/tree/master/skills/kui-framework into .cursor/skills/kui-framework/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "kui-framework", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/abersheeran/kui.git --path skills/kui-framework--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add abersheeran/kui --skill kui-framework -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install abersheeran/kui kui-framework --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/abersheeran/kui.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/kui-framework .gemini/skills/kui-framework && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "kui-framework" agent skill from https://github.com/abersheeran/kui/tree/master/skills/kui-framework into .gemini/skills/kui-framework/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "kui-framework", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install abersheeran/kui kui-frameworkInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add abersheeran/kui --skill kui-framework -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/abersheeran/kui.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/kui-framework .github/skills/kui-framework && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "kui-framework" agent skill from https://github.com/abersheeran/kui/tree/master/skills/kui-framework into .github/skills/kui-framework/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "kui-framework", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add abersheeran/kui --skill kui-framework -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install abersheeran/kui kui-framework --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/abersheeran/kui.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/kui-framework .opencode/skills/kui-framework && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "kui-framework" agent skill from https://github.com/abersheeran/kui/tree/master/skills/kui-framework into .opencode/skills/kui-framework/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "kui-framework", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
kui-frameworkGuide for building web applications with the Kui framework. An agent skill from abersheeran/kui.
Kui Framework is an agent skill from abersheeran/kui. Guide for building web applications with the Kui framework. Use when writing Kui ASGI/WSGI handlers, defining routes, binding parameters, configuring OpenAPI docs, or working with middleware/dependency injection.
Its SKILL.md is about 4.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Design patterns, OpenAPI specifications and Realtime and WebSockets. It works with OpenAPI. The repository describes itself as: An easy-to-use web framework. Supports both WSGI and ASGI modes. Gevent or asyncio, this is the question. The licence is Apache-2.0.
12 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit d1224de. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are python).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Kui Framework loads about 4.4k tokens when it runs. Until then it costs about 57 tokens; SKILL.md has 645 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from abersheeran/kui at commit d1224de, republished under its Apache-2.0 licence (© abersheeran). 645 words, ~4,375 tokens.
.claude/skills/kui-framework/SKILL.md (or your agent's skills folder).Kui is a Python web framework supporting both ASGI (async) and WSGI (sync). It provides type-safe parameter binding via Annotated, dependency injection, OpenAPI documentation generation, class-based views, and middleware composition.
ASGI imports: from kui.asgi import ...
WSGI imports: from kui.wsgi import ...
The two modules expose nearly identical APIs; ASGI handlers are async def, WSGI handlers are plain def. All examples below use ASGI unless noted.
from kui.asgi import Kui, OpenAPI
app = Kui(
routes=[], # Initial routes
http_middlewares=[], # App-level HTTP middleware
socket_middlewares=[], # App-level WebSocket middleware (ASGI only)
cors_config=None, # Optional CORSConfig dict
exception_handlers={}, # {status_or_exc_type: handler}
on_startup=[], on_shutdown=[], # Lifespan callbacks (ASGI only)
templates=None, # Optional Jinja2Templates instance
response_converters={}, # {type: converter_func}
json_encoder={}, # {type: serializer_func}
)app is a standard ASGI callable (async def __call__(scope, receive, send)).
For WSGI it is a standard def __call__(environ, start_response).
app.state.db = create_pool() # Set once; ImmutableAttribute prevents reassignment@app.router.http.get("/users/{user_id:int}")
async def get_user(user_id: Annotated[int, Path()]):
return {"id": user_id}
@app.router.http.post("/users")
async def create_user(body: Annotated[UserCreate, Body()]):
return body, 201
# Any HTTP method
@app.router.http("/health")
async def health():
return "ok"Available method shortcuts: .get(), .post(), .put(), .patch(), .delete().
Decorator parameters: path, name=, middlewares=[], summary=, description=, tags=.
<< operatorfrom kui.asgi import HttpRoute, SocketRoute
app.router <<= HttpRoute("/", homepage)
app.router <<= SocketRoute("/ws", ws_handler)
# Chain multiple
app.router <<= (
app.router
<< HttpRoute("/a", handler_a)
<< HttpRoute("/b", handler_b)
)from kui.asgi import Routes, HttpRoute
api_routes = Routes(
HttpRoute("/users", list_users),
HttpRoute("/posts", list_posts),
namespace="api", # Prefixes route names
tags=["API"], # OpenAPI tags for all routes
http_middlewares=[auth_mw],
)
# Prefix with // operator
app.router <<= "/api/v1" // api_routesapp.router.url_for("route-name") # "/path"
app.router.url_for("user", {"id": 42}) # "/users/42"@ operatorfrom kui.asgi import HttpRoute, required_method, allow_cors
route = HttpRoute("/data", handler) @ required_method("GET") @ allow_cors()
app.router <<= routeSupported converters: {name} (string), {name:int}, {name:decimal}, {name:date}, {name:uuid}, {name:any} (rest-of-path). str cannot match /; use any for rest-of-path (must be at the end).
@app.router.websocket("/ws")
async def ws_handler():
await websocket.accept()
data = await websocket.receive_json()
await websocket.send_json({"echo": data})
await websocket.close()All parameter bindings use typing_extensions.Annotated. The framework inspects the handler signature, extracts and validates parameters via Pydantic, and injects them as keyword arguments.
from typing_extensions import Annotated
from kui.asgi import Path, Query, Header, Cookie, Body
@app.router.http.get("/items/{item_id:int}")
async def get_item(
item_id: Annotated[int, Path()],
q: Annotated[str, Query(...)], # required query param
limit: Annotated[int, Query(10)], # default value
x_token: Annotated[str, Header(alias="x-token")], # header (alias lowercased)
session: Annotated[str, Cookie()] = "", # optional cookie
):
...from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
@app.router.http.post("/items")
async def create_item(item: Annotated[Item, Body(...)]):
return item
# Exclusive body: entire JSON body maps to one parameter
@app.router.http.post("/raw")
async def raw_body(data: Annotated[dict, Body(exclusive=True)]):
return dataPath(), Query(), Header(), Cookie(), Body() all accept standard Pydantic Field kwargs: default, default_factory, alias, title, description, plus any validation kwargs (ge, le, min_length, max_length, pattern, etc.).
from kui.asgi import UploadFile, Body
@app.router.http.post("/upload")
async def upload(file: Annotated[UploadFile, Body(...)]):
return {"filename": file.filename, "content": file.read().decode()}UploadFile attributes: filename, content_type, headers, file.
Methods: awrite, aread, aseek, asave, aclose.
from kui.asgi import Depends
# Simple dependency
async def get_db():
return db_pool.acquire()
# Generator dependency (with cleanup)
async def get_connection():
conn = await db_pool.acquire()
try:
yield conn
finally:
await conn.release()
@app.router.http.get("/")
async def handler(
conn: Annotated[Connection, Depends(get_connection)],
):
return await conn.fetch("SELECT 1")cache=True (default): result cached per request; same dependency injected once even if declared multiple times.cache=False: called fresh each time.Annotated parameters (nested injection).from kui.asgi import HttpView
@app.router.http("/users")
class UserView(HttpView):
@classmethod
async def get(cls):
return [{"id": 1}]
@classmethod
async def post(cls):
return {"created": True}, 201Supported methods: get, post, put, patch, delete, head, options, trace.
OPTIONS auto-generated if not defined. Returns 405 for unsupported methods.
from kui.asgi import SocketView, websocket
@app.router.websocket("/chat")
class Chat(SocketView):
encoding = "json" # "text", "bytes", "json", "anystr"
async def on_connect(self):
await websocket.accept()
async def on_receive(self, data):
await websocket.send_json({"echo": data})
async def on_disconnect(self, close_code: int):
await websocket.close(code=close_code)Merge multiple single-method handlers for the same path into one class-based view automatically:
from kui.asgi import MultimethodRoutes as Routes, HttpView
routes = Routes(base_class=HttpView)
@routes.http.get("/users")
async def list_users():
return []
@routes.http.post("/users")
async def create_user():
return {}, 201A middleware is a function (endpoint) -> new_endpoint:
def logging_middleware(endpoint):
async def wrapper():
print("before")
result = await endpoint()
print("after")
return result
return wrapperImportant: Do NOT use @functools.wraps on middleware wrappers. The framework raises RuntimeError if it detects this.
# Per-route via decorator parameter
@app.router.http.get("/", middlewares=[logging_middleware])
async def handler(): ...
# Per-route via @ operator
app.router <<= HttpRoute("/", handler) @ logging_middleware
# Per-Routes group
routes = Routes(..., http_middlewares=[logging_middleware])
# App-level
app = Kui(http_middlewares=[logging_middleware])
# Via Routes decorator
@routes.http_middleware
def mw(endpoint):
async def wrapper():
return await endpoint()
return wrapperMiddleware can declare its own Annotated parameters for automatic binding:
def auth_middleware(endpoint):
async def wrapper(token: Annotated[str, Header(alias="authorization")]):
verify(token)
return await endpoint()
return wrapperHandlers can return any of these types; the framework auto-converts:
| Return type | Converted to |
|---|---|
str, bytes | PlainTextResponse |
dict, list | JSONResponse |
BaseModel | JSONResponse |
PurePath | FileResponse |
URL | RedirectResponse |
AsyncGenerator (ASGI) / Generator (WSGI) | SendEventResponse |
HttpResponse subclass | Used as-is |
(body, status) or (body, status, headers) tuple | Converted via response_converter |
Use return type annotations:
@app.router.http.get("/")
async def handler() -> Annotated[Any, JSONResponse[200, {}, UserModel]]:
...
# Status-only: JSONResponse[200]
# Status + headers: JSONResponse[200, {"X-Custom": {"schema": {"type": "string"}}}]
# Status + headers + body schema: JSONResponse[200, {}, UserModel]Available: JSONResponse, HTMLResponse, PlainTextResponse, FileResponse, RedirectResponse, SendEventResponse, StreamResponse.
@app.router.http.get("/events")
async def events():
async def generate():
for i in range(10):
yield {"id": i, "data": "hello"}
await asyncio.sleep(1)
return generate()from dataclasses import dataclass
@dataclass
class Error:
code: int
message: str
app = Kui(
response_converters={
Error: lambda e, status=400, headers=None: JSONResponse(
{"code": e.code, "message": e.message}, status, headers
),
}
)Use convert_response(value) to explicitly trigger the response converter pipeline outside of normal handler return flow.
Access via context variables (no parameter needed):
from kui.asgi import request, websocket
@app.router.http.get("/")
async def handler():
request.method # "GET"
request.url # Full URL object
request.headers # Headers mapping
request.cookies # Cookies dict
request.path_params # Extracted path params
request.query_params # Query params
request.state # Per-request State dict
request.app # The Kui instance
await request.json # Parse JSON body (cached property, no parentheses)
await request.form # Parse form body (cached property, no parentheses)
await request.data() # Auto-detect body format (method call)request.state.user = current_user # write
name = request.state.user.name # read
del request.state.user # deleteWebSocket methods (ASGI only):
await websocket.accept()
await websocket.receive_text() / .receive_bytes() / .receive_json()
await websocket.send_text(s) / .send_bytes(b) / .send_json(obj)
await websocket.close(code=1000)from kui.asgi import OpenAPI, Routes
openapi = OpenAPI(
info={"title": "My API", "version": "1.0.0"},
template_name="swagger", # "swagger" | "redoc" | "rapidoc"
reload=True,
)
app.router <<= "/docs" // openapi.routesServes:
GET /docs/ -- Interactive HTML UIGET /docs/json -- OpenAPI 3.1.0 JSON schemaGET /docs/heartbeat -- SSE for hot reloadDocumentation is auto-generated from:
summary=, description=, tags= parameters on routesAnnotated parameter types (Path, Query, Header, Cookie, Body)Use describe_extra_docs to supplement OpenAPI docs for a specific endpoint. The descriptions will be merged into the generated documentation.
Override HttpRequest.data() with a ContentType annotation to change the documented request Content-Type:
from typing import Any
from typing_extensions import Annotated
from baize.datastructures import ContentType
from kui.asgi import HttpRequest, FactoryClass, Kui
class MsgPackRequest(HttpRequest):
async def data(self) -> Annotated[Any, ContentType("application/x-msgpack")]:
...
app = Kui(factory_class=FactoryClass(http=MsgPackRequest))from kui.asgi import HTTPException
# Raise in handlers
raise HTTPException(404)
raise HTTPException(403, content="Forbidden", headers={"X-Reason": "auth"})
# Register handlers
@app.exception_handler(404)
async def not_found(exc):
return {"error": "not found"}, 404
@app.exception_handler(ValueError)
async def value_error(exc):
return {"error": str(exc)}, 400Validation errors return 422 by default. Path validation errors return 404.
from kui.asgi import Depends, bearer_auth, basic_auth, api_key_auth_dependency
# Bearer token: Authorization: Bearer <token>
@app.router.http.get("/me")
async def me(token: Annotated[str, Depends(bearer_auth)]):
return decode_jwt(token)
# Basic auth: Authorization: Basic <base64>
@app.router.http.get("/admin")
async def admin(creds: Annotated[tuple[str, str], Depends(basic_auth)]):
username, password = creds
...
# API key from header/query/cookie
api_key = api_key_auth_dependency("X-API-Key", position="header")
@app.router.http.get("/data")
async def data(key: Annotated[str, Depends(api_key)]):
...All raise HTTPException(401) with appropriate WWW-Authenticate headers when auth fails. OpenAPI security schemes are auto-documented.
import re
from kui.asgi import allow_cors, Kui
# App-level
app = Kui(cors_config={
"allow_origins": [re.compile(r"https://example\.com")],
"allow_methods": ["GET", "POST"],
"allow_headers": [],
"expose_headers": [],
"allow_credentials": False,
"max_age": 600,
})
# Per-route
cors = allow_cors(allow_origins=[re.compile(".*")])
app.router <<= HttpRoute("/api", handler) @ corsPass an async generator function to Kui(lifespan=...). Code before yield runs on startup; code after yield runs on shutdown:
async def lifespan(app: Kui):
app.state.pool = await create_pool()
yield
await app.state.pool.close()
app = Kui(lifespan=lifespan)on_startup/on_shutdown and asynccontextmanager_lifespan are deprecated.
from kui.asgi import request
@app.router.http.post("/notify")
async def notify():
request.background_tasks.append(send_email, to="user@example.com")
return {"status": "queued"}
async def send_email(to: str):
...Background tasks run after the response is sent.
from kui.asgi import Jinja2Templates, TemplateResponse, request
templates = Jinja2Templates("templates")
app = Kui(templates=templates)
@app.router.http.get("/")
async def homepage():
return TemplateResponse("index.html", {"request": request, "name": "World"})from kui.asgi import Kui, FactoryClass, HttpRequest, WebSocket
class CustomRequest(HttpRequest): ...
class CustomWS(WebSocket): ...
app = Kui(factory_class=FactoryClass(http=CustomRequest, websocket=CustomWS))from datetime import datetime
app = Kui(json_encoder={datetime: lambda dt: dt.isoformat()})app.should_exitSet app.should_exit = True to signal graceful shutdown (requires server support).
import asyncio
from pathlib import Path as FilePath
from typing_extensions import Annotated
from kui.asgi import (
Kui, OpenAPI, HttpRoute, SocketRoute,
Path, Query, Body, Depends,
HTTPException, HttpView,
allow_cors, required_method, websocket,
)
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
items_db: list[Item] = []
async def get_items_db():
return items_db
app = Kui(
routes=[
HttpRoute("/", lambda: "Welcome to Kui!"),
],
http_middlewares=[allow_cors()],
)
@app.router.http.get("/items")
async def list_items(
skip: Annotated[int, Query(0)],
limit: Annotated[int, Query(10)],
db: Annotated[list, Depends(get_items_db)],
):
return db[skip:skip + limit]
@app.router.http.post("/items")
async def create_item(
item: Annotated[Item, Body(exclusive=True)],
db: Annotated[list, Depends(get_items_db)],
):
db.append(item)
return item, 201
app.router <<= "/docs" // OpenAPI(template_name="swagger").routes© abersheeran, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/kui-framework of abersheeran/kui.
Open the folder on GitHubat commit d1224de
Kui Framework next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Kui Framework this skillabersheeran/kui | 297 | — | ~4.4k | Automated safety check: Pass | Apache-2.0 | |
| Use Yaakmountain-loop/yaak | 19k | — | ~1.9k | Automated safety check: Pass | MIT | |
| Backendredis/RedisInsight | 8.9k | — | ~1.6k | Automated safety check: Pass | Custom licence | |
| FastAPI ExpertJeffallan/claude-skills | 12k | — | ~1.8k | Automated safety check: Pass | MIT | |
| API Contract Designrsmdt/the-startup | 551 | — | ~1.1k | Automated safety check: Pass | MIT | |
| Frontmcp Developmentagentfront/frontmcp | 146 | — | ~11k | Automated safety check: Pass | Apache-2.0 |
mountain-loop/yaak
A skill your agent uses when the user mentions Yaak, a Yaak workspace, or the yaak command, or asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API requests for reuse or manual…
redis/RedisInsight
NestJS backend development patterns for the RedisInsight API: module structure, services, controllers, DTOs, dependency injection, and error handling.
Jeffallan/claude-skills
Builds async Python APIs with FastAPI and Pydantic V2, covering endpoints, JWT authentication, async SQLAlchemy, WebSockets and pytest checks against the OpenAPI docs.
rsmdt/the-startup
REST and GraphQL API design patterns, OpenAPI/Swagger specifications, versioning strategies, and authentication patterns.
agentfront/frontmcp
A skill your agent uses when building any FrontMCP server component other than a tool (for tools, use create-tool).
aiskillstore/marketplace
FastAPI web framework patterns. An agent skill from aiskillstore/marketplace.
Works with
Categories
Guide for building web applications with the Kui framework. An agent skill from abersheeran/kui. Kui Framework is an agent skill from abersheeran/kui. Guide for building web applications with the Kui framework.
Kui Framework fits situations like: writing Kui ASGI/WSGI handlers; defining routes; binding parameters; configuring OpenAPI docs.
Run `npx skills add abersheeran/kui --skill kui-framework -a claude-code`. Or copy the skill folder (skills/kui-framework in abersheeran/kui) into .claude/skills/kui-framework in your project. Claude Code loads it when a task matches its description.
Run `npx skills add abersheeran/kui --skill kui-framework -a codex`. Or copy the skill folder (skills/kui-framework in abersheeran/kui) into .agents/skills/kui-framework in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add abersheeran/kui --skill kui-framework -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/kui-framework, .gemini/skills/kui-framework, .github/skills/kui-framework and .opencode/skills/kui-framework in your project.
SKILL.md names no scripts, command-line tools or credentials: Kui Framework is instructions for the agent only. Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Kui Framework is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.4k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Kui Framework: Use Yaak (mountain-loop/yaak, 19k stars), Backend (redis/RedisInsight, 8.9k stars), FastAPI Expert (Jeffallan/claude-skills, 12k stars) and API Contract Design (rsmdt/the-startup, 551 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
abersheeran (a GitHub user) maintains it in abersheeran/kui, which has 297 GitHub stars. The repository was last updated on September 23, 2026.
Source: abersheeran/kui on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.