C# Starter Template
Professional plugin template for C# with async/await patterns and modern .NET features.
Overview
The C# starter template provides a complete, production-ready foundation for building HyperHQ plugins in C# with:
- ✅ Modern async/await patterns throughout
- ✅ Challenge-response authentication
- ✅ SocketIOClient library integration
- ✅ Microsoft.Extensions.Logging for structured logging
- ✅ Single-file deployment option
Prerequisites
- .NET SDK 6.0 or later
- Visual Studio, VS Code, or Rider (optional)
- Basic understanding of C# and async programming
Quick Start
1. Get the Template
Navigate to the templates directory in your HyperHQ installation:
cd "C:\HyperHQ\docs\templates\csharp-starter"
Or copy the csharp-starter folder from HyperHQ's docs/templates directory to your development location.
2. Restore Dependencies
dotnet restore
3. Build
# Standard build
dotnet build -c Release
# Single-file executable
dotnet publish -c Release -r win-x64 \
--self-contained \
-p:PublishSingleFile=true \
-o ./publish
4. Install in HyperHQ
# Create plugin directory
mkdir "C:\HyperHQ\plugins\my-csharp-plugin"
# Copy files
copy publish\*.exe "C:\HyperHQ\plugins\my-csharp-plugin\"
copy plugin.json "C:\HyperHQ\plugins\my-csharp-plugin\"
Key Features
Environment Variables
The template validates required environment variables in the constructor:
Program.cs
public Plugin()
{
_pluginId = Environment.GetEnvironmentVariable("HYPERHQ_PLUGIN_ID");
if (string.IsNullOrEmpty(_pluginId))
{
throw new InvalidOperationException(
"Missing HYPERHQ_PLUGIN_ID - plugin must be launched by HyperHQ"
);
}
_authChallenge = Environment.GetEnvironmentVariable("HYPERHQ_AUTH_CHALLENGE");
// ... more validation
}
Async Socket.IO Communication
Full async/await pattern support:
Program.cs
_socket.On("authenticated", async response =>
{
var data = response.GetValue<Dictionary<string, object>>();
if (data["success"] is true)
{
_sessionToken = data["sessionToken"].ToString();
_isAuthenticated = true;
await RegisterPlugin();
await SendNotification("Connected to HyperHQ", "info");
}
});
Structured Logging
Built-in logging with Microsoft.Extensions.Logging:
Program.cs
_logger.LogInformation("Authentication successful");
_logger.LogDebug("Data request sent: {Method} (ID: {RequestId})", method, requestId);
_logger.LogError(ex, "Failed to connect to Socket.IO server");
Authenticated Requests
Helper method for making authenticated data requests:
Program.cs
private async Task<string> RequestData(string method, object parameters)
{
if (!_isAuthenticated)
{
throw new InvalidOperationException("Not authenticated with HyperHQ");
}
var requestId = $"{method}-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
await _socket.EmitAsync("request_data", new
{
method = method,
@params = parameters,
requestId = requestId,
sessionToken = _sessionToken
});
return requestId;
}
Template Structure
csharp-starter/
├── Program.cs # Main plugin implementation
├── Plugin.csproj # Project configuration
├── plugin.json # Plugin manifest
├── build.sh # Build script (Unix)
└── build.bat # Build script (Windows)
Customization
1. Update Project Settings
Edit Plugin.csproj:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>MyPlugin</AssemblyName>
</PropertyGroup>
2. Add Your Logic
Implement custom actions:
Program.cs
public async Task<object> Execute(Dictionary<string, object> data)
{
var action = data.ContainsKey("action") ? data["action"].ToString() : "default";
return action switch
{
"my_action" => await HandleMyAction(data),
"sync_data" => await HandleSyncData(data),
_ => new { error = $"Unknown action: {action}" }
};
}
3. Add Event Handlers
Program.cs
_socket.On("my:custom:event", response =>
{
var data = response.GetValue<Dictionary<string, object>>();
HandleCustomEvent(data);
});
Building for Production
Single-File Deployment
dotnet publish -c Release -r win-x64 \
--self-contained \
-p:PublishSingleFile=true \
-p:PublishTrimmed=true \
-o ./dist
Reduce File Size
dotnet publish -c Release -r win-x64 \
--self-contained \
-p:PublishSingleFile=true \
-p:PublishTrimmed=true \
-p:PublishReadyToRun=true \
-p:TrimMode=Link
Performance Tips
- Use async/await consistently - Don't mix sync and async
- Dispose resources properly - Use
usingstatements - Configure logging levels - Set to Warning/Error in production
- Use object pooling for frequently allocated objects
Troubleshooting
"Microsoft.Extensions.Logging not found"
dotnet restore
dotnet add package Microsoft.Extensions.Logging
dotnet add package Microsoft.Extensions.Logging.Console
"SocketIOClient not found"
dotnet add package SocketIOClient
Plugin crashes on startup
- Check dependencies are included in publish
- Use
--self-containedflag - Test executable from command line first
Authentication timeout
// Increase connection timeout
var options = new SocketIOOptions
{
ConnectionTimeout = TimeSpan.FromSeconds(10),
// ...
};
Advanced Features
Progress Reporting
for (int progress = 0; progress <= 100; progress += 10)
{
await _socket.EmitAsync("plugin:progress", new
{
task = "processing",
progress = progress,
message = $"Processing... {progress}%"
});
await Task.Delay(100);
}
Error Handling
try
{
await ProcessData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Processing failed");
await _socket.EmitAsync("plugin:notify", new
{
type = "error",
message = "Processing failed: " + ex.Message
});
}