Back to Explorer
Beginner Friendly Open-Source Swift

Good First Issues in Swift

Explore curated starter issues in high-scoring Swift repositories. Every listed issue belongs to a welcoming repository scored by C-Rank™ on PR merge rates, review responsiveness, and first-timer acceptance.

Updated: Sun, 30 Aug 2026 UTC (Live GitHub Sync)
Real-Time Radar

Arm Issue Sniper for fresh Swift beginner issues

Beginner issues in welcoming S/A-Tier repositories get snatched within 15 minutes. Receive instant alerts on Discord, Telegram, or Email the minute a maintainer opens a new task.

Live Good First Issues (30)

Real-Time Open GitHub Issues
awaseem/foqos694 Tier S · 73 pts
#482Opened 7 days ago
Active Profile Time For Shortcuts

Would it be possible to use iPhone shortcuts to see how long a Profile session has already been active for?, and how long is left in the session? I’d really like a way to give myself pauses that are only allowed after a certain amount of time in the session has passed.

enhancementhelp wantedgood first issueNeeds QA
2
rational-kunal/NeoBrutalism133 Tier B · 59 pts
#62Opened 7 days ago
CI doesn't run on changes to Scripts/

.github/workflows/ci.yml filters on: paths: - "Sources/**" - "Tests/**" - "Example/**" - ".github/workflows/**" - "Package.swift" Scripts/ isn't listed, but it holds the snapshot contract: Scripts/snapshot-env.sh pins the reference simulator (iPhone 16 / iOS 26.2) and the CI Xcode, and carries the comment "Change ONLY via a PR that also re-records every image". Scripts/test.sh controls how the suite is invoked, including the deliberate -parallel-testing-enabled NO. A PR touching only Scripts/ skips CI entirely, so nothing enforces that rule at exactly the moment it matters most. Suggested fix Add - "Scripts/**" to both the push and pull_request path filters. Found while reviewing #47 (v3.0.0). Not blocking the release.

buggood first issue
rational-kunal/NeoBrutalism133 Tier B · 59 pts
#61Opened 7 days ago
Authoring note leaked into nbDialog's public documentation

Sources/NeoBrutalism/Components/Dialog.swift:17-21: /// Tapping the scrim dismisses the dialog; actions must call /// your binding manually (just like SwiftUI's `alert` does). To apply destructive /// styling to a button, pass `.buttonStyle(.neoBrutalism(type: .neutral))` with a /// red-tinted theme, or document the limitation for your consumers. "…or document the limitation for your consumers" is an instruction to whoever was writing the library, not guidance for someone using it. It ships to the hosted DocC page for nbDialog. Worth rewriting that sentence to just state the limitation: Button(role: .destructive) inside nbDialog doesn't get destructive styling, and here's what to do about it. Found while reviewing #47 (v3.0.0). Not blocking the release.

documentationgood first issue
rational-kunal/NeoBrutalism133 Tier B · 59 pts
#58Opened 7 days ago
NBMenu sizes its scroll cap from UIScreen.main

Sources/NeoBrutalism/Components/Menu/NBMenu.swift:193: let screenHeight = UIScreen.main.bounds.height let scrollCap = screenHeight * 0.6 UIScreen.main is not scene-aware — it reports the device screen, not the window the menu is actually in — so the 60% cap is wrong under iPad Split View / Slide Over, in a resized window, or on an external display. It's also deprecated. The value is already available: NBMenuOverlayContent.body wraps everything in a GeometryReader whose proxy.size is passed to placement(in:) a few lines above. Suggested fix Thread that same size into dropdown(elevated:) instead of reaching for UIScreen.main. Found while reviewing #47 (v3.0.0). Not blocking the release.

buggood first issue
1
rational-kunal/NeoBrutalism133 Tier B · 59 pts
#56Opened 7 days ago
NBGaugeStyle drops currentValueLabel, minimumValueLabel and maximumValueLabel

NBGaugeStyle.makeBody reads only configuration.value and configuration.label: public func makeBody(configuration: Configuration) -> some View { let value = configuration.value HStack(spacing: theme.spacing) { configuration.label NBBarMeter(fraction: value) … } } — Sources/NeoBrutalism/Components/Gauge/GaugeStyle.swift So a Gauge built with any of the value labels silently loses them: Gauge(value: temp, in: 0...100) { Text("Temp") } currentValueLabel: { Text("\(temp)°") // never rendered } minimumValueLabel: { Text("0") // never rendered } maximumValueLabel: { Text("100") // never rendered } Related: #3 asks for the same thing on NBProgressViewStyle, so the two could share a layout decision. NBGaugeStyle's static var neoBrutalism is also the only style entry point in the library without a doc comment — worth adding in the same pass. Found while reviewing #47 (v3.0.0). Not blocking the rele

enhancementgood first issue
1
rational-kunal/NeoBrutalism133 Tier B · 59 pts
#54Opened 7 days ago
NBSegmentBuilder can't build if/else or loops

NBSegmentBuilder only implements the variadic buildBlock: @resultBuilder public struct NBSegmentBuilder<Value: Hashable> { public static func buildBlock(_ components: NBSegmentItem<Value>...) -> [NBSegmentItem<Value>] { components } } — Sources/NeoBrutalism/Components/SegmentedPicker/NBSegmentedPicker.swift So neither of these compiles inside an NBSegmentedPicker: NBSegmentedPicker(selection: $size) { ForEach(sizes) { Text($0.name).nbSegment($0) } // ✗ if showExtras { Text("XL").nbSegment(3) } // ✗ } NBMenuBuilder and NBTabBuilder in the same release both implement buildExpression / buildArray / buildOptional / buildEither, so this is an inconsistency between three builders that otherwise look alike. Suggested fix Mirror NBTabBuilder — it's the closest analogue and can be copied nearly verbatim. Found while reviewing #47 (v3.0.0). Not blocking the release.

enhancementgood first issue
mlemgroup/mlem247 Tier S · 78 pts
#2942Opened 8 days ago
"Insert spoiler" button should add a new line

If the cursor is at the end of a non-empty line and you tap the "spoiler" button, it adds the spoiler tag on the current line, which is invalid. It should make a new line for it instead in this case.

easy
termio-sh/termio357 Tier B · 56 pts
#383Opened 9 days ago
iOS: EXC_GUARD kill from close() on file descriptor 0 when a terminal surface is torn down

The iOS companion is killed by the kernel when a terminal surface is torn down. Two TestFlight crash reports carry the full log, and both are the same: Exception Type: EXC_GUARD (SIGKILL) Exception Subtype: GUARD_TYPE_FD Exception Message: CLOSE on file descriptor 0 Termination Reason: GUARD 0x4000000100000000 Something calls close() on fd 0. iOS guards stdin/stdout/stderr, so the process is killed outright — no exception to catch, no chance to recover. That is why the Mac side sees every companion socket for the phone drop in the same millisecond. Stack The iPad report symbolicates cleanly and pins the path: -[UIView removeFromSuperview] → UITerminalView.didMoveToWindow() UITerminalView+Lifecycle.swift:70 → TerminalSurfaceCoordinator.freeSurface() :361 → TerminalSurfaceCoordinator.tearDownSurface(removingBridgeFrom:) :386 → TerminalSurface.free()

bughelp wanted
MattFaz/actuali118 Tier A · 62 pts
#318Opened 9 days ago
[Bug]: Unable to see Wallet transactions when importing

Received the below as an App Store TestFlight Bug Report. App Version / Build v1.0.9 Build 300 What happened? I am unable to see transactions from my Wallet when trying to import. I was able to set up the shortcut feature to add transactions, but I have not been able to get the import feature to work. Steps to Reproduce N/A Screenshots / Additional Context

bughelp wanted
2
termio-sh/termio357 Tier B · 56 pts
#371Opened 10 days ago
Toolbar buttons draw without their glass capsule on some Macs

On some Macs the toolbar buttons — the navigator toggle, the sort pull-down, +, and the inspector toggle — draw as bare glyphs with no capsule behind them. On other Macs the same buttons carry the Liquid Glass capsule. Same source, sometimes even the same machine running two builds side by side. Nobody has reproduced this on a machine we control, so this issue is a call for data rather than a diagnosis. If your toolbar buttons have no capsule, please post the output of the two commands below. Screenshots What we know The buttons are plain NSToolbarItems with isBordered = true (Sources/termio/App/App.swift, the .toggleNavigator / .sortProjects / .newTerminal / .toggleInspector cases). The capsule is drawn by AppKit, not by us — we never paint it, and there is no setting that turns it off. AppKit decides that chrome from two numbers: the macOS version the app runs on and the SDK version the binary was linked against. Our own code only branches at runtime (if #available(macOS 26,

bughelp wanted
tornikegomareli/Talkify490 Tier D · 29 pts
#84Opened 11 days ago
HUD does not appear while another app is in native full screen

macOS 26.5.1, MacBook Pro M2 Pro, built-in display with a physical notch Talkify 0.6.0 Right ⌘, held Dictated into Brave in native full screen Dictation works and the text is inserted, but the HUD never appears. Leave full screen and it shows normally from the notch on the same display. Possibly relevant: HUDPanel.swift:30 sets .fullScreenAuxiliary, which only admits a window to the full-screen Space of a full-screen window in the same app, and .canJoinAllSpaces does not cover another app's full-screen Space. Not verified. Diagnosis produced with Claude Code.

buggood first issue
1
mlemgroup/mlem247 Tier S · 78 pts
#2936Opened 13 days ago
Move image upload button to start of toolbar

This would remove the need to scroll to access it. I'm guessing this one is used quite frequently, and should get higher priority as a result It could go just after the undo/redo buttons, maybe with a divider following it

easy
chattymin/PokeTokenBar337 Tier A · 68 pts
#178Opened 14 days ago
The Kiro reader re-parses every conversation on every poll, and narrowing the window does not help

LocalAdditionalUsageReader.kiroEntries (Sources/PokeTokenBar/Core/LocalAdditionalUsageProvider.swift:800) re-reads and re-parses every stored Kiro conversation on every poll. Unlike the Cursor and Copilot readers, it has no watermark to advance — Kiro rewrites a conversation's whole history JSON in place on each turn and deletes turns outright on /clear, so there is no monotonic row id to resume from. That was the right call for #170; the cost of it is what this issue is about. Measured here on a synthetic database of 30 conversations x 80 turns (user 500 B, assistant 2 KB per turn), 6.3 MB on disk: rescan : 209–360 ms (2400 entries) empty window : 37 ms (0 entries, `modifiedSince` past every turn) The 37 ms floor is the point: modifiedSince is applied inside kiroTurnEntries (:860), after the row has been read out of SQLite and jsonObject has parsed it. Narrowing the window skips entry construction, not the read or the parse. In normal operation since is the s

enhancementhelp wanted
chattymin/PokeTokenBar337 Tier A · 68 pts
#177Opened 14 days ago
Extend additional scan folders to every provider, not just Claude

Every provider resolves its log location on its own, and only Claude can be pointed somewhere else from inside the app. #162 adds a settings field for extra Claude scan folders; this issue tracks extending that to the rest. Where each provider looks today Provider Location Override Claude computed multi-root CLAUDE_CONFIG_DIR + settings field (#162) OpenCode ~/.local/share/opencode OPENCODE_DATA_DIR Hermes ~/.hermes HERMES_HOME Copilot ~/.copilot COPILOT_HOME Grok ~/.grok/sessions GROK_HOME Codex ~/.codex/sessions none Gemini ~/.gemini/tmp none Antigravity ~/.gemini/antigravity-cli/conversations none Cursor ~/Library/Application Support/Cursor/User/globalStorage none Environment overrides are now read through the login shell (#176), so they work from a GUI-launched .app. What remains is that four providers have no override at all, and that an environment variable is an awkward thing to ask a menu bar app's user for. Why this is worth doing The failure mode is

enhancementhelp wanted
1
chattymin/PokeTokenBar337 Tier A · 68 pts
#175Opened 14 days ago
The update wait loop matches any instance by process name, so it always times out while a duplicate is running

UpdateChecker.applyUpdate() calls NSApp.terminate(nil) (UpdateChecker.swift:66), which ends the instance whose popover was used. The detached script then waits for the app to be gone (UpdateChecker.swift:123): for i in $(seq 1 40); do pgrep -x PokeTokenBar >/dev/null 2>&1 || break; sleep 0.5; done pgrep -x matches on process name, so it matches any instance. With one instance the loop breaks in well under a second, which is the case it was written for. With two, it can never break: the surviving instance keeps the name alive, so the wait always burns its full 20s and falls through. Two things then follow, both of which the wait was there to prevent (:116): brew upgrade --cask replaces the bundle underneath a still-running app — the bundle-replacement race the loop was added to avoid. launchctl kickstart -k (:130) starts a new instance. If the survivor is the launchd job's process, -k replaces it and the update comes up. If the survivor is the GUI-launched one — which is the case w

bughelp wanted
chattymin/PokeTokenBar337 Tier A · 68 pts
#174Opened 14 days ago
AppLog drops lines written on the way out of the process, so `clean shutdown` is usually lost

AppLog.write hands the line to a background queue (AppLog.swift:28) and returns. When the caller is on its way out of the process, the line races the teardown and is frequently lost. The site that matters today is CrashReporter.markClean() (CrashReporter.swift:65-68), which runs from the NSApplication.willTerminateNotification observer registered in install() (:45-47). AppKit posts that notification and then exits, so clean shutdown is written only if the log queue happens to get scheduled first. Measured with an AppKit app reproducing the sequence — enqueue on a serial DispatchQueue, then NSApp.terminate(nil): runs=100 landed=58 lost=42 Consistent with what is on disk here: the current 1.2M PokeTokenBar.log has 1 launch: line and 0 clean shutdown lines; the rotated 2.0M PokeTokenBar.old.log has 1 and 1. The consequence is not just a missing line. clean shutdown is the human-readable half of the shutdown record, so the log reads as if sessions end abruptly even when they don't. The

bughelp wantedgood first issue
chattymin/PokeTokenBar337 Tier A · 68 pts
#168Opened 15 days ago
Make the popover's outside-click monitor registration idempotent

What startOutsideClickMonitor() (Sources/PokeTokenBar/PokeTokenBarApp.swift:375) overwrites outsideClickMonitor without removing whatever token is already stored: private func startOutsideClickMonitor() { outsideClickMonitor = NSEvent.addGlobalMonitorForEvents(matching: [.leftMouseDown, .rightMouseDown]) { ... } } Start and stop are not symmetric either: registration happens at the call site (togglePopover(), PokeTokenBarApp.swift:360) while removal happens in the delegate callback (popoverDidClose, :368). Why it matters Nothing is broken today. togglePopover() is the only path that calls popover.show, and openPopover() (:336) guards on popover.isShown, so the monitor cannot be registered twice. The point is what happens when a second show path is added: the previous token is dropped on the floor, NSEvent.removeMonitor is never called for it, and a global mouse monitor stays installed for the rest of the process — outliving the popover it was meant to track. That failure is silen

enhancementgood first issue
1
chattymin/PokeTokenBar337 Tier A · 68 pts
#167Opened 15 days ago
Speech-bubble layout guard passes copy that the view truncates

What testLocalizedAlertBubbleFitsDefaultPanel (Tests/PokeTokenBarTests/PerformanceTests.swift:204) is the guard that keeps alert copy from being clipped in the floating pet's speech bubble — it exists because Japanese copy once clipped by ~9pt (#124). It measures with FloatingPetController.measureSpeechBubble (Sources/PokeTokenBar/UI/FloatingPetPanel.swift:112), which lays the text out with no height constraint (height: 10_000) and then asserts the result fits bubbleHeadroom (72pt, minus 2). The view it is guarding renders with .lineLimit(2) (FloatingPetPanel.swift:417). So the guard answers "does the bubble overflow the panel?" while the view's actual failure mode is "does the copy exceed two lines and get truncated?" Those are different thresholds, and the gap is one line wide. Evidence Reproducing measureSpeechBubble's math on a 164pt content column (bubbleMinWidth 180 − bubbleHorizontalPadding 8 × 2), title Límite inminente at 11pt bold, body at 10pt: body measured height

bughelp wanted
marvinli001/ClashMax56 Tier B · 63 pts
#32Opened 15 days ago
Add `/group/{name}/delay` to MihomoAPIClient / 为 MihomoAPIClient 增加 `/group/{name}/delay`

Background / 背景 Batch delay testing is currently issued one node at a time, while the core has a whole-group endpoint /group/{name}/delay. MihomoAPIClient does not implement it yet. See roadmap item A6 (ROADMAP.md, 中文). 目前批量测速是逐节点打的,而内核有整组接口 /group/{name}/delay,MihomoAPIClient 还没实现。见路线图 A6。 Scope of this issue is the API client method and its tests only. Switching the batch-testing flow over to it is not part of this issue — see "Why the rewiring is out of scope" below. 本 issue 的范围只有 API 客户端方法及其测试。 把批量测速流程切换过去不属于本 issue——原因见下面"为什么切换不在范围内"。 Verified API contract / 已实测的接口约定 Probed against the bundled core (Resources/Core/mihomo, v1.19.29) using a select group holding one reachable node (DIRECT) and two dead nodes: 针对随包内核实测(v1.19.29),用一个含 1 个可达节点(DIRECT)和 2

enhancementgood first issue
marvinli001/ClashMax56 Tier B · 63 pts
#31Opened 15 days ago
Add `/cache/fakeip/flush` to MihomoAPIClient / 为 MihomoAPIClient 增加 `/cache/fakeip/flush`

Background / 背景 A stale fake-ip mapping currently can only be cleared by restarting the core. Mihomo exposes /cache/fakeip/flush for exactly this, and MihomoAPIClient does not implement it yet. See roadmap item A3 (ROADMAP.md, 中文). 目前 fake-ip 映射脏了只能靠重启内核清除。Mihomo 本来就有 /cache/fakeip/flush 这个接口,而 MihomoAPIClient 还没实现。见路线图 A3。 Scope of this issue is the API client method and its tests only. Surfacing it as a diagnosis fix action (the rest of A3) is deliberately not part of this issue. 本 issue 的范围只有 API 客户端方法及其测试。 把它做成诊断里的修复动作(A3 的其余部分)刻意不包含在内。 This is the smallest of the three API-client issues — a good one to pick if it is your first change here. 这是三个 API 客户端 issue 里最小的一个,如果是你在本仓库的第一次改动,推荐从这个开始。 Verified API contract / 已实测的接口约定 Probed

enhancementgood first issue
marvinli001/ClashMax56 Tier B · 63 pts
#30Opened 15 days ago
Add `/dns/query` to MihomoAPIClient / 为 MihomoAPIClient 增加 `/dns/query`

Background / 背景 MihomoAPIClient covers most of the Mihomo RESTful API, but /dns/query is missing. Without it the app can show rules and the exit IP, but not what DNS actually returned — a hole in the middle of the routing story. See roadmap item A2 (ROADMAP.md, 中文). MihomoAPIClient 已经覆盖了 Mihomo RESTful API 的大部分,但缺 /dns/query。缺了它,应用能展示规则和出口 IP,却展示不了 DNS 实际返回了什么。见路线图 A2。 Scope of this issue is the API client method and its tests only. The DNS panel UI described in A2 is deliberately not part of this issue. 本 issue 的范围只有 API 客户端方法及其测试。 A2 里描述的 DNS 面板 UI 刻意不包含在内。 Verified API contract / 已实测的接口约定 Probed against the bundled core (Resources/Core/mihomo, v1.19.29), so these are real responses, not guesses: 针对随包内核实测(v1.19.29),以下是真实返回,不是猜的: GET /dns/query?name=example.com&t

enhancementgood first issue
awaseem/foqos694 Tier S · 73 pts
#465Opened 17 days ago
[feature] start a profile by long clicking the icon

Hi, I would love to be able to quick start a profile By long pressing the app icon. User story: As a user I wan to start a profile with as few clicks as possible and as fast as possible. I would expect a long press on the app icon to open a context menu which says "Start <profile_name>" Currently there is no context menu implemented:

enhancementhelp wantedgood first issue
1
mlemgroup/mlem247 Tier S · 78 pts
#2925Opened 17 days ago
`MessageView` should use same swipe action configuration as replies

At the moment, there's a single trailing "mark read" swipe action. It does not follow the inbox swipe configuration

easy
1
Tahul/space-rabbit401 Tier A · 66 pts
#46Opened 17 days ago
Convert Transition Speed adjective to Transition Time value

I can't discern a difference between 'fast' and 'instant', and all of them are too fast for my liking. If not a millisecond value selector, then maybe a 'medium' setting halfway between 'normal' and 'fast'? Thanks for making this.

bughelp wanted
3
#159Opened 18 days ago
[Bug]: Android SDK does not drops 3s location fixes and locks activity state after stationary period (iOS works as expected)

Required Reading Confirmed SDK Version 4.1.8 Mobile operating-system(s) iOS Android Device Manufacturer(s) and Model(s) Google Pixel-5, Google Pixel-7, Google Pixel-9, Samsung Device operating-systems(s) 12+ Build tooling versions Android Gradle Plugin Version : 9.2.1, Gradle Version: 9.6.1 What happened? Core Issues Summary Inconsistent 3–5 Second Location Delivery on Android: Our app logic relies on the SDK to emit a location update every 3 to 5 seconds so we can aggregate and persist a record every 10 seconds (~6 records per minute / 60 records per 10 minutes). On Android, the SDK skips intervals and drops location fixes, producing 15–30+ second gaps. Activity Recognition Freezes in Previous State on Android: When an Android device halts for longer than 3 minutes, the SDK enters the stationary state. Upon moving again (e.g., riding a bike at 30–40 km/h), the SDK continues emitting stationary/still as the active triggerActivity instead of transitioning. Conversely, when

help wanted
5
termio-sh/termio357 Tier B · 56 pts
#267Opened 18 days ago
Usage supports more agents

The problem Settings ▸ Usage only reads four agents: Claude Code, Codex, Kimi, and Grok. Every other agent termio can launch — cursor-agent, Amp, OpenCode, Antigravity, Hermes, Prime — shows nothing, even when its CLI is installed and logged in. What you'd want instead One UsageProvider per additional agent, so the Usage tab reads its plan limits and token totals the same way it reads the four it already supports. How Usage is wired Sources/termio/Companion/Usage/ is one file per agent. Each provider holds its own credential read, its own plan-limit endpoint, and its own session-log scanner; UsageMonitor knows only the list. Adding an agent is a new file plus one line — not an edit threaded through the fetch and scan paths. protocol UsageProvider: Sendable { var agent: AgentPreset { get } func planLimits(allowKeychain: Bool) async -> PlanLimitReading func tokenUsage(in windows: DateWindows) -> AgentTokenUsage } UsageProvider's protocol extension already gives you th

enhancementhelp wanted
minh-ton/reynard-browser1,525 Tier C · 36 pts
#309Opened 18 days ago
[Bug] Keyboard text input has poor performance, buggy, and unstable

Before continuing, please confirm the following I have read the FAQ and searched for my issue. Describe the bug It’s so difficult to type in Reynard browser without errors. For some reason, the 3 suggestions the keyboard offers just keeps flashing (so they usually can’t be selected) indicating as though it’s processing something using the CPU in the background. The cursor many times lags behind the input. Tapping to reposition cursor usually is difficult then when trying to go back to correct typos. It’s almost as though it’s using a different keyboard compared to other parts of iOS where you need to type. I’m not sure if it’s my old non-powerful iPhone 6S, or because it’s iOS 15, but I’ve not experienced this kinda typing issues on any app in all my years of using this phone. I’ve waited to see if someone else has been having similar issues, but it appears no one uses these older phones anymore. Scrolling and other performance issues have been getting better and

bughelp wanted
2
Tahul/space-rabbit401 Tier A · 66 pts
#41Opened 21 days ago
Instant app switch [cmd+tab] (between spaces) is underliable [MacOS 27 Version 27.0 Beta (26A5388g)]

Instant app switch [cmd+tab] (between spaces) is unreliable [MacOS 27 Version 27.0 Beta (26A5388g)] – sometimes it works instantly, sometimes I see the animation.

bughelp wanted
3
mlemgroup/mlem247 Tier S · 78 pts
#2904Opened 22 days ago
Favourites should sort communities beginning with a number at the top, not the bottom

It's inconsistent with the rest of the subscription list

easy

Top Swift Repositories with Beginner Issues (20)

Updated Daily via GitHub GraphQL
artembobkin
ImmersiveMap
artembobkin/ImmersiveMap
BSolid
80·Swift

Native Swift 6 + Metal map rendering engine for SwiftUI. Globe and flat vector-tile maps with labels, SwiftUI markers and avatars, on iOS and macOS.

#geospatial#globe#ios
97%
Merge Rate
<1h
Review Time
100%
1st-Timers
2 GFI
Scorecard
mlemgroup
mlem
mlemgroup/mlem
SElite
247·Swift

Mlem for Lemmy

#activitypub#ios#lemmy
99%
Merge Rate
10h
Review Time
100%
1st-Timers
13 GFI
Scorecard
Clash-FX
ClashFX
Clash-FX/ClashFX
BSolid
249·Swift

ClashFX — macOS proxy tool with Enhanced Mode (TUN)

#clash#macos#mihomo
96%
Merge Rate
4h
Review Time
100%
1st-Timers
1 GFI
Scorecard
iliyami
MacSai
iliyami/MacSai
SElite
1.5k·Swift

Mac Sai: the open-source Mac cleaner, optimizer, and malware scanner. A free, Apple-notarized alternative to CleanMyMac, built with Swift 6 and SwiftUI.

#appkit#cleanmymac#cleanmymac-alternative
88%
Merge Rate
7h
Review Time
100%
1st-Timers
4 GFI
Scorecard
swiftlang
swift-java
swiftlang/swift-java
SElite
1.2k·Swift

Java interopability support for Swift

92%
Merge Rate
7h
Review Time
93%
1st-Timers
2 GFI
Scorecard
awaseem
foqos
awaseem/foqos
SElite
694·Swift

Foqos allows you to lock apps behind the tap of a NFC tag or scan of a QR code. Free and open source alternative to Brick, Opal, ScreenZen, Unpluq, Scrolly, Blok and more!

#ios-app#productivity#swiftui
85%
Merge Rate
11h
Review Time
50%
1st-Timers
4 GFI
Scorecard
awslabs
swift-aws-lambda-runtime
awslabs/swift-aws-lambda-runtime
BSolid
1.2k·Swift

Swift implementation of AWS Lambda Runtime

92%
Merge Rate
5h
Review Time
100%
1st-Timers
1 GFI
Scorecard
BasedHardware
omi
BasedHardware/omi
SElite
13.2k·Swift

AI that sees your screen, listens to your conversations and tells you what to do

#ai#app#flutter
79%
Merge Rate
21h
Review Time
54%
1st-Timers
40 GFI
Scorecard
mozilla-mobile
firefox-ios
mozilla-mobile/firefox-ios
SElite
13.0k·Swift

Firefox for iOS

#browser#firefox#ios-app
85%
Merge Rate
3d
Review Time
77%
1st-Timers
15 GFI
Scorecard
swiftlang
swift
swiftlang/swift
SElite
70.3k·Swift

The Swift Programming Language

77%
Merge Rate
10h
Review Time
57%
1st-Timers
12 GFI
Scorecard
TypeWhisper
typewhisper-mac
TypeWhisper/typewhisper-mac
AWelcoming
1.7k·Swift

Local speech-to-text for macOS on-device AI, fully private, optional cloud

#apple-silicon#dictation#macos
93%
Merge Rate
3d
Review Time
60%
1st-Timers
1 GFI
Scorecard
PowerBeef
Vocello
PowerBeef/Vocello
BSolid
357·Swift

Vocello: a local, private voice studio for Apple Silicon. Write a script, pick or describe a voice, and generate speech on-device, faster than realtime on an 8 GB M2 Mac mini. Native Swift + MLX, no Python. Mac app out now, iPhone beta on TestFlight. (Formerly QwenVoice.)

#apple-silicon#macos#mlx
93%
Merge Rate
4d
Review Time
100%
1st-Timers
2 GFI
Scorecard
rayl15
OpenVision
rayl15/OpenVision
AWelcoming
121·Swift

Open-source iOS app connecting Meta Ray-Ban smart glasses to AI — 5 backends (on-device MLX models, Apple Intelligence, OpenAI, Gemini Live, OpenClaw), on-device neural voice, face recognition & live web search. Private and offline-capable.

#ai-assistant#apple-intelligence#face-recognition
95%
Merge Rate
6d
Review Time
100%
1st-Timers
5 GFI
Scorecard
chattymin
PokeTokenBar
chattymin/PokeTokenBar
AWelcoming
337·Swift

Use your tokens to raise, evolve, and collect Pokémon! 🥚

#ai-coding#claude-code#codex
77%
Merge Rate
10h
Review Time
67%
1st-Timers
2 GFI
Scorecard
PostHog
posthog-ios
PostHog/posthog-ios
AWelcoming
108·Swift

PostHog iOS SDK

#ios#posthog#sdk
86%
Merge Rate
2d
Review Time
79%
1st-Timers
1 GFI
Scorecard
Tahul
space-rabbit
Tahul/space-rabbit
AWelcoming
401·Swift

Space Rabbit removes animations when switching macOS Spaces. Reclaim hours of your time every month!

78%
Merge Rate
1h
Review Time
100%
1st-Timers
3 GFI
Scorecard
nikships
droidproxy
nikships/droidproxy
AWelcoming
120·Swift

A native macOS menu bar app that proxies Claude/Codex/Gemini subscriptions for use with Factory Droid CLI. Always updated with new model releases!

#anthropic#claude#droid
58%
Merge Rate
2d
Review Time
83%
1st-Timers
6 GFI
Scorecard
darrylmorley
whatcable
darrylmorley/whatcable
AWelcoming
8.5k·Swift

macOS menu bar app that tells you, in plain English, what each USB-C cable plugged into your Mac can actually do

#apple-silicon#hardware-info#iokit
80%
Merge Rate
1d
Review Time
56%
1st-Timers
1 GFI
Scorecard
apple
swift-metrics
apple/swift-metrics
BSolid
793·Swift

Metrics API for Swift

#metrics#swift-server
89%
Merge Rate
14h
Review Time
100%
1st-Timers
1 GFI
Scorecard
osaurus-ai
osaurus
osaurus-ai/osaurus
AWelcoming
7.7k·Swift

Own your AI. The native macOS harness for AI agents -- any model, persistent memory, autonomous execution, cryptographic identity. Built in Swift. Fully offline. Open source.

#anthropic#apple-foundation-models#apple-intelligence
83%
Merge Rate
3d
Review Time
53%
1st-Timers
1 GFI
Scorecard

How to make your first Swift open-source pull request

Finding approachable Good First Issues in Swift allows you to build real-world software engineering experience. Instead of submitting PRs to abandoned repositories, GetMerged verifies maintainer review speeds and first-timer acceptance rates before you write a single line of code.

Select any issue above to claim it directly on GitHub, or click a repository to inspect full maintainer review turnaround metrics and triage guidance!

Get this week's top welcoming repos + fresh Good First Issues for Swift

Free weekly email, scoped to Swift. No account needed - confirm once and unsubscribe anytime.