How I’m using Copilot to not use Copilot - Kamil Gwóźdź
Kamil Gwóźdź
SubscribeSign in
How I’m using Copilot to not use Copilot<br>Reasons why your prompts suck (part 2) - you're using skills instead of extensions.
Kamil Gwóźdź<br>Jun 01, 2026
Share
In part 1 I talked about harnesses - giving Copilot ways to check its own work so it can converge on a good result instead of guessing. This time I want to talk about the opposite problem: the moments when you should deliberately stop letting Copilot do the work for you, and how to wire that into your tooling so you can’t accidentally skip them.<br>Before I get to the example, there’s a distinction in Copilot CLI that I think is underused - skills vs extensions .<br>A skill is just text. It’s a markdown file the agent reads when it thinks a topic is relevant, like “here’s how to write a good commit message” or “here’s the convention we use for branch names”. The agent can use it, or it can quietly ignore it. It costs context window. At the end of the day, it’s just special prompt.<br>An extension is code. It hooks directly into the agent’s runtime - it can inspect and rewrite CLI calls before they execute, validate the output of a tool call after it runs, or inject prompts when specific events happen. It’s deterministic. The agent can’t talk its way out of an extension the way it can talk its way past a skill it didn’t feel like reading.<br>That distinction matters because some rules in your workflow are “nice to have” and some are “never break this”. Examples of rules I defined for Copilot:<br>Never open a non-draft PR by accident.
Never @-mention people or teams from inside an agent - those notifications go to real humans and should be purposefully triggered by humans.
Always attempt to update my Obsidian vault with substantial information when a session ends
Those aren’t suggestions. They’re hard rules. So they live in extensions, not skills.<br>The extension I want to show off is pr-lifecycle . It does three things automatically: it silently injects --draft into any gh pr create that’s missing it, it blocks commands containing @ mentions before they run, and it validates that PR bodies have the structure I want (a human-written summary followed by an AI-generated block for agents). On top of that it exposes a finalize_pr tool that, when called, pops up two UI prompts asking me for the PR title and the description.<br>Here’s the workflow in practice. I tell Copilot to open a PR. The hook injects --draft, the PR opens with a placeholder body, and I get a reminder to call finalize_pr once CI is green - which ensures I only need to pay attention to it after changes were validated. When I do, the agent has to stop and ask me:
Then, separately, the description:
And the final PR ends up looking like this - my words at the top, with the AI’s structured summary tucked into a collapsible block underneath that reviewers can expand if they want the agent’s take:
(example PR)<br>Now here’s the part that actually matters, and the reason this extension exists at all.<br>The PR description is the one moment in the loop where I force myself to stop, slow down, and think. Not “review the diff and click merge” think - actually think. Did I consider the performance implications? Did I pick this architecture for a reason I can articulate? Is there a simpler version of this change I rejected, and why? Writing that down in my own words, in my own voice, is the closest thing I have to a guarantee that I actually understood what just got built. If I can’t describe the change, I don’t really understand it, and I shouldn’t be shipping it.<br>The PR description is also the artifact my reviewer should read carefully - they will skim the diff, they will not thoroughly read a wall of AI-generated text. Description written in my own words, is the signal I send them about how I think about my own changes. Outsourcing that part to the agent is outsourcing the one piece of the workflow where being a human actually matters and that's why I decided to purposely do it on my own. But the AI-summary part allows to preserve context for future agent sessions.
So the extension exists to make that pause non-skippable. The agent literally cannot finalize the PR without coming back to me and asking. It’s a tiny piece of friction, and it’s the most valuable friction in my entire workflow.<br>This is part 2 of “Reasons why your prompts suck” - a mini-series about closing the gap between what AI agents can do and what you’re actually getting out of them.
Share
Discussion about this post<br>CommentsRestacks
TopLatest
No posts
Ready for more?
Subscribe
© 2026 Kamil Gwóźdź · Privacy ∙ Terms ∙ Collection notice<br>Start your SubstackGet the app<br>Substack is the home for great culture
This site requires JavaScript to run correctly. Please turn on JavaScript or unblock scripts