iOS/APIExample-Audio/.agent/skills/review-case/SKILL.md
Structured code review for a case in the APIExample-Audio project. Checks engine lifecycle, audio-only constraints, thread safety, permissions, and API correctness. This project uses AgoraAudio_iOS — video APIs must not appear.
npx skillsauth add agoraio/api-examples review-caseInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Check:
enableVideo(), disableVideo(), setupLocalVideo(), setupRemoteVideo(), startPreview(), stopPreview()AgoraRtcVideoCanvas instantiationVideoView or video rendering views in storyboard or codeAny video API call in this project is a critical error — the SDK will crash or silently fail.
Check:
AgoraRtcEngineKit.sharedEngine(with:delegate:) called in viewDidLoad (not in Entry VC)leaveChannel() + AgoraRtcEngineKit.destroy() called in willMove(toParent:) when parent == nilCorrect:
override func willMove(toParent parent: UIViewController?) {
super.willMove(toParent: parent)
if parent == nil {
agoraKit?.leaveChannel()
AgoraRtcEngineKit.destroy()
}
}
All AgoraRtcEngineDelegate callbacks may arrive on a background thread.
Check:
DispatchQueue.main.async { }Check:
joinChannel()joinChannel() called only inside the permission grant callbackCheck:
joinChannel() checkedrtcEngine(_:didOccurError:) implemented and loggedCheck:
UIViewController, Main class inherits BaseViewController<ExampleName>Entry / <ExampleName>Main patternconfigs dictionary used to pass data from Entry to MainExamples/Basic/ or Examples/Advanced/ matching the MenuItem sectionCheck:
setAudioProfile(_:) called before joinChannel() if non-default profile neededsetAudioScenario(_:) called before joinChannel() if non-default scenario neededenableAudioVolumeIndication(_:smooth:reportVad:) called if volume callbacks are neededenableExternalAudioSink was calledCheck:
stopAudioMixing()) if startedstopRhythmPlayer()) if startedstopEchoTest()) if startedstopLastmileProbeTest()) if started[SEVERITY] file/line — issue description
Suggestion: how to fix
Severity levels:
[CRITICAL] — crash, leak, video API in audio-only project, or incorrect behavior[WARNING] — convention violation or subtle bug risk[INFO] — style or minor improvementAVAudioSession category should be .playAndRecord with .defaultToSpeaker option for most audio casesUIBackgroundModes includes audio in Info.plist if background playback is neededenable(inEarMonitoring:)) only works with wired headphones — document this limitation in the case if relevant[weak self] required in all closures capturing self to avoid retain cyclesdevelopment
Add a new API example or modify an existing one. Covers both creation and modification scenarios, including dialog class structure, message map registration, and ARCHITECTURE.md updates.
development
Code review for API examples. Ensures examples follow project conventions, handle lifecycle correctly, manage threads safely, and use APIs properly.
development
Add a new API example or modify an existing one. Covers both creation and modification scenarios, including file structure, registration, and ARCHITECTURE.md updates.
development
Code review for API examples. Ensures examples follow project conventions, handle lifecycle correctly, manage threads safely, and use APIs properly.