Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ A privacy-first plugin for Claude Code that scans prompts for sensitive data and
- ✅ **Works locally** - all scanning happens on your machine
- ✅ **Zero configuration** - works out of the box
- ✅ **Detailed reporting** - shows exactly what was detected
- ✅ **Toggle individual rules** - via `disabledRules`, a `list_rules` MCP tool, or `npx claude-code-privacy-guard rules` for a local web UI

## Installation

Expand Down Expand Up @@ -74,13 +75,14 @@ My API key is sk-proj-abc123xyz and email is john@example.com
🛡️ Privacy Guard blocked this prompt

Found 2 sensitive item(s):
- API_KEY: sk-proj-abc123xyz...
- EMAIL: john@example.com...
- OpenAI API Key (openai-api-key): sk-p…3xyz
- Email Address (email-address): john.com

Risk Score: 100/100
Secrets: 1 | PII: 1

Please remove or anonymize sensitive data before proceeding.
To disable a rule, add its ID to "disabledRules" in .privacy-guard.json.
```


Expand All @@ -94,7 +96,7 @@ file.
| Option | Type | Default | Status |
| --- | --- | --- | --- |
| `enabled` | `boolean` | `true` | ✅ Implemented. Set to `false` to disable the plugin entirely without uninstalling it. |
| `disabledRules` | `string[]` | `[]` | ✅ Implemented. Rule IDs to skip - see the built-in `id` fields in `src/scanner/detectors.ts` or the `name` fields in `data/regex_list_1.json` for external rules. |
| `disabledRules` | `string[]` | `[]` | ✅ Implemented. Rule IDs to skip - see [Managing Rules](#managing-rules) below for how to discover and toggle IDs. |
| `externalRulesJsonPath` | `string` | `./data/regex_list_1.json` | ✅ Implemented. Path (relative to the config file's directory) to the external regex dataset. |
| `externalRulesMode` | `"coding-only" \| "all"` | `"coding-only"` | ✅ Implemented. `"coding-only"` filters the external dataset down to rules whose name/description mentions a coding-secret keyword (key, token, secret, password, private key, etc.); `"all"` loads every external rule. |
| `strictMode` | `boolean` | `false` | ⚠️ Accepted in config but not yet enforced by the scanner ([#6](https://github.com/datumbrain/claude-code-privacy-guard/issues/6)). |
Expand All @@ -113,6 +115,22 @@ Example:
}
```

## Managing Rules

Every detection rule - built-in and external - has a stable `id` (e.g. `email-address`, `openai-api-key`, `external-slack-api-token`). Blocked prompts now show each finding's ID directly, so you always know what to put in `disabledRules`.

To see and toggle every rule at once, run:

```bash
npx claude-code-privacy-guard rules
```

This starts a local-only web UI (bound to `127.0.0.1`, never exposed to your network) listing every rule with its ID, title, severity, and category. Toggling a rule saves automatically to `disabledRules`.

It edits whichever `.privacy-guard.json` `ConfigLoader.findConfig` would resolve for the directory you run it from: an existing project-level config always wins, but if none exists anywhere up the directory tree it falls back to `~/.privacy-guard.json` - a systemwide default that applies to every project, since Privacy Guard is protecting you, not one repo. Run it from `~` (or any directory with no project-level config) to edit that global default; run it from inside a specific project to create or edit a project-level override instead. The page and console output both tell you which one you're editing.

If you're working inside a Claude Code chat session instead, the MCP server also exposes a `list_rules` tool that returns the same id/title/severity/category/enabled data for each rule.

## Development

```bash
Expand Down
16 changes: 16 additions & 0 deletions dist/cli/config-writer.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Reads and writes the disabledRules array in .privacy-guard.json without
* disturbing any other keys the user has set.
*/
/**
* Resolves which config file to edit. An existing project-level config
* (found by searching upward from cwd) always wins, since it's an explicit
* per-project override. Otherwise this falls back to the user's home
* directory rather than creating a new file in whatever project the CLI
* happened to be run from - Privacy Guard protects the person, not one repo,
* so a systemwide default is the sane default for a first save.
*/
export declare function resolveConfigPath(startDir?: string): string;
export declare function isGlobalConfigPath(configPath: string): boolean;
export declare function writeDisabledRules(configPath: string, disabledRules: string[]): void;
//# sourceMappingURL=config-writer.d.ts.map
1 change: 1 addition & 0 deletions dist/cli/config-writer.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions dist/cli/config-writer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/cli/config-writer.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions dist/cli/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env node
/**
* claude-code-privacy-guard CLI
*
* Usage: npx claude-code-privacy-guard rules
*/
export {};
//# sourceMappingURL=index.d.ts.map
1 change: 1 addition & 0 deletions dist/cli/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions dist/cli/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/cli/index.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions dist/cli/page.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Self-contained HTML page for the local rules-picker UI. No external
* assets/CDNs - everything is inlined so it works fully offline.
*/
export interface RuleRow {
id: string;
title: string;
severity: string;
category: string;
source: 'builtin' | 'external';
disabled: boolean;
}
export declare function renderPage(rules: RuleRow[], token: string, configPath: string, isGlobal: boolean): string;
//# sourceMappingURL=page.d.ts.map
1 change: 1 addition & 0 deletions dist/cli/page.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

145 changes: 145 additions & 0 deletions dist/cli/page.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/cli/page.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions dist/cli/server.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Local-only HTTP server for the rules-picker UI. Binds to loopback only,
* requires a random per-run token on the save endpoint (defense in depth -
* the JSON content-type already blocks simple cross-origin POSTs), and
* shuts itself down after a period of inactivity (saving keeps it alive so
* you can toggle and save again without restarting).
*/
export declare function startRulesServer(): Promise<void>;
//# sourceMappingURL=server.d.ts.map
1 change: 1 addition & 0 deletions dist/cli/server.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading