Every provider takes a token or API key created in its own UI. Three also support signing in through the browser, which needs an OAuth application registered with the provider; the ids for the hosted services are compiled in once registered, and a self hosted server needs its own.
Credentials are kept in the platform's secret store: the Windows Data Protection API for the current user, the macOS login Keychain, or the Secret Service on Linux through secret-tool, falling back to a file only the user can read. settings.json never holds one.
| Provider | Credential | Where to create it | What it needs |
|---|---|---|---|
| AppVeyor | API token | https://ci.appveyor.com/api-keys | A v1 token works as is. A v2 (user level) token also needs the account name in the connection. |
| Azure DevOps | Personal access token | User settings, Personal access tokens (see the docs) | Build: Read & execute, and Code: Read to tell when a failed branch is gone |
| Bitbucket Pipelines | API token | https://id.atlassian.com/manage-profile/security/api-tokens | Scopes read:pipeline:bitbucket, write:pipeline:bitbucket, read:repository:bitbucket, read:workspace:bitbucket, and read:pullrequest:bitbucket to tell when a failed branch is gone. Enter the Atlassian account email as the user. App passwords stopped working in June 2026. |
| GitHub Actions | Personal access token | Fine grained: https://github.com/settings/personal-access-tokens/new. Classic: https://github.com/settings/tokens | Fine grained: Actions read and write, Metadata read, on the repositories to watch, and Pull requests read and Contents read to tell when a failed branch is gone. Classic: repo. |
| GitLab CI | Personal access token | https://gitlab.com/-/user_settings/personal_access_tokens | api to retry and cancel, read_api to only watch |
| GoCD | Personal access token | https://<server>/go/access_tokens |
No scopes |
| Jenkins | API token | https://<server>/me/security |
Enter the Jenkins user name as the user |
| Octopus Deploy | API key | Profile, My API Keys (see the docs) | The user's permissions, with TaskCancel to cancel |
| TeamCity | Access token | Profile, Access Tokens (see the docs) | Same as the user, or limited to a project |
| Travis CI | API token | https://app.travis-ci.com/account/preferences | No scopes |
The connection editor links to the right page for the chosen provider.
| Provider | Browser | Device | Notes |
|---|---|---|---|
| GitHub Actions | Yes, with a registered OAuth App that has a client secret | Yes | The device flow needs only a client id and is the default. |
| GitLab CI | Yes, PKCE | Yes | Scopes read_api and api. A self hosted GitLab needs its own application; enter its id in the connection. |
| Azure DevOps | Yes, PKCE through Microsoft Entra ID | Yes | Work or school accounts only; Entra does not sign personal Microsoft accounts in to Azure DevOps. |
The browser flow opens the provider's sign in page in the default browser and listens on a loopback port for the redirect back. The device flow shows a code to enter on a page the browser opens, and needs no listener. The code goes on the clipboard as soon as it arrives, since the page shows it as a label and no toolkit lets a label be selected; Copy code puts it back for a clipboard that has moved on since.
The listener takes whatever port is free. GitHub and Microsoft Entra accept a loopback redirect on any port, and so does gitlab.com. A self hosted GitLab whose application was registered with a port in its redirect URI, such as http://127.0.0.1:8420/callback, needs that port entered as the connection's callback port so the redirect matches.
Refresh tokens are stored beside the access token and used when a poll is refused. If that fails too the connection shows "sign in required" and the tray icon turns amber until it is signed in again.
The ids for github.com, gitlab.com and Microsoft Entra are compiled into OAuthClients.cs, so sign in works without any setup. A self hosted GitLab or GitHub Enterprise Server needs its own registration, made as below, with its id entered in the connection editor.
https://github.com/settings/applications/new
- Application name:
BuildMonitor - Homepage URL:
https://github.com/SimonCropp/BuildMonitor - Authorization callback URL:
http://127.0.0.1/callback - Tick Enable Device Flow
- After creating, copy the Client ID into
GitHubClientId. The device flow needs only that. For the browser flow also generate a client secret and put it inGitHubClientSecret; it is embedded the way the GitHub CLI embeds its own, a secret in name only.
GitHub Enterprise Server: the same form under the server's own settings; the callback URL is unchanged.
https://gitlab.com/-/user_settings/applications
- Name:
BuildMonitor - Redirect URI:
http://127.0.0.1/callback - Untick Confidential
- Scopes:
read_apiandapi - After creating, copy the Application ID into
GitLabClientId. The secret is unused.
Self hosted GitLab: the same form under the instance's user settings. If the instance insists on an exact redirect match including a port, register http://127.0.0.1:<port>/callback and enter that port as the connection's callback port.
https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/CreateApplicationBlade
- Name:
BuildMonitor - Supported account types: Accounts in any organizational directory (multitenant)
- Redirect URI: platform Public client/native (mobile & desktop), value
http://localhost - After creating, under API permissions add Azure DevOps, Delegated,
user_impersonation - Under Authentication, set Allow public client flows to Yes, which the device flow needs
- Copy the Application (client) ID from Overview into
EntraClientId
Entra does not sign personal Microsoft accounts in to Azure DevOps; those users take a personal access token. The authority is /organizations, which only accepts a work or school account, so a personal account is turned away at Microsoft's own page as an address it does not recognise rather than as a method that does not apply. The connection editor says so under Sign in with before the flow is started.
How much a failure can say depends on how far the sign in got. Where Entra authenticates someone and only then finds the account belongs to no tenant it accepts, it redirects back with AADSTS50020, and BuildMonitor names the cause instead of showing the raw text. Where it refuses at its own address box it tells BuildMonitor nothing at all: the flow runs out of time with Microsoft still waiting, so the timeout offers the same advice as a possibility rather than a diagnosis. Entra's own wording, with the trace id a support request needs, goes to the log either way.
Sign in opens a listener on 127.0.0.1 on whatever port is free, sends the browser to the provider with that port in redirect_uri and a random state, and receives the one-time code when the provider redirects back. RFC 8252 requires an authorization server to accept any port on a loopback redirect, because a desktop app cannot know in advance which port will be free, and GitHub, gitlab.com and Entra all do. The request never leaves the machine, and PKCE means a code is useless without the verifier the app kept in memory.