Debugging a distributed application usually means moving between several tools.

You may start with the application dashboard, switch to a terminal to inspect a container, open another terminal for logs, and then return to the dashboard to check whether another service is failing.

.NET Aspire 13.6 improves this local development experience by adding a more capable terminal experience directly inside the Aspire Dashboard. The release includes a persistent, resizable terminal dock, detached terminal windows, and resource or AppHost-owned terminal sessions. It also adds database REPL support for several database and cache resources.

That matters because the dashboard already knows about the resources in your distributed application. Having terminal access alongside resource status, logs, metrics, and traces makes it easier to investigate a problem without constantly switching context.

This article explains how to use the capability, where it helps, and what developers should keep in mind when debugging containers.

What Changed in Aspire 13.6?

Aspire 13.6 adds a persistent terminal dock to the dashboard. The terminal can be resized, opened in tabs, or detached into its own window. The new terminal rendering system also improves copy and paste behavior and provides sizing controls.

The release also adds AppHost-owned interactive terminals, allowing an AppHost to create terminal processes that are not necessarily tied directly to a DCP-managed resource. These terminals can appear in the dashboard dock or in a separate dialog or window.

For developers, the practical difference is straightforward:

Before

Aspire Dashboard
      |
      +---- Logs
      +---- Metrics
      +---- Traces

Separate Terminal
      |
      +---- Container inspection
      +---- Commands
      +---- Database tools

With the newer dashboard experience:

Aspire Dashboard
      |
      +---- Resources
      +---- Logs
      +---- Metrics
      +---- Traces
      |
      +---- Terminal
             |
             +---- Commands
             +---- Container inspection
             +---- REPL

The goal is not to replace your normal terminal. It is to put runtime investigation closer to the application context.

Why Container Debugging Needs This Context

Consider a local application with several services:

                    Aspire
                       |
       +---------------+---------------+
       |               |               |
       v               v               v
      API          PostgreSQL        Redis
       |
       v
   Frontend

Suppose the API reports a database connection error.

You need to answer several questions:

The dashboard can show resource state and telemetry.

The terminal gives you another level of inspection.

That combination is useful because you can move from:

Something is failing
        |
        v
Dashboard
        |
        v
Identify the resource
        |
        v
Terminal
        |
        v
Inspect the runtime

Opening the Terminal

Aspire 13.6 provides a terminal dock directly in the dashboard. The terminal can remain available while you move between dashboard views, and terminal sessions can also be detached into separate windows.

This is useful during a debugging session because you can keep the terminal open while checking resource logs.

For example:

+------------------------------------------------+
| Aspire Dashboard                               |
|                                                |
| Resources | Logs | Traces | Metrics            |
|                                                |
|------------------------------------------------|
| Terminal                                       |
|                                                |
| $ pwd                                          |
| $ ls -la                                       |
| $ dotnet --info                                |
|                                                |
+------------------------------------------------+

The exact commands available depend on the resource and its environment.

Inspecting a Container

Suppose your AppHost includes a PostgreSQL resource.

A simplified AppHost might look like this:

var builder = DistributedApplication.CreateBuilder(args);

var postgres = builder
    .AddPostgres("postgres")
    .AddDatabase("appdb");

var api = builder
    .AddProject<Projects.Api>("api")
    .WithReference(postgres);

builder.Build().Run();

When the application is running, Aspire understands that the API depends on PostgreSQL.

If the database behaves unexpectedly, the dashboard gives you the application-level view, while terminal access lets you inspect the runtime environment.

Depending on the resource, you may be able to run commands that inspect files, environment information, processes, or available tools.

For example:

pwd

and:

ls -la

can help establish where you are and what files are available.

Checking the Runtime Environment

One of the first things to check when a container behaves differently from your local machine is the runtime environment.

For a .NET container:

dotnet --info

can show the installed .NET SDK and runtime information.

You can also inspect the operating system:

uname -a

if the command is available.

The point is to replace assumptions with evidence.

Instead of assuming that the container has the runtime you expected, inspect it.

Checking Environment Variables Safely

Configuration is another common source of container problems.

You may need to determine whether a required variable exists.

For example:

if [ -n "$ASPNETCORE_ENVIRONMENT" ]; then
    echo "Environment variable is configured"
else
    echo "Environment variable is missing"
fi

This is safer than dumping the entire environment.

Avoid casually running:

env

in an environment that contains secrets.

Environment variables may contain:

The dashboard and terminal make investigation easier, but they do not remove the need for careful handling of sensitive information.

Debugging a Database Connection

Suppose the API cannot connect to PostgreSQL.

Start by checking whether the PostgreSQL resource is running.

Then inspect the application logs.

If the error looks like:

Connection refused

you can investigate the database environment.

If the PostgreSQL client is available, you can check its version:

psql --version

You can then use the appropriate connection information to test connectivity.

For example:

psql \
  -h "$POSTGRES_HOST" \
  -U "$POSTGRES_USER" \
  -d "$POSTGRES_DB"

The exact variables depend on how your application is configured.

Do not paste real passwords directly into commands or source files.

Database REPLs

Aspire 13.6 also adds opt-in REPL commands for database and cache integrations. The release includes bundled clients for PostgreSQL, MySQL, MongoDB, SQL Server, Redis, and Valkey.

This can make database troubleshooting more convenient.

For example, instead of manually finding the container and starting a client, the resource can expose an appropriate interactive database command through the Aspire development experience.

The workflow becomes:

Database Resource
       |
       v
Resource Command / REPL
       |
       v
Database Client
       |
       v
Inspect Data

This is particularly useful for local development and debugging.

It should not be interpreted as a reason to give developers unrestricted database access in production.

Checking Redis

A similar workflow can be used with Redis.

If the appropriate client is available, a simple health check might look like:

redis-cli ping

A healthy Redis instance normally returns:

PONG

You can then inspect the data or configuration required for the development scenario.

Again, be careful with data that may contain credentials or other sensitive information.

Debugging Files Inside a Container

A common container problem is that a file exists on the developer's machine but not inside the container.

For example, the application expects:

/app/config/settings.json

You can inspect the directory:

ls -la /app

and then:

ls -la /app/config

This can quickly reveal whether the issue is related to:

The terminal is useful here because it shows the actual runtime filesystem rather than what exists on the host.

Host Files vs Container Files

This distinction causes many debugging mistakes.

Imagine:

Developer Machine
|
+-- C:\Projects\MyApp
|
+-- Docker
     |
     +-- API Container
           |
           +-- /app

A file in:

C:\Projects\MyApp\config.json

does not automatically exist at:

/app/config.json

inside the container.

Whether it exists depends on the container image and volume configuration.

The dashboard terminal gives you a direct way to inspect the resource's environment.

AppHost-Owned Terminals

Aspire 13.6 also introduces experimental AppHost-owned interactive terminals.

This is slightly different from simply opening a shell inside a resource.

The AppHost can create an interactive terminal process independently of the resources orchestrated by DCP. These terminals can be displayed in the dashboard dock, opened in a dialog, or used in headless scenarios for automation.

This can be useful when the application needs an interactive development tool that is not itself a container resource.

The architecture can look like:

AppHost
   |
   +---- API
   +---- Database
   +---- Cache
   |
   +---- Interactive Tool

This provides another way to integrate developer tooling into the local application experience.

Terminal Debugging vs Dashboard Observability

Terminal access does not replace the rest of the dashboard.

Each tool answers a different question.

Tool

Best Use

Resources

Is the service running?

Console Logs

What is the application reporting?

Structured Logs

What events are being emitted?

Traces

Where is a request spending time or failing?

Metrics

What is happening over time?

Terminal

What is actually present inside the runtime?

Database REPL

What does the development database contain?

A good debugging workflow uses them together.

For example:

API Request Fails
      |
      v
Trace
      |
      v
Database Span Looks Suspicious
      |
      v
PostgreSQL Resource
      |
      v
Terminal / REPL
      |
      v
Inspect Database

This is much more efficient than immediately opening a terminal and guessing.

A Practical Debugging Workflow

When a container is not behaving as expected, follow a consistent process.

Step 1: Check the Resource

Confirm whether the container is running.

Step 2: Check Logs

Look for startup failures, configuration errors, and dependency failures.

Step 3: Check Traces

If the problem occurs during a request, determine where the request fails.

Step 4: Open the Terminal

Inspect the actual runtime environment.

Step 5: Verify Configuration

Check the required variables without exposing sensitive values.

Step 6: Test the Dependency

Use the appropriate client or command to verify connectivity.

Step 7: Fix the Source Configuration

If the problem is caused by the AppHost, container image, or application code, make the permanent change there.

Do not rely on an interactive terminal change.

Common Mistakes

Assuming the Host and Container Are the Same

They are different environments.

A command working on your machine does not prove that it will work inside the container.

Treating Manual Changes as Permanent

Suppose you install a package interactively:

apt-get install some-package

The package may disappear when the container is recreated.

If the dependency is required, update the container image or development configuration.

Printing All Environment Variables

This can expose credentials.

Inspect only what you need.

Using the Terminal Instead of Observability

A shell can tell you what is happening inside a resource, but it is not a replacement for traces and metrics.

Debugging Without a Hypothesis

Do not run dozens of commands without knowing what question you are trying to answer.

Start with the failure and work toward the likely cause.

Troubleshooting Terminal Problems

Terminal Does Not Open

First confirm that the Aspire dashboard is running the expected version and that the terminal capability is available for the current resource.

If a terminal is resource-specific, verify that the selected resource supports the operation you are attempting.

A Command Is Missing

Minimal container images may not include common utilities.

Check:

which <command>

when which is available.

If the command is genuinely required by the application, add it through the correct image or development configuration instead of relying on a manual installation.

Terminal Works but the Fix Disappears

That is expected if you modified the running container directly.

Move the fix into:

depending on the actual cause.

Advantages

Less Context Switching

Developers can inspect resources without constantly moving between the dashboard and separate terminal applications.

Better Runtime Visibility

The terminal provides access to the environment where the resource is actually running.

Faster Database Troubleshooting

Database and cache REPL support can simplify local inspection.

Better Development Experience

The persistent terminal dock and detached windows make interactive debugging more convenient.

Disadvantages and Limitations

Not Every Resource Behaves Like a Shell

The available commands depend on the underlying resource and environment.

Manual Changes Are Temporary

Interactive modifications are generally lost when the resource is recreated.

Security Still Matters

A terminal can expose credentials and sensitive application data.

Experimental Features Can Change

Some of the terminal APIs in Aspire 13.6 are marked experimental, so teams should account for possible API or behavior changes when adopting them.

Best Practices

  1. Use the dashboard first to understand the system-level problem.

  2. Use the terminal to investigate a specific resource.

  3. Do not expose secrets while inspecting environment variables.

  4. Treat manual container changes as temporary experiments.

  5. Put permanent fixes into source-controlled configuration.

  6. Use explicit runtime and dependency versions where reproducibility matters.

  7. Use database REPLs carefully and preferably with non-production data.

  8. Keep production credentials out of local debugging environments whenever possible.

  9. Use traces and logs together with terminal investigation.

  10. Document repeatable troubleshooting commands for the development team.

Final Thoughts

Aspire 13.6 makes the local debugging experience more practical by bringing interactive terminals closer to the resources developers are already monitoring in the dashboard.

The real advantage is not simply having another terminal window. It is being able to move from a resource's status, logs, traces, and metrics to direct runtime inspection without losing the context of the distributed application.

For example, if an API cannot connect to PostgreSQL, you can start with the API resource, inspect the relevant trace, check the database resource, and then use a terminal or database REPL to verify the runtime state.

That makes debugging more deliberate and reduces unnecessary context switching.

Developers should still remember that a terminal is an investigation tool. A manual change inside a running container is not a substitute for fixing the Dockerfile, AppHost configuration, application code, or infrastructure definition.

Used correctly, the combination of Aspire's dashboard and terminal capabilities provides a much more complete local development workflow for distributed .NET applications.