Secretless
Secretless stores API keys outside project files and sets up AI coding tools not to read credential files. It is for developers using AI coding tools who do not want credentials landing in conversation history, tool calls, or file reads. In Claude Code a PreToolUse hook blocks credential file reads. For Cursor, GitHub Copilot, Devin Desktop (formerly Windsurf) and Cline it writes an instruction file that nothing enforces, and for Aider it writes ignore patterns. Run npx secretless-ai init once in a project to migrate hardcoded credentials to a secure backend and set up each AI coding tool it finds.
Setup
npm install -g secretless-ainpx secretless-ai initnpx secretless-ai verifyHow it works
Secretless intercepts credential access at the tool level. Instead of credentials appearing in LLM context (conversation history, tool calls, file reads), tools reference environment variables. Secretless manages the lifecycle:
- Scans project for credential patterns (API keys, tokens, connection strings)
- Migrates credentials to a secure backend (OS keychain, 1Password, vault)
- Replaces hardcoded values with
$ENV_VARreferences - Adds file patterns to block lists (prevents AI tools from reading .env files)
- Injects a CLAUDE.md / .cursorrules section instructing tools to use env vars
What secretless means here
On this page, secretless means the AI tool works without seeing secret values. The secrets still exist: they are stored in an encrypted backend and injected into a command's environment when it runs.
Secretless configures each AI coding tool it finds. In Claude Code a hook and deny rules refuse a read of a credential file before it runs. For Cursor, GitHub Copilot, Devin Desktop (formerly Windsurf) and Cline it writes an instruction file that asks the model not to read credential files, and for Aider it writes ignore patterns.
Does secretless mean there are no secrets?
No. The secrets are stored in a backend: the OS keychain, 1Password, HashiCorp Vault, GCP Secret Manager or an AES-256-GCM encrypted file. A command receives them as environment variables when it runs.
How does an AI coding tool use a stored key?
By name. To give one stored secret to one command:
npx secretless-ai run --only STRIPE_SECRET_KEY -- node charge.jsnode charge.js reads the value from its environment. The AI tool sees the name and whatever the command prints.
Is this authentication or authorization?
Neither on its own. Secretless AI is not an identity provider and signs nobody in: it stores credentials and controls how they reach a process. Authorization comes with the optional broker, a local daemon whose policy rules allow or deny each request by agent ID, credential name, time window and rate limit.
Does it replace HashiCorp Vault?
No. Vault is one of the five storage backends. Secretless AI reads and writes Vault's KV v2 engine using VAULT_ADDR and VAULT_TOKEN. This command copies stored secrets into it:
npx secretless-ai migrate --from local --to vaultThree-tier architecture
Secretless offers three layers of protection. Use one, two, or all three. Each works against any supported storage backend. Pick the tier that matches how a credential is used.
Credentials resolved in the call stack and zeroized after use. Available in the Python and TypeScript AIM SDKs. Sub-millisecond overhead.
When to use: a solo developer wiring credentials directly into application code.
A subprocess primitive that injects a credential into a child process's environment and not into the parent's. The AI tool that runs the command sees whatever the command prints, not the value handed to the child. Language-agnostic. Wraps any command.
npx secretless-ai vault exec github -- curl https://api.github.com/userThe child process receives $GITHUB. The value is not placed in the parent shell, in the AI tool's context or on the command line, where a process listing would show it. Like run, vault exec passes a value to one command; it does not stop a program that reads the credential's store without it.
When to use: a local agent that shells out to a single command needing one credential.
A local daemon that mediates credential access across multiple agents. Policy rules allow or deny access by agent ID, credential name, time window, and rate limit. Optional AIM integration adds trust-score and capability constraints.
npx secretless-ai broker startWhen to use: a fleet of agents that share credentials under per-agent policy.
AIM is optional. Tier 1 and Tier 2 work against any of the five storage backends with no AIM involvement. Tier 3 adds identity-bound policy when an AIM server is reachable. Default-deny still enforces locally without one.
Credential pattern library
Scanning draws on 57 credential patterns from the current @opena2a/credential-patterns release, lockstep-asserted. A directory scan checks source files (.js, .ts, .py, .go, .java, .rb, and others), key files, and the config files it recognizes by name, such as .env, config.json, package.json, CLAUDE.md, and MCP client configs. It does not open other files, such as values.yaml, main.tf, or most GitHub Actions workflows and .md files; name a file to scan it: npx secretless-ai scan deploy/values.yaml.
Fixture-path false positives are suppressed via .secretlessignore defaults (test/, __tests__/, examples/, e2e/, docs/vhs/, node_modules/, and similar). Run npx secretless-ai ignore <path> to append a path, or scan --no-ignore to keep fixture matches visible with a (looks like a test fixture) tag instead of re-suppressing them.
What is covered
File patterns that should never enter AI context, plus runtime credential pattern detection from the open source @opena2a/credential-patterns catalog.
| File patterns | Patterns |
|---|---|
| Environment files | .env, .env.*, .env.local, .env.production |
| Private keys | *.key, *.pem, *.p12, *.pfx, *.crt |
| Cloud credentials | .aws/credentials, .ssh/*, .docker/config.json |
| Package auth | .npmrc, .pypirc, .git-credentials |
| Infrastructure | *.tfstate, *.tfvars |
| Secret directories | secrets/, credentials/ |
Credential pattern families:
- Anthropic API keys
- OpenAI keys (project and legacy)
- AWS access keys plus secret keys
- GitHub PATs (classic and fine grained)
- Slack tokens (bot, user, webhook)
- Google API keys plus OAuth secrets
- Stripe live and test keys
- SendGrid keys
- Supabase service and anon keys
- Azure keys plus connection strings
- GitLab tokens (personal, project, group)
- Twilio account SID plus auth token
- Mailgun API keys
- MongoDB connection URIs
- JWTs and bearer tokens
Plus more in the catalog. Versioned and shared with hackmyagent and opena2a-cli.
Five storage backends
Choose where secrets are stored. All backends encrypt at rest. A command receives the secrets it needs as environment variables when it runs. Importing a .env file and migrating to another backend both copy secrets: the .env file and the source backend keep theirs until you delete them.
AES-256-GCM encrypted file on disk, written with 0600 permissions. No external dependencies. Used when the machine has no OS keychain, such as on Windows or on Linux without secret-tool.
Zero setup. Single machine. Filesystem auth.
macOS Keychain or Linux Secret Service (libsecret). Used by default on macOS, and on Linux when secret-tool is installed. Hardware backed encryption on Apple Silicon. OS login auth.
OS level encryption. Device local sync. OS login auth.
Dedicated vault via the op CLI. Biometric unlock (Touch ID). Service accounts for CI/CD. Cross device sync.
Biometric auth. Cross device sync. CI/CD via service accounts.
KV v2 secrets engine. Cross device and cross cluster sync. Vault token authentication.
Cross cluster sync. Vault token auth.
Google Cloud Secret Manager with IAM integration. Auto versioned. Native to Cloud Run, GKE, and Cloud Functions.
IAM integrated auth. Automatic versioning. Cloud native sync.
# Store new secrets in 1Password from now on npx secretless-ai backend set 1password # Or copy the stored secrets to 1Password and switch to it npx secretless-ai migrate --from local --to 1password
MCP secret protection
When AI tools use MCP servers, credentials can leak through:
- Tool call parameters (MCP server configs with inline API keys)
- File reads (.env, config files with embedded credentials)
- Conversation history (credentials pasted into chat)
- Error messages (stack traces revealing connection strings)
Secretless blocks all these vectors by ensuring credentials never enter the LLM context window.
Every MCP server config has plaintext API keys in JSON files. The LLM sees them. Secretless encrypts them.
$ npx secretless-ai protect-mcp
Secretless MCP Protection
Scanned 1 client(s)
+ claude-desktop/browserbase
BROWSERBASE_API_KEY (encrypted)
+ claude-desktop/github
GITHUB_PERSONAL_ACCESS_TOKEN (encrypted)
+ claude-desktop/stripe
STRIPE_SECRET_KEY (encrypted)
3 secret(s) encrypted across 3 server(s).{
"mcpServers": {
"stripe": {
"command": "npx",
"args": ["-y", "@stripe/mcp"],
"env": {
"STRIPE_SECRET_KEY": "<plaintext key>"
}
}
}
}{
"mcpServers": {
"stripe": {
"command": "secretless-mcp",
"args": ["npx", "-y", "@stripe/mcp"],
"env": {}
}
}
}HashiCorp Vault Backend
The Vault backend connects to a HashiCorp Vault instance using the KV v2 secrets engine. Secrets are read and written through the Vault HTTP API with token-based authentication. This backend is suited for teams that self-host their secret infrastructure or need cross-cluster credential synchronization.
# Point Secretless at the Vault server (add these to your shell profile) export VAULT_ADDR=https://vault.example.com export VAULT_TOKEN=<your-token> # Set as the active backend npx secretless-ai backend set vault
npx secretless-ai migrate --from local --to vault| Environment variable | Description |
|---|---|
| VAULT_ADDR | Vault server URL (e.g., https://vault.example.com). Required. |
| VAULT_TOKEN | Token that authenticates Vault API requests. Required. |
backend set vault and migrate stop with an error when either variable is unset. The CLI reads and writes secrets on the KV v2 engine mounted at secret and has no setting for another mount, a path prefix or a Vault Enterprise namespace. Code that imports VaultBackend from the secretless-ai package can pass another mount to its constructor: new VaultBackend({ mountPath: 'kv' }). The constructor also accepts addr and token in place of the two variables; it has no path prefix or namespace option.
GCP Secret Manager Backend
The GCP Secret Manager backend stores secrets in Google Cloud Secret Manager using the REST API with zero SDK dependency. Authentication uses Application Default Credentials (ADC) or a service account key file. This backend integrates natively with Cloud Run, GKE, and Cloud Functions.
# Authenticate with GCP (one-time) gcloud auth application-default login # Set as the active backend npx secretless-ai backend set gcp-sm
npx secretless-ai migrate --from local --to gcp-sm| Configuration | Environment Variable | Description |
|---|---|---|
| Project ID | gcp.projectId in config.json | GCP project containing the secrets. Auto-detected from service account key or ADC. |
| Key file | GOOGLE_APPLICATION_CREDENTIALS | Path to service account key JSON file (alternative to ADC) |
Credential scope discovery
Credential permissions change over time as platforms evolve. Scope discovery records what a stored credential can do as a baseline, and a later check reports the permissions added since.
Credential Scope Discovery detects when the permissions associated with a credential change after it was initially stored. This covers both scope expansion (a token gains new permissions) and scope contraction (permissions are revoked). Detecting scope drift is important because a compromised token that silently gains elevated permissions can be exploited without triggering traditional secret rotation alerts.
Supported Providers
| Provider | Credential | Detection Method | Status |
|---|---|---|---|
| GCP | Service account key JSON | testIamPermissions API | Available |
| HashiCorp Vault | Token prefix detection | capabilities-self endpoint | Available |
| AWS | Access key prefix detection | STS plus IAM introspection | Available |
All providers use self inspection APIs. No additional permissions required.
Commands
| Command | Description |
|---|---|
npx secretless-ai scope discover NAME | Probe the current permissions of the named credential and save them as its baseline. |
npx secretless-ai scope check NAME | Compare current permissions against the stored baseline. Reports expanded or contracted scopes. |
npx secretless-ai scope list | Display the recorded scope baselines for all credentials. |
npx secretless-ai scope reset NAME | Clear the baseline of the named credential, to discover it again. |
# Discover current permissions, save baseline $ npx secretless-ai scope discover MY_GCP_KEY # Compare current permissions to saved baseline $ npx secretless-ai scope check MY_GCP_KEY # List all stored baselines $ npx secretless-ai scope list # Clear a baseline to re discover $ npx secretless-ai scope reset MY_GCP_KEY
Runs on demand
The scope commands run when they are called; nothing schedules them. The broker does not read scope baselines: since 0.22.1 a policy rule that names scopeCheck is refused when the policy loads.
Allowlist and custom rules
A gitignore style .secretlessignore file suppresses known false positives. Custom deny rules add organization specific patterns. Both contain patterns, not secrets, so they are safe to commit.
Organizations can define additional deny patterns specific to their environment. These extend the built-in 57 credential patterns with company-specific env vars, config files, and CLI tools, and do not replace them.
# Safe to commit -- contains patterns, not secrets env: - ACME_* - INTERNAL_* files: - "*.acme-credentials" - ".corp-config" bash: - "curl*internal.corp.com*" - "corp-vault*get*"
Patterns use glob syntax where * matches any characters. Each pattern generates deny rules that block AI tools from accessing matching env vars, files, or running matching commands.
| Command | Description |
|---|---|
npx secretless-ai rules init | Create a .secretless-rules.yaml template in the current directory |
npx secretless-ai rules list | Show active custom rules and the number of deny rules they generate |
npx secretless-ai rules test "PATTERN" [--env|--file|--bash] | Preview generated deny rules for a pattern |
$ npx secretless-ai rules init $ npx secretless-ai rules test "ACME_*" $ npx secretless-ai rules list
After editing the rules file, run npx secretless-ai init to apply changes to your AI tool configurations.
Secret management
Store, list, and inject secrets without exposing them to AI tools. Import from .env files or set them individually.
Secretless provides encrypted secret storage with multiple backend support. Secrets are stored outside the project directory and injected at runtime.
| Command | Description |
|---|---|
npx secretless-ai secret set NAME=VALUE | Store a secret in the active backend |
npx secretless-ai secret list | List stored secret names (values are never displayed) |
npx secretless-ai secret get NAME | Retrieve a secret value (requires biometric on supported backends) |
npx secretless-ai secret rm NAME | Delete a stored secret |
npx secretless-ai run -- <command> | Run a command with all stored secrets injected as env vars |
npx secretless-ai run --only NAME -- <command> | Run a command with only the named secrets injected |
npx secretless-ai import <file> | Import secrets from a .env file into the active backend |
npx secretless-ai import --detect | Auto-detect .env files in the current directory and import all |
npx secretless-ai env | Output export statements for stored secrets (source-able in shell) |
$ npx secretless-ai secret set OPENAI_API_KEY=sk-... Stored: OPENAI_API_KEY $ npx secretless-ai run --only OPENAI_API_KEY -- python app.py # app.py reads os.environ["OPENAI_API_KEY"] at runtime
$ npx secretless-ai secret list
4 secret(s):
ANTHROPIC_API_KEY
OPENAI_API_KEY
STRIPE_KEY
DATABASE_URL
# Inject all secrets into a command
$ npx secretless-ai run -- npm test
# Inject only specific keys
$ npx secretless-ai run --only STRIPE_KEY -- npm start
# Import from existing .env files
$ npx secretless-ai import --detect
Secretless Import
.env: 4 imported
.env.local: 2 imported
Total: 6 secret(s) imported.AI safe guard
When an AI tool tries to read a secret value, secretless detects the non interactive context and blocks output.
$ npx secretless-ai secret get STRIPE_KEY
secretless: Blocked -- secret values cannot be read in non-interactive contexts.
AI tools capture stdout, which would expose the secret in their context.
To inject secrets into a command:
npx secretless-ai run -- <command>
To force output (e.g. piping to clipboard):
npx secretless-ai secret get <NAME> --forceDirect terminal access (a human at a real TTY) works normally. The guard detects non interactive execution, which is how AI tools run commands, and refuses to output secret values. With --force, secret get prints the value in a non interactive context as well.
Credential broker
Identity aware credential access control daemon. Enforces deny all policies so each credential is only accessible to authorized agents. Supports AIM identity verification, trust score constraints, and rate limiting.
- Deny all by default.
- Per credential policy rules.
- AIM identity plus trust score constraints.
The credential broker is a local daemon that mediates access to stored secrets. Instead of injecting all secrets into a process environment, the broker grants access per-request based on configurable policies. This enables rate limiting, trust-based access control, and audit logging for credential usage.
| Command | Description |
|---|---|
npx secretless-ai broker start [--port N] [--policy-file PATH] | Start the broker daemon |
npx secretless-ai broker stop | Stop the broker daemon |
npx secretless-ai broker status | Show broker status, uptime, and request count |
Policy constraints include rateLimit (max requests per time window), minTrustScore (AIM integration) and requireCapability (named permission check). A rule that names scopeCheck is refused when the policy loads (see credential scope discovery). Default policy is deny-all. Only explicitly allowed credentials are accessible.
The broker authenticates clients using bearer tokens. On startup, the broker generates a cryptographically random token (32 bytes via crypto.randomBytes) and writes it to ~/.secretless-ai/broker.token with mode 0600. Clients must include this token in the Authorization: Bearer header. Token comparison uses crypto.timingSafeEqual to prevent timing side-channel attacks.
Wires into agent identity
When the credential broker runs, every credential access is attributable to a cryptographically signed agent identity. Trust score and policy gates apply per agent.
- Agent attribution. Every broker decision is logged against an AIM identity, not a process or shell.
- Trust score gates. Policy rules can require a minimum trust score. Suspended or revoked agents lose credential access immediately.
- Shared CLI surface. opena2a-cli exposes secretless protect, broker, and scan commands through a unified surface.
Security Architecture
All cryptographic operations use Node.js built-in crypto module with no third-party dependencies.
| Function | Algorithm | Details |
|---|---|---|
| Secret encryption | AES-256-GCM | Authenticated encryption with 96-bit IV, 128-bit auth tag |
| Key derivation | scrypt | N=16384, r=8, p=1, 32-byte derived key |
| Session integrity | HMAC-SHA256 | Timing-safe verification of session state files |
| Broker auth | Bearer token | 32-byte random token, timing-safe comparison |
| Transcript redaction | Pattern matching | Regex-based credential detection with context-aware replacement |
All symmetric primitives (AES-256, HMAC-SHA256, scrypt) are not affected by quantum computing advances. Asymmetric operations (GCP JWT signing via RS256) are handled by cloud provider infrastructure and outside the scope of this tool.
Data loss prevention
Scan AI tool transcripts, shell history, and conversation logs for leaked credentials. Redact findings in place or preview with dry run. Set up real time monitoring to catch leaks as they happen.
AI tools store conversation transcripts locally. If a credential was accidentally pasted into a conversation, it persists in the transcript file. Secretless can scan and redact credentials from stored transcripts.
| Command | Description |
|---|---|
npx secretless-ai clean | Scan and redact credentials in stored transcripts |
npx secretless-ai clean --last | Scan and redact the transcript of the last session only |
npx secretless-ai clean --dry-run | Preview the redactions without writing them |
npx secretless-ai scan --history | Scan shell history for credentials |
npx secretless-ai clean-history | Redact credentials in shell history |
npx secretless-ai watch start | Monitor transcript files in real-time and redact on write |
npx secretless-ai watch stop | Stop the transcript monitor |
npx secretless-ai watch status | Check if the monitor is running |
- Shell history scanning and redaction.
- AI transcript credential detection.
- Real time watch daemon with system daemon support.
- Dry run mode for safe preview.
Git protection and verification
A pre-commit hook scans staged files for secrets before they enter git history. The verify command runs on demand: it lists the known API key variables set in the shell and reports any credential it finds in AI context files or in AI tool transcripts.
$ npx secretless-ai hook install Pre-commit hook installed. $ npx secretless-ai hook status Pre-commit hook: installed
npx secretless-ai verifyNanoMind integration
Optional integration with NanoMind adds two enhanced analysis features. Both gracefully degrade when the NanoMind packages are not installed.
npm install @nanomind/guard @nanomind/engine- MCP injection screening.
protect-mcpscreens env-var values for prompt-injection patterns and warns when suspicious content is detected. - Rich scan explanations.
scan --explaingenerates context-aware security explanations for each finding using NanoMind's local inference engine.
Supported tools
Six AI coding tools. What Secretless installs differs by tool: each supported AI tool gets a protection method matched to what that tool can enforce.
| Tool | Protection method | How it is applied |
|---|---|---|
| Claude Code | PreToolUse hook plus deny rules and CLAUDE.md instructions | Denied before the tool call runs |
| Cursor | .cursorrules instructions | Instruction file, not enforced |
| GitHub Copilot | .github/copilot-instructions.md instructions | Instruction file, not enforced |
| Devin Desktop (formerly Windsurf) | .windsurfrules instructions | Instruction file, not enforced |
| Cline | .clinerules instructions | Instruction file, not enforced |
| Aider | .aiderignore file patterns | Ignore patterns the tool applies |
In Claude Code, Secretless uses hooks: a script runs before the assistant's tool calls and denies one that would read a credential file. It is a gate on the assistant's tool path, not a boundary around the machine. For the other tools the protection is an instruction file or ignore patterns.