Files
vercel__chat/CLAUDE.md
T
Malte Ubl d2ffcc2cbe The great rename
We've acquired `chat` on npm. This plan covers renaming all packages and setting up automated publishing.

| Current Name | New Name | Version |
|--------------|----------|---------|
| `chat-sdk` | `chat` | 4.0.0 |
| `@chat-sdk/slack` | `@chat-adapter/slack` | 4.0.0 |
| `@chat-sdk/gchat` | `@chat-adapter/gchat` | 4.0.0 |
| `@chat-sdk/teams` | `@chat-adapter/teams` | 4.0.0 |
| `@chat-sdk/state-memory` | `@chat-adapter/state-memory` | 4.0.0 |
| `@chat-sdk/state-redis` | `@chat-adapter/state-redis` | 4.0.0 |
| `@chat-sdk/state-ioredis` | `@chat-adapter/state-ioredis` | 4.0.0 |

1. **Main package** (`packages/chat-sdk/package.json`):
   - Change `"name": "chat-sdk"` → `"name": "chat"`
   - Change `"version": "0.1.0"` → `"version": "4.0.0"`

2. **Adapter packages**:
   - `packages/adapter-slack/package.json`: `@chat-sdk/slack` → `@chat-adapter/slack`
   - `packages/adapter-gchat/package.json`: `@chat-sdk/gchat` → `@chat-adapter/gchat`
   - `packages/adapter-teams/package.json`: `@chat-sdk/teams` → `@chat-adapter/teams`
   - Update all versions to `4.0.0`
   - Update dependency on `chat-sdk` → `chat`

3. **State packages**:
   - `packages/state-memory/package.json`: `@chat-sdk/state-memory` → `@chat-adapter/state-memory`
   - `packages/state-redis/package.json`: `@chat-sdk/state-redis` → `@chat-adapter/state-redis`
   - `packages/state-ioredis/package.json`: `@chat-sdk/state-ioredis` → `@chat-adapter/state-ioredis`
   - Update all versions to `4.0.0`
   - Update dependency on `chat-sdk` → `chat`

Update `peerDependencies` and `dependencies` in each package:

```json
// Before
"peerDependencies": {
  "chat-sdk": "workspace:*"
}

// After
"peerDependencies": {
  "chat": "workspace:*"
}
```

Search and replace across the codebase:

| Find | Replace |
|------|---------|
| `from "chat-sdk"` | `from "chat"` |
| `from 'chat-sdk'` | `from 'chat'` |
| `import("chat-sdk")` | `import("chat")` |
| `from "@chat-sdk/slack"` | `from "@chat-adapter/slack"` |
| `from "@chat-sdk/gchat"` | `from "@chat-adapter/gchat"` |
| `from "@chat-sdk/teams"` | `from "@chat-adapter/teams"` |
| `from "@chat-sdk/state-memory"` | `from "@chat-adapter/state-memory"` |
| `from "@chat-sdk/state-redis"` | `from "@chat-adapter/state-redis"` |
| `from "@chat-sdk/state-ioredis"` | `from "@chat-adapter/state-ioredis"` |

Update any references to old package names in:
- `pnpm-workspace.yaml`
- `turbo.json` (task filters)
- Root `package.json` scripts

1. **README.md files** in each package
2. **Examples** (`examples/nextjs-chat/`)
3. **AGENTS.md** and other docs
4. **JSDoc comments** referencing package names

1. **Install changesets**:
   ```bash
   pnpm add -D @changesets/cli
   pnpm changeset init
   ```

2. **Configure `.changeset/config.json`**:
   ```json
   {
     "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
     "changelog": "@changesets/cli/changelog",
     "commit": false,
     "fixed": [],
     "linked": [
       ["chat", "@chat-adapter/*"]
     ],
     "access": "public",
     "baseBranch": "main",
     "updateInternalDependencies": "patch",
     "ignore": ["example-nextjs-chat"]
   }
   ```

3. **Add GitHub Action** (`.github/workflows/release.yml`):
   ```yaml
   name: Release

   on:
     push:
       branches:
         - main

   concurrency: ${{ github.workflow }}-${{ github.ref }}

   jobs:
     release:
       name: Release
       runs-on: ubuntu-latest
       steps:
         - uses: actions/checkout@v4
         - uses: pnpm/action-setup@v2
           with:
             version: 9
         - uses: actions/setup-node@v4
           with:
             node-version: 20
             cache: 'pnpm'

         - run: pnpm install
         - run: pnpm build
         - run: pnpm test

         - name: Create Release Pull Request or Publish
           uses: changesets/action@v1
           with:
             publish: pnpm changeset publish
           env:
             GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
             NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
   ```

4. **Add publish config to each package.json**:
   ```json
   "publishConfig": {
     "access": "public"
   }
   ```

1. Run full build: `pnpm build`
2. Run typecheck: `pnpm typecheck`
3. Run lint: `pnpm lint`
4. Run tests: `pnpm test`
5. Test local linking in example app

| File | Changes |
|------|---------|
| `packages/chat-sdk/package.json` | Rename to `chat`, version 4.0.0 |
| `packages/adapter-slack/package.json` | Rename to `@chat-adapter/slack`, update deps |
| `packages/adapter-gchat/package.json` | Rename to `@chat-adapter/gchat`, update deps |
| `packages/adapter-teams/package.json` | Rename to `@chat-adapter/teams`, update deps |
| `packages/state-memory/package.json` | Rename to `@chat-adapter/state-memory`, update deps |
| `packages/state-redis/package.json` | Rename to `@chat-adapter/state-redis`, update deps |
| `packages/state-ioredis/package.json` | Rename to `@chat-adapter/state-ioredis`, update deps |
| `examples/nextjs-chat/package.json` | Update all dependencies |
| `packages/integration-tests/package.json` | Update all dependencies |
| `turbo.json` | Update package references |
| All `*.ts` files | Update import statements |
| All `README.md` files | Update package names in docs |
| `.changeset/config.json` | Create new |
| `.github/workflows/release.yml` | Create new |

1. Update all `package.json` files (names, versions, dependencies)
2. Run `pnpm install` to update lockfile
3. Update all import statements in source files
4. Update all import statements in test files
5. Update documentation
6. Set up changesets
7. Run full validation
8. Create initial changeset for 4.0.0 release
9. Commit and push

If issues arise:
1. Git revert the rename commit
2. Run `pnpm install` to restore lockfile
3. Previous npm versions remain available
2026-01-02 13:56:55 -08:00

4.2 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build Commands

# Install dependencies
pnpm install

# Build all packages (uses Turborepo)
pnpm build

# Type-check all packages
pnpm typecheck

# Lint all packages
pnpm lint

# Check for unused exports/dependencies
pnpm knip

# Run all tests
pnpm test

# Run full validation. ALWAYS do this before declaring a task to be done.
pnpm validate


# Run dev mode (watch for changes)
pnpm dev

# Build a specific package
pnpm --filter chat build
pnpm --filter @chat-adapter/slack build
pnpm --filter @chat-adapter/gchat build
pnpm --filter @chat-adapter/teams build

# Run tests for a specific package
pnpm --filter chat test
pnpm --filter @chat-adapter/integration-tests test

# Run a single test file
pnpm --filter @chat-adapter/integration-tests test src/slack.test.ts

Code Style

  • Install dependencies with pnpm add rather than manually editing package.json
  • sample-messages.md files in adapter packages contain real-world webhook logs as examples

Architecture

This is a pnpm monorepo using Turborepo for build orchestration. All packages use ESM ("type": "module"), TypeScript, and tsup for bundling.

Package Structure

  • packages/chat-sdk - Core SDK (chat package) with Chat class, types, and markdown utilities (mdast-based)
  • packages/adapter-slack - Slack adapter using @slack/web-api
  • packages/adapter-gchat - Google Chat adapter using googleapis
  • packages/adapter-teams - Microsoft Teams adapter using botbuilder
  • packages/state-memory - In-memory state adapter (for development/testing)
  • packages/state-redis - Redis state adapter (for production)
  • packages/integration-tests - Integration tests against real platform APIs
  • examples/nextjs-chat - Example Next.js app showing how to use the SDK

Core Concepts

  1. Chat (packages/chat-sdk/src/chat.ts in chat package) - Main entry point that coordinates adapters and handlers
  2. Adapter - Platform-specific implementations (Slack, Teams, Google Chat). Each adapter:
    • Handles webhook verification and parsing
    • Converts platform-specific message formats to/from normalized format
    • Provides FormatConverter for markdown/AST transformations
  3. StateAdapter - Persistence layer for subscriptions and distributed locking
  4. Thread - Represents a conversation thread with methods like post(), subscribe(), startTyping()
  5. Message - Normalized message format with text, formatted (mdast AST), and raw (platform-specific)

Thread ID Format

All thread IDs follow the pattern: {adapter}:{channel}:{thread}

  • Slack: slack:C123ABC:1234567890.123456
  • Teams: teams:{base64(conversationId)}:{base64(serviceUrl)}
  • Google Chat: gchat:spaces/ABC123:{base64(threadName)}

Message Handling Flow

  1. Platform sends webhook to /api/webhooks/{platform}
  2. Adapter verifies request, parses message, calls chat.handleIncomingMessage()
  3. Chat class acquires lock on thread, then:
    • Checks if thread is subscribed -> calls onSubscribedMessage handlers
    • Checks for @mention -> calls onNewMention handlers
    • Checks message patterns -> calls matching onNewMessage handlers
  4. Handler receives Thread and Message objects

Formatting System

Messages use mdast (Markdown AST) as the canonical format. Each adapter has a FormatConverter that:

  • toAst(platformText) - Converts platform format to mdast
  • fromAst(ast) - Converts mdast to platform format
  • renderPostable(message) - Renders a PostableMessage to platform string

Linting

Uses Biome with strict rules:

  • noUnusedImports and noUnusedVariables as errors
  • useImportType enforced - use import type for type-only imports
  • noExplicitAny - avoid any types
  • noNonNullAssertion - avoid ! assertions

Environment Variables

Key env vars used (see turbo.json for full list):

  • SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET - Slack credentials
  • TEAMS_APP_ID, TEAMS_APP_PASSWORD, TEAMS_APP_TENANT_ID - Teams credentials
  • GOOGLE_CHAT_CREDENTIALS or GOOGLE_CHAT_USE_ADC - Google Chat auth
  • REDIS_URL - Redis connection for state adapter
  • BOT_USERNAME - Default bot username