-
Notifications
You must be signed in to change notification settings - Fork 3
Add usethis-agents skill with auto-generated skills directory
#1630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+209
−23
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
e005e67
Initial plan
Copilot 3c69a29
Add usethis-agents skill with auto-generated skills directory
Copilot cbce013
Remove skills directory and usethis-specific references from usethis-…
Copilot 1eec8eb
Address review: bullet format, sync markers, simpler description
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| --- | ||
| name: usethis-agents | ||
| description: Maintain AGENTS.md and agent skill configuration | ||
| compatibility: usethis, agent skills, markdown | ||
| license: MIT | ||
| metadata: | ||
| version: "1.0" | ||
| --- | ||
|
|
||
| # Agent Configuration | ||
|
|
||
| ## The One-Source-of-Truth Principle | ||
|
|
||
| When providing reference material about code objects (functions, classes, modules) to agents, always prefer automation over manual documentation. Use the source code's own docstrings as the single source of truth and extract them via prek hooks — never maintain hand-written summaries that duplicate what the code already says. | ||
|
|
||
| ### Why | ||
|
|
||
| Manually maintained reference material inevitably drifts out of sync with the code it describes. Docstrings live alongside the code, are reviewed during code changes, and can be mechanically extracted — ensuring the documentation always reflects reality. | ||
|
|
||
| ### How to apply the principle | ||
|
|
||
| When you need to add reference material about code to agent configuration: | ||
|
|
||
| 1. Ensure the relevant code objects have descriptive docstrings (or YAML frontmatter descriptions for skills). | ||
| 2. Create or extend a prek hook to extract the information into a generated file under `docs/`. | ||
| 3. Reference the generated file from `AGENTS.md` or skill files using `<!-- sync:path -->` markers. | ||
| 4. Never hand-write summaries of code that could be extracted automatically. | ||
|
|
||
| ## Maintaining AGENTS.md | ||
|
|
||
| `AGENTS.md` is the top-level agent configuration file. It uses sync blocks to embed auto-generated content and is validated by prek hooks. | ||
|
|
||
| ### Sync blocks | ||
|
|
||
| Content between `<!-- sync:path/to/file -->` and `<!-- /sync:path/to/file -->` markers is verified by the `check-doc-sync` hook. To update synced content: | ||
|
|
||
| 1. Modify the source (e.g. add a docstring to a module, or update a skill's description). | ||
| 2. Run the relevant export hook to regenerate the docs file. | ||
| 3. Copy the updated content into the sync block, or let prek handle it during commit. | ||
|
|
||
| ### Skills registry | ||
|
|
||
| The skills table in `AGENTS.md` must include every skill directory under `.agents/skills/`. The `check-skills-documented` hook enforces this. When creating a new skill, add it to the table (see the `usethis-skills-create` skill for the full procedure). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| - `usethis-agents`: Maintain AGENTS.md and agent skill configuration | ||
| - `usethis-cli-modify`: Modify the usethis CLI layer (commands, options, help text) and keep documentation in sync | ||
| - `usethis-file-remove`: Remove files from the project | ||
| - `usethis-github-actions-update`: Update GitHub Actions workflows | ||
| - `usethis-github-issue-create`: Create GitHub issues via the gh CLI to record lessons, track follow-up work, or file bugs discovered during development | ||
| - `usethis-pre-commit`: Guidance on pre-commit hooks — this project uses prek, not pre-commit directly | ||
| - `usethis-prek-add-hook`: Add a prek hook for dev | ||
| - `usethis-prek-hook-bespoke-create`: Write bespoke prek hooks as Python scripts for custom project-specific checks | ||
| - `usethis-python-code`: Guidelines for Python code design decisions such as when to share vs. duplicate code | ||
| - `usethis-python-code-modify`: Modify Python code (e.g. refactor, add new code, or delete code) | ||
| - `usethis-python-enum`: Style and testing conventions for working with Python enums | ||
| - `usethis-python-functions`: Guidelines for Python function design, including return types and signature simplicity | ||
| - `usethis-python-module-layout-modify`: Modify the Python module layout (create, move, rename, or delete modules) | ||
| - `usethis-python-ruff`: Guidelines for complying with Ruff linter rules instead of suppressing them | ||
| - `usethis-python-test-affected-find`: Identify tests that are potentially affected by code changes, to catch regressions before CI | ||
| - `usethis-python-test-full-coverage`: Write tests that achieve full code coverage and verify coverage locally before pushing | ||
| - `usethis-qa-import-linter`: Use the Import Linter software on the usethis project | ||
| - `usethis-qa-static-checks`: Perform static code checks | ||
| - `usethis-skills-create`: Create new agent skills (SKILL.md files) following best practices for content quality, structure, and discoverability | ||
| - `usethis-skills-external-add`: Add an external (community) skill to the project from a third-party source, including installing it and documenting it in AGENTS.md | ||
| - `usethis-skills-external-install`: Reinstall already-tracked external skills from skills-lock.json (e.g. after a fresh clone) | ||
| - `usethis-skills-modify`: Modify agent skills (SKILL.md files) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| """Export a skills directory from SKILL.md YAML frontmatter. | ||
|
|
||
| Scans agent skill directories for SKILL.md files, extracts the name and | ||
| description from each file's YAML frontmatter, and writes a formatted | ||
| Markdown bullet list to an output file. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import argparse | ||
| import re | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
|
|
||
| def _parse_frontmatter(path: Path) -> dict[str, str]: | ||
| """Extract top-level string fields from YAML frontmatter.""" | ||
| text = path.read_text(encoding="utf-8") | ||
| match = re.match(r"^---\n(.*?)\n---", text, re.DOTALL) | ||
| if not match: | ||
| return {} | ||
| frontmatter = match.group(1) | ||
| fields: dict[str, str] = {} | ||
| for line in frontmatter.splitlines(): | ||
| m = re.match(r"^(\w[\w-]*)\s*:\s*(.+)$", line) | ||
| if m: | ||
| key = m.group(1).strip() | ||
| value = m.group(2).strip().strip('"').strip("'") | ||
| fields[key] = value | ||
| return fields | ||
|
|
||
|
|
||
| def main() -> int: | ||
| """Export a skills directory bullet list from SKILL.md frontmatter.""" | ||
| parser = argparse.ArgumentParser( | ||
| description="Export a skills directory from SKILL.md frontmatter.", | ||
| ) | ||
| parser.add_argument( | ||
| "--skills-dir", | ||
| required=True, | ||
| help="Path to the skills directory to scan.", | ||
| ) | ||
| parser.add_argument( | ||
| "--output-file", | ||
| required=True, | ||
| help="Path to the output file to write the directory to.", | ||
| ) | ||
| parser.add_argument( | ||
| "--prefix", | ||
| default="usethis-", | ||
| help="Only include skills whose directory name starts with this prefix.", | ||
| ) | ||
| args = parser.parse_args() | ||
|
|
||
| skills_dir = Path(args.skills_dir) | ||
| output_file = Path(args.output_file) | ||
| prefix: str = args.prefix | ||
|
|
||
| if not skills_dir.is_dir(): | ||
| print(f"ERROR: {skills_dir} is not a directory.", file=sys.stderr) | ||
| return 1 | ||
|
|
||
| rows: list[tuple[str, str]] = [] | ||
| missing: list[str] = [] | ||
|
|
||
| for skill_dir in sorted(skills_dir.iterdir()): | ||
| if not skill_dir.is_dir(): | ||
| continue | ||
| if not skill_dir.name.startswith(prefix): | ||
| continue | ||
| skill_md = skill_dir / "SKILL.md" | ||
| if not skill_md.is_file(): | ||
| missing.append(skill_dir.name) | ||
| continue | ||
| fields = _parse_frontmatter(skill_md) | ||
| name = fields.get("name", skill_dir.name) | ||
| description = fields.get("description", "") | ||
| if not description: | ||
| missing.append(skill_dir.name) | ||
| continue | ||
| rows.append((name, description)) | ||
|
|
||
| if not rows: | ||
| print("ERROR: No skills found.", file=sys.stderr) | ||
| return 1 | ||
|
|
||
| lines: list[str] = [] | ||
| for name, desc in rows: | ||
| lines.append(f"- `{name}`: {desc}") | ||
|
|
||
| content = "\n".join(lines) + "\n" | ||
|
|
||
| output_file.parent.mkdir(parents=True, exist_ok=True) | ||
| output_file.write_text(content, encoding="utf-8") | ||
|
|
||
| print(f"Skills directory written to {output_file}.") | ||
|
|
||
| if missing: | ||
| print( | ||
| f"WARNING: {len(missing)} skill(s) missing SKILL.md or description:", | ||
| file=sys.stderr, | ||
| ) | ||
| for name in missing: | ||
| print(f" - {name}", file=sys.stderr) | ||
|
|
||
| return 0 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| raise SystemExit(main()) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.