RepoPilotOpen in app →

samhenrigold/LidAngleSensor

tfw when you when your lid when uhh angle your lid sensor

Mixed

Single-maintainer risk — review before adopting

worst of 4 axes
Use as dependencyMixed

top contributor handles 96% of recent commits; no tests detected…

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 7w ago
  • 3 active contributors
  • Apache-2.0 licensed
Show 4 more →
  • Small team — 3 contributors active in recent commits
  • Single-maintainer risk — top contributor 96% of recent commits
  • No CI workflows detected
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: diversify commit ownership (top <90%); add a test suite

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 "Forkable" badge

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

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/samhenrigold/lidanglesensor?axis=fork)](https://repopilot.app/r/samhenrigold/lidanglesensor)

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/samhenrigold/lidanglesensor on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: samhenrigold/LidAngleSensor

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/samhenrigold/LidAngleSensor 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

WAIT — Single-maintainer risk — review before adopting

  • Last commit 7w ago
  • 3 active contributors
  • Apache-2.0 licensed
  • ⚠ Small team — 3 contributors active in recent commits
  • ⚠ Single-maintainer risk — top contributor 96% of recent commits
  • ⚠ No CI workflows detected
  • ⚠ No test directory detected

<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 samhenrigold/LidAngleSensor repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/samhenrigold/LidAngleSensor.

What it runs against: a local clone of samhenrigold/LidAngleSensor — 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 samhenrigold/LidAngleSensor | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | Last commit ≤ 78 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>samhenrigold/LidAngleSensor</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of samhenrigold/LidAngleSensor. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/samhenrigold/LidAngleSensor.git
#   cd LidAngleSensor
#
# 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 samhenrigold/LidAngleSensor and re-run."
  exit 2
fi

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

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

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

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 78 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~48d)"
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/samhenrigold/LidAngleSensor"
  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

LidAngleSensor is a macOS utility written in Swift that reads the lid angle sensor found in modern MacBook Pro models (2019 16-inch and newer, M4, etc.) and displays the angle in real-time via a menu bar app. It optionally plays a wooden door creaking sound (from LEGO Batman 3) that speeds up as the lid opens faster, turning hardware sensor data into an audio-visual experience. Single Xcode project (LidAngleSensor.xcodeproj) with a flat app structure: LidAngleSensor/ contains the main SwiftUI app (LidAngleSensorApp.swift → ContentView.swift → MenuBarView.swift), sensor logic in LidAngleSensor.swift, audio engines in AudioEngines/ (protocol-driven, with CreakAudioEngine.swift and ThereminAudioEngine.swift implementations), and UI components like ParameterSlider.swift and AudioController.swift.

👥Who it's for

macOS users with compatible MacBook Pro models who want to visualize/monitor their lid position, and developers curious about accessing the Human Interface Device (HID) layer to read undocumented laptop sensors. Primarily a novelty/educational tool rather than a productivity app.

🌱Maturity & risk

Experimental/hobby project. Single maintainer (samhenrigold), no visible CI/CD pipeline, no test suite in the file structure, and the README itself admits 'I'm bad at audio' and hardware compatibility is spotty (M1/M2 devices notably broken). It works on M4 hardware but is fragile and specific to the author's test machine.

High risk for personal use: hard-coded sensor lookup means it only works on specific MacBook models the author has tested; breaking changes are likely as Apple updates HID APIs or hardware. No automated tests or CI means regressions are undetected. Single maintainer with no contributions visible suggests low bus factor. Audio Engine code (CreakAudioEngine.swift, ThereminAudioEngine.swift) admits technical debt.

Active areas of work

No visible recent commits or PR activity in the provided data. The README indicates the author is now employed but 'still doing this for the love of the game.' Known open issues include M1/M2 incompatibility and device-specific sensor detection failures (see README reference to hard-coded sensor lookup and the gist-based workaround).

🚀Get running

Clone and open in Xcode: git clone https://github.com/samhenrigold/LidAngleSensor.git && cd LidAngleSensor && open LidAngleSensor.xcodeproj. Build with Xcode 26+ (as per README). For Homebrew install: brew install lidanglesensor.

Daily commands: Open LidAngleSensor.xcodeproj in Xcode, select the LidAngleSensor scheme, and press Cmd+R. The app will launch as a menu bar utility. Click 'Start Audio' in the menu to enable the creaking sound effect.

🗺️Map of the codebase

🛠️How to make changes

For sensor issues: edit LidAngleSensor.swift (main sensor reading logic) and HardwareCompat.swift (device compatibility). For audio: modify AudioEngines/CreakAudioEngine.swift (the CREAK_LOOP.wav playback) or AudioEngines/ThereminAudioEngine.swift. For UI: edit ContentView.swift (main display), MenuBarView.swift (menu bar appearance), or ParameterSlider.swift (control components). For new audio modes: implement AudioEngineProtocol.swift and add to AudioMode enum.

🪤Traps & gotchas

Hard-coded sensor detection in HardwareCompat.swift means the app only works on the exact MacBook model the author tested (M4 MacBook Pro). The app will silently fail to find the sensor on other machines. No error handling visible for missing sensors—the angle will simply not update. Audio code acknowledges 'weird' feeling (CreakAudioEngine.swift) due to author's self-admitted poor audio skills. M1/M2 devices do not work at all per the README; root cause is unknown and no fallback exists.

💡Concepts to learn

  • Human Interface Device (HID) — The lid angle sensor is exposed via the HID protocol; understanding HID is essential to reading the raw sensor data and debugging why certain MacBooks don't report it
  • Menu Bar App (macOS) — LidAngleSensor runs as a menu bar utility, not a traditional windowed app; understanding menu bar lifecycle and MenuBarView.swift is critical for app behavior
  • SwiftUI State Management — ContentView.swift and MenuBarView.swift use @State and @ObservedObject to bind sensor readings and audio state; understanding reactive binding is necessary to modify UI behavior
  • Protocol-Driven Audio Architecture — AudioEngineProtocol.swift defines a contract for audio playback; both CreakAudioEngine and ThereminAudioEngine conform to it, enabling easy switching between audio modes
  • AVFoundation Audio Playback — CreakAudioEngine.swift and ThereminAudioEngine.swift likely use AVFoundation to play audio; understanding AVAudioPlayer or AVAudioEngine is necessary to improve audio quality
  • IOKit Device Enumeration — HardwareCompat.swift uses IOKit to enumerate and find the lid angle sensor; understanding IOKit's device matching APIs is essential for making sensor detection more robust across hardware
  • tcsenpai/pybooklid — Python library that accesses the same MacBook lid angle sensor; useful reference for understanding the HID protocol and sensor data format
  • apple/swift-system — Low-level system APIs for Swift; may be useful for improving HID device enumeration and compatibility beyond hard-coded lookups
  • jongwonwoo/MacBookSensorCollector — Alternative macOS sensor reading project; demonstrates different approaches to querying MacBook hardware sensors via IOKit

🪄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 HardwareCompat.swift detection and fallback logic for M1/M2 devices

The README explicitly mentions that M1/M2 devices don't work and the maintainer hasn't figured out a fix. HardwareCompat.swift currently has hard-coded sensor detection. A contributor could research M1/M2 sensor IDs, add device detection logic, and implement alternative sensor lookup strategies to support these devices.

  • [ ] Research M1/M2 MacBook Pro HID sensor identifiers using IOKit
  • [ ] Extend HardwareCompat.swift with device model detection (check System Information or IOKit registry)
  • [ ] Add fallback sensor search logic that iterates through available HID devices if hard-coded ID fails
  • [ ] Test on M1/M2 hardware or document expected sensor names for crowdsourced testing
  • [ ] Update README FAQ section with findings and workarounds

Create AudioEngines/README.md documenting audio engine architecture and adding ThereminAudioEngine tests

The AudioEngines directory has two engine implementations (CreakAudioEngine.swift and ThereminAudioEngine.swift) following AudioEngineProtocol.swift, but there's no documentation of how to add new engines. Additionally, no unit tests exist for the audio engines. A contributor could document the architecture and add tests for the Theremin engine.

  • [ ] Create AudioEngines/README.md explaining the AudioEngineProtocol and how to implement new engines
  • [ ] Create a test file (e.g., LidAngleSensor/Tests/AudioEngines/ThereminAudioEngineTests.swift)
  • [ ] Add tests for ThereminAudioEngine covering frequency calculation based on lid angle inputs
  • [ ] Add tests for CreakAudioEngine CREAK_LOOP.wav playback and parameter handling
  • [ ] Document the AudioEngineHelpers.swift utility functions in the README

Refactor ParameterSlider.swift into reusable UI component library with documentation

ParameterSlider.swift is a custom UI component used across the app (in MenuBarView and likely ContentView). This could be extracted into a proper component with variations, making it easier to maintain and extend audio parameter controls across multiple audio engines.

  • [ ] Create LidAngleSensor/Components/ directory and move ParameterSlider.swift there
  • [ ] Create a ParameterSliderPresets.swift file with common slider configurations (e.g., frequency ranges, angle ranges)
  • [ ] Add comprehensive SwiftUI previews to ParameterSlider.swift showing all slider variations
  • [ ] Create Components/README.md documenting ParameterSlider API and usage examples
  • [ ] Update MenuBarView.swift and any other files to import from the new location

🌿Good first issues

  • Add logging/diagnostics to HardwareCompat.swift to help users identify why their MacBook's lid sensor isn't detected, rather than silently failing. Include a button in ContentView.swift to print detected HID devices.
  • Write unit tests for the sensor reading logic in LidAngleSensor.swift (currently no tests exist). Mock the HID layer and verify angle values are parsed correctly from raw device data.
  • Improve audio quality in CreakAudioEngine.swift: the README admits the audio 'feels weird.' Implement pitch modulation or amplitude envelope shaping based on lid angle velocity to make the sound more natural.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • f7e4e5c — Lower CPU/memory usage (samhenrigold)
  • 736817a — Update ThereminAudioEngine.swift (samhenrigold)
  • 14a6621 — Hardware detection (samhenrigold)
  • 767f890 — Merge pull request #61 from samhenrigold/shg/swiftui-refactor (samhenrigold)
  • 5dd7923 — tweakable settings (samhenrigold)
  • 4826493 — Adds menu bar extra (samhenrigold)
  • bdbf25c — Update LidAngleSensor.swift (samhenrigold)
  • 170a356 — adds icon (samhenrigold)
  • 5441905 — Avoid explicit types (samhenrigold)
  • 9b5df81 — Update ThereminAudioEngine.swift (samhenrigold)

🔒Security observations

This macOS utility application demonstrates a generally secure posture for a local system tool. No critical vulnerabilities were identified. The main concerns are minor: hardcoded hardware sensor identifiers that limit compatibility, and the embedded audio resource. The application directly interfaces with hardware via HID (Human Interface Device) APIs, which is legitimate for a system utility. No injection risks, exposed credentials, or dependency vulnerabilities were detected. The codebase appears to be well-structured Swift code without obvious security misconfigurations. Recommendations focus on improving device compatibility and hardware abstraction rather than addressing active security flaws.

  • Low · Hardcoded Sensor Configuration — LidAngleSensor/HardwareCompat.swift. According to the README, the application has hardcoded logic to look for a specific lid angle sensor. This reduces flexibility and may cause compatibility issues across different MacBook models. The code in HardwareCompat.swift likely contains hardcoded sensor identifiers. Fix: Implement dynamic sensor detection that can enumerate available HID devices rather than hardcoding specific sensor identifiers. Maintain a configuration file for known sensor mappings.
  • Low · Audio Resource Embedded in Application — LidAngleSensor/AudioEngines/CREAK_LOOP.wav. The application embeds a WAV audio file (CREAK_LOOP.wav) directly in the bundle. While not a security risk per se, this increases app size and could theoretically be modified if the app bundle is tampered with. Fix: Consider code-signing the app bundle properly to ensure integrity. Alternatively, load audio resources from a secure, verified location.
  • Low · Limited Device Compatibility Documentation — README.md, LidAngleSensor/HardwareCompat.swift. The README indicates the application does not work on M1/M2 devices, and the developer notes they have only tested on M4 MacBook Pro. This suggests potential unvalidated hardware interactions that may cause unexpected behavior on unsupported devices. Fix: Implement proper device compatibility checks at runtime. Add explicit warnings or graceful degradation for unsupported hardware. Document all known limitations clearly.

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.

Mixed signals · samhenrigold/LidAngleSensor — RepoPilot