-
Notifications
You must be signed in to change notification settings - Fork 9
feat(plugin): add Claude Code plugin #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| "name": "foxguard", | ||
| "description": "Fast local security scanning in Claude Code: auto-scan edited files, slash commands for full scans, diff scans, post-quantum audits, and TUI triage. Powered by the foxguard Rust scanner — 170+ rules across 10 languages with cross-file taint tracking.", | ||
| "version": "0.1.0", | ||
| "author": { | ||
| "name": "PwnKit Labs", | ||
| "url": "https://foxguard.dev" | ||
| }, | ||
| "homepage": "https://foxguard.dev", | ||
| "repository": "https://github.com/PwnKit-Labs/foxguard", | ||
| "license": "MIT" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| # foxguard for Claude Code | ||
|
|
||
| Live security scanning inside [Claude Code](https://code.claude.com). Every file Claude writes or edits is auto-scanned by [foxguard](https://foxguard.dev) — findings are fed straight back so Claude self-corrects before bad patterns land. | ||
|
|
||
| ## What you get | ||
|
|
||
| - **PostToolUse auto-scan** — every `Write` / `Edit` / `MultiEdit` triggers `foxguard --format json` on the changed file. Medium+ findings are surfaced to Claude on stderr; clean files are silent. | ||
| - **SessionStart preamble** — Claude starts each session with foxguard's secure-coding defaults already in context. | ||
| - **Slash commands** for on-demand scans: | ||
| - `/foxguard:setup` — verify install, set severity threshold | ||
| - `/foxguard:scan [path]` — full scan, grouped and triaged by severity | ||
| - `/foxguard:diff-scan [base]` — only what this branch introduces vs `main` | ||
| - `/foxguard:pq-audit [path]` — post-quantum readiness with CNSA 2.0 deadlines | ||
| - `/foxguard:secrets [path]` — hardcoded secrets, tokens, private keys | ||
| - `/foxguard:triage [args]` — instructions for the interactive TUI | ||
| - **`secure-coding` skill** — model-invoked remediation guidance for command exec, SQL, path traversal, SSRF, secrets, randomness, crypto, and deserialization. | ||
|
|
||
| ## Install | ||
|
|
||
| ### 1. Install foxguard | ||
|
|
||
| Pick whichever fits: | ||
|
|
||
| ```sh | ||
| # Prebuilt binary — fastest | ||
| curl -fsSL https://foxguard.dev/install.sh | sh | ||
|
|
||
| # Homebrew | ||
| brew install pwnkit-labs/foxguard/foxguard | ||
|
|
||
| # npm (global or zero-install) | ||
| npm i -g foxguard # or just: npx foxguard | ||
|
|
||
| # cargo | ||
| cargo install foxguard | ||
| ``` | ||
|
|
||
| Verify with `foxguard --version`. | ||
|
|
||
| ### 2. Install the plugin | ||
|
|
||
| Until the plugin is published to a marketplace, load it directly from this repo: | ||
|
|
||
| ```sh | ||
| claude --plugin-dir /path/to/foxguard/plugins/claude-code | ||
| ``` | ||
|
|
||
| Or add to your settings to load it permanently. Once installed, run `/foxguard:setup` to confirm it's wired up. | ||
|
|
||
| ## Configuration | ||
|
|
||
| Environment variables: | ||
|
|
||
| | Var | Default | Purpose | | ||
| | :-- | :-- | :-- | | ||
| | `FOXGUARD_HOOK_SEVERITY` | `medium` | Minimum severity for the auto-scan. One of `low|medium|high|critical`. | | ||
|
|
||
| Set in your shell profile or in Claude Code's environment to tune noise. | ||
|
|
||
| ## How the auto-scan looks | ||
|
|
||
| After Claude edits a file, if foxguard finds an issue, Claude sees something like: | ||
|
|
||
| ``` | ||
| foxguard found 1 issue(s) in src/auth.py (severity >= medium): | ||
|
|
||
| [CRITICAL] py/no-command-injection at line 42 | ||
| os.system() called with dynamic argument — risk of command injection | ||
| CWE-78 | ||
| > os.system("ls " + user_input) | ||
|
|
||
| Fix these before continuing. Run `/foxguard:scan` for the full repo or `/foxguard:triage` for the interactive TUI. | ||
| ``` | ||
|
Comment on lines
+64
to
+73
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix markdownlint MD040: add a fenced-code language. The example block under “How the auto-scan looks” starts with a bare triple-backtick (line 64 per hint). Specify a language (e.g. Suggested change-```
+```text
foxguard found 1 issue(s) in src/auth.py (severity >= medium):
...🧰 Tools🪛 markdownlint-cli2 (0.22.1)[warning] 64-64: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||
|
|
||
| Claude is expected to fix the finding (or explain why it's a false positive) before moving on. | ||
|
|
||
| ## Layout | ||
|
|
||
| ``` | ||
| plugins/claude-code/ | ||
| ├── .claude-plugin/plugin.json # manifest | ||
| ├── hooks/hooks.json # PostToolUse + SessionStart | ||
| ├── scripts/ | ||
| │ ├── scan-edited-file.sh # the PostToolUse scanner | ||
| │ └── secure-defaults.txt # SessionStart preamble | ||
| ├── skills/ | ||
| │ ├── setup/SKILL.md # /foxguard:setup | ||
| │ ├── scan/SKILL.md # /foxguard:scan | ||
| │ ├── diff-scan/SKILL.md # /foxguard:diff-scan | ||
| │ ├── pq-audit/SKILL.md # /foxguard:pq-audit | ||
| │ ├── secrets/SKILL.md # /foxguard:secrets | ||
| │ ├── triage/SKILL.md # /foxguard:triage | ||
| │ └── secure-coding/SKILL.md # model-invoked remediation guidance | ||
| └── README.md | ||
| ``` | ||
|
Comment on lines
+79
to
+95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix markdownlint MD040: add a fenced-code language. The “Layout” directory tree block also uses a bare triple-backtick (line 79 per hint). Add a language identifier like Suggested change-```
+```text
plugins/claude-code/
├── .claude-plugin/plugin.json # manifest
...Verify each finding against the current code and only fix it if needed. In |
||
|
|
||
| ## Notes | ||
|
|
||
| - The hook intentionally never blocks Claude on its own machinery: missing binary, parse errors, or unreadable inputs all exit `0`. Only real findings exit `2`. | ||
| - The hook calls `foxguard` from `PATH` first, then falls back to `npx --yes foxguard`. If neither is available it stays silent — run `/foxguard:setup` to fix that. | ||
| - `--severity medium` is the default cutoff. Drop to `low` for stricter coverage; raise to `high` for noisier projects. | ||
| - foxguard's exit codes: `0` clean, `1` findings, `2` error. The hook checks for findings via the JSON, not the exit code, so a piped error doesn't trigger a false alarm. | ||
|
|
||
| ## License | ||
|
|
||
| MIT — same as foxguard. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "hooks": { | ||
| "PostToolUse": [ | ||
| { | ||
| "matcher": "Write|Edit|MultiEdit|NotebookEdit", | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "${CLAUDE_PLUGIN_ROOT}/scripts/scan-edited-file.sh" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "SessionStart": [ | ||
| { | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "cat \"${CLAUDE_PLUGIN_ROOT}/scripts/secure-defaults.txt\"" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,44 @@ | ||||||
| #!/usr/bin/env bash | ||||||
| # PostToolUse hook: scan the file Claude just wrote/edited and feed findings back. | ||||||
| # | ||||||
| # Reads the Claude Code hook input JSON from stdin, extracts tool_input.file_path, | ||||||
| # runs `foxguard --format json` on it, and emits a compact summary on stderr with | ||||||
| # exit 2 when medium+ findings exist so Claude treats it as actionable feedback. | ||||||
| # Stays silent (exit 0) on clean files, missing tools, or unreadable inputs — a | ||||||
| # scanner hook should never block Claude on its own machinery. | ||||||
|
|
||||||
| set -uo pipefail | ||||||
|
|
||||||
| input=$(cat) | ||||||
|
|
||||||
| file_path=$(printf '%s' "$input" | jq -r '.tool_input.file_path // .tool_input.path // empty' 2>/dev/null) | ||||||
|
|
||||||
| [ -z "$file_path" ] && exit 0 | ||||||
| [ ! -f "$file_path" ] && exit 0 | ||||||
|
|
||||||
| # Resolve foxguard binary: prefer PATH, fall back to npx. | ||||||
| if command -v foxguard >/dev/null 2>&1; then | ||||||
| fg=(foxguard) | ||||||
| elif command -v npx >/dev/null 2>&1; then | ||||||
| fg=(npx --yes foxguard) | ||||||
| else | ||||||
| exit 0 | ||||||
| fi | ||||||
|
|
||||||
| min_severity="${FOXGUARD_HOOK_SEVERITY:-medium}" | ||||||
|
|
||||||
| findings=$("${fg[@]}" --format json --severity "$min_severity" "$file_path" 2>/dev/null) || true | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent option-style filename bypass in scanner invocation On Line 30, Suggested fix-findings=$("${fg[@]}" --format json --severity "$min_severity" "$file_path" 2>/dev/null) || true
+findings=$("${fg[@]}" --format json --severity "$min_severity" -- "$file_path" 2>/dev/null) || true📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
|
|
||||||
| [ -z "$findings" ] && exit 0 | ||||||
| [ "$findings" = "[]" ] && exit 0 | ||||||
|
|
||||||
| count=$(printf '%s' "$findings" | jq 'length' 2>/dev/null) | ||||||
| [ -z "$count" ] || [ "$count" = "0" ] && exit 0 | ||||||
|
|
||||||
| { | ||||||
| printf 'foxguard found %s issue(s) in %s (severity >= %s):\n\n' "$count" "$file_path" "$min_severity" | ||||||
| printf '%s' "$findings" | jq -r '.[] | " [\(.severity | ascii_upcase)] \(.rule_id) at line \(.line)\n \(.description)\n \(.cwe // "")\n > \(.snippet)\n"' | ||||||
| printf '\nFix these before continuing. Run `/foxguard:scan` for the full repo or `/foxguard:triage` for the interactive TUI.\n' | ||||||
| } >&2 | ||||||
|
|
||||||
| exit 2 | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| foxguard is active. Apply these secure-coding defaults when writing or editing code: | ||
|
|
||
| - Never concatenate user input into shell, SQL, or path strings. Use parameterized APIs (`subprocess` arg lists, prepared statements, `pathlib.Path` joins). | ||
| - Never hardcode secrets, tokens, or keys. Read from env vars or a secrets manager. Treat any string that looks like a credential as a finding. | ||
| - Validate and canonicalize paths before file ops; reject paths that escape the intended root after resolution. | ||
| - For HTTP fetchers, validate the destination host against an allowlist or block private IP ranges to avoid SSRF. | ||
| - Prefer post-quantum-ready primitives where the project already supports them; flag legacy RSA / ECDSA / ECDH usage in security-sensitive paths. | ||
| - Use `crypto.randomBytes` / `secrets` / `OsRng` for security-sensitive randomness — never `Math.random`, `rand()`, or `random.random()`. | ||
|
|
||
| After every Write/Edit, foxguard scans the touched file. If findings come back, fix them before continuing rather than working around them. Use `/foxguard:scan` for a full repo scan, `/foxguard:diff-scan` for changed-only review, `/foxguard:pq-audit` for post-quantum readiness, and `/foxguard:triage` for the interactive TUI. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| --- | ||
| description: Scan only changes vs a base branch — surfaces what this branch introduced | ||
| disable-model-invocation: true | ||
| --- | ||
|
|
||
| Run a diff scan to show only findings introduced on the current branch. | ||
|
|
||
| 1. Determine the base branch. If the user passed one as `$ARGUMENTS`, use it. Otherwise default to `main`, falling back to `master` if `main` doesn't exist (`git rev-parse --verify main`). | ||
| 2. Run via Bash: `foxguard diff "$BASE" . --format json --severity medium`. | ||
| 3. Parse the JSON output the same way as `/foxguard:scan` — group by file and severity, show rule id, line, description, and snippet. | ||
| 4. Specifically frame the report as "what this branch adds." If the count is zero, say so plainly — this branch introduces no new findings vs `$BASE`. | ||
| 5. For critical/high findings, propose fixes. Make clear that pre-existing findings on `$BASE` are not shown — those need a full `/foxguard:scan`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --- | ||
| description: Post-quantum cryptography audit — find legacy RSA/ECDSA/ECDH usage with CNSA 2.0 deadlines | ||
| disable-model-invocation: true | ||
| --- | ||
|
|
||
| Run a post-quantum readiness audit. | ||
|
|
||
| 1. Take an optional path from `$ARGUMENTS`, default to `.`. | ||
| 2. Run via Bash: `foxguard pqc "$PATH_OR_DOT" --format json --severity medium`. | ||
| 3. Parse the JSON. Each finding may include a `cnsa2Deadline` field — surface that prominently. CNSA 2.0 mandates deprecation of classical asymmetric crypto in security-sensitive paths by specific dates; findings nearer those deadlines are higher priority. | ||
| 4. Report: | ||
| - Total PQ-vulnerable call sites | ||
| - Breakdown by primitive (RSA, ECDSA, ECDH, etc.) — derive from `rule_id` or `description` | ||
| - For each finding: `file:line`, the legacy primitive, the recommended PQ replacement (e.g., ML-KEM, ML-DSA, hybrid suites) | ||
| 5. Note that classical primitives may still be acceptable in non-security paths (test fixtures, signed-binary verification of trusted releases). Ask the user about context before recommending wholesale rewrites. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --- | ||
| description: Run a full foxguard security scan on the repository or a specific path | ||
| disable-model-invocation: true | ||
| --- | ||
|
|
||
| Run a full foxguard scan and walk the user through any findings. | ||
|
|
||
| 1. If the user passed a path as `$ARGUMENTS`, scan that. Otherwise scan `.`. | ||
| 2. Run via Bash: `foxguard --format json --severity medium "$PATH_OR_DOT"`. Capture stdout — exit 1 just means findings were detected, that's expected. | ||
| 3. Parse the JSON array. Group findings by `file`, then by `severity` (critical → high → medium). For each finding show: `[SEVERITY] rule_id` at `file:line` with the description and the `snippet`. | ||
| 4. Summarize at the top: total count, breakdown by severity, top 3 files by finding count. | ||
| 5. For each critical/high finding, propose a concrete fix the user can accept. Don't apply edits until the user confirms. | ||
| 6. If the JSON output is large (>50 findings), suggest `/foxguard:triage` for the interactive TUI instead of scrolling text. | ||
|
|
||
| If the scan errors (exit 2), report the error verbatim and suggest `/foxguard:setup`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --- | ||
| description: Scan for hardcoded secrets, API tokens, and private keys | ||
| disable-model-invocation: true | ||
| --- | ||
|
|
||
| Run a secrets-focused scan. | ||
|
|
||
| 1. Take an optional path from `$ARGUMENTS`, default to `.`. | ||
| 2. Run via Bash: `foxguard secrets "$PATH_OR_DOT" --format json`. | ||
| 3. Parse the JSON. Secret values are redacted by foxguard — do not try to reconstruct them. | ||
| 4. Report each finding: `file:line`, the `rule_id` (e.g., `secret/aws-access-key`, `secret/github-pat`), and the risk class (cloud key, VCS token, payment, generic high-entropy, private key, etc.). | ||
| 5. For each finding propose the right remediation: | ||
| - Cloud / SaaS tokens: rotate immediately at the issuer, then move to env vars or a secrets manager. | ||
| - Private keys: regenerate, never just delete from history without rotation. | ||
| - High-entropy strings that are NOT secrets: add to a baseline via `foxguard secrets --write-baseline .foxguard-secrets-baseline.json` — explain this is a suppression, not a fix. | ||
| 6. Remind the user that removing a leaked secret from the working tree does NOT remove it from git history. If the file was ever committed, the secret must be considered compromised. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,52 @@ | ||||||
| --- | ||||||
| description: Apply foxguard's secure-coding patterns when writing or fixing security-sensitive code. Use proactively when handling user input, shelling out, building SQL, doing file I/O, fetching URLs, generating randomness, or touching crypto. | ||||||
| --- | ||||||
|
|
||||||
| Use this guidance when writing or fixing code that touches any of these surfaces. Match the language patterns to what foxguard's rules look for so the auto-scan stays clean. | ||||||
|
|
||||||
| ## Command execution | ||||||
|
|
||||||
| - Never pass concatenated strings to a shell. Use argument lists. | ||||||
| - Python: `subprocess.run(["git", "log", branch], check=True)` — never `subprocess.run(f"git log {branch}", shell=True)`. | ||||||
| - Node: `execFile("git", ["log", branch])` — never `exec(`git log ${branch}`)`. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix malformed inline code span in Node example On Line 11, nested backticks break Markdown rendering for the Suggested fix- - Node: `execFile("git", ["log", branch])` — never `exec(`git log ${branch}`)`.
+ - Node: `execFile("git", ["log", branch])` — never `exec("git log " + branch)` (or template-string shell commands).📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| - Go: `exec.Command("git", "log", branch)` — never `exec.Command("sh", "-c", "git log "+branch)`. | ||||||
| - If a shell is genuinely required, validate the input against a strict allowlist regex first. | ||||||
|
|
||||||
| ## SQL | ||||||
|
|
||||||
| - Use parameterized queries everywhere. `cursor.execute("SELECT * FROM u WHERE id = ?", (uid,))` — not f-strings or `%`. | ||||||
| - ORMs are fine; raw `query.format(...)` / `+` concat is not. | ||||||
|
|
||||||
| ## Path traversal | ||||||
|
|
||||||
| - Resolve and bound paths: `Path(root).resolve() / Path(name).name` — strip directory components from untrusted names. | ||||||
| - Reject inputs that contain `..`, absolute paths, or null bytes before joining. | ||||||
|
|
||||||
| ## SSRF | ||||||
|
|
||||||
| - For outbound HTTP from user-supplied URLs: parse the URL, resolve the host, and reject private/loopback/link-local ranges (`10.0.0.0/8`, `127.0.0.0/8`, `169.254.0.0/16`, `172.16.0.0/12`, `192.168.0.0/16`, `::1`, `fc00::/7`, `fe80::/10`) and metadata endpoints (`169.254.169.254`). | ||||||
| - Prefer an allowlist over a denylist when the destinations are known. | ||||||
|
|
||||||
| ## Secrets | ||||||
|
|
||||||
| - Read from env / secrets manager, never from string literals. `os.getenv("API_TOKEN")` — not `API_TOKEN = "sk-..."`. | ||||||
| - Even in tests, prefer fixtures from env or a vault. High-entropy strings in code will be flagged. | ||||||
| - Never log secrets. Redact before logging. | ||||||
|
|
||||||
| ## Randomness | ||||||
|
|
||||||
| - Security-sensitive: `secrets.token_urlsafe`, `crypto.randomBytes`, `OsRng`, `crypto/rand`. Never `random.random()`, `Math.random()`, `rand()`, `math/rand`. | ||||||
| - Non-security (jitter, sampling): the fast PRNGs are fine. | ||||||
|
|
||||||
| ## Crypto | ||||||
|
|
||||||
| - New code: AES-GCM or ChaCha20-Poly1305 for symmetric; Ed25519 for signatures; X25519 for key agreement (until PQ rollout). Never DES, 3DES, RC4, MD5, SHA-1. | ||||||
| - Asymmetric crypto in long-lived security paths: prefer hybrid suites (X25519+ML-KEM) where the toolchain supports it. Use `/foxguard:pq-audit` to find legacy usage. | ||||||
| - Password hashing: argon2id or bcrypt. Never plain SHA-2 or unsalted hashes. | ||||||
|
|
||||||
| ## Deserialization | ||||||
|
|
||||||
| - Never `pickle.load`, `yaml.load` (use `safe_load`), `Marshal.load`, or `unserialize` on untrusted input. | ||||||
| - For JSON, deserialize into a typed schema (pydantic, zod, serde) — don't trust the shape. | ||||||
|
|
||||||
| When you finish a fix, the PostToolUse hook will re-scan the file and confirm it's clean. If a finding persists, read the rule's description carefully — the remediation is usually one of the patterns above. | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| --- | ||
| description: Verify foxguard is installed and ready for the Claude Code plugin | ||
| disable-model-invocation: true | ||
| --- | ||
|
|
||
| Walk the user through getting foxguard installed and the plugin working: | ||
|
|
||
| 1. Run `foxguard --version` via the Bash tool. If it succeeds, report the version and tell the user the plugin is ready — every Write/Edit will now be auto-scanned. | ||
| 2. If `foxguard` is not on PATH, offer the install options in this order: | ||
| - **Prebuilt binary (fastest)**: `curl -fsSL https://foxguard.dev/install.sh | sh` | ||
| - **Homebrew** (macOS): `brew install pwnkit-labs/foxguard/foxguard` | ||
| - **npm**: `npm i -g foxguard` or zero-install via `npx foxguard` | ||
| - **cargo**: `cargo install foxguard` | ||
| Ask which the user prefers; do NOT install without confirmation. | ||
| 3. Recommend the user run `foxguard init` inside their repo to add a pre-commit hook so foxguard also catches issues outside Claude Code sessions. | ||
| 4. Mention the env vars they can tune: | ||
| - `FOXGUARD_HOOK_SEVERITY` — minimum severity for auto-scan (default `medium`; values: `low|medium|high|critical`) | ||
|
|
||
| Finish with a one-line confirmation of which version is active and which severity threshold the auto-scan is using. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --- | ||
| description: Open the foxguard interactive TUI for triaging findings | ||
| disable-model-invocation: true | ||
| --- | ||
|
|
||
| Launch the foxguard TUI for interactive triage. | ||
|
|
||
| 1. Tell the user the TUI is an interactive terminal app and Claude cannot drive it — they need to interact with it directly in their terminal. | ||
| 2. Suggest they run one of these in their own terminal (NOT via your Bash tool, which can't render a TUI): | ||
| - `foxguard tui` — full repo | ||
| - `foxguard tui --changed` — staged/unstaged files only | ||
| - `foxguard tui --diff main` — diff vs main | ||
| - `foxguard tui --secrets` — secrets mode | ||
| - `foxguard tui --explain` — show dataflow traces in the detail pane | ||
| 3. Pass through any path or flags from `$ARGUMENTS`. | ||
| 4. After they finish triaging, offer to follow up with `/foxguard:scan` to re-verify the codebase is clean. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix markdownlint MD056: table column count.
Your configuration table around lines 54-57 is triggering
markdownlint-cli2MD056 (“Expected: 3; Actual: 6”). Adjust the table to unambiguously define 3 columns in the header/separator, and avoid any accidental extra|characters.Example normalization
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 56-56: Table column count
Expected: 3; Actual: 6; Too many cells, extra data will be missing
(MD056, table-column-count)
🤖 Prompt for AI Agents