A CLI toolkit for managing secrets through AWS Secrets Manager — designed so AI coding assistants never see your credentials.
When using AI coding tools (Claude Code, Gemini CLI, Codex, Cursor, etc.), you're often asked to paste API keys and passwords directly into the conversation. That means your secrets end up in:
- AI conversation logs
- Process arguments visible via
ps aux - Shell history
secret-store solves this by routing all credential entry through a separate terminal, with the value going straight to AWS Secrets Manager over TLS. The AI only ever knows the name of the secret, never the value.
AI assistant needs an API key
|
v
AI runs: secret-store create "myproject/stripe/api-key"
|
v
Prints a command for YOU to run in a separate terminal
|
v
You paste the command, type the value --> encrypted in AWS Secrets Manager
|
v
AI verifies: secret-store verify "myproject/stripe/api-key"
|
v
Scripts retrieve at runtime: $(secret-get "myproject/stripe/api-key")
The secret value never appears in the AI conversation, process args, or shell history.
| Stage | Protection |
|---|---|
| User types value | read -sp — hidden input, no echo to terminal |
| On disk (briefly) | mktemp + chmod 600 — only owner can read |
| Passed to AWS CLI | --cli-input-json file:// — not in process args, invisible to ps aux |
| After use | shred -u overwrites file with random data, then deletes |
| In transit | AWS CLI uses HTTPS/TLS |
| At rest | AWS Secrets Manager encrypts with AES-256 via KMS |
| In AI conversation | Never appears — AI only sees the secret name |
bash <(curl -sL https://raw.githubusercontent.com/AnkitClassicVision/secret-store/main/install.sh)Or clone and run:
git clone https://github.com/AnkitClassicVision/secret-store.git
bash secret-store/install.sh- AWS CLI installed and configured (
aws configure) - IAM permissions for
secretsmanager:*(or scoped to your prefix) ~/.local/binon yourPATH(the installer handles this)
cp secret-store secret-get secrets-lib.sh ~/.local/bin/
chmod +x ~/.local/bin/secret-store ~/.local/bin/secret-get ~/.local/bin/secrets-lib.sh$ secret-store create "myproject/stripe/api-key" "Stripe API key for production"
To CREATE secret 'myproject/stripe/api-key', run this in a separate terminal:
read -sp 'Enter value: ' v && echo "" && \
f=$(mktemp) && chmod 600 "$f" && \
printf '{"Name":"%s","Description":"%s","SecretString":"%s"}' 'myproject/stripe/api-key' 'Stripe API key for production' "$v" > "$f" && \
aws secretsmanager create-secret --region us-east-1 --cli-input-json "file://$f" && \
shred -u "$f" 2>/dev/null || rm -f "$f"; \
echo "Created."Copy that command, open a new terminal tab, paste it, type your secret.
$ secret-store verify "myproject/stripe/api-key"
Secret 'myproject/stripe/api-key' exists and has a value.Bash:
# Option 1: Direct
API_KEY=$(secret-get "myproject/stripe/api-key")
# Option 2: Source the library
source ~/.local/bin/secrets-lib.sh
API_KEY=$(get_secret "myproject/stripe/api-key")
# Option 3: Fail if missing
API_KEY=$(require_secret "myproject/stripe/api-key")Python (drop-in replacement for load_dotenv):
# Replace: from dotenv import load_dotenv; load_dotenv()
# With:
from secrets_loader import load_secrets
load_secrets("myproject/env") # loads all secrets under prefix into os.environ
# Then os.getenv() keeps working as before:
import os
api_key = os.getenv("STRIPE_API_KEY")Run any command with secrets pre-loaded (no code changes needed):
secret-env myproject/env -- python3 my_script.py
secret-env myproject/env skills/exa -- python3 multi_service.py$ secret-store update "myproject/stripe/api-key"
# Prints command to run in separate terminal$ secret-store list$ secret-store delete "myproject/stripe/api-key"
# Prints command to run in separate terminal<project>/<service>/<key-name>
Examples:
webapp/stripe/api-keybackend/database/passwordmobile-app/firebase/server-key
The installer automatically configures these AI tools to use the secrets protocol:
| Tool | Config File | What It Does |
|---|---|---|
| Claude Code | ~/.claude/CLAUDE.md |
Global instruction for all projects |
| Gemini CLI | ~/.gemini/GEMINI.md |
Global instruction for all sessions |
| Codex CLI | ~/.codex/instructions.md |
Global instruction for all sessions |
| Other | AGENTS.md (per repo) |
Add protocol reference manually |
Drop this into your AI tool's instruction file:
## Secrets Management — MANDATORY
NEVER ask the user to paste API keys, passwords, tokens, or credentials into the conversation.
When any secret/credential is needed:
1. Run: `secret-store create "project/service/key-name" "Description"`
2. Tell the user to run the printed command in a separate terminal tab
3. User types the value there — stored in AWS Secrets Manager, never visible to AI
4. Verify: `secret-store verify "project/service/key-name"`
5. In scripts: `$(secret-get "project/service/key-name")`Or reference the full protocol: AI-HARNESS-PROTOCOL.md
Each team member needs:
- AWS CLI configured with their own IAM credentials
- IAM permissions for Secrets Manager (example policy below)
- Run the installer:
bash install.sh
In practice you usually want two roles:
- Read-only (runtime/CI) — can fetch secrets at deploy/runtime
- CRUD (operators/dev) — can create/update/delete secrets
Note:
secretsmanager:ListSecretscannot be meaningfully resource-scoped, but it’s only needed if you usesecret-env/secrets_loader.py(they enumerate by prefix). If you only ever callsecret-getwith exact names, you can omitListSecrets.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:*:ACCOUNT_ID:secret:myproject/*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:ListSecrets"
],
"Resource": "*"
}
]
}{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:CreateSecret",
"secretsmanager:PutSecretValue",
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:DeleteSecret"
],
"Resource": "arn:aws:secretsmanager:*:ACCOUNT_ID:secret:myproject/*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:ListSecrets"
],
"Resource": "*"
}
]
}Replace ACCOUNT_ID with your AWS account ID and myproject/* with your prefix to scope access (or a deeper prefix like myproject/service/*).
| Command | Description |
|---|---|
secret-store create <name> [desc] |
Print command to create a new secret |
secret-store update <name> |
Print command to rotate a secret's value |
secret-store verify <name> |
Confirm a secret exists and has a value |
secret-store list |
List all secrets in the account |
secret-store delete <name> |
Print command to delete a secret |
secret-store get-arn <name> |
Print the ARN of a secret |
secret-get <name> |
Retrieve a secret's value (for scripts) |
secret-env <prefix> -- <cmd> |
Run any command with secrets pre-loaded as env vars |
secret-seed <manifest> |
Bulk create/update secrets from a manifest (interactive) |
secret-rotation-check |
Flag secrets older than N days (rotation reminder) |
| File | Purpose |
|---|---|
secret-store |
Main CLI — create, update, verify, list, delete secrets |
secret-get |
Retrieve a secret value (for use in scripts) |
secret-env |
Run commands with secrets loaded as environment variables |
secrets-lib.sh |
Bash library with get_secret() and require_secret() |
secrets_loader.py |
Python drop-in replacement for load_dotenv() |
secret-seed |
Bulk create/update secrets from a manifest (interactive) |
secret-rotation-check |
Rotation reminder (age check, optional CI gate) |
install.sh |
One-line installer for scripts + AI harness configs |
AI-HARNESS-PROTOCOL.md |
Full protocol doc for any AI tool integration |
iam/secret-store-readonly.json |
Read-only IAM policy template |
iam/secret-store-crud.json |
CRUD IAM policy template |
MIT