cometchat-features
SkillFiles & storageAdd features (calls, reactions, polls, file sharing, presence, etc.) to an already-integrated CometChat project. Routes to the right sub-flow based on feature type — default (already enabled), extension (API toggle), ai-feature (API toggle + OpenAI key), dashboard-only (third-party config), package-install (calls), or component-swap (rich text).
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the cometchat-features skill
What this skill tells your AI
The instructions your AI receives, as published by cometchat/cometchat-skills in skills/cometchat-features/SKILL.md and read by ahel’s review.
Ground truth: the 5-tier feature catalog
packages/registry/v6/features/catalog.json+ the per-platform UI KitdefaultExtensions[]. (Official docs linked below.) Verify symbols against the installed package/source before relying on them.
Scope — this IS the web / React features skill (
@cometchat/chat-uikit-react). Web/React intentionally has no separate "react-features" skill: this one is it. Each other family has its own features skill (native / angular / android-v5 / android-v6 / ios / flutter-v6). Flutter V5 has none — it proxies tocometchat-flutter-v6-featuresfor enablement: feature enablement is the SDK/dashboardapply-featurepath (identical across V5/V6); only the in-UI wiring differs, and V5 is legacy/maintenance-only. Theapply-featureCLI + the 5-tier taxonomy below apply to all families.
Companion skills:
cometchat-corecovers initialization and the provider pattern;cometchat-customizationis the next step when a feature is enabled but needs visual customization;cometchat-troubleshootinghandles post-feature-enable failures.
Purpose
This skill teaches Claude how CometChat features are structured and
what work is actually required to enable each one. Most features require
zero code — they are either already built into the UI Kit, toggled
via the cometchat apply-feature CLI (which hits the dashboard API),
or activated by a single npm install. Understanding which type a feature
is prevents unnecessary work.
1. Use this skill when
The user wants to add a specific feature to an already-integrated CometChat project. Trigger phrases:
/cometchat features(or invoke the cometchat-features skill via your agent's mechanism — keyword "cometchat feature" or "add chat feature" works in most agents)/cometchat features <name>(e.g./cometchat features reactions)/cometchat <feature>(e.g./cometchat polls,/cometchat calls)- "add reactions to my chat"
- "add video calling"
- "enable polls"
- "add file sharing"
- "enable smart replies"
- "add typing indicators"
2. Preconditions
The user must have an existing integration:
npx @cometchat/skills-cli info --json
If integrated is false, stop and tell the user to run /cometchat
first to create the integration.
3. The 5 feature categories (customer-facing) — and what work each needs
CometChat's canonical "Feature Availability" model sorts every feature into 5 categories by the work needed (the catalog encodes this per-feature as tier + the operative columns code / dashboard_settings / builder; run cometchat features info <id> --json).
Canonical public decision-reference (source of truth): Features & Extensions Guide on the public docs. It is the authoritative, always-current matrix of which integration method supports each feature (UI Kit / UI Kit Builder / Widget Builder / SDK), what dashboard setup it needs, and whether code is required. When the local
catalog.jsonand this page disagree, the docs page wins — the catalog is a build-time snapshot derived from the same model and can lag a release. For any "can the builder do X? / is feature Y code-or-dashboard?" decision, consult this page (WebFetch it, or query the docs MCP) rather than answering from memory or a stale snapshot.
| Tier | Category | Work needed | Example |
|---|---|---|---|
| 1 | Core Messaging (Zero Setup) | Nothing — renders out of the box | Typing Indicators |
| 2 | Builder-Enabled (Config + UI Toggle) | Enable via Dashboard API; toggle/place in the UI Kit Builder | Polls |
| 3 | Config-Only (Dashboard-Driven) | Enable via Dashboard API; works automatically | Link Preview |
| 4 | Config + Settings (Smart) | Dashboard API + extra settings (API keys, thresholds) — no code | Smart Replies |
| 5 | SDK-Integrated (Config + Code) | Dashboard API + custom client code | Bitly |
Tiers 1–4 need no client code (code: "none"). Tier 5 needs code — and the implementation already lives in the docs. When a feature's code is custom-code or steps-in-docs (i.e. auto_wired_in_uikit: false), the flow is: flip the dashboard toggle (apply-feature <id>), then fetch the reference implementation from the docs (docs_topic, via the docs MCP) and adapt it — do NOT hand-roll. A few Core features carry code: "stitch-components" (e.g. Threaded Conversations, Advanced Search): no extension, but you compose existing kit components — the kit sample apps show the wiring (see [[uikit-local-clones-canonical-source]]). The 14 code-needed extensions: bitly, message-shortcuts, pin-message, rich-media-preview, save-message, tinyurl, voice-transcription, giphy, reminders, stipop, tenor, disappearing-messages, chatwoot, intercom.
T2 vs T3 is a Builder-surface nuance (does the Builder expose a placement/toggle for it). Operationally both are "enable via Dashboard, no code" — the
builder: "toggle"flag marks the ones the Builder surfaces.
3b. Enablement mechanism (how the CLI flips each on)
Independently of the 5 customer-facing tiers above, the catalog tags each feature with an enablement mechanism — what the CLI's apply-feature actually does:
-
default (compiled-in): Shipped inside the UI Kit component bundle unconditionally. CometChat builds reactions, typing indicators, mentions, etc. into
CometChatMessageListandCometChatMessageComposerat compile time. The feature is always present; the only question is whether the prop that surfaces it is enabled. No action needed. -
extension (backend boolean toggle): Pure on/off backend extension. The CLI's
apply-featurecommand flips the toggle via the same REST API the dashboard UI uses (POST /apps/{id}/extensions), so no browser visit required. Once enabled, the UI Kit renders the matching UI automatically only for the auto-wired subset (auto_wired_in_uikit: true,code: "none"); the rest (tier 5) need client code from the docs. Examples: polls, link-preview, message-translation, stickers. -
ai-feature (backend AI toggle + OpenAI key): Same API path as extensions but split out because the AI feature requires an OpenAI API key on the app's AI settings (
PUT /apps/{id}/ai/settings) before the toggle (POST /apps/{id}/features/ai.{key}/enabled) succeeds. The CLI handles both calls in one invocation when given--openai-key sk-…. Examples: smart-replies, conversation-summary, conversation-starter. -
dashboard-only (third-party config): Requires entering config the user has to fetch themselves — third-party API keys (Giphy, Stipop, Tenor), webhooks (Chatwoot), or multi-field choices (disappearing-messages interval, message-shortcuts list). The CLI cannot automate these; the skill prints the dashboard path and stops.
-
package-install (separate SDK): Voice/video calling requires
@cometchat/calls-sdk-javascriptbecause it links against browser media APIs that would bloat every integration if bundled unconditionally. Once installed, the UI Kit detects it via dynamic import. -
component-swap (variant component): Replaces one UI Kit component with a drop-in variant whose default behavior differs (e.g.
CometChatCompactMessageComposerenables rich text by default). The CLI does a safe word-boundary replace instate.files_owned. Requirescometchat applyto have run (i.e. web/RN integrations only — native cohorts can't use this path).
4. The feature catalog
Type 1 — Default features (~14, already enabled in UI Kit)
These are already part of the components your integration uses. The skill's job is to tell the user they're already there and point at the relevant component:
- Instant Messaging
- Media Sharing (file/image/audio/video)
- Read Receipts
- Mark as Unread
- Typing Indicator
- User Presence (online/offline)
- Reactions
- Mentions (incl. @all)
- Threaded Conversations
- Quoted Replies
- Group Chat
- Report Message
- Conversation/Advanced Search
For these: query the docs MCP for the feature's component/usage docs, show the user where it is in their integration. No code changes needed.
Type 2a — Extensions (pure boolean, CLI-toggleable)
These are backend extensions enabled by a single API call (POST /apps/{id}/extensions).
Use the CLI — no browser visit required:
cometchat apply-feature <id>
For native cohorts (iOS / Android / Flutter / Angular) where there's no
.cometchat/state.json, pass --app-id explicitly:
cometchat apply-feature <id> --app-id <your-app-id>
Once enabled, the UI Kit auto-integrates them. No code changes needed — for the auto-wired subset.
⚠️ The "no code needed" pitch only holds for ~7 of 24 dashboard-toggle features (ENG-35721). The dashboard exposes 24 extensions; only the ones marked
auto_wired_in_uikit: truein the CLI's catalog (~7 — Link Preview, Polls, Stickers, Message Translation, Smart Replies, Conversation Starter, and a handful more) render automatically via the kit's bubbles + composer. The other ~17 (Bitly, TinyURL, Voice Transcription, Reminders, Save Message, Pin Message, etc.) require either a kit prop opt-in OR a small component-side handler —apply-feature <id>flips the dashboard toggle but does NOT wire client-side rendering for those. Before promising "no code needed" to the customer, runcometchat features info <id> --jsonand check theauto_wired_in_uikitfield; iffalse, set expectations honestly and emit the wiring code.
⚠️
features enablehas TWO unstated prereqs (ENG-35721):
auth loginmust have completed — the toggle is gated on the dashboard bearer token. The CLI's "no app" error says nothing about login; runningcometchat features enable <id>cold (after onlyprovision setup) fails with a misleading message. Runcometchat auth status --jsonfirst; if"logged-out", runcometchat auth loginbefore anyfeatures enable.- Either
.cometchat/config.jsonOR--app-id <id>— the toggle needs an app context. If the user pasted credentials manually (the dispatcher's Step 2d path) they may NOT have a.cometchat/config.jsonyet. Manual.envusers: runcometchat config save --app-id <id> --region <region> --jsonto bridge into.cometchat/config.jsonbeforeapply-feature, OR pass--app-idon everyapply-featurecall.
Note: Conversation and Advanced Search has its own toggle on the Features page. It is on by default but can be disabled. If a user reports that search is missing, check this toggle.
Extensions — User Experience: Avatar, Bitly, Link Preview, Message Shortcuts, Pin Message, Rich Media Preview, Save Message, Thumbnail Generation, TinyURL, Voice Transcription
Extensions — User Engagement: Giphy, Message Translation, Polls, Reminders, Stickers, Stipop, Tenor
⚠️ Broadcast was removed (ENG-35699). Earlier versions of this skill listed "Broadcast" here, but the CLI's 40-feature catalog has no
broadcastorbroadcast-messageid —cometchat-skills-cli features info broadcastreturns "not found." Broadcast as a use case is achievable via standard CometChat extensions (one-to-many group messages withsubscribePresenceForAllUsers) or via Custom Messages — but there is no "Broadcast" extension toggle in the dashboard today. If a customer asks for broadcast functionality, route them at custom messages + a server-side fan-out webhook, not a feature toggle.
Extensions — Collaboration: Collaborative Document, Collaborative Whiteboard
Extensions — Security: Disappearing Messages, E2E Encryption (Enterprise plan only)
Extensions — Moderation (LEGACY — prefer Rules Management, see §"Moderation" below): Data Masking, Image Moderation, Profanity Filter, Sentiment Analysis, XSS Filter, Human Moderation, Report User, Slow Mode, Virus/Malware Scanner. ⚠️ Deprecated; don't run alongside moderation Rules (double-processes every message).
Notifications extensions (Chat & Messaging → Features): Email Notification, Push Notification, SMS Notification
Extensions — Customer Support: Chatwoot, Intercom
Type 2b — AI features (CLI-toggleable, OpenAI key required)
smart-replies, conversation-summary, conversation-starter. These
need an OpenAI API key on the app's AI settings before the toggle
succeeds. The CLI does both calls in one invocation:
cometchat apply-feature smart-replies --openai-key sk-...
# native:
cometchat apply-feature smart-replies --app-id <id> --openai-key sk-...
After the first AI feature is enabled the key is stored on the app, so
subsequent ai-feature applies don't need --openai-key repeated.
Get an OpenAI key: https://platform.openai.com/api-keys
Type 2c — Dashboard-only (third-party config required)
These extensions require config the user has to provide themselves
(third-party API keys / webhooks / multi-field setup) — apply-feature
returns manual-action-required and prints the dashboard path. The
CLI cannot automate these:
- Third-party API keys: Giphy, Stipop, Tenor, Intercom
- Webhooks: Chatwoot
- Multi-field config: Message Shortcuts (shortcut list), Disappearing Messages (interval)
Manual flow for these:
- https://app.cometchat.com → select your app
- Sidebar → Chat & Messaging → Features
- Find the extension, enter the third-party config, toggle ON
Moderation — use Rules Management (NOT the legacy extensions)
The canonical moderation system is Rules Management, not the old per-extension
toggles. Configure rules once in the Dashboard (Moderation → Settings → Rules,
or the /moderation/rules REST API — also /moderation/{keywords,reasons, blocked-messages,flagged-messages,reviewed-messages}) and they auto-apply to every
message with no client code (the UI Kit + SDK enforce them seamlessly). Docs:
moderation/overview + moderation/rules-management.
⚠️ Do NOT run legacy moderation extensions AND Rules on the same app. The legacy extensions (Data Masking, Image Moderation, Profanity Filter, Sentiment Analysis, XSS Filter, Slow Mode, Virus/Malware Scanner) are deprecated. If both a legacy extension and a Rule are active, every message is processed twice → delays + perf issues. Disable the legacy extensions (Dashboard → Extensions) before creating Rules.
apply-feature <legacy-id>still works but emits this same warning — prefer Rules.
- Notifications (separate, unaffected): Email, Push, SMS — Sidebar → Extensions → configure + enable.
After enabling any feature, run cometchat verify to ensure the
existing integration still passes. No code changes are needed — the
UI Kit picks up enabled features automatically.
Type 3 — Package-install features (4, calls)
These require installing @cometchat/calls-sdk-javascript. Once installed,
the UI Kit auto-detects it and surfaces the call UI in CometChatMessageHeader,
CometChatConversations, etc.
- Call Buttons (in message headers)
- Incoming Call notifications
- Outgoing Call interface
- Call Logs (call history)
For these, the user opting in IS consent — run the install directly:
npm install @cometchat/calls-sdk-javascript@^5
npx @cometchat/skills-cli verify --json
The UI Kit's initiateAfterLogin() auto-calls enableCalling() after the
package is installed. No manual wiring needed for default call buttons in
CometChatMessageHeader. Restart the dev server.
Type 5 — Custom message types (APPEND, never REPLACE — ENG-35706)
When a customer wants to send a new message type (location, product card, custom event), the V6 React kit ships a templates API that is dangerously easy to misuse. Two testers hit the same trap: they added one custom template and watched ALL existing bubbles (text, image, audio, video, file) disappear AND the composer's entire attachment menu (Camera/Image/Video/File/Whiteboard/Document) get replaced by their one new attachment.
Cause: <CometChatMessageList templates={[locationTemplate]} /> and <CometChatMessageComposer attachmentOptions={[locationOption]} /> REPLACE the kit's built-in templates / options rather than appending to them.
Correct pattern — always merge with the kit's defaults:
import {
CometChatMessageList,
CometChatMessageComposer,
CometChatMessageTemplate, // the kit's template class — verified export (src/index.ts:79)
CometChatMessageComposerAction, // attachment-menu action class
CometChatUIKit, // exposes getDataSource()
CometChatUIKitConstants, // MessageTypes / MessageCategory enums
} from "@cometchat/chat-uikit-react";
// 1. Build your custom template with the kit's CometChatMessageTemplate class.
// ⚠️ It is `new CometChatMessageTemplate(...)` (UI Kit) — NOT
// `new CometChat.MessageTemplate(...)`. The Chat SDK has no MessageTemplate
// export; that form does not exist and will not compile.
const locationTemplate = new CometChatMessageTemplate({
type: "location",
category: CometChatUIKitConstants.MessageCategory.custom, // "custom"
contentView: (message, alignment) => <LocationBubble message={message} />,
// headerView / footerView / bottomView / bubbleView / statusInfoView / options
// all inherit the kit's defaults when omitted.
});
// 2. Merge with the kit's defaults — DO NOT pass only your template.
// CometChatUIKit.getDataSource() is the public accessor; it returns the same
// DataSource as ChatConfigurator.getDataSource() (the latter is internal).
const defaultTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
const mergedTemplates = [...defaultTemplates, locationTemplate];
<CometChatMessageList templates={mergedTemplates} />
Same rule for attachment options. getAttachmentOptions takes a ComposerId ({ user?, group?, parentMessageId? }) AND a required second argument (additionalConfigurations), then append your action:
// ComposerId = { parentMessageId, user, group } — all three keys, values nullable.
const composerId = {
parentMessageId: null,
user: selectedUser?.getUid() ?? null,
group: selectedGroup?.getGuid() ?? null,
};
// ⚠️ MUST pass a defined object as the 2nd arg. The extension data sources
// (Polls, Collaborative Document/Whiteboard) read `messageToReplyRef` off it
// WITHOUT optional chaining — passing nothing/undefined throws at runtime:
// "Cannot read properties of undefined (reading 'messageToReplyRef')"
// (Verified against the official v6 sample app's live-location feature.)
const additionalConfigurations = { messageToReplyRef: { current: null } };
const defaultAttachments = CometChatUIKit.getDataSource().getAttachmentOptions(
composerId,
additionalConfigurations,
);
const mergedAttachments = [...defaultAttachments, new CometChatMessageComposerAction({
id: "send-location",
title: "Location",
iconURL: "/icons/location.svg",
onClick: () => { /* open location picker */ },
})];
<CometChatMessageComposer attachmentOptions={mergedAttachments} />
Also: when sending the custom message, set both receiverType AND type correctly. Two testers hit "Cannot determine message recipient" because they passed a partial CustomMessage constructor. Use the full form:
const msg = new CometChat.CustomMessage(
receiverID, // who to send to (required)
receiverType, // CometChat.RECEIVER_TYPE.USER or .GROUP (required — this is the field testers missed)
"location", // custom type identifier
{ lat, lng, label } // your payload
);
CometChat.sendCustomMessage(msg);
Custom type sends + renders live, but vanishes on reload? The custom message appears immediately (the
ccMessageSentevent), but to fetch it from history you must include your custom category + type in the list'smessagesRequestBuilder. Extend the kit's defaults (don't hand-list them) — append togetAllMessageCategories()+getAllMessageTypes():const categories = CometChatUIKit.getDataSource().getAllMessageCategories(); if (!categories.includes(CometChatUIKitConstants.MessageCategory.custom)) categories.push(CometChatUIKitConstants.MessageCategory.custom); const types = CometChatUIKit.getDataSource().getAllMessageTypes(); if (!types.includes("location")) types.push("location"); const messagesRequestBuilder = new CometChat.MessagesRequestBuilder() .setCategories(categories).setTypes(types).hideReplies(true).setLimit(30); <CometChatMessageList templates={mergedTemplates} messagesRequestBuilder={messagesRequestBuilder} />(Verified against the official v6 sample app's live-location feature.) Tip: on the
CustomMessage, callsetConversationText("Live Location")so it reads nicely as the conversation-list preview, andsetSender(loggedInUser)for optimistic render.
Override an existing message type's bubble (text / image / etc.)
Same templates API — fetch all, replace contentView (or bubbleView for the whole bubble) on the matching template, pass the array. There is NO separate "override" call; you reuse getAllMessageTemplates():
const templates = CometChatUIKit.getDataSource().getAllMessageTemplates();
const withCustomTextBubble = templates.map((t) => {
if (
t.type === CometChatUIKitConstants.MessageTypes.text &&
t.category === CometChatUIKitConstants.MessageCategory.message
) {
t.contentView = (message, alignment) => <MyTextBubble message={message} />;
// or t.bubbleView = (...) => <... /> to replace the ENTIRE bubble (header+content+footer)
}
return t;
});
<CometChatMessageList templates={withCustomTextBubble} />
(CometChatUIKit.getDataSource().getMessageTemplate(type, category) returns a single template if you'd rather fetch just one — but you still pass the full array to the templates prop.)
Add a custom message option (Forward-style long-press action)
Message options live on each template's options function. Override it and merge with the kit defaults (same REPLACE-vs-APPEND rule) via getMessageOptions. Custom actions use CometChatActionsIcon (NOT CometChatMessageComposerAction — that's composer-only):
import { CometChatActionsIcon } from "@cometchat/chat-uikit-react";
const templates = CometChatUIKit.getDataSource().getAllMessageTemplates();
const withForward = templates.map((t) => {
if (t.type === CometChatUIKitConstants.MessageTypes.text) {
t.options = (loggedInUser, message, group) => {
// getMessageOptions(loggedInUser, messageObject, group?, additionalParams?)
const options = CometChatUIKit.getDataSource().getMessageOptions(loggedInUser, message, group);
options.push(
new CometChatActionsIcon({
id: "forward",
title: "Forward",
iconURL: "/icons/forward.svg",
onClick: (id) => { /* open your forward-to picker → CometChat.sendMessage(...) */ },
})
);
return options;
};
}
return t;
});
<CometChatMessageList templates={withForward} />
"Forward" is not a built-in kit option, so it's added as a custom CometChatActionsIcon. The built-ins (reply, edit, delete, react, …) come from getMessageOptions — keep them by merging, don't return only your action.
⚠️ Kit-side limitation (ENG-35706): custom message send sometimes replaces an existing message in the list in real-time (UI-side overwrite, not server-side). No client workaround today; file a kit ticket if you observe this and document for the customer.
Text formatters (inline text styling — mentions, URLs, custom @/#/! tokens)
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 105
- Forks
- 2
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
cometchat-features- Source
- github.com/cometchat/cometchat-skills