From pysheeet
Enforces readable Python rules: short focused functions, flat control flow, clear naming, readable structure, Pythonic idioms. Use when writing, reviewing, or refactoring Python code.
npx claudepluginhub crazyguitar/pysheeet --plugin pysheeetThis skill uses the workspace's default tool permissions.
Apply these rules when writing, reviewing, or refactoring Python code. Inspired by *The Art of Readable Code* by Dustin Boswell and Trevor Foucher.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Share bugs, ideas, or general feedback.
Apply these rules when writing, reviewing, or refactoring Python code. Inspired by The Art of Readable Code by Dustin Boswell and Trevor Foucher.
Core principle: Code should be easy to understand. The time it takes someone else (or future you) to understand the code is the ultimate metric.
if inside a loop inside an if, extract the inner block into a helper function with a descriptive name.continue or break to skip iterations rather than wrapping the body in a conditional.# Bad: nested and hard to follow
for user in users:
if user.is_active:
for order in user.orders:
if order.is_pending:
process(order)
# Good: flat, each function name explains what it does
active_users = get_active_users(users)
for user in active_users:
process_pending_orders(user.orders)
fetch_page not get, num_retries not n.tmp, data, result, val, info, handle — unless the scope is tiny (2-3 lines).max_items not limit. If a boolean, use is_, has_, should_, can_ prefixes.num, max, min, err are fine; svc_mgr_cfg is not).if length > 10 not if 10 < length.if/else blocks: positive case first, simpler case first, or the more interesting case first.if/else.# Bad
if not (age >= 18 and has_id and not is_banned):
deny()
# Good
is_eligible = age >= 18 and has_id and not is_banned
if not is_eligible:
deny()
if retries > MAX_RETRIES not if retries > 3.// TODO:, // HACK:, // XXX: with explanation.# Bad: black wraps this into a multi-line mess
result = (
client.get_session()
.query(User)
.filter(User.active == True)
.options(joinedload(User.orders))
.order_by(User.created_at.desc())
.limit(page_size)
.all()
)
# Good: extract a helper so the call site stays clean
def get_active_users(session, page_size: int) -> list[User]:
return (
session.query(User)
.filter(User.active == True)
.options(joinedload(User.orders))
.order_by(User.created_at.desc())
.limit(page_size)
.all()
)
users = get_active_users(client.get_session(), page_size=20)
# Bad: dict comprehension with inline chain — black expands to 5+ lines
config = {
k: settings.get(k, defaults.get(k, fallbacks.get(k, None)))
for k in required_keys
}
# Good: extract the lookup
def resolve_setting(key, settings, defaults, fallbacks):
return settings.get(key, defaults.get(key, fallbacks.get(key)))
config = {k: resolve_setting(k, settings, defaults, fallbacks) for k in required_keys}
# Good: simple and readable
names = [user.name for user in users if user.is_active]
# Bad: too much going on
result = [transform(item) for group in data for item in group.items if item.valid and item.type == "A"]
# Good: break it up
valid_items = get_valid_items(data, item_type="A")
result = [transform(item) for item in valid_items]
name, age = get_user() not result[0], result[1].first, *rest = items.** for merging dicts.enumerate, zip, and Itertoolsenumerate(items) — never track indices manually with i += 1.zip(a, b) to iterate in parallel — never index into parallel lists.itertools (chain, groupby, islice) before writing manual iteration logic.dataclass or NamedTuple.dataclass or NamedTuple — not a raw tuple.pathlib for File Pathspathlib.Path instead of os.path.join and string manipulation.Path objects are readable, composable (/ operator), and cross-platform.