Protect your Mac
Inventory
Browse everything Cloak Watch checks on your Mac, from packages, extensions and MCP servers to apps, trust stores, services and your footprint, and what each tab reads.
Inventory lists everything Cloak Watch checks on your Mac, in eleven tabs, with where each item lives and whether anything about it is wrong. Watch builds it by reading files and metadata during each scan. It never runs a package manager, a script, an MCP server or any project code to find out what’s installed. The two exceptions only ask: Safari’s extension list comes from macOS’s plug-in registry, and container images from each running container engine.
- Tabs, with a count each
- By project or All packages, and the filter
- Flagged rows come first
- The open incident for this item
- Read only, nothing was run
Use the Inventory
Section titled “Use the Inventory”- Tabs along the top: Packages, Editor extensions, Browser extensions, AI tools & MCP, Skills, Startup items, Keys & tokens, Apps & tools, Trust stores, Services and Footprint, each with its count. The tabs scroll sideways when the window is narrow. The Home chips open the matching tab.
- Filter (the field at the top right, for example Filter Packages) matches name, path, version, source and the tab’s extra column.
- On Packages, By project groups packages under each project, then Download caches, Homebrew, Installed globally and Other, with counts and how many are malicious or worth a look. Dependencies a project didn’t ask for directly are folded under Show N more dependencies (installed by the ones above); flagged ones are never folded. All packages shows one flat list.
- Click a column header to sort. Flagged rows sort first by default.
- The bar at the bottom counts what’s shown and says Read only, nothing was run, with when Watch last scanned.
Status
Section titled “Status”| Status | Meaning |
|---|---|
| Malicious (red) | An open incident that needs fixing now cites this item. |
| Worth a look (orange) | An open incident that’s worth a look cites this item. |
| — | The incident was marked not a problem, or it’s a Worth a look or Good to know finding about something already here when you started Watch. |
| Blank | Not a known attack, and nothing about it looks unusual. |
The inspector
Section titled “The inspector”Select an item to see:
- its name, version, kind and source;
- the open incident that cites it, if any, with See How to Fix It or Show in Inbox;
- What it is, in a sentence;
- Where: the path, and the project or folder it belongs to;
- Details: Found as (Lockfile, Installed, Global install, Cache or Config), Arrived, Signed by, the tab’s extra field (Scripts, Marketplace, ID, Scope or Runs), SHA-256 where Watch hashed it, and Status;
- Show in Finder and Copy Path.
Arrived and the First seen column come from the file’s modification and change times, not from when Watch first saw it.
Packages
Section titled “Packages”Columns: Package, Version, Status, Ecosystem, Scripts (install scripts it runs), First seen, Project.
| Where | What Watch reads |
|---|---|
| Lockfiles in your code folders | package-lock.json and npm-shrinkwrap.json, pnpm-lock.yaml, yarn.lock (v1 and Berry), bun.lock, poetry.lock, uv.lock, pdm.lock, Pipfile.lock and requirements.txt (exact == pins only), Cargo.lock, go.sum, Gemfile.lock, composer.lock |
| Installed Node packages | Each project’s node_modules, nested and scoped, including pnpm’s layout: name, version and install scripts (preinstall, install, postinstall) with the size of the file a script runs |
| Global Node installs | /opt/homebrew/lib/node_modules, /usr/local/lib/node_modules, nvm, fnm, Volta, ~/.bun/install/global, ~/.npm-global and pnpm’s global folder |
| Python environments | Project venv, .venv, env and .env environments, ~/.virtualenvs, pipenv, Poetry, pyenv, conda (Miniconda, Anaconda, Miniforge, Mambaforge), pipx, uv tools and Pythons, Rye, Hatch, asdf, mise, ~/Library/Python, ~/.local, Homebrew, python.org, Command Line Tools and Xcode Pythons: package folder names, plus every .pth, sitecustomize.py, usercustomize.py and .start file |
| Download caches | npm (~/.npm/_cacache index only, nothing extracted), pnpm stores, Yarn, Bun, uv, pip, Cargo, the Go module cache, gem folders and global Composer |
| Homebrew | Installed formulae and casks with versions, and taps |
| Container images New in 1.2.0 | Images in each running container engine (Docker Desktop, OrbStack, Colima, Rancher Desktop, Podman), with the ecosystem Docker: tags, digests and version settings. See Container images. |
| Other package rows | Registry settings files (.npmrc, .yarnrc.yml, bunfig.toml, pip.conf, Cargo config, .gemrc, uv.toml, pnpm’s rc, /etc/pip.conf, and projects’ pip.conf, uv.toml and requirements*.txt for extra indexes), GitHub Actions workflows (.github/workflows: the actions they use, their triggers, permissions, caches and the hosts they name, for the REPO checks), and whether Docker, OrbStack, Colima, Podman or Rancher Desktop is installed |
Watch reads only the folders you turned on in Settings › General for project files; global installs and caches are read wherever they are. Folders and package names you exclude there are skipped everywhere.
Editor extensions
Section titled “Editor extensions”Columns: Extension, Version, Status, Editor, Marketplace, First seen, Project.
Watch reads each extension’s package.json in the extensions folders of VS Code, VS Code Insiders, Cursor, Windsurf, VSCodium, Kiro, Trae, Positron and Antigravity, and each editor’s extensions.json, which says where an extension came from. Extensions in VS Code count as Marketplace extensions; in the other editors, as Open VSX. The Editor extensions tab also lists editor tasks from projects’ .vscode/tasks.json, Dev Container commands, and JetBrains plugins (from META-INF/plugin.xml in each IDE’s plugins folder) New in 1.2.0. See Extensions.
Browser extensions
Section titled “Browser extensions”Columns: Extension, Version, Status, Browser, First seen, ID.
| Browser | What Watch reads |
|---|---|
| Chrome (and Beta, Canary), Chromium, Brave, Edge, Arc, Vivaldi, Opera, Comet, Dia | Each profile’s extension manifests (Default, Profile N and Guest Profile), and its Secure Preferences, for where each extension came from, whether it’s on and whether Chrome flagged it |
| Firefox | Each profile’s extensions.json, skipping built-in add-ons |
| Safari | Installed Safari extensions, from macOS’s plug-in registry (pluginkit) New in 1.2.0. Which ones are turned on needs Full Disk Access. |
AI tools & MCP
Section titled “AI tools & MCP”Columns: Name, Kind, Status, Source, Runs, Project.
The AI tools & MCP tab.
| What | Where Watch reads it |
|---|---|
| MCP servers | Claude Code (~/.claude.json, plugins), Claude Desktop (claude_desktop_config.json), Cursor (~/.cursor/mcp.json), Windsurf, VS Code (mcp.json, settings.json), Codex (~/.codex/config.toml), Gemini CLI, Kiro, opencode, Zed, OpenClaw, Qwen Code, and the same tools’ project files (.mcp.json, .cursor/mcp.json, .vscode/mcp.json and others) |
| Agent settings and hooks | Claude Code’s ~/.claude/settings.json and settings.local.json (or $CLAUDE_CONFIG_DIR), managed settings, each project’s .claude/settings*.json, and plugin hooks |
| Rules files | CLAUDE.md, CLAUDE.local.md, AGENTS.md, GEMINI.md, .cursorrules, .windsurfrules, .clinerules, .github/copilot-instructions.md, .cursor/rules, and the home-folder versions |
Watch never launches an MCP server to learn about it. For servers that run through npx, uvx, pipx, bunx or docker, it reads the package name from the command. It keeps environment variable names, never their values.
Skills
Section titled “Skills”Columns: Skill, Status, Scope, Source, First seen, Project.
Watch finds SKILL.md files in ~/.claude/skills, Codex, ~/.agents/skills, OpenClaw, Cursor, Gemini and opencode skill folders, Claude Code plugins, and projects’ .claude/skills, .codex/skills, .agents/skills, .cursor/skills and skills folders.
Startup items
Section titled “Startup items”Columns: Item, Status, Type, Signed by, First seen, Runs.
| What | Where |
|---|---|
| Launch agents and daemons | ~/Library/LaunchAgents, /Library/LaunchAgents, /Library/LaunchDaemons, and launch items inside apps in /Applications. Type says LaunchAgent (you), LaunchAgent, LaunchDaemon or Login item; Signed by says Apple, Developer ID (with the team), Ad hoc, Unsigned or Program missing, from a static code-signature check. |
| Shell profiles | ~/.zshrc, .zshenv, .zprofile, .zlogin, .bashrc, .bash_profile, .bash_login, .profile, fish, ksh, and the system profiles in /etc. Watch keeps only the lines it flags, shortened and with secrets removed. |
| Git | ~/.gitconfig and ~/.config/git/config (a global core.hooksPath), each repository’s executable hooks, and each repository’s .git/config: its hooks path, and whether a remote URL holds a token (REPO-8; Watch keeps the host and kind, never the token) |
| Files | Known attack files at exact paths, when present; Docker CLI plugins; Homebrew cask apps without a quarantine flag; and self-hosted GitHub Actions runners New in 1.2.0 |
Keys & tokens
Section titled “Keys & tokens”Columns: Holds, Status, Token present, First seen, Where.
Watch checks that credential files exist, so an incident can tell you which of them an attack collects: SSH private keys, AWS, Azure and Google Cloud credentials, Kubernetes and Docker config, .npmrc, .pypirc, .netrc, Git credentials, the GitHub CLI, AI-tool logins (Claude, Codex, Cursor, Gemini), Cargo and gem credentials, GnuPG, 1Password CLI, Terraform, Vercel, Netlify, Fly, Wrangler, Stripe and Supabase. It doesn’t keep their values. For .npmrc it notes whether a token is present.
Terraform state files (*.tfstate, *.tfstate.backup) in your projects are listed here too, by size only, for REPO-9.
Separately, Watch looks for keys saved in plain text in dotfiles, .env files and AI tool configs: see SEC-1.
Apps & tools
Section titled “Apps & tools”Columns: App or tool, Version, Status, From, Where.
The versions of macOS and of the apps, runtimes and tools that version checks and VER-1 compare against exploited flaws. Watch reads each version from a file and never runs the program. From says where the copy came from: macOS, App, Homebrew, nvm, pyenv, Native installer, Installer package, or another version manager’s name.
| What | Where Watch reads the version |
|---|---|
| macOS | /System/Library/CoreServices/SystemVersion.plist |
| Apps: Safari, Google Chrome, Firefox, Microsoft Edge, Brave, Arc, Docker Desktop, OrbStack, Xcode, Visual Studio Code, Cursor, Windsurf, Zed, Claude, ChatGPT, Slack, JetBrains IDEs and Android Studio | Each app’s Contents/Info.plist in /Applications, /Applications/Utilities, ~/Applications and ~/Applications/JetBrains Toolbox |
| Apple’s Git and OpenSSH | The version text inside /Library/Developer/CommandLineTools/usr/bin/git, each Xcode’s git, and /usr/bin/ssh |
| Node.js | Each version in nvm, Volta, fnm, asdf and mise; Homebrew’s linked node; and /usr/local/bin/node from the nodejs.org installer |
| Python | pyenv and uv versions, and python.org Pythons in /Library/Frameworks/Python.framework |
| Ruby, Go, Java | rbenv versions; /usr/local/go/VERSION; the release file of each JDK in /Library/Java/JavaVirtualMachines and ~/Library/Java/JavaVirtualMachines |
| Homebrew formulae | The linked version of git, openssh, php, python, ruby, go, openjdk, codex and gemini-cli, from their opt links |
| Claude Code | The newest version in ~/.local/share/claude/versions |
Version checks also use Homebrew casks and global npm installs of Claude Code, Codex and Gemini CLI, which are listed under Packages.
Trust stores
Section titled “Trust stores”Columns: Trust store, Status, Used by, Certificates, Where.
Every list of trusted certificate authorities Watch found on the Mac, so a trust-store check can tell you which ones still trust a distrusted authority. Certificates counts the certificates in each store.
| Store | Used by |
|---|---|
| Apple system roots and the Apple revocation list (its date only) | Safari, curl, git, Go tools; every Apple TLS check |
| /etc/ssl/cert.pem (LibreSSL) | openssl, LibreSSL tools |
| Homebrew ca-certificates, and its copy with keychain roots | Homebrew curl, openssl@3 |
Each Python certifi copy, labelled with where it is (pyenv, pipx, uv, conda, Homebrew Python, python.org Python, ~/Library/Python or a project’s virtual environment) |
Python requests, httpx |
Each node program, labelled with its version manager and version, for example nvm Node v24.15.0 |
Node.js |
| Each Electron app, with its version and Electron’s | The app’s Node runtime |
Each JDK’s cacerts, including Homebrew openjdk, SDKMAN and Java bundled inside apps |
Java |
| Roots added to the keychains | Everything that uses the keychain |
| Keychain certificates | Your signing and client certificates |
Watch reads the files, and the keychains through macOS’s Security framework. For each certificate it keeps only a short fingerprint of its public key (and, for keychain certificates, the issuer’s name), never the keys themselves. Stores with identical contents, such as the same certifi in ten virtual environments, each get a row, and their fingerprints are stored once. Select a store to see what it is and how it gets updated.
Services
Section titled “Services”Columns: Service, Status, Covers, First seen, Where.
The hosted services this Mac is signed in to: one row per login, token or config file Watch found, out of 45 services from GitHub, npm and AWS to Anthropic, OpenAI and Cloudflare. A headline about a breached service uses this list to answer Relevant to you.
- Watch checks that each file exists. Covers shows the names a few files list, without values: OpenCode’s providers, Docker registry hosts, npm hosts with an auth line, GitHub CLI hosts, section names in the AWS, PyPI and Modal files (profiles and repositories),
.netrcmachine names, and Terraform hosts. Anything that looks like a token is dropped. - A folder counts only when something is in it, and a shared file such as
~/.docker/config.jsonor~/.netrccounts for a service only when it has that service’s own entry. - Where is the file. Watch never reads or stores the login itself.
Footprint
Section titled “Footprint”Columns: Name, Type, Provider, Found in, Where.
The repositories, domains, servers, clusters, cloud accounts and registries this Mac’s config files name, read without contacting any of them. See Footprint for where each comes from.
What Watch can’t see
Section titled “What Watch can’t see”| Gap | Why |
|---|---|
| Container images while their runtime is stopped | Images live inside the runtime’s virtual machine, so Watch can list them only while its engine runs. See Container images. |
| Login items list | macOS’s Background Task Management list needs admin rights. Watch reads launchd folders and launch items inside apps instead. |
| Which Safari extensions are turned on | Needs Full Disk Access. |
| Binary Bun lockfiles | bun.lockb isn’t parsed yet; installed node_modules still are. |
| Very large pnpm stores | Watch reads the first 40,000 index files. |
| Short-lived programs and network traffic | Watch mode checks running programs once a minute, so a program that starts and stops in between isn’t seen. Connections are seen only with the optional network extension, and only who connected where. |
| Logins kept only in the Keychain, a password manager or a browser | The Services tab finds files. Web-only logins leave nothing to find. |
| Repositories that are only on GitHub | Watch reads the local clones under your code folders. Checking repositories on GitHub needs the GitHub connection, which is coming soon. |
| Trust stores inside containers | They live inside the container runtime’s virtual machine. |
After each scan, a Not checked line under the Inventory table names the gaps that applied to your Mac. Expand it to see why and what would fix each one, with a button such as Open Full Disk Access where one helps.
The Not checked section in 1.1. From 1.2, Watch lists Safari extensions without Full Disk Access and only needs it to tell which are turned on.
Settings › Permissions lists them too, under Not checked on this Mac, and watchctl scan and watchctl inventory print them.