Corsair Key Modules and Packages to Focus On First: A Developer's Guide

Start with packages/corsair/core/index.ts (the createCorsair factory) and packages/corsair/client/index.ts (the client builder)—these two modules contain the entire initialization flow, tenant handling, and plugin wiring that powers every Corsair integration.

Corsair is organized as a monorepo where the core library lives in packages/corsair and each third-party integration ships as a separate plugin under packages/<plugin>/. Whether you're building your first integration or extending the framework, mastering the core modules first will dramatically accelerate your productivity. This guide maps out the essential files, explains how they connect, and provides runnable code examples from the corsairdev/corsair source code.

The Public API Entry Point: packages/corsair/index.ts

The file packages/corsair/index.ts re-exports everything consumers need: createCorsair, CorsairClient, CorsairTenantWrapper, and type definitions. This is the surface area you'll interact with as a library user.

Understanding this file reveals the high-level contract—what's public, what's typed, and how the pieces are named. From here, trace inward to the implementation details.

The Core Factory: packages/corsair/core/index.ts

The createCorsair factory function is the heart of the framework. Located in packages/corsair/core/index.ts, it:

  • Accepts a configuration object with plugins, database settings, a key-encryption-key (kek), and optional hub configuration
  • Builds the internal CorsairInternalConfig object containing resolved plugins, tenancy flags, permissions, and hub settings
  • Attaches this config to the client via the internal symbol CORSAIR_INTERNAL
  • Returns either a bare client (single-tenant) or a CorsairTenantWrapper (multi-tenant)

This is where multi-tenancy is implemented. When multiTenancy: true is set, the factory returns a wrapper exposing withTenant(tenantId), which produces a tenant-scoped client via the buildCorsairClient internal helper.

The Client Builder: packages/corsair/client/index.ts

Module packages/corsair/client/index.ts contains buildCorsairClient, the low-level builder that:

  • Generates the runtime client object
  • Attaches each plugin's methods according to its export type definitions
  • Applies authentication and exposes the keys namespace for integration-level key management

This file reveals how plugin APIs become typed methods on the client object. If you're debugging why a plugin method isn't appearing or why auth headers aren't attaching, trace the logic here.

Optional HTTP Server: packages/corsair/http.ts

The http.ts module provides a wrapper that exposes your integration as a REST endpoint via corsair http <port>. It's invaluable for:

  • Rapid prototyping of webhook receivers
  • Debugging integrations without deploying
  • Building microservices around Corsair clients

The server activates when NODE_ENV=development and requires a configured integration instance.

Hub and Tunnel Orchestration: packages/corsair/hub.ts

When running in the Corsair Hub (hosted OAuth and webhook manager), packages/corsair/hub.ts handles:

  • Hub configuration parsing
  • Development connect loop (triggered by ck_dev_… API keys)
  • Local tunnel orchestration (controlled via CORSAIR_TUNNEL environment variable)

Focus here if you're building OAuth flows or need the hosted tunnel for webhook development.

Plugin Scaffolding: scripts/generate-plugin.ts

The CLI utility at scripts/generate-plugin.ts is your fastest path to adding new integrations. Running it:

  1. Creates packages/<name>/ with index.ts and test skeleton
  2. Registers the plugin in packages/corsair/core/constants.ts
  3. Ensures correct repository layout and TypeScript configuration

Use this instead of manual setup to maintain consistency across the monorepo.

Code Examples: From Single-Tenant to Multi-Tenant

Single-Tenant Integration

import { createCorsair } from 'corsair';
import { slackPlugin } from '@corsair-dev/slack';

const client = createCorsair({
  plugins: [slackPlugin],
  kek: 'my-super-secret-kek',
});

await client.slack.sendMessage({
  channel: 'C123456',
  text: 'Hello from Corsair!',
});

Source: createCorsair in packages/corsair/core/index.ts; plugin structure from scaffolded packages.

Multi-Tenant with Tenant Scoping

import { createCorsair } from 'corsair';
import { gmailPlugin } from '@corsair-dev/gmail';

const wrapper = createCorsair({
  plugins: [gmailPlugin],
  kek: 'kek-for-multi-tenant',
  multiTenancy: true,
});

const tenantClient = wrapper.withTenant('tenant-abc');
await tenantClient.gmail.listThreads();

Source: withTenant logic in packages/corsair/core/index.ts.

Local HTTP Development Server

import { http } from 'corsair';

http({ port: 3000, integration: wrapper });

Source: packages/corsair/http.ts.

Scaffold a New Plugin

pnpm run generate:plugin \
  --name myplugin \
  --description "My custom integration"

Source: scripts/generate-plugin.ts.

How the Core Modules Connect

  1. Factory (createCorsair) receives configuration and resolves plugins
  2. Internal Config (CorsairInternalConfig) stores runtime state attached via CORSAIR_INTERNAL
  3. Client (buildCorsairClient) materializes typed plugin APIs
  4. Multi-Tenancy Wrapper (withTenant) scopes clients when enabled
  5. Hub & Tunnel provide optional hosted infrastructure for OAuth and webhooks

Summary

Frequently Asked Questions

What's the fastest way to understand how Corsair initializes integrations?

Read packages/corsair/core/index.ts and trace createCorsair from its parameter types through to the returned client or wrapper. The factory's ~200 lines contain the entire composition logic for plugins, database, keys, and tenancy.

How does multi-tenancy actually work in Corsair?

When multiTenancy: true is passed to createCorsair, the factory returns a wrapper object with a withTenant(tenantId) method. Calling this method invokes buildCorsairClient with tenant-scoped context, ensuring isolated data per customer in SaaS deployments.

Should I write plugins manually or use the generator?

Always use scripts/generate-plugin.ts. The generator ensures your plugin follows the monorepo's structural conventions, registers itself in packages/corsair/core/constants.ts, and includes the correct TypeScript boilerplate for type-safe exports.

What's the difference between the HTTP wrapper and the Hub?

The HTTP wrapper (http.ts) is a lightweight local server for development and testing. The Hub (hub.ts) is a production-grade hosted service handling OAuth token refresh, webhook ingress, and secure tunneling—activated when using ck_dev_… or production API keys.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →