How to Connect GitHub to a DigitalOcean Harness Runtime Sessionpublic

Last verified 13 Oct 2026

DigitalOcean Harness Runtime provides managed, hardware-isolated microVM sandboxes with built-in tools such as Chromium to run harnesses and execute arbitrary code. Rich lifecycle APIs preserve conversational history and working state across sessions, letting you pause, resume, and fork work to control costs and adapt to the nonlinear nature of agentic workflows. Scale complete agents such as Claude Code or use sandboxes independently for code execution, all through the same service. See What You Can Build for example use cases.

DigitalOcean Harness Runtime sandboxes have no repository access by default. Connect a GitHub account with OAuth, then select that connection in the environment spec so hosted sessions can run authenticated git clone, git pull, and git push against private repositories without pasting a personal access token into the spec.

A GitHub connection belongs to the DigitalOcean user who creates it and is identified by an actor ID that you choose. A team can hold several GitHub connections side by side, such as one for each team member or one for each GitHub account, and creating a connection never replaces another one. Harness Runtime shares connections with Action Gateway, so a GitHub account you already connected there is available here without authorizing it again.

Connect a GitHub Account

Create a connection from doctl. Replace <actor-id> with a stable name for the GitHub account you are connecting, such as alice or alice-work. Actor IDs use up to 64 letters, digits, periods, underscores, and hyphens:

doctl harness-runtime connections create --actor <actor-id>

This starts a browser-based authorization:

  1. doctl prints an authorization URL and opens it.
  2. Approve access in the browser.
  3. doctl waits and reports that the connection is active when authorization completes.

GitHub authorizes whichever account is already signed in to your browser, and offers no account chooser. Before you approve, confirm that the authorization page shows the account you want. To connect a different account, sign out of GitHub in that browser or use a private window, then start the flow again.

Without --scopes, the connection requests the provider’s default scope set, which includes the repo scope. To request fewer scopes, pass a comma-separated list, such as --scopes repo. You can only narrow the default set; scopes outside it are rejected. Use --no-browser to print the URL instead of opening it, or --no-wait to exit without waiting and check the result later with doctl harness-runtime connections get <connection-id>.

If the actor already has an active GitHub connection, the command reports that and does not start a new authorization. To connect a different GitHub account, use a different actor ID, and sign in to that account in the browser before you approve.

You can also connect a new account from the GitHub connection picker when you create an environment in the Control Panel.

Select a Connection

Selecting a connection takes two steps: find the actor ID of the connection you want, then name it in the environment spec. You select the connection in the spec, so the environment uses the same connection every time a session starts from it.

List Your GitHub Connections

List the GitHub connections available to you:

doctl harness-runtime connections list

Each entry shows the actor ID, status (active, pending, or expired, which means the authorization was not completed before its link expired), connection ID, and granted scopes. Add --actor <actor-id> or --status <status> to filter the list.

The list shows only connections that you own. Other team members’ connections do not appear, and the Control Panel picker offers the same set, because only a connection’s owner can select it for a new environment.

Name the Connection in the Environment Spec

Add a secrets slot with source: oauth, provider: github, and the connection’s actor. The slot name is the environment variable the token appears as inside the sandbox:

name: my-first-agent
agent: codex
size: mars-2vcpu-4gb
repos:
  - <your-org>/<your-private-repo>
env:
  MODEL: gpt-5.4
secrets:
  OPENAI_API_KEY: ${OPENAI_API_KEY}
  GITHUB_TOKEN:
    source: oauth
    provider: github
    actor: <actor-id>
permissions:
  default: ask
Warning

Declare the GitHub credential under secrets. Do not put tokens in env. DigitalOcean brokers the OAuth token server-side and never persists it as plaintext in the stored spec.

When you create the environment, DigitalOcean saves it as an Environment Config and authorizes the selected connection for it as you, the config’s creator. This happens for every session you create from a spec, including with doctl harness-runtime launch and the Control Panel. Team members who start sessions from the config then use that connection, even though they do not own it and do not see it in their own connection list. They cannot select your connection in a spec of their own.

If the selected connection cannot be resolved, session creation fails instead of falling back to another connection, so the agent never acts as a GitHub account the spec did not name.

The short form GITHUB_TOKEN: oauth/github, with no actor, uses the single team-wide connection created by doctl harness-runtime auth github. Both the shorthand and the command still work, so existing specs do not need to change. For new specs, name an actor so the environment uses a specific connection.

Run a Repository Workflow

Attach to the session and ask the agent to perform the GitHub workflow you need. For example:

Clone the private repo github.com/<owner>/<repo> using the GITHUB_TOKEN from your env. Create a new branch, update README.md with a Hello World section, commit, push the branch, and open a pull request against main. Share the PR link when done.

Approve the clone and push prompts as they appear.

The token is resolved once, when the session is created, and injected into the sandbox environment. Re-authorizing or revoking a connection afterward does not reach a session that is already running or paused. To pick up a new credential, create a new session.

With the oauth/github shorthand, a session created before the team connected GitHub does not have GITHUB_TOKEN. Create a new session after connecting.

Revoke a Connection

Revoke a connection to remove its GitHub access from DigitalOcean. Find the connection ID with doctl harness-runtime connections list, then revoke it:

doctl harness-runtime connections revoke <connection-id>

You can revoke only connections you own.

Revoking is blocked while any Environment Config still depends on the connection, and the error names those configs. Because every session you create from a spec saves a config that remains after the session ends, the list can include configs you did not create explicitly.

Configs are immutable and cannot be edited to drop the connection, so delete each one the error names. The error identifies configs by name, and config delete takes a config ID, so look up each ID with doctl harness-runtime config list, then delete the config:

doctl harness-runtime config delete <config-id>

If a config has many dependents, the error lists only some of them, so revoke again after deleting them to see whether others remain. A config cannot be deleted while it has active sessions, so remove those sessions first. Then revoke the connection again.

Revoking removes the connection only inside DigitalOcean. The OAuth grant on GitHub stays in place until you remove it from your GitHub authorized OAuth apps. Sessions that are already running keep the token they received when they were created, so to cut off access immediately, revoke the grant on GitHub as well.

Reconnect a GitHub Account

Reconnect an account when its token stops working, for example after the grant was revoked on GitHub. Creating a connection for an actor that is already active does not reauthorize it, as described in Connect a GitHub Account, so replace the connection instead:

  1. Delete the Environment Configs that use the connection, as described in Revoke a Connection. Team members who start sessions from those configs cannot use them until you re-create them.
  2. Revoke the connection with doctl harness-runtime connections revoke <connection-id>.
  3. Create it again with the same actor ID, using doctl harness-runtime connections create --actor <actor-id>.
  4. Create new sessions or configs from your spec.

A config is bound to the connection that existed when the config was created. The revoke guard normally prevents a config from outliving its connection, but a connection can still be removed while configs depend on it, for example by force-deleting it from the Action Gateway Connections page. Sessions started from such a config fail with an error that says to reconnect and re-create the agent.

Limitations

  • Organization-wide access: A connection is a GitHub OAuth App grant that, with the default scopes, includes the repo scope across every organization and repository the GitHub account can reach. There is no per-repository scoping. To limit access to specific repositories, use a personal access token.
  • Connection limit: GitHub issues at most 10 tokens for one GitHub account with the same scopes through DigitalOcean’s OAuth app. Creating an 11th connection for that account invalidates the token behind the oldest one, and sessions using it begin failing authentication. To recover, reconnect the account.
  • Long-lived tokens: Tokens do not expire and are not refreshed automatically.
  • Revocation on GitHub: DigitalOcean does not detect a grant revoked from GitHub’s settings. Inside the sandbox it appears as an ordinary git authentication failure, not as a DigitalOcean error, and the connection still shows as active. To recover, reconnect the account.
  • Running sessions: A session keeps the connection it started with. To use a different connection or account, create a new session.

Use a Personal Access Token

If you prefer a token you manage yourself, create one at GitHub personal access tokens with the repo scope (or a fine-grained token with Contents: Read and the write permissions you need). Then declare it under secrets:

repos:
  - <owner>/<repo>
secrets:
  GITHUB_TOKEN: ${GITHUB_TOKEN}

Export the token in your shell so doctl can expand ${GITHUB_TOKEN} before upload:

export GITHUB_TOKEN=<your-github-pat>

We can't find any results for your search.

Try using different keywords or simplifying your search terms.