> ## Documentation Index
> Fetch the complete documentation index at: https://docs.velatir.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Download and Install

> Install Velatir for Desktop on a single Windows or macOS device in a few minutes

export const DesktopInstallGenerator = () => {
  const [ingestKey, setIngestKey] = useState("");
  const [os, setOs] = useState("windows");
  const [arch, setArch] = useState("x64");
  const [copied, setCopied] = useState("");
  const cleanArg = value => value.trim().replace(/"/g, "");
  const typedKey = cleanArg(ingestKey);
  const hasKey = typedKey.length > 0;
  const key = typedKey || "vltr_ingest_yourIngestKeyHere";
  const isWindows = os === "windows";
  const file = isWindows ? `Velatir-Bootstrap-${arch}.msi` : `Velatir-Bootstrap-macos-${arch}.pkg`;
  const downloadUrl = isWindows ? `https://releases.velatir.com/velatir-desktop/windows-${arch}/latest/${file}` : `https://releases.velatir.com/velatir-desktop/macos-${arch}/latest/${file}`;
  const command = isWindows ? `msiexec /i ${file} INGEST_KEY="${key}" /qn` : `sudo installer -pkg ${file} -target /`;
  const intuneArgs = `/qn INGEST_KEY="${key}"`;
  const setKeyCommand = `sudo velatir set-api-key --key ${key}`;
  const archOptions = isWindows ? [{
    value: "x64",
    label: "x64"
  }, {
    value: "arm64",
    label: "arm64"
  }] : [{
    value: "arm64",
    label: "Apple Silicon"
  }, {
    value: "x64",
    label: "Intel"
  }];
  const selectOs = value => {
    setOs(value);
    setArch(value === "windows" ? "x64" : "arm64");
  };
  const copy = async (text, which) => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(which);
      setTimeout(() => setCopied(""), 2000);
    } catch (e) {}
  };
  const escapeXml = value => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
  const downloadText = (content, filename, mime) => {
    const blob = new Blob([content], {
      type: mime
    });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  };
  const apiKeyMobileconfig = () => `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
    <key>PayloadIdentifier</key>
    <string>com.velatir.desktopapp.mdm</string>
    <key>PayloadUUID</key>
    <string>6F2A8B14-9C3E-4D71-A5B8-1E7C4D9F2A60</string>
    <key>PayloadDisplayName</key>
    <string>Velatir Desktop Agent</string>
    <key>PayloadDescription</key>
    <string>Provisions the Velatir agent's ingest key.</string>
    <key>PayloadOrganization</key>
    <string>Velatir</string>
    <key>PayloadScope</key>
    <string>System</string>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadType</key>
            <string>com.apple.ManagedClient.preferences</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>PayloadIdentifier</key>
            <string>com.velatir.desktopapp.mdm.preferences</string>
            <key>PayloadUUID</key>
            <string>6F2A8B14-9C3E-4D71-A5B8-1E7C4D9F2A61</string>
            <key>PayloadDisplayName</key>
            <string>Velatir Agent Configuration</string>
            <key>PayloadContent</key>
            <dict>
                <key>com.velatir.agent</key>
                <dict>
                    <key>Forced</key>
                    <array>
                        <dict>
                            <key>mcx_preference_settings</key>
                            <dict>
                                <key>ApiKey</key>
                                <string>${escapeXml(key)}</string>
                            </dict>
                        </dict>
                    </array>
                </dict>
            </dict>
        </dict>
    </array>
</dict>
</plist>
`;
  const loginItemsMobileconfig = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
    <key>PayloadIdentifier</key>
    <string>com.velatir.desktopapp.loginitems</string>
    <key>PayloadUUID</key>
    <string>3C9E7A12-8B4F-4D6A-9E21-5F80C4B7A301</string>
    <key>PayloadDisplayName</key>
    <string>Velatir Background Items</string>
    <key>PayloadOrganization</key>
    <string>Velatir</string>
    <key>PayloadScope</key>
    <string>System</string>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadType</key>
            <string>com.apple.servicemanagement</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>PayloadIdentifier</key>
            <string>com.velatir.desktopapp.loginitems.rules</string>
            <key>PayloadUUID</key>
            <string>3C9E7A12-8B4F-4D6A-9E21-5F80C4B7A302</string>
            <key>PayloadDisplayName</key>
            <string>Velatir Managed Login Items</string>
            <key>Rules</key>
            <array>
                <dict>
                    <key>RuleType</key>
                    <string>TeamIdentifier</string>
                    <key>RuleValue</key>
                    <string>AA7QLU3S4R</string>
                    <key>Comment</key>
                    <string>Velatir agent and host background items</string>
                </dict>
            </array>
        </dict>
    </array>
</dict>
</plist>
`;
  const notificationsMobileconfig = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
    <key>PayloadIdentifier</key>
    <string>com.velatir.desktopapp.notifications</string>
    <key>PayloadUUID</key>
    <string>4D0F8B23-9C5A-4E7B-A032-6A91D5C8B401</string>
    <key>PayloadDisplayName</key>
    <string>Velatir Notifications</string>
    <key>PayloadOrganization</key>
    <string>Velatir</string>
    <key>PayloadScope</key>
    <string>System</string>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadType</key>
            <string>com.apple.notificationsettings</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>PayloadIdentifier</key>
            <string>com.velatir.desktopapp.notifications.settings</string>
            <key>PayloadUUID</key>
            <string>4D0F8B23-9C5A-4E7B-A032-6A91D5C8B402</string>
            <key>PayloadDisplayName</key>
            <string>Velatir Notification Settings</string>
            <key>NotificationSettings</key>
            <array>
                <dict>
                    <key>BundleIdentifier</key>
                    <string>com.velatir.desktopapp</string>
                    <key>NotificationsEnabled</key>
                    <true/>
                    <key>AlertType</key>
                    <integer>2</integer>
                    <key>ShowInNotificationCenter</key>
                    <true/>
                    <key>ShowInLockScreen</key>
                    <true/>
                    <key>BadgesEnabled</key>
                    <true/>
                    <key>SoundsEnabled</key>
                    <true/>
                    <key>CriticalAlertEnabled</key>
                    <false/>
                </dict>
            </array>
        </dict>
    </array>
</dict>
</plist>
`;
  const labelStyle = {
    display: "block",
    fontWeight: 600,
    fontSize: "14px",
    marginBottom: "2px"
  };
  const inputStyle = {
    width: "100%",
    boxSizing: "border-box",
    padding: "8px 12px",
    border: "1px solid rgba(128,128,128,0.4)",
    borderRadius: "8px",
    background: "transparent",
    color: "inherit",
    fontSize: "14px",
    marginTop: "4px"
  };
  const toggleButton = active => ({
    padding: "8px 16px",
    borderRadius: "8px",
    border: active ? "1px solid #F74F4F" : "1px solid rgba(128,128,128,0.4)",
    background: active ? "#F74F4F" : "transparent",
    color: active ? "#fff" : "inherit",
    fontWeight: 600,
    fontSize: "14px",
    cursor: "pointer"
  });
  const codeBox = {
    display: "block",
    width: "100%",
    boxSizing: "border-box",
    padding: "12px 14px",
    border: "1px solid rgba(128,128,128,0.3)",
    borderRadius: "8px",
    background: "rgba(128,128,128,0.08)",
    fontFamily: "monospace",
    fontSize: "13px",
    whiteSpace: "pre-wrap",
    wordBreak: "break-all",
    margin: 0
  };
  const copyButton = {
    padding: "6px 14px",
    borderRadius: "8px",
    border: "1px solid #F74F4F",
    background: "transparent",
    color: "#F74F4F",
    fontWeight: 600,
    fontSize: "13px",
    cursor: "pointer",
    marginTop: "8px"
  };
  const filledButton = enabled => ({
    padding: "6px 14px",
    borderRadius: "8px",
    border: "none",
    background: "#F74F4F",
    color: "#fff",
    fontWeight: 600,
    fontSize: "13px",
    cursor: enabled ? "pointer" : "not-allowed",
    opacity: enabled ? 1 : 0.5,
    marginTop: "8px"
  });
  const helpText = {
    fontSize: "13px",
    opacity: 0.75,
    margin: "8px 0 0"
  };
  const innerPanel = {
    border: "1px solid rgba(128,128,128,0.3)",
    borderRadius: "10px",
    padding: "14px"
  };
  const fleetKeySection = <div style={innerPanel}>
      <label style={labelStyle}>Ingest key profile</label>
      <p style={{
    ...helpText,
    marginTop: "4px"
  }}>
        Intune: <strong>Devices → Configuration → Create → Templates → Custom</strong>, upload the <code style={{
    fontFamily: "monospace"
  }}>.mobileconfig</code>. Jamf: upload the same file, or Application & Custom Settings → <code style={{
    fontFamily: "monospace"
  }}>ApiKey</code>.
      </p>
      <div style={{
    display: "flex",
    gap: "10px",
    flexWrap: "wrap",
    alignItems: "center"
  }}>
        <button type="button" disabled={!hasKey} onClick={() => downloadText(apiKeyMobileconfig(), "velatir-desktop-agent.mobileconfig", "application/x-apple-aspen-config")} style={filledButton(hasKey)}>
          .mobileconfig
        </button>
      </div>
      {!hasKey && <p style={{
    fontSize: "12px",
    opacity: 0.6,
    margin: "6px 0 0"
  }}>
          Enter an ingest key above to enable these. The key never leaves this browser.
        </p>}
    </div>;
  const quietProfilesSection = <div style={innerPanel}>
      <label style={labelStyle}>Quiet-install profiles</label>
      <p style={{
    ...helpText,
    marginTop: "4px"
  }}>
        Optional. Assign first, same Macs as the package.
      </p>
      <div style={{
    display: "flex",
    gap: "10px",
    flexWrap: "wrap",
    alignItems: "center"
  }}>
        <button type="button" onClick={() => downloadText(loginItemsMobileconfig, "velatir-background-items.mobileconfig", "application/x-apple-aspen-config")} style={copyButton}>
          Background items
        </button>
        <button type="button" onClick={() => downloadText(notificationsMobileconfig, "velatir-notifications.mobileconfig", "application/x-apple-aspen-config")} style={copyButton}>
          Notifications
        </button>
      </div>
    </div>;
  return <div style={{
    border: "1px solid rgba(128,128,128,0.3)",
    borderRadius: "12px",
    padding: "20px",
    margin: "16px 0"
  }}>
      <div style={{
    marginBottom: "14px"
  }}>
        <label style={labelStyle}>Ingest key</label>
        <input type="text" value={ingestKey} onChange={e => setIngestKey(e.target.value)} placeholder="vltr_ingest_..." autoComplete="off" spellCheck={false} style={{
    ...inputStyle,
    fontFamily: "monospace"
  }} />
        <p style={{
    fontSize: "13px",
    opacity: 0.7,
    margin: "6px 0 0"
  }}>
          The ingest key maps each machine's traces to your organisation.
        </p>
      </div>

      <div style={{
    marginBottom: "14px"
  }}>
        <label style={labelStyle}>Platform</label>
        <div style={{
    display: "flex",
    gap: "8px",
    marginTop: "4px"
  }}>
          <button type="button" onClick={() => selectOs("windows")} style={toggleButton(isWindows)}>Windows</button>
          <button type="button" onClick={() => selectOs("macos")} style={toggleButton(!isWindows)}>macOS</button>
        </div>
      </div>

      <div style={{
    marginBottom: "16px"
  }}>
        <label style={labelStyle}>Architecture</label>
        <div style={{
    display: "flex",
    gap: "8px",
    marginTop: "4px"
  }}>
          {archOptions.map(opt => <button key={opt.value} type="button" onClick={() => setArch(opt.value)} style={toggleButton(arch === opt.value)}>
              {opt.label}
            </button>)}
        </div>
      </div>

      <label style={labelStyle}>Install command</label>
      <code style={codeBox}>{command}</code>
      <div style={{
    display: "flex",
    gap: "10px",
    flexWrap: "wrap",
    alignItems: "center"
  }}>
        <button type="button" onClick={() => copy(command, "cmd")} style={copyButton}>
          {copied === "cmd" ? "Copied" : "Copy command"}
        </button>
        <a href={downloadUrl} download style={{
    display: "inline-flex",
    alignItems: "center",
    gap: "7px",
    padding: "7px 16px",
    borderRadius: "8px",
    background: "#F74F4F",
    color: "#fff",
    fontWeight: 600,
    fontSize: "13px",
    textDecoration: "none",
    marginTop: "8px"
  }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <path d="M12 3v12" />
            <path d="M7 11l5 5 5-5" />
            <path d="M5 21h14" />
          </svg>
          Download installer
        </a>
      </div>
      <p style={{
    fontSize: "12px",
    opacity: 0.6,
    marginTop: "6px",
    marginBottom: 0
  }}>{file}</p>

      {isWindows ? <details style={{
    marginTop: "16px"
  }}>
          <summary style={{
    cursor: "pointer",
    fontSize: "14px",
    fontWeight: 600
  }}>Microsoft Intune command-line arguments</summary>
          <p style={{
    fontSize: "13px",
    opacity: 0.7,
    margin: "8px 0"
  }}>
            For an Intune Line-of-business app, upload {file} and paste these into <strong>Command-line arguments</strong>.
          </p>
          <code style={codeBox}>{intuneArgs}</code>
          <button type="button" onClick={() => copy(intuneArgs, "intune")} style={copyButton}>
            {copied === "intune" ? "Copied" : "Copy arguments"}
          </button>
        </details> : <div style={{
    marginTop: "16px"
  }}>
          <div style={innerPanel}>
            <label style={labelStyle}>MDM Deployment</label>
            <p style={{
    ...helpText,
    marginTop: "4px",
    marginBottom: "12px"
  }}>
              The supported fleet path. Download these profiles and assign them with the package.
            </p>
            <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "10px"
  }}>
              {fleetKeySection}
              {quietProfilesSection}
            </div>
          </div>
          <div style={{
    marginTop: "16px"
  }}>
            <label style={labelStyle}>Single machine</label>
            <p style={helpText}>Only if you are not using MDM. After installing, set the key with:</p>
            <code style={{
    ...codeBox,
    marginTop: "8px"
  }}>{setKeyCommand}</code>
            <button type="button" onClick={() => copy(setKeyCommand, "setkey")} style={copyButton}>
              {copied === "setkey" ? "Copied" : "Copy command"}
            </button>
          </div>
        </div>}
    </div>;
};

Velatir for Desktop ships as a small installer. At first run it downloads the rest of the app and then keeps itself up to date, so this is the only step you take on the device.

<Note>
  Rolling out to a fleet? See [Enterprise deployment](/desktop-app/enterprise-deployment) for Microsoft Intune, Jamf Pro, and other MDM platforms.
</Note>

## Build your install command

Enter your ingest key, pick your platform, and copy the command. Generate a key on the **Setup** tab of the [Velatir dashboard](https://app.velatir.com).

<DesktopInstallGenerator />

## Requirements

| Requirement      | Detail                                                                             |
| ---------------- | ---------------------------------------------------------------------------------- |
| Operating system | Windows 10 or 11 (x64, arm64), or macOS 13 Ventura or later (Apple Silicon, Intel) |
| Access           | Administrator rights on the device                                                 |
| Network          | Outbound HTTPS to `api.velatir.com` and Velatir's update storage                   |

## Updates and uninstall

<AccordionGroup>
  <Accordion title="Updates" icon="refresh-cw">
    The agent checks for new versions every four hours and applies them automatically, so there is no update service to manage. On Windows, the background process runs as the `VelatirAgent` service. To apply an update immediately, run `velatir update --apply`. The previous version stays on disk until the new one is confirmed running, so there is no in-between state.
  </Accordion>

  <Accordion title="Uninstall" icon="trash-2">
    **Windows.** Remove from **Settings → Apps → Installed apps**, or run `msiexec /x` with the product code. This removes the agent, the host, and the `VelatirAgent` service.

    If the uninstall is interrupted, your MDM cannot remove the app, or items remain afterwards, see [Uninstall cleanup](/desktop-app/uninstall-cleanup). Devices on a version older than the current installer can also leave artefacts a standard uninstall does not clear.

    **macOS.** Run the bundled uninstaller:

    ```bash theme={null}
    sudo velatir-uninstall
    ```

    It removes the app and the background services. If an older version left a system extension on the device, a restart finishes removing it.

    <Note>
      **Using Firefox?** After uninstalling, the Velatir extension may still appear in Firefox. This is expected — and not something the uninstaller can fix. Unlike Chrome and Edge, which automatically remove an extension that was installed by policy, Firefox leaves a policy-installed extension in place (it becomes inactive once Velatir is gone). To remove it, open Firefox → **Menu → Add-ons and themes → Extensions**, click the **⋯** next to Velatir, and choose **Remove**. If **Remove** is greyed out, restart Firefox first so it picks up the change.
    </Note>
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Enterprise deployment" icon="building" href="/desktop-app/enterprise-deployment">
    Roll out silently across your fleet with Intune, Jamf, or any MDM.
  </Card>

  <Card title="Permissions" icon="shield-check" href="/desktop-app/permissions">
    What the installer asks for, and why.
  </Card>

  <Card title="Troubleshooting" icon="life-buoy" href="/desktop-app/troubleshooting">
    Resolve common install and first-run issues.
  </Card>

  <Card title="How it works" icon="layers" href="/desktop-app/how-it-works">
    The architecture behind the app.
  </Card>
</CardGroup>
