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 microsoft/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.



