Files
Alejandro Gutiérrez 5563f90733 feat: add @claudemesh/sdk package for non-Claude-Code clients
Standalone TypeScript SDK that any process can use to join a mesh and
send/receive messages. Implements the same WS protocol and libsodium
crypto_box encryption as the CLI, with an EventEmitter-based API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 23:53:22 +01:00

78 lines
2.3 KiB
TypeScript

/**
* @claudemesh/connector-slack — entry point.
*
* Bridges a Slack channel to a claudemesh mesh, relaying messages
* bidirectionally. The connector joins the mesh as a peer with
* peerType: "connector" and channel: "slack".
*
* Usage:
* SLACK_BOT_TOKEN=xoxb-... \
* SLACK_APP_TOKEN=xapp-... \
* SLACK_CHANNEL_ID=C0123456789 \
* MESH_BROKER_URL=wss://ic.claudemesh.com/ws \
* MESH_ID=... \
* MESH_MEMBER_ID=... \
* MESH_PUBKEY=... \
* MESH_SECRET_KEY=... \
* MESH_DISPLAY_NAME="Slack-#general" \
* node dist/index.js
*/
import { loadConfigFromEnv } from "./config";
import { SlackClient } from "./slack";
import { MeshClient } from "./mesh-client";
import { Bridge } from "./bridge";
async function main(): Promise<void> {
console.log("[connector-slack] Loading configuration...");
const config = loadConfigFromEnv();
// --- Connect to mesh ---
console.log(
`[connector-slack] Connecting to mesh ${config.meshId} at ${config.brokerUrl}...`,
);
const mesh = new MeshClient(config);
await mesh.connect();
console.log(
`[connector-slack] Mesh connected as "${config.displayName}" (peerType: connector, channel: slack)`,
);
mesh.setSummary(
`Slack connector bridging channel ${config.slackChannelId} to this mesh`,
);
// --- Connect to Slack ---
console.log("[connector-slack] Connecting to Slack via Socket Mode...");
const slack = new SlackClient(
config.slackBotToken,
config.slackAppToken,
config.slackChannelId,
);
await slack.connect();
console.log(
`[connector-slack] Slack connected, listening on channel ${config.slackChannelId}`,
);
// --- Start bridge ---
const bridge = new Bridge(slack, mesh, config);
bridge.start();
console.log("[connector-slack] Bridge active. Relaying messages...");
// --- Graceful shutdown ---
const shutdown = async (signal: string): Promise<void> => {
console.log(`\n[connector-slack] Received ${signal}, shutting down...`);
bridge.stop();
await slack.disconnect();
mesh.close();
console.log("[connector-slack] Goodbye.");
process.exit(0);
};
process.on("SIGINT", () => void shutdown("SIGINT"));
process.on("SIGTERM", () => void shutdown("SIGTERM"));
}
main().catch((err) => {
console.error("[connector-slack] Fatal:", err);
process.exit(1);
});