RepoPilotOpen in app →

ts1/BLEUnlock

Lock/unlock your Mac with your iPhone, Apple Watch, or any other Bluetooth LE devices

Concerns

Stale and unlicensed — last commit 2y ago

worst of 4 axes
Use as dependencyConcerns

no license — legally unclear; last commit was 2y ago…

Fork & modifyConcerns

no license — can't legally use code

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isConcerns

no license — can't legally use code; last commit was 2y ago

  • 6 active contributors
  • CI configured
  • Tests present
Show 3 more →
  • Stale — last commit 2y ago
  • Single-maintainer risk — top contributor 92% of recent commits
  • No license — legally unclear to depend on
What would change the summary?
  • Use as dependency ConcernsMixed if: publish a permissive license (MIT, Apache-2.0, etc.)
  • Fork & modify ConcernsMixed if: add a LICENSE file
  • Deploy as-is ConcernsMixed if: add a LICENSE file

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Great to learn from" badge

Paste into your README — live-updates from the latest cached analysis.

RepoPilot: Great to learn from
[![RepoPilot: Great to learn from](https://repopilot.app/api/badge/ts1/bleunlock?axis=learn)](https://repopilot.app/r/ts1/bleunlock)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/ts1/bleunlock on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: ts1/BLEUnlock

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ts1/BLEUnlock shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

AVOID — Stale and unlicensed — last commit 2y ago

  • 6 active contributors
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 2y ago
  • ⚠ Single-maintainer risk — top contributor 92% of recent commits
  • ⚠ No license — legally unclear to depend on

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live ts1/BLEUnlock repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/ts1/BLEUnlock.

What it runs against: a local clone of ts1/BLEUnlock — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in ts1/BLEUnlock | Confirms the artifact applies here, not a fork | | 2 | Default branch master exists | Catches branch renames | | 3 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 4 | Last commit ≤ 696 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ts1/BLEUnlock</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ts1/BLEUnlock. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/ts1/BLEUnlock.git
#   cd BLEUnlock
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of ts1/BLEUnlock and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ts1/BLEUnlock(\\.git)?\\b" \\
  && ok "origin remote is ts1/BLEUnlock" \\
  || miss "origin remote is not ts1/BLEUnlock (artifact may be from a fork)"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "BLEUnlock/BLE.swift" \\
  && ok "BLEUnlock/BLE.swift" \\
  || miss "missing critical file: BLEUnlock/BLE.swift"
test -f "BLEUnlock/AppDelegate.swift" \\
  && ok "BLEUnlock/AppDelegate.swift" \\
  || miss "missing critical file: BLEUnlock/AppDelegate.swift"
test -f "BLEUnlock/lowlevel.c" \\
  && ok "BLEUnlock/lowlevel.c" \\
  || miss "missing critical file: BLEUnlock/lowlevel.c"
test -f "BLEUnlock/LEDeviceInfo.swift" \\
  && ok "BLEUnlock/LEDeviceInfo.swift" \\
  || miss "missing critical file: BLEUnlock/LEDeviceInfo.swift"
test -f "BLEUnlock/Info.plist" \\
  && ok "BLEUnlock/Info.plist" \\
  || miss "missing critical file: BLEUnlock/Info.plist"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 696 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~666d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/ts1/BLEUnlock"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

BLEUnlock is a macOS menu bar utility that automatically locks and unlocks your Mac based on proximity to a Bluetooth Low Energy (BLE) device like an iPhone or Apple Watch. It monitors BLE signal strength and uses the Accessibility API to trigger Mac unlock, eliminating the need for password entry when your authorized device is near. Single Xcode project structure with main application in BLEUnlock/ directory. Core logic split into: BLE.swift (Bluetooth LE scanning and device management), AppDelegate.swift (menu bar integration), LEDeviceInfo.swift (device metadata), with Objective-C bridge (BLEUnlock-Bridging-Header.h) for private macOS frameworks like MediaRemote.h (for pause/resume music control).

👥Who it's for

macOS users who want seamless, proximity-based Mac security without entering passwords repeatedly. Specifically targets users with iPhones/Apple Watches who want automatic lock/unlock based on physical proximity, combined with power users who need custom lock/unlock scripts.

🌱Maturity & risk

Production-ready with active maintenance. The project has CI/CD via GitHub Actions (.github/workflows/test.yml), distributes via Homebrew Cask, and supports macOS 10.13+. However, it appears to be a single-maintainer project (ts1) with modest download volume, suggesting it's stable but niche rather than widely battle-tested.

Low risk for core functionality but single-maintainer risk is significant. The codebase is small (~58KB Swift) with no visible dependency management files (no Package.swift or Podfile in file list), meaning minimal third-party dependency risk. Primary risk: Accessibility API changes in new macOS versions could break unlock functionality; Bluetooth API changes could affect device detection.

Active areas of work

No recent commit data visible in file structure provided, but the presence of checkUpdate.swift indicates active update management. GitHub Actions workflow exists but specific recent changes cannot be determined from file listing alone. Project accepts translations (da.lproj/ for Danish suggests i18n work).

🚀Get running

git clone https://github.com/ts1/BLEUnlock.git
cd BLEUnlock
open BLEUnlock.xcodeproj
# Build in Xcode or via command line:
xcodebuild -scheme BLEUnlock -configuration Release

Daily commands: Open BLEUnlock.xcodeproj in Xcode, select the BLEUnlock scheme, and press Cmd+R to run. Or build via xcodebuild -scheme BLEUnlock -configuration Release and run the resulting app from Build/Products/Release/BLEUnlock.app.

🗺️Map of the codebase

  • BLEUnlock/BLE.swift — Core BLE scanning and device management logic; handles all Bluetooth Low Energy operations and proximity detection
  • BLEUnlock/AppDelegate.swift — Application entry point and lifecycle management; coordinates menu bar UI, system integration, and lock/unlock triggers
  • BLEUnlock/lowlevel.c — C bridge to macOS system APIs for screen lock/unlock functionality via low-level system calls
  • BLEUnlock/LEDeviceInfo.swift — Data model for tracked BLE devices; persists device configurations and RSSI thresholds to Keychain
  • BLEUnlock/Info.plist — App manifest defining macOS deployment target, Bluetooth permissions, and required capabilities
  • BLEUnlock/BLEUnlock.entitlements — Security entitlements file granting privileged access to system lock/unlock and Bluetooth features

🛠️How to make changes

Add support for a new BLE device type

  1. Add the device's BLE MAC address pattern or UUID to the scanning filter in BLE.swift's CBCentralManagerDelegate methods (BLEUnlock/BLE.swift)
  2. If needed, map the device name to a human-readable identifier in appleDeviceNames.swift (BLEUnlock/appleDeviceNames.swift)
  3. Test RSSI-based proximity detection by adjusting the threshold constants in BLE.swift and LEDeviceInfo.swift (BLEUnlock/LEDeviceInfo.swift)

Add a new localization language

  1. Create a new language directory (e.g., fr.lproj) under BLEUnlock/ (BLEUnlock/Base.lproj/Localizable.strings)
  2. Copy Localizable.strings from Base.lproj and translate all key-value pairs (BLEUnlock/Base.lproj/Localizable.strings)
  3. Do the same for AboutBox.strings (BLEUnlock/Base.lproj/AboutBox.xib)
  4. Declare the new language in BLEUnlock.xcodeproj project settings (Localization) (BLEUnlock.xcodeproj/project.pbxproj)

Modify the lock/unlock trigger logic

  1. Review the state machine logic in BLE.swift's didDiscoverPeripheral and distance calculation methods (BLEUnlock/BLE.swift)
  2. Adjust RSSI thresholds and hysteresis in LEDeviceInfo.swift to change proximity sensitivity (BLEUnlock/LEDeviceInfo.swift)
  3. Call the lock/unlock functions from AppDelegate.swift, which delegates to lowlevel.c via the C bridge (BLEUnlock/AppDelegate.swift)
  4. Test system calls by modifying lockMac() and unlockMac() in lowlevel.c if custom system behavior is needed (BLEUnlock/lowlevel.c)

Add a new menu bar feature or preference

  1. Define the new UI element in Base.lproj/MainMenu.xib using Interface Builder (BLEUnlock/Base.lproj/MainMenu.xib)
  2. Add corresponding action handler or property in AppDelegate.swift (BLEUnlock/AppDelegate.swift)
  3. Persist any user preference to Keychain via LEDeviceInfo.swift's storage mechanism (BLEUnlock/LEDeviceInfo.swift)
  4. Add localized labels for the new feature in Localizable.strings (BLEUnlock/Base.lproj/Localizable.strings)

🔧Why these technologies

  • Swift + Objective-C — Primary language for macOS app development; Objective-C used for legacy launcher helper and C interop
  • Core Bluetooth (CBCentralManager) — macOS native framework for BLE scanning and device discovery; no external dependencies needed
  • C low-level APIs (via lowlevel.c) — Unlocking the Mac requires private macOS frameworks (IOKit, possibly EventSource); C bridge allows access without runtime dependency loading risks
  • macOS Keychain — Secure storage of device configurations and pairing history without embedding secrets in plist
  • Xcode & xcodeproj — Standard macOS development toolchain; native support for entitlements, code signing, and app export

⚖️Trade-offs already made

  • Use private macOS APIs for system unlock

    • Why: Public alternatives (e.g., AppleScript) are slower and less reliable; private APIs provide direct control
    • Consequence: App may break on macOS updates; requires code-signing and entitlements; not distributable via Mac App Store
  • RSSI-based proximity detection instead of iBeacon

    • Why: Works with any BLE device without requiring custom firmware or specific beacon implementation
    • Consequence: RSSI is noisy and distance estimates vary by environment; requires hysteresis and threshold tuning
  • Menu bar utility (background app) rather than login-item daemon

    • Why: Simpler privilege escalation and UI accessibility; launcher helper still available for auto-start
    • Consequence: Requires macOS Big Sur or later user permissions for Bluetooth access; cannot run headless
  • No iPhone companion app required

    • Why: Simpler deployment; iPhone itself is
    • Consequence: undefined

🪤Traps & gotchas

  1. Accessibility permissions are mandatory but silently fail if not granted—app will appear to do nothing on unlock attempts. 2) Private Apple frameworks (MediaRemote.h) may break with macOS updates. 3) BLE devices require static MAC addresses; moving MAC addresses (like some privacy modes) will prevent reliable detection. 4) Keychain access during locked screen requires explicit Keychain permission grant at runtime. 5) The bridging header approach (BLEUnlock-Bridging-Header.h) limits this to native Apple development; no Swift Package Manager support visible.

🏗️Architecture

💡Concepts to learn

  • Bluetooth Low Energy (BLE) / Bluetooth LE — This app's entire core function depends on BLE scanning and RSSI (signal strength) measurement to detect device proximity—understanding BLE advertisement packets and power consumption tradeoffs is essential
  • RSSI (Received Signal Strength Indicator) — BLEUnlock uses RSSI values to infer proximity (distance estimation) rather than true GPS; understanding RSSI noise, filtering, and threshold tuning is key to device detection reliability
  • macOS Accessibility API (AX) — Required to programmatically unlock the locked screen; uses private Apple frameworks and requires explicit user permission, making it a critical but fragile integration point
  • Keychain Services — App stores the user's login password securely in Keychain for unlocking; understanding Keychain access, permissions, and unlock-time availability is crucial for password-based unlock logic
  • Static MAC Address Requirement — BLEUnlock relies on consistent BLE MAC addresses to identify devices; understanding why randomized MAC addresses break proximity detection and design tradeoffs is essential for device selection
  • Menu Bar Application (NSStatusBar) — App integrates as a menu bar utility rather than a windowed app; understanding NSStatusBar lifecycle, image rendering, and event handling for macOS menu bar apps is needed for UI modifications
  • Swift-Objective-C Interoperability (Bridging Header) — App uses a bridging header to call private Objective-C frameworks (MediaRemote); understanding Swift-ObjC calling conventions and header configuration is needed for adding features that use private APIs
  • kadiks/BLEUnlock — Active fork/alternative implementation of BLE-based Mac unlock with potentially different architecture or features
  • swiftlang/swift — Swift language and standard library; critical for understanding macOS app development patterns used here
  • apple/swift-corelibs-foundation — Foundation framework source; relevant for Keychain, NSStatusBar, and other macOS framework internals
  • Homebrew/homebrew-cask — This repo is distributed via Homebrew Cask; understanding cask manifest structure helps with packaging and distribution
  • actions/checkout — Used in the GitHub Actions workflow; understanding CI/CD patterns for macOS app testing

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add integration tests for BLE.swift device detection and connection logic

The BLE.swift file handles the core functionality of detecting and connecting to Bluetooth LE devices, but there are no visible unit/integration tests in the repo (test.yml exists but likely contains minimal coverage). Adding tests would ensure device detection, connection state management, and proximity-based locking/unlocking work correctly across macOS versions and device types.

  • [ ] Create Tests/BLETests.swift with XCTest cases for BLE.swift
  • [ ] Add tests for CBCentralManagerDelegate callbacks (device discovery, connection state changes)
  • [ ] Add tests for proximity threshold logic that triggers lock/unlock
  • [ ] Update .github/workflows/test.yml to run XCTest suite during CI
  • [ ] Ensure tests cover both connected and disconnected device states

Refactor lowlevel.c/h into a separate reusable module with build documentation

The C code in lowlevel.c handles macOS-specific unlock operations via private APIs (MediaRemote.h). This is tightly coupled to the main app but lacks documentation on why these private APIs are needed and how to maintain them across macOS versions. Extracting this into a well-documented module would make it easier for contributors to understand and maintain.

  • [ ] Create a new BLEUnlock/SecurityLayer/ directory for lowlevel.c and lowlevel.h
  • [ ] Add detailed comments in lowlevel.h explaining each private API call and its macOS version compatibility
  • [ ] Create BLEUnlock/SecurityLayer/README.md documenting why private APIs are necessary and maintenance risks
  • [ ] Update BLEUnlock-Bridging-Header.h to reference the reorganized module
  • [ ] Update project.pbxproj build settings if needed for the new module structure

Add comprehensive documentation for multi-language support and contributor guidelines for translations

The repo already has 7 language localizations (Danish, German, Japanese, Norwegian, Swedish, Turkish, Simplified Chinese) but lacks contributor documentation explaining how to add or maintain translations. This creates friction for translation contributors and risks inconsistent translation quality.

  • [ ] Create CONTRIBUTING.md with a dedicated 'Translations' section
  • [ ] Document the .lproj folder structure and how Base.lproj/Localizable.strings maps to language variants
  • [ ] Create a TRANSLATION_GUIDE.md explaining how to submit new language additions (required files: AboutBox.strings + Localizable.strings)
  • [ ] Add a checklist in CONTRIBUTING.md for translation PRs (e.g., 'Verify both string files are translated, test in app UI')
  • [ ] Reference this guide in the README.md to encourage community translations

🌿Good first issues

  • Add unit tests for LEDeviceInfo.swift signal strength calculations and filtering logic—currently no tests visible in file list, and RSSI-based proximity detection is critical to reliability.
  • Expand appleDeviceNames.swift with missing Apple device identifiers (newer iPhone/Watch models)—the mapping is hardcoded and needs periodic updates; good documentation task.
  • Create comprehensive developer documentation for the private Accessibility API calls in AppDelegate.swift explaining unlock trigger sequence and failure modes—currently undocumented and a barrier to contributors.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 2eeb35d — Update README.md (ts1)
  • 28e96a9 — Update FUNDING.yml (ts1)
  • 9bce666 — Fix README (ts1)
  • c33a132 — Run intruded event if wake without unlock (ts1)
  • 33bbe3e — Use notary tool (ts1)
  • 463f46d — Update README.md (ts1)
  • a8edb92 — Merge pull request #83 from tokfrans03/patch-1 (ts1)
  • 006fd72 — Fixed all of the "google translate" errors (tokfrans03)
  • eda9acd — 1.12.1 (ts1)
  • d139f23 — Added to README on how to reset Bluetooth on Monterey (ts1)

🔒Security observations

  • High · Unsafe C Code in lowlevel.c — BLEUnlock/lowlevel.c and BLEUnlock/lowlevel.h. The presence of lowlevel.c without visibility into its implementation poses security risks. C code is prone to buffer overflows, memory corruption, and other low-level vulnerabilities. Given that this application deals with system-level lock/unlock functionality, vulnerabilities here could be exploited for privilege escalation. Fix: Conduct a thorough security audit of lowlevel.c. Use static analysis tools (e.g., clang-analyzer, cppcheck). Implement bounds checking, use safe string functions, and avoid manual memory management where possible. Consider fuzzing the C code with malicious inputs.
  • High · Private API Usage - MediaRemote — BLEUnlock/MediaRemote.h. The codebase includes MediaRemote.h which suggests use of private/undocumented Apple APIs. This violates Apple's App Store guidelines and may break between OS updates. It also indicates the app may bypass security checks intended by Apple. Fix: Replace private API usage with documented public APIs where available. If public APIs don't provide the needed functionality, request this as a feature from Apple or use documented alternatives.
  • High · Unverified Bluetooth Device Pairing — BLEUnlock/BLE.swift. The app unlocks the Mac based on BLE device proximity without apparent cryptographic verification. An attacker could spoof a BLE MAC address to unlock the Mac. The README notes reliance on 'static MAC address' which is insufficient for security as MAC addresses can be spoofed. Fix: Implement cryptographic authentication using BLE signed write/read operations or a proper challenge-response mechanism. Never rely solely on MAC address for authentication. Consider implementing mutual authentication between the BLE device and Mac.
  • High · Privilege Escalation via Script Execution — BLEUnlock/AppDelegate.swift (inferred). The feature to 'optionally runs your own script upon lock/unlock' could allow privilege escalation if the script execution context has excessive permissions or if user-supplied scripts aren't properly validated. Fix: Implement strict script validation and sandboxing. Run scripts with minimal necessary privileges. Log all script execution. Consider restricting script locations to specific directories and verifying code signatures.
  • Medium · Missing Input Validation on BLE Signals — BLEUnlock/BLE.swift. The application processes BLE signals based on proximity thresholds without apparent validation of signal strength (RSSI) authenticity. Attackers could send crafted BLE advertisements to manipulate the proximity detection. Fix: Implement signal strength validation with multiple readings to confirm proximity. Use rolling averages and statistical analysis to detect anomalous signal patterns. Consider implementing signal integrity checks.
  • Medium · Potential Entitlements Misconfiguration — BLEUnlock/BLEUnlock.entitlements and Launcher/Launcher.entitlements. The app uses entitlements files (BLEUnlock.entitlements, Launcher.entitlements) which grant special permissions. Without reviewing the content, there's a risk of over-privileged entitlements being granted. Fix: Audit entitlements files to ensure they follow the principle of least privilege. Only request necessary entitlements for the app's functionality. Remove any unused entitlements.
  • Medium · No Apparent Rate Limiting on Lock/Unlock Operations — BLEUnlock/BLE.swift, BLEUnlock/AppDelegate.swift. Without rate limiting, an attacker with a spoofed BLE device could rapidly trigger lock/unlock cycles, causing denial of service or masking malicious activity. Fix: Implement rate limiting on lock/unlock operations. Add cooldown periods between consecutive operations. Log and alert on suspicious patterns of lock/unlock activity.
  • Medium · Dependency on External Update Mechanism — BLEUnlock/checkUpdate.swift. The file checkUpdate.swift suggests a custom update mechanism outside the Mac App Store. This could be vulnerable to man-in-the-middle attacks if updates are fetched over unencrypted connections or without signature verification. Fix: Ensure updates are fetched over HTTPS with certificate pinning. Verify update signatures

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Concerning signals · ts1/BLEUnlock — RepoPilot