@chat-adapter/linear

中文文档
4.44.0发布于 2026/11/02MITTypeScriptES Module构建来源已验证近 30 天下载 44.9万

Linear adapter for Chat SDK — @mentions in issue comments and Linear agent sessions

原始使用文档
文档目录29 节
  1. Installation
  2. Scaffold with the CLI
  3. Quick start
  4. Configuration
  5. Authentication
  6. Option A — Vercel Connect
  7. Option B — Personal API key
  8. Option C — Pre-obtained OAuth access token
  9. Option D — Multi-tenant OAuth installs
  10. Option E — Single-tenant client credentials
  11. Token encryption
  12. Making the bot @-mentionable (optional)
  13. Direct API client
  14. Webhook setup
  15. Thread model
  16. Reactions
  17. Environment variables
  18. Features
  19. Messaging
  20. Rich content
  21. Conversations
  22. Message history
  23. Limitations
  24. Troubleshooting
  25. "Invalid signature" error
  26. Bot not responding to mentions
  27. "Webhook expired" error
  28. AI Coding Agents
  29. License

Linear adapter for Chat SDK

@chat-adapter/linear

npm package: @chat-adapter/linear

Agent Stack MIT License

Linear adapter for Chat SDK. Respond to @mentions in issue comment threads and Linear app-actor agent sessions.

The Linear adapter treats issue comments as messages and issues as threads.

Documentation: chat-sdk.dev/adapters/official/linear · Guides: vercel.com/kb/chat-sdk

Installation

pnpm add @chat-adapter/linear

Scaffold with the CLI

To scaffold a new Linear bot with this adapter preselected:

npx create-chat-sdk@latest my-bot --adapter linear memory

Visit the adapters directory to see other available official and vendor-official adapters.

Quick start

For managed credentials and webhook verification, see Vercel Connect.

The adapter auto-detects credentials from LINEAR_API_KEY, LINEAR_ACCESS_TOKEN, LINEAR_CLIENT_CREDENTIALS_CLIENT_ID/LINEAR_CLIENT_CREDENTIALS_CLIENT_SECRET, or LINEAR_CLIENT_ID/LINEAR_CLIENT_SECRET, plus LINEAR_WEBHOOK_SECRET and LINEAR_BOT_USERNAME:

import { Chat } from "chat";
import { createLinearAdapter } from "@chat-adapter/linear";

const bot = new Chat({
  userName: "my-bot",
  adapters: {
    linear: createLinearAdapter(),
  },
});

bot.onNewMention(async (thread, message) => {
  await thread.post("Hello from Linear!");
});

The adapter defaults to mode: "comments" and handles Comment webhooks. For Vercel Connect and Linear app-actor installations, we recommend explicitly setting mode: "agent-sessions" to handle AgentSessionEvent webhooks, including mentions and replies within a session.

Configuration

All options are auto-detected from environment variables when not provided.

OptionRequiredDescription
apiKeyNo*Personal API key. Auto-detected from LINEAR_API_KEY
accessTokenNo*OAuth access token. Accepts a string, or (Vercel Connect) a () => string | Promise<string> resolver invoked per API call. Auto-detected from LINEAR_ACCESS_TOKEN
clientIdNo*Multi-tenant OAuth app client ID. Auto-detected from LINEAR_CLIENT_ID
clientSecretNo*Multi-tenant OAuth app client secret. Auto-detected from LINEAR_CLIENT_SECRET
encryptionKeyNoAES-256-GCM key for encrypting stored OAuth tokens. Auto-detected from LINEAR_ENCRYPTION_KEY
clientCredentialsNo*Single-tenant client credentials config
clientCredentials.scopesNoScopes for client credentials auth. Defaults to ["read", "write", "comments:create", "issues:create"]
modeNoInbound webhook handling mode. Defaults to "comments". Set "agent-sessions" for the recommended Connect setup
webhookSecretNo**Webhook signing secret. Auto-detected from LINEAR_WEBHOOK_SECRET
webhookVerifierNo**Custom verifier (request, body) => unknown | Promise<unknown> used in place of webhookSecret. Takes precedence over webhookSecret/LINEAR_WEBHOOK_SECRET. Required in Connect mode
userNameNoBot display name. Auto-detected from LINEAR_BOT_USERNAME (default: "linear-bot")
apiUrlNoOverride the Linear GraphQL API base URL. Auto-detected from LINEAR_API_URL
loggerNoLogger instance (defaults to ConsoleLogger("info"))

*One of apiKey, accessToken (string or Vercel Connect resolver), top-level clientId/clientSecret, or clientCredentials is required (via config or env vars).

**Either webhookSecret (via config or LINEAR_WEBHOOK_SECRET) or a webhookVerifier is required. When webhookVerifier is set it takes precedence and the secret is ignored.

Authentication

Option A — Vercel Connect

Use Vercel Connect to source the Linear access token at runtime instead of storing a long-lived token or OAuth secret. Pass accessToken as a resolver and verify inbound webhooks with webhookVerifier (a Vercel OIDC token from Connect trigger forwarding) instead of a webhook secret.

The simplest path is the connectLinearAdapter() helper from @vercel/connect/chat:

import { createLinearAdapter } from "@chat-adapter/linear";
import { connectLinearAdapter } from "@vercel/connect/chat";

createLinearAdapter({
  ...connectLinearAdapter("linear/acme-linear"),
  mode: "agent-sessions",
});

Or wire the fields yourself:

import { getToken } from "@vercel/connect";

createLinearAdapter({
  accessToken: () =>
    getToken("linear/acme-linear", { subject: { type: "app" } }),
  webhookVerifier: myConnectWebhookVerifier,
  mode: "agent-sessions",
});

We recommend agent sessions for Vercel Connect bots. Enable Agent session events on the Linear app and use an app-actor installation. Omitting mode keeps the "comments" default; existing bots do not need to change their configuration. Changing the adapter mode does not change the app's webhook subscriptions or permissions.

accessToken accepts a string or () => string | Promise<string> resolver invoked per API call, so it composes with Connect's short-lived tokens. When webhookVerifier is set it takes precedence over webhookSecret and LINEAR_WEBHOOK_SECRET.

Freshness: OIDC verification replaces Linear's signature + timestamp check, so request freshness relies on the short-lived OIDC token's expiry rather than the >5 min timestamp rejection, and there is no built-in delivery de-duplication. Keep your webhook handlers idempotent (Linear can also deliver events out of order).

Option B — Personal API key

Best for personal projects, testing, or single-workspace bots. Actions are attributed to you as an individual.

  1. Go to Settings > Security & Access
  2. Under Personal API keys, click Create key
  3. Select Only select permissions and enable Create issues, Create comments
  4. Choose team access
  5. Click Create and set LINEAR_API_KEY
createLinearAdapter({
  apiKey: process.env.LINEAR_API_KEY!,
});

Option C — Pre-obtained OAuth access token

Use this when your app already manages the OAuth flow and you just want the adapter to operate with a single workspace token.

createLinearAdapter({
  accessToken: process.env.LINEAR_ACCESS_TOKEN!,
});

Option D — Multi-tenant OAuth installs

Use top-level clientId / clientSecret for Slack-style multi-tenant installs. Each Linear workspace installation is stored separately, webhook requests resolve the correct workspace token by organizationId, and withInstallation() lets you target a specific organization outside webhook handling.

  1. Go to Settings > API > Applications
  2. Create an OAuth2 application with your bot's name and icon
  3. Note the Client ID and Client Secret
const adapter = createLinearAdapter({
  clientId: process.env.LINEAR_CLIENT_ID!,
  clientSecret: process.env.LINEAR_CLIENT_SECRET!,
  mode: "agent-sessions",
});

Example callback route:

await bot.initialize();
const { organizationId } = await adapter.handleOAuthCallback(request, {
  redirectUri: process.env.LINEAR_REDIRECT_URI!,
});

Example background job:

await adapter.withInstallation("org-id", async () => {
  await adapter.postMessage("linear:issue-id", "Hello from a background job");
});

Option E — Single-tenant client credentials

If you want app identity without multi-tenant installs, use the explicit clientCredentials config. The adapter fetches and refreshes the token automatically.

createLinearAdapter({
  clientCredentials: {
    clientId: process.env.LINEAR_CLIENT_CREDENTIALS_CLIENT_ID!,
    clientSecret: process.env.LINEAR_CLIENT_CREDENTIALS_CLIENT_SECRET!,
    scopes: ["read", "write", "comments:create", "issues:create"],
  },
  mode: "agent-sessions",
});

Token encryption

For multi-tenant OAuth installs, pass a base64-encoded 32-byte key as encryptionKey (or set LINEAR_ENCRYPTION_KEY) to encrypt stored access and refresh tokens at rest using AES-256-GCM:

openssl rand -base64 32

When encryptionKey is set, setInstallation() encrypts tokens before writing them to the configured state adapter and getInstallation() decrypts them transparently. Existing plaintext records continue to work, so you can roll the key in without flushing installs. Without an encryptionKey, tokens are stored in plaintext (the previous default).

Making the bot @-mentionable (optional)

To make the bot appear in Linear's @ mention dropdown as an Agent:

  1. In your OAuth app settings, enable Agent session events under webhooks
  2. Have a workspace admin install the app with actor=app and the app:mentionable scope:
https://linear.app/oauth/authorize?
  client_id=your_client_id&
  redirect_uri=https://your-domain.com/callback&
  response_type=code&
  scope=read,write,comments:create,issues:create,app:mentionable&
  actor=app

If you use single-tenant client credentials, request the same scopes there:

createLinearAdapter({
  clientCredentials: {
    clientId: process.env.LINEAR_CLIENT_CREDENTIALS_CLIENT_ID!,
    clientSecret: process.env.LINEAR_CLIENT_CREDENTIALS_CLIENT_SECRET!,
    scopes: [
      "read",
      "write",
      "comments:create",
      "issues:create",
      "app:mentionable",
    ],
  },
});

Once installed with actor=app, set mode: "agent-sessions" so the adapter treats AgentSessionEvent as the entrypoint for mentions:

  • onNewMention fires from the session-created event
  • thread.startTyping() sends an ephemeral Linear thought
  • thread.post(stream) uses agent activities and session plan updates
  • Session threads are append-only, so sent.edit() / sent.delete() are not supported there

See the Linear Agents docs for full details.

Direct API client

For anything beyond the unified SDK, access the underlying LinearClient via .linearClient:

const linear = bot.getAdapter("linear").linearClient;

const issue = await linear.issue("ENG-123");
const project = await issue.project;

API key, access token, and single-tenant client-credentials modes return the same client anywhere. Multi-tenant OAuth mode requires webhook handler context to resolve the per-org token — calling .linearClient outside a handler throws.

The previous .client getter still works as a deprecated alias for .linearClient.

Webhook setup

Note: Webhook management requires workspace admin access. If you don't see the API settings page, ask a workspace admin to create the webhook for you.

  1. Go to Settings > API and click Create webhook
  2. Fill in:
    • Label: A descriptive name (e.g., "Chat Bot")
    • URL: https://your-domain.com/api/webhooks/linear
  3. Copy the Signing secret as LINEAR_WEBHOOK_SECRET
  4. Under Data change events, select:
    • Comments (required for mode: "comments")
    • Agent session events (required for mode: "agent-sessions")
    • Issues (recommended)
    • Emoji reactions (optional)
  5. Under Team selection, choose All public teams or a specific team
  6. Click Create webhook

Thread model

Linear has four thread variants:

TypeDescriptionThread ID format
Issue-levelTop-level comments on an issuelinear:{issueId}
Comment threadReplies nested under a specific commentlinear:{issueId}:c:{commentId}
Agent session on issueApp-actor session attached to an issuelinear:{issueId}:s:{agentSessionId}
Agent session on comment threadApp-actor session attached to a comment threadlinear:{issueId}:c:{commentId}:s:{agentSessionId}

When a user writes a comment, the bot replies within the same comment thread.

Reactions

SDK emojiLinear emoji
thumbs_upthumbs_up
thumbs_downthumbs_down
heartheart
firefire
rocketrocket
eyeseyes
sparklessparkles
wavewave

Environment variables

# API Key auth
LINEAR_API_KEY=lin_api_xxxxxxxxxxxx

# OR pre-obtained access token
LINEAR_ACCESS_TOKEN=lin_oauth_xxxxxxxxxxxx

# OR single-tenant client credentials auth
LINEAR_CLIENT_CREDENTIALS_CLIENT_ID=your-client-id
LINEAR_CLIENT_CREDENTIALS_CLIENT_SECRET=your-client-secret
# Optional, comma-separated
LINEAR_CLIENT_CREDENTIALS_SCOPES=read,write,comments:create,issues:create

# OR multi-tenant OAuth installs
LINEAR_CLIENT_ID=your-client-id
LINEAR_CLIENT_SECRET=your-client-secret
LINEAR_REDIRECT_URI=https://your-domain.com/api/linear/install/callback
# Optional: encrypt stored OAuth tokens at rest
LINEAR_ENCRYPTION_KEY=...

# Optional: inbound webhook mode
# comments | agent-sessions
LINEAR_MODE=comments

# Required
LINEAR_WEBHOOK_SECRET=your-webhook-secret

# Optional: override the Linear GraphQL API base URL
LINEAR_API_URL=...

Features

Messaging

FeatureSupported
Post messageYes
Edit messagePartial
Delete messagePartial
File uploadsNo
StreamingAgent sessions / Post+Edit fallback

Rich content

FeatureSupported
Card formatMarkdown
ButtonsNo
Link buttonsNo
Select menusNo
TablesGFM
FieldsYes
Images in cardsNo
ModalsNo

Conversations

FeatureSupported
Slash commandsNo
MentionsYes
Add reactionsYes
Remove reactionsPartial
Typing indicatorAgent sessions only
DMsNo
Ephemeral messagesNo

Message history

For agent-session threads, fetchMessages() throws a ValidationError if the session has no associated issue or its issue ID does not match the issue ID in the thread ID. The adapter checks this before fetching session comments or activities.

FeatureSupported
Fetch messagesYes
Fetch single messageNo
Fetch thread infoYes
Fetch channel messagesNo
List threadsNo
Fetch channel infoNo
Post channel messageNo

Limitations

  • Comment threads are still comment-based — typing indicators and native streaming only exist for app-actor agent sessions
  • Agent session threads are append-only — editMessage and deleteMessage work for normal comments, but not for session activities
  • No DMs — Linear doesn't have direct messages
  • No modals — Linear doesn't support interactive modals
  • Action buttons — Rendered as text; use link buttons for clickable actions
  • Remove reaction — Requires reaction ID lookup (not directly supported)

Troubleshooting

"Invalid signature" error

  • Verify LINEAR_WEBHOOK_SECRET matches the secret from your webhook configuration
  • The webhook secret is shown only once at creation — regenerate if lost

Bot not responding to mentions

  • Verify webhook events are configured with Comments resource type
  • For app-actor mode, also enable Agent session events
  • Check that the webhook URL is correct and accessible
  • Ensure the userName config matches how users mention the bot
  • If using app-actor installs, ensure the app was installed with actor=app and app:mentionable
  • Linear may auto-disable webhooks after repeated failures

"Webhook expired" error

  • Webhook timestamp is too old (> 5 minutes)
  • Usually indicates a delivery delay or clock skew
  • Check that your server time is synchronized

AI Coding Agents

If you use an AI coding agent such as OpenAI Codex, Claude Code, or Cursor, install the Chat SDK skill so it knows the SDK APIs, adapter patterns, and project conventions before writing code.

npx skills add vercel/chat

The skill references bundled documentation in node_modules/chat/docs, plus adapter guides and starter templates in the published package.

You can also install the Vercel Plugin for a broader agent toolkit — it includes the Chat SDK skill alongside specialist agents, agent slash commands, and more:

npx plugins add vercel/vercel-plugin

The plugin is optional; the skill alone is enough to build with Chat SDK.

For agent-readable documentation, see chat-sdk.dev/llms.txt (page index) or chat-sdk.dev/llms-full.txt (full text).

License

MIT

版本与发布记录

@chat-adapter/linear 共发布 48 个版本,首次发布于 2026/02/07;过去 12 个月发布了 48 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.44.0latest2026/11/026 天前
4.43.02026/10/1921 天前
4.42.02026/10/1425 天前
4.41.12026/09/291 个月前
4.41.02026/09/181 个月前
4.40.02026/09/052 个月前

关于 @chat-adapter/linear 的常见问题

@chat-adapter/linear 是什么?

Linear adapter for Chat SDK — @mentions in issue comments and Linear agent sessions

如何安装 @chat-adapter/linear?

在项目目录运行 npm install @chat-adapter/linear,或使用 pnpm add / yarn add / bun add。

@chat-adapter/linear 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@chat-adapter/linear 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@chat-adapter/linear 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@chat-adapter/linear 可以商用吗?

@chat-adapter/linear 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@chat-adapter/linear 的下载量有多少?

根据 npm 官方下载统计,@chat-adapter/linear 在 2026/10/10 – 2026/11/08 这 30 天内被下载 449,223 次,日均约 14,974 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@chat-adapter/linear 还在维护吗?

最新版本 4.44.0 发布于 2026/11/02(6 天前);至今共发布 48 个版本,其中过去 12 个月发布了 48 个;首次发布于 2026/02/07。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。