diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index a1f82f0d..6dc4b121 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -71,4 +71,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
\ No newline at end of file
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5c8ac13c..3ee9e4f4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -82,4 +82,4 @@ Please note that this project is released with a [Contributor Code of Conduct](C
## License
-By contributing to this repository, you agree that your contributions will be licensed under the MIT License.
\ No newline at end of file
+By contributing to this repository, you agree that your contributions will be licensed under the MIT License.
diff --git a/README.md b/README.md
index f70435ed..1c8cbf0c 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ Enhance your GitHub Copilot experience with community-contributed instructions,
GitHub Copilot provides three main ways to customize AI responses and tailor assistance to your specific workflows, team guidelines, and project requirements:
-| **π§ Custom Instructions** | **π Reusable Prompts** | **π Custom Chat Modes** |
+| **π§ Custom Instructions** | **π Reusable Prompts** | **π§© Custom Chat Modes** |
| --- | --- | --- |
| Define common guidelines for tasks like code generation, reviews, and commit messages. Describe *how* tasks should be performed
**Benefits:**
β’ Automatic inclusion in every chat request
β’ Repository-wide consistency
β’ Multiple implementation options | Create reusable, standalone prompts for specific tasks. Describe *what* should be done with optional task-specific guidelines
**Benefits:**
β’ Eliminate repetitive prompt writing
β’ Shareable across teams
β’ Support for variables and dependencies | Define chat behavior, available tools, and codebase interaction patterns within specific boundaries for each request
**Benefits:**
β’ Context-aware assistance
β’ Tool configuration
β’ Role-specific workflows |
@@ -21,22 +21,21 @@ We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md)
Team and project-specific instructions to enhance GitHub Copilot's behavior for specific technologies and coding practices:
-- [Angular Development Instructions](instructions/angular.md) - Angular-specific coding standards and best practices
-- [ASP.NET REST API Development](instructions/aspnet-rest-apis.md) - Guidelines for building REST APIs with ASP.NET
-- [Azure Functions Typescript](instructions/azure-functions-typescript.md) - TypeScript patterns for Azure Functions
-- [Bicep Code Best Practices](instructions/bicep-code-best-practices.md) - Infrastructure as Code with Bicep
-- [Blazor](instructions/blazor.md) - Blazor component and application patterns
-- [Cmake Vcpkg](instructions/cmake-vcpkg.md) - C++ project configuration and package management
+- [Angular Development Instructions](instructions/angular.instructions.md) - Angular-specific coding standards and best practices
+- [ASP.NET REST API Development](instructions/aspnet-rest-apis.instructions.md) - Guidelines for building REST APIs with ASP.NET
+- [Azure Functions Typescript](instructions/azure-functions-typescript.instructions.md) - TypeScript patterns for Azure Functions
+- [Bicep Code Best Practices](instructions/bicep-code-best-practices.instructions.md) - Infrastructure as Code with Bicep
+- [Blazor](instructions/blazor.instructions.md) - Blazor component and application patterns
+- [Cmake Vcpkg](instructions/cmake-vcpkg.instructions.md) - C++ project configuration and package management
- [Copilot Process tracking Instructions](instructions/copilot-thought-logging.instructions.md) - See process Copilot is following where you can edit this to reshape the interaction or save when follow up may be needed
-- [C# Development](instructions/csharp.md) - Guidelines for building C# applications
-- [Dotnet Maui](instructions/dotnet-maui.md) - MAUI component and application patterns
-- [Genaiscript](instructions/genaiscript.md) - AI-powered script generation guidelines
-- [Generate Modern Terraform Code For Azure](instructions/generate-modern-terraform-code-for-azure.md) - Guidelines for generating modern Terraform code for Azure
-- [Guidance for Localization](instructions/localization.md) - Guidelines for localizing markdown documents
-- [Markdown](instructions/markdown.md) - Documentation and content creation standards
-- [Next.js + Tailwind Development Instructions](instructions/nextjs-tailwind.md) - Next.js + Tailwind development standards and instructions
-- [Python Coding Conventions](instructions/python.md) - Python coding conventions and guidelines
-
+- [C# Development](instructions/csharp.instructions.md) - Guidelines for building C# applications
+- [.NET MAUI](instructions/dotnet-maui.instructions.md) - .NET MAUI component and application patterns
+- [Genaiscript](instructions/genaiscript.instructions.md) - AI-powered script generation guidelines
+- [Generate Modern Terraform Code For Azure](instructions/generate-modern-terraform-code-for-azure.instructions.md) - Guidelines for generating modern Terraform code for Azure
+- [Guidance for Localization](instructions/localization.instructions.md) - Guidelines for localizing markdown documents
+- [Markdown](instructions/markdown.instructions.md) - Documentation and content creation standards
+- [Next.js + Tailwind Development Instructions](instructions/nextjs-tailwind.instructions.md) - Next.js + Tailwind development standards and instructions
+- [Python Coding Conventions](instructions/python.instructions.md) - Python coding conventions and guidelines
> π‘ **Usage**: Copy these instructions to your `.github/copilot-instructions.md` file or create task-specific `.github/.instructions.md` files in your workspace's `.github/instructions` folder.
@@ -44,27 +43,20 @@ Team and project-specific instructions to enhance GitHub Copilot's behavior for
Ready-to-use prompt templates for specific development scenarios and tasks, defining prompt text with a specific mode, model, and available set of tools.
-### Backend Development
-- [ASP.NET Minimal API with OpenAPI](prompts/aspnet-minimal-api-openapi.prompt.md) - Generate API endpoints with proper documentation
-- [Entity Framework Core Best Practices](prompts/ef-core.prompt.md) - Database operations and ORM patterns
-- [Multi-Stage Dockerfile](prompts/multi-stage-dockerfile.prompt.md) - Optimized container builds for any technology
-
-### Testing & Quality
-- [C# Async Programming](prompts/csharp-async.prompt.md) - Asynchronous programming best practices
-- [MSTest Best Practices](prompts/csharp-mstest.prompt.md) - MSTest unit testing with data-driven tests
-- [NUnit Best Practices](prompts/csharp-nunit.prompt.md) - NUnit testing patterns and assertions
-- [XUnit Best Practices](prompts/csharp-xunit.prompt.md) - XUnit testing with modern C# features
-- [JavaScript/TypeScript Jest](prompts/javascript-typescript-jest.prompt.md) - Jest testing patterns, mocking, and structure
-
-### Documentation & Project Management
-- [Comment Code Generate Tutorial](prompts/comment-code-generate-a-tutorial.prompt.md) - Transform code into educational content
-- [Generate Specs as Issues](prompts/gen-specs-as-issues.prompt.md) - Convert requirements into GitHub issues
+- [ASP.NET Minimal API with OpenAPI](prompts/aspnet-minimal-api-openapi.prompt.md) - Create ASP.NET Minimal API endpoints with proper OpenAPI documentation
+- [Azure Cost Optimize](prompts/az-cost-optimize.prompt.md) - Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations.
+- [Comment Code Generate A Tutorial](prompts/comment-code-generate-a-tutorial.prompt.md) - Transform this Python script into a polished, beginner-friendly project by refactoring the code, adding clear instructional comments, and generating a complete markdown tutorial.
+- [C# Async Programming Best Practices](prompts/csharp-async.prompt.md) - Get best practices for C# async programming
+- [C# Documentation Best Practices](prompts/csharp-docs.prompt.md) - Ensure that C# types are documented with XML comments and follow best practices for documentation.
+- [MSTest Best Practices](prompts/csharp-mstest.prompt.md) - Get best practices for MSTest unit testing, including data-driven tests
+- [NUnit Best Practices](prompts/csharp-nunit.prompt.md) - Get best practices for NUnit unit testing, including data-driven tests
+- [XUnit Best Practices](prompts/csharp-xunit.prompt.md) - Get best practices for XUnit unit testing, including data-driven tests
+- [Entity Framework Core Best Practices](prompts/ef-core.prompt.md) - Get best practices for Entity Framework Core
+- [Product Manager Assistant: Feature Identification and Specification](prompts/gen-specs-as-issues.prompt.md) - This workflow guides you through a systematic approach to identify missing features, prioritize them, and create detailed specifications for implementation.
+- [Javascript Typescript Jest](prompts/javascript-typescript-jest.prompt.md) - Best practices for writing JavaScript/TypeScript tests using Jest, including mocking strategies, test structure, and common patterns.
+- [Multi Stage Dockerfile](prompts/multi-stage-dockerfile.prompt.md) - Create optimized multi-stage Dockerfiles for any language or framework
- [My Issues](prompts/my-issues.prompt.md)
- [My Pull Requests](prompts/my-pull-requests.prompt.md)
-- [C# Documentation Best Practices](prompts/csharp-docs.prompt.md) - Ensure that C# types are documented with XML comments and follow best practices for documentation.
-
-### FinOps
-- [Azure Cost Optimize](prompts/az-cost-optimize.prompt.md) - Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations.
> π‘ **Usage**: Use `/prompt-name` in VS Code chat, run `Chat: Run Prompt` command, or hit the run button while you have a prompt open.
@@ -73,12 +65,11 @@ Ready-to-use prompt templates for specific development scenarios and tasks, defi
Custom chat modes define specific behaviors and tools for GitHub Copilot Chat, enabling enhanced context-aware assistance for particular tasks or workflows.
- [4.1 Beast Mode](chatmodes/4.1-Beast.chatmode.md) - A custom prompt to get GPT 4.1 to behave like a top-notch coding agent.
-- [Database Administrator Chat Mode](chatmodes/PostgreSQL%20DBA.chatmode.md) - Work with PostgreSQL databases using the PostgreSQL extension.
- [Debug Mode Instructions](chatmodes/debug.chatmode.md) - Debug your application to find and fix a bug
- [Planning mode instructions](chatmodes/planner.chatmode.md) - Generate an implementation plan for new features or refactoring existing code.
+- [PostgreSQL Database Administrator](chatmodes/postgresql-dba.chatmode.md) - Work with PostgreSQL databases using the PostgreSQL extension.
- [Refine Requirement or Issue Chat Mode](chatmodes/refine-issue.chatmode.md) - Refine the requirement or issue with Acceptance Criteria, Technical Considerations, Edge Cases, and NFRs
-
> π‘ **Usage**: Create new chat modes using the command `Chat: Configure Chat Modes...`, then switch your chat mode in the Chat input from _Agent_ or _Ask_ to your own mode.
## π Additional Resources
@@ -103,4 +94,4 @@ This project may contain trademarks or logos for projects, products, or services
trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
-Any use of third-party trademarks or logos are subject to those third-party's policies.
+Any use of third-party trademarks or logos are subject to those third-party's policies.
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
index 4279c87f..67a9cbf2 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -28,4 +28,4 @@ This information will help us triage your report more quickly.
## Policy
-See [GitHub's Safe Harbor Policy](https://docs.github.com/en/site-policy/security-policies/github-bug-bounty-program-legal-safe-harbor#1-safe-harbor-terms)
\ No newline at end of file
+See [GitHub's Safe Harbor Policy](https://docs.github.com/en/site-policy/security-policies/github-bug-bounty-program-legal-safe-harbor#1-safe-harbor-terms)
diff --git a/SUPPORT.md b/SUPPORT.md
index bf9050bc..72edc54c 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -12,4 +12,4 @@ Please include one of the following statements file:
-
## GitHub Support Policy
-Support for this project is limited to the resources listed above.
\ No newline at end of file
+Support for this project is limited to the resources listed above.
diff --git a/chatmodes/4.1-Beast.chatmode.md b/chatmodes/4.1-Beast.chatmode.md
index 090466e2..3a0c3d40 100644
--- a/chatmodes/4.1-Beast.chatmode.md
+++ b/chatmodes/4.1-Beast.chatmode.md
@@ -133,4 +133,4 @@ I'm now checking to ensure that these changes will correctly update the UI when
4. Reuse previous context unless something has changed.
5. If redoing work, explain briefly *why* itβs necessary and proceed.
-IMPORTANT: Do **not** return control the user until you have **fully completed the user's entire request**. All items in your todo list MUST be checked off. Failure to do so will result in a bad rating for you.
\ No newline at end of file
+IMPORTANT: Do **not** return control the user until you have **fully completed the user's entire request**. All items in your todo list MUST be checked off. Failure to do so will result in a bad rating for you.
diff --git a/chatmodes/debug.chatmode.md b/chatmodes/debug.chatmode.md
index 098fa074..199a0c63 100644
--- a/chatmodes/debug.chatmode.md
+++ b/chatmodes/debug.chatmode.md
@@ -1,5 +1,5 @@
---
-description: Debug your application to find and fix a bug
+description: 'Debug your application to find and fix a bug'
tools: ['codebase', 'readFiles', 'editFiles', 'githubRepo', 'runCommands', 'fetch', 'search', 'usages', 'findTestFiles', 'get_errors', 'test_failure', 'run_in_terminal', 'get_terminal_output']
---
diff --git a/chatmodes/planner.chatmode.md b/chatmodes/planner.chatmode.md
index eaa1bfb9..baf3afb8 100644
--- a/chatmodes/planner.chatmode.md
+++ b/chatmodes/planner.chatmode.md
@@ -1,5 +1,5 @@
---
-description: Generate an implementation plan for new features or refactoring existing code.
+description: 'Generate an implementation plan for new features or refactoring existing code.'
tools: ['codebase', 'fetch', 'findTestFiles', 'githubRepo', 'search', 'usages']
---
# Planning mode instructions
@@ -11,4 +11,4 @@ The plan consists of a Markdown document that describes the implementation plan,
* Overview: A brief description of the feature or refactoring task.
* Requirements: A list of requirements for the feature or refactoring task.
* Implementation Steps: A detailed list of steps to implement the feature or refactoring task.
-* Testing: A list of tests that need to be implemented to verify the feature or refactoring task.
\ No newline at end of file
+* Testing: A list of tests that need to be implemented to verify the feature or refactoring task.
diff --git a/chatmodes/PostgreSQL DBA.chatmode.md b/chatmodes/postgresql-dba.chatmode.md
similarity index 51%
rename from chatmodes/PostgreSQL DBA.chatmode.md
rename to chatmodes/postgresql-dba.chatmode.md
index e43766ee..be3a399d 100644
--- a/chatmodes/PostgreSQL DBA.chatmode.md
+++ b/chatmodes/postgresql-dba.chatmode.md
@@ -1,9 +1,11 @@
---
description: 'Work with PostgreSQL databases using the PostgreSQL extension.'
-tools: ['codebase', 'editFiles', 'githubRepo', 'runCommands', 'database', 'pgsql_bulkLoadCsv', 'pgsql_connect', 'pgsql_describeCsv', 'pgsql_disconnect', 'pgsql_listDatabases', 'pgsql_listServers', 'pgsql_modifyDatabase', 'pgsql_open_script', 'pgsql_query', 'pgsql_visualizeSchema']
+tools: ['codebase', 'editFiles', 'githubRepo', 'extensions', 'runCommands', 'database', 'pgsql_bulkLoadCsv', 'pgsql_connect', 'pgsql_describeCsv', 'pgsql_disconnect', 'pgsql_listDatabases', 'pgsql_listServers', 'pgsql_modifyDatabase', 'pgsql_open_script', 'pgsql_query', 'pgsql_visualizeSchema']
---
-# Database Administrator Chat Mode
+# PostgreSQL Database Administrator
+
+Before running any tools, use #extensions to ensure that `ms-ossdata.vscode-pgsql` is installed and enabled. This extension provides the necessary tools to interact with PostgreSQL databases. If it is not installed, ask the user to install it before continuing.
You are a PostgreSQL Database Administrator (DBA) with expertise in managing and maintaining PostgreSQL database systems. You can perform tasks such as:
- Creating and managing databases
diff --git a/instructions/angular.md b/instructions/angular.instructions.md
similarity index 97%
rename from instructions/angular.md
rename to instructions/angular.instructions.md
index 654c3dab..b80f434a 100644
--- a/instructions/angular.md
+++ b/instructions/angular.instructions.md
@@ -1,6 +1,6 @@
---
-description: |
- Angular-specific coding standards and best practices
+description: 'Angular-specific coding standards and best practices'
+applyTo: '**/*.ts, **/*.html, **/*.scss, **/*.css'
---
# Angular Development Instructions
diff --git a/instructions/aspnet-rest-apis.md b/instructions/aspnet-rest-apis.instructions.md
similarity index 98%
rename from instructions/aspnet-rest-apis.md
rename to instructions/aspnet-rest-apis.instructions.md
index 9981e7be..c550ae38 100644
--- a/instructions/aspnet-rest-apis.md
+++ b/instructions/aspnet-rest-apis.instructions.md
@@ -1,5 +1,6 @@
---
-description: Guidelines for building REST APIs with ASP.NET
+description: 'Guidelines for building REST APIs with ASP.NET'
+applyTo: '**/*.cs, **/*.json'
---
# ASP.NET REST API Development
diff --git a/instructions/azure-functions-typescript.md b/instructions/azure-functions-typescript.instructions.md
similarity index 81%
rename from instructions/azure-functions-typescript.md
rename to instructions/azure-functions-typescript.instructions.md
index 0c2c4a5e..2e5c3424 100644
--- a/instructions/azure-functions-typescript.md
+++ b/instructions/azure-functions-typescript.instructions.md
@@ -1,5 +1,6 @@
---
-description: TypeScript patterns for Azure Functions
+description: 'TypeScript patterns for Azure Functions'
+applyTo: '**/*.ts, **/*.js, **/*.json'
---
## Guidance for Code Generation
@@ -10,4 +11,4 @@ description: TypeScript patterns for Azure Functions
- Ask before adding any extra dependencies to the project
- The API is built using Azure Functions using `@azure/functions@4` package.
- Each endpoint should have its own function file, and use the following naming convention: `src/functions/-.ts`
-- When making changes to the API, make sure to update the OpenAPI schema (if it exists) and `README.md` file accordingly.
\ No newline at end of file
+- When making changes to the API, make sure to update the OpenAPI schema (if it exists) and `README.md` file accordingly.
diff --git a/instructions/bicep-code-best-practices.md b/instructions/bicep-code-best-practices.instructions.md
similarity index 96%
rename from instructions/bicep-code-best-practices.md
rename to instructions/bicep-code-best-practices.instructions.md
index 32e948f4..d6a9a32f 100644
--- a/instructions/bicep-code-best-practices.md
+++ b/instructions/bicep-code-best-practices.instructions.md
@@ -1,6 +1,6 @@
---
-description: Infrastructure as Code with Bicep
-applyTo: "**/*.bicep"
+description: 'Infrastructure as Code with Bicep'
+applyTo: '**/*.bicep'
---
## Naming Conventions
diff --git a/instructions/blazor.md b/instructions/blazor.instructions.md
similarity index 97%
rename from instructions/blazor.md
rename to instructions/blazor.instructions.md
index 113b924d..5113943c 100644
--- a/instructions/blazor.md
+++ b/instructions/blazor.instructions.md
@@ -1,6 +1,6 @@
---
-description: Blazor component and application patterns
-applyTo: "**/*.razor, **/*.razor.cs, **/*.razor.css"
+description: 'Blazor component and application patterns'
+applyTo: '**/*.razor, **/*.razor.cs, **/*.razor.css'
---
## Blazor Code Style and Structure
diff --git a/instructions/cmake-vcpkg.md b/instructions/cmake-vcpkg.instructions.md
similarity index 84%
rename from instructions/cmake-vcpkg.md
rename to instructions/cmake-vcpkg.instructions.md
index 2e10e979..95b64ae3 100644
--- a/instructions/cmake-vcpkg.md
+++ b/instructions/cmake-vcpkg.instructions.md
@@ -1,5 +1,6 @@
---
-description: C++ project configuration and package management
+description: 'C++ project configuration and package management'
+applyTo: '**/*.cmake, **/CMakeLists.txt, **/*.cpp, **/*.h, **/*.hpp'
---
This project uses vcpkg in manifest mode. Please keep this in mind when giving vcpkg suggestions. Do not provide suggestions like vcpkg install library, as they will not work as expected.
diff --git a/instructions/copilot-thought-logging.instructions.md b/instructions/copilot-thought-logging.instructions.md
index 1a69ab8f..8377784c 100644
--- a/instructions/copilot-thought-logging.instructions.md
+++ b/instructions/copilot-thought-logging.instructions.md
@@ -1,6 +1,5 @@
---
applyTo: '**'
-mode: "agent"
description: 'See process Copilot is following where you can edit this to reshape the interaction or save when follow up may be needed'
---
@@ -60,4 +59,4 @@ description: 'See process Copilot is following where you can edit this to reshap
- NEVER continue past current phase without user input
- If you catch yourself being verbose, STOP and provide only required output
- If you catch yourself about to skip a phase, STOP and go back to the correct phase
-- If you catch yourself combining phases, STOP and perform only the current phase
\ No newline at end of file
+- If you catch yourself combining phases, STOP and perform only the current phase
diff --git a/instructions/csharp.md b/instructions/csharp.instructions.md
similarity index 98%
rename from instructions/csharp.md
rename to instructions/csharp.instructions.md
index c12d7aa1..5ee3b352 100644
--- a/instructions/csharp.md
+++ b/instructions/csharp.instructions.md
@@ -1,5 +1,6 @@
---
-description: Guidelines for building C# applications
+description: 'Guidelines for building C# applications'
+applyTo: '**/*.cs'
---
# C# Development
diff --git a/instructions/dotnet-maui.md b/instructions/dotnet-maui.instructions.md
similarity index 83%
rename from instructions/dotnet-maui.md
rename to instructions/dotnet-maui.instructions.md
index e5e7e419..c6848f43 100644
--- a/instructions/dotnet-maui.md
+++ b/instructions/dotnet-maui.instructions.md
@@ -1,12 +1,14 @@
---
-description: MAUI component and application patterns
-appliesTo: "**/*.xaml, **/*.cs"
+description: '.NET MAUI component and application patterns'
+applyTo: '**/*.xaml, **/*.cs'
---
-## MAUI Code Style and Structure
+# .NET MAUI
-- Write idiomatic and efficient MAUI and C# code.
-- Follow .NET and MAUI conventions.
+## .NET MAUI Code Style and Structure
+
+- Write idiomatic and efficient .NET MAUI and C# code.
+- Follow .NET and .NET MAUI conventions.
- Prefer inline functions for smaller components but separate complex logic into code-behind or service classes.
- Async/await should be used where applicable to ensure non-blocking UI operations.
@@ -16,16 +18,16 @@ appliesTo: "**/*.xaml, **/*.cs"
- Use camelCase for private fields and local variables.
- Prefix interface names with "I" (e.g., IUserService).
-## MAUI and .NET Specific Guidelines
+## .NET MAUI and .NET Specific Guidelines
-- Utilize MAUI's built-in features for component lifecycle (e.g. OnAppearing, OnDisappearing).
+- Utilize .NET MAUI's built-in features for component lifecycle (e.g. OnAppearing, OnDisappearing).
- Use data binding effectively with {Binding}.
-- Structure MAUI components and services following Separation of Concerns.
+- Structure .NET MAUI components and services following Separation of Concerns.
- Always use the latest version C#, currently C# 13 features like record types, pattern matching, and global usings.
## Error Handling and Validation
-- Implement proper error handling for MAUI pages and API calls.
+- Implement proper error handling for .NET MAUI pages and API calls.
- Use logging for error tracking in the backend and consider capturing UI-level errors in MAUI with tools like MAUI Community Toolkit's Logger.
- Implement validation using FluentValidation or DataAnnotations in forms.
diff --git a/instructions/genaiscript.md b/instructions/genaiscript.instructions.md
similarity index 90%
rename from instructions/genaiscript.md
rename to instructions/genaiscript.instructions.md
index 7a14eeb2..fa753c28 100644
--- a/instructions/genaiscript.md
+++ b/instructions/genaiscript.instructions.md
@@ -1,6 +1,6 @@
---
-applyTo: "**/*.genai.*"
-description: AI-powered script generation guidelines
+description: 'AI-powered script generation guidelines'
+applyTo: '**/*.genai.*'
---
## Role
diff --git a/instructions/generate-modern-terraform-code-for-azure.md b/instructions/generate-modern-terraform-code-for-azure.instructions.md
similarity index 95%
rename from instructions/generate-modern-terraform-code-for-azure.md
rename to instructions/generate-modern-terraform-code-for-azure.instructions.md
index 71e1a220..622b47dd 100644
--- a/instructions/generate-modern-terraform-code-for-azure.md
+++ b/instructions/generate-modern-terraform-code-for-azure.instructions.md
@@ -1,6 +1,6 @@
---
-description: Guidelines for generating modern Terraform code for Azure
-applyTo: "**/*.tf"
+description: 'Guidelines for generating modern Terraform code for Azure'
+applyTo: '**/*.tf'
---
## 1. Use Latest Terraform and Providers
@@ -79,4 +79,4 @@ Use Terraform modules to group reusable infrastructure components. For any resou
- **Consider implementing automated checks**:
- CI pipeline
- Pre-commit hooks
- - Enforce formatting, linting, and basic validation
\ No newline at end of file
+ - Enforce formatting, linting, and basic validation
diff --git a/instructions/localization.md b/instructions/localization.instructions.md
similarity index 95%
rename from instructions/localization.md
rename to instructions/localization.instructions.md
index 0fbac957..e7d3d35e 100644
--- a/instructions/localization.md
+++ b/instructions/localization.instructions.md
@@ -1,6 +1,6 @@
---
-description: Guidelines for localizing markdown documents
-applyTo: "**/*.md"
+description: 'Guidelines for localizing markdown documents'
+applyTo: '**/*.md'
---
# Guidance for Localization
diff --git a/instructions/markdown.md b/instructions/markdown.instructions.md
similarity index 97%
rename from instructions/markdown.md
rename to instructions/markdown.instructions.md
index d11c76b6..724815d0 100644
--- a/instructions/markdown.md
+++ b/instructions/markdown.instructions.md
@@ -1,6 +1,6 @@
---
-description: Documentation and content creation standards
-applyTo: "**/*.md"
+description: 'Documentation and content creation standards'
+applyTo: '**/*.md'
---
## Markdown Content Rules
diff --git a/instructions/nextjs-tailwind.md b/instructions/nextjs-tailwind.instructions.md
similarity index 92%
rename from instructions/nextjs-tailwind.md
rename to instructions/nextjs-tailwind.instructions.md
index 36d56b8e..ffc43781 100644
--- a/instructions/nextjs-tailwind.md
+++ b/instructions/nextjs-tailwind.instructions.md
@@ -1,5 +1,6 @@
---
-description: Next.js + Tailwind development standards and instructions
+description: 'Next.js + Tailwind development standards and instructions'
+applyTo: '**/*.tsx, **/*.ts, **/*.jsx, **/*.js, **/*.css'
---
# Next.js + Tailwind Development Instructions
@@ -68,4 +69,4 @@ Instructions for high-quality Next.js applications with Tailwind CSS styling and
5. Add proper error handling
6. Implement responsive styling
7. Add loading states
-8. Write tests
\ No newline at end of file
+8. Write tests
diff --git a/instructions/python.md b/instructions/python.instructions.md
similarity index 96%
rename from instructions/python.md
rename to instructions/python.instructions.md
index 96350435..a783f424 100644
--- a/instructions/python.md
+++ b/instructions/python.instructions.md
@@ -1,5 +1,6 @@
---
-description: Python coding conventions and guidelines
+description: 'Python coding conventions and guidelines'
+applyTo: '**/*.py'
---
# Python Coding Conventions
@@ -52,4 +53,4 @@ def calculate_area(radius: float) -> float:
"""
import math
return math.pi * radius ** 2
-```
\ No newline at end of file
+```
diff --git a/prompts/aspnet-minimal-api-openapi.prompt.md b/prompts/aspnet-minimal-api-openapi.prompt.md
index 007157dd..1cfa5389 100644
--- a/prompts/aspnet-minimal-api-openapi.prompt.md
+++ b/prompts/aspnet-minimal-api-openapi.prompt.md
@@ -1,9 +1,11 @@
---
-mode: "agent"
-tools: ["changes", "codebase", "editFiles", "problems"]
-description: "Create ASP.NET Minimal API endpoints with proper OpenAPI documentation"
+mode: 'agent'
+tools: ['changes', 'codebase', 'editFiles', 'problems']
+description: 'Create ASP.NET Minimal API endpoints with proper OpenAPI documentation'
---
+# ASP.NET Minimal API with OpenAPI
+
Your goal is to help me create well-structured ASP.NET Minimal API endpoints with correct types and comprehensive OpenAPI/Swagger documentation.
## API Organization
diff --git a/prompts/az-cost-optimize.prompt.md b/prompts/az-cost-optimize.prompt.md
index 546bda5b..c780f5f7 100644
--- a/prompts/az-cost-optimize.prompt.md
+++ b/prompts/az-cost-optimize.prompt.md
@@ -1,9 +1,10 @@
---
-mode: agent
-description: Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations.
+mode: 'agent'
+description: 'Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations.'
---
-## Overview
+# Azure Cost Optimize
+
This workflow analyzes Infrastructure-as-Code (IaC) files and Azure resources to generate cost optimization recommendations. It creates individual GitHub issues for each optimization opportunity plus one EPIC issue to coordinate implementation, enabling efficient tracking and execution of cost savings initiatives.
## Prerequisites
@@ -301,4 +302,4 @@ This workflow analyzes Infrastructure-as-Code (IaC) files and Azure resources to
- β
All recommendations include specific, executable Azure CLI commands
- β
Priority scoring enables ROI-focused implementation
- β
Architecture diagram accurately represents current state
-- β
User confirmation prevents unwanted issue creation
\ No newline at end of file
+- β
User confirmation prevents unwanted issue creation
diff --git a/prompts/comment-code-generate-a-tutorial.prompt.md b/prompts/comment-code-generate-a-tutorial.prompt.md
index 2b590d22..0d949c24 100644
--- a/prompts/comment-code-generate-a-tutorial.prompt.md
+++ b/prompts/comment-code-generate-a-tutorial.prompt.md
@@ -1,3 +1,7 @@
+---
+description: 'Transform this Python script into a polished, beginner-friendly project by refactoring the code, adding clear instructional comments, and generating a complete markdown tutorial.'
+---
+
Transform this Python script into a polished, beginner-friendly project by refactoring the code, adding clear instructional comments, and generating a complete markdown tutorial.
1. **Refactor the code**
@@ -18,4 +22,4 @@ Transform this Python script into a polished, beginner-friendly project by refac
- **How It Works:** A breakdown of the code logic based on the comments
- **Example Usage:** A code snippet showing how to use it
- **Sample Output:** (Optional) Include if the script returns visible results
- - Use clear, readable Markdown formatting
\ No newline at end of file
+ - Use clear, readable Markdown formatting
diff --git a/prompts/csharp-async.prompt.md b/prompts/csharp-async.prompt.md
index 3c614970..5ce18834 100644
--- a/prompts/csharp-async.prompt.md
+++ b/prompts/csharp-async.prompt.md
@@ -1,7 +1,7 @@
---
-mode: "agent"
-tools: ["changes", "codebase", "editFiles", "problems"]
-description: "Get best practices for C# async programming"
+mode: 'agent'
+tools: ['changes', 'codebase', 'editFiles', 'problems']
+description: 'Get best practices for C# async programming'
---
# C# Async Programming Best Practices
diff --git a/prompts/csharp-docs.prompt.md b/prompts/csharp-docs.prompt.md
index 39b672ab..9523cd23 100644
--- a/prompts/csharp-docs.prompt.md
+++ b/prompts/csharp-docs.prompt.md
@@ -1,7 +1,7 @@
---
-mode: "agent"
-tools: ["changes", "codebase", "editFiles", "problems"]
-description: "Ensure that C# types are documented with XML comments and follow best practices for documentation."
+mode: 'agent'
+tools: ['changes', 'codebase', 'editFiles', 'problems']
+description: 'Ensure that C# types are documented with XML comments and follow best practices for documentation.'
---
# C# Documentation Best Practices
diff --git a/prompts/csharp-mstest.prompt.md b/prompts/csharp-mstest.prompt.md
index f4ec8b33..4d096cc5 100644
--- a/prompts/csharp-mstest.prompt.md
+++ b/prompts/csharp-mstest.prompt.md
@@ -1,7 +1,7 @@
---
-mode: "agent"
-tools: ["changes", "codebase", "editFiles", "problems", "search"]
-description: "Get best practices for MSTest unit testing, including data-driven tests"
+mode: 'agent'
+tools: ['changes', 'codebase', 'editFiles', 'problems', 'search']
+description: 'Get best practices for MSTest unit testing, including data-driven tests'
---
# MSTest Best Practices
@@ -65,4 +65,4 @@ Your goal is to help me write effective unit tests with MSTest, covering both st
* Group tests by feature or component
* Use test categories with `[TestCategory("Category")]`
* Use test priorities with `[Priority(1)]` for critical tests
-* Use `[Owner("DeveloperName")]` to indicate ownership
\ No newline at end of file
+* Use `[Owner("DeveloperName")]` to indicate ownership
diff --git a/prompts/csharp-nunit.prompt.md b/prompts/csharp-nunit.prompt.md
index e266975b..cdabee7b 100644
--- a/prompts/csharp-nunit.prompt.md
+++ b/prompts/csharp-nunit.prompt.md
@@ -1,7 +1,7 @@
---
-mode: "agent"
-tools: ["changes", "codebase", "editFiles", "problems", "search"]
-description: "Get best practices for NUnit unit testing, including data-driven tests"
+mode: 'agent'
+tools: ['changes', 'codebase', 'editFiles', 'problems', 'search']
+description: 'Get best practices for NUnit unit testing, including data-driven tests'
---
# NUnit Best Practices
diff --git a/prompts/csharp-xunit.prompt.md b/prompts/csharp-xunit.prompt.md
index 50b64096..a5b80ece 100644
--- a/prompts/csharp-xunit.prompt.md
+++ b/prompts/csharp-xunit.prompt.md
@@ -1,7 +1,7 @@
---
-mode: "agent"
-tools: ["changes", "codebase", "editFiles", "problems", "search"]
-description: "Get best practices for XUnit unit testing, including data-driven tests"
+mode: 'agent'
+tools: ['changes', 'codebase', 'editFiles', 'problems', 'search']
+description: 'Get best practices for XUnit unit testing, including data-driven tests'
---
# XUnit Best Practices
diff --git a/prompts/ef-core.prompt.md b/prompts/ef-core.prompt.md
index 3ad63507..5ae7a22c 100644
--- a/prompts/ef-core.prompt.md
+++ b/prompts/ef-core.prompt.md
@@ -1,7 +1,7 @@
---
-mode: "agent"
-tools: ["changes", "codebase", "editFiles", "problems", "runCommands"]
-description: "Get best practices for Entity Framework Core"
+mode: 'agent'
+tools: ['changes', 'codebase', 'editFiles', 'problems', 'runCommands']
+description: 'Get best practices for Entity Framework Core'
---
# Entity Framework Core Best Practices
diff --git a/prompts/gen-specs-as-issues.prompt.md b/prompts/gen-specs-as-issues.prompt.md
index ac32f0e7..772b42f5 100644
--- a/prompts/gen-specs-as-issues.prompt.md
+++ b/prompts/gen-specs-as-issues.prompt.md
@@ -1,3 +1,7 @@
+---
+description: 'This workflow guides you through a systematic approach to identify missing features, prioritize them, and create detailed specifications for implementation.'
+---
+
# Product Manager Assistant: Feature Identification and Specification
This workflow guides you through a systematic approach to identify missing features, prioritize them, and create detailed specifications for implementation.
@@ -157,4 +161,4 @@ Remember throughout this process:
- Build a foundation that can be extended later
- Consider the open-source community and contribution model
-This workflow embodiment of our approach should help maintain consistency in how features are specified and prioritized, ensuring that software projects evolve in a thoughtful, user-centered way.
\ No newline at end of file
+This workflow embodiment of our approach should help maintain consistency in how features are specified and prioritized, ensuring that software projects evolve in a thoughtful, user-centered way.
diff --git a/prompts/javascript-typescript-jest.prompt.md b/prompts/javascript-typescript-jest.prompt.md
index f1580677..5aa8ce10 100644
--- a/prompts/javascript-typescript-jest.prompt.md
+++ b/prompts/javascript-typescript-jest.prompt.md
@@ -1,5 +1,5 @@
---
-description: "Best practices for writing JavaScript/TypeScript tests using Jest, including mocking strategies, test structure, and common patterns."
+description: 'Best practices for writing JavaScript/TypeScript tests using Jest, including mocking strategies, test structure, and common patterns.'
---
### Test Structure
diff --git a/prompts/multi-stage-dockerfile.prompt.md b/prompts/multi-stage-dockerfile.prompt.md
index 47d988cb..0d4a47f4 100644
--- a/prompts/multi-stage-dockerfile.prompt.md
+++ b/prompts/multi-stage-dockerfile.prompt.md
@@ -1,7 +1,7 @@
---
-mode: "agent"
-tools: ["codebase"]
-description: "Create optimized multi-stage Dockerfiles for any language or framework"
+mode: 'agent'
+tools: ['codebase']
+description: 'Create optimized multi-stage Dockerfiles for any language or framework'
---
Your goal is to help me create efficient multi-stage Dockerfiles that follow best practices, resulting in smaller, more secure container images.
diff --git a/prompts/my-issues.prompt.md b/prompts/my-issues.prompt.md
index 55860771..113c77fb 100644
--- a/prompts/my-issues.prompt.md
+++ b/prompts/my-issues.prompt.md
@@ -1,7 +1,7 @@
---
-mode: agent
+mode: 'agent'
tools: ['githubRepo', 'github', 'get_issue', 'get_issue_comments', 'get_me', 'list_issues']
-description: "List my issues in the current repository"
+description: 'List my issues in the current repository'
---
Search the current repo (using #githubRepo for the repo info) and list any issues you find (using #list_issues) that are assigned to me.
diff --git a/prompts/my-pull-requests.prompt.md b/prompts/my-pull-requests.prompt.md
index 3a83c399..25b8d755 100644
--- a/prompts/my-pull-requests.prompt.md
+++ b/prompts/my-pull-requests.prompt.md
@@ -1,7 +1,7 @@
---
-mode: agent
+mode: 'agent'
tools: ['githubRepo', 'github', 'get_me', 'get_pull_request', 'get_pull_request_comments', 'get_pull_request_diff', 'get_pull_request_files', 'get_pull_request_reviews', 'get_pull_request_status', 'list_pull_requests', 'request_copilot_review']
-description: "List my pull requests in the current repository"
+description: 'List my pull requests in the current repository'
---
Search the current repo (using #githubRepo for the repo info) and list any pull requests you find (using #list_pull_requests) that are assigned to me.
@@ -12,4 +12,4 @@ If a PR is waiting for someone to review, highlight that in the response.
If there were any check failures on the PR, describe them and suggest possible fixes.
-If there was no review done by Copilot, offer to request one using #request_copilot_review.
\ No newline at end of file
+If there was no review done by Copilot, offer to request one using #request_copilot_review.
diff --git a/update-readme.js b/update-readme.js
index 27c314f2..144d8736 100755
--- a/update-readme.js
+++ b/update-readme.js
@@ -3,191 +3,260 @@
const fs = require("fs");
const path = require("path");
-function extractTitle(filePath) {
+// Template sections for the README
+const TEMPLATES = {
+ header: `# π€ Awesome GitHub Copilot Customizations
+
+Enhance your GitHub Copilot experience with community-contributed instructions, prompts, and configurations. Get consistent AI assistance that follows your team's coding standards and project requirements.
+
+## π― GitHub Copilot Customization Features
+
+GitHub Copilot provides three main ways to customize AI responses and tailor assistance to your specific workflows, team guidelines, and project requirements:
+
+| **π§ Custom Instructions** | **π Reusable Prompts** | **π§© Custom Chat Modes** |
+| --- | --- | --- |
+| Define common guidelines for tasks like code generation, reviews, and commit messages. Describe *how* tasks should be performed
**Benefits:**
β’ Automatic inclusion in every chat request
β’ Repository-wide consistency
β’ Multiple implementation options | Create reusable, standalone prompts for specific tasks. Describe *what* should be done with optional task-specific guidelines
**Benefits:**
β’ Eliminate repetitive prompt writing
β’ Shareable across teams
β’ Support for variables and dependencies | Define chat behavior, available tools, and codebase interaction patterns within specific boundaries for each request
**Benefits:**
β’ Context-aware assistance
β’ Tool configuration
β’ Role-specific workflows |
+
+> **π‘ Pro Tip:** Custom instructions only affect Copilot Chat (not inline code completions). You can combine all three customization types - use custom instructions for general guidelines, prompt files for specific tasks, and chat modes to control the interaction context.
+
+
+## π Contributing
+
+We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details on how to submit new instructions and prompts.`,
+
+ instructionsSection: `## π Custom Instructions
+
+Team and project-specific instructions to enhance GitHub Copilot's behavior for specific technologies and coding practices:`,
+
+ instructionsUsage: `> π‘ **Usage**: Copy these instructions to your \`.github/copilot-instructions.md\` file or create task-specific \`.github/.instructions.md\` files in your workspace's \`.github/instructions\` folder.`,
+
+ promptsSection: `## π― Reusable Prompts
+
+Ready-to-use prompt templates for specific development scenarios and tasks, defining prompt text with a specific mode, model, and available set of tools.`,
+
+ promptsUsage: `> π‘ **Usage**: Use \`/prompt-name\` in VS Code chat, run \`Chat: Run Prompt\` command, or hit the run button while you have a prompt open.`,
+
+ chatmodesSection: `## π§© Custom Chat Modes
+
+Custom chat modes define specific behaviors and tools for GitHub Copilot Chat, enabling enhanced context-aware assistance for particular tasks or workflows.`,
+
+ chatmodesUsage: `> π‘ **Usage**: Create new chat modes using the command \`Chat: Configure Chat Modes...\`, then switch your chat mode in the Chat input from _Agent_ or _Ask_ to your own mode.`,
+
+ footer: `## π Additional Resources
+
+- [VS Code Copilot Customization Documentation](https://code.visualstudio.com/docs/copilot/copilot-customization) - Official Microsoft documentation
+- [GitHub Copilot Chat Documentation](https://code.visualstudio.com/docs/copilot/chat/copilot-chat) - Complete chat feature guide
+- [Custom Chat Modes](https://code.visualstudio.com/docs/copilot/chat/chat-modes) - Advanced chat configuration
+- [VS Code Settings](https://code.visualstudio.com/docs/getstarted/settings) - General VS Code configuration guide
+
+
+## π License
+
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+
+## π€ Code of Conduct
+
+Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
+
+## β’οΈ Trademarks
+
+This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
+trademarks or logos is subject to and must follow
+[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
+Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
+Any use of third-party trademarks or logos are subject to those third-party's policies.`,
+};
+
+// Add error handling utility
+function safeFileOperation(operation, filePath, defaultValue = null) {
try {
- const content = fs.readFileSync(filePath, "utf8");
- const lines = content.split("\n");
-
- // Step 1: Look for title in frontmatter for all file types
- let inFrontmatter = false;
- let frontmatterEnded = false;
-
- for (const line of lines) {
- if (line.trim() === "---") {
- if (!inFrontmatter) {
- inFrontmatter = true;
- } else if (!frontmatterEnded) {
- frontmatterEnded = true;
- }
- continue;
- }
+ return operation();
+ } catch (error) {
+ console.error(`Error processing file ${filePath}: ${error.message}`);
+ return defaultValue;
+ }
+}
- if (inFrontmatter && !frontmatterEnded) {
- // Look for title field in frontmatter
- const titleMatch = line.match(/^title:\s*['"]?(.+?)['"]?$/);
- if (titleMatch) {
- return titleMatch[1].trim();
- }
- }
- }
+function extractTitle(filePath) {
+ return safeFileOperation(
+ () => {
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n");
- // Reset for second pass
- inFrontmatter = false;
- frontmatterEnded = false;
+ // Step 1: Look for title in frontmatter for all file types
+ let inFrontmatter = false;
+ let frontmatterEnded = false;
- // Step 2: For prompt/chatmode files, look for heading after frontmatter
- if (filePath.includes(".prompt.md") || filePath.includes(".chatmode.md")) {
for (const line of lines) {
if (line.trim() === "---") {
if (!inFrontmatter) {
inFrontmatter = true;
- } else if (inFrontmatter && !frontmatterEnded) {
+ } else if (!frontmatterEnded) {
frontmatterEnded = true;
}
continue;
}
- if (frontmatterEnded && line.startsWith("# ")) {
+ if (inFrontmatter && !frontmatterEnded) {
+ // Look for title field in frontmatter
+ if (line.includes("title:")) {
+ // Extract everything after 'title:'
+ const afterTitle = line
+ .substring(line.indexOf("title:") + 6)
+ .trim();
+ // Remove quotes if present
+ const cleanTitle = afterTitle.replace(/^['"]|['"]$/g, "");
+ return cleanTitle;
+ }
+ }
+ }
+
+ // Reset for second pass
+ inFrontmatter = false;
+ frontmatterEnded = false;
+
+ // Step 2: For prompt/chatmode/instructions files, look for heading after frontmatter
+ if (
+ filePath.includes(".prompt.md") ||
+ filePath.includes(".chatmode.md") ||
+ filePath.includes(".instructions.md")
+ ) {
+ for (const line of lines) {
+ if (line.trim() === "---") {
+ if (!inFrontmatter) {
+ inFrontmatter = true;
+ } else if (inFrontmatter && !frontmatterEnded) {
+ frontmatterEnded = true;
+ }
+ continue;
+ }
+
+ if (frontmatterEnded && line.startsWith("# ")) {
+ return line.substring(2).trim();
+ }
+ }
+
+ // Step 3: Format filename for prompt/chatmode/instructions files if no heading found
+ const basename = path.basename(
+ filePath,
+ filePath.includes(".prompt.md")
+ ? ".prompt.md"
+ : filePath.includes(".chatmode.md")
+ ? ".chatmode.md"
+ : ".instructions.md"
+ );
+ return basename
+ .replace(/[-_]/g, " ")
+ .replace(/\b\w/g, (l) => l.toUpperCase());
+ }
+
+ // Step 4: For instruction files, look for the first heading
+ for (const line of lines) {
+ if (line.startsWith("# ")) {
return line.substring(2).trim();
}
}
- // Step 3: Format filename for prompt/chatmode files if no heading found
- const basename = path.basename(
- filePath,
- filePath.includes(".prompt.md") ? ".prompt.md" : ".chatmode.md"
- );
+ // Step 5: Fallback to filename
+ const basename = path.basename(filePath, path.extname(filePath));
return basename
.replace(/[-_]/g, " ")
.replace(/\b\w/g, (l) => l.toUpperCase());
- }
-
- // Step 4: For instruction files, look for the first heading
- for (const line of lines) {
- if (line.startsWith("# ")) {
- return line.substring(2).trim();
- }
- }
-
- // Step 5: Fallback to filename
- const basename = path.basename(filePath, path.extname(filePath));
- return basename
- .replace(/[-_]/g, " ")
- .replace(/\b\w/g, (l) => l.toUpperCase());
- } catch (error) {
- // Fallback to filename
- const basename = path.basename(filePath, path.extname(filePath));
- return basename
+ },
+ filePath,
+ path
+ .basename(filePath, path.extname(filePath))
.replace(/[-_]/g, " ")
- .replace(/\b\w/g, (l) => l.toUpperCase());
- }
+ .replace(/\b\w/g, (l) => l.toUpperCase())
+ );
}
function extractDescription(filePath) {
- try {
- const content = fs.readFileSync(filePath, "utf8");
-
- // Parse frontmatter for description (for both prompts and instructions)
- const lines = content.split("\n");
- let inFrontmatter = false;
- let frontmatterEnded = false;
-
- // For multi-line descriptions
- let isMultilineDescription = false;
- let multilineDescription = [];
-
- for (let i = 0; i < lines.length; i++) {
- const line = lines[i];
-
- if (line.trim() === "---") {
- if (!inFrontmatter) {
- inFrontmatter = true;
- } else if (inFrontmatter && !frontmatterEnded) {
- frontmatterEnded = true;
- break;
- }
- continue;
- }
+ return safeFileOperation(
+ () => {
+ const content = fs.readFileSync(filePath, "utf8");
+
+ // Parse frontmatter for description (for both prompts and instructions)
+ const lines = content.split("\n");
+ let inFrontmatter = false;
+ let frontmatterEnded = false;
+
+ // For multi-line descriptions
+ let isMultilineDescription = false;
+ let multilineDescription = [];
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
- if (inFrontmatter && !frontmatterEnded) {
- // Check for multi-line description with pipe syntax (|)
- const multilineMatch = line.match(/^description:\s*\|(\s*)$/);
- if (multilineMatch) {
- isMultilineDescription = true;
- // Continue to next line to start collecting the multi-line content
+ if (line.trim() === "---") {
+ if (!inFrontmatter) {
+ inFrontmatter = true;
+ } else if (inFrontmatter && !frontmatterEnded) {
+ frontmatterEnded = true;
+ break;
+ }
continue;
}
- // If we're collecting a multi-line description
- if (isMultilineDescription) {
- // If the line has no indentation or has another frontmatter key, stop collecting
- if (!line.startsWith(" ") || line.match(/^[a-zA-Z0-9_-]+:/)) {
- isMultilineDescription = false;
- // Join the collected lines and return
- return multilineDescription.join(" ").trim();
+ if (inFrontmatter && !frontmatterEnded) {
+ // Check for multi-line description with pipe syntax (|)
+ const multilineMatch = line.match(/^description:\s*\|(\s*)$/);
+ if (multilineMatch) {
+ isMultilineDescription = true;
+ // Continue to next line to start collecting the multi-line content
+ continue;
}
- // Add the line to our multi-line collection (removing the 2-space indentation)
- multilineDescription.push(line.substring(2));
- } else {
- // Look for single-line description field in frontmatter
- const descriptionMatch = line.match(
- /^description:\s*['"]?(.+?)['"]?$/
- );
- if (descriptionMatch) {
- return descriptionMatch[1];
+ // If we're collecting a multi-line description
+ if (isMultilineDescription) {
+ // If the line has no indentation or has another frontmatter key, stop collecting
+ if (!line.startsWith(" ") || line.match(/^[a-zA-Z0-9_-]+:/)) {
+ isMultilineDescription = false;
+ // Join the collected lines and return
+ return multilineDescription.join(" ").trim();
+ }
+
+ // Add the line to our multi-line collection (removing the 2-space indentation)
+ multilineDescription.push(line.substring(2));
+ } else {
+ // Look for single-line description field in frontmatter
+ const descriptionMatch = line.match(
+ /^description:\s*['"]?(.+?)['"]?$/
+ );
+ if (descriptionMatch) {
+ return descriptionMatch[1];
+ }
}
}
}
- }
- // If we've collected multi-line description but the frontmatter ended
- if (multilineDescription.length > 0) {
- return multilineDescription.join(" ").trim();
- }
-
- return null;
- } catch (error) {
- return null;
- }
-}
+ // If we've collected multi-line description but the frontmatter ended
+ if (multilineDescription.length > 0) {
+ return multilineDescription.join(" ").trim();
+ }
-function updateInstructionsSection(
- currentReadme,
- instructionFiles,
- instructionsDir
-) {
- const instructionsSection = currentReadme.match(
- /## π Custom Instructions\n\nTeam and project-specific instructions.+?(?=\n\n>)/s
+ return null;
+ },
+ filePath,
+ null
);
+}
- if (!instructionsSection) {
- return currentReadme;
- }
-
- // Extract existing instruction links from README
- const existingInstructionLinks = [];
- const instructionLinkRegex = /\[.*?\]\(instructions\/(.+?)\)/g;
- let match;
-
- while ((match = instructionLinkRegex.exec(currentReadme)) !== null) {
- existingInstructionLinks.push(match[1]);
- }
-
- // Find new instructions that aren't already in the README
- const newInstructionFiles = instructionFiles.filter(
- (file) => !existingInstructionLinks.includes(file)
- );
+/**
+ * Generate the instructions section with an alphabetical list of all instructions
+ */
+function generateInstructionsSection(instructionsDir) {
+ // Get all instruction files
+ const instructionFiles = fs
+ .readdirSync(instructionsDir)
+ .filter((file) => file.endsWith(".md"))
+ .sort();
- if (newInstructionFiles.length === 0) {
- console.log("No new instructions to add.");
- } else {
- console.log(`Found ${newInstructionFiles.length} new instructions to add.`);
- }
+ console.log(`Found ${instructionFiles.length} instruction files`);
- let instructionsListContent = "\n\n";
+ let instructionsContent = "";
- // Generate alphabetically sorted list of instruction links
+ // Generate list items for each instruction file
for (const file of instructionFiles) {
const filePath = path.join(instructionsDir, file);
const title = extractTitle(filePath);
@@ -196,210 +265,100 @@ function updateInstructionsSection(
// Check if there's a description in the frontmatter
const customDescription = extractDescription(filePath);
- if (customDescription) {
+ if (customDescription && customDescription !== "null") {
// Use the description from frontmatter
- instructionsListContent += `- [${title}](${link}) - ${customDescription}\n`;
+ instructionsContent += `- [${title}](${link}) - ${customDescription}\n`;
} else {
// Fallback to the default approach - use last word of title for description, removing trailing 's' if present
const topic = title.split(" ").pop().replace(/s$/, "");
- instructionsListContent += `- [${title}](${link}) - ${topic} specific coding standards and best practices\n`;
+ instructionsContent += `- [${title}](${link}) - ${topic} specific coding standards and best practices\n`;
}
}
- // Replace the current instructions section with the updated one
- const newInstructionsSection =
- "## π Custom Instructions\n\nTeam and project-specific instructions to enhance GitHub Copilot's behavior for specific technologies and coding practices:" +
- instructionsListContent;
-
- return currentReadme.replace(instructionsSection[0], newInstructionsSection);
+ return `${TEMPLATES.instructionsSection}\n\n${instructionsContent}\n${TEMPLATES.instructionsUsage}`;
}
-function updatePromptsSection(currentReadme, promptFiles, promptsDir) {
- // Extract existing prompt links from README
- const existingPromptLinks = [];
- const promptLinkRegex = /\[.*?\]\(prompts\/(.+?)\)/g;
- let match;
-
- while ((match = promptLinkRegex.exec(currentReadme)) !== null) {
- existingPromptLinks.push(match[1]);
- }
-
- // Find new prompts that aren't already in the README
- const newPromptFiles = promptFiles.filter(
- (file) => !existingPromptLinks.includes(file)
- );
-
- if (newPromptFiles.length === 0) {
- console.log("No new prompts to add.");
- return currentReadme;
- }
-
- console.log(`Found ${newPromptFiles.length} new prompts to add.`);
-
- // Create content for new prompts (in Uncategorised section)
- let newPromptsContent = "";
+/**
+ * Generate the prompts section with an alphabetical list of all prompts
+ */
+function generatePromptsSection(promptsDir) {
+ // Get all prompt files
+ const promptFiles = fs
+ .readdirSync(promptsDir)
+ .filter((file) => file.endsWith(".prompt.md"))
+ .sort();
- // Check if we already have an Uncategorised section
- const uncategorisedSectionRegex = /### Uncategorised\n/;
- const hasUncategorisedSection = uncategorisedSectionRegex.test(currentReadme);
+ console.log(`Found ${promptFiles.length} prompt files`);
- // If we need to add the section header
- if (!hasUncategorisedSection) {
- newPromptsContent += "### Uncategorised\n";
- }
+ let promptsContent = "";
- // Add each new prompt
- for (const file of newPromptFiles) {
+ // Generate list items for each prompt file
+ for (const file of promptFiles) {
const filePath = path.join(promptsDir, file);
const title = extractTitle(filePath);
- const description = extractDescription(filePath);
const link = encodeURI(`prompts/${file}`);
- if (description) {
- newPromptsContent += `- [${title}](${link}) - ${description}\n`;
- } else {
- newPromptsContent += `- [${title}](${link})\n`;
- }
- }
-
- // Add a newline if we created a new section
- if (!hasUncategorisedSection) {
- newPromptsContent += "\n";
- }
+ // Check if there's a description in the frontmatter
+ const customDescription = extractDescription(filePath);
- // Update the README content - insert new content in the right place
- if (hasUncategorisedSection) {
- // Add to existing Uncategorised section
- const uncategorisedSectionPos = currentReadme.match(
- uncategorisedSectionRegex
- ).index;
- const sectionEndRegex = /\n\n/;
- let sectionEndMatch = sectionEndRegex.exec(
- currentReadme.slice(uncategorisedSectionPos + 16)
- ); // 16 is length of "### Uncategorised\n"
-
- let insertPos;
- if (sectionEndMatch) {
- insertPos = uncategorisedSectionPos + 16 + sectionEndMatch.index;
+ if (customDescription && customDescription !== "null") {
+ promptsContent += `- [${title}](${link}) - ${customDescription}\n`;
} else {
- // If we can't find the end of the section, just insert at the end of the section header
- insertPos = uncategorisedSectionPos + 16;
+ promptsContent += `- [${title}](${link})\n`;
}
-
- return (
- currentReadme.slice(0, insertPos) +
- newPromptsContent +
- currentReadme.slice(insertPos)
- );
- } else {
- // No Uncategorised section exists yet - find where to add it
- return addNewUncategorisedSection(currentReadme, newPromptsContent);
- }
-}
-
-function addNewUncategorisedSection(currentReadme, newPromptsContent) {
- // Look for the "Ready-to-use prompt templates" section and the next section after it
- const promptSectionRegex =
- /## π― Reusable Prompts\n\nReady-to-use prompt templates/;
- const promptSectionMatch = currentReadme.match(promptSectionRegex);
-
- if (!promptSectionMatch) {
- console.error("Could not find the Reusable Prompts section in the README.");
- return currentReadme;
}
- // Find where to insert the new section - after any existing categories
- let insertPos;
- // First check if there are any existing categories
- const existingCategoriesRegex = /### [^\n]+\n/g;
- let lastCategoryMatch = null;
- let match;
+ return `${TEMPLATES.promptsSection}\n\n${promptsContent}\n${TEMPLATES.promptsUsage}`;
+}
- while ((match = existingCategoriesRegex.exec(currentReadme)) !== null) {
- lastCategoryMatch = match;
+/**
+ * Generate the chat modes section with an alphabetical list of all chat modes
+ */
+function generateChatModesSection(chatmodesDir) {
+ // Check if chatmodes directory exists
+ if (!fs.existsSync(chatmodesDir)) {
+ console.log("Chat modes directory does not exist");
+ return "";
}
- if (lastCategoryMatch) {
- // Find the end of the last category section
- const afterLastCategory = currentReadme.slice(
- lastCategoryMatch.index + lastCategoryMatch[0].length
- );
- const nextSectionRegex = /\n\n>/;
- const nextSectionMatch = afterLastCategory.match(nextSectionRegex);
-
- if (nextSectionMatch) {
- insertPos =
- lastCategoryMatch.index +
- lastCategoryMatch[0].length +
- nextSectionMatch.index;
- } else {
- // If we can't find the next section, add at the end of the prompt section
- insertPos = currentReadme.indexOf("> π‘ **Usage**: Use `/prompt-name`");
- if (insertPos === -1) {
- // Fallback position - before Additional Resources
- insertPos = currentReadme.indexOf("## π Additional Resources");
- }
- }
- } else {
- // No categories yet, add right after the intro text
- const afterIntroRegex = /prompt\` command\.\n\n/;
- const afterIntroMatch = currentReadme.match(afterIntroRegex);
-
- if (afterIntroMatch) {
- insertPos = afterIntroMatch.index + afterIntroMatch[0].length;
- } else {
- // Fallback position - before Additional Resources
- insertPos = currentReadme.indexOf("## π Additional Resources");
- }
- }
+ // Get all chat mode files
+ const chatmodeFiles = fs
+ .readdirSync(chatmodesDir)
+ .filter((file) => file.endsWith(".chatmode.md"))
+ .sort();
- if (insertPos !== -1) {
- return (
- currentReadme.slice(0, insertPos) +
- newPromptsContent +
- currentReadme.slice(insertPos)
- );
- } else {
- console.error("Could not find a suitable place to insert new prompts.");
- return currentReadme;
- }
-}
+ console.log(`Found ${chatmodeFiles.length} chat mode files`);
-function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
- // No chat mode files, nothing to do
+ // If no chat modes, return empty string
if (chatmodeFiles.length === 0) {
- return currentReadme;
+ return "";
}
- // Extract existing chat mode links from README
- const existingChatModeLinks = [];
- const chatModeLinkRegex = /\[.*?\]\(chatmodes\/(.+?)\)/g;
- let match;
+ let chatmodesContent = "";
- while ((match = chatModeLinkRegex.exec(currentReadme)) !== null) {
- existingChatModeLinks.push(match[1]);
- }
+ // Generate list items for each chat mode file
+ for (const file of chatmodeFiles) {
+ const filePath = path.join(chatmodesDir, file);
+ const title = extractTitle(filePath);
+ const link = encodeURI(`chatmodes/${file}`);
- // Find new chat modes that aren't already in the README
- const newChatModeFiles = chatmodeFiles.filter(
- (file) => !existingChatModeLinks.includes(file)
- );
+ // Check if there's a description in the frontmatter
+ const customDescription = extractDescription(filePath);
- if (newChatModeFiles.length === 0) {
- console.log("No new chat modes to add.");
- } else {
- console.log(`Found ${newChatModeFiles.length} new chat modes to add.`);
+ if (customDescription && customDescription !== "null") {
+ chatmodesContent += `- [${title}](${link}) - ${customDescription}\n`;
+ } else {
+ chatmodesContent += `- [${title}](${link})\n`;
+ }
}
- const chatmodesSection = currentReadme.match(
- /## π§© Custom Chat Modes\n\nCustom chat modes define.+?(?=\n\n>)/s
- );
+ return `${TEMPLATES.chatmodesSection}\n\n${chatmodesContent}\n${TEMPLATES.chatmodesUsage}`;
if (chatmodesSection) {
let chatmodesListContent = "\n\n";
- // Generate list of chat mode links
- for (const file of chatmodeFiles) {
+ // Always regenerate the entire list to ensure descriptions are included
+ for (const file of chatmodeFiles.sort()) {
const filePath = path.join(chatmodesDir, file);
const title = extractTitle(filePath);
const link = encodeURI(`chatmodes/${file}`);
@@ -407,7 +366,7 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
// Check if there's a description in the frontmatter
const customDescription = extractDescription(filePath);
- if (customDescription) {
+ if (customDescription && customDescription !== "null") {
// Use the description from frontmatter
chatmodesListContent += `- [${title}](${link}) - ${customDescription}\n`;
} else {
@@ -419,7 +378,8 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
// Replace the current chat modes section with the updated one
const newChatmodesSection =
"## π§© Custom Chat Modes\n\nCustom chat modes define specific behaviors and tools for GitHub Copilot Chat, enabling enhanced context-aware assistance for particular tasks or workflows." +
- chatmodesListContent;
+ chatmodesListContent +
+ "\n> π‘ **Usage**: Create new chat modes using the command `Chat: Configure Chat Modes...`, then switch your chat mode in the Chat input from _Agent_ or _Ask_ to your own mode.";
return currentReadme.replace(chatmodesSection[0], newChatmodesSection);
} else {
@@ -429,6 +389,7 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
);
const chatmodesListContent = chatmodeFiles
+ .sort()
.map((file) => {
const filePath = path.join(chatmodesDir, file);
const title = extractTitle(filePath);
@@ -444,7 +405,7 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
.join("\n");
const newChatmodesSection =
- "## π Custom Chat Modes\n\n" +
+ "## π§© Custom Chat Modes\n\n" +
"Custom chat modes define specific behaviors and tools for GitHub Copilot Chat, enabling enhanced context-aware assistance for particular tasks or workflows.\n\n" +
chatmodesListContent +
"\n\n> π‘ **Usage**: Create new chat modes using the command `Chat: Configure Chat Modes...`, then switch your chat mode in the Chat input from _Agent_ or _Ask_ to your own mode.\n";
@@ -466,68 +427,57 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
}
}
+/**
+ * Generate the complete README.md content from scratch
+ */
function generateReadme() {
const instructionsDir = path.join(__dirname, "instructions");
const promptsDir = path.join(__dirname, "prompts");
const chatmodesDir = path.join(__dirname, "chatmodes");
- const readmePath = path.join(__dirname, "README.md");
-
- // Check if README file exists
- if (!fs.existsSync(readmePath)) {
- console.error(
- "README.md not found! Please create a base README.md file first."
- );
- process.exit(1);
- }
- // Read the current README content
- let currentReadme = fs.readFileSync(readmePath, "utf8");
+ // Generate each section
+ const instructionsSection = generateInstructionsSection(instructionsDir);
+ const promptsSection = generatePromptsSection(promptsDir);
+ const chatmodesSection = generateChatModesSection(chatmodesDir);
- // Get all instruction files
- const instructionFiles = fs
- .readdirSync(instructionsDir)
- .filter((file) => file.endsWith(".md"))
- .sort();
+ // Build the complete README content with template sections
+ let readmeContent = [TEMPLATES.header, instructionsSection, promptsSection];
- // Get all prompt files - we'll use this to find new prompts
- const promptFiles = fs
- .readdirSync(promptsDir)
- .filter((file) => file.endsWith(".prompt.md"))
- .sort();
+ // Only include chat modes section if we have any chat modes
+ if (chatmodesSection) {
+ readmeContent.push(chatmodesSection);
+ }
- // Get all chat mode files - we'll use this to update the chat modes section
- const chatmodeFiles = fs.existsSync(chatmodesDir)
- ? fs
- .readdirSync(chatmodesDir)
- .filter((file) => file.endsWith(".chatmode.md"))
- .sort()
- : [];
-
- // Update instructions section
- currentReadme = updateInstructionsSection(
- currentReadme,
- instructionFiles,
- instructionsDir
- );
+ // Add footer
+ readmeContent.push(TEMPLATES.footer);
- // Update prompts section
- currentReadme = updatePromptsSection(currentReadme, promptFiles, promptsDir);
+ return readmeContent.join("\n\n");
+}
- // Update chat modes section
- currentReadme = updateChatModesSection(
- currentReadme,
- chatmodeFiles,
- chatmodesDir
- );
+// Main execution
+try {
+ console.log("Generating README.md from scratch...");
- return currentReadme;
-}
+ const readmePath = path.join(__dirname, "README.md");
+ const newReadmeContent = generateReadme();
-// Generate and write the README
-const updatedReadme = generateReadme();
+ // Check if the README file already exists
+ if (fs.existsSync(readmePath)) {
+ const originalContent = fs.readFileSync(readmePath, "utf8");
+ const hasChanges = originalContent !== newReadmeContent;
-// Only write file if we have content to write
-if (updatedReadme) {
- fs.writeFileSync(path.join(__dirname, "README.md"), updatedReadme);
- console.log("README.md updated successfully!");
+ if (hasChanges) {
+ fs.writeFileSync(readmePath, newReadmeContent);
+ console.log("README.md updated successfully!");
+ } else {
+ console.log("README.md is already up to date. No changes needed.");
+ }
+ } else {
+ // Create the README file if it doesn't exist
+ fs.writeFileSync(readmePath, newReadmeContent);
+ console.log("README.md created successfully!");
+ }
+} catch (error) {
+ console.error(`Error generating README.md: ${error.message}`);
+ process.exit(1);
}