> ## Documentation Index
> Fetch the complete documentation index at: https://site.aspect.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Driving the CLI from scripts and AI agents

> Drive the Aspect CLI from scripts and AI agents with aspect describe, JSON auth status, pipe-safe output, and the aspect mcp build results server.

The Aspect CLI surface can vary by repository. In addition to built-in tasks, `aspect <task>` runs tasks declared in your `.aspect/*.axl` files. The CLI provides a machine-readable view of the tasks, flags, and defaults available in the current workspace, along with structured output for other read-only commands used in automation.

Use the features on this page when:

* You're writing a shell script or CI job that needs to enumerate tasks or flags without parsing help text.
* You're driving `aspect` from an AI coding agent that needs to discover commands, inspect a task's flags on demand, and recover from errors without relying on prior knowledge.
* You're piping `aspect` output to a log, another process, or a file and need clean output without interactive progress updates or ANSI escape codes.
* You want an AI agent to read your team's build and test results directly, using the [`aspect mcp`](#serve-build-results-to-agents-with-aspect-mcp) server.

## Discover the surface with `aspect describe`

`aspect describe` prints the resolved CLI surface as JSON on stdout. It includes built-in and custom `.axl` tasks, the flags each task accepts, and the effective defaults after `config.axl` is applied. Flag names come from the same definitions used by the CLI, keeping the description aligned with the accepted arguments.

Start with the command index, then request full details for a specific task when needed:

```shell theme={null}
aspect describe                    # command index with summaries
aspect describe 'cache diff'       # full details for one task
```

<Note>
  Quote multi-word task paths as a single argument. Use <code>{"aspect describe 'cache diff'"}</code> to inspect the <code>cache diff</code> task. If you run <code>aspect describe cache diff</code> without quotes, the command reports the extra argument as an error.
</Note>

Both forms default to JSON on stdout and exit non-zero on an unknown command (`aspect describe 'nope'` fails), so scripts can rely on the exit status.

### The index (`aspect describe`)

The index lists every reachable task with a copy-pasteable `command` string, its group path, one-line summary, and defining module. Use it to discover what's available before drilling into a specific task:

```shell theme={null}
$ aspect describe | jq '.tasks[] | select(.command | startswith("cache"))'
{
  "command": "aspect cache diff",
  "group": ["cache"],
  "kind": "diff",
  "summary": "List test targets affected by the current tree vs. the remote cache.",
  "module": "@aspect//cache/diff.axl"
}
```

### One task's flags (`aspect describe '<command>'`)

Passing a command string returns the same header plus every flag it accepts, with type, default, allowed values, and description. Feature flags accepted everywhere are included too:

```shell theme={null}
$ aspect describe 'cache diff' | jq '.flags[] | {name, type, default, description}'
{
  "name": "--mode",
  "type": "string",
  "default": "overreport",
  "description": "How to attribute cache misses to affected test targets."
}
{
  "name": "--output",
  "type": "string",
  "default": "lines",
  "description": "Output format: 'lines' (one label per line) or 'json'."
}
...
```

### `config.axl` overrides show through as effective defaults

If your `config.axl` overrides a task's default, `describe` reports the **effective** default that applies in the current repository. Overrides preserve their declared types, so an integer override reads `2`, not `["2"]`, and include `"default_from_config": true`:

```json theme={null}
{
  "name": "--jobs",
  "type": "int",
  "default": 2,
  "default_from_config": true,
  "description": "..."
}
```

This makes `describe` a reliable way to determine a command's default behavior in the current repository.

## Check auth state with `aspect auth status --output=json`

`aspect auth status` prints a human-readable summary by default. Pass `--output=json` for machine-readable data that scripts and agents can use to diagnose authentication problems without parsing the text output:

```shell theme={null}
$ aspect auth status --output=json
{
  "account": {
    "logged_in": true,
    "status": "ok",
    "identity": "you@example.com",
    "login_command": "aspect auth login"
  },
  "deployments": [
    {
      "name": "example",
      "logged_in": false,
      "status": "expired",
      "identity": null,
      "endpoints": { "api": "https://api.example.aspect.build" },
      "login_command": "aspect auth login --deployment=example"
    }
  ],
  "default_deployment": "example"
}
```

Each entry includes `logged_in`, `status`, `identity`, its endpoints, and the exact `login_command` that re-authenticates it. A caller that finds an expired token gets the remedy without additional lookups.

Only the JSON goes to stdout. The task header stays on stderr, so you can pipe stdout cleanly to `jq` or a file. Text output is unchanged.

## `--output` is the standard flag for machine-readable output

Read commands use `--output` for their format switch. `aspect cache diff` now documents `--output` as the spelling for its format flag. The older `--format` still works but prints a deprecation warning:

```shell theme={null}
aspect cache diff --output=json    # documented spelling
aspect cache diff --format=json    # deprecated alias; still works, warns
```

See [`aspect cache diff`](/docs/cli/tasks/cache_diff) for the full list of formats.

## Pipe-safe help and output

Use `aspect --help` as a useful first call for both humans and agents:

* Every built-in task, including `build`, `format`, `gazelle`, `lint`, and `test`, has a one-line summary in the top-level help.
* Task groups list their members inline, so you can see what's inside a group without a second `--help` call:

  ```
  Task Groups:
    auth     configure, login, logout, remove, status, use
    cache    diff
    wrapper  install, uninstall
  ```

  Long groups use `… (+N more)` to omit additional members.
* `aspect test --help` cross-references `aspect cache diff` under the section on running only affected tests.

The launcher's download progress and `aspect feature` output are also safe to capture:

* For redirected output, the launcher emits concise progress updates instead of terminal redraws. Interactive terminals and CI retain their existing progress behavior.
* `aspect feature` strips ANSI escape codes when its output isn't a terminal and honors [`NO_COLOR`](https://no-color.org).

## Serve build results to agents with `aspect mcp`

`aspect mcp` runs a [Model Context Protocol](https://modelcontextprotocol.io) server over stdio. It exposes read-only build and test results from an Aspect Workflows deployment's REST API: invocations, logs, targets, artifacts, and cross-invocation target statistics. The command is not interactive. An AI tool such as Claude Code or Cursor launches it and speaks MCP on stdin/stdout.

Use it when you want an agent to answer questions like "why did CI fail on my branch", "tail the log of the last failed build", or "when did this target start flaking". The agent reads the results directly, so you don't paste logs into the chat.

### Prerequisites

* The deployment runs Aspect Workflows 6.0.30 or later with the REST API enabled (`webapp.web.api_enabled = true`). Against an older deployment, or one without the flag, the server still starts. Every tool call then returns a message explaining the version and flag requirement instead of failing, so your MCP config keeps working across an upgrade.
* Once per developer, configure and sign in to the deployment:

  ```shell theme={null}
  aspect auth configure remote.<deployment-domain>   # records the deployment; often already done for the remote cache
  aspect auth login --deployment <name>              # browser login; `configure` prints the name
  ```

The server reuses the stored deployment credential from `aspect auth login` and refreshes it automatically, so long agent sessions stay authenticated. It discovers the API host from the deployment's advertised build-results URL, so there is nothing else to configure.

### Register the server in your AI tool

Add an entry to the tool's MCP configuration. For Claude Code that is `.mcp.json` in the repository root; for Cursor it is `.cursor/mcp.json`. Both use the same shape:

```json theme={null}
{
  "mcpServers": {
    "aspect": {
      "command": "aspect",
      "args": ["mcp"]
    }
  }
}
```

The server targets the default configured deployment. To pin one, add `--deployment <name>` to the args. For several deployments, register one entry per deployment (for example `aspect-staging` and `aspect-prod`) with distinct `--deployment` args:

```json theme={null}
{
  "mcpServers": {
    "aspect-prod": {
      "command": "aspect",
      "args": ["mcp", "--deployment", "prod"]
    }
  }
}
```

### Available tools

The server publishes 13 read-only tools:

| Tool                            | What it returns                                                                                                        |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `list_invocations`              | Builds (invocations), newest first, filterable by status, Bazel command, repository, or Bazel-printed invocation UUID. |
| `get_invocation`                | Full detail of one build: header, status, timings, VCS info, links to sub-resources.                                   |
| `get_invocation_configurations` | The build configurations present in one build.                                                                         |
| `get_invocation_metadata`       | User- and CI-supplied metadata key/values recorded on one build.                                                       |
| `get_invocation_metrics`        | One build's performance metrics: action counts, cache hit rates, critical path.                                        |
| `get_build_log`                 | One page of a build's log, paged from the start.                                                                       |
| `tail_build_log`                | The last page of a build's log, usually where the failure is.                                                          |
| `list_invocation_targets`       | The targets one build built or tested, with per-target status; filterable to failures or tests.                        |
| `get_target_summary`            | Aggregate counts of one build's targets by outcome.                                                                    |
| `get_target`                    | The detail of one target within one build, including test detail.                                                      |
| `list_target_artifacts`         | The output artifacts one target produced in one build.                                                                 |
| `list_target_invocations`       | The builds that built one target over a lookback window, for "when did this start failing" questions.                  |
| `get_target_stats`              | Cross-invocation statistics over a lookback window: build counts, failure and flake rates, durations.                  |

Builds are addressed by the `id` that `list_invocations` returns. When the agent only has the invocation UUID Bazel printed, it resolves that first with `list_invocations(invocation_id=...)`. Each tool's description documents this, so agents pick it up from `tools/list` without extra prompting.

### For AXL authors: `ctx.aspect.mcp.serve()`

The `mcp` task is a built-in `.axl` task implemented with the `ctx.aspect.mcp.serve(deployment = ...)` runtime API. If you wrap or replace the task in your own `.axl` files, call `serve()` and return its result as the task's exit code. Keep stdout untouched: it carries the MCP protocol, and anything else printed there corrupts the JSON-RPC stream. Diagnostics go to stderr.

## When to use which command

| I want to…                                              | Use                                                         |
| ------------------------------------------------------- | ----------------------------------------------------------- |
| List every task available in this repo                  | `aspect describe` (index) or `aspect --help`                |
| See one task's full flag detail                         | `aspect describe '<command>'`                               |
| Know the effective default for a flag in this repo      | `aspect describe '<command>'` — check `default_from_config` |
| Diagnose an auth failure programmatically               | `aspect auth status --output=json`                          |
| Get the exact command to re-authenticate                | `login_command` field in `aspect auth status --output=json` |
| Get affected test labels for scripting                  | `aspect cache diff --output=json`                           |
| Let an agent read build and test results from Workflows | `aspect mcp` registered as an MCP server                    |

## Example: driving `aspect` from a script

Enumerate every task, drill into one, and act on its flags:

```shell theme={null}
#!/usr/bin/env bash
set -euo pipefail

# 1. Discover: does this repo have `cache diff`?
if ! aspect describe | jq -e '.tasks[] | select(.command == "aspect cache diff")' > /dev/null; then
  echo "cache diff not available in this repo" >&2
  exit 1
fi

# 2. Drill: read its effective default for --mode.
mode=$(aspect describe 'cache diff' | jq -r '.flags[] | select(.name == "--mode") | .default')
echo "Default mode is: $mode"

# 3. Run: use the JSON output format.
aspect cache diff --output=json > affected.json
```

## Example: an agent recovering from an auth failure

```shell theme={null}
status=$(aspect auth status --output=json)
if [ "$(echo "$status" | jq -r '.account.status')" != "ok" ]; then
  cmd=$(echo "$status" | jq -r '.account.login_command')
  echo "Re-authenticate with: $cmd" >&2
  exit 1
fi
```

## See also

* [`aspect cache diff`](/docs/cli/tasks/cache_diff): use `--output=json` with affected-test results.
* [Authenticating the Aspect CLI](/docs/cli/authentication): learn how `aspect auth login` works and how CI authenticates with `ASPECT_API_TOKEN`.
* [Tasks overview](/docs/cli/tasks): explore the built-in tasks that `aspect describe` lists and how custom `.axl` tasks appear alongside them.
* [Build results over MCP](/docs/aspect-workflows/using-workflows/build-results-mcp): the Workflows-side guide to the MCP server, including operator setup and troubleshooting.
