IssueCrush: A practical Copilot SDK integration
Issue triage is one of the most tedious parts of repository maintenance. Each issue requires reading the title, scanning the description, checking labels, and judging priority. Scale that across dozens of issues and multiple repositories, and the cognitive load becomes significant. The GitHub Copilot SDK offers a way to offload the initial reading and summarization work to AI, letting maintainers make faster decisions.
IssueCrush, a React Native app, demonstrates this pattern by presenting GitHub issues as swipeable cards. A "Get AI Summary" button invokes Copilot to read the issue and return an actionable summary. The implementation reveals several important architectural decisions and SDK patterns worth examining.
Why the SDK runs server-side
The Copilot SDK cannot run directly inside a React Native application. It requires a Node.js runtime and manages a local Copilot CLI process, communicating with it over JSON-RPC. The CLI binary must be installed and available on the system PATH, which rules out mobile deployment. This forces a server-side architecture with several benefits:
- Single SDK instance shared across clients: One server-side connection serves all mobile clients, avoiding per-client process spawning and auth handshakes.
- Server-side secret management: Copilot authentication tokens never reach the client bundle, where they could be decompiled.
- Graceful degradation: The server can fall back to metadata-based summaries when the AI service is unavailable, so triage continues uninterrupted.
- Centralized logging: Every prompt and response passes through the server, enabling latency tracking and debugging without mobile instrumentation.
Before implementing this pattern, you need the Copilot CLI installed on your server, a GitHub Copilot subscription or BYOK configuration, and authentication set up via copilot auth or the COPILOT_GITHUB_TOKEN environment variable.
Core SDK patterns
The SDK follows a strict lifecycle: start() → createSession() → sendAndWait() → disconnect() → stop(). Resource leaks are a real risk when cleanup is skipped. Every session interaction should be wrapped in try/finally, and cleanup calls should include .catch(() => {}) so cleanup errors don't mask the original failure.
Prompt engineering matters more than prompt length. Structured metadata—title, labels, author, and body—produces better summaries than dumping raw issue text. Author context is particularly important: an issue from a first-time contributor deserves different treatment than one from a core maintainer, and the model uses that signal to adjust its response.
Response handling requires defensive checks. The sendAndWait() method returns the assistant's response once the session goes idle, but the response chain should be validated before accessing nested properties. The second argument to sendAndWait() is a timeout in milliseconds—set it high enough for complex issues but low enough that users don't stare at a spinner indefinitely.
Failure handling and UX
The client-side service layer wraps API calls with initialization and error state management. Once a summary is generated, it's cached on the issue object. If the user swipes away and returns, the cached version renders instantly without another API call.
The backend distinguishes between two failure modes. Subscription errors return a 403, allowing the client to display a clear message. All other failures trigger a fallback that builds a summary from available issue metadata. This ensures users can still process issues offline or during AI service disruptions.
Two additional patterns improve the experience. The server exposes a /health endpoint that signals AI availability; clients check it on startup and hide the summary button entirely if the feature is unsupported. And summaries are generated on demand rather than preemptively, keeping API costs down and avoiding wasted calls on issues users swipe past without reading.
One implementation detail: the SDK is loaded dynamically via await import('@github/copilot-sdk') instead of a top-level import. This allows the server to start even if the SDK has issues, simplifying deployment and debugging.
Practical takeaways
The server-side architecture is the right approach for mobile Copilot SDK integrations. It keeps AI logic centralized, simplifies the client, and keeps credentials secure.
Prompt structure has a clear impact on output quality. Feeding organized metadata produces markedly better summaries than concatenated raw text. Similarly, a robust fallback path is essential—AI services go down and rate limits happen, so triage shouldn't depend on their availability.
The SDK's resource management deserves attention. Skipping a disconnect() call can cause memory leaks that are difficult to trace. Consistent use of try/finally avoids those debugging sessions.
The bigger picture: triage is one of those invisible maintenance tasks that contributes to burnout. Cutting the time needed to process a backlog of issues is meaningful time returned to code review, mentoring, or simply avoiding notification dread. The source code is available at AndreaGriffiths11/IssueCrush, and the Getting Started guide for the SDK walks through a first integration in about five lines of code.



