Skip to content

GitHub Gist Store

Store subscribers in a private GitHub Gist — ideal for public repos where you can’t commit a subscribers.json file without exposing email addresses.

The JSON file store requires subscribers.json to be checked into the repo so GitHub Actions can read it. In a public repo, that means subscriber emails are visible to anyone. The Gist store solves this by keeping the same JSON format in a private Gist that’s only accessible via the GitHub API with a token.

Create a new secret Gist with a file named subscribers.json:

[]

Copy the Gist ID from the URL (e.g., https://gist.github.com/yourname/abc123def456abc123def456).

The default GITHUB_TOKEN in Actions is scoped to the repository and cannot access private gists. Create a classic PAT and check the gist scope.

Terminal window
gh secret set SUBSCRIBERS_GIST_ID --body "abc123def456"
gh secret set SUBSCRIBERS_GIST_TOKEN --body "ghp_your_pat_here"
Terminal window
export SUBSCRIBER_STORE=gist
export GITHUB_GIST_ID=abc123def456
export GITHUB_TOKEN=ghp_your_pat_here
VariableRequiredDescription
GITHUB_GIST_IDYesID of the private Gist
GITHUB_TOKENYesClassic PAT with gist scope (fine-grained PATs do not support gists; the default Actions token cannot access private gists)

The Gist uses the same JSON format as the JSON file store:

[
{
"email": "alice@example.com",
"name": "Alice",
"productIds": ["my-app", "other-app"]
},
{
"email": "bob@example.com",
"productIds": ["my-app"]
}
]

Audience compound keys work the same way:

[
{
"email": "alice@example.com",
"productIds": ["my-app:beta"]
}
]

Sent emails are logged to an email-log.json file in the same Gist (created automatically on first send).

- uses: atriumn/cryyer/.github/actions/send-file@v0
with:
product: my-app
draft-path: drafts/v1.2.0.md
from-email: updates@yourdomain.com
email-api-key: ${{ secrets.RESEND_API_KEY }}
subscriber-store: gist
github-gist-id: ${{ secrets.SUBSCRIBERS_GIST_ID }}
github-token: ${{ secrets.SUBSCRIBERS_GIST_TOKEN }}

You can manage subscribers through any of the standard Cryyer interfaces:

  • MCP tools: add_subscriber, remove_subscriber, list_subscribers
  • Directly: Edit the Gist at https://gist.github.com/{id}
  • GitHub CLI: gh gist edit {id}