The GitHub integration lets recipes listen for repository events through the Neurocad GitHub App, call the GitHub REST API to read files and pull-request data, and route events to the right recipe by repository. Two things have to be in place before a GitHub-driven recipe will run end-to-end:
There is no per-user link step the way Slack has — GitHub events aren't user-invoked, so the bot/user identity gating that drives /neurocad link doesn't apply here.
The rest of this doc walks through each of those, then covers the GitHub trigger and GitHub action nodes.
In Neurocad, go to /connect → GitHub → Add connection. Unlike a typical OAuth app, this kicks off a GitHub App install flow:
What's stored on the connection: the GitHub App installationId, the current installation access token (a short-lived bearer; see below), the token's expiry timestamp, the stable account id, the account login, and the account type (User / Organization). The stable account id is what every trigger registration and inbound webhook routes on — install ids rotate when an install is removed and re-added, but account ids don't.
GitHub App installation tokens are valid for one hour. You don't need to do anything to keep them fresh — before each request, the credential checks the stored expiry, and if it's missing, unparseable, or within 5 minutes of expiring, it mints a new one through the platform's signed App JWT and updates the stored token. Subsequent calls in the same execution use the refreshed token.
If the platform can't mint a token (the GITHUB_APP_ID or GITHUB_APP_PRIVATE_KEY_B64 environment variables are missing on the host), executions fail with a clear error: "GitHub installation token is stale but this execution host has no GitHub App token minter configured. Ensure GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY_B64 are set on the host." That's an operator config issue, not a user-fixable one.
Like Slack, the connection can drift away from a healthy state via lifecycle events GitHub delivers to the App:
There's no needs_reauth state for GitHub — the App's install is either present or not. Tokens are refreshed transparently as long as the install exists.
If you delete the connection from /connect, Neurocad calls DELETE /app/installations/{installationId} against GitHub using the App-level JWT (an installation token can't manage its own install). This actually removes the App from the GitHub account/org — not just from Neurocad. To put it back, run the install flow again from /connect.
This is the GitHub equivalent of "invite the bot to the channel." The App can only see repos that are explicitly covered by the install. You manage that on github.com, not in Neurocad:
If a recipe references a repository the App isn't installed on, the GitHub trigger never fires for it (events for that repo are simply not delivered to Neurocad) and the GitHub action node gets 404s when it tries to read files. Fix is always: install or extend the App's repository access on github.com.
GitHub trigger starts a recipe when a configured webhook event arrives for a specific repository. The credential is githubApi. With the GitHub App delivery model, webhooks arrive automatically for every repo the App is installed on — there's a single Request URL configured on the App itself (/api/github/webhooks), so activation is purely about writing a routing entry. There's no per-repo POST /repos/{owner}/{repo}/hooks call.
A repository field with two modes:
The chosen repository is stored as owner/repo and lowercased on activation. That string is the trigger's routing key.
Multi-select of GitHub webhook event types this trigger fires on. The list is the repository-routable subset of GitHub's event taxonomy — events whose payloads reliably carry a top-level repository. Pick Any event (the leading *) to receive every supported event for the chosen repository.
Account-level, organization-level, and App-lifecycle events (e.g. installation, installation_repositories, installation_target) are deliberately not in this list — they require an account-scoped trigger shape, which is not the contract this node implements. Those events are still consumed internally by the platform for credential lifecycle (e.g. flipping a connection to uninstalled), they just aren't routed to user recipes.
The property panel's Listen button works the same way as for Slack: click Listen, then push a commit / open a PR / etc. on the watched repo, and Neurocad captures one real GitHub event so the rest of the graph has a real payload to wire against.
Under the hood, activation registers an entry keyed by:
When a webhook arrives at /api/github/webhooks, the platform:
You don't configure any of that — it's a contract the trigger node satisfies on your behalf — but knowing the shape helps when something doesn't fire.
GitHub is the outbound action node. Like Slack, it exposes a Resource + Operation selector. The credential is githubApi, and every request goes out through the installation token using GitHub's pinned API version (X-GitHub-Api-Version: 2022-11-28).
Compare two refs and return one workflow item per changed file. GitHub includes up to 300 changed files per compare — beyond that, you'll need a different shape.
Inputs:
This is the heart of the GitHub file change to Slack preset — push a commit, fan out one item per changed file, send each to a downstream node.
Fetch a single file's contents at a chosen ref.
Inputs:
The response is requested as application/vnd.github.raw and exposed as a binary on the workflow item under field name data. Downstream nodes (Library, Schematic, Create share link) can wire the binary directly without needing a base64 decode step.
List the files changed by a pull request, paginated. GitHub's per_page is capped at 100; this operation paginates through all pages automatically.
Inputs:
Most GitHub action errors come down to App access: the installation can't see the repo you asked about. The fix is on github.com — extend the install's repository access — not in Neurocad. If the install was uninstalled entirely, reconnect from /connect.
The built-in GitHub file change to Slack preset is the canonical example:
GitHub trigger (push to a repo)
→ GitHub (compare → List changed files, before/after wired from $json)
→ GitHub (file → Get, fetches the file at the new ref)
→ Library
→ Create share link
→ Slack (message → Send the share URL to a chosen channel)
The preset's first canvas note spells out the same checklist: "This recipe requires your GitHub connection. Navigate to /connect and add it there first. Then install the Neurocad GitHub app on the repository you want to watch. Select GitHub trigger and choose the repository, branch, and file path to watch."
A simpler PR-driven shape:
GitHub trigger (pull_request)
→ GitHub (pull request → List files)
→ GitHub (file → Get for the changed file)
→ Library
→ Create share link
→ Slack (message → Send to #ops)
You can also use a GitHub trigger purely as a manual ping mechanism — fire on release or workflow_run to kick off downstream regeneration whenever a release or CI run completes.
GitHub recipes are deployable — they start from a server-side trigger and only use Connect / EDA / MDA nodes. Once the recipe is shaped:
Two activation-time errors are worth knowing:
There is no command-word collision check the way Slack has, because GitHub doesn't use slash commands here — two recipes can subscribe to the same (repo, event) and both will fire on the same delivery.
If you've read the Slack doc, here's the quick translation:
If a GitHub-driven recipe isn't firing, walk this list — almost every "it's not working" report is one of these:
If all of those pass and it's still silent, capture a real event with the GitHub trigger's Listen button. That's the cheapest test for "is GitHub actually reaching this workflow," separate from whether downstream nodes are succeeding.
Last updated May 7, 2026