# Check Before Commit

> Scan staged git changes for sensitive information before committing. Checks for API keys, credentials, infrastructure details, PII, and sensitive config files. Behavior adapts to repo visibility: blocks on public repos, warns on private repos. Supports project-level allowlist via .claude/allowlist.json. Use when: committing code, before commit, check sensitive info, pre-commit check, 扫描泄露, 检查敏感信息, commit 前检查.

- Skill: `jamesshi96/check-before-commit` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add jamesshi96/check-before-commit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jamesshi96/check-before-commit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: jamesshi96 (https://skillmd.com/u/jamesshi96)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jamesshi96/check-before-commit

---


# Check Before Commit

Pre-commit sensitive information scanner. Adapts behavior based on repo visibility.

## Trigger

- Automatically before `commit-commands:commit`
- Manual: `/check-before-commit`

## Workflow

### Step 1: Detect repo visibility

Run:
```bash
gh repo view --json visibility --jq .visibility 2>/dev/null
```

- If returns `PUBLIC` → strict mode (block on findings)
- If returns `PRIVATE` or `INTERNAL` → warn mode (report but don't block)
- If fails → ask user: "Can't detect repo visibility. Is this a public or private repo?"

### Step 2: Get staged changes

Run:
```bash
git diff --cached
```

If no staged changes, report "No staged changes to scan" and exit.

### Step 3: Load allowlist (optional)

Check for `.claude/allowlist.json` in project root. If exists, load the `allowed` array.
Items in the allowlist are skipped during scanning.

### Step 4: Scan staged changes

#### Layer 1: Regex scan (deterministic)

Scan the diff output for these patterns:

**Secrets & credentials:**
```
sk-(live|test|proj)-[a-zA-Z0-9]{20,}
AKIA[0-9A-Z]{16}
ghp_[a-zA-Z0-9]{36}
gho_[a-zA-Z0-9]{36}
xox[bpras]-[a-zA-Z0-9-]{10,}
-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----
-----BEGIN PGP (PRIVATE KEY BLOCK|SIGNATURE)-----
```

**Infrastructure:**
```
# Private IPs
10\.\d{1,3}\.\d{1,3}\.\d{1,3}
172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}
192\.168\.\d{1,3}\.\d{1,3}

# Local paths (non-generic)
/Users/[^/\s]+/[^\s]*(?!\.(git|npm|cache))
/C/Users/[^/\s]+/
/home/[^/\s]+/

# Database connection strings
(postgres|mysql|mongodb|redis)://[^\s]+:[^\s]+@
```

**Sensitive config files (check staged filenames):**
```
.env
.env.*
*.pem
*.key
*.p12
*.pfx
.npmrc
.netrc
.ssh/
credentials
service-account*.json
```

For each regex match:
1. Check if the matched value is in the allowlist → skip if yes
2. Otherwise record as finding

#### Layer 2: Semantic scan (Claude judgment)

Review the diff content for PII that regex can't reliably catch:
- Phone numbers (especially Chinese mobile: 1[3-9]\d{9})
- National ID numbers (身份证号)
- Real personal names in comments or config (not variable names or git authors)
- Personal email addresses in non-git-config context

Use context to distinguish:
- `var userName = "test"` → OK, variable value
- `// Contact 张三 at 13800138000` → finding, PII in comment
- `sk-test-1234` in test fixture → check allowlist, suggest adding if not present

### Step 5: Report findings

**No findings:**
Output: "No sensitive information detected. Safe to commit."
→ Allow commit to proceed.

**Findings + PUBLIC repo (strict mode):**
Block the commit. Output each finding with:
- File and line
- Category (secret / infrastructure / PII / config file)
- The matched content (partially masked for secrets)
- Suggested action (remove / add to allowlist / use env variable)

Wait for user to fix or explicitly override.

**Findings + PRIVATE repo (warn mode):**
List the findings as a warning. Output same details but don't block.
User can proceed or choose to fix.

## Allowlist Management

When a finding is a false positive, suggest:
> "This appears to be a test/example value. Add to `.claude/allowlist.json` to skip in future scans?"

Format of `.claude/allowlist.json`:
```json
{
  "allowed": [
    "sk-test-xxx",
    "example@company.com",
    "10.0.0.1"
  ]
}
```

If the file doesn't exist, offer to create it when the first false positive is found.

## Integration with commit-commands:commit

When triggered as part of the commit workflow:
1. Run this scan first
2. If scan blocks (public repo + findings) → stop, don't commit
3. If scan passes → proceed to normal commit flow

