The agent check-up

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.

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.

1. What it is

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. Claude Code and Claude Desktop are read in full; Cursor, Windsurf, Codex CLI, Gemini CLI, Cline and VS Code are read for their MCP servers, instruction and rule files and skills (Gemini CLI's hooks too). OpenClaw is detected only — present or absent, with the paths looked at — and not inventoried: nothing under it is opened, nothing about it is assessed, and it has no score. Not inventoried is not a pass. An agent not in that list is reported as not present.

2. Install and run

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.5.0-py3-none-any.whl repogates-checkup

Its SHA-256 is published beside it, at /cli/repogates_checkup-0.5.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.

OptionWhat it does
--agent NAMEOne agent (claude-code, claude-desktop, cursor, windsurf, codex, gemini, cline, vscode, openclaw) or all, the default.
--project DIRA 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.
--jsonThe 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.
--offlineThe 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 TEXTA label for this run on your account page.
--home DIRRead DIR as the home — a mounted profile, a fixture.
--api-base URLThe API base (default $REPOGATES_API_BASE or https://api.repogates.com). From 0.1.2 only RepoGates over https, or 127.0.0.1 / localhost over http with a port: for any other address the token is not read, nothing is sent and the run is an offline one that says why.

Exit codes

CodeMeaning
0allow — no finding the policy acts on.
1warn — at least one finding the policy warns on.
2block — at least one finding the policy blocks on.
3not 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.

3. What it reads, per agent

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 Code — read in full

  • ~/.claude/settings.json and ~/.claude/settings.local.json — permission rules, hooks, the on/off flags, enabled plugins, extra marketplaces (scopes user and local).
  • The operating system's managed-settings file, scope 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.
  • Per --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 — read in full

  • 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).

Cursor, Windsurf, Codex CLI, Gemini CLI, Cline and VS Code — what each reader opens

For these six the check-up opens the files below and nothing else: MCP servers (names of environment variables and headers, never their values), instruction and rule files (a rule id, a count and a SHA-256), and skills. A rule file in a folder is named by the folder and its place in it (.cursor/rules/#2), never by its own file name. In a project, a symbolic link is not followed.

AgentUnder the homeIn a --project
Cursor.cursor/mcp.json, .cursor/rules/*.mdc and *.md, .cursor/skills. User rules kept in Cursor's settings database are not read..cursor/mcp.json, .cursor/rules, .cursorrules, .cursor/skills
Windsurf.codeium/windsurf/mcp_config.json, .codeium/windsurf/memories/global_rules.md.windsurf/rules/*.md, .windsurfrules
Codex CLI.codex/config.toml — [mcp_servers.*] only; .codex/AGENTS.md, .codex/skills.codex/config.toml ([mcp_servers.*] only), AGENTS.md
Gemini CLI.gemini/settings.json — mcpServers and hooks only; .gemini/GEMINI.md, .gemini/skills. Extensions under .gemini/extensions are listed as present, not opened..gemini/settings.json (the same two keys), GEMINI.md
Clinecline_mcp_settings.json in VS Code's globalStorage/saoudrizwan.claude-dev/settings (under Library/Application Support/Code/User, .config/Code/User or AppData/Roaming/Code/User) and in .cline/data/settings; Documents/Cline/Rules; .cline/skills.clinerules (a file or a folder)
VS CodeUser/mcp.json under Library/Application Support/Code, .config/Code or AppData/Roaming/Code — servers only, read as JSON with comments. Agent plugins under .vscode/agent-plugins are listed as present, not opened..vscode/mcp.json, .github/copilot-instructions.md, .github/instructions/*.instructions.md

Detected only in this version — OpenClaw

OpenClaw is reported present or absent, with the paths looked at: .openclaw/openclaw.json, .openclaw and .config/openclaw under the home. Nothing under them is opened, nothing about it is assessed, and it carries no score.

4. What leaves your machine

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 reduced to flag names, NAME=<redacted>, URL hostnames and the package a runner starts (npx -y @scope/pkg@version), every other word replaced by <arg> 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, arguments reduced the same way 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:

  • Marketplace: name, scope, source (type; for 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).
  • Plugin: its 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.
  • Skill and command: name, scope, the SHA-256 of the file, source, findings as rule id and count.
  • Subagent: name, scope, SHA-256, the declared tools and model, findings.
  • MCP server: name, scope, transport, the launch program's basename, its arguments as flag names, NAME=<redacted>, URL hostnames and the package a runner starts (every other word <arg>), the package it launches (registry, name, version), a remote server's hostname, the names of its environment variables and headers, findings (for a key found in plain text in its values, checkup-plaintext-key with the provider's name and a count, never the key).
  • Hook: event, matcher, type, the program's basename, its arguments reduced the same way, timeout, scope, an http hook's hostname, findings (a key in its command or headers: the provider's name and a count).
  • Permissions: scope, the allow / deny / ask rules with paths collapsed, the default mode, the on/off flags (bypass disabled, auto mode, skip-auto-prompt, hooks disabled, all project MCP), the count of additional directories and of enabled plugins, and each extra marketplace's source type and hostname.
  • Instructions: which file (CLAUDE.md, AGENTS.md, .claude/CLAUDE.md), scope, SHA-256, findings.
  • The run: the schema name, the CLI's name, version, rules version and platform, the random check-up id, your label, and per agent whether it is present and which scopes it has.

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.

5. What it cannot see

  • Runtime behaviour — what a plugin's code or an MCP server does once it runs. The check-up reads configuration; the deep scan is the tool that reads a package's files.
  • A skill's origin when no provenance file exists. A skill copied by hand into ~/.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).
  • An agent not in the list — reported as not present, not as anything else.
  • OpenClaw's configuration, in this version: it is present or absent and nothing more.
  • For Cursor, Windsurf, Codex CLI, Gemini CLI, Cline and VS Code, anything outside the files listed in section 3 — their other settings, Cursor's user rules (kept in its settings database), Gemini CLI extensions and VS Code agent plugins (listed as present, not opened), and the editor extensions themselves.
  • Your installed editor extensions and Docker Desktop extensions. The check-up does not list them. A VS Code Marketplace extension or a Docker Desktop extension is checked before you install it, through the MCP server and the plugin's hook — not in the browser, and not by the check-up.
  • An MCP server whose package declares no repository — "not assessed", never a pass. The launch line still gets the local checks (a fetch piped into a shell is a finding whatever the package).
  • A detected-only agent carries no score. 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.

6. How to read the score

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 16 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.

Since your last check-up on this machine

From CLI 0.3.1, an online run ends with a short section, Since your last check-up on this machine: the items added and removed since the previous run, the verdicts that moved, the findings that appeared or went (on the permission settings, the permission or posture that changed), and the run's score, grade and action before and after. The account page shows the same block above the history, and the MCP last_checkup tool returns it as changed_since.

It compares two runs of the same machine only: the random id the CLI keeps in ~/.config/repogates/checkup-id, never a run from another machine. The server works it out from the two summaries it already stores, when you ask, and keeps nothing more; nothing more leaves your machine for it. Hooks, and items that have no name, are counted rather than compared by name, so two hooks of the same event and program read as a number that went up or down. A machine's first check-up has nothing to compare with and says so.

Re-checked when you look

On a paid plan, the server keeps, for each plugin, skill, MCP server or marketplace it could resolve, the key it resolved it to — a repository, package or skill key, never a path. When you open the account page or ask the MCP last_checkup tool, those keys from your newest check-up are re-checked if they were not checked in the last day (at most 20 new assessments a day, shared with your watchlist), and the answer says which changed since you last looked and why, which were checked recently, and which were not re-checked yet. Nothing more leaves your machine for it, and nothing runs while you are not looking. A check-up stored before 2 November 2026 has no keys; it says a new check-up is needed.

The checks, their severity and the fix

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.

CheckTitleSeverityFix
checkup-plugin-sourcePlugin source verdictCRIT when the source is campaign-listed; HIGH on BLOCK; MED on REVIEW; a note on PASSUninstall 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-sourceMarketplace source verdictCRIT / HIGH / MED / note, by the marketplace repository's verdictRemove the marketplace (/plugin marketplace remove name) until its repository's verdict is PASS; every plugin it lists is installed on its word.
checkup-mcp-sourceMCP server package source verdictCRIT / HIGH / MED / note, by the package's source repository's verdictRemove 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-execMCP server launch line fetches and runsCRITReplace 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-execHook command fetches and runsCRITReplace 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-remoteHook posts tool input off the machineHIGHPoint 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-sourcePlugin installed by a shell commandHIGHPrefer a plugin whose marketplace entry names a repository; a command source runs a shell command at install and once per session.
checkup-mcp-unpinnedMCP server package not pinned to a versionMEDPin 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-hostRemote MCP host outside the registry censusINFO 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 itConfirm 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-envCredential-named variable to an unknown remoteMEDGive the credential to the remote only after confirming its host; the name of the variable was sent, its value never was.
checkup-plaintext-keyAPI key stored in plain text in agent configurationMEDMove the key out of the agent configuration: into your operating system's keychain, or an env file outside the agent config that the server reads at start; then rotate it if the config was ever shared, synced or committed. Online, the check-up sends RepoGates the provider and a count, never the key; offline it sends nothing.
checkup-posture-bash-wildcardEvery shell command allowed without a promptMED — a choice, statedReplace Bash(*) in the allow list with the commands you mean (Bash(npm test:*)), so a prompt returns for everything else.
checkup-posture-bypassPermission prompts bypassed by defaultMED — a choice, stated; INFO in a project file, where it does not take effectSet defaultMode back to a prompting mode in your user settings; a project file cannot turn bypass on.
checkup-posture-all-project-mcpEvery project's MCP servers start without approvalMED — a choice, statedTurn enableAllProjectMcpServers off and approve each project's .mcp.json servers as you open them.
checkup-posture-autoAuto mode onINFONo change needed; auto mode is your choice, and the check-up states it.
checkup-posture-hooks-disabledAll hooks disabledINFONo change needed unless a hook you rely on is silently off.
checkup-posture-skip-promptAuto-mode prompt skippedINFONo change needed; stated so the setting is not a surprise.
checkup-injection:overrideInstruction shape: override or hide from the userMEDRead 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 commentINFO until the false-positive runRead the matched file yourself before the next session; the check-up sends only the rule id and a count, never the text.
hidden-unicodeHidden Unicode in an agent fileCRITOpen 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-redirectAPI base URL or key overriddenCRITRemove the ANTHROPIC_BASE_URL / OPENAI_BASE_URL override or the *_API_KEY assignment unless you set it yourself for a proxy you run.
mcp-execLauncher config fetches and runsCRITReplace the launch line with a pinned package or an installed program; never a fetch piped into a shell.
checkup-mcp-no-sourceMCP server names no package or repositoryINFONo change needed; the server launches something the check-up cannot trace to a package or repository, so nothing was assessed.
checkup-skill-unknown-sourceSkill with no known originINFONo change needed; if you want provenance, reinstall the skill from its repository through npx skills add owner/repo.
checkup-not-assessedNot assessedINFO — never a pass; sets partialRun 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.

7. The measurement

Measured on 21 September 2026 on the official plugin catalogue (anthropics/claude-plugins-official, all 310 plugins, each installed alone in a synthesised home and run as its own check-up) and on the first 100 plugins of the community catalogue, offline and online. The gate was 0 critical false positives on the catalogue, or the rule is downgraded before launch. It is met. The first run found 59 critical findings on the official set, every one a misread — mostly a credential variable merely named in a plugin's text — and the calibration made those a note while the real shape, a base URL assigned to someone else's host, stays critical.

  • Official catalogue: 287 plugins allow, 23 warn, none block; median score 100, lowest 92. The warnings are 25 MCP servers launched with no version pinned — every one real — and one line of defensive text read as an instruction, the one false positive left.
  • Community catalogue, first 100: 90 allow, 10 warn, none block.
  • Offline and online agree on all 410 runs, so a CI job that runs offline gets the same answer.
  • The reference runs: an empty home is exit 0; a minimal home is 100 and green; a test home built to be hostile — a curl … | sh server, a curl | sh hook, a hidden-Unicode CLAUDE.md and a base-URL redirect — still scores 0, red, which is how you know the calibration did not blunt the rules.

Nothing here is a catch rate. The check-up matches these shapes on the configuration it reads; what a plugin's code does when it runs is the deep scan's question.

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.

9. Looking for secrets: repogates-checkup secrets

From version 0.2.0 the same wheel carries a second command that looks for secrets — API keys, tokens, private keys — on your machine. It matches these patterns: Gitleaks' own rules (version 8.30.1, vendored with its MIT licence) and six of RepoGates' own for AI providers Gitleaks does not cover (Replicate, Groq, OpenRouter, xAI, Mistral, DeepSeek; only Replicate publishes its key format, the other five are shapes observed and labelled so). A match is not proof, and no match does not mean there is no secret.

uvx --from https://repogates.com/cli/repogates_checkup-0.5.0-py3-none-any.whl repogates-checkup secrets .
repogates-checkup secrets . --staged          # what you are about to commit
repogates-checkup secrets . --history         # and the last 1,000 commits
repogates-checkup secrets . --json            # for CI
  • Free, offline, no account and no token. It needs no plan and sends nothing anywhere; the value of a secret is never printed in full, never written and never sent. A finding shows its first four characters when the value is at least 16 long, and its length (ghp_…(40)).
  • What it reads. By default the working tree under the path you give: every file, .git skipped, a file over 1 MB skipped and counted, a file with a NUL byte in its first 8 KB counted as binary, a link not followed. A directory Gitleaks' own allowlist excuses whole (node_modules, a virtualenv's lib) is not opened, and counted. --staged reads the lines added in what is staged; --history also reads the lines each of the last 1,000 commits added (--max-commits changes it), so a key that is only in history is named as such.
  • It may run git. --staged and --history run git diff --cached and git log -p, read-only, with external diff drivers, textconv filters and the fsmonitor hook turned off. That is this command's own contract; the check-up itself still never runs a program.
  • Triage. Each secret is one incident however many files and commits hold it, with its provider and where it is (working tree, staged, history). A test, fixture or example path, a placeholder (${OPENAI_API_KEY}, <your-key>) or a low-entropy value is listed as likely not real. The fix comes in order: rotate the key with its provider first, then remove it from the file, then purge it from the git history.
  • Exit codes. 0 nothing likely real matched; 1 a likely-real secret; 2 an error (no such path, not a git repository for --staged or --history).
  • --check-live, only when you ask. With the flag, each likely-real key whose provider documents a read-only identity endpoint (GitHub, GitLab, OpenAI, Anthropic, Hugging Face, Slack, Stripe) is sent to that provider and to no other host, once — no retry, no redirect followed, a 5-second timeout — and reported as live, revoked or unknown. The key is never logged. Without the flag nothing touches the network.

In the check-up itself, the same engine runs on your machine over the values the readers already hold — an MCP server's environment values, headers and arguments, a hook's command. A key found there is the finding checkup-plaintext-key (MED): what leaves is the rule id, the provider's name and a count, never the key.

10. At a terminal: repogates check and repogates clone

From version 0.4.1 the same wheel answers at a terminal what the preflight hook answers inside a Claude Code session: RepoGates' decision on one command line, on your account's policy, before the line runs. Only what runs through it is seen. repogates is a second name for repogates-checkup.

uvx --from https://repogates.com/cli/repogates_checkup-0.5.0-py3-none-any.whl repogates check "git clone https://github.com/owner/repo"
repogates check -- npm install express
repogates clone owner/repo [dir] [git clone options]
  • check runs nothing. It sends the line (POST /v1/preflight) and prints the decision entry by entry. Exit 0 allowed by your policy, 1 a warning, 2 blocked by your policy, 3 not assessed: no token, an unknown or revoked one, no paid plan, a rate limit, the service out of reach, a line over 8,192 bytes. No answer is never read as a pass.
  • clone runs git, by design. It checks git clone and your words, then runs git with the same words, as a list and never through a shell. Blocked: git does not run. A warning or a check that could not be made: you are asked on a terminal; anywhere else the clone is refused unless --yes comes before the repository. A line that names nothing RepoGates assesses (another host, a local path) is not a pass. The check-up itself still never runs a program.
  • What it does not see. Anything that does not go through it: a git clone typed on its own, a package manager, curl, an IDE or an agent. A URL's user name and password and a credential header's value are cut from the copy that is sent; the token goes only to RepoGates and is never printed.

← All documentation · AI agents & MCP guide · Personal user guide · The CLI page