Guest post authored by Jules. Based on an audio transcript of Micah yammering to himself about this topic.
GitHub Copilot. It’s in your VS Code, whispering sweet code suggestions. Sometimes it’s a mind-reading marvel. Other times? It’s like trying to explain astrophysics to a Golden Retriever – well-intentioned, but ultimately… fuzzy. The truth is, Copilot’s raw power, like any sophisticated tool, needs direction. Your direction.
Want to transform Copilot from an occasionally helpful wildcard into a disciplined, context-aware teammate that consistently nails your engineering playbook? Of course you do. That’s why you’re here. This isn’t about arcane “prompt engineering” rituals; it’s about leveraging three specific, built-in VS Code features with a simple, potent framework called RICCE. Get this right, and you’ll spend less time wrestling with AI output and more time shipping brilliant code.
RICCE: Your AI’s Missing Instruction Manual
Think of RICCE – Role, Instructions, Context, Constraints, Examples – as the essential checklist your AI wishes it came with. Ignore it, and you’re gambling. Master it, and you’re conducting an orchestra.
- Role: Who is Copilot for this task? A battle-hardened “Senior Security Engineer,” a “UX-focused Frontend Developer,” a “Clear Technical Writer”? Defining a Role primes Copilot with the right domain knowledge and even jargon. Know who you’re talking to, and who’s talking.
- Instructions (Plural, mind you): What, precisely, must Copilot do? Break it down. Use crisp, active-voice commands. Think bullet points, not rambling paragraphs. Omit needless words!
- Context: What information does Copilot absolutely need to nail this? Your target audience, specific business rules, relevant code snippets from your project. No more, no less. Filler here is like static on the line – it just garbles the signal.
- Constraints: What are the non-negotiable boundaries? Output format (Markdown, JSON, a sonnet?), length (“under 500 words, or I walk”), tone (“formal, like a legal brief,” or “breezy, like we’re at a barbecue”). These are your guardrails.
- Examples (The Secret Sauce): This, dear reader, is where the magic happens. Show, don’t just tell. One or two well-crafted examples of your desired output style, format, or logic can slash “hallucinations” and align Copilot with your brainwaves faster than any abstract instruction. If your prompt feels complete without an example, you probably haven’t been specific enough.
VS Code’s Customization Trio: Your RICCE Toolkit
VS Code, bless its extensible heart, gives you three specific levers to implement RICCE. These aren’t buried in some config swamp; they’re designed to be version-controlled files, living right alongside your code in .github/instructions/
, .github/prompts/
, and .github/chatmodes/
. Treat them like code. Because they are code – code for conversing with your AI.
- Custom Instructions (
*.instructions.md
): Think of these as your project’s Ten Commandments for Copilot. Reusable, often file-specific rules (“Always usepathlib
for Python paths, you heathen!”) that Copilot silently applies. - Prompt Files (
*.prompt.md
- still a bit experimental, but promising!): Named, pre-baked recipes for common tasks. Want to run a “Security Review Checklist” or “Generate API Docs”? Trigger it with a slash command. - Custom Chat Modes (
*.chatmode.md
): These are Copilot personas on demand. A “Planning Mode” that can only read code and suggest outlines? A “Refactoring Mode” with specific refactoring tools enabled? Yes, please.
Weaving RICCE into VS Code: Practical Magic
Let’s connect the dots. How do these VS Code features bring RICCE to life?
Constraints: Your Digital Rulebook via *.instructions.md
This is where you lay down the law. *.instructions.md
files are the primary home for RICCE’s Constraints. They are your always-on style guides, your coding standard enforcers.
- How it works: Use simple Markdown with optional YAML front-matter. The
applyTo: "**/*.ts"
directive, for instance, scopes your rules to TypeScript files. Below this, list your non-negotiables as clear, declarative bullets. - Example (Constraint & Embedded Example):
```yaml
—
applyTo: “*/.py”
—
- Employ
pathlib.Path
for all filesystem path operations. (Show, don’t tell:from pathlib import Path; config_file = Path("/etc/app/config.ini")
) - All public functions must include type hints.
```
Copilot sees this and, ideally, stops suggesting
os.path
like it’s 1999. Clarity itself.
- Employ
Roles: Crafting Copilot Personas with *.chatmode.md
Want Copilot to think like a specific kind of expert? *.chatmode.md
files embody RICCE’s Role.
- How it works: YAML front-matter defines the
description
(what shows up in VS Code),tools
Copilot can use (e.g.,githubRepo
,codeSearch
), andallowedFolders
(a crucial Context Constraint, keeping Copilot focused). The Markdown body is a system prompt – here, you define the persona, its goals, and often a step-by-step workflow (initial Instructions). - Example (Role, Workflow Instructions, Tone Constraint, Embedded Example):
--- description: "The Devil's Advocate: Stress-tests technical plans." tools: [codeSearch] # Can read, can't write. Perfect. allowedFolders: ["docs/rfc", "specs"] --- # ROLE You are the Devil's Advocate. Your sole purpose is to find flaws in technical proposals, not to be nice. Be direct, be skeptical. ## WORKFLOW 1. Summarize the core proposal (max 2 sentences). 2. Identify three potential failure modes or overlooked edge cases. 3. For each, ask a sharp "What if..." question. (Example: "What if the primary database becomes unavailable during the migration?")
This mode has personality. It’s bold.
Instructions & Tasks: Reusable Playbooks with *.prompt.md
For those multi-step coding recipes you use all the time, *.prompt.md
files are your RICCE Instructions powerhouse.
- How it works: YAML sets the
mode
(e.g.,agent
for complex tasks),tools
, anddescription
. The Markdown body details the step-by-step instructions. These can use variables like${workspaceFolder}
or${selection}
(Context!) and even include other prompt files. - Example (Full RICCE in one prompt file):
--- mode: agent tools: [codebase, terminal] description: "Scaffold a new React component with tests" --- # ROLE Act as a senior frontend developer following our team's conventions. # INSTRUCTIONS 1. Ask the user for the component name (e.g., `UserProfileCard`). 2. Create a new folder named `${selection}` in `src/components/`. 3. Inside this folder, generate: - A functional React component file (`${selection}.tsx`) using TypeScript. - It should accept `title` (string) and `userData` (object) as props. - (Example structure: `interface Props { title: string; userData: object; } const ${selection}: React.FC<Props> = ({ title, userData }) => { ... }; export default ${selection};`) - A basic Storybook file (`${selection}.stories.tsx`). - A `pytest`-style test file (`${selection}.test.tsx`) with a simple render test. 4. Adhere to our ESLint rules (Context: assume project ESLint config). 5. Constraint: All generated files must include a standard license header.
This prompt doesn’t just ask; it specifies. It tells a small story of creation.
Context: It’s All Around You (If You Point it Out)
Copilot isn’t clairvoyant. You provide Context by:
- Scoping:
allowedFolders
in chat modes. - Injecting: Variables in prompt files.
- Opening Files: Copilot sees what you see in your active editor tabs. Use this.
- Pasting: Directly share error messages, logs, or key code snippets in chat. Sometimes the most direct route is indeed the scenic one, if “scenic” means “copy-paste.”
Examples: The Linchpin, Woven Throughout
Remember, Examples aren’t a separate VS Code feature; they are a principle you apply within all other features. Embed them in your *.instructions.md
to clarify rules, in your *.prompt.md
to show desired output, and in your *.chatmode.md
system prompts to define interaction styles.
The Payoff: From Chatty Wildcard to Disciplined Teammate
Why bother with all this? Because by treating your Copilot configurations – your instructions, your prompts, your modes – as first-class, version-controlled artifacts, and by structuring them with RICCE, you change the game.
- Precision Skyrockets: Copilot makes fewer bizarre detours.
- Consistency Reigns: Outputs align with your standards, not its whims.
- Efficiency Soars: Less time correcting, more time creating. Don’t make the customer do the work.
- Onboarding Smoothed: New team members (and your future self) get a Copilot already trained in “the way things are done here.”
This isn’t about stifling AI creativity. It’s about channeling it. It’s about moving from hoping for good output to engineering it.
Your Turn:
Pick one common task. Try building a *.prompt.md
for it. Define some *.instructions.md
for the relevant file types. Maybe even craft a *.chatmode.md
for the mindset you need.
Treat these files like code. Iterate. Refine.
Adopt this habit, and Copilot will stop feeling like a clever party trick and start acting like the profoundly capable (and disciplined) teammate you always wanted.
—