---
title: "Configure from the environment"
description: "Create providers from FORGES_* environment variables."
canonical_url: "https://docs-oquac2tli-poetry.vercel.app/guides/environment"
---
# Configure from the environment

> Create providers from FORGES_* environment variables.

`forges/env` creates providers from environment variables, so a CLI or a server can pick up credentials for any forge without code for each one. Each variable has the form `FORGES_<KIND>_<FIELD>`, such as `FORGES_GITHUB_TOKEN` or `FORGES_GITLAB_BASE_URL`.

## Create the providers

`forgesFromEnv()` reads the variables and passes every configured provider to `createForges()`:

```ts
import { forgesFromEnv } from 'forges/env'

const forges = forgesFromEnv(process.env)
```

## Report skipped forges

`providersFromEnv()` returns one entry for each set of variables. An entry has a `factory` when the variables configure a provider, and a `skipped` reason when they don't. The reason never contains a credential:

```ts
import { createForges } from 'forges'
import { providersFromEnv } from 'forges/env'

const entries = providersFromEnv(process.env)

for (const entry of entries) {
  if (entry.skipped) {
    console.warn(`Skipping ${entry.kind}: ${entry.skipped}`)
  }
}

const forges = createForges(
  entries.flatMap(entry => entry.factory ? [entry.factory] : []),
)
```

## Variables

`<KIND>` is the forge in upper case, with underscores for hyphens: `GITHUB`, `GITLAB`, `BITBUCKET`, `FORGEJO`, `GITEA`, `GITEE`, `AZURE_DEVOPS`, `CURSOR_ORIGIN`, `TANGLED` or `PUSHIN`.

These fields set the shared provider options:

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Effect
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        TOKEN
      </code>
    </td>
    
    <td>
      Sets <code>
        auth
      </code>
      
       to a token
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        BASE_URL
      </code>
    </td>
    
    <td>
      Sets <code>
        baseUrl
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        INSTANCE
      </code>
    </td>
    
    <td>
      Sets <code>
        instance
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        INSTANCE_VERSION
      </code>
    </td>
    
    <td>
      Sets <code>
        instanceVersion
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        WEBHOOK_SECRET
      </code>
    </td>
    
    <td>
      Sets <code>
        webhookSecret
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        READ_ONLY
      </code>
    </td>
    
    <td>
      Sets <code>
        readOnly: true
      </code>
      
       when the value is <code>
        1
      </code>
      
       or <code>
        true
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ENABLED
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
      
       or <code>
        true
      </code>
      
       creates an anonymous provider without a token. <code>
        0
      </code>
      
       or <code>
        false
      </code>
      
       skips the forge
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        DEMO_REPO
      </code>
    </td>
    
    <td>
      Sets <code>
        entry.demoRepo
      </code>
      
       to an <code>
        owner/name
      </code>
      
       repository for your code to use, and enables anonymous reads
    </td>
  </tr>
</tbody>
</table>

Some forges read more fields:

<table>
<thead>
  <tr>
    <th>
      Forge
    </th>
    
    <th>
      Fields
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      GitHub, Cursor Origin
    </td>
    
    <td>
      <code>
        APP_ID
      </code>
      
      , <code>
        PRIVATE_KEY
      </code>
      
       and <code>
        INSTALLATION_ID
      </code>
      
       for app auth. Write the newlines in <code>
        PRIVATE_KEY
      </code>
      
       as <code>
        \n
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      Bitbucket, Azure DevOps
    </td>
    
    <td>
      <code>
        USERNAME
      </code>
      
       and <code>
        PASSWORD
      </code>
      
       for Basic auth
    </td>
  </tr>
  
  <tr>
    <td>
      Azure DevOps
    </td>
    
    <td>
      <code>
        ORGANIZATION
      </code>
      
      , which is required
    </td>
  </tr>
  
  <tr>
    <td>
      Tangled
    </td>
    
    <td>
      <code>
        IDENTIFIER
      </code>
      
      , <code>
        PASSWORD
      </code>
      
       and an optional <code>
        PDS
      </code>
      
       for an app password. <code>
        API_URL
      </code>
      
       and <code>
        NOTIFICATIONS_URL
      </code>
      
       set the service URLs
    </td>
  </tr>
</tbody>
</table>

The [provider page](https://docs-oquac2tli-poetry.vercel.app/providers) for each forge explains what these options do.

## Configure a second instance

Add a suffix after the field to start another set of variables for the same forge. Every variable in a set has the same suffix, and `entry.suffix` holds it:

```sh
FORGES_GITHUB_TOKEN=ghp_...
FORGES_GITHUB_TOKEN_WORK=ghp_...
FORGES_GITHUB_BASE_URL_WORK=https://ghe.example.com/api/v3
```

`createForges()` throws when two providers share a forge and an instance. If two sets point at the same host, give one of them a different `INSTANCE`.


## Sitemap

See the full [sitemap](https://docs-oquac2tli-poetry.vercel.app/sitemap.md) for all pages.
