An inventory of what your AI-agent setup already has — plugins, skills, MCP servers, hooks, permissions — scored by RepoGates. It reads; it never runs a program, never changes a file, and never blocks anything. ← All documentation
The single sentence. The check-up reads your AI-agent configuration on your machine and sends RepoGates identifiers, never contents. It reads; it never runs a program, never changes a file, and never blocks anything. The full list of what leaves and what never leaves is below, verbatim, and on the privacy page.
Everything else RepoGates does is about what is about to be fetched — a repository, a model, an extension, a skill. The check-up is about what an agent installation already has: the plugins installed and the marketplace each came from, the skills, commands and subagents on the machine, the MCP servers and hooks that run, the permission rules in force, the instruction files that exist. It is a read-only inventory, scored by RepoGates. Each plugin's, skill's and MCP server's source is assessed through the same rosters every RepoGates verdict uses (the 15 skill and plugin checks, the 22 on a repository); the served rule set is applied to the files on the machine — hidden Unicode, a launch line that fetches and runs, an API base URL override, the instruction shapes — and the permission posture is stated as what it is: a choice, never a critical finding. The answer is one score for the run, one per agent, one per item, with the findings that decided it and a fix for each.
It is part of every paid plan — Personal, Premium and Team — and not of the free trial. In this version Claude Code and Claude Desktop are read in full. Cursor, Windsurf, Codex CLI, Gemini CLI, Cline, VS Code and OpenClaw are detected — present or absent, with the paths looked at — and not inventoried: nothing under them is opened, nothing about them is assessed, and they have no score. Not inventoried is not a pass. An agent not in that list is reported as not present.
Inside Claude Code, /repogates:checkup (plugin 0.9.0)
runs it and reads the result. Anywhere else, the
repogates-checkup command line — Python 3.11 or newer, no
dependencies — is served as a wheel from this site
and nowhere else; there is no PyPI package to install, and the install
line names the exact file:
uvx --from https://repogates.com/cli/repogates_checkup-0.1.0-py3-none-any.whl repogates-checkup
Its SHA-256 is published beside it, at
/cli/repogates_checkup-0.1.0-py3-none-any.whl.sha256 and on
the CLI page, so the bytes you run are the bytes
that were built (shasum -a 256 -c against the downloaded
wheel). With pipx instead of uv: pipx run --spec <the same
URL> repogates-checkup. The Claude Code command finds
uvx or pipx on the machine and, if neither is
there, points you at uv's documentation or pip install --user
pipx and stops — it never installs a runner with a
curl | sh line.
A RepoGates API token names your account: $REPOGATES_TOKEN,
or the first line of ~/.config/repogates/token — the file
the plugin's hook reads (create one on
the account page). Without a token the check-up runs offline and
says so: the bundled rule set, local findings only, nothing sent and
nothing written. The token is never printed and never put on a command
line.
| Option | What it does |
|---|---|
--agent NAME | One agent (claude-code, claude-desktop, cursor, windsurf, codex, gemini, cline, vscode, openclaw) or all, the default. |
--project DIR | A project directory to read — its .mcp.json, CLAUDE.md, AGENTS.md and .claude/ — repeatable, sent as project:N and never as a path. With no home configuration on the runner this is the CI shape: repogates-checkup --project . --json reads a repository's agent files before merge; the exit code gates the job, the JSON is the record. Give the job REPOGATES_TOKEN as a secret for the server's verdicts, or run --offline for the local findings alone. |
--json | The JSON document instead of the table: {"local": …} offline, {"local": …, "server": …} online. local.inventory is byte for byte what was sent, so you can read it before you trust it. |
--offline | The bundled copy of the rule set (pinned equal to the served one in this repository's tests), the local findings only; nothing is sent and nothing is written. No verdict on any plugin's, skill's or server's source — that is what the server knows. |
--label TEXT | A label for this run on your account page. |
--home DIR | Read DIR as the home — a mounted profile, a fixture. |
--api-base URL | The API base (default $REPOGATES_API_BASE or https://api.repogates.com). |
| Code | Meaning |
|---|---|
0 | allow — no finding the policy acts on. |
1 | warn — at least one finding the policy warns on. |
2 | block — at least one finding the policy blocks on. |
3 | not run — no answer: the token was refused, the plan does not include the check-up, the daily allowance (12 runs) is spent, the API was unreachable, the server refused the inventory, or nothing was inventoried — every present agent was only detected, so the run has no score and no action. Not run is never a pass. |
Online, the code is the server's action for the run. Offline, it is
the worst local severity through the action mapping the rules file
carries — absent one, a CRIT blocks and HIGH or MED warns. The MCP
server's last_checkup tool reads the stored summary back;
no tool on that server reads a machine.
These are the files each reader opens, and nothing else. Every file's contents stay on the machine: the rules run on them there, and what leaves is a rule id and a count. A file over 1 MB is not read and is counted. Paths in arguments and permission rules are collapsed before they reach an item.
~/.claude/settings.json and ~/.claude/settings.local.json — permission rules, hooks, the on/off flags, enabled plugins, extra marketplaces (scopes user and local).managed: /Library/Application Support/ClaudeCode/managed-settings.json on macOS, /etc/claude-code/managed-settings.json on Linux, %ProgramData%\ClaudeCode\managed-settings.json on Windows.~/.claude/CLAUDE.md — instructions.~/.claude/skills/*/SKILL.md — skills. No provenance file exists for a hand-copied skill, so each is "local, source unknown".~/.claude/commands/*.md and one level of */*.md — commands.~/.claude/agents/*.md and one level of */*.md — subagents; the frontmatter's name, tools and model.~/.claude/plugins/installed_plugins.json and ~/.claude/plugins/known_marketplaces.json.~/.claude/plugins/marketplaces/<marketplace>/.claude-plugin/marketplace.json — the catalogue, to name each plugin's own source.~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/ — inside it .claude-plugin/plugin.json, hooks/hooks.json, .mcp.json, skills/*/SKILL.md, commands/*.md, agents/*.md.~/.claude.json — mcpServers and projects[*].mcpServers only. The file carries more than eighty keys, among them oauthAccount and machineID; two are read, and a test proves nothing else serialises. The project path that keys each entry is matched against --project for project:N and otherwise the servers are local; the path itself is never kept.--project DIR: .mcp.json, CLAUDE.md, AGENTS.md, .claude/settings.json, .claude/settings.local.json, .claude/CLAUDE.md, .claude/skills, .claude/agents, .claude/commands.claude_desktop_config.json — mcpServers only; the file also carries preferences and a user files path, and neither is read. Every operating system's location under the home is looked at: ~/Library/Application Support/Claude/ (macOS), ~/AppData/Roaming/Claude/ (Windows), ~/.config/Claude/ (Linux).For these seven the check-up reports present or absent and names the paths it looked at. Nothing under them is opened, nothing about them is assessed, and the agent carries no score. Their readers follow once fixtures exist (the roadmap).
| Agent | Under the home | In a --project |
|---|---|---|
| Cursor | .cursor/mcp.json, .cursor/skills, .cursor/rules, .cursor | .cursor/mcp.json, .cursor/rules, .cursorrules |
| Windsurf | .codeium/windsurf/mcp_config.json, .codeium/windsurf, .windsurf | .windsurf/rules, .windsurfrules |
| Codex CLI | .codex/config.toml, .codex/skills, .codex | .codex |
| Gemini CLI | .gemini/settings.json, .gemini/extensions, .gemini/skills, .gemini | .gemini/settings.json, GEMINI.md |
| Cline | .cline/skills, .cline, and VS Code's globalStorage/saoudrizwan.claude-dev under Library/Application Support/Code/User, .config/Code/User or AppData/Roaming/Code/User | .clinerules |
| VS Code | .vscode/agent-plugins, and User/mcp.json under Library/Application Support/Code, .config/Code or AppData/Roaming/Code | .vscode/mcp.json, .github/copilot-instructions.md |
| OpenClaw | .openclaw/openclaw.json, .openclaw, .config/openclaw | — |
The check-up reads your AI-agent configuration on your machine and
sends RepoGates identifiers, never contents. What leaves: the
names and versions of installed plugins and the marketplace each came
from, with its source type and repository or URL hostname; marketplace
names and sources; skill, command and subagent names with where each
lives (user, project or plugin), a SHA-256 of each SKILL.md that
identifies a known skill without revealing it, and a subagent's
declared tools and model; for each MCP server its name, transport, the
launch program's name and its arguments with every NAME=value,
path and token-shaped string replaced, the package it launches
(npx -y @scope/pkg@version) and, for a remote server, the
hostname only; the names of environment variables and headers a server
or hook is given, never their values; each hook's event, matcher, type,
program name, redacted arguments and timeout; your permission rules
with paths collapsed, your permission mode and the on/off flags;
whether CLAUDE.md, AGENTS.md or rules files exist; the findings the
served rule set produced on your machine, as a rule id, a count and a
file's place in the list, never the matching text; a random check-up
id stored in ~/.config/repogates that is not derived from
your hardware; and your API token, to name your account. What never
leaves: the contents of any file, environment-variable values, tokens,
full URLs, your machine's hostname or user name, your home directory
path, project paths or names (a project is sent as its position in
the list), and any key of ~/.claude.json or
claude_desktop_config.json other than
mcpServers. RepoGates keeps the identifiers and their
verdicts for your account page and deletes them with your account.
The check-up reads; it never runs a program, never changes a file,
and never blocks anything.
The same list, item by item — every field the checkup/v1
document has, and the document has no other:
github the owner/repo, path and ref; for a URL the hostname and, only when it is a github.com or gitlab.com repository, the repository path; for npm the package name; for an archive the hostname; for a command source the program's basename; path and unknown carry nothing).name@marketplace key, version, scope, the installed commit, its source as above, and the names of the hooks, MCP servers, skills, commands and subagents it ships.CLAUDE.md, AGENTS.md, .claude/CLAUDE.md), scope, SHA-256, findings.Every run prints a sent: line so you see what left, in
the CLI's own words:
sent: 9 agents (2 present), 41 items — 3 marketplaces, 6 plugins, 12 skills, 4 commands, 2 subagents, 7 MCP servers, 3 hooks, 2 permissions, 2 instructions — 5 findings as rule ids and counts; 0 file contents, 0 environment values, 0 tokens, 0 full paths; 9,812 bytes
The numbers above are an illustration of the shape; yours are your
own. Offline the line reads sent: nothing (offline) — 0 file
contents, 0 identifiers, 0 bytes. The server holds the other
end of the contract: it validates the document strictly (an unknown
key is refused by name) and refuses, before anything is stored, a
value that looks like a token or a NAME=value with a value
— so a redaction the CLI missed is a 400, not a row. The summary the
server keeps for your account page carries identifiers and verdicts
only: no arguments, no environment-variable names, no hook lines. The
newest thirty runs are kept per account, and all of them are deleted
with the account. The check-up registers no device and does not count
against your device allowance; its check-up id is random, minted once,
and is not a fingerprint.
~/.claude/skills is "local, source unknown" and is scored on its text alone. If you want provenance, reinstall it from its repository (npx skills add owner/repo).not_inventoried is a status, not a 100; a run whose present agents were all only detected has no score and no action.A PASS is on the identifiers and the text read, not on anything having been run.
The answer has three levels. Per agent, a status:
inventoried (present, read, at least one item — with a
score, a grade and an action of its own), not_inventoried
(present, detected only — score: null, grade
unknown, no action) or absent. Per
item, a verdict — PASS, REVIEW,
BLOCK or NOT_ASSESSED — a score, an action,
the basis it was decided on (skill-roster for a plugin or
skill source through the 15 checks, repo-22 for a
repository, launch-line for an MCP server or hook,
posture for permissions, rules for a file's
findings) and the check ids that fired. The run: one score and
grade over every row, the action the policy takes, the drivers behind
it, and partial: true when anything was not assessed.
The arithmetic is the same as every other RepoGates verdict —
score_report over the rows, the same profiles for the
action — so a check-up score reads like a repository score. Two rules
are its own. Posture rows are MED at most — a
Bash(*) allow, a bypass mode, every project's MCP servers
auto-approved — because each is a choice you made, and the check-up's
job is to state it, not to call it critical. And an item the server
could not assess is checkup-not-assessed — the run's
cold-verdict allowance (40 per run, 120 a day across runs) used up, a source that could not
be resolved, a registry that did not answer — an INFO row that keeps
the item out of PASS and sets partial; it is never
unassessable, which would null the whole run. A
campaign-listed key is CRIT whatever else happened.
Titles are the server's; fixes are the served rule set's, quoted as
given. The severity column is the row the engine holds for the check
(backend/policy/scoring.json); a source verdict's row
follows the source's own verdict.
| Check | Title | Severity | Fix |
|---|---|---|---|
checkup-plugin-source | Plugin source verdict | CRIT when the source is campaign-listed; HIGH on BLOCK; MED on REVIEW; a note on PASS | Uninstall the plugin (/plugin uninstall name@marketplace) until its source repository's verdict is PASS, or allowlist it on your account page after reading the findings. |
checkup-marketplace-source | Marketplace source verdict | CRIT / HIGH / MED / note, by the marketplace repository's verdict | Remove the marketplace (/plugin marketplace remove name) until its repository's verdict is PASS; every plugin it lists is installed on its word. |
checkup-mcp-source | MCP server package source verdict | CRIT / HIGH / MED / note, by the package's source repository's verdict | Remove the server from the settings file it lives in until the package's source repository is PASS, or pin a version you have read. |
checkup-mcp-exec | MCP server launch line fetches and runs | CRIT | Replace the launch line with a pinned package or an installed program; a fetch piped into a shell runs whatever the URL serves, every start. |
checkup-hook-exec | Hook command fetches and runs | CRIT | Replace the hook command with a script on the machine; a hook that fetches and runs does so on every matching tool call. |
checkup-hook-http-remote | Hook posts tool input off the machine | HIGH | Point the http hook at a loopback address or a service you run; each tool call's input is posted to the host named. |
checkup-plugin-command-source | Plugin installed by a shell command | HIGH | Prefer a plugin whose marketplace entry names a repository; a command source runs a shell command at install and once per session. |
checkup-mcp-unpinned | MCP server package not pinned to a version | MED | Pin the package version on the launch line (npx -y @scope/pkg@1.2.3, uvx pkg==1.2.3) so an upstream release cannot change what starts. |
checkup-mcp-unknown-host | Remote MCP host outside the registry census | INFO while the served host list is a seed; MED once the full census replaces it; a server whose whole address is a variable sends no host, so this check cannot see it | Confirm the remote server's host is the vendor's own before handing it a credential; a host outside the registry census is not thereby malicious. |
checkup-mcp-credential-env | Credential-named variable to an unknown remote | MED | Give the credential to the remote only after confirming its host; the name of the variable was sent, its value never was. |
checkup-posture-bash-wildcard | Every shell command allowed without a prompt | MED — a choice, stated | Replace Bash(*) in the allow list with the commands you mean (Bash(npm test:*)), so a prompt returns for everything else. |
checkup-posture-bypass | Permission prompts bypassed by default | MED — a choice, stated; INFO in a project file, where it does not take effect | Set defaultMode back to a prompting mode in your user settings; a project file cannot turn bypass on. |
checkup-posture-all-project-mcp | Every project's MCP servers start without approval | MED — a choice, stated | Turn enableAllProjectMcpServers off and approve each project's .mcp.json servers as you open them. |
checkup-posture-auto | Auto mode on | INFO | No change needed; auto mode is your choice, and the check-up states it. |
checkup-posture-hooks-disabled | All hooks disabled | INFO | No change needed unless a hook you rely on is silently off. |
checkup-posture-skip-prompt | Auto-mode prompt skipped | INFO | No change needed; stated so the setting is not a surprise. |
checkup-injection:override | Instruction shape: override or hide from the user | MED | Read the matched file yourself; an instruction that hides something from you has no honest place in a skill. |
checkup-injection:* (decode-exec, password-archive, fetch-exec, credential-read, exfil, dynamic-context, permission-bypass, html-comment) | Instruction shape: decode and run · password-protected archive · fetch and run · credential read · send off the machine · dynamic context span · permission bypass · hidden HTML comment | INFO until the false-positive run | Read the matched file yourself before the next session; the check-up sends only the rule id and a count, never the text. |
hidden-unicode | Hidden Unicode in an agent file | CRIT | Open the file in an editor that shows invisible characters and remove them, or remove the file; a leading BOM alone is not a finding. |
credential-redirect | API base URL or key overridden | CRIT | Remove the ANTHROPIC_BASE_URL / OPENAI_BASE_URL override or the *_API_KEY assignment unless you set it yourself for a proxy you run. |
mcp-exec | Launcher config fetches and runs | CRIT | Replace the launch line with a pinned package or an installed program; never a fetch piped into a shell. |
checkup-mcp-no-source | MCP server names no package or repository | INFO | No change needed; the server launches something the check-up cannot trace to a package or repository, so nothing was assessed. |
checkup-skill-unknown-source | Skill with no known origin | INFO | No change needed; if you want provenance, reinstall the skill from its repository through npx skills add owner/repo. |
checkup-not-assessed | Not assessed | INFO — never a pass; sets partial | Run the check-up again later; the server could not look at this item this time. |
A subagent whose declared tools include Bash is recorded
and is never a finding. The rule set itself — the regex source strings
and the posture lists — is served as data by
GET /v1/checkup/rules and bundled in the wheel; remote
data, never remote code, and the patterns are byte for byte the
engine's own.
Measured on … — the K2e run publishes the false-positive rate of the
launch-config and permission findings here before the pricing row goes
live. The method is fixed: the official plugin catalogue
(anthropics/claude-plugins-official) synthesised into a
home and run through the CLI offline and online, findings tallied per
check id, every CRIT and HIGH listed by plugin for hand review, and
three reference runs — the owner's own machine (counts only), an empty
home (no agents present, exit 0 offline) and a minimal home. The gate:
0 critical false positives on the catalogue, or the rule is downgraded
before launch. Until that run is published, no number appears here.
The contract above is repeated, verbatim, on the privacy page, in the CLI's README, on the CLI page and in the Claude Code command's own text; a test in this repository pins the key clause on each. The extension's privacy notice version does not change for the check-up: nothing new leaves the extension, and the check-up is a separate, opt-in program you run yourself.
← All documentation · AI agents & MCP guide · Personal user guide · The CLI page