Skip to main content
Some Aspect CLI features post results back to your version-control host as your CI runs. They authenticate to the Aspect API, which in turn calls your VCS through the Aspect App installed on your organization. This page covers the provider-agnostic half of that setup: creating an Aspect account, signing in locally, and generating the ASPECT_API_TOKEN that CI uses. Installing the App that talks to your VCS is provider-specific:

GitHub App

Install and link the Aspect Workflows GitHub App, then enable status checks, the PR task summary comment, and PR lint comments.

GitLab App

Link the Aspect Workflows GitLab App, then enable commit statuses, rolling MR notes, and MR lint comments.

Do I need to authenticate?

Only if you use a CLI feature that talks to the Aspect API. Plain commands — aspect test //... locally, or aspect build //... against a remote cache — work with no auth at all, so you can skip this page if none of the features below apply. The features that require authentication, by provider:
ProviderFeatureWhat it does
GitHubGithubStatusChecksPer-task pass/fail status checks on the commit under review.
GitHubGithubStatusCommentsA single PR task summary comment aggregating every task’s live status.
GitHubGithubLintCommentsInline aspect lint findings as PR review comments.
GitHubaspect format / aspect lintBacks up changed-file detection with the GitHub PR Files API when a local git diff can’t resolve the diff base (e.g. shallow clones). Optional — git diff is the default.
GitLabGitlabCommitStatusesPer-task pass/fail status on the commit (the MR’s commit status column).
GitLabGitlabStatusCommentsA single rolling MR note aggregating every task’s live status.
GitLabGitlabLintCommentsInline aspect lint findings as position-bound MR discussions.
When authentication is unavailable, every feature above skips gracefully — the underlying aspect command continues normally and logs a single line explaining what was missing.

Setup overview

Authentication always involves the same two pieces, regardless of host:
  1. Install and link the Aspect App for your VCS organization — one-time per org. See the GitHub App or GitLab App page.
  2. Generate an ASPECT_API_TOKEN so CI runners can authenticate non-interactively — covered below.
Both are scoped to an Aspect account: whenever the CLI authenticates (on CI via ASPECT_API_TOKEN, or locally via aspect auth login), it does so as your Aspect account.
Don’t have an account? Sign up for free at signup.aspect.build. A free account works across all Aspect products and unlocks our free Bazel courses.The first user to sign up is automatically granted the Account Admin role. Subsequent users joining the same account need an existing admin to assign them an appropriate role in the Aspect admin portal before they can install or link an App — GitHub Integration Admin for the GitHub App, GitLab Integration Admin for the GitLab App, or Account Admin for both.

Generate an Aspect API token (for CI)

CI runners are non-interactive, so they authenticate with a long-lived token instead of a browser flow.
1

Create the token

Open the API Tokens portal and select Generate Token. In the dialog:
  • Description — any label that identifies where the token will be used (e.g. ASPECT_API_TOKEN, ci-main).
  • Roles — select the GitHub Integration and/or GitLab Integration roles your CI needs. The role gates which VCS scopes tasks and features can use — see Token roles and scopes below. For most CI use cases pick GitHub CI and/or GitLab CI.
  • Expiry — the portal’s This token will expire field sets how long the token stays valid. Pick a lifetime that matches your secret-rotation policy; you’ll need to generate a new token and update CI when it expires.
2

Copy the secret

After you select Create, the portal shows a Client ID and Secret Key.
The Secret Key is shown once and never again. Copy it immediately — if you lose it you’ll need to generate a new token.
The value of ASPECT_API_TOKEN is the two strings joined with a colon:
<CLIENT_ID>:<SECRET_KEY>
3

Provide the token to CI

Store ASPECT_API_TOKEN as a secret in your CI platform and expose it to the runner. How you wire it in depends on the platform:
jobs:
  aspect-task:
    runs-on: ubuntu-latest
    permissions:
      id-token: write    # required for ArtifactUpload (and silences setup-aspect's id-token warning)
    steps:
      - uses: actions/checkout@v6
      - uses: aspect-build/setup-aspect@2306377a61c45954ab2df7c7311698b109364352 # v2026.26.9
        with:
          aspect-api-token: ${{ secrets.ASPECT_API_TOKEN }}
      - run: aspect <task> //...
On GitHub Actions, prefer the with: aspect-api-token: input over env: ASPECT_API_TOKEN:. The aspect-build/setup-aspect action receives the long-lived <CLIENT_ID>:<SECRET> only within its own step’s process, pipes it via stdin to aspect auth login --with-api-token, and persists the resulting short-lived JWT on disk. Downstream steps see only the JWT — the long-lived token is never written to GITHUB_ENV, so any other action you call in the same job (including untrusted third-party ones that read process.env) cannot exfiltrate it.Setting the token as a job-level env: exposes the raw secret to every step in the job, which is the failure mode the input-based pattern is designed to eliminate. On Buildkite, store the token as a Buildkite secret named exactly ASPECT_API_TOKEN — the CLI fetches it directly from the secret store (via buildkite-agent secret get) when the env var is unset, so the raw token never enters the job environment. The GitLab and CircleCI examples above use a CI/CD variable because no equivalent mechanism exists yet for those platforms.

Token roles and scopes

ASPECT_API_TOKEN does not itself carry any VCS permissions. It authenticates to the Aspect API, and when a feature needs to call your VCS the Aspect API uses the linked App to make the call. Which scopes a feature can use is determined by the roles assigned to your token in the API Tokens portal, bounded by the App’s own permissions (so a feature can never receive more access than the App was granted at install time). Roles are bundles of fine-grained permissions. Pick the smallest bundle that covers what your CI actually does, or pick the Integration User role for everything.

GitHub token roles and scopes

RoleGitHub installation token scope(s)Typical use
GitHub CIchecks: write, statuses: write, pull_requests: write, actions: readRecommended default for CI runners. Covers status checks and PR comments.
GitHub Integration UserAll scopes belowFull access — equivalent to every GitHub Token: role combined.
GitHub Token: checkschecks: read, checks: writeGithubStatusChecks.
GitHub Token: statusesstatuses: read, statuses: writeCommit status APIs.
GitHub Token: pull requestspull_requests: read, pull_requests: writeGithubStatusComments, GithubLintComments, and other PR-comment features.
GitHub Token: issuesissues: readRead-only issue access.
GitHub Token: actionsactions: readRead-only GitHub Actions API access.
Write implies read — assigning a *.write role automatically authorizes the matching *.read scope, so you don’t need to add both. metadata: read is always included on every token.

GitLab token roles and scopes

RoleGitLab token scopeTypical use
GitLab CIapiRecommended default for CI runners. Covers GitlabCommitStatuses, GitlabStatusComments, and GitlabLintComments.
GitLab Integration Userapi, read_apiFull access — equivalent to every GitLab Token: role combined.
GitLab Token: apiapiPosting commit statuses, creating/updating MR notes, anything else under GitLab’s broad api scope.
GitLab Token: external status checksapiPosting External Status Check responses on MRs (Premium/Ultimate tier only).
GitLab Token: MR notesapiCreating and updating merge request notes.
GitLab Token: MR readread_apiRead-only access to merge request metadata + changes.
Unlike the GitHub roles, GitLab token roles do not auto-imply each other. GitLab’s OAuth scope vocabulary is coarser than GitHub’s per-resource permission map, so role narrowing applies primarily as a permission gate; the minted token’s effective scope set is whatever the App was registered with for your role’s GitLab scope (today: api read_api).

When a role is missing

If a feature needs a scope your token’s roles don’t cover, the Aspect API returns 403 and the feature skips gracefully — the affected feature logs authentication failed for <owner>/<repo> — <reason>. Add the missing role in the API Tokens portal and re-issue the token to enable the scope.

Local development

None of the built-in Aspect CLI tasks currently need authentication when run on a developer machine — aspect <task> works locally without any auth setup. Future CLI features that interact with the Aspect API from your machine will, and when they ship you’ll authenticate by running:
aspect auth login
This walks through a device OAuth flow in your browser and stores credentials under ~/.aspect/credentials.json (mode 0600) so subsequent aspect invocations pick them up automatically. The flow needs an interactive browser session and does not work on CI runners; CI must always use ASPECT_API_TOKEN. Related commands:
  • aspect auth logout — remove stored credentials for the current profile.
  • aspect auth login --profile <name> — sign in under a named credential profile (defaults to default), useful when switching between Aspect accounts.

Troubleshooting

If authentication is unavailable (missing credentials, App not installed/linked, or not a PR/MR context), authenticating features skip their work and the underlying aspect command continues normally. They log authentication failed for <owner>/<repo> — <reason> explaining what was missing. If PR comments, MR notes, or status checks aren’t appearing as expected, check the App installation and ASPECT_API_TOKEN first — see the GitHub App or GitLab App page for provider-specific symptoms.

Support

Hit a bug or have a feature request? Open an issue on aspect-build/aspect-cli. For questions or to chat with the team and other users, join our community Slack at slack.aspect.build.