Skip to main content

When to use this

Run this cleanup if your fleet was previously deployed with the script-based Detect path (an MDM Script + the runlayer-scan PPPC profile) and you are migrating to the macOS .pkg flow (see the per-MDM guides linked from Deploy AI Watch). The two paths use different binary identifiers, paths, and PPPC pins — leaving the old artifacts in place causes:
  • Duplicate scans (per-user com.runlayer.scan LaunchAgent + system-wide com.runlayer.aiwatch LaunchAgent both fire).
  • Dangling TCC grants for /usr/local/bin/runlayer-scan that survive even after the script is unscoped.
  • Confusing log output split across /var/log/runlayer/ai_watch_detect.log (old) and the new macOS unified log under process == "aiwatch".
The legacy script was generated by the dashboard (Settings → Shadow MCPs → Detect → Configure) and pasted into your MDM. The dashboard no longer offers it; this page is the only remaining reference. It ran as root on every MDM and installed per signed-in user. Workspace ONE and Intune fleets never had the script flow and need none of this. AI Watch 0.31.14 or newer retires the on-device agent for you: the .pkg preinstall and the uninstall package both boot out every user’s com.runlayer.scan LaunchAgent and remove its plist and the runlayer-scan wrapper. What remains for you is the MDM side, the legacy org API key in Runlayer, and optional user-space tidy-up.
This page cleans up the legacy script-based Detect rollout. To remove the current AI Watch package itself, use Remove AI Watch.

What gets left behind

The script-based deployment installs and configures the following on each enrolled device. Removed by says who cleans it up. /var/log/runlayer/ is shared with the Enforce hook and sync MDM scripts; only ai_watch_detect.log belongs to the legacy Detect rollout.

Order of operations

  1. Delete the legacy MDM artifacts (Script + old PPPC profile) so devices stop receiving the script-based deployment. On Iru/Kandji delete the Custom Script library item first: its Audit Script reinstalls the agent on every run until it is gone.
  2. Deploy the .pkg (0.31.14 or newer) via the guide for your MDM platform — see Deploy AI Watch. The installer retires the legacy agent and wrapper on every device it reaches. Wait one MDM check-in cycle after step 1 so no device gets the legacy script re-pushed after the package lands.
  3. Revoke the legacy org API key in Settings → Organization API keys. Every legacy device stored this key; revoking it is what ends access, whether or not a given device is ever cleaned.
  4. Optional: tidy user space with the script below. It removes the uv-installed CLI, its shim, the stored key entry, and the old logs, and also covers devices still on a .pkg older than 0.31.14.
  5. Verify with the MDM verification script.

MDM-side cleanup

For each MDM, remove or unscope the two script-based artifacts. Names below match the artifacts suggested in the original setup guides; yours may differ. The PPPC profile shows up in every MDM under its display name Runlayer AI Watch - Full Disk Access (identifier com.runlayer.scan.pppc).
  1. Computers → Policies → open the “Deploy AI Watch Detect” Policy (earliest adopters: “Deploy Runlayer Detect”) → set Scope to none, then delete it. Its trigger was Recurring Check-in or Login with frequency Ongoing, so an unscoped-but-present policy keeps logging failures once the script is gone.
  2. Settings → Computer Management → Scripts → delete the “AI Watch Detect” Script (“Runlayer Detect” for earliest adopters).
  3. Computers → Configuration Profiles → delete “Runlayer AI Watch - Full Disk Access” (com.runlayer.scan.pppc).
To run the tidy script, create a Policy with the script as a payload, trigger Login + Recurring Check-in, frequency Once per computer. To find stragglers, paste the audit variant of the verification script into an Extension Attribute and build a Smart Group on a non-zero result. Leave EXPECT_TIDY=0 until the tidy Policy has run, or the group targets every legacy device.

Per-device tidy script

Optional. Push it as a one-time root Custom Script to devices that previously ran the script-based deployment. It removes what the .pkg leaves alone — the uv-installed Runlayer CLI, its shim, the stored ai_watch_mdm key entry, and the old logs — and also retires the agent and wrapper on devices still running a .pkg older than 0.31.14. It walks every home under /Users, so it works at the login window and on shared Macs. It is idempotent, a no-op on devices that never had the old deployment, and always exits 0. The key entry is removed under every host stored in ~/.runlayer/config.yaml. The name ai_watch_mdm was only ever written by the legacy script, so there is no tenant URL to fill in.
The script intentionally leaves the following in place:
  • uv itself (/usr/local/bin/uv, /usr/local/bin/uvx) and its download cache ~/.cache/uv — general-purpose tooling that may be in use for other workflows. Only the runlayer uv-tool install is removed.
  • ~/.runlayer/config.yaml — only the org_api_keys.ai_watch_mdm entry for your host is removed. Other host entries and any personal runlayer login credentials are kept. The file is not deleted, even if it ends up empty.
  • Other files in /var/log/runlayer/ — the Enforce hook and sync MDM scripts log there too. Only ai_watch_detect.log is removed; the directory goes only if it is empty afterwards.
  • OS Keychain entries — the script-based deployment never wrote to the keychain. Any runlayer keychain entries belong to an interactive runlayer login session and are left untouched.

Verification

Audit variant (exit 1 on leftovers)

Push this as a root Custom Script after the .pkg has rolled out. It checks every home under /Users, prints one line per check, and exits 0 when the agent, its plist, and the wrapper are gone and 1 when any is left, so your MDM’s script status matches reality. Use it as the Audit Script on Iru/Kandji, as an Extension Attribute on Jamf Pro, and as a plain one-time script elsewhere. The checks come in two groups. Agent checks (plist, loaded agent, wrapper) are what the .pkg guarantees and always count. User-space checks (uv tool, stored key entry) are only cleared by the tidy script, so by default they print as NOTE and do not fail the audit. Once you have deployed the tidy script, set EXPECT_TIDY=1 at the top so they count too; that is what makes an Iru Audit + Remediation pairing retry the tidy script.
On Jamf Pro, wrap the script so the Extension Attribute reports <result> with the exit code, and build a Smart Group on a non-zero value to re-target stragglers with the tidy script.

Spot-check a test device

After the .pkg is deployed, run these in Terminal as the signed-in user (not from MDM: id -u would be root’s) to confirm there is exactly one Runlayer scan agent. Every line exits 0; read the printed message, not the exit status.
A clean fleet shows TCC entries only for com.runlayer.aiwatch. Empty output is also clean: it means no TCC decision was logged in the last hour. Any remaining com.runlayer.scan entry means the device still has the old PPPC profile or wrapper; re-run the audit script against it.

Rollback

If you need to revert to the script-based deployment temporarily, re-scope the original Script and PPPC profile in your MDM; the legacy script reinstalls the agent and wrapper on its next run. The .pkg and the old wrapper can coexist for short periods (they use distinct identifiers and paths), but scheduled scans then run twice per cycle, and the next .pkg install or self-update retires the legacy agent again — use only as a short-term safety net during migration.