GitHub token
A least-privilege GitHub token for one project, stored in 1Password and attached to it.
A project that calls GitHub’s API (reading repositories, stars, releases)
needs its own token: not the one gh uses (GitHub),
which can write to your repositories. One token per project, with only what
that project needs, so revoking it breaks nothing else.
Creating it is manual on purpose: GitHub has no API that creates personal access tokens, so no tool can do it for you.
1. Create the token (once per project)
Open https://github.com/settings/personal-access-tokens/new:
- Token name:
<project>-github, the same name it gets in 1Password. - Expiration: your choice. A date means renewing it (see Renewing).
- Repository access:
- Public repositories if the project only reads public data. It then gets read access to every public repository on GitHub and nothing else.
- Only select repositories if it works with specific repositories of yours, and then only the permissions it needs, such as Contents: Read.
- Permissions: none beyond what the project’s documentation asks for.
Generate it and copy it: it’s shown only once. GitHub may ask for 2FA first.
2. Store it (once per project)
dot secret add <project>-github
Paste the token when asked; it isn’t shown while you type. The command stores it in your development vault and prints the next command to run.
3. Attach it to the project
From the project’s folder, with the variable name the project reads
(usually GITHUB_TOKEN):
dot secret attach <project>-github GITHUB_TOKEN
The project needs a .env.schema that loads Varlock’s 1Password plugin
first; if it doesn’t have one, the command says what’s missing
(README.md).
4. Check it
From the project’s folder:
varlock run -- sh -c 'curl -s -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/rate_limit' | grep -m1 '"limit"'
"limit": 5000 means GitHub accepted the token; without one it’s 60. The
token only exists inside that command.
Friction
| Criterion | GitHub token for a project |
|---|---|
| Time | not measured |
| Browser | once per token, to create it |
| 2FA | when GitHub asks, while creating it |
| Per machine | nothing: 1Password syncs it to every Mac |
| Expires | as set when creating it |
| Secret on disk | no |
Renewing
GitHub emails you before a token expires. Create a new one (step 1), then:
dot secret update <project>-github
The reference stays the same, so the project picks up the new value on its next run.
Alternative: a GitHub App
A job that runs unattended, on a server or a schedule, can use a GitHub App instead: the app mints tokens through the API that expire in an hour, so nothing long-lived needs renewing. It takes more setup: the app, its private key in 1Password, and code that exchanges one for the other.