> For the complete documentation index, see [llms.txt](https://docs.we360.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.we360.ai/deployment-and-it-ops/deploy/agent-deployment-hub/mass-deployment/macos-mdm/microsoft-intune-macos.md).

# Microsoft Intune (macOS)

Deploy the We360.ai MyZen macOS agent with Microsoft Intune, including the shell-script method for Stealth.

Intune manages macOS through a combination of the **MDM channel** (configuration profiles) and the **Microsoft Intune management agent for macOS** (PKG app installs and shell scripts). Both are needed for a complete MyZen deployment.

{% hint style="info" %}
For the **Windows** agent via Intune (MSI → `.intunewin`), see [Microsoft Intune (Windows)](/deployment-and-it-ops/deploy/agent-deployment-hub/mass-deployment/microsoft-intune.md).
{% endhint %}

**Prerequisites**

* macOS devices enrolled in Intune (Apple Business Manager / Automated Device Enrollment, or Company Portal enrollment).
* A valid **Apple Push Notification (APNs)** certificate in **Tenant administration > Connectors and tokens > Apple MDM Push certificate** (renew annually).
* The **Microsoft Intune management agent for macOS** version 2308.006 or later. It installs automatically the first time a macOS PKG app or shell script policy is assigned to the device.
* The MyZen `.pkg` is well under Intune's 8 GB app size limit.

**Step 1 — Deploy the PPPC Profile (before the PKG)**

**Option A — Upload the pre-built profile (recommended):**

1. Sign in to the **Microsoft Intune admin center** (`intune.microsoft.com`).
2. Navigate to **Devices > macOS > Configuration** and click **Create > New Policy**.
3. Set **Profile type** to **Templates**, select **Custom**, and click **Create**.
4. **Name:** e.g., "ZS App Permissions (PPPC)".
5. On the **Configuration settings** page:
   * **Deployment channel:** **Device channel** — TCC/PPPC payloads must be delivered on the device channel.
   * **Configuration profile file:** upload [`zs-pppc.mobileconfig`](https://github.com/zenstack-we360/documentation/tree/main/docs-we360-ai/it-ops/.gitbook/assets/zs-pppc.mobileconfig).
6. Assign to the target **device groups** and click **Create**.

**Option B — Build it in the Settings Catalog:**

1. Navigate to **Devices > macOS > Configuration > Create > New Policy**.
2. Set **Profile type** to **Settings catalog** and click **Create**.
3. Click **Add settings** and search for **Privacy Preferences Policy Control**, then expand **Services**.
4. Add **Accessibility** and configure the ZS agent entry:
   * **Identifier:** `ai.zs.zs` (Stealth) or `ai.we360.MyZenV2` (Standard)
   * **Identifier Type:** Bundle ID
   * **Code Requirement:** paste the code requirement from [App & Team Identifiers](/deployment-and-it-ops/deploy/agent-deployment-hub/mass-deployment/macos-mdm/macos-mdm.md#app-and-team-identifiers)
   * **Static Code:** false
   * **Allowed:** true
5. Add **AppleEvents** entries for each browser you need URL reading from. Each entry needs both a *source* (the ZS agent identifier and code requirement) and a *receiver* (the browser bundle ID and its code requirement) — see [Supported Browsers for AppleEvents](/deployment-and-it-ops/deploy/agent-deployment-hub/mass-deployment/macos-mdm/macos-mdm.md#supported-browsers-for-appleevents-url-reading) on the parent page.
6. Assign to the target device groups and click **Create**.

{% hint style="warning" %}
**PPPC failures are silent.** Intune will report the profile as successfully applied even when macOS discards an entry because the code requirement doesn't match the app's signature. If Accessibility is still prompting the user after the profile lands, re-extract the code requirement with `codesign -dr -` on an installed endpoint and compare it character-for-character. The AppleEvents entries in the Settings Catalog are fiddly to build by hand — prefer Option A.
{% endhint %}

**Step 2 — Deploy the Background Items Profile**

**Option A — Settings catalog (native):**

1. Navigate to **Devices > macOS > Configuration > Create > New Policy > Settings catalog**.
2. Click **Add settings** and search for **Service Management - Managed Login Items**.
3. Add a rule:
   * **Rule Type:** Team Identifier
   * **Rule Value:** `5KPT5U8WVR`
   * **Team Identifier:** `5KPT5U8WVR` (Intune requires this field even though Apple treats it as optional)
4. Assign to the same device groups and click **Create**.

**Option B — Custom profile:** upload [`zs-background-items.mobileconfig`](https://github.com/zenstack-we360/documentation/tree/main/docs-we360-ai/it-ops/.gitbook/assets/zs-background-items.mobileconfig) using the same **Templates > Custom** flow as Step 1 (Device channel).

**Step 3 — Upload and Deploy the PKG**

1. Navigate to **Apps > All apps > Create**.
2. Under **Select app type**, choose the **macOS** platform and select **macOS app (PKG)** — the *unmanaged* PKG type. Click **Select**.
3. Click **Select app package file** and upload the MyZen `.pkg`. Click **OK**.
4. Fill in **Name**, **Description**, and **Publisher** (Zenstack Private Limited), then click **Next**.
5. **Program** (optional) — you may supply a pre-install script to skip devices that already have the agent:

   ```bash
   #!/bin/bash
   # Exit non-zero to block the install (Intune retries at next check-in)
   if [ -d "/usr/local/zs/zs.app" ]; then
     exit 1   # already installed
   fi
   exit 0
   ```
6. **Requirements** — set the **Minimum Operating System** to the lowest macOS version you support.
7. **Detection rules:**
   * **Ignore app version:** **Yes** (the agent self-updates, so version matching would cause reinstall loops).
   * **Included apps:** add the bundle ID and build number of the app the PKG installs:

     | Variant  | Bundle ID          | Build number source                                                                |
     | -------- | ------------------ | ---------------------------------------------------------------------------------- |
     | Standard | `ai.we360.MyZenV2` | `defaults read /Applications/MyZenV2.app/Contents/Info CFBundleShortVersionString` |
     | Stealth  | `ai.zs.zs`         | `defaults read /usr/local/zs/zs.app/Contents/Info CFBundleShortVersionString`      |
8. Assign the app as **Required** to the target device groups.
9. **Review + create**.

{% hint style="info" %}
**Why the "macOS app (PKG)" type and not "Line-of-business app" (`.intunemac`)?** The unmanaged PKG app type is the only one that supports packages which install outside `/Applications/`, packages containing scripts, and component/non-flat packages. The Stealth build installs to `/usr/local/zs/`, so it requires this app type. The DMG app type does not apply — MyZen ships as a PKG.
{% endhint %}

{% hint style="warning" %}
**Stealth installer filename:** the Stealth PKG's filename encodes your organization's license. Intune stores and delivers the package from its own content cache, and — unlike ManageEngine — there is **no install command you can override** to rename the file back before `installer` runs. Verify on a pilot device that the Stealth agent enrolls into the correct tenant. If it does not, deploy via the **shell script method** below (recommended), or place your stealth config at `/Library/Preferences/zs.json` with a platform script (Step 5) that runs before the app assignment lands.
{% endhint %}

**Alternative to Step 3 — Deploy the Stealth PKG via Intune Shell Script (recommended for Stealth)**

Instead of uploading the PKG as an app, deploy it with an Intune **macOS shell script**. The script downloads the correct architecture's PKG directly from the We360.ai portal and inserts your license key itself, so Intune's content cache and filename handling never come into play.

1. Navigate to **Devices > macOS > Shell scripts** and click **Add**.
2. Paste (or upload as `.sh`) the script below, after replacing `<license-key>` with your organization's stealth license key — the Base64-encoded filename of your stealth PKG as downloaded from the portal, **without** the `.pkg` extension:

   ```bash
   #!/bin/bash
   set -e

   # REQUIRED: your stealth license key — the Base64-encoded installer
   # filename from the We360.ai portal, without the .pkg extension.
   LICENSE_KEY="<license-key>"

   if [ -z "$LICENSE_KEY" ] || [ "$LICENSE_KEY" = "<license-key>" ]; then
       echo "ERROR: LICENSE_KEY is not set. Paste your stealth license key." >&2
       exit 1
   fi

   ARCH="$(uname -m)"
   if [ "$ARCH" = "arm64" ]; then
       PKG_URL="https://portal.we360.ai/static/installers/zs-arm64.pkg"
   else
       PKG_URL="https://portal.we360.ai/static/installers/zs-amd64.pkg"
   fi

   DOWNLOAD_PATH="/tmp/zs-installer.pkg"
   PKG_PATH="/tmp/${LICENSE_KEY}.pkg"

   echo "Detected architecture: $ARCH"

   echo "Downloading installer..."
   if ! curl -fsSL "$PKG_URL" -o "$DOWNLOAD_PATH"; then
       echo "ERROR: Download failed" >&2
       exit 1
   fi

   echo "Renaming installer to insert license key..."
   mv "$DOWNLOAD_PATH" "$PKG_PATH"

   echo "Installing..."
   # ZS_KEY_CONFIG_BASE64_ENCODED doubles up the license insertion (v4.15+
   # agents); the renamed PKG filename covers older installers.
   if ! ZS_KEY_CONFIG_BASE64_ENCODED="$LICENSE_KEY" installer -pkg "$PKG_PATH" -target /; then
       echo "ERROR: Installation failed" >&2
       rm -f "$PKG_PATH"
       exit 1
   fi

   rm -f "$PKG_PATH"
   echo "Install completed successfully"
   exit 0
   ```
3. Configure the script settings:
   * **Run script as signed-in user:** **No** (must run as root).
   * **Hide script notifications on devices:** **Yes**.
   * **Script frequency:** Not configured (run once).
   * **Max number of times to retry if script fails:** 3 times.
4. Assign to the target device groups.

{% hint style="info" %}
The script inserts the license key **twice** for safety: it renames the PKG to `<license-key>.pkg` (the mechanism every agent version understands) and also exports `ZS_KEY_CONFIG_BASE64_ENCODED` (highest-precedence method on v4.15+ agents). See [Stealth License Key Insertion Methods](/deployment-and-it-ops/deploy/agent-deployment-hub/mass-deployment/macos-mdm/macos-mdm.md#stealth-license-key-insertion-methods).

Because a shell-script install bypasses Intune's app model, there is no Intune install/detection reporting — treat the **We360.ai dashboard** as the source of truth, which is already the recommendation for Stealth (see the reporting note above).
{% endhint %}

{% hint style="warning" %}
**Install reporting for Stealth:** Intune detects installs by looking for the bundle IDs listed under **Included apps**. Because the Stealth app lives outside `/Applications/`, install status in Intune may stay **Pending** or report a failure even when the agent installed correctly. Treat the **We360.ai dashboard** as the source of truth for Stealth rollouts, not the Intune app report.
{% endhint %}

**Step 4 — Screen Recording (Optional, User Action)**

Screen Recording cannot be granted by Intune or any other MDM. If your plan uses screenshots, instruct users to approve the prompt and then **logout/login**.

**Step 5 — Shell Scripts (config drop and uninstall)**

Intune has **no Uninstall assignment type for macOS PKG apps**. Removal is done with a shell script:

1. Navigate to **Devices > macOS > Shell scripts** and click **Add**.
2. Upload `remove_myzenv2_Version3.sh` (download it from the We360.ai admin portal).
3. Set **Run script as signed-in user:** **No** (run as root).
4. **Script frequency:** Not configured (run once).
5. Assign to the group of devices you want the agent removed from.

The same mechanism is used to drop `/Library/Preferences/zs.json` if you were supplied a stealth config file.

**Step 6 — Verify Deployment**

1. Navigate to **Devices > macOS > macOS devices**, select a target device, and open **Device configuration** — both the PPPC and Background Items profiles should show **Succeeded**.
2. Open **Managed Apps** — the MyZen app should show **Installed** (see the Stealth reporting caveat above).
3. On the endpoint, confirm the agent is present:

   ```bash
   ls -d /usr/local/zs/zs.app          # Stealth
   ls -d /Applications/MyZenV2.app     # Standard
   launchctl list | grep -i "zs\|MyZen"
   ```
4. Ask the end user to **logout/login** or **restart**.
5. Verify the endpoint appears online in the **We360.ai dashboard** at `portal.we360.ai`.

{% hint style="info" %}
**Agent logs on the endpoint** for troubleshooting Intune-side install failures: `/Library/Logs/Microsoft/Intune/` (management agent), plus MyZen's own install logs at `/tmp/zs-*.log` (Stealth) or `/tmp/MyZenV2-*.log` (Standard).
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.we360.ai/deployment-and-it-ops/deploy/agent-deployment-hub/mass-deployment/macos-mdm/microsoft-intune-macos.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
