[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6MF9014T2SNB4VP9YGC8104":3,"skill-same:01M6MF9014T2SNB4VP9YGC8104":98},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":59,"repositoryHtmlUrl":60,"repositoryHomepageUrl":61,"ownerHtmlUrl":62,"ownerBlogUrl":63,"ownerDescription":64,"updatedAt":65,"install":66,"resources":79},"01M6MF9014T2SNB4VP9YGC8104","cometchat-flutter-v5-sdk",null,"Add voice & video calling to any Flutter app FROM SCRATCH with the headless CometChat Calls SDK v5 (`cometchat_calls_sdk`, pub.dev) — no UI Kit. init→login→generateCallToken→joinSession, which hands back a Flutter `Widget?` you mount in your tree; CallSession listeners, in-call actions (mute\u002Fvideo\u002Flayout\u002Frecord\u002FPiP\u002Fraise-hand), meet-style session rooms AND 1:1 ringing (Chat SDK signaling + Calls SDK media). Triggers: 'add calling from scratch flutter', 'standalone video call dart', 'headless calls sdk flutter', 'build my own call screen flutter', 'meeting room join by session id flutter', 'one-on-one ringing call without uikit flutter'.","hashgraph-online\u002Fawesome-codex-plugins","hashgraph-online","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F160371962?v=4","01M6CNB6NRJVNNGN14TR01Q6D3","HOL (Hashgraph Online)","01M6JT1HSKKG9V68KQAQGBA7XP",1575,"MIT","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fcometchat\u002Fcometchat-skills\u002Fskills\u002Fcometchat-flutter-v5-sdk\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"sdk","cometchat flutter v5 sdk","flutter","cometchat","scratch","calling","dev","call","triggers","for","ui","verified","screen","login","you","join","kit","actions","Media","which","app","Video","2026-11-10 10:12:30",false,"---\nname: cometchat-flutter-v5-sdk\ndescription: \"Add voice & video calling to any Flutter app FROM SCRATCH with the headless CometChat Calls SDK v5 (`cometchat_calls_sdk`, pub.dev) — no UI Kit. init→login→generateCallToken→joinSession, which hands back a Flutter `Widget?` you mount in your tree; CallSession listeners, in-call actions (mute\u002Fvideo\u002Flayout\u002Frecord\u002FPiP\u002Fraise-hand), meet-style session rooms AND 1:1 ringing (Chat SDK signaling + Calls SDK media). Triggers: 'add calling from scratch flutter', 'standalone video call dart', 'headless calls sdk flutter', 'build my own call screen flutter', 'meeting room join by session id flutter', 'one-on-one ringing call without uikit flutter'.\"\nlicense: \"MIT\"\ncompatibility: \"Flutter >=2.5.0, Dart >=2.17.0 \u003C4.0.0 · Android minSdk 26 (Android 8.0) · iOS 15.1. cometchat_calls_sdk ^5.0.3 — resolves to 5.0.9 (latest); compiler-verified vs 5.0.7, and 5.0.8\u002F5.0.9 source-checked with no API removed. 1:1 ringing also needs cometchat_sdk v5 (>=5.0.6, latest 5.0.8 — the signaling symbols are identical across them) for signaling.\"\nmetadata:\n  author: \"CometChat\"\n  version: \"1.0.0\"\n  tags: \"cometchat calls sdk v5 headless voice video webrtc dart flutter calling standalone\"\n---\n\n> **Ground truth:** `cometchat_calls_sdk` **5.0.7 from pub.dev** + catalog `flutter-calls-v5.json` (the closed symbol list — 59 COMPILER-VERIFIED symbols; every type below is in it). Catalog built from the PUBLISHED package; at 5.0.7 it matches the `calls-core` monorepo exactly — but **never infer that from a version string** (`references\u002Fdocs-map.md` § \"Upstream\"). Official docs: `\u002Fcalls\u002Fflutter\u002F**` = **v5** · Docs MCP. Fetch exact `SessionSettings` fields, event names and signatures from the docs (`references\u002Fdocs-map.md`) — never memory. **⚠️ The live pages carry ~56 symbols that DO NOT COMPILE, including the entire documented token flow — see \"Doc corrections\" below; prefer THIS skill's names over the page's.** **APPEND to the user's app — additive wiring only.** This is the HEADLESS path (no UI Kit); for the prebuilt drop-in call UI use `cometchat-flutter-v6-calls` instead.\n\n## Companion skills (read first)\n- **Standalone\u002Fheadless entry** — this skill owns its own package (the Calls SDK) and has no `-core` sibling; self-contained for meet-style calling.\n- **For 1:1 RINGING only** it also drives the **Chat SDK** (`cometchat_sdk` v5) for signaling — signatures fetched via `references\u002Fdocs-map.md` (§ \"1:1 RINGING\"). It does NOT depend on the Flutter UI Kit.\n- **Prefer the UI Kit instead?** If the app also wants chat and a prebuilt call UI, use `cometchat-flutter-v6-core` + `cometchat-flutter-v6-calls` — not this skill.\n\n## Use this skill when\n\"add calling from scratch \u002F without the UI Kit\", \"standalone voice\u002Fvideo on Flutter\", \"build my own call screen\", \"headless calls SDK\", \"meeting-room join by session id\", \"one-on-one ringing\". Precondition: the caller chose the **from-scratch \u002F standalone** path (the \"add calling\" router asks this). If they want the prebuilt call UI, route to `cometchat-flutter-v6-calls`.\n\n## Prerequisites & install\n```yaml\n# pubspec.yaml\ndependencies:\n  cometchat_calls_sdk: ^5.0.9   # latest; API compiler-verified vs 5.0.7, unchanged through 5.0.9\n```\nthen `flutter pub get`.\n\n**1:1 ringing additionally needs the Chat SDK** (`cometchat_sdk` v5) for signaling.\n\n**Permissions — REQUIRED or the call dies on the first permission prompt.**\n- `android\u002Fapp\u002Fsrc\u002Fmain\u002FAndroidManifest.xml`: `INTERNET`, `CAMERA`, `RECORD_AUDIO`, `MODIFY_AUDIO_SETTINGS`, `ACCESS_NETWORK_STATE`. On **API 23+ you must ALSO request camera + mic at runtime** — the manifest alone is not enough, and this is the single most common \"the SDK is broken\" report on Android.\n- `ios\u002FRunner\u002FInfo.plist`: `NSCameraUsageDescription` + `NSMicrophoneUsageDescription`.\n- Android **`minSdkVersion 26`**, iOS **`platform :ios, '15.1'`** — the real floors (5.0.7 through 5.0.9). **The docs say 24 and iOS 12; both fail at BUILD time.** iOS moved 13.0 → 15.1 *in 5.0.7*, so an app can break on a routine `pub upgrade`.\n\n**Credentials:** App ID · Region · Auth Key (dev only), fetched through the CometChat MCP — `cometchat_whoami` (connected + signed in?), `cometchat_list_apps` (ask which EXISTING app), `cometchat_get_app_credentials`, or pasted from Dashboard → Credentials. Mint **auth tokens server-side** for production; never ship the Auth Key.\n\n## Init & login ordering (BAKED — invariant)\nInit (once, must succeed) → `CometChatCalls.login(...)` → then `generateCallToken` \u002F `joinSession` \u002F listeners. Nothing joins before init+login resolve. `CometChatCalls.isInitialized` is the guard.\n\n- **DEFAULT to `CometChatCalls.initFromSettings(onSuccess:, onError:)`** — the ai-agent \u002F telemetry-attributed path (persists `integrationSource=\"ai-agent\"`).\n\n  \u003C!-- STOPGAP: source-derived (calls-core\u002Fcalls-sdk-flutter), NOT in the public docs.\n       `initFromSettings` is `@nodoc` and ai-agent-only. DOCS-BACKLOG F4\u002FD4 closed it WONTFIX —\n       it is to STAY hidden, so this stopgap is permanent, not pending a docs fix. -->\n  It takes **no settings argument**: it reads `cometchat-settings.json` through **`rootBundle`**, so the file must sit at the **project root** *and* be registered as a Flutter asset:\n  ```yaml\n  flutter:\n    assets:\n      - cometchat-settings.json\n  ```\n  Root keys `appId` + `region`; optional `callsSDK` → `adminHost`\u002F`clientHost`\u002F`callsHost`. **No Auth Key — the Calls SDK reads nothing else from this file** (the key is a `login()` argument). Registering it under `flutter: assets:` is the ONLY step; no Xcode or Gradle change, because it is read through `rootBundle`. Miss the `assets:` entry and init fails with settings-file-not-found — a quiet callback, not a crash.\n\n- **Fallback (public-doc path):**\n  ```dart\n  CallAppSettings s = (CallAppSettingBuilder()..appId = appId..region = region).build();\n  CometChatCalls.init(s, onSuccess: (String m) {}, onError: (CometChatCallsException e) {});\n  ```\n  Note the **Dart cascade** (`..appId =`) — these are **fields, not `setX()` methods**. `CallAppSettingBuilder` is singular (no `s`).\n- ⚠️ **Never do both.** A builder init AFTER `initFromSettings` re-attributes the app to `\"manual\"` and the ai-agent telemetry is lost.\n- **Login:** `CometChatCalls.login(uid:, authKey:, onSuccess:, onError:)` (dev) or `CometChatCalls.loginWithAuthToken(authToken:, onSuccess:, onError:)` (production). Check `await CometChatCalls.getLoggedInUser()` first — it returns `Future\u003CUser?>` and the SDK keeps the session, so logging in twice is wasted work. **Both `onSuccess` callbacks hand you a NULLABLE `User?`** — the docs dereference it unguarded; do not copy that.\n\n## Two build modes (BAKED — the router picks one)\n- **Meet-style (session room)** — Calls SDK ONLY, no Chat SDK. Everyone joining the same session id lands in the same call.\n- **1:1 ringing** — Chat SDK signals, Calls SDK carries media. Needs `cometchat_sdk` v5 as well. Fetch signatures via `references\u002Fdocs-map.md` § \"1:1 RINGING\".\n\n## ⚠️ The Flutter fork: `joinSession` returns a WIDGET\nEvery other platform mounts the call into a container you hand it. **Flutter hands the call back to\nyou as a `Widget?`** and mounts nothing:\n```dart\nWidget? _callWidget;\n\nCometChatCalls.joinSession(\n  sessionId: sessionId,\n  sessionSettings: settings,\n  onSuccess: (Widget? w) => setState(() => _callWidget = w),   \u002F\u002F ← THIS is the render step\n  onError: (CometChatCallsException e) { \u002F* surface it *\u002F },\n);\n\n@override\nWidget build(BuildContext c) => Scaffold(body: _callWidget ?? const CircularProgressIndicator());\n```\nAn emit that ignores the `onSuccess` argument **joins the call successfully and shows nothing** — audio flows, no video, no controls. It reads as a broken SDK and it is the #1 Flutter-specific failure. There is no container parameter and no zero-bounds trap; there is only \"did you put the widget in the tree\".\n\n## SDK method map (BAKED closed list — from the catalog; signatures → FETCH from docs)\n- **Lifecycle:** `CometChatCalls.initFromSettings` · `CometChatCalls.init` · `CallAppSettingBuilder` → `CallAppSettings` · `CometChatCalls.isInitialized` · `login` · `loginWithAuthToken` · `logout` · `getLoggedInUser` → `User?`\n- **Session:** `CometChatCalls.generateCallToken(sessionId, ...)` → `CallToken` · `joinSession(...)` → `Widget?` · `SessionSettingsBuilder` → `SessionSettings` · `SessionType`\n- **⚠️ TWO join paths, both real in 5.0.7** — pick one: `generateCallToken(sessionId)` → `joinSession(callToken:sessionSettings:)`, **or** `joinSession(sessionId:sessionSettings:)` directly.\n- **In-call actions — on `CallSession.getInstance()`, for CUSTOM controls ONLY** (the returned widget already renders them; see pitfall #1): `leaveSession` · `muteAudio`\u002F`unMuteAudio` · `pauseVideo`\u002F`resumeVideo` · `setLayout` · `setAudioModeType` · `switchCamera` · `raiseHand`\u002F`lowerHand` · `startRecording`\u002F`stopRecording` · `startScreenShare`\u002F`stopScreenShare`\u002F`toggleScreenShare` · `pinParticipant`\u002F`unPinParticipant` · `muteParticipant` · `pauseParticipantVideo` · `enablePictureInPictureLayout`\u002F`disablePictureInPictureLayout` · `enterPipMode`\u002F`isPipSupported` · `setChatButtonUnreadCount` · `isCallSessionActive`\n  - **Toggles** (Flutter-only, no iOS analogue): `toggleMuteAudio` · `togglePauseVideo` · `toggleCameraSource` · `toggleRaiseHand`\n  - **Aliases** for the same actions: `endCallSession` · `startCallRecording`\u002F`stopCallRecording` · `setCallLayoutType`\n  - **Settings panels:** `hideSettingsPanel` · `openCallSettingsPanel` · `openVirtualBackgroundSettingsPanel`\n  - **State getters (read, don't track):** `isAudioMuted` · `isVideoPaused` · `isHandRaised` · `isRecording` · `isScreenSharing` · `isTranscribing`\n- **Listeners (on `CallSession.getInstance()`; four are add\u002Fremove, `LayoutListeners` is a single-slot property):** `SessionStatusListeners` · `ParticipantEventListeners` · `MediaEventListeners` · `ButtonClickListeners` · `LayoutListeners`\n- **Call logs:** `CallLogRequestBuilder` (top-level; **FIELDS, no `setX()`**) → `CallLogRequest` → `fetchNext`\u002F`fetchPrevious` → `CallLog` (+ `CallUser`\u002F`CallGroup`\u002F`CallEntity`)\n- **Background:** `CometChatOngoingCallService.launch()` \u002F `.abort()` — Android foreground service, no-op on iOS\n- **Enums:** `AudioMode` (`.speaker`\u002F`.earpiece`\u002F`.bluetooth`) · `SessionType` · `LayoutType` (`.tile`\u002F`.spotlight`\u002F`.sidebar`) · `CameraFacing`\n\n> A curated highlight, **NOT the full surface**. The authoritative closed list is the **catalog** (59 symbols, each proven by a `flutter analyze` probe). A symbol is real **iff it is in the catalog** — confirm there, then fetch its signature from the page in `references\u002Fdocs-map.md`.\n\n## Listener lifecycle (BAKED)\n**All five listener types are `abstract class`es you IMPLEMENT — they are NOT constructible.**\nThe live docs build every one of them with named callbacks\n(`SessionStatusListeners(onSessionJoined: () {...})`); an abstract class cannot be instantiated, so\nnone of those examples compile. `flutter analyze` reports `instantiate_abstract_class`.\n```dart\nclass _Status extends SessionStatusListeners {\n  @override void onSessionJoined() { \u002F* ... *\u002F }\n  @override void onSessionTimedOut() { \u002F* distinct from onSessionLeft — handle BOTH *\u002F }\n  \u002F\u002F `extends` instead of `implements` and the other four inherit their no-op bodies.\n}\n\nfinal _status = _Status();                                       \u002F\u002F hoist into a FIELD\nCallSession.getInstance()?.addSessionStatusListener(_status);     \u002F\u002F BEFORE joining\n\u002F\u002F teardown:\nCallSession.getInstance()?.removeSessionStatusListener(_status);  \u002F\u002F the SAME instance\nCallSession.getInstance()?.leaveSession();\n```\n- Every method already has a no-op body, so **`extends` lets you override only what you need**; `implements` obliges you to write them all.\n- **`remove*Listener` takes the object you added.** Constructing a fresh listener to remove one is a no-op that silently leaks the original — and it is what the live docs show (D4). Hoist into a field; there is no other shape in which removal works.\n- **⚠️ Registration names do NOT match the type names** — full table in `references\u002Fdocs-map.md`. Two you cannot guess: `MediaEvent**Listeners**` registers via `addMediaEvent**s**Listener`, and **`LayoutListeners` has no add\u002Fremove at all** — it is a single-slot `layoutListener = l` setter, cleared with `= null`.\n- **`CallSession.getInstance()` is never actually null** — the singleton is eagerly built, so registering BEFORE `joinSession` really does attach (certified: `onSessionJoined` fires). The type is still `CallSession?`, so keep `?.`; use `isCallSessionActive()` to test for a live session.\n- **`ButtonClickListeners` callbacks fire alongside the SDK's own action and do NOT suppress it.** Reacting to `onLeaveSessionButtonClicked` must NOT also call `leaveSession()` — the SDK is already leaving; doing both double-leaves. Use it to run `CometChat.endCall(sessionId)` on the ringing path.\n- **`Participant` has TWELVE fields, all nullable:** `uid` · `name` · `avatar` · `mid` · `state` · `isJoined` · `deviceId` · `joinedAt` · `leftAt` · `totalAudioMinutes` · `totalVideoMinutes` · `totalDurationInMinutes`. **No mute\u002Fpin\u002Fhand\u002Fshare flags** — the seven the docs' \"Participant Object Reference\" lists (`pid`\u002F`role`\u002F`audioMuted`\u002F`videoPaused`\u002F`isPinned`\u002F`isPresenting`\u002F`raisedHandTimestamp`) do NOT exist and do not compile (see `doc-corrections.md`); accumulate that live state from `ParticipantEventListeners`, as iOS must. Prefer `onParticipantListChanged`, which delivers the WHOLE list. (`Participants`, plural, is a `@Deprecated` typedef alias of `Participant`.)\n\n## Least-code recipe (meet-style — ORDER, not signatures)\n```dart\n\u002F\u002F Fetch every signature\u002Ffield from references\u002Fdocs-map.md. This is the ORDER, which is the part that bites.\nimport 'package:cometchat_calls_sdk\u002Fcometchat_calls_sdk.dart';\n\n1. CometChatCalls.initFromSettings(onSuccess:, onError:)   \u002F\u002F ai-agent default; cometchat-settings.json as a Flutter ASSET\n2. CometChatCalls.login(uid:, authKey:, onSuccess:, onError:)   \u002F\u002F or loginWithAuthToken in production\n3. final settings = (SessionSettingsBuilder()..setDisplayName(name)..setType(SessionType.video)).build();\n4. CallSession.getInstance()?.addSessionStatusListener(_status);   \u002F\u002F register BEFORE joining\n5. CometChatCalls.joinSession(sessionId:, sessionSettings:, onSuccess: (Widget? w) => setState(() => _call = w), onError:)\n   \u002F\u002F   or: generateCallToken(sessionId) -> joinSession(callToken:sessionSettings:)\n6. \u002F\u002F return _call from build() — NOTHING renders until you do\n7. \u002F\u002F NO control buttons needed — the returned widget ALREADY renders mute\u002Fvideo\u002Fleave.\n8. \u002F\u002F teardown -> remove each listener (same instance); CallSession.getInstance()?.leaveSession()\n```\n\n## Backgrounding & call notifications → `references\u002Fplatform-notes.md`\nTwo things that are NOT on the join path and are easy to get wrong:\n- **Backgrounding** — Android kills a call the moment the app backgrounds unless\n  `CometChatOngoingCallService.launch()` holds a foreground service (`.abort()` on teardown).\n  **Flutter-only**; both calls are safe no-ops on iOS. The manifest permissions are not optional.\n- **Ringing a closed app** — **there is no first-party CometChat Flutter push package** (iOS has\n  one; Flutter does not), and **no symbol in this skill's catalog implements it**. It is FCM on\n  Android and APNs\u002FPushKit\u002FCallKit on iOS, wired by the app. Needs a dashboard push provider and a\n  **physical device**. An emit naming a `cometchat_push_notifications` Flutter package invented it.\n\n## Doc corrections (⚠️ the live pages do not compile — full table: `references\u002Fdoc-corrections.md`)\n**23 classes of symbol** on `\u002Fcalls\u002Fflutter\u002F**` fail `flutter analyze` against 5.0.7. Read\n`references\u002Fdoc-corrections.md` before copying off a page. The two that bite hardest:\n\n| The docs write | It does not compile — use |\n|---|---|\n| `generateToken(sessionId: ...)` → `CallToken` (13 pages) | **`generateCallToken(sessionId, onSuccess:, onError:)`** → `CallToken`. `generateToken` is `@Deprecated`, takes two POSITIONAL args, and yields `GenerateToken`. **No page mentions `generateCallToken` at all** |\n| `Participant.pid` \u002F `.role` \u002F `.audioMuted` \u002F `.videoPaused` \u002F `.isPinned` \u002F `.isPresenting` \u002F `.raisedHandTimestamp` | **None exist.** `Participant` has 7 fields; track the rest from events |\n\nDocs PR cometchat\u002Fdocs#492 fixes the first seven classes (56 → 3 analyzer errors). **Five more —\nincluding the abstract-listener one — were found by running `flutter analyze` over this skill's\nown harness AFTER #492 was open, and are not in it.** 12 fences on those pages parse in no shape\nand were never machine-checked, so the table is a floor, not a total.\n\n## Common pitfalls (BAKED)\n- **Forgetting to mount the returned widget (the #1 Flutter mistake)** — `joinSession` renders nothing itself. Store the `Widget?` from `onSuccess` in State and return it from `build()`.\n- **Don't duplicate the built-in call controls (the #1 mistake everywhere else).** The joined widget renders a COMPLETE call UI — mute, camera, layout, participants, leave. Do NOT add your own buttons around it. The `CallSession.getInstance()` action methods are for CUSTOM controls ONLY — reach for them **just when the user EXPLICITLY asks** to replace the defaults, and hide the built-ins first via the `..hide*Button` setters on `SessionSettingsBuilder`. To merely REACT to the built-in leave button, use `ButtonClickListeners(onLeaveSessionButtonClicked:)` — do not add a second button.\n- **Removing a listener you did not keep** — construct once into a field; `remove*Listener` matches by instance.\n- **`User` is exported by BOTH barrels** — ringing imports both SDKs; `ambiguous_import` until one is imported with a prefix (`... as calls;`, then `calls.CallSession` etc.). No page says so.\n- **Ringing teardown needs BOTH SDKs** — `leaveSession()` ends your media, `CometChat.endCall(sessionId)` tells the peer and completes the log. Only the first, and the peer still thinks the call is live.\n- **There is no `cancelCall`** — cancel your own outgoing call with `rejectCall(sessionId, CometChatCallStatus.cancelled)`.\n- **Manifest permissions without the runtime request** — on Android 6+ the manifest alone grants nothing; request camera\u002Fmic before joining or the call is black and silent.\n- **`minSdkVersion` left at Flutter's default** — the floor is **26** (docs say 24), in `android\u002Fapp\u002Fbuild.gradle.kts` on current Flutter, not `android\u002Fbuild.gradle`.\n- **iOS Simulator on Apple Silicon:** `CometChatWebRTC` excludes arm64, so the app builds x86_64 — fine on an iOS 18 simulator (Rosetta), **impossible on iOS 26+**. Device or iOS 18 sim; details in `references\u002Fplatform-notes.md`.\n- **`cometchat-settings.json` not in `flutter: assets:`** — `initFromSettings` fails with settings-file-not-found. It is a *quiet* error callback, not a crash. Registering the asset is the whole job; no Xcode step.\n- **Double init** — `init` after `initFromSettings` silently re-attributes telemetry to `\"manual\"`.\n- **Handling `onSessionLeft` but not `onSessionTimedOut`** — idle timeout (default **300s**, `0` disables) fires a DIFFERENT callback; miss it and the user sits on a dead call screen.\n- **Emitting an API Flutter lacks** — no presentation mode, no first-party push package. Say so rather than emitting code that cannot resolve. The two PiPs are also different calls: `enablePictureInPictureLayout()` is the in-app layout, `enterPipMode()` is Android system PiP.\n- **Screen share — the control methods DO ship (docs lag them).** `CallSession.getInstance()` has real `startScreenShare()`\u002F`stopScreenShare()`\u002F`toggleScreenShare()` + an `isScreenSharing` getter (barrel-reachable in 5.0.7; the method channel invokes a native `startScreenShare` and web routes to `getDisplayMedia`), and `hideScreenSharingButton` defaults to **`false`** so the built-in button is visible. **From 5.0.8, Android local share is opt-in:** without two manifest entries the plugin hides the share button (`references\u002Fplatform-notes.md` → Screen share on Android). So an emit calling `startScreenShare()` COMPILES and dispatches — never say local screen share is impossible or \"invented.\" The **`\u002Fcalls\u002Fflutter\u002Fscreen-sharing` DOC page still says \"receive-only\"** — it documents only the RECEIVE side (`onParticipantStartedScreenShare`, `participant.isPresenting`, viewing a web participant's share); the shipped local-share control API is undocumented there. Reflect the shipped methods, and note the page lags them.\n- **Joining before init+login resolve** — chain from the success callbacks.\n- **Assuming a signature** — event names, `SessionSettings` fields and action params are FETCHED from docs, never guessed.\n\n## Verify it works\n- **Tier-1 catalog:** every `cometchat_calls_sdk` symbol emitted appears in `flutter-calls-v5.json` (`node test-suite\u002Fscripts\u002Fverify-catalog.mjs --family flutter-calls-v5`).\n- **Tier-2 compile:** the emit analyzes clean against the installed `cometchat_calls_sdk` (5.0.7) with `flutter analyze` in `test-suite\u002Fharness\u002Fflutter-calls`.\n- **Tier-3 smoke:** the round-trip (init→login→generateCallToken→join→**widget-mounted**→leaveSession) via the pack's dev calls-smoke harness (internal QA, not shipped) — **certified on a physical Android device**. **Ringing runs as TWO concurrent devices**, one process per role, and only counts if both succeed on the SAME session id — see `references\u002Fdocs-map.md` § \"1:1 RINGING\".\n","> **Ground truth:** `cometchat_calls_sdk` **5.0.7 from pub.dev** + catalog `flutter-calls-v5.json` (the closed symbol list — 59 COMPILER-VERIFIED symbols; every type below is in it). Catalog built from the PUBLISHED package; at 5.0.7 it matches the `calls-core` monorepo exactly — but **never infer that from a version string** (`references\u002Fdocs-map.md` § \"Upstream\"). Official docs: `\u002Fcalls\u002Fflutter\u002F**` = **v5** · Docs MCP. Fetch exact `SessionSettings` fields, event names and signatures from the docs (`references\u002Fdocs-map.md`) — never memory. **⚠️ The live pages carry ~56 symbols that DO NOT COMPILE, including the entire documented token flow — see \"Doc corrections\" below; prefer THIS skill's names over the page's.** **APPEND to the user's app — additive wiring only.** This is the HEADLESS path (no UI Kit); for the prebuilt drop-in call UI use `cometchat-flutter-v6-calls` instead.\n\n## Companion skills (read first)\n- **Standalone\u002Fheadless entry** — this skill owns its own package (the Calls SDK) and has no `-core` sibling; self-contained for meet-style calling.\n- **For 1:1 RINGING only** it also drives the **Chat SDK** (`cometchat_sdk` v5) for signaling — signatures fetched via `references\u002Fdocs-map.md` (§ \"1:1 RINGING\"). It does NOT depend on the Flutter UI Kit.\n- **Prefer the UI Kit instead?** If the app also wants chat and a prebuilt call UI, use `cometchat-flutter-v6-core` + `cometchat-flutter-v6-calls` — not this skill.\n\n## Use this skill when\n\"add calling from scratch \u002F without the UI Kit\", \"standalone voice\u002Fvideo on Flutter\", \"build my own call screen\", \"headless calls SDK\", \"meeting-room join by session id\", \"one-on-one ringing\". Precondition: the caller chose the **from-scratch \u002F standalone** path (the \"add calling\" router asks this). If they want the prebuilt call UI, route to `cometchat-flutter-v6-calls`.\n\n## Prerequisites & install\n```yaml\n# pubspec.yaml\ndependencies:\n  cometchat_calls_sdk: ^5.0.9   # latest; API compiler-verified vs 5.0.7, unchanged through 5.0.9\n```\nthen `flutter pub get`.\n\n**1:1 ringing additionally needs the Chat SDK** (`cometchat_sdk` v5) for signaling.\n\n**Permissions — REQUIRED or the call dies on the first permission prompt.**\n- `android\u002Fapp\u002Fsrc\u002Fmain\u002FAndroidManifest.xml`: `INTERNET`, `CAMERA`, `RECORD_AUDIO`, `MODIFY_AUDIO_SETTINGS`, `ACCESS_NETWORK_STATE`. On **API 23+ you must ALSO request camera + mic at runtime** — the manifest alone is not enough, and this is the single most common \"the SDK is broken\" report on Android.\n- `ios\u002FRunner\u002FInfo.plist`: `NSCameraUsageDescription` + `NSMicrophoneUsageDescription`.\n- Android **`minSdkVersion 26`**, iOS **`platform :ios, '15.1'`** — the real floors (5.0.7 through 5.0.9). **The docs say 24 and iOS 12; both fail at BUILD time.** iOS moved 13.0 → 15.1 *in 5.0.7*, so an app can break on a routine `pub upgrade`.\n\n**Credentials:** App ID · Region · Auth Key (dev only), fetched through the CometChat MCP — `cometchat_whoami` (connected + signed in?), `cometchat_list_apps` (ask which EXISTING app), `cometchat_get_app_credentials`, or pasted from Dashboard → Credentials. Mint **auth tokens server-side** for production; never ship the Auth Key.\n\n## Init & login ordering (BAKED — invariant)\nInit (once, must succeed) → `CometChatCalls.login(...)` → then `generateCallToken` \u002F `joinSession` \u002F listeners. Nothing joins before init+login resolve. `CometChatCalls.isInitialized` is the guard.\n\n- **DEFAULT to `CometChatCalls.initFromSettings(onSuccess:, onError:)`** — the ai-agent \u002F telemetry-attributed path (persists `integrationSource=\"ai-agent\"`).\n\n  \u003C!-- STOPGAP: source-derived (calls-core\u002Fcalls-sdk-flutter), NOT in the public docs.\n       `initFromSettings` is `@nodoc` and ai-agent-only. DOCS-BACKLOG F4\u002FD4 closed it WONTFIX —\n       it is to STAY hidden, so this stopgap is permanent, not pending a docs fix. -->\n  It takes **no settings argument**: it reads `cometchat-settings.json` through **`rootBundle`**, so the file must sit at the **project root** *and* be registered as a Flutter asset:\n  ```yaml\n  flutter:\n    assets:\n      - cometchat-settings.json\n  ```\n  Root keys `appId` + `region`; optional `callsSDK` → `adminHost`\u002F`clientHost`\u002F`callsHost`. **No Auth Key — the Calls SDK reads nothing else from this file** (the key is a `login()` argument). Registering it under `flutter: assets:` is the ONLY step; no Xcode or Gradle change, because it is read through `rootBundle`. Miss the `assets:` entry and init fails with settings-file-not-found — a quiet callback, not a crash.\n\n- **Fallback (public-doc path):**\n  ```dart\n  CallAppSettings s = (CallAppSettingBuilder()..appId = appId..region = region).build();\n  CometChatCalls.init(s, onSuccess: (String m) {}, onError: (CometChatCallsException e) {});\n  ```\n  Note the **Dart cascade** (`..appId =`) — these are **fields, not `setX()` methods**. `CallAppSettingBuilder` is singular (no `s`).\n- ⚠️ **Never do both.** A builder init AFTER `initFromSettings` re-attributes the app to `\"manual\"` and the ai-agent telemetry is lost.\n- **Login:** `CometChatCalls.login(uid:, authKey:, onSuccess:, onError:)` (dev) or `CometChatCalls.loginWithAuthToken(authToken:, onSuccess:, onError:)` (production). Check `await CometChatCalls.getLoggedInUser()` first — it returns `Future\u003CUser?>` and the SDK keeps the session, so logging in twice is wasted work. **Both `onSuccess` callbacks hand you a NULLABLE `User?`** — the docs dereference it unguarded; do not copy that.\n\n## Two build modes (BAKED — the router picks one)\n- **Meet-style (session room)** — Calls SDK ONLY, no Chat SDK. Everyone joining the same session id lands in the same call.\n- **1:1 ringing** — Chat SDK signals, Calls SDK carries media. Needs `cometchat_sdk` v5 as well. Fetch signatures via `references\u002Fdocs-map.md` § \"1:1 RINGING\".\n\n## ⚠️ The Flutter fork: `joinSession` returns a WIDGET\nEvery other platform mounts the call into a container you hand it. **Flutter hands the call back to\nyou as a `Widget?`** and mounts nothing:\n```dart\nWidget? _callWidget;\n\nCometChatCalls.joinSession(\n  sessionId: sessionId,\n  sessionSettings: settings,\n  onSuccess: (Widget? w) => setState(() => _callWidget = w),   \u002F\u002F ← THIS is the render step\n  onError: (CometChatCallsException e) { \u002F* surface it *\u002F },\n);\n\n@override\nWidget build(BuildContext c) => Scaffold(body: _callWidget ?? const CircularProgressIndicator());\n```\nAn emit that ignores the `onSuccess` argument **joins the call successfully and shows nothing** — audio flows, no video, no controls. It reads as a broken SDK and it is the #1 Flutter-specific failure. There is no container parameter and no zero-bounds trap; there is only \"did you put the widget in the tree\".\n\n## SDK method map (BAKED closed list — from the catalog; signatures → FETCH from docs)\n- **Lifecycle:** `CometChatCalls.initFromSettings` · `CometChatCalls.init` · `CallAppSettingBuilder` → `CallAppSettings` · `CometChatCalls.isInitialized` · `login` · `loginWithAuthToken` · `logout` · `getLoggedInUser` → `User?`\n- **Session:** `CometChatCalls.generateCallToken(sessionId, ...)` → `CallToken` · `joinSession(...)` → `Widget?` · `SessionSettingsBuilder` → `SessionSettings` · `SessionType`\n- **⚠️ TWO join paths, both real in 5.0.7** — pick one: `generateCallToken(sessionId)` → `joinSession(callToken:sessionSettings:)`, **or** `joinSession(sessionId:sessionSettings:)` directly.\n- **In-call actions — on `CallSession.getInstance()`, for CUSTOM controls ONLY** (the returned widget already renders them; see pitfall #1): `leaveSession` · `muteAudio`\u002F`unMuteAudio` · `pauseVideo`\u002F`resumeVideo` · `setLayout` · `setAudioModeType` · `switchCamera` · `raiseHand`\u002F`lowerHand` · `startRecording`\u002F`stopRecording` · `startScreenShare`\u002F`stopScreenShare`\u002F`toggleScreenShare` · `pinParticipant`\u002F`unPinParticipant` · `muteParticipant` · `pauseParticipantVideo` · `enablePictureInPictureLayout`\u002F`disablePictureInPictureLayout` · `enterPipMode`\u002F`isPipSupported` · `setChatButtonUnreadCount` · `isCallSessionActive`\n  - **Toggles** (Flutter-only, no iOS analogue): `toggleMuteAudio` · `togglePauseVideo` · `toggleCameraSource` · `toggleRaiseHand`\n  - **Aliases** for the same actions: `endCallSession` · `startCallRecording`\u002F`stopCallRecording` · `setCallLayoutType`\n  - **Settings panels:** `hideSettingsPanel` · `openCallSettingsPanel` · `openVirtualBackgroundSettingsPanel`\n  - **State getters (read, don't track):** `isAudioMuted` · `isVideoPaused` · `isHandRaised` · `isRecording` · `isScreenSharing` · `isTranscribing`\n- **Listeners (on `CallSession.getInstance()`; four are add\u002Fremove, `LayoutListeners` is a single-slot property):** `SessionStatusListeners` · `ParticipantEventListeners` · `MediaEventListeners` · `ButtonClickListeners` · `LayoutListeners`\n- **Call logs:** `CallLogRequestBuilder` (top-level; **FIELDS, no `setX()`**) → `CallLogRequest` → `fetchNext`\u002F`fetchPrevious` → `CallLog` (+ `CallUser`\u002F`CallGroup`\u002F`CallEntity`)\n- **Background:** `CometChatOngoingCallService.launch()` \u002F `.abort()` — Android foreground service, no-op on iOS\n- **Enums:** `AudioMode` (`.speaker`\u002F`.earpiece`\u002F`.bluetooth`) · `SessionType` · `LayoutType` (`.tile`\u002F`.spotlight`\u002F`.sidebar`) · `CameraFacing`\n\n> A curated highlight, **NOT the full surface**. The authoritative closed list is the **catalog** (59 symbols, each proven by a `flutter analyze` probe). A symbol is real **iff it is in the catalog** — confirm there, then fetch its signature from the page in `references\u002Fdocs-map.md`.\n\n## Listener lifecycle (BAKED)\n**All five listener types are `abstract class`es you IMPLEMENT — they are NOT constructible.**\nThe live docs build every one of them with named callbacks\n(`SessionStatusListeners(onSessionJoined: () {...})`); an abstract class cannot be instantiated, so\nnone of those examples compile. `flutter analyze` reports `instantiate_abstract_class`.\n```dart\nclass _Status extends SessionStatusListeners {\n  @override void onSessionJoined() { \u002F* ... *\u002F }\n  @override void onSessionTimedOut() { \u002F* distinct from onSessionLeft — handle BOTH *\u002F }\n  \u002F\u002F `extends` instead of `implements` and the other four inherit their no-op bodies.\n}\n\nfinal _status = _Status();                                       \u002F\u002F hoist into a FIELD\nCallSession.getInstance()?.addSessionStatusListener(_status);     \u002F\u002F BEFORE joining\n\u002F\u002F teardown:\nCallSession.getInstance()?.removeSessionStatusListener(_status);  \u002F\u002F the SAME instance\nCallSession.getInstance()?.leaveSession();\n```\n- Every method already has a no-op body, so **`extends` lets you override only what you need**; `implements` obliges you to write them all.\n- **`remove*Listener` takes the object you added.** Constructing a fresh listener to remove one is a no-op that silently leaks the original — and it is what the live docs show (D4). Hoist into a field; there is no other shape in which removal works.\n- **⚠️ Registration names do NOT match the type names** — full table in `references\u002Fdocs-map.md`. Two you cannot guess: `MediaEvent**Listeners**` registers via `addMediaEvent**s**Listener`, and **`LayoutListeners` has no add\u002Fremove at all** — it is a single-slot `layoutListener = l` setter, cleared with `= null`.\n- **`CallSession.getInstance()` is never actually null** — the singleton is eagerly built, so registering BEFORE `joinSession` really does attach (certified: `onSessionJoined` fires). The type is still `CallSession?`, so keep `?.`; use `isCallSessionActive()` to test for a live session.\n- **`ButtonClickListeners` callbacks fire alongside the SDK's own action and do NOT suppress it.** Reacting to `onLeaveSessionButtonClicked` must NOT also call `leaveSession()` — the SDK is already leaving; doing both double-leaves. Use it to run `CometChat.endCall(sessionId)` on the ringing path.\n- **`Participant` has TWELVE fields, all nullable:** `uid` · `name` · `avatar` · `mid` · `state` · `isJoined` · `deviceId` · `joinedAt` · `leftAt` · `totalAudioMinutes` · `totalVideoMinutes` · `totalDurationInMinutes`. **No mute\u002Fpin\u002Fhand\u002Fshare flags** — the seven the docs' \"Participant Object Reference\" lists (`pid`\u002F`role`\u002F`audioMuted`\u002F`videoPaused`\u002F`isPinned`\u002F`isPresenting`\u002F`raisedHandTimestamp`) do NOT exist and do not compile (see `doc-corrections.md`); accumulate that live state from `ParticipantEventListeners`, as iOS must. Prefer `onParticipantListChanged`, which delivers the WHOLE list. (`Participants`, plural, is a `@Deprecated` typedef alias of `Participant`.)\n\n## Least-code recipe (meet-style — ORDER, not signatures)\n```dart\n\u002F\u002F Fetch every signature\u002Ffield from references\u002Fdocs-map.md. This is the ORDER, which is the part that bites.\nimport 'package:cometchat_calls_sdk\u002Fcometchat_calls_sdk.dart';\n\n1. CometChatCalls.initFromSettings(onSuccess:, onError:)   \u002F\u002F ai-agent default; cometchat-settings.json as a Flutter ASSET\n2. CometChatCalls.login(uid:, authKey:, onSuccess:, onError:)   \u002F\u002F or loginWithAuthToken in production\n3. final settings = (SessionSettingsBuilder()..setDisplayName(name)..setType(SessionType.video)).build();\n4. CallSession.getInstance()?.addSessionStatusListener(_status);   \u002F\u002F register BEFORE joining\n5. CometChatCalls.joinSession(sessionId:, sessionSettings:, onSuccess: (Widget? w) => setState(() => _call = w), onError:)\n   \u002F\u002F   or: generateCallToken(sessionId) -> joinSession(callToken:sessionSettings:)\n6. \u002F\u002F return _call from build() — NOTHING renders until you do\n7. \u002F\u002F NO control buttons needed — the returned widget ALREADY renders mute\u002Fvideo\u002Fleave.\n8. \u002F\u002F teardown -> remove each listener (same instance); CallSession.getInstance()?.leaveSession()\n```\n\n## Backgrounding & call notifications → `references\u002Fplatform-notes.md`\nTwo things that are NOT on the join path and are easy to get wrong:\n- **Backgrounding** — Android kills a call the moment the app backgrounds unless\n  `CometChatOngoingCallService.launch()` holds a foreground service (`.abort()` on teardown).\n  **Flutter-only**; both calls are safe no-ops on iOS. The manifest permissions are not optional.\n- **Ringing a closed app** — **there is no first-party CometChat Flutter push package** (iOS has\n  one; Flutter does not), and **no symbol in this skill's catalog implements it**. It is FCM on\n  Android and APNs\u002FPushKit\u002FCallKit on iOS, wired by the app. Needs a dashboard push provider and a\n  **physical device**. An emit naming a `cometchat_push_notifications` Flutter package invented it.\n\n## Doc corrections (⚠️ the live pages do not compile — full table: `references\u002Fdoc-corrections.md`)\n**23 classes of symbol** on `\u002Fcalls\u002Fflutter\u002F**` fail `flutter analyze` against 5.0.7. Read\n`references\u002Fdoc-corrections.md` before copying off a page. The two that bite hardest:\n\n| The docs write | It does not compile — use |\n|---|---|\n| `generateToken(sessionId: ...)` → `CallToken` (13 pages) | **`generateCallToken(sessionId, onSuccess:, onError:)`** → `CallToken`. `generateToken` is `@Deprecated`, takes two POSITIONAL args, and yields `GenerateToken`. **No page mentions `generateCallToken` at all** |\n| `Participant.pid` \u002F `.role` \u002F `.audioMuted` \u002F `.videoPaused` \u002F `.isPinned` \u002F `.isPresenting` \u002F `.raisedHandTimestamp` | **None exist.** `Participant` has 7 fields; track the rest from events |\n\nDocs PR cometchat\u002Fdocs#492 fixes the first seven classes (56 → 3 analyzer errors). **Five more —\nincluding the abstract-listener one — were found by running `flutter analyze` over this skill's\nown harness AFTER #492 was open, and are not in it.** 12 fences on those pages parse in no shape\nand were never machine-checked, so the table is a floor, not a total.\n\n## Common pitfalls (BAKED)\n- **Forgetting to mount the returned widget (the #1 Flutter mistake)** — `joinSession` renders nothing itself. Store the `Widget?` from `onSuccess` in State and return it from `build()`.\n- **Don't duplicate the built-in call controls (the #1 mistake everywhere else).** The joined widget renders a COMPLETE call UI — mute, camera, layout, participants, leave. Do NOT add your own buttons around it. The `CallSession.getInstance()` action methods are for CUSTOM controls ONLY — reach for them **just when the user EXPLICITLY asks** to replace the defaults, and hide the built-ins first via the `..hide*Button` setters on `SessionSettingsBuilder`. To merely REACT to the built-in leave button, use `ButtonClickListeners(onLeaveSessionButtonClicked:)` — do not add a second button.\n- **Removing a listener you did not keep** — construct once into a field; `remove*Listener` matches by instance.\n- **`User` is exported by BOTH barrels** — ringing imports both SDKs; `ambiguous_import` until one is imported with a prefix (`... as calls;`, then `calls.CallSession` etc.). No page says so.\n- **Ringing teardown needs BOTH SDKs** — `leaveSession()` ends your media, `CometChat.endCall(sessionId)` tells the peer and completes the log. Only the first, and the peer still thinks the call is live.\n- **There is no `cancelCall`** — cancel your own outgoing call with `rejectCall(sessionId, CometChatCallStatus.cancelled)`.\n- **Manifest permissions without the runtime request** — on Android 6+ the manifest alone grants nothing; request camera\u002Fmic before joining or the call is black and silent.\n- **`minSdkVersion` left at Flutter's default** — the floor is **26** (docs say 24), in `android\u002Fapp\u002Fbuild.gradle.kts` on current Flutter, not `android\u002Fbuild.gradle`.\n- **iOS Simulator on Apple Silicon:** `CometChatWebRTC` excludes arm64, so the app builds x86_64 — fine on an iOS 18 simulator (Rosetta), **impossible on iOS 26+**. Device or iOS 18 sim; details in `references\u002Fplatform-notes.md`.\n- **`cometchat-settings.json` not in `flutter: assets:`** — `initFromSettings` fails with settings-file-not-found. It is a *quiet* error callback, not a crash. Registering the asset is the whole job; no Xcode step.\n- **Double init** — `init` after `initFromSettings` silently re-attributes telemetry to `\"manual\"`.\n- **Handling `onSessionLeft` but not `onSessionTimedOut`** — idle timeout (default **300s**, `0` disables) fires a DIFFERENT callback; miss it and the user sits on a dead call screen.\n- **Emitting an API Flutter lacks** — no presentation mode, no first-party push package. Say so rather than emitting code that cannot resolve. The two PiPs are also different calls: `enablePictureInPictureLayout()` is the in-app layout, `enterPipMode()` is Android system PiP.\n- **Screen share — the control methods DO ship (docs lag them).** `CallSession.getInstance()` has real `startScreenShare()`\u002F`stopScreenShare()`\u002F`toggleScreenShare()` + an `isScreenSharing` getter (barrel-reachable in 5.0.7; the method channel invokes a native `startScreenShare` and web routes to `getDisplayMedia`), and `hideScreenSharingButton` defaults to **`false`** so the built-in button is visible. **From 5.0.8, Android local share is opt-in:** without two manifest entries the plugin hides the share button (`references\u002Fplatform-notes.md` → Screen share on Android). So an emit calling `startScreenShare()` COMPILES and dispatches — never say local screen share is impossible or \"invented.\" The **`\u002Fcalls\u002Fflutter\u002Fscreen-sharing` DOC page still says \"receive-only\"** — it documents only the RECEIVE side (`onParticipantStartedScreenShare`, `participant.isPresenting`, viewing a web participant's share); the shipped local-share control API is undocumented there. Reflect the shipped methods, and note the page lags them.\n- **Joining before init+login resolve** — chain from the success callbacks.\n- **Assuming a signature** — event names, `SessionSettings` fields and action params are FETCHED from docs, never guessed.\n\n## Verify it works\n- **Tier-1 catalog:** every `cometchat_calls_sdk` symbol emitted appears in `flutter-calls-v5.json` (`node test-suite\u002Fscripts\u002Fverify-catalog.mjs --family flutter-calls-v5`).\n- **Tier-2 compile:** the emit analyzes clean against the installed `cometchat_calls_sdk` (5.0.7) with `flutter analyze` in `test-suite\u002Fharness\u002Fflutter-calls`.\n- **Tier-3 smoke:** the round-trip (init→login→generateCallToken→join→**widget-mounted**→leaveSession) via the pack's dev calls-smoke harness (internal QA, not shipped) — **certified on a physical Android device**. **Ringing runs as TWO concurrent devices**, one process per role, and only counts if both succeed on the SAME session id — see `references\u002Fdocs-map.md` § \"1:1 RINGING\".\n",{"name":5,"license":15,"metadata":51,"description":7,"compatibility":55},{"tags":52,"author":53,"version":54},"cometchat calls sdk v5 headless voice video webrtc dart flutter calling standalone","CometChat","1.0.0","Flutter >=2.5.0, Dart >=2.17.0 \u003C4.0.0 · Android minSdk 26 (Android 8.0) · iOS 15.1. cometchat_calls_sdk ^5.0.3 — resolves to 5.0.9 (latest); compiler-verified vs 5.0.7, and 5.0.8\u002F5.0.9 source-checked with no API removed. 1:1 ringing also needs cometchat_sdk v5 (>=5.0.6, latest 5.0.8 — the signaling symbols are identical across them) for signaling.","main","cebc3dce495d7eb80d3b1d5841f877a4a92e162d","plugins\u002Fcometchat\u002Fcometchat-skills\u002Fskills\u002Fcometchat-flutter-v5-sdk",491,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins","https:\u002F\u002Fhol.org\u002Fplugins\u002Fbest-codex-plugins","https:\u002F\u002Fgithub.com\u002Fhashgraph-online","https:\u002F\u002Fhol.org","Open-source standards and developer tools for interoperable AI agents: discovery, identity, communication, payments, privacy and security.","2026-11-14 14:06:13",{"source":8,"skillName":5,"commands":67,"prompt":77,"zipAvailable":78},[68,71,74],{"tool":69,"command":70},"npx","npx skills add hashgraph-online\u002Fawesome-codex-plugins --skill cometchat-flutter-v5-sdk",{"tool":72,"command":73},"bunx","bunx skills add hashgraph-online\u002Fawesome-codex-plugins --skill cometchat-flutter-v5-sdk",{"tool":75,"command":76},"pnpm","pnpm dlx skills add hashgraph-online\u002Fawesome-codex-plugins --skill cometchat-flutter-v5-sdk","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fcometchat\u002Fcometchat-skills\u002Fskills\u002Fcometchat-flutter-v5-sdk\u002FSKILL.md",true,[80,86,90,94],{"path":81,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":84,"sourceHtmlUrl":85},"references\u002Fdoc-corrections.md","REFERENCE","参考文档",8837,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fcometchat\u002Fcometchat-skills\u002Fskills\u002Fcometchat-flutter-v5-sdk\u002Freferences\u002Fdoc-corrections.md",{"path":87,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":88,"sourceHtmlUrl":89},"references\u002Fdocs-map.md",17524,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fcometchat\u002Fcometchat-skills\u002Fskills\u002Fcometchat-flutter-v5-sdk\u002Freferences\u002Fdocs-map.md",{"path":91,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":92,"sourceHtmlUrl":93},"references\u002Fplatform-notes.md",4337,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fcometchat\u002Fcometchat-skills\u002Fskills\u002Fcometchat-flutter-v5-sdk\u002Freferences\u002Fplatform-notes.md",{"path":95,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":96,"sourceHtmlUrl":97},"references\u002Ftranscription.md",3700,"https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fcometchat\u002Fcometchat-skills\u002Fskills\u002Fcometchat-flutter-v5-sdk\u002Freferences\u002Ftranscription.md",[99,108,115,122,148,173],{"skillNo":100,"name":101,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":103,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":107},"01M746ZWACVKMZ1BJXJZHYJSSX","migrate-to-e2e","Moves an existing Playwright, Cypress, Selenium, Appium, Detox, Maestro, or TesterArmy suite to e2e one slice at a time, with the old suite running beside the new one until each ported test is proven. Keeps a MIGRATION.md progress file so any later session resumes where the last stopped. Optionally plants a defect to show both suites catch it. Use for \u002Fmigrate-to-e2e, \"migrate our tests to e2e\", \"port these Maestro flows\", \"move our TesterArmy tests\", or when a project has an e2e config and an older suite still running.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fmigrate-to-e2e\u002FSKILL.md",[],[],"2026-11-11 15:11:14",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":103,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":114,"publishedAt":107},"01M746ZPTAX1Q0FBKAB1CYND7E","e2e","Writes, runs, and debugs end-to-end tests for web and mobile apps with e2e, the agentic test runner, which mixes agent.act goals with exact locator assertions on a Playwright browser or an iOS or Android device. Also drives a project's running app live over the e2e MCP server to look at a screen, check a UI change, take a screenshot or record a video, and try a locator; and runs bug bashes, parallel e2e explore runs with each bug proven by a repro test. Use when a project depends on e2e or has an e2e.config.ts, when asked for end-to-end, browser, mobile, or agentic UI tests, to check a change in the running app, to QA or bug bash an app or branch, or when an e2e run fails.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fe2e\u002FSKILL.md",[],[],{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":103,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":107},"01M746ZJN784HVHMDP9MQGCSGG","create-verification-skill","Generate a project-local verify-\u003Capp> skill on top of e2e, so any coding agent can launch the app, check it is worth driving, exercise a feature the way a user does, keep evidence, and bug bash it. Writes the skill, a feature map with one explore charter per feature, and proves it once. Use for \u002Fcreate-verification-skill, \"make a verification skill for this repo\", or when a project has no scripted way to prove UI behavior.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftester-army\u002Fe2e\u002Fskills\u002Fcreate-verification-skill\u002FSKILL.md",[],[],{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":103,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":46},"01M716A6ETNB9B1SQ3GXZC75VR","deja-search","deja-vu memory — search the user's past AI coding sessions with the deja CLI. Holds what they already settled and never wrote into the repo (naming rules, banned or already-tried tools, required checks before merge, preferred values, who owns what). Use before your first edit in a task, before you call a change done or ready to merge, before you recommend a tool, library, design or reviewer, before re-debugging an error that may already be solved, when they say 'didn't we fix this before', 'what did we decide about X' or 'I already have that', and before telling them something on this machine does not exist.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fvshulcz\u002Fdeja-vu\u002Fskills\u002Fdeja-search\u002FSKILL.md",[],[129,130,131,132,133,134,135,136,137,138,139,140,38,141,142,143,144,145,146,147],"search","deja search","never","error","ready","memory","re","decide","fix","design","debugging","when","done","reviewer","io","change","cli","merge","past",{"skillNo":149,"name":150,"nameZh":6,"description":151,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":103,"licenseFileUrl":6,"sourceHtmlUrl":152,"categories":153,"keywords":154,"publishedAt":46},"01M716A3J2W5SENSE9VGMXB375","deja-reflect","End-of-session reflection and memory curation with deja-vu. Review what was decided, what commands broke and what repaired them, and record durable project rules or decisions with deja remember so the next session starts with them.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Fvshulcz\u002Fdeja-vu\u002Fskills\u002Fdeja-reflect\u002FSKILL.md",[],[155,156,157,143,158,159,160,161,162,163,164,165,166,167,134,168,169,170,171,172],"deja reflect","reflect","review","with","record","github","next","https","node","Rules","decisions","brew","remember","project rules","project","session","end","reflection",{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":103,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":186,"publishedAt":46},"01M715T3RR4BAYSR57HPPTJ0PF","revid","Make, edit, export and post AI videos with Revid (revid.ai) through the Revid MCP server. Use whenever the user wants a short-form or long-form video made (from an idea, a script, a URL, an article, a PDF, a tweet, a product page, their own clips, or a song), wants to find what is going viral on TikTok, YouTube, Instagram or X before making something, wants to edit or re-export an existing Revid project, generate a standalone AI image or clip, make a series episode, or publish and schedule a finished video to connected social accounts. Covers setup (hosted MCP with OAuth, or an API key), the 36 tools, credits, polling and the rules for publishing. Routes to the more specific revid-* skills when one fits.","https:\u002F\u002Fgithub.com\u002Fhashgraph-online\u002Fawesome-codex-plugins\u002Fblob\u002Fmain\u002Fplugins\u002Ftmakersas\u002Frevid-skills\u002Fskills\u002Frevid\u002FSKILL.md",[179,180,183],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":181,"categoryName":182,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":184,"categoryName":185,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",[175,187,45,188,189,190,191,169,192,135,193,194,195,196,140,197,198,199,200,201],"URL","short-form","standalone","PDF","viral","tiktok","short","social","MCP","song","image","mcp server","schedule","api","publish"]