> Mechanically replace static dependency call sites with wrapper or built-in abstraction calls across a bounded scope (file, project, or namespace). Performs codemod-style bulk replacement of DateTime.UtcNow to TimeProvider.GetUtcNow(), File.ReadAllText to IFileSystem, and similar transformations. Adds constructor injection parameters and updates DI registration. TimeProvider, migrate static calls to wrapper, bulk replace File.* with IFileSystem, codemod static to injectable, add constructor injection for time provider, mechanical migration of statics, refactor DateTime to TimeProvider, swap static for injected dependency, convert static calls to use abstraction, replace statics in a class, migrate one file to TimeProvider, scoped migration, update call sites. wrappers (use generate-testability-wrappers), migrating between test frameworks.
npx skills add https://github.com/microsoft/testfx --skill migrate-static-to-wrapper
Perform mechanical, codemod-style replacement of static dependency call sites with calls to injected wrapper interfaces or built-in abstractions. Operates on a bounded scope (single file, project, or namespace) so migrations can be done incrementally.
generate-testability-wrappers) or built-in abstractions identifiedDateTime.UtcNow → TimeProvider.GetUtcNow() across a projectFile.* → IFileSystem.File.* across a namespacegenerate-testability-wrappers first)detect-static-dependencies)| Input | Required | Description |
|-------|----------|-------------|
| Static pattern | Yes | What to replace (e.g., DateTime.UtcNow, File.ReadAllText) |
| Replacement abstraction | Yes | What to use instead (e.g., TimeProvider, IFileSystem) |
| Scope | Yes | File path, project (.csproj), namespace, or directory to migrate |
| Injection strategy | No | constructor (default), primary-constructor, or ambient |
Before modifying any code:
TimeProvider, verify the target framework is .NET 8+ or Microsoft.Bcl.TimeProvider is referenced. For System.IO.Abstractions, verify the NuGet package is referenced.Program.cs or Startup.cs for the service registration. If missing, add it before proceeding..cs files that will be modified. Exclude test projects, obj/, bin/, and generated code.For each file containing the static pattern, determine:
TimeProvider, IFileSystem, etc. parameters| Category | Original | DI replacement |
|----------|----------|----------------|
| Time | DateTime.Now | _timeProvider.GetLocalNow().DateTime |
| Time | DateTime.UtcNow | _timeProvider.GetUtcNow().DateTime |
| Time | DateTime.Today | _timeProvider.GetLocalNow().Date |
| Time | DateTimeOffset.UtcNow | _timeProvider.GetUtcNow() |
| File | File.ReadAllText(path) | _fileSystem.File.ReadAllText(path) |
| File | File.WriteAllText(path, text) | _fileSystem.File.WriteAllText(path, text) |
| File | File.Exists(path) | _fileSystem.File.Exists(path) |
| File | Directory.Exists(path) | _fileSystem.Directory.Exists(path) |
| Env | Environment.GetEnvironmentVariable(name) | _env.GetEnvironmentVariable(name) |
| Console | Console.WriteLine(msg) | _console.WriteLine(msg) |
| Process | Process.Start(info) | _processRunner.Start(info) |
Apply the same pattern for other members in each category.
Add the new dependency following the class's existing pattern:
public class OrderProcessor(ILogger<OrderProcessor> logger, TimeProvider timeProvider)private readonly field + constructor parameter, matching the existing field naming convention (_camelCase or m_camelCase)Perform each replacement mechanically. For each call site:
using directives if not already present| Abstraction | Using directive |
|------------|-----------------|
| TimeProvider | None (in System namespace) |
| IFileSystem | using System.IO.Abstractions; |
| IHttpClientFactory | using System.Net.Http; (usually already present) |
| Custom wrappers | using <wrapper namespace>; |
If test files exist for the migrated classes:
TimeProvider → new FakeTimeProvider() from Microsoft.Extensions.TimeProvider.TestingIFileSystem → new MockFileSystem() from System.IO.Abstractions.TestingHelpersnew Mock<IWrapperName>() or hand-rolled fakeAfter all changes in the current scope:
dotnet build <project.csproj>
If the build fails:
using directivedotnet add package <name>Summarize what was done:
## Migration Summary
**Pattern**: DateTime.UtcNow → TimeProvider.GetUtcNow()
**Scope**: MyProject/Services/
### Files Modified (production)
| File | Call Sites Replaced | Injection Added |
|------|--------------------:|:----------------|
| OrderProcessor.cs | 3 | Yes (constructor) |
| NotificationService.cs | 1 | Yes (primary ctor) |
### Files Modified (tests)
| File | Change |
|------|--------|
| OrderProcessorTests.cs | Added FakeTimeProvider parameter |
### Remaining (out of scope)
- MyProject/Legacy/ — 8 call sites not migrated (different namespace)
using directives added| Pitfall | Solution |
|---------|----------|
| Replacing statics in test code | Only replace in production code; tests should use fakes/mocks |
| Breaking static classes | Static classes can't have constructors — use ambient context for these |
| Missing FakeTimeProvider NuGet | Add Microsoft.Extensions.TimeProvider.Testing to test project |
| Replacing in expression-bodied members without updating return type | DateTime → DateTimeOffset when using TimeProvider.GetUtcNow() — verify type compatibility |
| Migrating too much at once | Stick to the defined scope — one project or namespace per run |
| Forgetting DI registration | Always verify Program.cs/Startup.cs has the registration before replacing call sites |
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
Take microsoft/migrate-static-to-wrapper from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.