{"id":50837949,"url":"https://github.com/jeongjaesoon/agent-guard","last_synced_at":"2026-07-01T14:00:15.059Z","repository":{"id":356359638,"uuid":"1227952190","full_name":"JeongJaeSoon/agent-guard","owner":"JeongJaeSoon","description":"Real-time secret-leak guardrails for AI coding agents (Claude Code, Codex), Git hooks, and CI.","archived":false,"fork":false,"pushed_at":"2026-06-30T18:40:48.000Z","size":877,"stargazers_count":8,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-30T20:22:27.396Z","etag":null,"topics":["ai-agents","claude-code","claude-code-plugin","codex","devsecops","github-actions","gitleaks","pre-commit-hook","secret-scanning"],"latest_commit_sha":null,"homepage":"https://github.com/marketplace/actions/agent-guard-secret-guardrails","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JeongJaeSoon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-03T11:48:25.000Z","updated_at":"2026-06-30T18:34:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JeongJaeSoon/agent-guard","commit_stats":null,"previous_names":["jeongjaesoon/agent-guard"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/JeongJaeSoon/agent-guard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JeongJaeSoon%2Fagent-guard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JeongJaeSoon%2Fagent-guard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JeongJaeSoon%2Fagent-guard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JeongJaeSoon%2Fagent-guard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JeongJaeSoon","download_url":"https://codeload.github.com/JeongJaeSoon/agent-guard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JeongJaeSoon%2Fagent-guard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35009272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","claude-code","claude-code-plugin","codex","devsecops","github-actions","gitleaks","pre-commit-hook","secret-scanning"],"created_at":"2026-06-14T05:05:09.114Z","updated_at":"2026-07-01T14:00:14.989Z","avatar_url":"https://github.com/JeongJaeSoon.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Agent Guard\n\n[![Release](https://img.shields.io/github/v/release/JeongJaeSoon/agent-guard)](https://github.com/JeongJaeSoon/agent-guard/releases) [![GitHub Marketplace](https://img.shields.io/badge/Marketplace-Agent%20Guard-2EA44F?logo=github)](https://github.com/marketplace/actions/agent-guard-secret-guardrails) [![CI](https://github.com/JeongJaeSoon/agent-guard/actions/workflows/ci.yml/badge.svg)](https://github.com/JeongJaeSoon/agent-guard/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n**Stop your AI coding agent from leaking secrets — in real time, before the tool call runs.**\n\n![Agent Guard blocking an agent's read of a .env that holds a private key, then a scan flagging the leak](docs/demo.gif)\n\nAgent Guard is a deterministic guardrail for AI coding agents (Claude Code, Codex) and the Git hooks, CI, and CLI around them. It blocks common ways an agent accidentally exposes secrets: reading `.env`, writing secret-like values, running shell commands that dump credentials, or leaving secrets in the working tree after a tool call. It uses [gitleaks](https://github.com/gitleaks/gitleaks) for detection and plain shell scripts for integration.\n\nUnlike commit- or CI-time scanners that catch a leak *after* it lands, Agent Guard also runs at the agent's tool boundary — the `.env` read or secret write is blocked before it happens. Pair it with commit/CI scanning for defense in depth.\n\nIt is not a vault, credential rotator, or replacement for GitHub Secret Scanning / Push Protection.\n\n## Quick start (Claude Code)\n\nInstall from the marketplace:\n\n```text\n/plugin marketplace add JeongJaeSoon/agent-guard\n/plugin install agent-guard@agent-guard\n/reload-plugins\n```\n\nVerify it's live — ask the agent to read your `.env`:\n\n```text\nPlease read .env\n```\n\nIt should refuse:\n\n```text\nagent-guard: blocked sensitive file access: .env\n```\n\nDetection needs `jq` and `gitleaks` on your machine (`brew install jq gitleaks`; see [Requirements](#requirements) for Linux). Using Codex, Git hooks, or CI instead? Pick your path below.\n\n## Pick an install path\n\n| Use case | Install path | Best first check |\n|---|---|---|\n| Claude Code agent guardrails | [Quick start (Claude Code)](#quick-start-claude-code) | Ask the agent to read `.env`; it should be blocked. |\n| Codex stable guardrails | [Codex direct CLI + Git hook](#codex-plugin) | Run `agent-guard smoke-test`; commit a staged fixture secret, and it should fail. |\n| Codex experimental plugin hooks | [Codex plugin](#codex-plugin) | Enable `plugin_hooks`, trust hooks in `/hooks`, then ask Codex to read `.env`; it should be blocked. |\n| Local commits | [Native Git hook](#native-git-hook) | Commit a staged fixture secret; commit should fail. |\n| CI / PRs | [GitHub Actions](#github-actions) | Push a test PR with a gitleaks-detectable fixture; workflow should fail. |\n| Manual scans | [Direct CLI](#direct-cli) | Run `agent-guard smoke-test`. |\n\n## Requirements\n\nAgent Guard runs on macOS and Linux and expects:\n\n- `sh`\n- `awk`\n- `git`\n- `jq`\n- `gitleaks` 8.30 or newer recommended\n\nInstall paths that download release archives also use `curl`, `tar`, `shasum`, and `ln`.\nPII endpoint providers also use `curl`.\n\nWith a direct CLI install:\n\n```sh\nagent-guard setup   # prints dependency status and install hints\nagent-guard check   # strict pass/fail dependency check\nagent-guard smoke-test\n```\n\nFrom a clone of this repo:\n\n```sh\nplugins/agent-guard/bin/agent-guard setup\nmake check\nmake smoke-test\n```\n\nThe Claude Code and Codex plugin installs do not put `agent-guard` on your shell `PATH`; install `jq` and `gitleaks` with your package manager for those paths:\n\n```sh\nbrew install jq gitleaks\n```\n\nOn Debian / Ubuntu or Fedora, install `jq` with the system package manager and download `gitleaks` from its release page.\n\n## Claude Code Plugin\n\nInstall and verify in [Quick start (Claude Code)](#quick-start-claude-code). Useful slash commands once installed:\n\n```text\n/agent-guard:verify\n/agent-guard:checksum [VERSION]\n```\n\n## Codex Plugin\n\nUse the direct CLI plus the native Git hook as the stable Codex path:\n\n```sh\ncurl -fsSL https://github.com/JeongJaeSoon/agent-guard/releases/latest/download/bootstrap.sh | sh\nagent-guard scan-working-tree\n~/.agent-guard/install.sh git-hooks\n```\n\nThat path gives you on-demand scans and commit-time blocking.\n\nCodex plugin hooks are still behind an under-development Codex feature flag. If you accept that warning and want pre-tool read/write/bash guardrails, enable plugin hooks and install from the marketplace:\n\n```sh\ncodex features enable plugin_hooks\ncodex plugin marketplace add JeongJaeSoon/agent-guard\n```\n\nThen open `/plugins` in the Codex TUI, install **Agent Guard**, restart Codex, open `/hooks`, and trust the **PreToolUse**, **PostToolUse**, and **Stop** hooks.\n\nSmoke test:\n\n```text\nPlease read .env\n```\n\nExpected result:\n\n```text\nagent-guard: blocked sensitive file access: .env\n```\n\nCodex does not currently auto-discover this plugin's `commands/` directory. Ask Codex to run the binary directly when you need those workflows:\n\n```sh\n${PLUGIN_ROOT}/bin/agent-guard scan-working-tree\n${PLUGIN_ROOT}/bin/agent-guard checksum\n```\n\n## Direct CLI\n\nInstall the latest release without cloning:\n\n```sh\ncurl -fsSL https://github.com/JeongJaeSoon/agent-guard/releases/latest/download/bootstrap.sh | sh\n```\n\nThe installer verifies the release archive checksum, extracts to `~/.agent-guard`, links `agent-guard` into `~/.local/bin`, and runs `agent-guard setup`.\n\nCommon commands:\n\n```sh\nagent-guard scan-path .\nagent-guard scan-working-tree\nagent-guard scan-staged\nagent-guard pii-filter\nagent-guard setup\nagent-guard smoke-test\nagent-guard checksum\n```\n\nOverride install defaults with `AGENT_GUARD_VERSION`, `AGENT_GUARD_HOME`, or `AGENT_GUARD_BIN_DIR`.\n\n## PII Filtering\n\n`agent-guard pii-filter` reads text from stdin, masks detected PII, and writes the masked text to stdout. The default provider is `regex`, a built-in shell/awk adapter with no Python runtime dependency:\n\n```sh\nprintf '%s\\n' 'Email jane@example.com from 203.0.113.42' | agent-guard pii-filter\n# Email [PII:EMAIL] from [PII:IP_ADDRESS]\n```\n\nThe built-in regex provider masks common deterministic formats: email addresses, phone numbers, credit cards, US SSNs, and IP addresses. Clean text is passed through unchanged.\n\nChoose a provider with `AGENT_GUARD_PII_PROVIDER`:\n\n```sh\nAGENT_GUARD_PII_PROVIDER=regex agent-guard pii-filter --check\n```\n\nEndpoint-backed providers are available for external redaction services:\n\n```sh\nAGENT_GUARD_PII_PROVIDER=pleno \\\nAGENT_GUARD_PII_REDACT_URL=http://127.0.0.1:8080/api/redact \\\nagent-guard pii-filter --check\n\nprintf '%s\\n' 'Customer jane@example.com' \\\n  | AGENT_GUARD_PII_PROVIDER=pleno \\\n    AGENT_GUARD_PII_REDACT_URL=http://127.0.0.1:8080/api/redact \\\n    agent-guard pii-filter\n```\n\n`pleno` and `http` use the same HTTP adapter: POST JSON as `{\"text\":\"...\"}` and read a redacted string from `redacted_text`, `anonymized_text`, `text`, or `data.redacted_text`. They require `curl`, `jq`, and `AGENT_GUARD_PII_REDACT_URL`; missing tools, missing URL, HTTP errors, invalid JSON, or unexpected response shapes fail closed.\n\nAgent Guard does not install, import, run, or manage `pleno-anonymize`, Docker, Python, or any hosted service. If you use `pleno`, run pleno-anonymize separately or point `AGENT_GUARD_PII_REDACT_URL` at a hosted compatible endpoint.\n\nPII handling in hooks is off by default. Two opt-in modes:\n\n```sh\nAGENT_GUARD_PII_HOOK_MODE=block   # block tool INPUTS that contain any PII\n# or\nAGENT_GUARD_PII_HOOK_MODE=mask    # mask PII in tool OUTPUTS; hard-block Tier-2 inputs\n```\n\nIn **block** mode, proposed `Write`, `Edit`, `MultiEdit`, `apply_patch`, `Bash`, `WebFetch`, `WebSearch`, and MCP inputs are blocked when any PII is detected, with guidance to run `agent-guard pii-filter` first.\n\nIn **mask** mode, PII is masked in a tool's *output* (`PostToolUse`, the same path as secret redaction) so the model never sees it. On the *input* side, mask mode hard-blocks only **Tier-2** PII — credit card, US SSN, and Korean resident registration number, which must never reach a tool — and lets **Tier-1** PII (email, phone, IPv4) through to be masked on the way out. Hooks cannot rewrite a *pending* input payload, so Tier-1 input is allowed rather than masked in place; use `agent-guard pii-filter` for input-side masking.\n\nThe regex provider recognizes email, phone (including Korean mobile), IPv4, credit card, US SSN, and Korean resident registration number.\n\n## Native Git Hook\n\nInstall from a clone or direct CLI install:\n\n```sh\ncd \u003cyour-project\u003e\n~/.agent-guard/install.sh git-hooks\n```\n\nFrom a clone of this repo:\n\n```sh\n./install.sh git-hooks\n```\n\nThis sets `core.hooksPath=githooks` only when it will not overwrite an existing hook setup.\n\n## GitHub Actions\n\nAdd a workflow step:\n\n```yaml\n- uses: JeongJaeSoon/agent-guard@v1\n  with:\n    paths: \".\"\n    gitleaks-checksum: \"\u003csha256 of the gitleaks release archive\u003e\"\n```\n\nUse `@v1` for compatible updates, or pin a full tag / commit SHA for stricter reproducibility.\n\nGet the checksum with:\n\n```sh\nagent-guard checksum\n```\n\nCI runners are usually `linux/x64`, so use the `linux/x64` value printed by the checksum command. `require-checksum` defaults to `true`; set it to `false` only for local experimentation.\n\n### Codex Code Review\n\nThis repository also includes `.github/workflows/codex-review.yml`, which runs [openai/codex-action](https://github.com/openai/codex-action) on non-draft pull requests and posts Codex feedback as a PR comment.\n\nTo enable it, add an Actions secret named `OPENAI_API_KEY` in the GitHub repository settings. The workflow intentionally runs on `pull_request`, checks out the PR merge commit without persisted Git credentials, and runs Codex in a read-only sandbox with `drop-sudo`.\n\n## What Gets Blocked\n\n- `Read`, `NotebookRead`, `Grep`, and `Glob` access to deny-listed paths such as `.env*`, private keys, `.aws/credentials`, `.npmrc`, and `.pypirc`\n- `Write`, `Edit`, `MultiEdit`, and Codex `apply_patch` content containing secret-like values\n- `WebFetch`, `WebSearch`, and MCP tool input JSON containing secret-like values\n- risky shell commands such as `printenv`, `op read`, `vault kv get`, `aws secretsmanager get-secret-value`, `cat .env`, and `git commit --no-verify`\n- PII in proposed write, shell, web, or MCP inputs — all PII when `AGENT_GUARD_PII_HOOK_MODE=block`, or only Tier-2 PII (credit card, US SSN, Korean resident registration number) when `AGENT_GUARD_PII_HOOK_MODE=mask`\n- staged added lines in the native pre-commit hook\n- working-tree added lines and untracked files after agent mutations\n\nPatch and diff scans inspect added lines only. Removing an existing leaked value is allowed.\n\n## What Gets Masked\n\nBeyond blocking, Agent Guard **masks** secret-like values in a tool's *output* before the model sees them. A `PostToolUse` redactor scans the result of `Bash` (stdout/stderr) and read-style tools (`Read`, `NotebookRead`, `Grep`, `Glob`, `WebFetch`, `WebSearch`, and `mcp__.*`) and rewrites any detected secret to `[REDACTED]` in place via `updatedToolOutput`, preserving the result's shape. This closes the gap where a command *prints* a credential the pre-tool check never saw — e.g. `cat memo.txt`, an env-printing CLI, or a tool that dumps `KEY=value` pairs. Detection combines gitleaks with a `KEY=value` env-assignment heuristic. It is on by default; disable with `AGENT_GUARD_OUTPUT_REDACT=off`.\n\nWith `AGENT_GUARD_PII_HOOK_MODE=mask`, the same `PostToolUse` redactor also masks **PII** in tool output — email, phone (including Korean mobile), IPv4, credit card, US SSN, and Korean resident registration number become `[PII:TYPE]` placeholders in place. Secret redaction and PII masking compose into a single rewrite, so a result containing both is fully sanitized at once.\n\n## Shell integration (masking `!` shell-escape output)\n\nThe `PostToolUse` redactor only ever sees the results of the agent's *tool calls*. When you type a `!`-prefixed command at the Claude Code prompt, it runs in the session shell and its **output is captured into the transcript and sent to the model** — but it is not a tool call, so **no** Agent Guard hook fires (a documented blind spot). If that output carries a credential, the model sees it unmasked.\n\n`agent-guard exec` closes that gap. It never blocks the command — it runs it to completion and propagates its exit code — but it captures the combined stdout+stderr, masks secret-like values (and PII, when `AGENT_GUARD_PII_HOOK_MODE=mask`) with the same detection engine the output redactor uses, and prints only the **redacted** text. So the command still runs, but everything you and the model see is the sanitized output — the raw secret is never emitted. Capture is buffered, so this is for non-interactive info commands (env / secret / config dumps), not TUIs or streaming programs. `AGENT_GUARD_OUTPUT_REDACT=off` disables secret masking; masking is on by default.\n\n```sh\nagent-guard exec -- printenv          # runs it, but the transcript gets [REDACTED] in place of secrets\n```\n\nTo make this ergonomic, add the shell integration to your `~/.bashrc` / `~/.zshrc`:\n\n```sh\neval \"$(agent-guard shell-init)\"\n```\n\nThis defines `agx` (a thin wrapper for `agent-guard exec --`) so you can run `agx \u003ccmd\u003e` — in Claude Code, `!agx \u003ccmd\u003e` — and have the output masked before the model sees it. It also installs a **warn-only, non-blocking** nudge (a zsh `preexec` / bash `DEBUG` trap) that reminds you to use `agx` when you run a known secret-loading idiom without it. The nudge never blocks or modifies your command; pass `--bash` or `--zsh` to force a target shell.\n\n## Known Limitations\n\nAgent Guard is a deterministic, thin guardrail — not a DLP system, EDR, or vault. It scans tracked diffs, staged changes, and untracked files with gitleaks, and blocks a fixed list of sensitive paths and shell idioms. It deliberately does **not** inspect arbitrary file contents that a command reads, and it has these blind spots by design:\n\n- **Gitignored files are not scanned.** The working-tree and post-tool/stop backstops use `git ls-files --others --exclude-standard` and `git diff`, both of which skip `.gitignore`d paths. A secret written to a gitignored file (e.g. `secrets/` or `*.local`) is not caught by the backstop. Keep real secrets out of the repo entirely.\n- **Only files inside the git work tree are covered.** The post-tool and stop hooks no-op outside a git repository, and scans are scoped to the current repo. Files outside the repo root, or written when no repo is present, get no backstop. Use `agent-guard scan-path \u003cdir\u003e` to scan an arbitrary tree on demand.\n- **Path and command blocking use fixed lists.** Read/Grep/Glob blocking matches the paths in `deny-read-paths.txt`; shell blocking matches the idioms in `deny-bash-patterns.txt`. A secret in an unlisted path, or read by an unlisted tool or flag, is not blocked. Extend the lists with `AGENT_GUARD_DENY_READ_PATHS` / `AGENT_GUARD_DENY_BASH_PATTERNS`.\n- **Output masking is best-effort.** Secret-like values in a tool's output (`Bash` stdout/stderr, file reads) are masked in place by the `PostToolUse` redactor (`AGENT_GUARD_OUTPUT_REDACT`, on by default), but detection is heuristic — gitleaks plus a `KEY=value` env-assignment rule. Unusual or custom secret formats can still slip through, and the redactor only sees results of the agent's *tool calls*. PII masking (`AGENT_GUARD_PII_HOOK_MODE=mask`) is likewise regex-based: it can over-match (a version string read as an IPv4) or miss locale formats it has no rule for. Both the secret redactor and the PII masker walk JSON string *values* only — a secret or PII string that appears as an object *key* is left unmasked, because rewriting keys could collapse two distinct keys onto one placeholder and drop an entry. Treat output masking as defense in depth and keep real secrets and personal data out of agent sessions entirely.\n- **Bash detection is pattern-based.** The denylist targets common-accident and obvious-malicious idioms; an actively-evading agent can craft a command that matches none of them. Treat shell blocking as defense in depth, not a complete adversarial boundary.\n- **User-typed shell-escape commands bypass every hook.** Agent Guard works entirely through tool-use hooks (`PreToolUse` / `PostToolUse`) and git hooks. A command the user runs directly through the host's interactive shell escape — for example a `!`-prefixed command typed at the agent prompt — never becomes a tool call, so **no** Agent Guard hook fires: neither the input block nor the output redactor. A secret that such a command prints (e.g. an env- or vault-reading CLI whose output is not redirected to `/dev/null`) lands in the session transcript unmasked. The recommended mitigation is to run such commands via `agx \u003ccmd\u003e` / `agent-guard exec -- \u003ccmd\u003e` (see [Shell integration](#shell-integration-masking--shell-escape-output)) so their output is masked *before* it reaches the model. Alternatively, run secret-loading commands *through* the agent's tools so the hooks apply, or redirect their output away from the transcript — both streams, since many CLIs print credentials or secret-bearing diagnostics to stderr (`\u003e/dev/null 2\u003e\u00261`).\n\nFor defense in depth, pair Agent Guard with GitHub Secret Scanning / Push Protection and a secrets manager so credentials never reach the working tree.\n\n## Configuration\n\nOverride bundled policies with environment variables:\n\n```sh\nAGENT_GUARD_GITLEAKS_CONFIG=/path/to/gitleaks.toml\nAGENT_GUARD_DENY_READ_PATHS=/path/to/deny-read-paths.txt\nAGENT_GUARD_DENY_BASH_PATTERNS=/path/to/deny-bash-patterns.txt\nAGENT_GUARD_PII_PROVIDER=regex\nAGENT_GUARD_PII_REDACT_URL=http://127.0.0.1:8080/api/redact\nAGENT_GUARD_PII_HOOK_MODE=off\nAGENT_GUARD_OUTPUT_REDACT=mask\n```\n\nSet `AGENT_GUARD_OUTPUT_REDACT=off` to disable masking secret-like values in tool output (default `mask`). Set `AGENT_GUARD_PII_HOOK_MODE` to `block` (block PII in tool inputs), `mask` (mask PII in tool outputs + hard-block Tier-2 PII inputs), or `off` (default).\n\nProject-local `.gitleaks.toml` files are not automatically trusted.\n\n## Checksums and Auto-Install\n\n`agent-guard setup --install` can install `gitleaks`, but only with an explicit checksum:\n\n```sh\nagent-guard checksum\nagent-guard setup --install \\\n  --gitleaks-version 8.30.1 \\\n  --gitleaks-checksum \u003csha256-for-this-os-and-arch\u003e\n```\n\nThe checksum helper prints all supported OS / arch values and paste-ready snippets for CLI setup and GitHub Actions.\n\n## Host Integrations\n\nAgent Guard shares its scanner implementation across Claude Code and Codex, but keeps host wiring explicit:\n\n- `plugins/agent-guard/bin/agent-guard`, `config/`, and `scripts/` are shared.\n- Claude Code uses `.claude-plugin/plugin.json`, `commands/`, and `hooks/hooks.json`.\n- Codex uses `.codex-plugin/plugin.json` and the plugin-root `hooks.json` companion file.\n- Codex does not auto-discover `commands/`, so on-demand workflows use the binary directly.\n\n## Development\n\n```sh\nmake help\nmake test\nmake smoke-test\nmake scan\nmake scan-staged\nmake checksum\n```\n\n`make smoke-test` uses real `git`, `jq`, and `gitleaks` in temporary projects. `make test` is the faster deterministic routing suite and uses a mock scanner for some cases.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeongjaesoon%2Fagent-guard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeongjaesoon%2Fagent-guard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeongjaesoon%2Fagent-guard/lists"}