skills/style/SKILL.md
General coding conventions for clean, maintainable code. Always load this skill when writing or reviewing code in any language.
npx skillsauth add alexanderguy/skills styleInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
General guidelines for writing clean, maintainable code.
Agents must only operate within git repositories. Before performing any work:
Without a git repository, it's too hard to succeed with agents - changes can't be tracked, reviewed, or safely reverted.
Code should be self-documenting. Do not add comments that describe what the code obviously does:
// Bad - obvious comments
// Base configuration type for all backends
BaseConfigArgs = { level: LogLevel }
// Good - let code speak for itself
BaseConfigArgs = { level: LogLevel }
Decorative comment blocks (ASCII art dividers, section headers) add visual noise without providing meaningful information.
When comments ARE useful:
// XXX - Temporary workaround until upstream fix
// TODO - Switch to newMethod when minimum version is bumped
result = await legacyMethod()
TODO/FIXME/XXX markers are not a deferral mechanism. They are reserved for work that is genuinely blocked by something outside your control — waiting on an upstream library fix, an unreleased API version, missing access or credentials, a dependency in another team's queue. The marker must name the blocker, so a reader knows what would unblock it.
Do not use these markers for:
If you could do it now, do it now. A TODO is a promise to the reader that the work cannot be done yet; abusing the marker for work you simply chose not to do is dishonest and accumulates as dead weight in the codebase.
Code comments speak for the commit they appear in. Do not write comments that refer to other commits — neither what an earlier commit changed nor what a planned follow-up commit will do. A comment like // stub; next commit fills this in is wrong the moment that follow-up is reordered, dropped, or read by someone who reverted past it. If the code is intentionally a stub now, say why it is a stub now, not what is supposed to replace it.
This holds even when you have a multi-commit plan in context — a planned commit does not exist until it lands, and the comment must be accurate for the commit it lives in, standing alone.
Commits should read like a story, allowing others and future-you to understand why changes were made.
Commit Organization:
git commit --amend) to refine the most recent commit (e.g., critique fixes, wording changes, missed files)edit in the rebase todo, make the fix at the stop, amend, and continue. The fix is authored against the target commit's historical tree, which keeps the change intent-correct against the right baseline — downstream commits may still produce a replay conflict if they touch the same lines, but resolving that conflict is straightforward because both sides of it are coherent diffs.git rebase -i origin/main # substitute your project's base branch
# In the editor, change "pick abc1234 ..." to "edit abc1234 ..."
# git stops with the target commit checked out
# ... make the fix ...
git add <files>
git commit --amend --no-edit
git rebase --continue
For more elaborate history surgery — scripted plans, multiple targets, splits, per-commit validation — search your available skills for one whose description covers git rebase or branch-history cleanup, and load it when the simple form above is not enough.
Message Format:
Before drafting a subject, sample the project's existing log:
git log origin/main --format='%s' | head -20
The existing commits document the project's actual subject convention — verb tense, level of detail, voice, capitalization. Match what is there.
The project's log can override the no-prefix rule below, but only when the recent history is predominantly prefixed in a single consistent convention — i.e., the prefix is the obvious shape of the last ~20 commits, not a minority pattern visible in a few. Mixed signals fall through to the no-prefix rule; tie goes to no prefix.
No subject prefixes. Summary lines are plain English sentences that start with a verb and describe the change directly. Do not prefix the subject with anything — no tag, no scope, no category, no ticket ID, no severity marker. This is a flat rule across every prefix convention, including:
feat:, fix:, chore:, docs:, refactor:, test:Anthropic adapter:, mm:, [X86], drivers/net:, frontend:INTR-79:, JIRA-1234:, #456:WIP:, [urgent], (security):Several of these patterns are widespread in well-known projects (Linux kernel, LLVM, Conventional-Commits-adopting projects) and feel idiomatic from sheer exposure. They are still banned here. Familiarity is not a justification.
Summary lines also use no abbreviations and do not end with punctuation.
Good examples:
Add retry logic for failed network requests
Fix race condition in transaction verification
Document API response format
Bad examples:
feat: add retry logic (Conventional Commits prefix)
Anthropic adapter: handle 429s (component-scope prefix)
INTR-79: add retry logic (ticket-ID prefix)
[WIP] refactor the parser (status tag)
Update code (too vague)
Fix bug in server.ts (filename in subject)
Document INFERENCE.md updates (filename in subject)
Self-contained:
A commit message must stand alone. Do not reference:
Someone reading git log years from now, with only the repo in hand, should understand the change without leaving the message.
Acronyms are not words. Do not reshape them to fit camelCase or PascalCase word boundaries. Preserve the acronym's natural capitalization regardless of position in the name.
// Good
JSONSchema, HTTPClient, parseJSON, requestURL
// Bad - treating acronyms as regular words
JsonSchema, HttpClient, parseJson, requestUrl
When making changes to code, check whether related documentation needs updating:
Update documentation in the same commit as the code change, not as a separate task.
Only touch code that is directly related to the task at hand. Do not make drive-by changes to surrounding code, even if they look like improvements. Common violations:
These changes pollute diffs, make review harder, and risk introducing unintended breakage.
Scope discipline exists to prevent unrelated drive-bys, not to license deferral of work that is genuinely part of the task you accepted. If you read the task narrowly enough, almost anything can be called "out of scope" — that is a failure mode, not a virtue.
A change is in scope if it is:
A change is out of scope only if it has no causal relationship to the work you are doing — a tangential improvement you noticed while passing through.
When something is in scope but inconvenient — a refactor your change makes obvious, a test you should add, a docstring that's now wrong, a helper that should be extracted — the default is to do it now, in a properly-scoped commit on this branch. Not a TODO. Not a follow-up ticket. Not a "we should clean this up someday." Those mechanisms exist for genuinely blocked work; using them as a release valve for work you'd rather not do creates debt the team has to carry.
If you genuinely cannot do it on this branch, "raise it as a separate piece of work" means one of:
If none of those are happening, you are not deferring the work, you are dropping it. Don't pretend otherwise.
Do not reimplement functionality that already exists in the codebase. Before writing new code:
When a refactor might be necessary, prompt the user with specific options:
Allow the user to provide their own answer if none of the options fit.
When refactoring replaces an old implementation, delete the old one. Do not leave backwards-compatibility shims, re-exports, renamed _unused variables, or // removed comments for code that no longer serves a purpose. If all callers are internal and have been updated, the old path should not survive. See the philosophy skill for the reasoning behind this.
Any code from outside the organization requires careful attribution and licensing compliance:
If modifications to external code are needed, make them in a separate follow-up commit with clear explanation of what changed and why.
Never trust data from outside the program. All external input — user submissions, API responses, file contents, environment variables, query parameters, message payloads — must be validated at the boundary where it enters the system. Parse it, check it, and reject it if it's wrong. Once data has crossed the boundary and been validated, internal code can trust it without re-checking.
This means validation logic lives at the edge: HTTP handlers, CLI argument parsers, message consumers, file readers, and configuration loaders. It does not live deep inside business logic, scattered across internal functions, or deferred until the data happens to cause a failure somewhere downstream.
If invalid data can travel through multiple layers before something finally breaks, the validation boundary is in the wrong place.
Always run the full build command before declaring any task complete.
Never silently skip a failing step or substitute a partial build.
Do not modify configuration files (e.g. eslint, prettier, tsconfig) unless explicitly asked. Focus on writing working software, not changing the conventions that are being used.
Keep consistent even if we disagree; if we decide to change a style, make it an explicit decision and discussion, not a side effect of other work.
Do not use emojis in code or documentation. Act professionally.
At the start of a session, after reviewing this skill, state: "I have reviewed the style skill, and I am ready to proceed in good taste."
development
Perform a code review or pull request review on a branch
development
Write scripts using opsh and its built-in libraries. Load this skill when writing, reviewing, or debugging opsh scripts.
testing
Reshape git history with rebase — edit-in-place to fix an earlier commit, squash/fixup, drop, split, reword, or validate every replayed commit. Load whenever you need to change a commit that is not HEAD, or for any branch-history cleanup before push. Covers driving every editor invocation non-interactively so the rebase runs without a human at the keyboard.
tools
Conduct an iterative multiple-choice interview using AskUserQuestion. Returns the Q&A inline. Use as a utility when a caller needs structured user input on a topic.