| name | macos-enterprise-app-cleanup |
| description | Clean up macOS enterprise, MDM, VPN, EDR, security, and company-internal software remnants after a user leaves a company. Use this skill whenever the user asks to remove or audit corporate software, agents, proxies, VPNs, endpoint security, launch agents, system extensions, login/background items, package receipts, or company-branded leftovers on a Mac. Especially use it for Meituan/Sankuai, MOA, 文枢/wenshu, Kaspersky, Cisco AnyConnect, wsAssistant, EDR/MEDR, DNS proxy, Network Extension, Socket Filter, or similar enterprise tools. |
macOS Enterprise App Cleanup
This skill turns a one-off cleanup into a careful, repeatable macOS workflow. The goal is to remove confirmed company-related software and configuration while avoiding accidental deletion of unrelated tools.
Core Principles
- Start with read-only discovery. Do not delete anything until the candidate list is understood.
- Treat uncertainty as a stop point. If a path, bundle id, app, or vendor is not clearly related to the user's target company, ask before deleting.
- Prefer official uninstallers for security, VPN, EDR, and enterprise apps. They usually unregister services, filters, receipts, firewall rules, and system extensions more cleanly than manual deletion.
- Use exact matches and scoped paths. Avoid broad
rm -rf or deleting every file containing a generic term like vpn, agent, assistant, or security.
- Expect macOS protection boundaries. Root can remove many files, but SIP, TCC, System Extensions, and Background Task Management may require a reboot, System Settings action, or supported system command.
- Report residual state precisely. Distinguish active processes, deleted files, stale background-item cache, and system extensions waiting to uninstall on reboot.
When To Use
Use this workflow when a user says things like:
- "我离职了,帮我删掉公司软件/配置"
- "清理美团/三快/MOA/文枢/Kaspersky/Cisco"
- "Mac 上还有代理/VPN/EDR/安全软件残留"
- "系统设置里还有某个后台项目/系统扩展"
- "删除企业软件后还弹系统扩展/Socket Filter/Network Extension 提示"
Known examples from the source cleanup:
- Meituan/Sankuai:
meituan, sankuai, MOA, moadeploy, moatray, moalogin, wenshu, 文枢, .MTEDR, MEDR, syswframework, EncryptionBox, cn.neixin.pc
- Kaspersky:
Kaspersky Anti-Virus For Mac.app, Kaspersky Lab, klnagent, com.kaspersky.*
- Cisco AnyConnect:
/opt/cisco/anyconnect, com.cisco.anyconnect.*, Cisco AnyConnect Socket Filter
- Sankuai wsAssistant:
/Library/Application Support/wsAssistant, logs calling cryptbox.sankuai.com or sec_shared_pid_wenshu
Workflow
1. Establish Scope
Ask for or infer the company/product names and any known apps from the user. If the user says "delete all related", still separate:
- Clearly related items
- Unclear but suspicious items
- Unrelated third-party products
Do not assume a vendor is company-related merely because it appeared during cleanup. For example, Cisco AnyConnect is Cisco software; only delete it once the user confirms or the configuration clearly ties it to the target company.
2. Read-Only Discovery
Use parallel shell reads where possible. Search applications, launchd jobs, packages, processes, system extensions, background items, profiles, and support folders.
Useful discovery commands:
find /Applications /Users/"$USER"/Applications -maxdepth 2 \
\( -iname '*meituan*' -o -iname '*sankuai*' -o -iname '*kaspersky*' -o -iname '*moa*' -o -iname '*wenshu*' -o -name '*文枢*' \) -print
pkgutil --pkgs | rg -i 'meituan|sankuai|kaspersky|installmoa|moadeploy|EncryptionBox|anyconnect|cisco'
launchctl list | rg -i 'meituan|sankuai|kaspersky|moa|wenshu|medr|anyconnect|cisco'
systemextensionsctl list | rg -i 'meituan|sankuai|kaspersky|moa|wenshu|medr|anyconnect|cisco'
ps aux | rg -i 'meituan|sankuai|kaspersky|moa|wslaunch|wenshu|文枢|medr|mtdr|syswframework|neixin|anyconnect|cisco|wsAssistant'
sfltool dumpbtm | rg -i 'meituan|sankuai|kaspersky|moa|wenshu|medr|anyconnect|cisco|wsAssistant'
profiles list -all 2>&1 | rg -i -C 4 'meituan|sankuai|kaspersky|moa|wenshu|medr|anyconnect|cisco|vpn'
Search common file locations:
find \
/Library/Application\ Support \
"$HOME/Library/Application Support" \
/Library/Preferences \
"$HOME/Library/Preferences" \
/Library/LaunchAgents \
/Library/LaunchDaemons \
"$HOME/Library/LaunchAgents" \
"$HOME/Library/Caches" \
"$HOME/Library/WebKit" \
"$HOME/Library/Saved Application State" \
"$HOME/Library/Group Containers" \
-maxdepth 4 \
\( -iname '*meituan*' -o -iname '*sankuai*' -o -iname '*kaspersky*' -o -iname '*moa*' -o -iname '*wenshu*' -o -name '*文枢*' -o -iname '*MTEDR*' -o -iname '*MEDR*' -o -iname '*neixin*' -o -iname '*syswframework*' \) -print 2>/dev/null
If a generic-looking folder appears, verify content before deleting:
rg -a -i -n -m 20 'meituan|sankuai|wenshu|文枢|moa|medr|neixin|daxiang|ssosv|cryptbox\.sankuai' /path/to/candidate 2>/dev/null
3. Classify Candidates
Create a short deletion plan before acting:
- Apps:
/Applications/MOA.app, /Applications/wenshu.app, /Applications/.MTEDR.app, /Applications/Kaspersky Anti-Virus For Mac.app
- Support dirs:
/Library/Application Support/MOADeploy, /Library/Application Support/.MTEDR, /Library/Application Support/Kaspersky Lab, /Library/Application Support/wsAssistant
- Launch items:
com.meituan.*, com.kaspersky.*, com.cisco.anyconnect.*, com.syswframework.launch.plist
- User data:
~/Library/Application Support/cn.neixin.pc, ~/Library/Preferences/cn.neixin.pc.plist, Kaspersky group containers
- Receipts:
pkgutil --pkgs matches
- System extensions: Meituan network extension, Cisco socket filter, Kaspersky system extension
Ask before deleting any uncertain or unrelated vendor item. If the user confirms "delete all" or specifically names the item, proceed.
4. Use Official Uninstallers First
Prefer vendor uninstall scripts/apps when present:
/bin/sh "/Library/Application Support/Kaspersky Lab/KAV/Binaries/UninstallScript"
/bin/sh "/Library/Application Support/Kaspersky Lab/klnagent/Binaries/UninstallScript"
/bin/sh "/opt/cisco/anyconnect/bin/anyconnect_uninstall.sh"
/bin/bash "/opt/cisco/anyconnect/bin/vpn_uninstall.sh"
Run these with administrator privileges. In Codex Desktop on macOS, osascript can request an admin prompt:
osascript -e 'do shell script "id -u" with administrator privileges'
If the test returns 0, the admin path is working.
5. Stop Services And Processes
Unload launchd jobs before deleting files:
launchctl bootout system /Library/LaunchDaemons/com.example.daemon.plist
launchctl bootout "gui/$(id -u "$USER")" /Library/LaunchAgents/com.example.agent.plist
launchctl disable system/com.example.daemon
launchctl disable "gui/$(id -u "$USER")/com.example.agent"
Then terminate remaining processes by exact path or exact vendor pattern:
pkill -f '/Applications/MOA.app|/Library/Application Support/MOADeploy|/Applications/wenshu.app|/Applications/.MTEDR.app'
pkill -f '/opt/cisco/anyconnect|Cisco AnyConnect'
sleep 1
pkill -9 -f '/opt/cisco/anyconnect|Cisco AnyConnect'
6. Remove Files, Receipts, And User Data
Remove only confirmed paths. Clear immutable flags first when needed:
chflags -R nouchg,noschg "$path" 2>/dev/null
chmod -R u+w "$path" 2>/dev/null
rm -rf "$path"
Forget package receipts:
pkgutil --pkgs | rg -i 'meituan|sankuai|kaspersky|installmoa|moadeploy|EncryptionBox|anyconnect|cisco' |
while IFS= read -r pkg; do
sudo pkgutil --forget "$pkg"
done
For protected user group containers that return Operation not permitted, inspect xattrs:
ls -laOe@ "$HOME/Library/Group Containers/<container>"
xattr -lr "$HOME/Library/Group Containers/<container>"
If the user owns the folder, removing com.apple.macl and clearing xattrs may allow deletion:
xattr -dr com.apple.macl "$HOME/Library/Group Containers/<container>" 2>/dev/null
xattr -cr "$HOME/Library/Group Containers/<container>" 2>/dev/null
rm -rf "$HOME/Library/Group Containers/<container>"
7. Handle System Extensions
System extensions have special lifecycle behavior.
Check status:
systemextensionsctl list
Try supported cleanup:
systemextensionsctl uninstall TEAMID bundle.id
systemextensionsctl gc
Interpret common states:
activated enabled: still active.
terminated waiting to uninstall on reboot: cleanup succeeded; ask the user to reboot.
- No matching extension after reboot: fully removed.
If systemextensionsctl uninstall says SIP prevents use, do not fight SIP by default. Try systemextensionsctl gc, remove the owning app and launchd jobs, reboot, then recheck. Only discuss disabling SIP if the user explicitly wants a forceful Recovery-mode cleanup and understands the risk.
8. Clear Background Item Cache
After deleting launchd files, System Settings may still show stale "Login Items & Extensions" entries.
First verify the referenced executable/plist is gone. Then clear Background Task Management cache:
sfltool dumpbtm | rg -i 'cisco|anyconnect|meituan|sankuai|kaspersky|moa|wenshu|medr'
sfltool resetbtm
sfltool dumpbtm | rg -i 'cisco|anyconnect|meituan|sankuai|kaspersky|moa|wenshu|medr'
Use resetbtm only after explaining that it resets the background-task management database and may cause legitimate background items to reappear as newly managed by macOS.
9. Final Verification
Run a final no-residue check:
find /Applications /Users/"$USER"/Applications /opt /Library/Application\ Support /Library/LaunchAgents /Library/LaunchDaemons "$HOME/Library/Application Support" "$HOME/Library/Preferences" "$HOME/Library/Caches" "$HOME/Library/Saved Application State" -maxdepth 4 \
\( -iname '*meituan*' -o -iname '*sankuai*' -o -iname '*kaspersky*' -o -iname '*moa*' -o -iname '*wenshu*' -o -name '*文枢*' -o -iname '*MTEDR*' -o -iname '*MEDR*' -o -iname '*neixin*' -o -iname '*syswframework*' -o -iname '*anyconnect*' -o -iname '*cisco*' -o -iname '*wsAssistant*' \) -print 2>/dev/null
ps -axo pid,ppid,user,command | awk 'BEGIN{IGNORECASE=1} /\/opt\/cisco|Cisco AnyConnect|vpnagentd|wsAssistant|meituan|sankuai|wenshu|MOA|Kaspersky|MEDR|MTEDR/ && $0 !~ /awk|ps -axo|zsh -c|zsh -lc/ {print}'
pkgutil --pkgs | rg -i 'meituan|sankuai|kaspersky|installmoa|moadeploy|EncryptionBox|neixin|anyconnect|cisco'
systemextensionsctl list | rg -i 'meituan|sankuai|kaspersky|moa|wenshu|medr|anyconnect|cisco'
sfltool dumpbtm | rg -i 'meituan|sankuai|kaspersky|moa|wenshu|medr|anyconnect|cisco|wsAssistant'
Be careful not to count the verification command itself as a matching process. Use filters or rerun process checks after find completes.
Reporting Format
Keep the final report concise:
- State what was removed.
- State what checks are clean.
- State any remaining macOS-managed status, such as "waiting to uninstall on reboot".
- Mention if a reboot is needed.
- Mention any intentionally preserved unrelated software.
Example:
已删除 MOA、文枢、Kaspersky、Cisco AnyConnect、wsAssistant 及相关启动项、进程、包收据、用户配置和后台项目缓存。
复查结果:无相关应用、LaunchAgent/LaunchDaemon、进程、pkg 收据或系统扩展。systemextensionsctl 只剩 OBS 虚拟摄像头。
Safety Notes
- Do not delete unrelated VPNs, proxies, EDRs, or security apps unless the user confirms them. Examples: Cisco AnyConnect, GlobalProtect, OpenVPN, Clash, Sangfor, Avast, OBS system extension.
- Do not edit
/Library/SystemExtensions/db.plist or protected network extension plists directly. SIP may block root writes, and manual edits can corrupt system extension state.
- Do not use destructive global commands such as
git reset, broad rm -rf /Library/*agent*, or deleting all VPN/network files.
- If a command requires administrator privileges, tell the user what category of change it will make before triggering the prompt.