Aspire extension to start the Temporal CLI dev server as a container or executable resource, with an optional client library for automatic connection string resolution and OpenTelemetry integration.
Note: Only container works as expected. See dotnet/aspire#1637 and temporalio/cli#316
- An Aspire project. See Aspire docs to get started.
- Temporal CLI (only if using the executable resource)
# Hosting library (AppHost project)
dotnet add package InfinityFlow.Aspire.Temporal
# Client library (Worker/API projects)
dotnet add package InfinityFlow.Aspire.Temporal.Client// AppHost/Program.cs
using InfinityFlow.Aspire.Temporal;
var builder = DistributedApplication.CreateBuilder(args);
// Container resource (recommended)
var temporal = builder.AddTemporalServerContainer("temporal")
.WithLogFormat(LogFormat.Json)
.WithLogLevel(LogLevel.Info)
.WithNamespace("test1", "test2")
.WithDynamicConfigValue("frontend.enableUpdateWorkflowExecution", true);
// With fixed ports (dynamic by default)
var temporalWithPorts = builder.AddTemporalServerContainer("temporalWithPorts")
.WithServicePort(7233)
.WithUiPort(8233);
// Reference from your projects
builder.AddProject<Projects.Worker>("worker")
.WithReference(temporal);
builder.AddProject<Projects.Api>("api")
.WithReference(temporal);
builder.Build().Run();You should see Temporal running under the Containers tab.
The InfinityFlow.Aspire.Temporal.Client package provides automatic connection string resolution, OpenTelemetry integration, and health checks.
// Worker/Program.cs
using InfinityFlow.Aspire.Temporal.Client;
var builder = Host.CreateApplicationBuilder(args);
builder.AddTemporalWorker("temporal", "my-task-queue", opts =>
{
opts.Namespace = "my-namespace";
})
.AddWorkflow<MyWorkflow>()
.AddScopedActivities<MyActivities>();
builder.Build().Run();// Api/Program.cs
using InfinityFlow.Aspire.Temporal.Client;
var builder = WebApplication.CreateBuilder(args);
builder.AddTemporalClient("temporal", opts =>
{
opts.Namespace = "my-namespace";
});
var app = builder.Build();
// ...Both AddTemporalWorker and AddTemporalClient automatically:
- Resolve the connection string from the Aspire resource reference
- Register a
TracingInterceptorfor distributed tracing - Set up a
TemporalRuntimewithCustomMetricMeterfor metrics - Add a health check for the Temporal connection
Add AddTemporalServiceDefaults() in your service defaults to wire up OpenTelemetry meters and tracing sources:
// ServiceDefaults/Extensions.cs
using InfinityFlow.Aspire.Temporal.Client;
builder.Services.AddTemporalServiceDefaults();This registers the Temporal meter and TracingInterceptor activity sources with the OpenTelemetry pipeline. See the sample for a complete example.
If done correctly, you should see tracing and metrics on the Aspire dashboard:
The dev server is configured with fluent extension methods:
builder.AddTemporalServerContainer("temporal")
.WithDbFileName("/location/of/persistent/file") // --db-filename
.WithNamespace("namespace-name") // --namespace
.WithServicePort(7233) // external host port (container internal is always 7233)
.WithHttpPort() // --http-port
.WithMetricsEndpoint() // --metrics-port
.WithUiPort(8233) // external host port (container internal is always 8233)
.WithHeadlessUi() // --headless
.WithIp("127.0.0.1") // --ip
.WithUiIp("127.0.0.1") // --ui-ip
.WithUiAssetPath("/location/of/custom/assets") // --ui-asset-path
.WithUiCodecEndpoint("http://localhost:8080") // --ui-codec-endpoint
.WithLogFormat(LogFormat.Pretty) // --log-format
.WithLogLevel(LogLevel.Info) // --log-level
.WithSQLitePragma(SQLitePragma.JournalMode) // --sqlite-pragma
.WithDynamicConfigValue("key", value) // --dynamic-config-value
.WithLogConfig(true) // --log-config
.WithSearchAttribute("MyKey", SearchAttributeType.Keyword) // --search-attribute
.WithUiPublicPath("/temporal"); // --ui-public-pathYou can run temporal server start-dev --help to get more information about the CLI flags on the dev server.



