dotnet new classlib -n MyPlugin
cd MyPlugin
dotnet add package GitHub.Copilot.PluginSystemYou have two options:
using GitHub.Copilot.PluginSystem;
public class MyPlugin : PluginBase
{
public override string Id => "my-plugin";
public override string Name => "My Plugin";
public override string Version => "1.0.0";
public override string Description => "Does something cool";
public override string Author => "Your Name";
public override async Task<RequestContext> BeforeRequestAsync(RequestContext request)
{
// Your logic here
return request;
}
}using GitHub.Copilot.PluginSystem;
public class MyPlugin : IPlugin
{
public string Id => "my-plugin";
public string Name => "My Plugin";
// ... implement all interface members
}public override Task InitializeAsync(IPluginContext context)
{
// Setup: Load config, connect to services, etc.
Console.WriteLine($"[{Name}] Initialized");
return Task.CompletedTask;
}
public override async Task<RequestContext> BeforeRequestAsync(RequestContext request)
{
// Intercept/modify requests before they go to Copilot
// - Add context
// - Validate safety
// - Log metrics
return request;
}
public override async Task<ResponseContext> AfterResponseAsync(ResponseContext response)
{
// Process responses after Copilot returns
// - Extract insights
// - Log results
// - Trigger actions
return response;
}
public override Task ShutdownAsync()
{
// Cleanup: Close connections, save state, etc.
Console.WriteLine($"[{Name}] Shutdown");
return Task.CompletedTask;
}public override async Task<RequestContext> BeforeRequestAsync(RequestContext request)
{
if (ContainsUnsafePattern(request.Prompt))
{
request.Metadata["blocked"] = "true";
request.Prompt = "Operation blocked for safety reasons";
}
return request;
}public override async Task<ResponseContext> AfterResponseAsync(ResponseContext response)
{
await File.AppendAllTextAsync("copilot-log.txt",
$"{DateTime.Now}: {response.Response}\n");
return response;
}public override async Task<RequestContext> BeforeRequestAsync(RequestContext request)
{
var projectContext = await LoadProjectContextAsync();
request.Prompt = $"{projectContext}\n\n{request.Prompt}";
return request;
}private int _requestCount = 0;
private Dictionary<string, int> _topicCounts = new();
public override async Task<RequestContext> BeforeRequestAsync(RequestContext request)
{
_requestCount++;
var topics = ExtractTopics(request.Prompt);
foreach (var topic in topics)
_topicCounts[topic] = _topicCounts.GetValueOrDefault(topic, 0) + 1;
return request;
}using GitHub.Copilot.PluginSystem;
var manager = new PluginManager();
// Load from directory
await manager.LoadPluginsFromDirectoryAsync("./plugins");
// Or register manually
await manager.RegisterPluginAsync(new MyPlugin());
// Execute before request pipeline
var modifiedRequest = await manager.ExecuteBeforeRequestAsync(originalRequest);
// Execute after response pipeline
var modifiedResponse = await manager.ExecuteAfterResponseAsync(originalResponse);
// Shutdown all plugins
await manager.ShutdownAllAsync();- Error Handling: Wrap plugin logic in try/catch - plugin failures shouldn't crash the host
- Performance: Keep BeforeRequest fast - it blocks the request pipeline
- State Management: Use metadata dictionary for passing data between hooks
- Logging: Use Console.WriteLine with plugin name prefix for debugging
- Testing: Write unit tests for your plugin logic
- Versioning: Follow semantic versioning for your plugins
The RequestContext and ResponseContext include a Metadata dictionary for passing data:
// In BeforeRequest
request.Metadata["analyzed"] = "true";
request.Metadata["risk_level"] = "low";
// In AfterResponse
if (response.Metadata.ContainsKey("analyzed"))
{
var riskLevel = response.Metadata["risk_level"];
// Handle accordingly
}Check out the src/Examples/ directory for complete working examples:
- TrustFrameworkPlugin - Safety evaluation and blocking
- MetaCognitionPlugin - Conversation analysis and insights
- Build your plugin:
dotnet build -c Release - Package it:
dotnet pack -c Release - Publish to NuGet:
dotnet nuget push *.nupkg --source https://api.nuget.org/v3/index.json - Share with the community!
Open an issue on GitHub: https://github.com/barrersoftware/copilot-plugin-system/issues