jev-pii-checker
September 20, 2026 · View on GitHub
CLI for scanning text and files for PII using TypeSafe's Jev model, regex patterns, and word segmentation.
📖 Documentation — getting started, CLI reference, how the three layers work, categories and sensitivity levels, limitations.
Warning
The scanned text is sent to TypeSafe's Jev API. Detection happens on their servers, so this tool is not a local-only guard: everything you scan leaves your machine. Use it only on data you are allowed to hand to a third party, such as text you were going to send to an LLM anyway, and check TypeSafe's data-retention terms before scanning anything you would not send there directly. For a guard that never sends anything, see sensitive-canary. Details in SECURITY.md.
Features
Three-layer detection:
- Gate — 13 PII category Nouls (person name, email/phone, postal address, date of birth, government ID, financial account, health info, biometric, IP address, SNS handle, employment, race/religion) + 3-level sensitivity score (none/low/high, IBM taxonomy)
- Regex — Extract emails, JP/intl phones, digit strings (10–16 chars); filter corporate addresses (noreply@, 0120-, server IPs)
- Segmentation — Generate person-name candidates using
Intl.Segmenter, query Jev for judgment, assemble overlapping spans, attach title suffixes
Output:
- JSON: machine-readable (categories, sensitivity level, findings with spans)
- Human: compact table per file, plaintext
- Exit codes: 0 = none, 1 = error, 2 = severity ≥ threshold
Measured Results
- Gate accuracy: 100% on person_name / email_or_phone / phone presence (IBM corpus)
- Sensitivity levels: 22/24 correct (seminar/clinic context distinction works)
- Digit disambiguation: correctly classifies credit cards, My Numbers, order numbers, product serials
Install
Install globally from npm:
bun install -g @coo-quack/jev-pii-checker
# or run without installing
bunx @coo-quack/jev-pii-checker report.txt --json
Requires Node.js 20+ or Bun.
From source
bun install
bun run build
jev-pii-checker --version
Usage
Scan stdin
export TYPESAFE_API_KEY="your-key-here"
echo "佐藤健一郎さんの携帯は090-1234-5678、メールはk.sato@example.co.jpです。" \
| jev-pii-checker --json
Scan files
jev-pii-checker file1.txt file2.txt --json --show-values
Exit on severity
jev-pii-checker data.txt --fail-on high
echo $? # 2 if high-sensitivity PII detected, 0 otherwise
Masking (default)
By default, PII values are masked as first2…last1:
john@example.com→jo…m090-1234-5678→09…8
Use --show-values to disable masking (for debugging).
Flags
--json Output JSON (default: human-readable)
--threshold <0-1> Gate probability threshold (default: 0.5)
--span-threshold <0-1> Name candidate threshold (default: 0.8)
--no-spans Skip name extraction (regex only)
--fail-on none|low|high Exit with code 2 if sensitivity >= level (default: none)
--show-values Show unmasked PII values
--max-chars <n> Chunk size in bytes (default: 4000)
--model <id> TypeSafe model ID (optional; uses SDK default)
--concurrency <n> Parallel requests (default: 4; not yet implemented)
--help Show help
--version Show version
Environment
TYPESAFE_API_KEY— Required. TypeSafe API key.
Setting up the key:
# If your key file has no `export`:
set -a
source ~/.config/chata/typesafe.env
set +a
jev-pii-checker file.txt
Limitations
- Public figures: Cannot distinguish historical or public figures (e.g., "Natsume Soseki" may be flagged as a person name). Names are always treated as PII unless reviewed manually.
- Borderline HR/discipline records: Sensitivity for confidential performance reviews and disciplinary records can flip between low and high across runs when the model's probabilities sit near 0.5 (e.g., 0.47/0.53 low/high boundary). Run multiple times for high-confidence assessments.
- Candidate rules are list-based: Political/military/legal/clerical titles and form labels (Name, Email, Phone, Subject, etc.) are hard-coded. Unknown titles may still be merged into a name.
- Checksum verification: Credit card Luhn checksums and passport/ID formats are not validated, so synthetic or invalid numbers may be flagged.
- Code/config snippets: JSON, SQL, regex patterns treated as plain text; variables named like PII attributes (e.g.,
person_name,user_id,phone_number) may be over-reported. - Organization names: Out of scope; cannot identify company/brand/institution names.
Development
bun install
bun run dev file.txt
bun run lint
bun run format
bun test
bun run build
Integration tests
set -a
source ~/.config/chata/typesafe.env
set +a
JEV_PII_INTEGRATION=1 bun test tests/integration.test.ts
License
MIT — see LICENSE for details.