Repository navigation
Modules
A module is one collector with one top-level key in the payload. Each is a
subclass of BaseModuleProcessor implementing collectData(), and each may use
executeWithFallback(osquery:bash:) — osquery first, shell second — or drive
shell commands directly.
| Name | Processor | Notes |
|---|---|---|
hardware |
HardwareModuleProcessor |
|
system |
SystemModuleProcessor |
|
network |
NetworkModuleProcessor |
|
security |
SecurityModuleProcessor |
|
applications |
ApplicationsModuleProcessor |
Also receives the app-usage service |
management |
ManagementModuleProcessor |
|
inventory |
InventoryModuleProcessor |
|
identity |
IdentityModuleProcessor |
|
installs |
InstallsModuleProcessor |
|
peripherals |
PeripheralsModuleProcessor |
|
displays |
PeripheralsModuleProcessor |
Alias for peripherals |
printers |
PeripheralsModuleProcessor |
Alias for peripherals |
Anything else logs Unknown module: <name> and is skipped. Printers are
collected inside peripherals, and displays inside hardware. Requesting an
alias runs the peripherals processor and sends its output under the alias's own
key (displays or printers), so use peripherals and hardware directly. The
payload envelope also carries a profiles slot for parity with the Windows
client; installed profiles are reported inside management.
At -vv every module except inventory prints one progress line per step, in
the form [03/15] [████░░░░░░░░░░░░░░░░] 20% uptime, and the step names below
are the ones that appear there.
The examples below are hand-authored illustrations of the shape, not captured output. Fields are omitted where a Mac would not report them.
Device identity and the organisational metadata an enrolment process wrote to disk.
Sources. osquery system_info (uuid, hardware_serial, computer_name),
with a system_profiler SPHardwareDataType + hostname shell fallback. Asset
metadata is parsed from /Library/Management/Inventory.yaml — the keys asset,
location, allocation, area, catalog, usage and fleet, mapped onto
assetTag, location, owner, department, catalog, usage and fleet.
fleet is truncated at the first comma, because a spill from the enrolment
script's IFS-split can append later CSV columns to it.
{
"inventory": {
"deviceName": "mac-0001",
"serialNumber": "SERIAL123",
"assetTag": "AST-4471",
"uuid": "00000000-0000-0000-0000-000000000001",
"location": "Building A",
"owner": "helpdesk",
"department": "Design",
"catalog": "production",
"usage": "shared",
"fleet": "lab-a",
"collectionTimestamp": "2026-01-15T09:30:12Z",
"success": true
}
}Operating system, uptime, kernel, launchd jobs, update state and the macOS extension surfaces.
Fifteen steps: os_info, system_details, uptime, kernel_info,
launch_items, launchd_services, software_updates, pending_updates,
install_history, system_config, environment, login_items,
system_extensions, kernel_extensions and privileged_helpers.
Sources. osquery os_version, system_info, uptime, kernel_info,
launchd, system_extensions, kernel_extensions, package_receipts, and the
macadmins extension's pending_apple_updates. Shell fallbacks use sw_vers,
uname, sysctl, launchctl and codesign. Boot time comes from
sysctl kern.boottime and is published at systemDetails.bootTime.
Reboot and OS-update detection read this module's output — see Architecture.
{
"system": {
"operatingSystem": {
"name": "macOS",
"version": "15.3",
"major": "15",
"minor": "3",
"patch": "0",
"buildNumber": "24D60",
"arch": "arm64"
},
"systemDetails": {
"computerName": "mac-0001",
"bootTime": "2026-01-14T07:41:03Z",
"timeZone": "UTC"
},
"uptime": 92349,
"uptimeString": "1 day, 1 hour, 39 minutes",
"kernelInfo": { "version": "24.3.0", "path": "/System/Library/Kernels/kernel" },
"scheduledTasks": [],
"services": [
{ "name": "com.github.reportmate.hourly", "status": "loaded", "disabled": false }
],
"pendingAppleUpdates": [
{ "name": "macOS Sequoia 15.3.1", "version": "15.3.1", "restartRequired": true }
],
"installHistory": [
{ "packageId": "com.github.reportmate", "version": "2026.01.15.0930", "installTime": "2026-01-15T09:12:44Z" }
],
"environment": {},
"systemConfiguration": {},
"loginItems": [],
"systemExtensions": [],
"kernelExtensions": [],
"privilegedHelperTools": []
}
}Model, chip, memory, storage, displays, battery, radios and thermals.
Sources. osquery system_info, battery and mounts; system_profiler
for SPHardwareDataType, SPMemoryDataType, SPStorageDataType,
SPNVMeDataType, SPDisplaysDataType, SPPowerDataType, SPAirPortDataType
and SPBluetoothDataType; ioreg for the platform serial, the marketing
product name and display EDIDs; sysctl for the Apple Silicon core split and
NPU detection; diskutil and tmutil for volume details; du for the deep
storage walk. Apple Silicon performance and efficiency core counts come from the
last two fields of system_profiler's number_processors (proc 14:10:4 is
total, performance, efficiency).
Displays. Displays come from system_profiler SPDisplaysDataType, joined per
connector to the raw EDID that the IO registry keeps on the
IOPortTransportState (Apple Silicon) and IODisplayConnect (Intel) nodes. The
join is on vendor id, product id and the EDID header serial. The serial reported
is the human-readable one from the EDID's 0xFF descriptor, and is null, not
"0", when the panel does not carry one. Those registry nodes persist when
system_profiler lists nothing, as on a desktop Mac at the login window with no
console user, so displays are then reported from the EDID alone (name,
vendor, product and resolution, including DisplayID extension blocks). The EDID
path reports no manufacture year or week, because no single year offset agrees
with what system_profiler and Windows report across vendors;
system_profiler rows keep their own date.
Model names are resolved to a marketing name where possible ("Mac mini (2024)")
with the raw Mac16,11-style identifier kept alongside. manufacturer is
normalised to Apple, and processor.name has its redundant Apple prefix
stripped.
Storage modes. StorageMode (or --storage-mode) decides whether the
directory-level walk of the root volume runs:
| Mode | Behaviour |
|---|---|
quick |
Drive totals only; a previous deep analysis is reused from cache if present |
deep |
Always run the directory walk, then update the cache |
auto |
Run the walk only when the cache is missing or older than 24 hours |
The cache is /Library/Managed Reports/cache/storage_analysis.json. The hourly
daemon and the post-install run use quick; the daily daemon runs deep. When no cache
exists and the walk did not run, the drive carries
"storageAnalysisEnabled": false.
{
"hardware": {
"collectedAt": "2026-01-15T09:30:44Z",
"model": "MacBook Pro (2024)",
"model_identifier": "Mac16,7",
"manufacturer": "Apple",
"formFactor": "laptop",
"processor": {
"name": "M4 Pro",
"cores": 14,
"performance_cores": 10,
"efficiency_cores": 4,
"logical_cores": 14,
"architecture": "ARM64",
"manufacturer": "Apple"
},
"graphics": {
"name": "Apple M4 Pro",
"manufacturer": "Apple",
"cores": 20,
"bus": "Builtin",
"device_type": "GPU",
"metal_support": "Metal 4",
"vendor": "Apple"
},
"displays": [
{
"name": "Built-in Liquid Retina XDR Display",
"display_type": "Retina LCD",
"resolution": "3456 x 2234",
"scaled_resolution": "1728 x 1117 @ 120.00Hz",
"is_main_display": true,
"mirror": false,
"online": true
}
],
"memory": {
"physical_memory": 51539607552,
"type": "LPDDR5",
"unified_memory": true,
"manufacturer": "Hynix"
},
"storage": [
{
"name": "Macintosh HD",
"is_internal": true,
"health": "Good",
"storageAnalysisEnabled": true
}
],
"battery": {
"health": "Good",
"condition": "Normal",
"cycle_count": 118,
"percent_remaining": 84,
"state": "AC Power"
},
"wireless": {},
"bluetooth": {},
"thermal": {},
"npu": { "present": true }
}
}Interfaces, addressing, DNS, Wi-Fi and VPN, plus a measured throughput test.
Sources. osquery interface_addresses joined to interface_details, and
the macadmins extension's network_quality and wifi_network tables. Shell
collection uses ifconfig, networksetup, scutil, the CoreWLAN-backed
airport data, system_profiler SPAirPortDataType and networkQuality -s.
Seven steps: network_interfaces, hostname_info, network_quality,
wifi_network, vpn_connections, saved_wifi and dns_config. An osquery
failure in the interface step does not sink the module: the system fallback
still yields the interface list, Wi-Fi typing and the active address.
The network-quality step measures actual throughput and takes 20–30 seconds; it
runs on every collection of this module. When networkQuality -s is the source,
throughput values are the Mbps figures it prints, kept as strings, and rating
is the lower of the two responsiveness ratings. On a Mac without the
networkQuality tool the object is {"error": "Not Available (macOS 12+ required)"}. If the current SSID is unreadable
because Location Services is off, the client substitutes the first known network
and marks it with a note.
Addresses. localIpAddresses lists every usable address on the Mac's
current interfaces, IPv4 first. hostnameAddresses lists what DNS returns for
the Mac's hostname, local hostname, <local hostname>.local and the process
host name. managementAddress is the first DNS-resolved address that is also
on a local interface, or null when none agree. It is the address to reach
the Mac by for management; the default-route address in activeConnection can
differ from it.
{
"network": {
"hostname": "mac-0001",
"localHostname": "mac-0001",
"sharingName": "mac-0001",
"localIpAddresses": ["10.0.12.44", "fe80::1c2b:3d4e:5f60:7182"],
"hostnameAddresses": ["10.0.12.44"],
"managementAddress": "10.0.12.44",
"interfaces": [
{
"name": "en0",
"displayName": "Wi-Fi",
"type": "WiFi",
"macAddress": "aa:bb:cc:00:11:22",
"mtu": 1500,
"isUp": true,
"isLoopback": false,
"addresses": [
{ "address": "10.0.12.44", "netmask": "255.255.255.0", "family": "IPv4" }
]
}
],
"routes": [],
"dnsConfiguration": { "servers": ["10.0.0.10"], "searchDomains": ["example.com"] },
"wifiInfo": {
"powerStatus": true,
"knownNetworks": [{ "ssid": "example-corp", "securityType": "WPA2 Enterprise" }]
},
"currentWiFiNetwork": {
"ssid": "example-corp",
"bssid": "aa:bb:cc:dd:ee:ff",
"channel": "44",
"rssi": -52
},
"networkQuality": {
"dl_throughput": "412.6",
"ul_throughput": "88.1",
"dl_rating": "High",
"ul_rating": "Medium",
"idle_latency": "21.4",
"rating": "Medium"
},
"vpnConnections": [],
"listeningPorts": [],
"arpCache": [],
"activeConnection": { "interface": "en0", "address": "10.0.12.44" }
}
}Twenty-two independent posture probes: sip_status, gatekeeper, firewall,
filevault, xprotect, ssh_status, secure_boot, firmware_password,
root_user, mrt_status, secure_enclave, activation_lock,
filevault_users, secure_token, bootstrap_token, authdb,
unpatched_cves, security_release, remote_management, certificates,
endpoint_security and edr_products.
Sources. csrutil, spctl, fdesetup, socketfilterfw, nvram,
systemsetup, system_profiler, dscl, security and launchctl for the
shell probes; osquery xprotect_entries; and the macadmins extension's
sofa_unpatched_cves, sofa_security_release_info, filevault_users and
authdb tables. The SOFA tables fetch the SOFA feed over the network, which is
why extension queries get their own, longer timeout.
Bootstrap token status is read from profiles status -type bootstraptoken by
the word after each phrase (escrowed to server: and supported on server:),
giving Escrowed, Not Escrowed, Not Supported or Requires MDM Enrollment.
Platform SSO is deliberately not collected here — it is an identity concern and lives in the identity module, where it is not stuck behind these slower probes.
{
"security": {
"systemIntegrityProtection": { "enabled": true, "status": "Enabled" },
"gatekeeper": { "enabled": true, "status": "Enabled", "developerIdEnabled": true },
"firewall": { "enabled": true, "stealthMode": false },
"fileVault": { "enabled": true, "status": "Enabled" },
"fileVaultUsers": [{ "username": "localadmin" }],
"secureToken": { "enabled": true },
"bootstrapToken": { "escrowed": true, "status": "Escrowed", "supported": true, "isAppleSilicon": true },
"xprotect": { "version": "5290" },
"ssh": { "remoteLoginEnabled": false },
"secureBoot": { "policy": "full" },
"firmwarePassword": { "enabled": false },
"rootUser": { "enabled": false },
"mrt": { "version": "1.93" },
"secureEnclave": { "present": true },
"activationLock": { "enabled": false },
"authorizationDB": {},
"unpatchedCVEs": [{ "cve": "CVE-2026-00000", "patchedVersion": "15.3.1" }],
"securityReleaseInfo": { "latestOS": "15.3.1", "activelyExploitedCVEs": 0 },
"remoteManagement": {
"ard_enabled": false,
"screen_sharing_enabled": false,
"remote_login_enabled": false
},
"certificates": [],
"endpointSecurity": [],
"edrProducts": []
}
}Local accounts, groups, sessions and directory state.
Sources. dscl is the primary source — the osquery users table is
deliberately skipped because it carries no admin status or SSH access. Local
users with UID between 500 and 65533 are enumerated, and each is read for
UniqueID, PrimaryGroupID, RealName, NFSHomeDirectory, UserShell and
GeneratedUID, plus admin, SSH and Screen Sharing group membership. Each user
object is emitted by jq and the array assembled with jq -s, so a name or
hint containing a quote or backslash cannot invalidate the list. Sessions
come from osquery logged_in_users and login history from last/wtmp.
Linked Apple ID is read from MobileMeAccounts, Platform SSO from
/usr/bin/app-sso, and auto-login from
/Library/Preferences/com.apple.loginwindow.
{
"identity": {
"users": [
{
"username": "jdoe",
"realName": "J Doe",
"uid": 501,
"gid": 20,
"homeDirectory": "/Users/jdoe",
"shell": "/bin/zsh",
"uuid": "00000000-0000-0000-0000-000000000501",
"isAdmin": false,
"sshAccess": false,
"screenSharingAccess": false,
"autoLoginEnabled": false,
"lastLogon": "2026-01-15T08:55:10Z",
"failedLoginCount": 0,
"linkedAppleId": "",
"groupMembership": "staff,everyone",
"isDisabled": false
}
],
"groups": [{ "name": "admin", "gid": 80 }],
"loggedInUsers": [{ "username": "jdoe", "tty": "console", "time": "2026-01-15T08:55:10Z" }],
"loginHistory": [],
"directoryServices": { "nodes": ["/Local/Default"] },
"secureTokenUsers": ["localadmin"],
"platformSSOUsers": [],
"summary": { "totalUsers": 2, "adminCount": 1, "loggedInCount": 1 }
}
}Installed apps, running processes, startup items and usage.
Sources. osquery apps (restricted to /Applications,
/System/Applications and any */Applications/* path), processes, launchd,
startup_items and the Background Task Management data. The shell fallback
walks .app bundles with find and reads each Info.plist with PlistBuddy.
Usage comes from the watcher's SQLite database via ApplicationUsageService.
source is derived from the install path: /System/… is Apple,
/Applications/… is Local, an App Store marker gives App Store, anything
else is User.
Usage accounting. applicationUsage describes the current window;
dailyUsageHistory is per-day, per-app increments and is produced only when
the data came from the watcher (captureMethod: SQLiteWatcher); the ProcessPolling fallback has no watermark, so
anything it reported would be double-counted next cycle. Each session carries a
watermark of the seconds already accepted by the server, so a still-running app
contributes only its increment. A launch is counted once, on the day it
happened, the first time its session is reported. A session for an app that is
still open across a watcher restart (a reboot or a client upgrade) is carried
over with its id and watermark, so it is not counted as a second launch. A
session is matched to a running process by PID, bundle path and start time,
since PIDs are reused. Before sending, each increment is put back in physical
order: foreground is capped at the session's total, and active at foreground.
Sessions are retired only after the API confirms delivery.
{
"applications": {
"installedApplications": [
{
"name": "Safari",
"path": "/Applications/Safari.app",
"bundleIdentifier": "com.apple.Safari",
"version": "18.3",
"buildVersion": "20621.1.15.11.10",
"category": "public.app-category.productivity",
"source": "Local",
"minimumSystemVersion": "15.0",
"developmentRegion": "en",
"compiler": "com.apple.compilers.llvm.clang.1_0"
}
],
"runningProcesses": [{ "name": "Safari", "pid": 4211, "uid": 501 }],
"startupPrograms": [],
"applicationUsage": {
"isCaptureEnabled": true,
"status": "complete",
"captureMethod": "SQLiteWatcher",
"generatedAt": "2026-01-15T09:30:50Z",
"windowStart": "2026-01-15T00:00:00Z",
"windowEnd": "2026-01-15T09:30:50Z",
"totalLaunches": 6,
"totalUsageSeconds": 12840,
"activeSessions": [
{
"sessionId": "6f2a…",
"name": "Safari",
"path": "/Applications/Safari.app",
"processId": 4211,
"user": "jdoe",
"startTime": "2026-01-15T08:56:02Z",
"durationSeconds": 2088,
"foregroundSeconds": 1450,
"activeSeconds": 1122,
"isActive": true
}
]
},
"dailyUsageHistory": [
{
"date": "2026-01-15",
"appName": "Safari",
"launches": 1,
"totalSeconds": 2088,
"activeSeconds": 1122
}
]
}
}Managed software state: Munki, Homebrew and the OS installer history.
Eight steps: install_history, homebrew_packages, munki_log,
munki_info, munki_installs, pending_updates, catalog_metadata and
manifest_catalogs.
Sources. osquery package_install_history and homebrew_packages; Munki's
ManagedInstallReport.plist, its ManagedSoftwareUpdate.log run log, its
manifest and catalogs.
Items are enriched with category and developer from the catalogs in
/Library/Managed Installs/catalogs. A catalog is parsed as a plist and, when
that fails, as YAML, so repos that serve YAML catalogs are enriched too.
REPORTMATE_CATALOGS_DIR overrides the directory for testing.
Structured session reports. When Munki writes reports/sessions.json under
/Library/Managed Installs, the module reads it with reports/items.json, the
latest finished session under logs/YYYY-MM-DD/HHMM[_n]/ (skipping one still
marked running), that session's events.jsonl (falling back to
reports/events.json), and reports/run.log. These are the same layout and
field names the Windows client reads from Cimian. The munki object then gains
sessions, events, totalSessions, sessionId, runType,
durationSeconds, lastSessionStatus, warningItems and errorItems, and each
item gains the Windows field names (currentStatus, mappedStatus,
latestVersion, lastSeenInSession, lastAttemptTime, lastAttemptStatus,
lastUpdate, failureCount, warningCount, actionPerformed), with
lastError and lastWarning taken by exact item name. Without the reports, the
legacy plist path runs and messages are attributed to items by pattern-matching
Munki's message text.
Install-loop guard. Every item carries its install-loop state as both
hasInstallLoop and installLoopDetected, false when Munki did not flag it.
An item the guard is holding also carries statusReasonCode, statusReason,
warningMessages (the loop line, then its cause) and both lines joined in
lastWarning.
Transient downloads. A download that failed because the connection dropped,
timed out, went offline, or could not reach or resolve the server is not an
install failure: the item keeps its pending status and the message goes to
lastWarning and pendingReason instead of lastError. An item counts as
transient when Munki's download_error_is_transient flag says so, or when its
Download failed: message matches one of those conditions. Anything else, such
as a TLS failure or insufficient disk space, stays an error.
munki.status is derived: Error if there are errors, else Warning if there
are warnings, else Active if the last run succeeded, else Inactive.
runLog is carried at the top level under the same key the Windows client uses
for Cimian, so the dashboard reads both platforms the same way.
This module is what the Munki postflight collects, and its results also drive
per-item events in the payload's events array (see Architecture).
newlyRemovedItems lists what the run removed, and the removal event sends the
full list as removed_items with action: remove.
{
"installs": {
"installHistory": [
{ "packageId": "com.apple.pkg.Safari", "version": "18.3", "installTime": "2026-01-12T04:11:20Z" }
],
"homebrewPackages": [{ "name": "jq", "version": "1.7.1" }],
"managedInstalls": [
{
"name": "ExampleApp",
"displayName": "Example App",
"version": "4.2.0",
"installedVersion": "4.2.0",
"status": "Installed",
"type": "managed_install",
"installedSize": 184320
}
],
"pendingUpdates": [{ "name": "ExampleTool", "version": "2.9.1" }],
"munki": {
"isInstalled": true,
"version": "6.6.1",
"status": "Active",
"lastRunSuccess": true,
"clientIdentifier": "labs/design",
"manifestName": "labs/design",
"softwareRepoURL": "https://munki.example.com/repo",
"consoleUser": "jdoe",
"startTime": "2026-01-15T09:05:00Z",
"endTime": "2026-01-15T09:07:41Z",
"lastRun": "2026-01-15T09:07:41Z",
"catalogs": ["production"],
"newlyInstalledCount": 1,
"newlyInstalledItems": [{ "name": "ExampleApp", "version": "4.2.0" }],
"newlyRemovedCount": 0,
"newlyRemovedItems": [],
"items": [
{
"id": "exampleapp",
"name": "ExampleApp",
"displayName": "Example App",
"version": "4.2.0",
"installedVersion": "4.2.0",
"status": "Installed",
"type": "managed_install",
"installedSize": 184320,
"endTime": "2026-01-15T09:07:12Z",
"lastError": "",
"lastWarning": "",
"pendingReason": "",
"hasInstallLoop": false,
"installLoopDetected": false,
"category": "Productivity",
"developer": "Example Ltd"
}
]
},
"runLog": "…"
}
}MDM enrolment, profiles, managed policies and the estate's log roots.
Sources. osquery system_info and the macadmins extension's mdm table;
/usr/libexec/mdmclient dumpManagementStatus for supervision, user enrolment,
activation-lock policy and organisation details; profiles -C -v and
system_profiler SPConfigurationProfileDataType for installed profiles, server
and check-in URLs and SCEP payloads; and the osquery managed_policies table
for forced preferences.
The MDM identity certificate is resolved through the com.apple.mdm payload,
which names its certificate by UUID; that UUID resolves to the ACME, SCEP or
PKCS12 payload that provisions it, which carries the subject CN. Matching
keychain labels against an "MDM" substring is not used: it picks up dead
certificates from previous enrolments and cannot match identities named by bare
GUID at all.
Each of the nine steps (mdm_status, mdm_info, mdm_certificate,
ade_config, device_ids, remote_mgmt, profiles, managed_policies and
managed_logs) is isolated. A step that throws records {step, error} in
_collection_errors and returns an empty default rather than sinking the module —
a management payload that never arrives leaves the server showing the device's
previous record, so a re-enrolled Mac would report its old MDM provider
indefinitely.
Log survey. logs is a file-system survey of the management-tool log
roots, in the same shape the Windows client sends under management.logs:
- Every
/Library/Managed*directory with alogs(orLogs) subdirectory, up to 20 roots. The tool key is the directory name afterManaged, lowercased (Managed Installsisinstalls,Managed Reportsisreports). - The MDM agent's logs, reported with tool
mdm: Intune'sIntuneMDMDaemon *.logfiles under/Library/Logs/Microsoft/Intune, or/var/log/jamf.log. Only the first one present is reported. - The OS installer log,
/var/log/install.logand its rotated copies, reported with toolinstaller.
For each root it reports a layout (flat, daily for logs/YYYY-MM-DD/, or
sessions for logs/YYYY-MM-DD/HHMM[SS][_n]/), a file inventory of up to 50
files (the walk stops after 5,000 entries and sets inventoryTruncated), the
latest session summary when the tool writes session.json, up to six tails, and
errorCount and warningCount from the primary log's tail. The primary tail
holds up to 2,000 lines or 256 KiB, enough for a whole ordinary run; other tails
hold 150 lines or 32 KiB. Each root carries the owning tool's version, read
from its package receipt in /var/db/receipts or, for the Intune agent, from
its app bundle.
{
"management": {
"mdm_enrollment": {
"enrolled": "true",
"server_url": "https://mdm.example.com/mdm/",
"checkin_url": "https://mdm.example.com/checkin/",
"user_approved": "true",
"installed_from_dep": "true",
"dep_capable": "true",
"access_rights": "8191",
"has_scep_payload": "true"
},
"mdm_info": { "is_supervised": "true", "org_name": "Example Org" },
"mdm_certificate": {
"push_topic": "com.apple.mgmt.External.0000",
"cert_subject": "MDM Identity",
"cert_expires": "2027-02-01T00:00:00Z",
"mdm_provider": "Example MDM"
},
"ade_configuration": { "activation_record_present": true },
"device_identifiers": { "serial_number": "SERIAL123" },
"remote_management": { "ard_enabled": false },
"installed_profiles": [
{
"identifier": "com.example.reportmate.settings",
"displayName": "ReportMate",
"organization": "Example Org",
"installDate": "2026-01-10T12:00:00Z"
}
],
"managed_policies": [
{ "domain": "com.github.reportmate", "name": "ApiUrl", "forced": 1 }
],
"logs": {
"platform": "macOS",
"roots": [
{
"tool": "reports",
"name": "Managed Reports",
"path": "/Library/Managed Reports/logs",
"layout": "flat",
"fileCount": 4,
"totalBytes": 183204,
"newestModified": "2026-01-15T09:31:10Z",
"inventoryTruncated": false,
"files": [],
"primaryLog": "reportmate.log",
"errorCount": 0,
"warningCount": 1,
"tails": [],
"version": "2026.10.07.2024"
}
]
}
}
}Everything attached to the Mac, in one flat set of per-category arrays. Displays are not collected here; the hardware module reports them.
Ten steps: usb_devices, input_devices, audio_devices,
bluetooth_devices, camera_devices, thunderbolt_devices, printers,
scanners, external_storage and serial_ports.
Sources. osquery usb_devices; system_profiler for SPUSBDataType,
SPAudioDataType, SPBluetoothDataType, SPCameraDataType,
SPThunderboltDataType and SPPrintersDataType; ioreg for a single pass over
the HID registry; and CUPS data for printers.
Input devices are classified by HID usage from one HID enumeration rather than
from legacy IOKit class names, and are deduplicated on name plus vendor/product
id, because a device is enumerated once per HID collection it publishes and the
same keyboard would otherwise appear several times. Each entry carries the serial
number the device publishes, whether it is built in (SPI or FIFO transport), and
its connection type. A pen digitizer is reported under tablets as a
Graphics Tablet with tabletType: "Pen Input"; the screen of a pen display is
a display, which the hardware module reports from its EDID.
{
"peripherals": {
"collectedAt": "2026-01-15T09:31:02Z",
"usbDevices": [
{
"vendor": "Example Ltd",
"vendor_id": "0x1234",
"model": "Example Hub",
"model_id": "0x5678",
"serial": "EX-0001",
"removable": 1
}
],
"inputDevices": {
"keyboards": [
{
"name": "Apple Internal Keyboard / Trackpad",
"vendor": "Apple Inc.",
"vendorId": "05AC",
"productId": "0343",
"serialNumber": "",
"isBuiltIn": true,
"connectionType": "Built-in",
"deviceType": "Keyboard"
}
],
"mice": [],
"trackpads": [],
"tablets": [
{
"name": "Example Pen Tablet",
"vendor": "Example Ltd",
"vendorId": "1234",
"productId": "5678",
"serialNumber": "SERIAL456",
"isBuiltIn": false,
"connectionType": "USB",
"deviceType": "Graphics Tablet",
"tabletType": "Pen Input"
}
]
},
"audioDevices": [{ "name": "MacBook Pro Speakers" }],
"bluetoothDevices": [{ "name": "Example Headset", "connected": true }],
"cameras": [{ "name": "FaceTime HD Camera" }],
"thunderboltDevices": [],
"printers": [
{
"name": "Design-Floor2",
"status": "idle",
"uri": "ipp://print.example.com/printers/design",
"ppd": "Example Printer PPD",
"driverVersion": "1.4"
}
],
"scanners": [],
"externalStorage": [],
"serialPorts": []
}
}The SQL each module runs is written inline in its processor, not loaded from a
file. Sources/Resources/queries.json and
Sources/Resources/fallback_collection.sh exist in the tree but are not
referenced by any code path; treat them as reference material, not as the
queries actually issued.
MIT licensed. — reportmate.app