GitHub Integration
Last updated: 2025-12-03Overview
KanbanAI integrates with GitHub to:- Authenticate users via the OAuth Device Authorization Flow.
- Import issues into project boards as cards.
- Automatically sync issues in the background for projects that opt in.
- Optionally create GitHub issues when you create new tickets, keeping them linked.
- Create pull requests from attempt branches, keeping tickets, attempts, and PRs linked.
OAuth App & credentials
- KanbanAI expects a GitHub OAuth App with Device Flow enabled.
- You can provide the OAuth Client ID and Client Secret in three ways:
- During onboarding (
/onboarding). - From Settings → App → GitHub OAuth App.
- Via environment variables in
server/.env:GITHUB_CLIENT_IDGITHUB_CLIENT_SECRET
- During onboarding (
- Credentials are stored locally in SQLite; there is no remote storage.
- When both DB config and environment variables are present, the server prefers the stored configuration and falls back to env only when necessary.
Device Authorization Flow
The GitHub module implements Device Flow using dedicated endpoints:POST /auth/github/device/start- Starts the device flow and returns a
device_code,user_code, and verification URL.
- Starts the device flow and returns a
POST /auth/github/device/poll- Polls GitHub until the user completes verification in the browser.
- On success, stores tokens and emits
github.connected.
GET /auth/github/check- Returns the current connection status for the sidebar and settings UI.
POST /auth/github/logout- Revokes stored credentials and emits
github.disconnected.
- Revokes stored credentials and emits
GET /auth/github/app– returns the effective GitHub OAuth App configuration and whether it came from the DB or env.PUT /auth/github/app– updates the stored OAuth App config (clientId,clientSecret).
Importing and syncing issues
- Once GitHub is connected, you can import issues into a project’s board:
POST /projects/:projectId/board/import/github/issues- or
POST /boards/:boardId/import/github/issues
- The import service:
- Fetches issues from the configured repository.
- Creates or updates cards on the target board.
- Emits
github.issues.importedwith the number of issues processed.
- Imported cards retain links back to the originating GitHub issues so you can navigate between the board and GitHub.
- When GitHub Issue Creation is enabled in a project’s settings, the Create Ticket dialog exposes a per‑ticket Create GitHub Issue checkbox.
- If checked, KanbanAI creates a new issue in the project’s origin repository using the ticket title and description.
- The created issue is stored in
github_issueswithdirection = 'exported', so the card displays a clickable#<issueNumber>badge. - Subsequent edits to the ticket’s title or description automatically PATCH the exported GitHub issue to stay in sync.
- If issue creation fails, the ticket is still created and the client shows an error toast.
Background Issue Sync
- Each project has optional GitHub Issue Sync settings, exposed via:
GET /projects/:projectId/settingsPATCH /projects/:projectId/settings
- Settings live alongside other project settings:
githubIssueSyncEnabled: boolean– opt in/out of automatic sync (defaultfalse).githubIssueSyncState: 'open' | 'all' | 'closed'– which issue states to sync (defaultopen).githubIssueSyncIntervalMinutes: number– how often to sync (default15, min5, max1440).githubIssueAutoCreateEnabled: boolean– enables per‑ticket GitHub issue creation (defaultfalse).autoCloseTicketOnIssueClose: boolean– automatically move cards to Done when their linked GitHub issue is closed (defaultfalse).
- When enabled and a valid GitHub connection + origin (
owner/repo) exist:- A lightweight scheduler in the server periodically selects eligible projects.
- For each project, it checks the last sync metadata stored in
project_settings:lastGithubIssueSyncAt: Date | nulllastGithubIssueSyncStatus: 'idle' | 'running' | 'succeeded' | 'failed'
- If the interval has elapsed and no sync is currently running, it calls
importGithubIssueswith the configured state.
- Sync runs are fully logged via the structured server logger using the
github:syncscope, including:- Start/end of each scheduled sync run with project + repo context.
- Counts of new/updated/skipped issues.
- Per-issue logging when cards are created or updated.
- The Project Settings UI also surfaces aggregated counts of linked issues (
imported,exported,total) by calling/boards/:boardId/github/issues/statswhen the GitHub connection and board context are available, so you can see how many issues have already been synced or exported. - Cards that are mapped in
github_issuesexpose a#<issueNumber>badge in the board and inspector UI; clicking it opens the GitHub issue in a new tab.
Pull requests
- Attempts and projects can create pull requests through project-scoped endpoints:
POST /projects/:projectId/pull-requestsGET /projects/:projectId/pull-requestsGET /projects/:projectId/pull-requests/:number
- When creating a PR, the payload can include:
branch– the attempt or feature branch to PR.attemptId– associates the PR with an Attempt.cardId– links the PR back to a board card.
- The PR helper emits
github.pr.createdso other modules can react (for example, refreshing PR lists or updating activity feeds). - For inline PR summaries (title + body suggestions), the API also exposes:
POST /projects/:projectId/pull-requests/summary– uses the configured inline agent/profile to summarize the diff between a base and head branch, returning{summary: {title, body}}for the Create PR dialog; you can passattemptId/cardIdso linked GitHub issues are detected and the returned body can append auto-close lines (e.g.closes #123, fixes #456).- The client caches inline summary results per project + branch so users can trigger a summary, close the PR dialog, and return later to apply the cached suggestion; cancellation is explicit (AbortController) rather than tied to dialog lifecycle.
Auto‑close tickets on PR merge
- Projects can opt into automatic ticket closure when PRs are merged:
autoCloseTicketOnPRMerge: boolean(defaultfalse).
- When enabled, a lightweight background scheduler periodically scans cards in the Review column that have a linked
prUrl. - If a linked PR is closed and merged, the card is automatically moved to the Done column.
- The scheduler currently identifies these columns by title, so your board must contain columns titled Review and Done.
- You can disable this on a per‑ticket basis by setting:
disableAutoCloseOnPRMerge: booleanon the card (defaultfalse).
Auto‑close tickets on GitHub issue close
- Projects can opt into automatic ticket closure when linked GitHub issues are closed:
autoCloseTicketOnIssueClose: boolean(defaultfalse).
- When enabled, a lightweight background scheduler periodically scans cards that have a linked GitHub issue.
- If a linked issue is closed, the card is automatically moved to the Done column.
- The scheduler currently identifies the Done column by title, so your board must contain a column titled Done.
- This feature works for both:
- Cards imported from GitHub issues (via background sync or manual import).
- Cards exported to GitHub issues (created via the Create Ticket dialog with the GitHub issue creation option enabled).
- You can disable this on a per‑ticket basis by setting:
disableAutoCloseOnIssueClose: booleanon the card (defaultfalse).