Deploying MacWhisper with MDM
MacWhisper reads its MDM configuration from one of two places, in this order:
- Managed preferences (recommended): a configuration profile whose payload domain is
com.goodsnooze.MacWhisper. This is the standard "custom settings" / "application preferences" payload in Jamf, Kandji, Mosyle, Intune and similar. Changes push to every Mac automatically, and the values are read-only for the user. Available from MacWhisper 15.0.1. - A license file at
~/Library/Application Support/MacWhisper/mdmlicense.plist, for MDMs that can only deploy files or scripts.
Both use the same keys. If both are present, the managed preferences win and the file is ignored. Either way the license is validated on launch.
Configuration profile (managed preferences)
Put the keys from the tables below at the top level of a payload with PayloadType com.goodsnooze.MacWhisper. Everything the file supports is supported here too, including the aiServices array. A minimal user-scope profile:
<?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>PayloadContent</key>
<array>
<dict>
<key>PayloadType</key>
<string>com.goodsnooze.MacWhisper</string>
<key>PayloadIdentifier</key>
<string>com.goodsnooze.MacWhisper.settings</string>
<key>PayloadUUID</key>
<string>6F1B2C3D-4E5F-4A6B-8C7D-9E0F1A2B3C4D</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadDisplayName</key>
<string>MacWhisper settings</string>
<key>licenseKey</key>
<string>xxxxxxxxx-xxxxxxxx-xxxxxxx-xxxxxxxx</string>
<key>allowsAppUpdates</key>
<false/>
<key>allowsRemoteTranslation</key>
<true/>
<key>allowsCloudTranscription</key>
<true/>
<key>allowsAddingAIServices</key>
<true/>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>MacWhisper MDM configuration</string>
<key>PayloadIdentifier</key>
<string>com.goodsnooze.MacWhisper.mdm</string>
<key>PayloadOrganization</key>
<string>Your organisation</string>
<key>PayloadScope</key>
<string>User</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>0A1B2C3D-4E5F-4A6B-8C7D-9E0F1A2B3C4E</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
Most MDMs will generate this for you if you upload a plain plist containing just the MacWhisper keys and point it at the com.goodsnooze.MacWhisper domain.
Checking that it arrived
Open MacWhisper > Settings > MDM. The "Loaded From" row shows where the active configuration came from:
- Managed preferences (configuration profile): the profile is installed and its values are enforced. This is what you want.
- App preferences (not managed, users can change it): the values reached the app's preference domain but not as a managed profile, for example from a "set once" payload or
defaults write. The configuration works, but users can change it. - mdmlicense.plist in Application Support: no profile was found; the file method is in use.
License file
If a user has a MacWhisper license file at the following location it will be read on launch (unless a configuration profile is present):
~/Library/Application\ Support/MacWhisper/mdmlicense.plist
Here is a complete mdmlicense.plist example file:
<?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>licenseKey</key>
<string>xxxxxxxxx-xxxxxxxx-xxxxxxx-xxxxxxxx</string>
<key>allowsRemoteTranslation</key>
<true/>
<key>allowsCloudTranscription</key>
<true/>
<key>allowsAddingAIServices</key>
<true/>
<key>allowsAppUpdates</key>
<true/>
<!-- AI Services Configuration (optional, available from MacWhisper v12.14+) -->
<!-- MDM-configured AI services appear as "MDM Managed" and cannot be edited/deleted by users -->
<key>aiServices</key>
<array>
<!-- OpenAI: ChatGPT models for AI Assistant -->
<!-- Required: type, uniqueId, model, apiKey -->
<dict>
<key>type</key>
<string>openAI</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440001</string>
<key>model</key>
<string>gpt-4o-mini</string>
<key>apiKey</key>
<string>sk-your-openai-api-key-here</string>
</dict>
<!-- Anthropic: Claude models for AI Assistant -->
<!-- Required: type, uniqueId, model, apiKey -->
<dict>
<key>type</key>
<string>anthropic</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440002</string>
<key>model</key>
<string>claude-3-5-sonnet-latest</string>
<key>apiKey</key>
<string>sk-ant-your-anthropic-api-key-here</string>
</dict>
<!-- Azure OpenAI Service: Microsoft-hosted OpenAI models -->
<!-- Required: type, uniqueId, deploymentURL, apiVersion, apiKey -->
<dict>
<key>type</key>
<string>azure</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440000</string>
<key>deploymentURL</key>
<string>https://mycompany.openai.azure.com/openai/deployments/gpt-4o/chat/completions</string>
<key>apiVersion</key>
<string>2024-02-15-preview</string>
<key>apiKey</key>
<string>your-azure-api-key-here</string>
</dict>
<!-- Groq -->
<!-- Required: type, uniqueId, model, apiKey -->
<dict>
<key>type</key>
<string>groq</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440004</string>
<key>model</key>
<string>llama-3.3-70b-versatile</string>
<key>apiKey</key>
<string>gsk_your-groq-api-key-here</string>
</dict>
<!-- OpenRouter -->
<!-- Required: type, uniqueId, model, apiKey -->
<dict>
<key>type</key>
<string>openRouter</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440005</string>
<key>model</key>
<string>meta-llama/llama-3.1-70b-instruct</string>
<key>apiKey</key>
<string>sk-or-your-openrouter-api-key-here</string>
</dict>
<!-- xAI: Grok models -->
<!-- Required: type, uniqueId, model, apiKey -->
<dict>
<key>type</key>
<string>xAI</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440006</string>
<key>model</key>
<string>grok-beta</string>
<key>apiKey</key>
<string>xai-your-xai-api-key-here</string>
</dict>
<!-- Deepseek -->
<!-- Required: type, uniqueId, model, apiKey -->
<dict>
<key>type</key>
<string>deepseek</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440007</string>
<key>model</key>
<string>deepseek-chat</string>
<key>apiKey</key>
<string>sk-your-deepseek-api-key-here</string>
</dict>
<!-- Google Gemini -->
<!-- Required: type, uniqueId, model, apiKey -->
<dict>
<key>type</key>
<string>gemini</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440008</string>
<key>model</key>
<string>gemini-1.5-flash</string>
<key>apiKey</key>
<string>your-gemini-api-key-here</string>
</dict>
<!-- Ollama: Self-hosted open models -->
<!-- Required: type, uniqueId, baseURL, model -->
<!-- Note: No apiKey needed for local deployment -->
<dict>
<key>type</key>
<string>ollama</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440003</string>
<key>baseURL</key>
<string>http://localhost:11434</string>
<key>model</key>
<string>llama3.2</string>
</dict>
<!-- LMStudio: Self-hosted models via LMStudio app -->
<!-- Required: type, uniqueId, baseURL, model -->
<!-- Note: No apiKey needed for local deployment -->
<dict>
<key>type</key>
<string>lmstudio</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440009</string>
<key>baseURL</key>
<string>http://localhost:1234/v1</string>
<key>model</key>
<string>local-model</string>
</dict>
<!-- Custom: Any OpenAI-compatible API endpoint -->
<!-- Required: type, uniqueId, name, baseURL, model -->
<!-- Optional: apiKey (only if endpoint requires authentication) -->
<dict>
<key>type</key>
<string>custom</string>
<key>uniqueId</key>
<string>550e8400-e29b-41d4-a716-446655440010</string>
<key>name</key>
<string>Corporate LLM Server</string>
<key>baseURL</key>
<string>https://llm.company.com/v1</string>
<key>model</key>
<string>company-llm-model</string>
<key>apiKey</key>
<string>custom-api-key-here</string>
</dict>
</array>
</dict>
</plist>
Fields listed in the plist will be hidden from configuration within the app (i.e. the corresponding Settings toggle will not be shown). Setting a field to false disables the feature entirely. Omitting a key makes that feature user-configurable.
Required*
| key | Description | value |
| licenseKey | The license key associated with your MDM purchase | String |
Functionality
| allowsCloudTranscription | Allow users to use cloud transcription services such as OpenAI, ElevenLabs and Deepgram | Bool |
| allowsAddingAIServices | Allow users to setup AI Services | Bool |
| allowsRemoteTranslation | Allow users to use remote translation services such as DeepL. Does not currently disable use of Apple's Translate API. | Bool |
| allowsAppUpdates | Whether MacWhisper may check for and offer updates. Set to false on Macs where users cannot install updates themselves (for example non-admin users): the update checker is never started, and every "Check for Updates" button, the automatic-update setting and the "Update Available" sidebar button are hidden. Omit or set to true to keep updates on. With updates off, you are responsible for rolling out new versions through your MDM. Available from MacWhisper 15.0.1. |
Bool |
| allowAnalytics | Whether the app may send anonymous usage analytics. Defaults to true. |
Bool |
MacWhisper uses Sparkle for updates, and Sparkle reads its own SUEnableAutomaticChecks and SUAutomaticallyUpdate keys from the same com.goodsnooze.MacWhisper domain. Those only control Sparkle's scheduled check; MacWhisper's own update buttons are not affected by them. Use allowsAppUpdates instead, which covers everything.
Features
| playSoundOnCompleteTranscription | Whether to play a sound when a transcription completes | Bool |
| shouldShowTranscriptWithSentences | Show the transcript split up by sentences | Bool |
| showTimestampInSegment | Show timestamps in the segment view | Bool |
| showTimestampMilliseconds | Show milliseconds in the segment view | Bool |
| shouldAlsoSaveVideoToWhisperFile | Save video files to a .whisper file when saving | Bool |
| enableSpeakerDetection | Enable automatic speaker recognition (with supported models) | Bool |
| removeDuplicatedSegments | Automatically remove duplicated segments | Bool |
| shouldLaunchOnLogin | Will add MacWhisper to the system Login Items | Bool |
| aiServices | Allows preconfigured AI Services to be added. See the plist example above. | Array |
If you are interested in deploying MacWhisper in your organisation and you have more questions or features you would want to configure, please reach out to support@macwhisper.com and we'd be happy to see what we can do!