Find and redact secrets in your AI coding agent's local history. Fully offline.
Watch the full clip with sound
Prevention: Don't paste API keys into cloud-backed AI agents at all. The key transits the provider's servers before it ever hits your disk.
If you already did: agentsweep removes the remaining local attack vector: supply-chain malware and compromised packages that scan your disk for credentials. Your files never leave your machine.
31 agents supported: Claude Code · Codex · OpenCode · Cursor · Windsurf · Aider · Cline · Kilo Code · Roo Code · PearAI · Trae · Void · Gemini CLI · Qwen Code · Continue · Open Interpreter · GitHub Copilot Chat · OpenClaw · Hermes · Goose · llm (Datasette) · Warp · Crush · Grok CLI · Kiro CLI · Zed · Codebuff · Plandex · Junie · Mentat · JetBrains AI
Experimental sources (Warp, Crush, Grok CLI, Kiro CLI, Zed, Codebuff, Plandex, Qwen Code, PearAI, Trae, Void, Junie, Mentat, JetBrains AI) have storage paths/formats derived from research but not yet verified against a real install. Scanning is safe: a wrong path finds nothing. They may under-report until confirmed. They're tagged
(experimental)in the picker and print a notice on scan.
201 detection rules: AWS, GitHub, Stripe, OpenAI, Anthropic, Google, Slack, Discord, HuggingFace, JWT, PEM keys, DB URLs, BIP-39 seed phrases, and many more
Alpha: every destructive step is gated, backed up, and reversible with one command
Claude Code (and every other AI coding CLI) stores your full conversation history as plain-text JSONL on disk, under ~/.claude/projects/ for Claude Code and ~/.codex/sessions/ for OpenAI Codex. Anything you paste, whether an AWS key, a .env file, or a database URL, sits in clear text indefinitely. A typical dev's history accumulates dozens of secrets over months, usually unnoticed.
agentsweep scans that history, tells you what leaked, and can redact the secret values in place while preserving the JSONL structure byte-for-byte. It also tells you which keys to rotate, with the right revocation URL for each provider.
Scope of protection: agentsweep is fully local and offline. It reads and writes only files on your machine and makes zero network calls. It removes one attack vector: secrets sitting in local history files. It does not affect what your AI provider already received. When you paste a key into Claude Code, Cursor, or any cloud-backed agent, that key already transited the provider's servers before it hit disk. If that concerns you, consider a locally-hosted model (Ollama, LM Studio, OpenCode) where nothing leaves your machine, which pairs well with agentsweep.
Supply chain attacks are accelerating. In 2024 and 2025, a wave of malicious npm and PyPI packages (sha256-universal, shailulid, hundreds of typosquats) were caught exfiltrating developer credentials off the machine that installed them. They target environment variables, .env files, shell history, SSH keys, and now AI agent history files.
AI coding assistants have created a new category of credential exposure that didn't exist two years ago:
- You paste a production API key into Claude Code to debug something → it's now in
~/.claude/projects/*/conversations/*.jsonlforever - A compromised npm package runs
postinstall→ scans common paths → finds your JSONL history → exfiltrates 50 API keys in one request - You rotate the key you used in public but forget the dozen others in your history
- Meanwhile your history grows: every
.envyou asked an AI to help with, every DB URL you shared for debugging, every token you pasted for a one-liner
AI agent history holds full context, not just the commands a shell history keeps. Attackers already scan for it. agentsweep cleans it up before that happens.
pip install uv # get uv (skip if you already have it)
uv tool install agentsweep # install — adds `agentsweep` and `asweep` to PATH
asweep # run — interactive menu guides you through everythingNo virtualenv to activate and no PATH fiddling. uv tool install gives the command its own isolated environment.
agentsweep runs a fixed 5-stage pipeline. scan stops after stage 3; fix continues through redaction.
flowchart LR
A("🔍 DISCOVER\nwalk history dirs\nstream file list") --> B("⚡ SCAN\nAho-Corasick pre-filter\n201 regex rules + BIP-39")
B --> C{"secrets\nfound?"}
C -- "none" --> D("✅ CLEAN\nexit 0")
C -- "found" --> E("📋 FINDINGS\nshow report\nexit 1")
E -. "scan only" .-> F("⚠️ ROTATE\nkeys still live")
E -- "type REDACT" --> G("✏️ REDACT\natomic write · .bak backup\npost-write JSON validation")
G --> H("🔑 ROTATE\nper-provider\nrevocation links")
style A fill:#1e3a5f,color:#fff,stroke:#2d5986
style B fill:#1e3a5f,color:#fff,stroke:#2d5986
style C fill:#4a3728,color:#fff,stroke:#7a5c3f
style D fill:#1a4731,color:#fff,stroke:#2d7a52
style E fill:#4a3a1e,color:#fff,stroke:#7a6030
style F fill:#4a2020,color:#fff,stroke:#8b3a3a
style G fill:#1e3a5f,color:#fff,stroke:#2d5986
style H fill:#2d1e4a,color:#fff,stroke:#5a3a8b
Eight safety invariants protect every write: atomic replace, mandatory .bak backup, symlink rejection, mtime and process gates, and post-write JSONL validation. agentsweep undo restores from backups.
agentsweep is a command-line tool, so install it in its own isolated environment. Both recommended options set that up.
uv (recommended):
uv tool install agentsweep # install
uv tool upgrade agentsweep # update
uvx agentsweep@latest # or run once without installingpipx:
pipx install agentsweep
pipx upgrade agentsweeppip works too, but keep it inside a virtual environment. Modern Linux and macOS block pip install into the system Python (PEP 668), and a CLI has no business there anyway:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install agentsweepYou do not need conda. It exists for heavy binary and scientific stacks, and agentsweep is pure Python with three small dependencies.
Android (Termux):
pkg install python clang
pip install agentsweepThe clang package lets the one native dependency build against Android's libc.
No
uv?pip install uvor see astral.sh/uv. Requires Python 3.11+.
Build the image from the repo root:
docker build -t agentsweep .agentsweep scans files under a source's history root (e.g. ~/.claude), so
mount your real home directory (or just the relevant agent folder) into the
container and point --root at it. -u $(id -u):$(id -g) keeps files
written back to the mount (like .bak backups) owned by you, not root:
docker run --rm -it -u $(id -u):$(id -g) \
-v "$HOME/.claude:/home/sweeper/.claude:rw" \
agentsweep scan --source claude-codeFor agentsweep fix, keep the same mount read-write so it can write
redactions and .bak backups back to your real history directory.
agentsweep supports tab-completion for subcommands, flags, and dynamically lists source names for the --source option.
To activate completions for the current session:
eval "$(agentsweep completion bash)"
# Or using the register-python-argcomplete utility:
eval "$(register-python-argcomplete agentsweep)"To make it permanent, add the eval line to your ~/.bashrc (or equivalent).
Zsh uses the bashcompinit compatibility layer. Add the following to your ~/.zshrc:
# Initialize shell completion if not already done
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
eval "$(agentsweep completion zsh)"
# Or using the register-python-argcomplete utility:
eval "$(register-python-argcomplete agentsweep)"To activate completions for the current session:
agentsweep completion fish | sourceTo make it permanent, save the completion script:
agentsweep completion fish > ~/.config/fish/completions/agentsweep.fish
# Or using the register-python-argcomplete utility:
register-python-argcomplete --shell fish agentsweep > ~/.config/fish/completions/agentsweep.fishWorks in both Windows PowerShell 5.1 and PowerShell 7+. To activate completions for the current session:
agentsweep completion powershell | Out-String | Invoke-ExpressionTo make it permanent, append the completion script to your profile:
if (-not (Test-Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force }
agentsweep completion powershell | Out-String | Add-Content $PROFILEIf your profile blocks script execution, allow local scripts first with
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned.
Run with no arguments in a terminal and you get the banner, a numbered menu,
typed confirmations before anything destructive, and one-key undo (restores the
.bak backups). Any interactive scan that finds secrets ends with an offer to
redact them on the spot (type REDACT to confirm):
agentsweep
Scripting is unaffected: any flag, or a piped/redirected stream, skips the menu and behaves as documented below.
| Command | What it does |
|---|---|
agentsweep scan |
Scan only: read-only, no files are modified (default when no verb given) |
agentsweep fix |
Scan, then offer to redact findings in place (type REDACT to confirm) |
agentsweep undo |
Restore all .bak backups, reverting any previous redaction |
agentsweep purge |
Delete all .bak backups once the leaked keys are rotated (permanent, undo stops working) |
agentsweep list-sources |
List every supported agent and show which ones have history on this machine (read-only) |
agentsweep explain <rule-id> |
Print one detection rule's pattern and its rotation guidance (read-only) |
agentsweep --version / -V |
Print the installed version |
agentsweep --update |
Check PyPI for a newer release |
The legacy flag form agentsweep --fix is still accepted and behaves identically to agentsweep fix.
Pick which agent's history to target with --source. The default is claude-code.
agentsweep scan --source claude-code # ~/.claude/projects/ (or $CLAUDE_CONFIG_DIR)
agentsweep scan --source codex # ~/.codex/sessions/
agentsweep scan --source opencode # OpenCode SQLite store
agentsweep scan --source cursor # Cursor history
agentsweep scan --source windsurf # Windsurf history
agentsweep scan --source aider # per-repo .aider.chat.history.md under $HOME
agentsweep scan --source crush # per-project .crush/crush.db under $HOME
agentsweep scan --source cline # Cline history
agentsweep scan --source gemini-cli # Gemini CLI history
agentsweep scan --source continue-vscode # Continue (VS Code) history
agentsweep scan --source github-copilot-chat # GitHub Copilot Chat history
agentsweep scan --source openclaw # OpenClaw ~/.openclaw/
agentsweep scan --source hermes # Hermes Agent ~/.hermes/state.db
agentsweep scan --source goose # Goose ~/.local/share/goose/
agentsweep scan --source llm # Datasette llm CLI logs.db (io.datasette.llm/)Running Claude Code under a custom profile? Set CLAUDE_CONFIG_DIR (the same variable Claude Code honors) and agentsweep scans that profile's projects/ instead of ~/.claude. To scan several profiles at once, for example a personal side-project profile alongside your work one, list them comma-separated and agentsweep scans all of them:
CLAUDE_CONFIG_DIR=~/.claude,~/.claude-personal agentsweep scan --source claude-codeNot sure which agents you have installed? list-sources prints every supported
source, its history location, and whether that history exists on this machine,
so you know which --source values are worth scanning. It reads nothing and
writes nothing.
agentsweep list-sources # all 31 sources + which are on disk
agentsweep list-sources --detected # only the ones found on this machine
agentsweep list-sources --json # machine-readable (for scripts/CI)Wondering why a finding fired, or how to revoke the key it caught? explain
prints a rule's pattern and its rotation guidance without scanning anything:
agentsweep explain stripe-live # pattern + where to roll the key
agentsweep explain --list # every rule id, one per lineScan every registered agent in one pass (aggregated findings; redaction stays per-source):
agentsweep scan --all # all registered sources
agentsweep scan --all --detected # only sources with a history root on disk
agentsweep scan --all --json # aggregated JSON (each finding has "source")
agentsweep scan --all --json -o out.jsonOverride the default root directory to scan any arbitrary folder:
agentsweep scan --root ~/backups/claude-history
agentsweep fix --root /tmp/history-copy --allow-production# Machine-readable JSON to stdout (exit 0 = clean, 1 = findings found, 2 = error)
agentsweep scan --json
# Write findings JSON to a file instead of stdout
agentsweep scan --json -o findings.json
agentsweep scan --json --output /tmp/report.json
# SARIF 2.1.0 for GitHub code scanning / VS Code SARIF viewer (scan only)
agentsweep scan --format sarif -o agentsweep.sarif
agentsweep scan --all --format sarif -o agentsweep.sarif
# Skip .agentsweepignore files
agentsweep scan --no-ignore
# Plain output with no ANSI colors/styling (also honored via NO_COLOR=1)
agentsweep scan --no-color
NO_COLOR=1 agentsweep scan--format sarif emits SARIF 2.1.0, so findings show up as code-scanning annotations instead of something you have to parse. Rotation guidance rides along in each rule's help text, and only the masked preview is included. The secret itself is never written to the report.
- name: Scan agent history for secrets
run: |
pipx run agentsweep scan --all --format sarif -o agentsweep.sarif || true
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: agentsweep.sarif|| true keeps the upload step reachable. scan exits 1 when it finds something, and you want the SARIF to report that rather than the step failing.
Stop yourself from committing while your agent history holds a live key. Add this to your repo's .pre-commit-config.yaml:
repos:
- repo: https://github.com/Ishannaik/agent-sweep
rev: v0.1.9 # pin to a released tag
hooks:
- id: agentsweepThen pre-commit install. The hook runs agentsweep scan --all --detected on every commit and blocks it (exit 1) if any detected agent history contains a secret. It scans your history roots (~/.claude, ~/.codex, ...) rather than the repo's staged files, so it runs once per commit no matter what changed. It works as a per-commit checkpoint. With no agent history on the machine it exits 0 and does nothing.
# Redact Claude Code history in place (--allow-production required for default roots during alpha)
agentsweep fix --allow-production
# Skip creating .bak backups (not recommended)
agentsweep fix --allow-production --no-backup
# Bypass soft safety checks: mtime gate (files modified <60 s ago) and running-process gate
agentsweep fix --allow-production --force
# Customize the redaction placeholder (default: [REDACTED:{rule}]); {rule} is
# optional. Rejected up front if it contains a path separator or a control
# character, or if {rule} substitution would fail.
agentsweep fix --allow-production --redact-with "***{rule}***"
# Combine: non-interactive JSON-mode redaction against a custom root
agentsweep fix --root ~/history-copy --json# Undo redactions for a specific source
agentsweep undo --source codex
# Undo against a custom root
agentsweep undo --root ~/history-copyA redactor that corrupts your history leaves you worse off than the leak it's fixing. agentsweep enforces these invariants on every --fix:
- Redaction happens in parsed JSON, not on raw bytes. Secrets are replaced as string values inside the parsed structure, then re-serialized. Structural damage is impossible by construction.
- Atomic writes. Every rewrite goes: temp file →
fsync()→os.replace()over the original. A crash at any instant leaves either the complete old file or the complete new file, never a torn write. - Post-write validation. Before committing, the new content must pass a format-aware check. JSONL: every non-empty line parses as JSON and the line count matches the original. Whole-file JSON: the document parses. Markdown/plaintext: the line count matches the original. SQLite: the rewritten copy passes
PRAGMA integrity_check. If the check fails, the write aborts and the original is untouched. .bakbackup by default. Created owner-readable only (mode0600) since it holds the pre-redaction secrets; refuses to run if a.bakalready exists (so prior backups can't be clobbered).- Path containment. Refuses any target that doesn't resolve inside one of the source's history trees (e.g. Windsurf's User dir and its
~/.codeium/windsurf/memories/). - Symlink rejection. Refuses symlinks outright.
- mtime window. Refuses files modified in the last 60 seconds (likely an active session).
--forceoverrides. - Running-process check. Refuses if a Claude Code process appears to be running.
--forceoverrides. - Alpha-stage production gate.
--fixagainst the default~/.claude/projects/root requires--allow-productionuntil v1.0. - Audit log. Every write appends SHA256 before/after and path to
~/.agentsweep/audit.jsonl.
Every redacted file has a sibling *.bak with the original bytes. The easiest way to undo all redactions for a source is:
agentsweep undo # undo Claude Code (default)
agentsweep undo --source codex # undo a specific source
agentsweep undo --root ~/history-copy # undo against a custom rootIf you need to restore a single file manually (e.g. you deleted the undo command's source):
mv session.jsonl.bak session.jsonlThe backups hold the pre-redaction originals, plaintext secrets and all, so a sweep isn't finished until the leaked keys are rotated and the backups are gone. Once you've rotated:
agentsweep purge # delete Claude Code backups (asks first)
agentsweep purge --source windsurf # delete a specific source's backups
agentsweep purge --yes # non-interactive (scripts / CI)201 high-confidence patterns, plus a checksum-validated crypto seed-phrase detector. It confirms BIP-39 mnemonics (12/15/18/21/24 words, the wallet format behind BTC, ETH, SOL, BNB, ADA, DOGE, LTC, DOT, AVAX and most major chains) and Electrum seeds cryptographically (BIP-39 checksum or Electrum version tag), so English prose that happens to use wallet words won't trigger a false positive.
The patterns: AWS access keys, GitHub tokens (PAT/OAuth/App/fine-grained), Stripe live/test, OpenAI, Anthropic, Google API, Slack bot/user/webhook, Hugging Face, JWT, PEM private keys, DB URLs with embedded passwords, and npm/PyPI/SendGrid/Twilio tokens. On top of those sit 187 rules mapped to the gitleaks pack covering GitLab, Grafana, HashiCorp Vault/Terraform, DigitalOcean, Shopify, PlanetScale, Databricks, Atlassian, Azure AD, 1Password, Sentry, New Relic, Mailgun, Datadog, Twilio, Twitter/X, Twitch, Yandex, JFrog, Snyk, Mailchimp, curl credentials on the command line, and many more. The patterns run high-precision: false positives are rare, and provider-context rules are keyword-gated so large pastes stay fast.
A false positive you already understand should not keep showing up. Put an
.agentsweepignore file in the scan root or your current working
directory (both are read; entries merge). Each non-comment line is one of
three forms:
| Form | What it suppresses |
|---|---|
rule:<rule-id> |
Every finding from that rule |
<relpath>:<line>:<rule> |
One exact finding — the fingerprint agentsweep prints next to each hit |
| a bare literal | Any finding whose secret value matches |
Example:
# never flag the demo AWS key
AKIAIOSFODNN7EXAMPLE
# ignore the whole slack-webhook rule
rule:slack-webhook
# one exact false positive in a fixture
tests/fixtures/claude/sample.jsonl:42:aws-access-key-id
Copy-paste path: run a scan, copy the fingerprint printed beside the false
positive, paste it into .agentsweepignore, re-scan — it will be gone. Use
--no-ignore to bypass both files when you want a completely fresh pass.
Repeating the same flags on every invocation gets old. agentsweep reads an
optional config file for four flags that are safe to default silently. TOML
keys drop the CLI flag's leading -- and use underscores instead of hyphens:
| CLI flag | TOML key |
|---|---|
--source |
source |
--no-color |
no_color |
--format |
format |
--no-ignore |
no_ignore |
# agentsweep.toml (or .agentsweeprc, same format) in the current directory
source = "codex"
no_color = true
format = "sarif"
no_ignore = falseLookup order (first file found wins, values are never merged across files):
./agentsweep.toml./.agentsweeprc~/.config/agentsweep/config.toml
Precedence: CLI flag > config file > built-in default, applied per option.
A flag you pass on the command line always overrides the config file's value
for that same option — it does not clear other configured options. A
configured format = "sarif" is skipped entirely (not merged, not erroring)
on fix, --json, or --report invocations, since those are incompatible
with SARIF output; it only ever applies to a plain scan.
--allow-production, --force, and --no-backup can never be set from
a config file, even if present in one (agentsweep drops them with a warning)
— those safety gates must stay explicit on every invocation so a stale or
shared config file can't silently weaken a redaction safety check.
- Custom/proprietary secrets without a recognizable prefix.
- Monero seed phrases (25 words from Monero's own wordlist; planned).
- Unknown tokens that look like arbitrary base64.
- Secrets split across multiple messages.
- Anything inside a binary/non-UTF-8 file.
For deeper detection, run gitleaks or trufflehog alongside agentsweep, since their rule packs are more exhaustive. agentsweep earns its keep by covering the agent-history-specific surface those tools skip.
They solve different problems and compose well together. agentsweep covers the surface a git-repo scanner was never built for: the local AI-agent history files where pasted keys accumulate.
| agentsweep | gitleaks | trufflehog | |
|---|---|---|---|
| Primary target | AI agent history (~/.claude/, ~/.codex/, Cursor, 31 agents) |
git repos & commits | git repos, filesystems, cloud, CI |
| Redacts in place | ✅ structure-preserving, atomic, reversible (undo) |
❌ detection only | ❌ detection only |
| Rotation guidance | ✅ per-provider revocation links | ❌ | ❌ |
| Verifies live keys | ❌ | ❌ | ✅ (network) |
| Rules | 201 (187 mapped to gitleaks rules) | ~150 | 800+ verified |
| Runs fully offline | ✅ zero network calls | ✅ |
Scan your codebase and CI with gitleaks or trufflehog, then scan the agent-history surface they don't touch with agentsweep. Running both is the intent: they overlap and cover each other's blind spots.
If list-sources shows a source as not detected or a scan finds nothing,
work through this before assuming there are no secrets:
-
Confirm the source is actually installed and detected.
agentsweep list-sources
A missing tool is fine; a tool you use daily should not be missing.
-
Check a non-default profile. Claude Code (and some other agents) can store history outside the default config dir. Point at the profile you actually use:
CLAUDE_CONFIG_DIR=~/.claude-work agentsweep list-sources --detected agentsweep scan --root ~/.claude-work/projects
(Other sources have their own env overrides — see the source table.)
-
Point
--rootat a specific directory to isolate whether default root resolution is the problem:agentsweep scan --root /path/to/history
How do I remove secrets (API keys) from my Claude Code history?
Install with uv tool install agentsweep, run asweep, and the interactive menu scans ~/.claude/projects/. When it finds secrets it offers to redact them in place (type REDACT to confirm). It replaces the values, preserves the JSONL structure byte-for-byte, and keeps a .bak backup so you can agentsweep undo. The same flow works for Codex, Cursor, and 27 other agents via --source.
Is it safe to run on my real agent history?
Yes. Scanning is read-only. Redaction is gated behind a typed REDACT confirmation, writes atomically (temp file → fsync → os.replace), keeps an owner-only .bak backup, validates the rewritten file parses before committing, and is fully reversible with agentsweep undo. Nine safety invariants guard every write. See Corruption-prevention guarantees.
Which AI coding agents does it support?
31, including Claude Code, OpenAI Codex, Cursor, Windsurf, Aider, Cline, Gemini CLI, GitHub Copilot Chat, Continue, and OpenCode. Run agentsweep list-sources to see the full list and which ones have history on your machine.
Why does uvx agentsweep show an old version?
uvx caches tools locally. Use uvx agentsweep@latest to always run the newest version (recommended), or force a cache refresh with uvx --reinstall agentsweep.
Where is OpenCode in the menu?
OpenCode support was added in v0.1.1. Run pip install --upgrade agentsweep or uvx agentsweep@latest to get it.
Does agentsweep send my data anywhere? No. It is fully offline, with zero network calls during scanning or redacting. The only optional network call is the background update check, which fetches the latest version number from PyPI.
agentsweep runs against your most sensitive data, so a malicious contribution would be worth more to an attacker than one to an ordinary tool. Every pull request gets a line-by-line review for backdoors and supply-chain risk before it merges, on top of the usual correctness check. A PR is rejected if it:
- Adds a network call. agentsweep is offline by design, and the only permitted outbound request is the optional PyPI version check. Any new socket /
urllib/requests/ webhook call is a hard no. - Introduces obfuscated or dynamic code:
eval/exec/compileon runtime data,base64/hex-decoded payloads, dynamic__import__,pickle/marshalof untrusted input. - Weakens a safety invariant: anything that writes outside
safe_write(), drops a post-write validation, skips the.bakbackup, or logs/prints a raw secret value. See Safety-first review. - Pulls in an unvetted dependency or repins an existing one to an unexpected source/version.
- Edits CI/workflows to exfiltrate secrets or tokens (e.g. printing
GITHUB_TOKEN, adding a step that phones home, or touching the PyPI Trusted-Publisher release path).
Every PR also runs GitGuardian and a bandit SAST scan in CI (see Security linting), and workflows from first-time contributors require maintainer approval before they execute. Maintainers merge only after this review. A green checkmark on its own is never enough.
Thanks to everyone who has contributed code, bug reports, and ideas. Ask questions or get help in the Discord server.
MIT. See LICENSE.

