Skip to main content

Posts

Showing posts from March, 2026

VS Code Memory Tool: Local Memory meets GitHub Copilot Memory

A few weeks ago I wrote about Copilot Memory in VS Code - the GitHub-hosted system that lets Copilot learn repository-specific insights across agents. Since then, VS Code has shipped a second, complementary memory system: the Memory tool . These two systems solve related but distinct problems, and understanding both helps you get the most out of Copilot in your daily workflow. What is the Memory Tool? The Memory tool is a built-in agent capability that stores notes locally on your machine . Unlike Copilot Memory, which lives on GitHub's servers and requires a GitHub repo to function, the Memory tool writes plain files to your local filesystem and reads them back at the start of each session. You enable or disable it with the github.copilot.chat.tools.memory.enabled setting. It's on by default. Three memory scopes VSCode organizes memories into three scopes: Scope Persists across sessions Persists across workspaces Good for ...

DeepWiki - Talk to your documentation

I regularly clone repos on Github. I explore other codebases to learn other coding approaches and improve my understanding of specific libraries. Sometimes these repos have good documentation available but most of the time I end up spelunking through source files trying to reverse-engineer what this thing does. Until I discovered DeepWiki DeepWiki is built to fix that. What is DeepWiki? Launched by Cognition AI — the team behind Devin — DeepWiki is the free public version of their internal Devin Wiki and Devin Search tools, designed to help developers quickly understand complex codebases. The idea is simple: whether it's a public repository or a private project, DeepWiki generates Wikipedia-like documentation pages through simple operations. The quickest way to try it? Just replace github.com with deepwiki.com in any public repo URL. If your repo is not indexed yet, you can ask to index it. Enter an email and you are good to go.   That's it. No install, no acc...

SQL Server silently renames your user when you ALTER with a login

With all this AI features available, you would expect that you no longer loose time on stupid issues. Unfortunately, we are not there yet. I lost a chunk of time today to a behavior in SQL Server that, once you know it, is totally obvious — but until then is absolutely maddening. I'm sharing it here so hopefully you don't lose the same time I did. The setup I had a script meant to be idempotent: create a database user if it doesn't exist, or update it if it does. Standard stuff. Here's a simplified version: Looks fine, right? Run it once — works. Run it a second time and SQL Server throws an error saying it can't find usr_SampleDB_reader . The user you just created. In the same database. With the same script. What's actually happening When you run ALTER USER [...] WITH LOGIN = [...] , SQL Server renames the user to match the login name — by default, silently, without a warning. So after the first run, usr_SampleDB_reader no longer exists. It's...

Compile-Time options validation with the OptionsValidator source generator

In the previous post, we looked at how to implement IValidateOptions<T> by hand — writing a dedicated validator class, injecting services, and expressing cross-property constraints that Data Annotations can't handle. That approach gives you full control and is the right tool when validation logic is genuinely complex. While researching that post I discovered another feature that's worth knowing about: when your validation can be expressed with Data Annotation attributes, the options validation source generator (available since .NET 8) will write the IValidateOptions<T> implementation for you at compile time. You get the safety of startup validation without the boilerplate, and as a bonus the generated code is reflection-free and AOT-compatible. The problem with runtime data annotations Before the source generator existed, the standard way to add annotation-based validation was ValidateDataAnnotations() : This works, but it uses reflection at runtime to ...

Validating configuration at startup with IValidateOptions in .NET

When you build .NET applications with strongly typed configuration, IOptions<T> and its variants give you a clean way to bind appsettings.json sections to C# classes. But binding isn't the same as validating - a missing required value or an out-of-range number will happily bind to a default and silently break your app at runtime. IValidateOptions<T> is the hook .NET provides to fix that. The problem: silent misconfiguration Consider a typical options class: If Host is missing from appsettings.json , your app starts fine. The failure surfaces only when the first email is sent — in production, at 2 AM. Data Annotations ( [Required] , [Range] ) combined with ValidateDataAnnotations() help, but they fall short when you need: Cross-property validation (e.g., Port must be 465 when UseSsl is true ) Async or database-backed checks Conditional logic depending on environment Reusable validators shared across multiple options types This is where I...

How to explore multiple solutions in parallel when using Github Copilot

If you've ever been mid-session with Copilot and thought "I want to try a completely different approach, but I don't want to lose everything I've built up here" — the new /fork command is exactly what you've been waiting for. Shipped in the February 2026 release of VS Code, /fork lets you branch a chat session into a new, fully independent thread — complete with the full conversation history — so you can explore an alternative direction without touching the original. The problem it solves Until now, exploring multiple design options or implementation strategies with Copilot meant one of two things: Start a new session — losing all the context you've already established. Stay in the same session — making your conversation messy and hard to track. Neither is great. Especially for larger tasks where the agent has already built up a useful mental model of your codebase, intent, and constraints. How to use /fork There are two ways to ...

You no longer have to wait for Copilot to finish thinking

There's a specific kind of frustration familiar to anyone who's used an AI coding agent: you send a request, it starts running, and thirty seconds later you realize you forgot to add a critical constraint. Or you think of a follow-up. Or you can see it heading somewhere wrong, and there's nothing you can do but sit there and watch. That's been the workflow. One prompt, one response, wait, repeat. The February 2026 release of VSCode (1.110) changes this in a way that's simple to describe but surprisingly powerful in practice: you can now send messages while a request is still running. What's actually changed The new behavior covers two distinct scenarios. The first is mid-flight intervention : if Copilot is in the middle of generating a response and you realize it's going in the wrong direction, you can now type a corrective message immediately. You don't have to wait. The agent incorporates your guidance and adjusts course without restarting the se...

GitHub Copilot CLI Tips & Tricks — Part 5: Delegation

We've covered modes, session management, parallelization with /fleet , and hooks. To close out the series, we're looking at delegation, the feature that lets you hand off work from your terminal to a background agent in the cloud, and build a network of specialized custom agents for your team. Two flavors of delegation "Delegation" in Copilot CLI means two related but distinct things: /delegate — handing off a task to the Copilot coding agent in the cloud, which works asynchronously on GitHub while you continue with other work Custom agents + /agent — routing tasks to specialized subagents tailored to specific types of work, running locally within your CLI session Both follow the same principle: rather than one generalist agent handling everything, you route work to whatever agent is best suited for the job. Let's look at each in turn. /delegate — Offload to the cloud What it does Running /delegate TASK-DESCRIPTION commits any unstaged ch...

GitHub Copilot CLI Tips & Tricks — Part 4: Automating and enforcing policies with hooks

So far in this series we've covered modes, session management, and parallelization with /fleet . This post is about hooks — one of the more powerful features of Copilot CLI. Hooks let you inject your own shell scripts at key moments during a session, enabling everything from audit logging to blocking dangerous commands before they execute. What are hooks? Hooks are custom scripts that run at specific points during a Copilot CLI session. They receive structured JSON input describing what's happening at that moment — which tool is being called, what arguments it received, what the session context looks like — and can optionally respond with a JSON output that influences what Copilot does next. The key thing that makes hooks different from just writing good prompts or instructions: hooks are deterministic. They execute your code at specific lifecycle points with guaranteed outcomes. Unlike instructions that guide agent behavior, a hook can guarantee that a dangerous comman...

GitHub Copilot CLI Tips & Tricks — Part 3: Parallelizing Work

In the previous posts we covered the different CLI modes and session management. This time we're looking at one of Copilot CLI's most powerful features: the /fleet command. If you've ever wished you could clone yourself to tackle several parts of a codebase at once, this is the closest thing to it. What is /fleet ? When you send a prompt to Copilot CLI, by default a single agent works through the task sequentially. /fleet changes that model entirely. The /fleet slash command lets Copilot CLI break down a complex request into smaller tasks and run them in parallel, maximizing efficiency and throughput. The main Copilot agent analyzes the prompt and determines whether it can be divided into smaller subtasks. It then acts as an orchestrator, managing the workflow and dependencies between those subtasks, each handled by a separate subagent. In practice, this means a task that might take 20 minutes sequentially can complete in a fraction of the time — because independ...

GitHub Copilot CLI Tips & Tricks — Part 2: Session management

In the first post we covered the different modes in Copilot CLI. This time we're looking at something that becomes essential once you're doing serious work in the CLI: session management. Sessions let you pause, resume, and organize your work — across terminal restarts, across machines, and across multiple concurrent workstreams. What is a session? Every time you launch Copilot CLI, you're working inside a session. A session captures your full conversation history, the tool calls Copilot made, the files it touched, and the permissions you granted — all stored locally under ~/.copilot/session-state/ . Sessions are identified by a UUID and automatically receive an AI-generated name based on your first message, making them easy to identify later. Most important is that sessions persist after you close the CLI. That means nothing is lost when you shut down your terminal — you can always pick up right where you left off. Resuming a session Pick up where you left off ...

GitHub Copilot CLI Tips & Tricks — Part 1: Understanding the Different Modes

Welcome to the first post in my series on getting the most out of GitHub Copilot in the terminal. We'll kick things off with one of the most important things to understand: the different modes Copilot CLI operates in, and when to reach for each one. A quick intro to GitHub Copilot CLI GitHub Copilot CLI is a terminal-native coding agent — not just a chat wrapper. It can plan complex tasks, edit files, run tests, and iterate autonomously, all without leaving your terminal. But to get the most out of it, you need to understand how to control how much autonomy you give it at any point in time. That's exactly what the different modes are for. You cycle through the main modes using Shift+Tab . A mode indicator in the CLI's footer tells you which one you're currently in. The three main modes 1. Standard Mode — The default When you launch copilot , you start in standard (interactive) mode. This is the classic back-and-forth: you submit a prompt, Copilot responds o...