| 1 | --- |
| 2 | title: Setup |
| 3 | description: Connect alchemy to GitHub — account, credentials, and profiles. |
| 4 | --- |
| 5 | |
| 6 | Register the provider next to your cloud's: |
| 7 | |
| 8 | ```typescript |
| 9 | // alchemy.run.ts |
| 10 | import * as GitHub from "alchemy/GitHub"; |
| 11 | |
| 12 | providers: Layer.mergeAll(Cloudflare.providers(), GitHub.providers()), |
| 13 | ``` |
| 14 | |
| 15 | Run `alchemy profile edit --add GitHub` and pick between two local options: |
| 16 | |
| 17 | - **`gh` CLI** — shells out to `gh auth token` (recommended). |
| 18 | - **Stored PAT** — a personal access token entered interactively, |
| 19 | saved under `~/.alchemy/credentials/<profile>/`. |
| 20 | |
| 21 | When `CI=true`, profiles are bypassed and Alchemy reads |
| 22 | `GITHUB_ACCESS_TOKEN` or `GITHUB_TOKEN` directly. |
| 23 | |
| 24 | See [Profiles](/environments/profiles) for how credentials are stored |
| 25 | and switched. |
| 26 | |
| 27 | ## GitHub Enterprise |
| 28 | |
| 29 | Both profile methods and CI environment credentials work against GitHub Enterprise Server and GitHub |
| 30 | Enterprise Cloud with data residency. `alchemy profile edit |
| 31 | re-configure GitHub` prompts for the host. Leave it blank for github.com, or enter your |
| 32 | enterprise host (e.g. `github.example.com` or `acme.ghe.com`). |
| 33 | |
| 34 | The host is normalized into the REST API base URL automatically: |
| 35 | |
| 36 | - `github.example.com` → `https://github.example.com/api/v3` (GHES) |
| 37 | - `acme.ghe.com` → `https://api.acme.ghe.com` (data residency) |
| 38 | - an explicit URL like `https://github.example.com/api/v3` is used as-is |
| 39 | |
| 40 | Alternatively, set the host in the environment — `GITHUB_BASE_URL`, |
| 41 | `GITHUB_API_URL` (set automatically on GitHub Actions runners), or |
| 42 | `GH_HOST` — and every method picks it up without reconfiguring. On an |
| 43 | enterprise host, CI environment resolution also honors the `gh` |
| 44 | CLI's `GH_ENTERPRISE_TOKEN` / `GITHUB_ENTERPRISE_TOKEN` before falling |
| 45 | back to `GITHUB_ACCESS_TOKEN` / `GITHUB_TOKEN`, and the `gh` CLI method |
| 46 | runs `gh auth token --hostname <host>` (run |
| 47 | `gh auth login --hostname <host>` once first). |
| 48 | |
| 49 | ### Pin the host in code |
| 50 | |
| 51 | To fix the host for the whole app — independent of profile |
| 52 | configuration or the environment — pass it to `providers()`: |
| 53 | |
| 54 | ```typescript |
| 55 | providers: GitHub.providers({ baseUrl: "github.example.com" }), |
| 56 | ``` |
| 57 | |
| 58 | The auth provider sees the pinned host too: the configure flow stops |
| 59 | prompting for it and authenticates against it directly. |
| 60 | |
| 61 | ### Per-resource host override |
| 62 | |
| 63 | Every GitHub resource also takes its own `baseUrl` prop, so a single |
| 64 | stack can span github.com and an enterprise instance: |
| 65 | |
| 66 | ```typescript |
| 67 | yield* GitHub.Repository("mirror", { |
| 68 | owner: "my-org", |
| 69 | name: "mirror", |
| 70 | baseUrl: "github.example.com", |
| 71 | }); |
| 72 | ``` |
| 73 | |
| 74 | Resolution order is: resource `baseUrl` → `providers({ baseUrl })` → |
| 75 | the host from the login profile or environment. Changing a resource's |
| 76 | `baseUrl` replaces it — the same name on a different GitHub instance |
| 77 | is a different physical resource. |
| 78 | |
| 79 | ## Token scopes |
| 80 | |
| 81 | - `repo` — always required. |
| 82 | - `workflow` — when you manage [Actions secrets and variables](/github/actions-config). |
| 83 | - `delete_repo` — only when you opt a [repository](/github/repository) |
| 84 | into deletion via `destroy()`. Repositories default to retain on |
| 85 | removal, so most tokens never need it. |
| 86 | |
| 87 | ## Programmatic credentials |
| 88 | |
| 89 | Skip profiles entirely by building the credentials layer from a token |
| 90 | you already have in hand — useful in tests: |
| 91 | |
| 92 | ```typescript |
| 93 | Effect.provide(GitHub.fromToken(token)) |
| 94 | ``` |
| 95 | |
| 96 | `fromToken` accepts a plain string or a `Redacted` value, plus an |
| 97 | optional `baseUrl` for GitHub Enterprise: |
| 98 | |
| 99 | ```typescript |
| 100 | Effect.provide(GitHub.fromToken(token, { baseUrl: "github.example.com" })) |
| 101 | ``` |
| 102 | |
| 103 | To read from the environment instead, `GitHub.fromEnv()` builds the |
| 104 | same layer from `GITHUB_ACCESS_TOKEN` or `GITHUB_TOKEN` (and resolves |
| 105 | the enterprise host from `GITHUB_BASE_URL` / `GITHUB_API_URL` / |
| 106 | `GH_HOST` when set). |
| 107 | |
| 108 | ## Next steps |
| 109 | |
| 110 | - [GitHub overview](/github) — resources and compositions. |