Claude-skill-registry integration-development
Guide for creating new OAuth-based integrations in the Orient codebase. Use when adding external service integrations (APIs like Linear, GitHub, Slack, Notion, etc.), implementing OAuth flows, or creating catalog-based integration manifests. Covers the full integration lifecycle from manifest definition to tool implementation.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/integration-development" ~/.claude/skills/majiayu000-claude-skill-registry-integration-development && rm -rf "$T"
skills/data/integration-development/SKILL.mdIntegration Development
This skill provides guidance for creating OAuth-based integrations in Orient.
Integration Architecture
Orient uses a catalog-based architecture for integrations:
packages/integrations/src/ ├── catalog/ # Integration definitions │ ├── linear/ │ │ ├── INTEGRATION.yaml # Manifest │ │ ├── oauth-config.ts # OAuth configuration │ │ ├── tools.ts # API client and tools │ │ └── index.ts # Exports │ └── github/ │ └── ... ├── types/ │ └── integration.ts # IntegrationManifest types └── index.ts # Package exports
Quick Start
- Create directory:
packages/integrations/src/catalog/<integration-name>/ - Create
manifestINTEGRATION.yaml - Create
for OAuth flowoauth-config.ts - Create
for API clienttools.ts - Create
for exportsindex.ts - Update package.json exports
File Templates
INTEGRATION.yaml
See
references/manifest-template.md for the complete template.
Key fields:
: lowercase identifier (e.g.,name
,linear
)github
: display nametitle
: 50+ character descriptiondescription
: semver (e.g.,version
)1.0.0
: authorization and token URLs, scopesoauth
: CLIENT_ID, CLIENT_SECRET, etc.requiredSecrets
: available API operationstools
:status
,stable
, orbetaexperimental
oauth-config.ts
Required exports:
- Scope constants (e.g.,
)LINEAR_SCOPES - Default scopes array
- Config interface
- generate authorization URLgetAuthUrl()
- exchange code for tokensexchangeCode()
- fetch user profilegetUserInfo()
- load config from environmentgetConfigFromEnv()
tools.ts
Required exports:
- Type definitions for API responses
- Client class with API methods
- Factory function (e.g.,
)createLinearClient()
OAuth Flow Patterns
Standard OAuth 2.0
Most services use standard OAuth 2.0:
// 1. Generate auth URL with state const authUrl = getAuthUrl(config, scopes, state); // 2. User authorizes in browser, redirected with code // 3. Exchange code for tokens const tokens = await exchangeCode(config, code); // 4. Use access token for API calls const client = createClient(tokens.accessToken);
OAuth 2.0 with PKCE
Some services require PKCE (Proof Key for Code Exchange):
// 1. Generate code verifier and challenge const codeVerifier = crypto.randomBytes(32).toString('base64url'); const codeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('base64url'); // 2. Include challenge in auth URL const authUrl = `${baseUrl}?code_challenge=${codeChallenge}&code_challenge_method=S256`; // 3. Include verifier in token exchange const tokens = await exchangeCode(config, code, codeVerifier);
API Client Patterns
GraphQL APIs (Linear, GitHub GraphQL)
private async query<T>(query: string, variables?: Record<string, unknown>): Promise<T> { const response = await fetch(this.apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.accessToken}`, }, body: JSON.stringify({ query, variables }), }); const result = await response.json(); if (result.errors?.length > 0) { throw new Error(`GraphQL error: ${result.errors[0].message}`); } return result.data; }
REST APIs (GitHub REST, Slack)
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> { const response = await fetch(`${this.apiUrl}${endpoint}`, { ...options, headers: { Authorization: `Bearer ${this.accessToken}`, Accept: 'application/json', 'Content-Type': 'application/json', ...options.headers, }, }); if (!response.ok) { const error = await response.json().catch(() => ({ message: response.statusText })); throw new Error(`API error: ${error.message}`); } return response.json(); }
Logging Pattern
Always use the service logger:
import { createServiceLogger } from '@orientbot/core'; const logger = createServiceLogger('integration-name'); async function someOperation() { const op = logger.startOperation('operationName', { param1: value1 }); try { const result = await doWork(); op.success('Operation completed', { resultCount: result.length }); return result; } catch (error) { op.failure(error instanceof Error ? error : String(error)); throw error; } }
Type Transformation
Transform API responses to camelCase:
// API returns snake_case const apiResponse = { created_at: '2024-01-15', pull_request: { html_url: '...' }, }; // Transform to camelCase const result = { createdAt: apiResponse.created_at, pullRequest: { htmlUrl: apiResponse.pull_request.html_url }, };
Required Secrets
Define all required secrets in the manifest:
requiredSecrets: - name: SERVICE_CLIENT_ID description: OAuth Client ID from developer settings category: oauth required: true - name: SERVICE_CLIENT_SECRET description: OAuth Client Secret category: oauth required: true - name: SERVICE_WEBHOOK_SECRET description: Webhook signing secret (optional) category: webhook required: false
Webhook Support
For integrations that support webhooks:
webhooks: events: - push - pull_request - issues signatureHeader: X-Hub-Signature-256 signatureAlgorithm: hmac-sha256
Testing Integrations
- OAuth flow: Test with real credentials in development
- API calls: Mock API responses in unit tests
- Token refresh: Test expiration handling
- Error handling: Test API error responses
Common Pitfalls
- Missing scopes: Always request all needed scopes upfront
- Token expiration: Handle refresh tokens if provided
- Rate limiting: Implement backoff for API errors
- Pagination: Handle paginated API responses
- Error messages: Parse API error details for useful messages
References
- Full INTEGRATION.yaml templatereferences/manifest-template.md
- OAuth configuration for common providersreferences/oauth-providers.md