# Read private NuGet packages.

Give Perfloop access to the GitHub Packages NuGet feeds your builds need. In every workspace, an Admin saves the credential in Setup. Connecting a repo through the GitHub App supplies no package credential.

## Supported registries and packages

Setup supports credentials for NuGet feeds on GitHub Packages at `nuget.pkg.github.com`. Credentials for other registries and package types are not supported, including Azure Artifacts, self-hosted feeds, npm, Maven and container registries. Public package downloads use your workspace's network access settings. Package publication is not supported.

## Access you need

GitHub Packages requires a personal access token (classic) for this NuGet connection. Fine-grained personal access tokens and GitHub App installation tokens are not supported. The `GITHUB_TOKEN` exception applies to GitHub Actions workflows, not Perfloop Sessions.

A classic PAT cannot be scoped to one organization or package. Use a dedicated machine-user account with read access only to the packages needed for these builds. Review its organization and team memberships, inherited repository permissions, and access to internal packages. Explicit package grants do not remove access the account gets through those other paths.

## Setup

### 1 · grant package access

For each required package, open its settings in GitHub. Under **Manage access**, select **Invite teams or people**, add the machine-user account, and give it the **Read** role. The account must also be an organization member to read private or internal organization packages. Check the package's visibility and inherited permissions before relying on an explicit grant.

### 2 · create a read-only token

Sign in as the machine user. Open **Settings → Developer settings → Personal access tokens → Tokens (classic)** and generate a token. Select only `read:packages`. Do not add `repo`, write, or delete scopes. Set an expiration date. If the organization uses SAML SSO, authorize the token for that organization through **Configure SSO**.

Keep the token in your secret store. Enter it only in Setup, never in chat, source files, package-manager configuration, or an MCP call.

### 3 · save the feed in Perfloop

As a workspace Admin, open **Setup → Network access → Private registries**. Under **Supported registries**, select **Add feed** on **GitHub Packages (NuGet)**. Enter the package owner in **Organization or user**; Setup shows the feed address it saves, such as `https://nuget.pkg.github.com/YOUR-ORG/`. Enter the machine user's GitHub login in **GitHub username** and its token in **Classic personal access token**. Select **Save and test**.

The saved feed permits HTTPS package reads across eligible Sessions in the workspace, not only one repo. It grants no package publication. You do not need a separate destination Allow for that feed.

Keep the package source in your repo's `NuGet.Config`. Use the saved feed address exactly, including the owner's capitalization, and append `index.json`, for example `https://nuget.pkg.github.com/YOUR-ORG/index.json`. Keep credentials out of that file. Setup supplies the saved credential when Perfloop restores packages from this feed.

Saving a GitHub Packages NuGet feed also permits HTTPS downloads from `*.blob.core.windows.net`. You do not need to allow those download hosts separately. This covers subdomains across Azure storage accounts, not only the account GitHub uses. Download addresses can carry data out. Perfloop sends no registry token or cookies to those hosts. Other download hosts still need separate network access.

Saving alone does not check whether GitHub accepts the credential, so Setup then makes one test read of the feed and shows the result on the saved row: **Read OK**, **Token rejected** (401), **Access refused** (403), **Unreachable** or the HTTP status, with when it happened. Later, the row can also show a result recorded during a restore, with its time. It does not show every read. A failed test leaves the feed saved. Select **Replace token** or **Test again** on the row after you fix the account or token. Replacing the token clears its previous status and tests the new one.

A successful response does not prove a package restore. A 401 or 403 does not identify the cause. Check the account's package access, token scope, expiry, and SSO authorization. Replace the saved credential if needed. Authentication errors do not pause work automatically.

## Data Perfloop reads and keeps

Perfloop reads feed metadata and package content within the saved prefix, and packages from the download hosts above. Those bytes are available to its work and can remain in build caches. Credentials are stored encrypted and scoped to the workspace and the saved feed address. Another workspace cannot use your saved credential. Perfloop does not put the token in the build environment or package-manager configuration, and never displays a saved token again. See [Security](https://perfloop.ai/security) for data handling.

## Replace a token

Before expiry, create a replacement token with the same limited permissions and required SSO authorization. In Setup, select **Manage**, then **Replace token** on the saved feed. Enter the username and replacement token, then select **Replace and test**. Revoke the replaced token in GitHub too. To change the feed address, remove the feed and add another.

## Remove access

Select **Manage**, then **Remove feed** on the saved feed and confirm. This removes that credential and prefix grant. Removing the last GitHub Packages NuGet feed also removes the download access described above. Separately saved network destinations remain in place; remove those in **Public destinations** if you no longer need them. A shorter saved parent prefix can still provide feed access. Requests already in progress can finish, and downloaded packages remain in caches. Revoke the token in GitHub to remove its upstream access too.

Security questions: [security@perfloop.ai](mailto:security@perfloop.ai?subject=Private%20registry%20access)
