{"id":51295495,"url":"https://github.com/bvolpato/promptcloak","last_synced_at":"2026-06-30T14:03:03.596Z","repository":{"id":363010983,"uuid":"1261636962","full_name":"bvolpato/promptcloak","owner":"bvolpato","description":"Local OpenAI-compatible proxy and Python library that redacts secrets before prompts leave your machine.","archived":false,"fork":false,"pushed_at":"2026-06-18T06:35:53.000Z","size":1623,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T08:11:10.041Z","etag":null,"topics":["llm","openai","privacy","proxy","redaction","security"],"latest_commit_sha":null,"homepage":"https://bvolpato.github.io/promptcloak/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bvolpato.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-07T00:41:06.000Z","updated_at":"2026-06-18T06:35:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bvolpato/promptcloak","commit_stats":null,"previous_names":["bvolpato/promptcloak"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bvolpato/promptcloak","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bvolpato%2Fpromptcloak","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bvolpato%2Fpromptcloak/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bvolpato%2Fpromptcloak/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bvolpato%2Fpromptcloak/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bvolpato","download_url":"https://codeload.github.com/bvolpato/promptcloak/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bvolpato%2Fpromptcloak/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34969682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["llm","openai","privacy","proxy","redaction","security"],"created_at":"2026-06-30T14:03:02.903Z","updated_at":"2026-06-30T14:03:03.586Z","avatar_url":"https://github.com/bvolpato.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PromptCloak\n\n**Run LLM requests through a local secret scrubber before they leave your machine.**\n\nPromptCloak is an OpenAI-compatible proxy and Python library for removing secrets from prompts. It scans request values locally, replaces API keys, passwords, tokens, private keys, signed URLs, and custom matches, then forwards or returns cleaned payloads.\n\nNo telemetry. No phone-home. No full-secret storage required.\n\n![PromptCloak site preview](site/hero.png)\n\nWebsite: `https://bvolpato.github.io/promptcloak/`\nRepository: `https://github.com/bvolpato/promptcloak`\n\n## 60-second demo\n\n```bash\nbrew tap bvolpato/tap\nbrew install promptcloak\npromptcloak init\nexport OPENROUTER_API_KEY=\"\u003cupstream-provider-key\u003e\"\npromptcloak serve\n```\n\nSend traffic through PromptCloak:\n\n```bash\ncurl http://127.0.0.1:8000/v1/chat/completions \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"openai/gpt-5.5\",\n    \"messages\": [\n      {\n        \"role\": \"user\",\n        \"content\": \"Here is my .env: OPENAI_API_KEY=\u003capi-key-like-value\u003e\"\n      }\n    ]\n  }'\n```\n\nUpstream sees:\n\n```text\nOPENAI_API_KEY=[REDACTED_SECRET]\n```\n\nPartial masking is available, but full masking is safer and default:\n\n```yaml\nredaction:\n  redact_mode: \"partial\"\n```\n\n## Deterministic redaction smoke\n\nDo not verify redaction by asking an LLM to repeat what it received. Models can refuse, infer, summarize, or misstate what happened. Use an echo target:\n\n```bash\nFAKE_GEMINI_KEY=\"AI\"\"zaSyFixtureToken000000000000000000000\"\n\ncurl -fsS http://127.0.0.1:8000/v1/chat/completions \\\n  -H \"X-Target-Base-URL: https://httpbin.org/anything\" \\\n  -H \"Content-Type: application/json\" \\\n  --data \"$(jq -nc --arg key \"$FAKE_GEMINI_KEY\" \\\n    '{messages:[{role:\"user\",content:(\"GEMINI_API_KEY=\" + $key)}]}')\" \\\n  | jq -r '.json.messages[0].content'\n```\n\nExpected output:\n\n```text\nGEMINI_API_KEY=[REDACTED_SECRET]\n```\n\nPromptCloak audit logs include counts and rule names, never secret values.\n\n## Install with Homebrew\n\n```bash\nbrew tap bvolpato/tap\nbrew install promptcloak\npromptcloak version\npromptcloak init --target-base-url https://openrouter.ai/api/v1\n```\n\nForeground mode keeps the upstream key in your shell:\n\n```bash\nexport OPENROUTER_API_KEY=\"\u003copenrouter-upstream-key\u003e\"\npromptcloak serve\n```\n\nService mode needs the upstream key in config or service-manager env:\n\n```bash\nbrew services start bvolpato/tap/promptcloak\n```\n\n## Install release with uv\n\n```bash\nuv tool install \\\n  https://github.com/bvolpato/promptcloak/releases/download/v0.1.5/promptcloak-0.1.5-py3-none-any.whl\npromptcloak doctor\n```\n\n## Install from source\n\n```bash\ngit clone https://github.com/bvolpato/promptcloak.git\ncd promptcloak\nuv sync --extra dev\nuv run promptcloak doctor\n```\n\n## Use as a library\n\nPromptCloak can run without proxy service. Import redaction helpers and filter request values before passing them to any SDK. PromptCloak does not install OpenAI, LiteLLM, LangChain, or Anthropic SDKs; examples assume those are already in your app.\n\n```bash\nuv add \\\n  https://github.com/bvolpato/promptcloak/releases/download/v0.1.5/promptcloak-0.1.5-py3-none-any.whl\n```\n\n```python\nfrom promptcloak import redact_messages, scan_messages\n\nmessages = [\n    {\n        \"role\": \"user\",\n        \"content\": \"Debug this .env: OPENAI_API_KEY=\u003capi-key-like-value\u003e\",\n    }\n]\n\nsafe_messages = redact_messages(messages)\nresult = scan_messages(messages)\n\nassert result.stats.redactions \u003e= 1\n```\n\nFor custom tail-only rules:\n\n```python\nfrom promptcloak import PromptCloak\nfrom promptcloak.config import RedactionConfig, RuleConfig\n\ncloak = PromptCloak(\n    RedactionConfig(\n        rules=[RuleConfig(type=\"exact\", value=\"abcd1234\", name=\"tail-only\")]\n    )\n)\n\nsafe_messages = cloak.messages(messages)\n```\n\n### OpenAI Python\n\n```python\nfrom openai import OpenAI\nfrom promptcloak import redact_messages, redact_params\n\nclient = OpenAI()\n\nmessages = [{\"role\": \"user\", \"content\": \"API key: \u003capi-key-like-value\u003e\"}]\n\nresponse = client.chat.completions.create(\n    model=\"gpt-5.5\",\n    messages=redact_messages(messages),\n)\n\nresponse_api = client.responses.create(\n    **redact_params(\n        model=\"gpt-5.5\",\n        input=\"Summarize this config: OPENAI_API_KEY=\u003capi-key-like-value\u003e\",\n    )\n)\n```\n\n### LiteLLM\n\n```python\nfrom litellm import completion\nfrom promptcloak import redact_params\n\nmessages = [{\"role\": \"user\", \"content\": \"GEMINI_API_KEY=\u003capi-key-like-value\u003e\"}]\n\nresponse = completion(\n    **redact_params(\n        model=\"openrouter/openai/gpt-5.5\",\n        messages=messages,\n    )\n)\n```\n\n### LangChain\n\nTuple-style messages:\n\n```python\nfrom langchain_openai import ChatOpenAI\nfrom promptcloak import redact_messages\n\nllm = ChatOpenAI(model=\"gpt-5.5\")\n\nresponse = llm.invoke(\n    redact_messages(\n        [\n            (\"system\", \"You are concise.\"),\n            (\"human\", \"Here is my token: \u003capi-key-like-value\u003e\"),\n        ]\n    )\n)\n```\n\nLangChain message objects:\n\n```python\nfrom langchain_core.messages import HumanMessage\nfrom langchain_openai import ChatOpenAI\nfrom promptcloak import redact_messages\n\nllm = ChatOpenAI(model=\"gpt-5.5\")\n\nresponse = llm.invoke(\n    redact_messages(\n        [\n            HumanMessage(content=\"Here is my token: \u003capi-key-like-value\u003e\"),\n        ]\n    )\n)\n```\n\n### Anthropic Python\n\n```python\nfrom anthropic import Anthropic\nfrom promptcloak import redact_messages\n\nclient = Anthropic()\n\nresponse = client.messages.create(\n    model=\"claude-opus-4-8\",\n    max_tokens=1024,\n    messages=redact_messages(\n        [{\"role\": \"user\", \"content\": \"ANTHROPIC_API_KEY=\u003capi-key-like-value\u003e\"}]\n    ),\n)\n```\n\n### LlamaIndex\n\n```python\nfrom llama_index.core.llms import ChatMessage\nfrom llama_index.llms.openai import OpenAI\nfrom promptcloak import redact_messages\n\nllm = OpenAI(model=\"gpt-5.5\")\n\nresponse = llm.chat(\n    redact_messages(\n        [\n            ChatMessage(role=\"user\", content=\"Here is my token: \u003capi-key-like-value\u003e\"),\n        ]\n    )\n)\n```\n\n### Raw HTTP or custom clients\n\n```python\nimport httpx\nfrom promptcloak import redact_payload\n\npayload = {\n    \"model\": \"openai/gpt-5.5\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"secret=\u003capi-key-like-value\u003e\"}],\n}\n\nresponse = httpx.post(\n    \"https://openrouter.ai/api/v1/chat/completions\",\n    headers={\"Authorization\": \"Bearer \u003cprovider-api-key\u003e\"},\n    json=redact_payload(payload),\n)\n```\n\n## Run\n\n```bash\nuv run promptcloak init --target-base-url https://openrouter.ai/api/v1\nexport OPENROUTER_API_KEY=\"\u003copenrouter-upstream-key\u003e\"\nuv run promptcloak serve\n```\n\nDefault config: `~/.config/promptcloak/config.yaml`\n\n```yaml\nserver:\n  host: 127.0.0.1\n  port: 8000\n  api_key: null\n\ntarget:\n  default_base_url: https://openrouter.ai/api/v1\n  api_key: ${OPENROUTER_API_KEY}\n  api_key_header: authorization\n  forward_client_authorization: false\n  timeout_seconds: 180\n  allowed_base_urls: []\n  block_private_targets: true\n\nredaction:\n  enabled: true\n  engine: detect-secrets\n  redact_mode: full\n  encrypted: false\n  scan_responses: false\n  rules:\n    - type: exact\n      value: abcd1234\n      name: tail-only-example\n    - type: regex\n      value: sk-[A-Za-z0-9_-]{20,}\n      name: openai-style-token\n```\n\nBest practice: store only key tails in `rules`, never full secrets.\n\n## Supported routes\n\nPromptCloak forwards any path, with first-class tests for:\n\n- `/v1/chat/completions`\n- `/v1/responses`\n- `/v1/completions`\n- `/v1/models`\n- `/v1/messages` for Claude-compatible gateways\n\nIt preserves streaming responses, tools, structured outputs, vision payloads, and unknown provider fields because it redacts recursively without reshaping request schemas.\n\n## Dynamic backends\n\nSet default backend in config, or override per request:\n\n```bash\ncurl http://127.0.0.1:8000/v1/responses \\\n  -H \"X-Target-Base-URL: https://api.openai.com/v1\" \\\n  -H \"X-Target-API-Key: $OPENAI_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"gpt-5.5\",\"input\":\"scan this \u003capi-key-like-value\u003e\"}'\n```\n\nSet `X-Target-API-Key-Header: x-api-key` for Anthropic-style upstream authentication.\n\nUse `target.allowed_base_urls` for strict allowlists.\n\n## Codex\n\nCodex speaks OpenAI Responses. Some gateways expose Chat Completions only. PromptCloak can bridge Codex `/v1/responses` traffic to upstream `/v1/chat/completions` with `compat.responses_to_chat: true`.\n\nFor OpenRouter through PromptCloak, put `env_key = \"OPENROUTER_API_KEY\"` in the Codex provider. Codex attaches the key to localhost requests, and PromptCloak forwards that Authorization header to the allowed OpenRouter upstream.\n\nPromptCloak config:\n\n```bash\nmkdir -p ~/.config/promptcloak\ncp examples/promptcloak-openrouter.config.yaml ~/.config/promptcloak/config.yaml\nexport OPENROUTER_API_KEY=\"\u003copenrouter-upstream-key\u003e\"\nuv run promptcloak serve\n```\n\nRelevant PromptCloak settings:\n\n```yaml\ntarget:\n  default_base_url: https://openrouter.ai/api/v1\n  api_key: null\n  forward_client_authorization: true\n  allowed_base_urls:\n    - https://openrouter.ai/api/v1\n\ncompat:\n  responses_to_chat: true\n```\n\nCodex profile:\n\n`~/.codex/config.toml`\n\n```toml\nmodel = \"openai/gpt-oss-120b\"\nmodel_provider = \"promptcloak-openrouter\"\n\n[model_providers.promptcloak-openrouter]\nname = \"PromptCloak OpenRouter\"\nbase_url = \"http://127.0.0.1:8000/v1\"\nenv_key = \"OPENROUTER_API_KEY\"\nwire_api = \"responses\"\nrequest_max_retries = 0\nstream_max_retries = 0\n```\n\nOr keep it as a separate profile:\n\n```bash\nmkdir -p ~/.codex\ncp examples/codex-openrouter-promptcloak.config.toml ~/.codex/openrouter-promptcloak.config.toml\ncodex -p openrouter-promptcloak\n```\n\nSmoke test:\n\n```bash\ncodex -p openrouter-promptcloak --sandbox read-only --ask-for-approval never exec \\\n  --cd /home/bruno/githubworkspace/promptcloak \\\n  \"Reply with exactly: promptcloak-openrouter-ok\"\n```\n\nConfirm Chat Completions separately:\n\n```bash\ncurl -fsS http://127.0.0.1:8000/v1/chat/completions \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\":\"openai/gpt-oss-120b\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply exactly: ok\"}]}' \\\n  | jq -r '.choices[0].message.content'\n```\n\nUse any OpenRouter model by changing the profile `model`. Add `server.api_key` only if you bind PromptCloak beyond localhost.\n\nBridge notes:\n\n- Do not put raw keys in TOML. Put the env var name in `env_key`.\n- Keep `target.allowed_base_urls` tight when forwarding client auth.\n- Text responses and standard function calls are translated.\n- PromptCloak redacts before translation.\n- Leave `compat.responses_to_chat` off for upstreams with native `/v1/responses`.\n\n## OpenCode\n\nOpenCode supports custom OpenAI-compatible providers through `@ai-sdk/openai-compatible` and `options.baseURL`.\n\nOption A: set upstream provider on PromptCloak:\n\n```bash\nexport PROMPTCLOAK_TARGET_BASE_URL=\"https://openrouter.ai/api/v1\"\nexport PROMPTCLOAK_TARGET_API_KEY=\"\u003copenrouter-upstream-key\u003e\"\npromptcloak serve\n```\n\nOption B: set upstream provider per request from OpenCode headers:\n\n`opencode.json`\n\n```json\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"provider\": {\n    \"promptcloak\": {\n      \"npm\": \"@ai-sdk/openai-compatible\",\n      \"name\": \"PromptCloak\",\n      \"options\": {\n        \"baseURL\": \"http://127.0.0.1:8000/v1\",\n        \"headers\": {\n          \"X-Target-Base-URL\": \"https://openrouter.ai/api/v1\",\n          \"X-Target-API-Key\": \"{env:OPENROUTER_API_KEY}\"\n        }\n      },\n      \"models\": {\n        \"openai/gpt-5.5\": {\n          \"name\": \"GPT-5.5 via PromptCloak\"\n        }\n      }\n    }\n  },\n  \"model\": \"promptcloak/openai/gpt-5.5\"\n}\n```\n\nUpstream provider URL and key are `X-Target-Base-URL` and `X-Target-API-Key`, or `PROMPTCLOAK_TARGET_BASE_URL` and `PROMPTCLOAK_TARGET_API_KEY` when configured on PromptCloak.\n\n## Claude Code\n\nClaude Code uses Anthropic-compatible traffic, not OpenAI Chat Completions. PromptCloak can still redact and forward Claude Code requests when upstream is Anthropic-compatible or an LLM gateway that accepts Claude Code traffic.\n\nConfig:\n\n```yaml\ntarget:\n  default_base_url: https://api.anthropic.com\n  api_key: ${ANTHROPIC_UPSTREAM_API_KEY}\n  api_key_header: x-api-key\n```\n\nShell:\n\n```bash\nexport ANTHROPIC_UPSTREAM_API_KEY=\"\u003canthropic-upstream-key\u003e\"\nexport ANTHROPIC_BASE_URL=\"http://127.0.0.1:8000\"\nexport ANTHROPIC_API_KEY=\"${PROMPTCLOAK_LOCAL_API_KEY:-placeholder}\"\nexport DISABLE_TELEMETRY=1\nexport DO_NOT_TRACK=1\npromptcloak serve\nclaude\n```\n\nPromptCloak forwards `/v1/messages` to configured upstream. It does not translate OpenAI protocol into Anthropic protocol.\n\n## Redaction Engine\n\nPromptCloak uses `bc-detect-secrets` directly, plus deterministic rules for provider tokens and user-defined exact-tail or regex matches. No model runtime involved.\n\nCoverage includes fixture-shaped examples for:\n\n- GitHub classic and fine-grained PATs\n- Atlassian API tokens\n- OpenAI project/API keys\n- Gemini API keys\n- Anthropic API keys\n- OpenRouter keys\n- Z.AI, MiniMax, DeepSeek, Codex/OpenAI, xAI/Grok, and Fireworks keys when labeled or prefix-shaped\n- GitLab, Slack, Stripe, AWS, Google API keys\n- 1Password, Databricks, DigitalOcean, Hugging Face, Linear, npm, PyPI, SendGrid, Telegram, Twilio, Vault, Shopify, Sentry\n- Cloudflare API keys/tokens in assignment form or `X-Auth-Key` / `CF-Access-Token` headers\n- AWS, Google Cloud Storage, and Azure signed URL signatures and credential parameters\n- JWTs\n- PEM, encrypted PEM, and PGP private keys\n- Authorization-style headers and URL credentials in request bodies\n- `password=...`, `token=...`, `api_key=...`\n- JSON object fields named like `api_key`, `token`, `secret`, `password`, `authorization`, `credentials`, `signed_url`, or `sas_token`\n- User exact-tail and regex rules\n\nEvery scan is local. PromptCloak never calls an LLM to detect secrets. Entropy-only\nmatching is intentionally disabled; use custom rules for opaque internal formats.\n\n## Encrypt rules at rest\n\n```bash\nuv run promptcloak encrypt-rules\n```\n\nThis creates `~/.config/promptcloak/key` with mode `0600`, encrypts `redaction.rules` using AES-GCM, writes `redaction.encrypted_rules`, and clears plain rules.\n\nYou can also provide key material through:\n\n```bash\nexport PROMPTCLOAK_CONFIG_KEY=\"base64-url-safe-32-byte-key\"\n```\n\n## Docker\n\nPublished image:\n\n```bash\nexport OPENROUTER_API_KEY=\"\u003copenrouter-upstream-key\u003e\"\n\ndocker run -d --name promptcloak --rm \\\n  -p 127.0.0.1:8000:8000 \\\n  -e PROMPTCLOAK_TARGET_BASE_URL=https://openrouter.ai/api/v1 \\\n  -e PROMPTCLOAK_TARGET_API_KEY=\"$OPENROUTER_API_KEY\" \\\n  ghcr.io/bvolpato/promptcloak:0.1.5\n\ncurl -fsS http://127.0.0.1:8000/healthz\ndocker stop promptcloak\n```\n\nLocal build:\n\n```bash\ndocker build -t promptcloak:local .\ndocker run -d --name promptcloak --rm \\\n  -p 127.0.0.1:8000:8000 \\\n  -e PROMPTCLOAK_TARGET_BASE_URL=https://openrouter.ai/api/v1 \\\n  -e PROMPTCLOAK_TARGET_API_KEY=\"$OPENROUTER_API_KEY\" \\\n  promptcloak:local\n\ncurl -fsS http://127.0.0.1:8000/healthz\ndocker stop promptcloak\n```\n\nCompose:\n\n```bash\nexport OPENROUTER_API_KEY=\"\u003copenrouter-upstream-key\u003e\"\ndocker compose up --build\n```\n\n## Helm\n\nLocal chart:\n\n```bash\nhelm install promptcloak ./charts/promptcloak \\\n  --set secretEnv.PROMPTCLOAK_TARGET_API_KEY=\"$OPENROUTER_API_KEY\"\n\nkubectl wait deployment/promptcloak --for=condition=Available --timeout=90s\nkubectl port-forward svc/promptcloak 8000:8000\n```\n\nIn another shell:\n\n```bash\ncurl -fsS http://127.0.0.1:8000/healthz\nhelm uninstall promptcloak\n```\n\nUse locally built images in Kind:\n\n```bash\ndocker build -t promptcloak:local .\nkind load docker-image promptcloak:local\nhelm install promptcloak ./charts/promptcloak \\\n  --set image.repository=promptcloak \\\n  --set image.tag=local \\\n  --set image.pullPolicy=Never \\\n  --set secretEnv.PROMPTCLOAK_TARGET_API_KEY=\"$OPENROUTER_API_KEY\"\n```\n\nRelease asset:\n\n```bash\nhelm pull https://github.com/bvolpato/promptcloak/releases/download/v0.1.5/promptcloak-0.1.5.tgz\nhelm install promptcloak ./promptcloak-0.1.5.tgz \\\n  --set secretEnv.PROMPTCLOAK_TARGET_API_KEY=\"$OPENROUTER_API_KEY\"\n```\n\n## Security model\n\nPromptCloak protects request bodies before they leave your machine. It masks sensitive auth headers in debug logs, but it cannot remove upstream credentials from provider-bound auth headers because providers need those credentials to authenticate the request. Recommended setup:\n\n- Put upstream provider key in PromptCloak config or env.\n- Keep `forward_client_authorization: false` unless you intentionally want client auth forwarded.\n- Use `api_key_header: x-api-key` for Anthropic-compatible upstreams.\n- Set `server.api_key` only when exposing PromptCloak beyond `127.0.0.1`.\n- Store only secret tails in redaction rules.\n- Keep `block_private_targets: true`.\n- Set `allowed_base_urls` in shared/team installs.\n- Keep response scanning off unless you need it; streaming response redaction is intentionally not attempted yet.\n- Add custom rules for internal tokens or providers without stable public prefixes.\n- In library mode, call `redact_messages`, `redact_params`, or `redact_payload` before SDK calls.\n\n## Emergency request tracing\n\n`promptcloak serve --debug-requests` logs raw request bodies before redaction. Use it only with local fixture data when an echo target is not enough. Auth, target-key, and redaction-rule headers are masked; body text is not.\n\n## Development\n\n```bash\nuv sync --extra dev\nuv run scripts/audit_secrets.py\nuv run pytest\nuv run ruff check .\nuv build\nuv run promptcloak scan 'OPENAI_API_KEY=\u003capi-key-like-value\u003e'\n```\n\nTests cover nested OpenAI, Responses, and Claude-style payloads, dynamic upstream\nheaders, audit logs, emergency tracing, response scanning, target allowlists, text\nbodies, and provider-shaped fixture tokens. Fixtures are split in source so no real or\ncontiguous fake keys are committed.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md), [SECURITY.md](SECURITY.md), and [SECURITY_AUDIT.md](SECURITY_AUDIT.md) before opening issues or pull requests. Never post real secrets in public project surfaces.\n\n## Distribution\n\nPromptCloak ships GitHub releases with source, wheel, Helm chart, Homebrew formula, and GHCR image artifacts.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbvolpato%2Fpromptcloak","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbvolpato%2Fpromptcloak","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbvolpato%2Fpromptcloak/lists"}