How the openlogi-permissions Crate Checks macOS TCC and Linux Device Permissions

The openlogi-permissions crate provides a non-prompting abstraction layer that queries macOS TCC permissions via read-only system APIs and validates Linux device access by probing /dev/uinput and Logitech hidraw nodes, returning a unified PermissionStatus enum across both platforms.

The openlogi-permissions crate in the AprilNEA/OpenLogi repository standardizes privacy permission detection for the OpenLogi agent. It enables silent status checks without triggering system consent dialogs, while supporting deep-link navigation to macOS System Settings when users need to manually grant access.

macOS TCC Permission Handling

The macOS implementation in src/macos.rs focuses on Transparency, Consent, and Control (TCC) permissions, specifically covering Accessibility, Input Monitoring, CoreBluetooth, and Camera access. All query functions use read-only APIs—such as IOHIDCheckAccess—to ensure the crate never triggers a permission prompt; the owning process presents the prompt only when first accessing the resource.

Querying Input Monitoring and Accessibility

The input_monitoring() function determines authorization status by calling IOHIDCheckAccess(IOHIDRequestType::ListenEvent) and mapping the result to PermissionStatus::{Granted, Denied, Unknown}. As implemented in src/macos.rs lines 22-30, this approach reads the current TCC database state without modifying it or alerting the user.

Bluetooth Authorization Status

For Bluetooth permissions, the bluetooth() function instantiates the Objective-C class CBCentralManager via the objc2 crate to read the authorization property. According to src/macos.rs lines 32-48, the implementation translates the integer authorization codes into the crate's PermissionStatus enum, allowing the agent to detect whether the user has granted CoreBluetooth access.

Camera Access Detection

The camera() function delegates to the openlogi-camera crate's camera_authorization() function, then maps the returned enum to PermissionStatus. This integration, found in src/macos.rs lines 51-59, ensures consistent status reporting across the OpenLogi ecosystem while respecting the camera subsystem's specific implementation.

Deep-Linking to System Settings

When the application needs to direct users to grant permissions manually, the open_pane(permission) function constructs deep-link URLs such as x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility based on the Permission enum variant. As defined in src/macos.rs lines 62-75, this helper uses the opener crate to launch the specific privacy pane in System Settings.

Linux Device Permission Validation

Linux platforms lack consent dialogs; instead, access depends on udev rules granting read/write rights to device files. The implementation in src/linux.rs probes these filesystem permissions to determine if the user can access input devices.

Probing /dev/uinput and HID-Raw Devices

The input_device_access() function performs two distinct probes:

  • Uinput check – Attempts to open /dev/uinput for writing; success indicates the user has permissions to create virtual input devices (src/linux.rs lines 62-68).
  • Logitech HID-raw scan – Iterates through /dev entries matching hidraw*, filters devices belonging to Logitech using the vendor ID defined in openlogi_core, and attempts read/write access. The results populate the internal HidrawProbe enum (src/linux.rs lines 70-88).

Permission Status Logic

The combined probe results convert to PermissionStatus via the From<Probes> implementation in src/linux.rs lines 54-58:

  • Granted – Both uinput is writable and at least one Logitech hidraw device is accessible.
  • Denied – Either uinput is not writable or hidraw access is denied.
  • Unknown – Uinput is writable but no Logitech hidraw devices are present (hardware may be disconnected).

Because Linux lacks a settings pane equivalent, the open_pane function is a no-op on non-macOS platforms (src/lib.rs lines 72-76).

Cross-Platform API Usage

The crate exposes platform-specific functions conditionally compiled via #[cfg]. Applications can query permissions without handling platform differences manually:

use openlogi_permissions::{Permission, PermissionStatus, open_pane};

#[cfg(target_os = "macos")]
fn check_macos_permissions() {
    // Query current status without prompting
    let im = openlogi_permissions::input_monitoring();
    println!("Input Monitoring: {:?}", im);
    
    // Open System Settings if access is denied
    if im != PermissionStatus::Granted {
        open_pane(Permission::Accessibility);
    }
}

#[cfg(target_os = "linux")]
fn check_linux_permissions() {
    // Returns Granted, Denied, or Unknown based on device file probes
    let dev = openlogi_permissions::input_device_access();
    println!("Linux input-device access: {:?}", dev);
}

Summary

  • The openlogi-permissions crate provides a unified PermissionStatus abstraction across macOS TCC and Linux udev permission models.
  • macOS checks use read-only APIs (IOHIDCheckAccess, CBCentralManager) in src/macos.rs to avoid triggering prompts, while supporting deep-links to System Settings.
  • Linux validation probes /dev/uinput and Logitech hidraw device files in src/linux.rs to determine access rights without requiring consent dialogs.
  • The open_pane helper only functions on macOS, providing URLs like x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility for manual permission configuration.

Frequently Asked Questions

How does openlogi-permissions avoid triggering macOS permission prompts?

The crate exclusively uses read-only APIs such as IOHIDCheckAccess for Input Monitoring and property reads on CBCentralManager for Bluetooth. These functions query the TCC database without requesting access, ensuring input_monitoring() and bluetooth() calls remain silent. The owning process—typically the OpenLogi agent—triggers the actual prompt only when first attempting to use the protected resource.

What determines PermissionStatus::Unknown on Linux?

According to the From<Probes> implementation in src/linux.rs lines 57-58, the status returns Unknown when the user has write access to /dev/uinput but no Logitech hidraw devices are detected in /dev. This typically indicates that the user has sufficient permissions but the hardware is disconnected or not yet enumerated by the kernel.

Why is the open_pane function unavailable on Linux?

Linux lacks a centralized consent management interface equivalent to macOS System Settings TCC panes. As implemented in src/lib.rs lines 72-76, the open_pane function compiles to a no-op on non-macOS targets, allowing cross-platform code to call it unconditionally without runtime errors.

Which specific device files does the Linux implementation check?

The Linux module in src/linux.rs validates two resources: /dev/uinput for virtual input device creation, and /dev/hidraw* nodes specifically filtered for Logitech vendor IDs (defined in openlogi_core). The implementation attempts read/write opens on these files to determine effective permissions, returning Granted only when both resources are accessible.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →