patterns
Skill0 starsChanged 4 months agoMITView on GitHub
Research patterns and antipatterns for given languages, and apply them to a codebase. Supports repos with multiple languages/frameworks (e.g. Terraform, Terragrunt, and one or more application languages) via one `patterns-<name>.md` file per component. Use "help" to list all available subskills.
We split this skill into the rules it gives an agent
41 rules. 0 are common, 22 are distinctive, and 19 are very specific to this project.
0
Common
Most of the 9 edited versions we read keep these.
22
Distinctive
This author's own choices. Worth a look.
19
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 20
If args is empty or there is no matching subskill, print an error "Subskill missing/invalid", then run the help subskill, then stop.
- Very specific: line 46
If two components would resolve to the same slug, disambiguate by appending -2, -3, … to the later slug(s) (or ask the user for a …
- Very specific: line 50
Every subskill below that needs to find "the patterns file(s)" means: every file at the repo root matching patterns-*.md, plus a legacy …
- Very specific: line 62
If args is non-empty, there is exactly one component to research: its langs is args.
- Distinctive: line 66
If a file already exists at that path:
- Distinctive: line 68
If the user chooses skip, move to the next component.
- Distinctive: line 70
If this is an interactive session and the user has not already been asked, ask where new patterns files should be stored.
- Distinctive: line 73
If this is a non-interactive/headless session, use the repo root.
- Distinctive: line 74
Create a temporary file.
- Very specific: line 75
Create a search string by concatenating all entries in this component's langs space-separated, then appending "_software design patterns …
- Distinctive: line 76
Search the internet using the search string.
- Distinctive: line 78
Read the temporary file and create deduplicated lists of patterns and anti-patterns, merging descriptions per the deduplication rules and …
- Very specific: line 79
Update the H1 heading to replace "LANGUAGENAME" with this component's langs
- Distinctive: line 80
Remove sample/dummy patterns, anti-patterns
- Distinctive: line 81
Add a list of patterns under the H2 heading "Patterns to Follow"
- Distinctive: line 82
Add a list of anti-patterns under the H2 heading "Anti-patterns to Avoid"
- Distinctive: line 83
Delete the temporary file created in step 7.
- Very specific: line 93
If args is non-empty, filter pattern_files to only those whose filename slug or H1 langs case-insensitively match at least one entry in …
- Very specific: line 97
Create a search string by concatenating all entries in langs space-separated, then appending "_software design patterns anti-patterns best …
- Distinctive: line 99
Read the temporary file, then create deduplicated lists of patterns and anti-patterns by merging its content with the original content of …
- Very specific: line 114
Check the repo remote once to see if creating remote Issues is possible.
- Very specific: line 116
Search the codebase for source files relevant to this component's langs.
- Distinctive: line 119
Search the files identified in the previous step for:
- Distinctive: line 123
Create an in-memory Issue consisting of:
- Distinctive: line 129
Check the state from step 3, and proceed as follows:
- Very specific: line 130
If remote_authenticated, then use a command (gh or glab) to create an Issue from the in-memory Issue.
- Very specific: line 131
If write_to_file, then append the in-memory Issue to patterns-recommendations.md.
- Distinctive: line 133
If Github/Gitlab Issues were created, then include the Issue numbers
- Very specific: line 140
Use find/grep to look for markers such as (this list is illustrative, not exhaustive — use judgement for markers not listed here):
- Very specific: line 158
Search the repo (ignoring dependency/build directories such as node_modules, .dart_tool, build, target, __pycache__, .terraform, vendor) …
- Distinctive: line 165
Use git remote -v to determine if the repo is Github, Gitlab, or other git repo, or not a git repo.
- Distinctive: line 167
If the repo has a remote that is Github or Gitlab then:
- Very specific: line 169
use gh for Github
- Very specific: line 170
use glab for Gitlab
- Very specific: line 171
Check if the user is authenticated by using the auth status subcommand.
- Very specific: line 176
Check if patterns-recommendations.md exists in the repo root:
- Distinctive: line 177
If it does not exist, create it and add a H1 heading of "Pattern Recommendations".
- Very specific: line 178
If it already exists, do not overwrite it.
- Distinctive: line 199
If two items share the same name, or their descriptions describe the same concept in substantially similar language, treat them as …
- Distinctive: line 211
Use markdown footnotes for linking patterns and anti-patterns to their source(s).
- Distinctive: line 234
When instructed to create a temporary file, use this shell script to generate the filename and the file:
“Common” is measured: kept by at least 6 in 10 of the 9 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Subskills
Parse args to determine which subskill to run. Use the first element of args as the name of the subskill to run. Pass the remainder of args as arguments to the subskill.
If args is empty or there is no matching subskill, print an error "Subskill missing/invalid", then run the help subskill, then stop.
help subskill
Print the subskill list below to the user as literal text. Do not reflow, re-render, summarise, or execute it; emit it exactly as written (the surrounding ```markdown fence is a delimiter, not part of the output):
- **help** to list subskills.
- **research-create [<language_or_framework>...]** to research patterns for one or more languages/frameworks and create a new `patterns-<name>.md`. Run with no arguments to auto-detect every language/framework component used in the repo (confirming the list with you) and create one patterns file per component.
- **research-update [<component>...]** to research and update existing `patterns-*.md` file(s). Run with no arguments to update every patterns file found; pass one or more component names to update only matching files.
- **analyse** to check if the codebase needs improvements to better follow patterns and avoid anti-patterns, across all `patterns-*.md` files found. Create Issues, or write `patterns-recommendations.md`.Multi-component model
A repo may contain more than one distinct technology (e.g. Terragrunt environments, Terraform modules, a Python service, a Java service). Each such component gets its own patterns file at the repo root, named patterns-<slug>.md, where <slug> is derived from the component's langs list as follows:
- Lowercase every entry and join the entries with dashes.
- Replace any remaining non-alphanumeric character with a dash.
- Collapse any run of consecutive dashes into a single dash, and strip any leading or trailing dash.
Examples: ["Terraform", "Terragrunt"] → patterns-terraform-terragrunt.md; ["C#", ".NET"] → patterns-c-net.md.
If two components would resolve to the same slug, disambiguate by appending -2, -3, … to the later slug(s) (or ask the user for a distinguishing name in an interactive session) so no patterns file is silently overwritten by another component.
A repo created with an older version of this skill may have a single legacy patterns.md (no suffix) at the repo root. Treat it as just another component's patterns file: identify its langs from its H1 as usual. Do not rename it.
Every subskill below that needs to find "the patterns file(s)" means: every file at the repo root matching patterns-*.md, plus a legacy patterns.md if present.
Only the research-create subskill discovers components from source (via the component detection subprocess). research-update and analyse deliberately do not scan source for new components; they operate solely on the patterns files that already exist at the repo root. To add coverage for a newly introduced component, run research-create first, then research-update/analyse will pick up the new file.
research-create subskill
This subskill is for creating one or more new patterns-<slug>.md files at the repo root, one per component.
Process:
- If
argsis non-empty, there is exactly one component to research: itslangsisargs. Skip to step 3. - If
argsis empty, run the component detection subprocess to propose a list of components (each with anameandlangs). Present the proposed list to the user and ask them to confirm, remove, merge, rename, or add components before proceeding. Use the confirmed list as the component list for the remaining steps. - For each component in the component list, independently perform steps 4–12:
- Compute the target filename
patterns-<slug>.mdper the multi-component model. - If a file already exists at that path:
- Tell the user it already exists and ask whether to: overwrite it, skip this component, or update it instead (in which case, run the research-update subskill process for just this one file, then move to the next component).
- If the user chooses skip, move to the next component.
- Decide where this component's patterns file will be stored:
- If this is an interactive session and the user has not already been asked, ask where new patterns files should be stored. Give options:
- Repo root (default)
- Other directory: ask for input from the user
- If this is a non-interactive/headless session, use the repo root.
- If this is an interactive session and the user has not already been asked, ask where new patterns files should be stored. Give options:
- Create a temporary file.
- Create a search string by concatenating all entries in this component's
langsspace-separated, then appending "software design patterns anti-patterns best practices" - Search the internet using the search string.
- For each of the top search results (up to a maximum of 10), follow the webpage subprocess. For the first result, pass
N=0. Record the number returned by the subprocess, and pass this updated number asNto the next webpage subprocess call. Maintain a set of URLs already visited (both search results and links followed inside the subprocess) and skip any result whose URL is already in the set, so the same page is never fetched twice. - Read the temporary file and create deduplicated lists of patterns and anti-patterns, merging descriptions per the deduplication rules and retaining all footnotes. Using these lists, along with the template, create a new
patterns-<slug>.mdin the location from step 6.- Update the H1 heading to replace "LANGUAGENAME" with this component's
langs - Remove sample/dummy patterns, anti-patterns
- Add a list of patterns under the H2 heading "Patterns to Follow"
- Add a list of anti-patterns under the H2 heading "Anti-patterns to Avoid"
- Update the H1 heading to replace "LANGUAGENAME" with this component's
- Delete the temporary file created in step 7.
- Once every component has been processed, give the user a summary: files created, files skipped, and files updated in place of creation.
research-update subskill
This subskill is for updating existing patterns-*.md file(s), which live at the repo root per the multi-component model. This subskill takes optional arguments naming which components to update.
Process:
- Find all patterns files at the repo root (see multi-component model). Call this list
pattern_files. If none can be found, ask the user for their location(s). If still none can be found, then stop. - If
argsis non-empty, filterpattern_filesto only those whose filename slug or H1langscase-insensitively match at least one entry inargs. If the filtered list is empty, tell the user no matching patterns files were found and stop. - For each file in the (filtered) list, independently perform steps 4–9:
- Read the file and identify from its H1 heading the languages/frameworks being used. If no languages can be identified from the H1, ask the user. Call the list of languages/frameworks
langs. Record the highest numbered footnote number, call itN. If no footnotes are found, setN=0. - Create a temporary file.
- Create a search string by concatenating all entries in
langsspace-separated, then appending "software design patterns anti-patterns best practices" - Search the internet using the search string. For each of the top search results (up to a maximum of 10), follow the webpage subprocess. For the first result, pass in
Nas found in step 4. Record the number returned by the subprocess, and pass this updated number asNto the next webpage subprocess call. Maintain a set of URLs already visited (both search results and links followed inside the subprocess) and skip any result whose URL is already in the set, so the same page is never fetched twice. - Read the temporary file, then create deduplicated lists of patterns and anti-patterns by merging its content with the original content of this file (read in step 4):
- deduplicating and summarising: Patterns to Follow
- deduplicating and summarising: Anti-patterns to Avoid
- keeping all footnote source citations, but moving any citation definitions that are not at the end of the file to the end of the file.
- Save the merged results back to this same file. Do not write to the temporary file. Delete the temporary file.
- Once every file has been processed, give the user a summary of which files were updated.
analyse subskill
This subskill reads the codebase and checks if it needs improvements to better follow patterns and avoid anti-patterns, across every component's patterns file.
Process:
- Find all patterns files at the repo root (see multi-component model). Call this list
pattern_files. If none can be found, ask the user for their location(s). If still none can be found, then stop. - For each file, read it and identify from its H1 heading the languages/frameworks to investigate (
langs) and derive a component name/slug per the multi-component model. If a file has no identifiablelangs, warn the user and skip that file. - Check the repo remote once to see if creating remote Issues is possible. Remember the state (
remote_authenticatedorwrite_to_file); this applies to every component below. - For each patterns file (with its own
langsand component slug), independently perform steps 5–7: - Search the codebase for source files relevant to this component's
langs. Ignore:- build artefacts
- dependency directories (e.g.
node_modules,.dart_tool,build,target,__pycache__,.terraform), and generated files.
- Search the files identified in the previous step for:
- occurrences of anti-patterns that are being used
- occurrences of patterns that are not being followed. A pattern describes what code should do, so you cannot search for it directly. Instead, for each pattern, describe the concrete code shape that appears when the pattern is ignored, and search for that shape. Examples: for "every public function has a doc comment", find public function declarations and flag those with no preceding doc comment; for "use parameterised queries", search for string-concatenated SQL. If a pattern's violation cannot be expressed as a searchable code shape, record it as unverified and move on rather than guessing.
- For each occurrence:
- Create an in-memory Issue consisting of:
- Title: a short (max 20 words) description of the problem (pattern not followed; anti-pattern being used), prefixed with this component's slug in square brackets, e.g.
[terraform] ..., so issues from different components are distinguishable. - Description: a paragraph describing the problem, including:
- the offending code snippet using triple-backticks (max 10 lines) and a language hint immediately after the opening triple-backticks
- file reference (including full line range)
- name and description of the pattern/anti-pattern, and which patterns file it came from
- Title: a short (max 20 words) description of the problem (pattern not followed; anti-pattern being used), prefixed with this component's slug in square brackets, e.g.
- Check the state from step 3, and proceed as follows:
- If
remote_authenticated, then use a command (ghorglab) to create an Issue from the in-memory Issue. - If
write_to_file, then append the in-memory Issue topatterns-recommendations.md.
- If
- Create an in-memory Issue consisting of:
- Give the user a summary of the Issues created, grouped by component, including:
- If Github/Gitlab Issues were created, then include the Issue numbers
- Issue Titles
<a name="component-detection"></a> Component detection subprocess
This subprocess scans the repo for recognisable project markers and proposes a list of components (each a name and langs) for confirmation by the user. It is used by research-create when run with no arguments.
Use find/grep to look for markers such as (this list is illustrative, not exhaustive — use judgement for markers not listed here):
| Marker | Component | langs |
terragrunt.hcl files | Terragrunt | ["Terragrunt"] |
*.tf files (outside .terraform/) | Terraform | ["Terraform"] |
pyproject.toml, requirements*.txt, setup.py, Pipfile | Python | ["Python"] |
pom.xml, build.gradle, build.gradle.kts | Java | ["Java"] |
pubspec.yaml | Dart/Flutter | ["Dart", "Flutter"] |
package.json (with TypeScript config) | TypeScript | ["TypeScript"] |
package.json (no TypeScript config) | JavaScript/Node | ["JavaScript", "Node.js"] |
go.mod | Go | ["Go"] |
Gemfile | Ruby | ["Ruby"] |
Cargo.toml | Rust | ["Rust"] |
*.csproj, *.sln | .NET | ["C#", ".NET"] |
Process:
- Search the repo (ignoring dependency/build directories such as
node_modules,.dart_tool,build,target,__pycache__,.terraform,vendor) for the markers above and any other clearly identifiable project markers. - Group findings into a proposed component list. Related but distinct tools (e.g. Terraform and Terragrunt) should normally be proposed as separate components unless there is reason to merge them (e.g. very few files of one kind).
- Present the proposed component list to the user, showing for each: the component name, its
langs, and roughly how many matching files were found. Ask the user to confirm, or to remove/merge/rename/add components. - Return the confirmed component list to the calling process.
<a name="remote-issues"></a> Creating remote Issues
Use git remote -v to determine if the repo is Github, Gitlab, or other git repo, or not a git repo.
If the repo has a remote that is Github or Gitlab then:
- Select a command:
- use
ghfor Github - use
glabfor Gitlab
- use
- Check if the user is authenticated by using the
auth statussubcommand. If the user is authenticated, remember the state asremote_authenticated. Stop here, and return to the calling process. - In a non-interactive/headless session, do not attempt
auth login: it is interactive and will hang. Treat the repo as not authenticated and continue. Otherwise, use theauth loginsubcommand to log in. If login succeeds, remember the state asremote_authenticated, stop here, and return to the calling process. If login failed, or if the user declined, continue.
If the repo does not have a remote that is Github or Gitlab, or if it was not allowed/possible to log in, then remember that creating remote Issues is not possible. Instead, be prepared to write Issues to a file patterns-recommendations.md in the repo root.
Check if patterns-recommendations.md exists in the repo root:
- If it does not exist, create it and add a H1 heading of "Pattern Recommendations".
- If it already exists, do not overwrite it. Instead, add an H2 timestamp (in
yyyy-mm-dd hh:mmformat). Issues will be appended to it.
Remember this state as write_to_file.
<a name="webpage-subprocess"></a> webpage subprocess
This subprocess takes an argument N which is the highest known footnote number.
- Fetch and read the content of the webpage.
- Identify patterns and anti-patterns on the webpage.
- Append them all to the temporary file created at the start of the main process. The temporary file is the accumulator that carries state between calls to this subprocess, so appending must preserve everything already in it. There is no append tool, so append by one of: reading the current file with Read and rewriting it with Write as (existing content + new block); or using Edit to add the new block at the end. Never overwrite the file with only the new block.
- Patterns go in a list of patterns.
- Anti-patterns go in a list of anti-patterns.
- Each pattern/anti-pattern should include a footnote citation to the source webpage.
- Add footnote definitions at the end of your appended block (i.e. after the patterns and anti-patterns you are adding in this subprocess call). Ensure footnote numbers start at
N+1whereNis the subprocess argument passed in. Keep track of the highest numbered footnote number used.
- Be verbose with the description of the patterns and anti-patterns. Do not worry about duplicates at this stage.
- Follow at most 5 links whose anchor text or surrounding context (e.g. link title, section heading) suggests they describe a named pattern or anti-pattern. For each followed link, identify and record patterns, anti-patterns along with their sources. Do not follow any links from a webpage which was not a page found directly from an internet search. Do not follow links more than one level deep from the search results.
- Return to the calling process the number that corresponds to the highest numbered footnote.
<a name="dedup-pattern"></a> Rules for deduplicating and summarising patterns and anti-patterns
If two items share the same name, or their descriptions describe the same concept in substantially similar language, treat them as duplicates.
In the case of 2 or more duplicate items (patterns or anti-patterns), merge the items by creating a description that encompases all items without repetition. Keep all source citation footnotes.
In source citations, when the same base URL appears (with different anchors) as a source for any items in the document, collapse it to one footnote entry pointing to the base URL.
Example: https://www.example.com/path/to/language/patterns#rule1 and https://www.example.com/path/to/language/patterns#rule2 can be deduplicated to https://www.example.com/path/to/language/patterns
Multiple patterns may legitimately share the same footnote number after deduplication; this is correct.
<a name="citations"></a> Citations
Use markdown footnotes for linking patterns and anti-patterns to their source(s). A footnote name is a unique number. When adding footnotes to an existing document, continue numbering from the highest existing footnote index.
Example:
# Dart Patterns and Anti-patterns
## Patterns to Follow
**some-pattern**
A widget should always have a name[^1].
## Anti-patterns to Avoid
**example-anti-pattern**
A widget should never be transparent[^2].
[^1]: See [Naming Widgets](https://www.example.com/widget/names/).
[^2]: See [Widget Transparency](https://www.example.com/widget/colours/).<a name="tmpfile"></a> Temporary files
When instructed to create a temporary file, use this shell script to generate the filename and the file:
#!/usr/bin/env bash
# Print the path of a fresh temporary file. Uses only mktemp and touch
# (both allow-listed); falls back to a PID-based name if mktemp is absent.
if mktemp /tmp/patterns-XXXXXXXX.md 2>/dev/null ; then
: # mktemp already printed the path on success
else
f="/tmp/patterns-$$.md"
touch "$f" && printf '%s\n' "$f"
fi<a name="template"></a> Template patterns output
# LANGUAGENAME Patterns and Anti-patterns
## Patterns to Follow
**pattern name**
Description of pattern.
## Anti-patterns to Avoid
**anti-pattern name**
Description of anti-pattern.Other versions12 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 12
- ai-analyst-lab/ai-analyst★ 304same name
- nklisch/claude-code-modes★ 116same name
- mycelium-hq/ai-brain-starter★ 50same name
- jmylchreest/aide★ 19same name
- zllovesuki/cloudflare-agent-skills★ 9same name
- nklisch/skills★ 8same name
- Lukasbrujula/claude-code-framework★ 4same name
- nklisch/krometrail★ 3same name
- ffsshhttiikk/opencode-agents-skills★ 2same name
- tizonai/hyperui★ 2same name
2 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
Used alongsideProjects with it also use setup.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
VercelSkillsetup
Set up Vercel CLI and project configuration. Use when the user says "set up Vercel", "configure Vercel", "link to Vercel", or "vercel init".
Also in 3 projects that use this
In this repositoryOne other file it gives its agents.
- terminologySkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

