
background-execution
Writes and reviews Swift code for background execution on Apple platforms - BGTaskScheduler (app refresh, processing, continued processing), beginBackgroundTask assertions, background URLSession downloads/uploads, silent and VoIP push, background modes (audio, location, BLE), the SwiftUI .backgroundTask modifier, and macOS schedulers. Use when scheduling deferred work, finishing work after the app backgrounds, transferring files in the background, waking the app via push, or debugging background tasks that never run.
- Installs
- 247
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/n0an/background-execution-agent-skill --skill background-execution- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads background-execution automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Write and review Swift code that runs work while the app is backgrounded or suspended, choosing the right API for the job and respecting the system's constraints so the work actually runs and the app is not terminated.
Review process:
- Establish the background execution model (lifecycle, budgets, force-quit, the five principles) using
references/fundamentals.md. - Confirm the chosen API matches the work using the decision tree below; reroute if it does not.
- Validate
BGTaskSchedulerusage (registration timing, Info.plist, expiration,setTaskCompleted) usingreferences/bg-task-scheduler.md. - Validate task assertions (
beginBackgroundTask/endBackgroundTask,performExpiringActivity) usingreferences/task-assertions.md. - Validate background
URLSessionconfig and the relaunch flow usingreferences/background-url-session.md. - Validate silent/VoIP push payloads, headers, and handlers using
references/background-push.md. - Validate
UIBackgroundModesdeclarations and location specifics usingreferences/background-modes.md. - Validate background audio (session category, recording while locked, interruptions, route changes, mic permission) using
references/background-audio.md. - Validate SwiftUI
ScenePhase/.backgroundTaskusage usingreferences/swiftui-background-tasks.md. - Validate macOS schedulers (
NSBackgroundActivityScheduler,beginActivity,SMAppService) usingreferences/macos-background.md. - Check testing/debugging and constraint handling using
references/testing-and-debugging.md. - Catch common mistakes using
references/anti-patterns.md.
If doing partial work, load only the relevant reference files.
Task-based routing
Match the user's goal to the read order. Load only what you need.
"Refresh my app's content in the background"
references/bg-task-scheduler.md-BGAppRefreshTask, register/submit/expirationreferences/testing-and-debugging.md- simulate the launch, handlebackgroundRefreshStatus
"Run long maintenance / ML / cleanup in the background"
references/bg-task-scheduler.md-BGProcessingTask, power/network requirementsreferences/testing-and-debugging.md- simulate launch and expiration
"Let a user-started export keep running after they leave (iOS 26)"
references/bg-task-scheduler.md-BGContinuedProcessingTask, progress, submission strategy, GPUreferences/fundamentals.md- the consent / user-initiated principle
"Finish an in-flight upload / save when the app backgrounds"
references/task-assertions.md-beginBackgroundTask/endBackgroundTask,performExpiringActivity
"Download or upload a large file that survives suspension"
references/background-url-session.md- background config, delegate, the relaunch flowreferences/testing-and-debugging.md- force-quit and constraint caveats
"Wake my app from the server"
references/background-push.md- silent push payload/headers/handler, or PushKit for callsreferences/background-modes.md- theremote-notificationmode
"Keep playing audio in the background"
references/background-audio.md- theaudiomode + active session, category/mode/options, interruptions, route changes
"Record / dictate / transcribe with the screen locked"
references/background-audio.md-.playAndRecord, recording while locked, mic permission, AVAudioEngine taps, the production gotchas
"Track location in the background"
references/background-modes.md- thelocationmode, significant-change and region monitoring
"Do this the SwiftUI way"
references/swiftui-background-tasks.md-ScenePhase,.backgroundTask(.appRefresh/.urlSession)references/bg-task-scheduler.md- you still schedule withBGTaskScheduler
"Background work on macOS"
references/macos-background.md-NSBackgroundActivityScheduler,beginActivity,SMAppService
"My background task never runs / how do I test it"
references/testing-and-debugging.md- lldb simulate commands, the states that gate executionreferences/anti-patterns.md- the usual causes
"I'm hitting bugs or App Review issues"
references/anti-patterns.md- catches with before/after fixes
Decision tree
Which background API should I use?
Does the work require user consent or input mid-flight?
-> Background runtime is wrong. Bring it to the foreground.
Is work already running and you just need to finish it as the app backgrounds?
-> beginBackgroundTask / endBackgroundTask (apps)
-> ProcessInfo.performExpiringActivity (app extensions, watchOS)
Is it a user-initiated long task that should continue with visible progress? (iOS/iPadOS 26)
-> BGContinuedProcessingTask
Is it a large/long file download or upload that must survive suspension/termination?
-> background URLSession
Does the server need to tell the app new content exists?
-> background (silent) push (apns-push-type: background, content-available: 1)
Is it an incoming call invitation?
-> PushKit + CallKit (report the call on every push)
Is it periodic content refresh before the user opens the app?
-> BGAppRefreshTask
Is it long, deferrable maintenance / ML / cleanup?
-> BGProcessingTask (optionally requiresExternalPower / requiresNetworkConnectivity)
Does the app need to keep playing audio or recording the mic (incl. while locked)?
-> audio UIBackgroundMode + active AVAudioSession (.playback or .playAndRecord) [background-audio.md]
Does the app need to keep running for location / BLE / VoIP?
-> declare the matching UIBackgroundModes capability [background-modes.md]
macOS, deferrable repeating maintenance?
-> NSBackgroundActivityScheduler
macOS, keep critical non-UI work from being napped?
-> ProcessInfo.beginActivity / performActivity
Which BGTask type?
Short content refresh, system picks the time around app usage?
-> BGAppRefreshTask (UIBackgroundModes: fetch)
Long maintenance, ideally on charger + network?
-> BGProcessingTask (UIBackgroundModes: processing; requiresExternalPower / requiresNetworkConnectivity)
User-tapped long work with progress UI, continues after backgrounding? (iOS 26)
-> BGContinuedProcessingTask (title/subtitle, progress, submission strategy, optional .gpu)
Long processing of health-research-study data? (iOS 17)
-> BGHealthResearchTask
Core Instructions
- Never treat background execution as guaranteed. It is opportunistic and discretionary; design every feature with a foreground reconciliation path and never put correctness-critical logic solely in a background task.
- Never register a
BGTaskSchedulerhandler lazily, in view code, or after launch finishes. Register all handlers inApp.init()/application(_:didFinishLaunchingWithOptions:), because the system may launch the app directly into the background. (BGContinuedProcessingTaskis the one exception - it registers dynamically on user intent.) - Never register the same task identifier twice - it crashes the app.
- Never omit the expiration handler on a
BGTask; without one the system silently marks the task complete-and-unsuccessful. Set it, have it cancel work fast, and callsetTaskCompleted(success:)exactly once. - Never forget to reschedule.
BGTaskSchedulerrequests are one-shot; submit the next request as the first line of the launch handler. - Put
requiresExternalPower/requiresNetworkConnectivityonly onBGProcessingTaskRequest, never on app-refresh. TreatearliestBeginDateas a floor, not a schedule. - Never leave a
beginBackgroundTaskunbalanced. CallendBackgroundTaskon both the success path and inside the expiration handler, idempotently (guard on.invalid); an unbalanced assertion kills the app. CallbeginBackgroundTaskbefore starting the work, not at the end of the background-transition delegate. - Never trust
backgroundTimeRemainingas a real budget - it isDBL_MAXin the foreground and advisory in the background. Plan for ~30 s and rely on the expiration handler. - Use
beginBackgroundTask(apps) orperformExpiringActivity(extensions, watchOS) only to finish work already running, never to start fresh long work or schedule future work. - Never use completion-handler convenience methods or
dataTaskon a backgroundURLSession; background sessions require a delegate. Create one session per identifier, store it, and recreate it at relaunch with the identical identifier and config. - Implement the full relaunch flow for background
URLSession: store the handler fromhandleEventsForBackgroundURLSession, recreate the session, and call the stored handler fromurlSessionDidFinishEvents(forBackgroundURLSession:)on the main thread. Move the file fromdidFinishDownloadingTo'slocationsynchronously inside the callback. - For background uploads, use file-backed
uploadTask(with:fromFile:)- data and stream uploads fail after the app exits. - Never send a silent push without
apns-push-type: background(andapns-priority: 5), and keep theapsdictionary tocontent-availableonly. Call the fetch completion handler within ~30 s. Treat silent push as throttled and coalesced, not reliable. - On iOS 13+, report an incoming call to CallKit on every VoIP push, or the system terminates the app and revokes VoIP-push privileges. Never use VoIP pushes for non-call data.
- Never set
allowsBackgroundLocationUpdates = truewithout thelocationbackground mode - it is a fatal error. Prefer significant-change / region monitoring over the continuouslocationmode. - Background audio needs both the
audiomode and an activeAVAudioSessionwith a background-capable category (.playbackfor playback,.playAndRecord/.recordfor recording-while-locked); the mode alone does nothing. Activate the session when audio begins (not at launch) and deactivate with.notifyOthersOnDeactivation. Always handleinterruptionNotification(check.shouldResumebefore resuming) androuteChangeNotification(pause on.oldDeviceUnavailable). - For mic capture, require permission with
AVAudioApplication.requestRecordPermission()(iOS 17+) and declareNSMicrophoneUsageDescription- without the key the app crashes, and without permission capture returns silent zeroed samples, not an error. InstallAVAudioEnginetaps off the main actor (the closure runs on a realtime thread) and matchAVAudioFilesettings to the input node's format. - Declare
UIBackgroundModessparingly; App Review rejects unjustified modes. Prefer the lighter alternative. - Account for the user: a force-quit suppresses
BGTaskScheduler, silent push, and backgroundURLSessionrelaunch until the next manual launch. ReadbackgroundRefreshStatus(degrade on.denied, stay silent on.restricted) and back off under Low Power Mode and elevated thermal state. - Do background-relevant setup (task registration, session recreation, dependency wiring) on a path that runs on every launch, not in
.onAppear/.task- a background launch may never build the UI. - With scenes enabled, use
sceneDidEnterBackground(_:)(not the deprecatedapplicationDidEnterBackground(_:)); it has ~5 s to return. - On macOS use
NSBackgroundActivitySchedulerfor deferrable maintenance andProcessInfo.beginActivity/endActivity(balanced, orperformActivity) to control App Nap;performExpiringActivitydoes not exist on macOS. - Test background tasks on a real device with the lldb
_simulateLaunchForTaskWithIdentifier:/_simulateExpirationForTaskWithIdentifier:commands - never ship a reference to them. Always test the expiration path.
Output Format
If the user asks for a review, organize findings by file. For each issue:
- State the file and relevant line(s).
- Name the anti-pattern being replaced.
- Show a brief before/after code fix.
Skip files with no issues. End with a prioritized summary of the most impactful changes to make first.
If the user asks you to write or fix background-execution code, make the changes directly instead of returning a findings report.
Example output:
SyncManager.swift
Line 22: BGTaskScheduler handler registered in .onAppear - never runs on a background launch.
// Before
.onAppear {
BGTaskScheduler.shared.register(forTaskWithIdentifier: id, using: nil) { ... }
}
// After - register in App.init() / didFinishLaunching
init() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: id, using: nil) { task in
self.handleRefresh(task: task as! BGAppRefreshTask)
}
}
Line 48: missing expiration handler and setTaskCompleted - the app is killed at expiry.
// Before
func handleRefresh(task: BGAppRefreshTask) { refresh() }
// After
func handleRefresh(task: BGAppRefreshTask) {
scheduleNext()
let op = RefreshOperation()
task.expirationHandler = { op.cancel() }
op.completionBlock = { task.setTaskCompleted(success: !op.isCancelled) }
queue.addOperation(op)
}
Summary
- Registration timing (high): move the handler to
App.init()or it never fires on background launch. - Completion contract (high): add the expiration handler and call
setTaskCompletedexactly once.
End of example.
References
references/fundamentals.md- the execution model: foreground/background/suspended, system budgets, force-quit, user toggles, the five principles, the lifecycle and scene states, the "which API" map.references/bg-task-scheduler.md-BackgroundTasks:BGAppRefreshTask,BGProcessingTask,BGContinuedProcessingTask(iOS 26),BGHealthResearchTask, registration, Info.plist keys, submit, expiration, errors.references/task-assertions.md-beginBackgroundTask/endBackgroundTask,backgroundTimeRemaining,ProcessInfo.performExpiringActivity, assertions vsBGTaskScheduler.references/background-url-session.md- backgroundURLSessionconfig, mandatory delegate, the relaunch /handleEventsForBackgroundURLSessionflow, knobs, resume data.references/background-push.md- silent/background push (payload, headers, handler, throttling), PushKit/VoIP + the CallKit requirement.references/background-modes.md- theUIBackgroundModesmatrix, background location, BLE/accessory/PTT, deprecated background fetch.references/background-audio.md- background playback and recording:AVAudioSessioncategories/modes/options, recording while locked, mic permission, interruptions, route changes,AVAudioEnginetaps and production gotchas.references/swiftui-background-tasks.md-ScenePhase, the.backgroundTaskscene modifier, async cancellation, scheduling vs handling.references/macos-background.md-NSBackgroundActivityScheduler,ProcessInfo.beginActivity/App Nap,SMAppService, cross-platform map.references/testing-and-debugging.md- lldb simulate-launch/expiration,backgroundRefreshStatus, Low Power Mode, thermal state, what gates execution.references/anti-patterns.md- common mistakes LLMs make when generating background-execution code.
FAQ
What does the background-execution skill do?
Writes and reviews Swift code for background execution on Apple platforms - BGTaskScheduler (app refresh, processing, continued processing), beginBackgroundTask assertions, background URLSession downloads/uploads, silent and VoIP push, background modes (audio, location, BLE), the SwiftUI .backgroundTask modifier, and macOS schedulers. Use when scheduling deferred work, finishing work after the app backgrounds, transferring files in the background, waking the app via push, or debugging background tasks that never run.
How do I install background-execution?
Run npx skills add https://github.com/n0an/background-execution-agent-skill --skill background-execution in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/background-execution/ (personal) or .claude/skills/background-execution/ (project).
Which AI agents can use background-execution?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is background-execution safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains background-execution?
It is published by n0an in n0an/background-execution-agent-skill. It has 247 recorded installs.
Popular mobile skills
design-mobile-apps
designed-by-ai/skills
Design mobile app screens with Sleek, edit Sleek projects, and implement their designs in React Native or HTML.
ios-design
uizze.sh
Design and review iOS UI/UX for iPhone apps in SwiftUI, UIKit, or React Native. Use for mobile app design, screen redesigns, navigation flows, typography, forms, keyboard and safe-area layout, and accessibility checks. Apply Apple Human Interface Guidelines and consult real product references through the optional Uizze connection.
vercel-react-native-skills
vercel-labs/agent-skills
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
animate-expo
emilkowalski/skills
Build animations in React Native and Expo, making the decisions in the order that determines whether they feel right — should it animate, which thread it runs on, which properties, spring or timing, how the gesture hands off, how it degrades. Writes the implementation with Reanimated, Gesture Handler, Expo Router and expo-haptics. Use when animating anything in an Expo app, adding gestures, sheets, screen transitions, press feedback or haptics, or fixing motion that stutters on device. For web animation use animate.
xcode-project-setup
firebase/agent-skills
Safely modifies Xcode projects (.pbxproj) to add Swift Packages and link files. Use this skill whenever an iOS project needs dependencies installed (e.g. Firebase, Alamofire).
firebase-remote-config-basics
firebase/agent-skills
Manages Firebase Remote Config templates, feature flags, loading strategies, and SDKs (Android, iOS). Use when downloading/deploying remoteconfig JSON templates, managing version history/feature flags, setting in-app defaults, fetchAndActivate(), real-time listeners, or SDK setup. Don't use for Firebase Hosting, Auth, Firestore, Data Connect, Crashlytics, or App Hosting.