cometchat-customization — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cometchat-customization (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Ground truth: the per-platform UI Kit customization systems (theme objects / CSS vars, message templates, text formatters) verified against the installed kit. (Official docs linked below.) Verify symbols against the installed package/source before relying on them.
Companion skills:cometchat-componentsprovides the component catalog (what exists); this skill provides the customization workflow (how to modify what exists). Usecometchat-componentsto look up component names and props, then use this skill to plan and execute the customization. For any pattern not covered below, the docs MCP atcometchat-docsis the source of truth — query it before generating any code.
The user has already run /cometchat (or invoked the cometchat skill via their agent's mechanism — keyword "cometchat" or "integrate chat" works in most agents) (Phase A complete — there's a working integration with .cometchat/state.json) and wants to change how a component looks or behaves beyond what the CLI's deterministic commands handle.
Trigger phrases:
/cometchat customizereplies, etc.) → use cometchat-features instead
border radius) → use cometchat-theming instead (CSS-variable overrides written directly into the project — there is no theming CLI)
cometchatdispatcher skill to run Phase A first
cometchat-troubleshooting and run cometchat doctor
This skill is fundamentally docs-driven — every customization question requires a fact (prop name, callback signature, builder method, event topic, CSS selector) that lives in the canonical CometChat docs, not in this skill's text. Embedding examples here would create drift the moment the SDK changes.
The canonical CometChat docs are the source of truth for this skill. The docs MCP at cometchat-docs is the best way to query them when available, but it is not a hard requirement — fall back to the public docs site for any agent without it. The docs cover:
headerView, subtitleView, tailView,optionsView, bubbleView, emptyView, loadingView, errorView (which components support which slots — verified against the v6 React kit: the list components CometChatConversations/MessageList/Users/ Groups use emptyView/loadingView/errorView, not the *StateView form; only CometChatNotificationFeed uses emptyStateView/loadingStateView/errorStateView)
CometChatMessageTemplate.type,category, contentView, headerView, footerView)
ConversationsRequestBuilder,MessagesRequestBuilder, UsersRequestBuilder, GroupsRequestBuilder, CallLogsRequestBuilder and their methods
CometChatMessageEvents, CometChatUserEvents,CometChatGroupEvents, CometChatCallEvents, CometChatUIEvents and the topic names
(.cometchat-message-bubble-incoming, .cometchat-conversations-header, etc.)
Hard rules:
invent prop names, builder methods, event topics, or CSS classes from training-data memory. Use whichever lookup path is available, in order:
cometchat-docs MCP tool if your agenthas it. Richest path.
claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp. Other agents (Cursor, Codex, Cline, …) configure MCP their own way, or not at all — do NOT block.
URLs below, or web-search site:cometchat.com/docs. Universal fallback; never STOP and dead-end the user when the MCP isn't installed — fall through to (c).
both are options — composition is more stable across SDK versions.
bubbleView/contentView), adding a Message Composer attachment option, and adding a message action like Forward — all live in `cometchat-features` §Type 5 (append-not-replace via CometChatUIKit.getDataSource()). Route there for the actual code; this skill covers the custom-VIEW-slot props.CometChatTextFormatter): the four formatter guides custom-text-formatter-guide, mentions-formatter-guide, url-formatter-guide, shortcut-formatter-guide under ui-kit/react/. Recipe + the append-not-replace getAllTextFormatters({}) pattern live in `cometchat-features` §Type 5 → Text formatters.CometChatLocalize) — route there for any locale/string work; docs https://www.cometchat.com/docs/ui-kit/react/localizenpx @cometchat/skills-cli info --jsonIf integrated is false, stop and tell the user to run /cometchat first to create the base integration. Customization modifies an existing integration; it doesn't create one.
Note the framework, experience, files_owned, and applied_features from the response — you'll need them in the next steps.
START HERE: Read the component catalog at references/component-catalog.md (in this skill's directory). It has the canonical list of all 88 exported symbols, all 14 sample-app patterns, and a 40-row task→component lookup table. If the user's request maps to an entry in the catalog, use that entry directly — skip the rest of this step.If the catalog doesn't have a match (or you need prop-level detail), walk these FOUR discovery checks in this exact order:
integration ALREADY mounts have a prop that does what the user is asking for? The kit follows a "props over components" philosophy — most additions are props on existing components, not new components. This check goes FIRST.
built-in CometChat<X> component in @cometchat/chat-uikit-react's exports?
--cometchat-<x> CSSvariable for any styling you'd write?
the sample app at github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/components for the user's pattern?
The CometChat React UI Kit ships FOUR things, not one:
filters, custom views, click handlers, disable flags) are PROPS on existing components — NOT new components
@cometchat/chat-uikit-react/css-variables.css
chat UX patterns (user/group details, threaded messages layout, top-level home layout, multi-tab chat, notifications, new chat dialog, etc.) that combine multiple kit components but aren't shipped as single named exports
Critical: the docs MCP does NOT index the sample app. When the MCP says "no `CometChat<X>` component exists", that only covers the npm package — you must still check the sample app via GitHub before concluding the user needs hand-rolled code.
Hand-rolling something the kit, the variable system, OR the sample app already provides means missing the kit's theming, accessibility, i18n, error handling, and every future SDK update.
#### 2a. Existing-component prop check (do this FIRST)
Most chat features are already props on the components you have. A user asking for "add search", "filter conversations", "custom empty state", or "click handler on a message" is almost always asking for a prop, not a new component or custom code.
Process:
integration.** Read the integration's owned files (from state.json) and grep for <CometChat JSX usage:
grep -hoE '<CometChat[A-Z][a-zA-Z]*' \
$(jq -r '.files_owned[]' .cometchat/state.json 2>/dev/null) \
2>/dev/null | sort -u"CometChatConversations props""CometChatMessageList props""CometChatMessageHeader props""CometChatMessageComposer props"mappings:
| User asks for | Likely prop on which component |
|---|---|
| Search bar / "add search" | showSearchBar on CometChatConversations (or onSearchBarClicked to swap in <CometChatSearch> for advanced dual-scope search) |
| Filter conversations | conversationsRequestBuilder on CometChatConversations |
| Filter messages | messagesRequestBuilder on CometChatMessageList |
| Filter users / groups | usersRequestBuilder / groupsRequestBuilder |
| Custom empty state | emptyView on the list components (Conversations/MessageList/Users/Groups); emptyStateView only on CometChatNotificationFeed |
| Custom error UI | errorView (list components); errorStateView on CometChatNotificationFeed |
| Custom loading UI | loadingView (list components); loadingStateView on CometChatNotificationFeed |
| Custom header above the list | headerView |
| Custom message bubble | templates prop on CometChatMessageList (not a custom bubble component) |
| Click handler on item / message / search bar / back button | onItemClick, onMessageClick, onBack, onSearchBarClicked |
| Hide / disable a sub-feature | disable* boolean props (e.g. disableTyping, disableReactions) |
| Custom subtitle / status / timestamp | subtitleView, statusView, timestampView |
| Show / hide receipts | hideReceipts |
| Selection mode | selectionMode on list components |
If you find a matching prop, just add the prop and stop. No new components. No custom CSS. No new files. Surface to the user: "The `<X>` you already have supports this via the `<propName>` prop. Adding that single prop."
If 2a turns up nothing, proceed to 2b.
#### 2b. New-component check (do this only if 2a turned up nothing)
Common requests that look like "customization" but are actually "use the existing component":
| User asks for | Use this built-in component |
|---|---|
| Threaded replies / "wire up threads" | CometChatThreadHeader + scope a CometChatMessageList and CometChatMessageComposer with parentMessageId |
| Group members panel / "list group members" | CometChatGroupMembers |
| Add members to a group | CometChatAddMembers |
| Transfer group ownership | CometChatTransferOwnership |
| Banned users management | CometChatBannedMembers |
| Block/unblock users panel | CometChatBlockedUsers |
| New chat / "start a new conversation" dialog | CometChatNewChat |
| Create new group dialog | CometChatCreateGroup |
| User / group details panel | CometChatDetails |
| Mentions popover in composer | CometChatMentionsFormatter (already wired into the composer) |
| Voice / video call buttons in header | CometChatCallButtons |
| Outgoing call screen | CometChatOutgoingCall |
| Incoming call notification | CometChatIncomingCall |
| Ongoing call UI | CometChatOngoingCall |
| Call logs list | CometChatCallLogs |
| Reactions on messages | Already built into CometChatMessageList — check if it's just disabled |
| Message bubble customization | Use the templates prop on CometChatMessageList, not a custom bubble component |
⚠️ Not every row above is a kit export.CometChatAddMembers,CometChatTransferOwnership,CometChatBannedMembers,CometChatBlockedUsers,CometChatNewChat,CometChatCreateGroup, andCometChatDetailsare sample-app components, NOT `@cometchat/chat-uikit-react` v6 exports — importing<CometChatTransferOwnership/>etc. is an unresolved-import build error. Build these by copying the sample-app implementation (§2d), do not import them from the package. The genuinely package-exported entries in this table are:CometChatThreadHeader,CometChatGroupMembers,CometChatMentionsFormatter,CometChatCallButtons,CometChatOutgoingCall,CometChatIncomingCall,CometChatOngoingCall,CometChatCallLogs. Always grep the installed package's exports (next step) before emitting any of these.
Search strategies, in this order:
Examples:
"thread reply UI react ui kit" → finds CometChatThreadHeader"new chat dialog" → finds CometChatNewChat"group transfer ownership" → finds CometChatTransferOwnership"block user list" → finds CometChatBlockedUsers grep -E "^export.*CometChat[A-Z][a-zA-Z]+" \
node_modules/@cometchat/chat-uikit-react/dist/index.d.ts \
2>/dev/null | head -50https://www.cometchat.com/docs/ui-kit/react/components-overview
If you find a built-in component that matches, use it as-is. Surface to the user: "The kit already ships `CometChat<X>` for this. I'll wire it up directly."
#### 2c. Stylesheet check (do this even when you DO need custom layout glue)
Even when you have to write some CSS for layout glue (positioning a panel, sizing a container, wiring up the height chain that .cometchat-message-list requires), never hand-pick colors, fonts, borders, spacings, or radii from your head. The kit ships a canonical CSS variable system. Use it.
The rule:
containers, the height chain). Example: .thread-wrapper { width: 400px; height: 100vh; display: flex; flex-direction: column; }
.thread-wrapper { border-left: 1px solid var(--cometchat-border-color-light); background: var(--cometchat-background-color-01); }
badge / divider that the kit already provides as a component. Example: a hand-rolled .thread-header + .thread-close button when CometChatThreadHeader exists.
that don't reference the --cometchat-* variables. Example: border: 1px solid #E8E8E8 instead of border: 1px solid var(--cometchat-border-color-light).
Discovery commands for the variable system:
# List every --cometchat-* variable the kit defines
grep -oE '\-\-cometchat-[a-z0-9-]+' \
node_modules/@cometchat/chat-uikit-react/css-variables.css \
2>/dev/null | sort -u | head -60
# Or search for a specific token category
grep -E '\-\-cometchat-(border|background|text|primary|font)' \
node_modules/@cometchat/chat-uikit-react/css-variables.css \
2>/dev/null | head -40Common variable categories (query the docs MCP for the canonical list — these change between SDK versions):
| Category | Example variables |
|---|---|
| Brand colors | --cometchat-primary-color, --cometchat-error-color, --cometchat-success-color |
| Backgrounds | --cometchat-background-color-01 (white), --cometchat-background-color-02, --cometchat-background-color-03 (light grey) |
| Text | --cometchat-text-color-primary, --cometchat-text-color-secondary, --cometchat-text-color-tertiary |
| Borders | --cometchat-border-color-light, --cometchat-border-color-default, --cometchat-border-color-dark |
| Radii | --cometchat-radius-1, --cometchat-radius-2, --cometchat-radius-3, --cometchat-radius-max |
| Fonts | --cometchat-font-heading1-bold, --cometchat-font-heading4-medium, --cometchat-font-body-regular, --cometchat-font-caption2-regular |
| Spacing | --cometchat-spacing-1 through --cometchat-spacing-10 |
| Shadows | --cometchat-shadow-1, --cometchat-shadow-2, --cometchat-shadow-3 |
#### 2d. Sample app reference check (do this when 2a + 2b turned up nothing)
If 2b didn't find a CometChat<X> component for the user's request, don't immediately conclude they need custom code. The kit ships a reference sample app at:
https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/components
with implementations for common chat UX patterns that combine multiple kit components but aren't shipped as single named exports. Examples that look like "missing components" but are in the sample app:
| User asks for | Sample app reference path |
|---|---|
| User / group details panel | sample-app/src/components/CometChatDetails/CometChatUserDetails.tsx (group details is inline in CometChatHome.tsx's SideComponentGroup) |
| Threaded messages panel layout | sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx |
| Top-level chat layout (left pane + main + side rail) | sample-app/src/components/CometChatHome/CometChatHome.tsx |
| Multi-tab chat (Chats / Calls / Users / Groups) | sample-app/src/components/CometChatSelector/CometChatTabs.tsx |
| New conversation dialog with user/group picker | Inline in CometChatHome.tsx as CometChatNewChatView (CSS: sample-app/src/styles/CometChatNewChat/CometChatNewChatView.css) |
| Search view (conversations + messages) | sample-app/src/components/CometChatSearchView/ |
| Call log details / history / recordings | sample-app/src/components/CometChatCallLog/ (5 sub-files: Details, History, Info, Participants, Recordings) |
| App state / active-chat React context | sample-app/src/context/AppContext.jsx + appReducer.ts |
| Group ownership transfer modal | sample-app/src/components/CometChatTransferOwnership/ |
These patterns include matching CSS at sample-app/src/styles/<ComponentName>/ using BEM-style class names that are already wired to the kit's CSS variable system.
Discovery commands:
# List the sample app's components directory via the GitHub API
curl -s "https://api.github.com/repos/cometchat/cometchat-uikit-react/contents/sample-app/src/components?ref=v6" \
| grep -oE '"name":\s*"[^"]+"' | head -30
# Fetch a specific component file directly
curl -s "https://raw.githubusercontent.com/cometchat/cometchat-uikit-react/v6/sample-app/src/components/CometChatDetails/CometChatUserDetails.tsx"
# Fetch its matching stylesheet
curl -s "https://raw.githubusercontent.com/cometchat/cometchat-uikit-react/v6/sample-app/src/styles/CometChatDetails/CometChatUserDetails.css"You can also use WebFetch on the URLs above. The docs MCP does NOT index the sample app — you must fetch it from GitHub directly.
If you find a matching reference implementation:
.tsx file AND its matching .css file (atsample-app/src/styles/<ComponentName>/)
e.g. src/cometchat/CometChatDetails/CometChatUserDetails.tsx plus src/cometchat/CometChatDetails/CometChatDetails.css
(.cometchat-user-details__header, .cometchat-user-details__content-avatar, etc.) — they're already integrated with the kit's CSS variable system
doesn't have:
useContext(AppContext) → inline the valuesgetLocalizedString(...) → inline the English stringscometchat-resources/ SVG icons → use Unicode equivalents orstrip them
but the official sample app has the reference implementation at cometchat/cometchat-uikit-react/v6/sample-app/.../CometChat<X>. I'm adapting it to your project."*
#### 2e. After discovery — decide what to do
In strict order, take the FIRST option that applies:
No new files. Most chat features land here.
component as-is. Zero custom CSS.
component; write minimal layout-only CSS that consumes --cometchat-* variables (per 2c).
sample app pattern, mirroring its file structure and BEM class names.
classify the request as a true customization.
Read the user's request and place it into one of these buckets. The right approach is different per bucket:
| Bucket | Examples | Approach |
|---|---|---|
| A. Custom view slot | "add a custom header above the conversation list", "show a custom empty state", "render messages with my own bubble" | Use the corresponding *View prop (headerView, emptyView, bubbleView, etc.) — look up which prop the target component supports (list components use emptyView/loadingView/errorView; CometChatNotificationFeed uses the *StateView form) |
| B. Filter / pagination | "only show conversations with VIP users", "load 10 messages at a time", "show only joined groups" | Use the corresponding RequestBuilder (ConversationsRequestBuilder.setTags, setLimit, setUserAndGroupTags, etc.) — query the MCP for the builder methods |
| C. Action / callback | "do X when a user clicks a conversation", "intercept message send", "log every search" | Use the corresponding on* callback prop (onItemClick, onSendButtonClick, onSearch, etc.) — query the MCP for the callback signature |
| D. Event subscription | "show a toast when a new message arrives", "update my unread count when someone reads a message", "track typing indicators" | Subscribe to the corresponding CometChat*Events topic (CometChatMessageEvents.ccMessageSent, ccMessageRead, CometChatUserEvents.ccUserOnline, etc.) — query the MCP for the event topic |
| E. Component-level CSS | "make incoming bubbles green", "hide the conversation timestamps", "compact the message list spacing" | Add a CSS rule under .cometchat <selector> in the integration's global stylesheet — query the MCP for the right selector class. NEVER invent class names; the SDK's selectors are namespaced and prefix-protected. |
| F. Component composition | "wrap CometChatConversations with my own search bar", "render two CometChatGroups side by side", "embed CometChatMessageList inside my own card layout" | Standard React composition. The CometChat components are React components — use them like any other component. Query the MCP for which props are required vs optional. |
Message templates / options / composer attachments → use the verified recipes in `cometchat-features` §Type 5, not a hand-rolledbubbleView. Sending a custom message TYPE, overriding an existing type's bubble, adding a Forward-style message action, or adding a composer attachment all require the append-not-replaceCometChatUIKit.getDataSource()merge (a baretemplates=/attachmentOptions=array silently wipes the built-ins — ENG-35706). §Type 5 has the copy-ready, tsc-verified code.
If the user's request doesn't fit any bucket, ask them to clarify — don't guess. Customization is the place where ambiguous requests produce wrong code most often.
Once you've classified the request, query the docs MCP with a specific search:
| Bucket | MCP query example |
|---|---|
| A. Custom view slot | "headerView prop CometChatConversations" |
| B. Filter / pagination | "ConversationsRequestBuilder methods setTags" |
| C. Action / callback | "CometChatMessageList onMessageClick callback signature" |
| D. Event subscription | "CometChatMessageEvents ccMessageSent subscribe" |
| E. Component-level CSS | "CSS selector cometchat-message-bubble-incoming" |
| F. Component composition | "CometChatConversations props required" |
The MCP returns canonical, current docs. Read them BEFORE writing any code. If multiple results come back, prefer the React UI Kit v6 result over older versions.
Use the framework + experience you noted in Step 1 to find the right file. The integration's primary client file is conventional per framework:
| Framework | Primary client file |
|---|---|
| reactjs (Vite) | src/App.tsx (renders the conversation list / messages) + src/cometchat/CometChatSelector.tsx (the selector) |
| nextjs (App Router) | src/app/cometchat/CometChatNoSSR.tsx (renders the chat) + src/app/cometchat/CometChatSelector.tsx (the selector) |
| nextjs (Pages Router) | src/cometchat/CometChatNoSSR.tsx + src/cometchat/CometChatSelector.tsx |
| react-router (v6 + v7) | app/cometchat/CometChatNoSSR.tsx + app/cometchat/CometChatSelector.tsx |
| astro | src/cometchat/ChatApp.tsx (the React island) + src/cometchat/CometChatSelector.tsx |
For CSS overrides (bucket E), the global stylesheet is:
src/index.csssrc/app/globals.csssrc/styles/globals.cssapp/app.csssrc/cometchat/ChatApp.tsx (NOT a global stylesheet)These are also in state.json under files_owned if you need to verify.
Generate the code based on the docs MCP response from Step 4. Show the user:
code)
file)
Wait for the user to confirm before writing. Customization edits the integration's owned files — drift detection will show this on the next cometchat info. The user should know.
If the user confirms, write the change. If they don't, surface what they'd want to change and stop.
npx @cometchat/skills-cli verify --jsonThe 5 AST checks still apply to customized files. If anything fails, surface verbatim and offer to revert.
npx @cometchat/skills-cli info --jsonThe customized file will now show as drifted (its checksum no longer matches the original template). This is expected — it's the explicit drift the user just asked for. Not a bug.
The dev server picks up React changes via HMR. Tell the user:
Then offer to do another customization OR to return to the framework skill's Phase B menu.
or hand-rolled UI. The kit follows a "props over components" philosophy and ships FOUR things, not one: (0) props on already-mounted components for most features (search bar, filters, custom views, click handlers, disable flags) — check this FIRST, (1) 60+ named React components in `@cometchat/chat-uikit-react`, (2) a 200+ CSS variable system in `css-variables.css`, (3) a reference sample app at `github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/components` with implementations for common chat UX patterns that combine multiple kit components but aren't shipped as single named exports (user/group details panels, thread layouts, top-level home layout, notifications, new chat dialog, etc.). The docs MCP does NOT index the sample app — fetch it from GitHub directly. Adding a new component when an existing one's prop would do, or hand-rolling something the kit, the variable system, or the sample app already provides, means missing the kit's theming, i18n, accessibility, and every future SDK update. Step 2 (subsections 2a + 2b + 2c + 2d) is mandatory — do NOT skip it. 2a (existing-component prop check) goes FIRST** because most features are props on already-mounted components, not new components.
sizing, flex/grid containers, the height chain). Even there, never hardcode colors / fonts / borders / radii / spacings — always reference --cometchat-* variables. Hand-rolled headers, buttons, icons, panels, badges, dividers, etc. are NEVER OK if the kit already provides them.
CSS selector. Never invent SDK API from memory.
existing integration files; it does not create new ones.
user-side intent — they need visibility.
The user's customizations live in state.files_owned and will show up in cometchat info as modified. That's correct.
composition is stable across SDK versions; CSS selectors are not.
class prefix is .cometchat- but the leaf names (-message-bubble-incoming, -conversations-header, etc.) MUST come from the docs.
contract): docs MCP if your agent has it → else fetch/web-search the public docs at cometchat.com/docs. Never STOP just because the MCP isn't installed — fall through to the public docs.
cometchat init)cometchat-features+ cometchat apply-feature)
cometchat-theming —CSS-variable overrides, no CLI)
cometchat-troubleshooting + cometchat doctor)
components that the integration already uses
For anything in the "does not" list, route the user to the right skill/command instead of attempting it here.
Sound is a customization sub-dimension. The UI Kit plays incoming/outgoing message + call sounds via CometChatSoundManager — mute it, swap custom audio, or play a specific sound. The full API + recipe lives in `cometchat-theming` (Sound section). Verify the access path against the installed kit before relying on it.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.