A deploy fails, and you paste the error into your assistant to ask what went wrong. The error includes a database URL with the password in it. The session goes well, so you save it as a useful debugging record. A month later you share the project with a teammate, and the password goes with it.
Nobody decided to leak that secret. It travelled through four normal steps: an error message, a chat, a saved transcript, a share. AI-assisted work adds new places for secrets to end up, and each one can be copied, stored or shared.
This guide shows you where secrets enter your AI context, how to keep them out of the files your assistant reads, how to clean transcripts before you keep them, and what to do when a key leaks anyway.
How secrets end up in AI context
Secrets rarely leak because someone was careless in one big way. They leak through small, normal actions. The common paths are:
- Pasting into a chat. An error message, a config snippet, a
curlcommand with anAuthorizationheader. - The assistant reading files. A coding agent that can read your project can read
.env, local config files and key files if nothing stops it. - Command output. Asking the assistant to run
env,printenv,docker inspector a verbose deploy command can print secrets into the session. - Saved transcripts. Everything above ends up in the transcript. Save it, and the secret is now a file in your project.
- Project memory and instructions. A note like "staging DB: postgres://admin:hunter2@..." in
CLAUDE.mdor a notes file, written to save time.
Each path needs its own habit. No single tool closes all of them.
Never paste a secret into a chat
This is the simplest rule and the most important one. If a value would let someone access a system, it does not go into the conversation.
Before you paste an error, config file or command, replace secret values with placeholders. Instead of this:
DATABASE_URL=postgres://app:Xk29fLq@db.internal:5432/orders
Paste this:
DATABASE_URL=postgres://app:<REDACTED>@<DB_HOST>:5432/orders
The assistant almost never needs the real value to help you. It needs the shape: which variable, which format, which error. If it truly needs to use a credential to run a command, let the command read it from the environment rather than writing it into the prompt.
A useful habit: treat anything you type or paste into an assistant as something that could later be saved and shared. If you would not put it in a pull request description, do not put it in a chat.
Keep secrets out of the files your assistant reads
Your assistant works with the files in your project. Make sure the secrets are not among them, or at least not easy to reach.
Use .env for values and .env.example for names
Keep real values in a local .env that is never committed. Commit a .env.example with the variable names and harmless placeholders. A .env.example might look like this:
DATABASE_URL=postgres://user:password@localhost:5432/orders_dev
STRIPE_API_KEY=sk_test_replace_me
SENTRY_DSN=
Your assistant and your teammates can read .env.example to learn which variables exist, without seeing any real value.
Keep secrets out of instructions and memory
Your CLAUDE.md, AGENTS.md and project notes should describe where secrets come from, never contain them:
### Environment
- Local values live in `.env` (copy `.env.example`). Never print or read `.env`.
- Staging credentials are in the team password manager, entry "billing-staging".
- Do not run `env` or `printenv`; ask me for a specific variable name instead.
Instructions like these help, because Claude Code reads CLAUDE.md and many coding agents read AGENTS.md. But an instruction is a request, not a lock. If a file with real secrets is in reach, assume it could be read. The article on writing CLAUDE.md and AGENTS.md covers how to phrase rules like these clearly.
Keep key files outside the project folder
Private keys, service account files and cloud credentials belong in your home folder, a secret manager or your operating system's keychain, not in the repository tree. If a tool needs a path, point it there through an environment variable.
Use ignore files as a second layer
Ignore files stop secret files from being committed or captured by tools that respect them. A starting .gitignore for secrets:
.env
.env.*
!.env.example
*.pem
*.key
*.p12
id_rsa*
credentials.json
service-account*.json
.aws/
.secrets/
Keep two limits in mind:
- Ignore files work on filenames, not content. A token pasted into
notes.mdor a saved transcript is not caught by any pattern above. - Ignoring a file does not remove it from history. If
.envwas committed before you added the rule, it is still in past commits. Treat those values as leaked and rotate them.
If you use a tool that has its own ignore file, such as .prjignore for PrjLab, list anything there that should stay in your git repository but out of that tool.
Clean transcripts before you keep them
Saved sessions are valuable, and they are also the easiest place for a secret to hide. Every error, command output and paste is in there. The guide on which AI coding sessions are worth keeping explains how to choose them. Before you keep one, clean it:
- Prefer a summary. A short write-up of the symptom, cause and fix usually carries the value without the raw output.
- Search for secret patterns. Run a quick check over your saved context:
grep -rniE 'api[_-]?key|secret|token|password|passwd|bearer|authorization:|BEGIN [A-Z ]*PRIVATE KEY|://[^ /]+:[^ @]+@' \
.prjcontext/ CLAUDE.md AGENTS.md
The last pattern catches URLs with a user and password in them, like database connection strings. Expect false positives; you are looking for real values.
- Read it anyway. Pattern searches miss secrets that look like random strings, customer data and internal hostnames. A human read is the real check.
- Replace, do not blur. Swap values for clear placeholders such as
<REDACTED>so the record still makes sense.
Do this before you share context with anyone. The article on sharing AI coding context with your team has a full review pass.
If a key leaks: rotate first, clean up second
If a real secret ended up in a chat, a committed file, a saved transcript or a shared project, assume it is compromised. Deleting the text does not undo who or what may already have a copy.
Work through these steps in order:
- Revoke or rotate the secret at the provider: issue a new key, change the password, invalidate the token. Do this first.
- Update where the new value lives: your local
.env, your secret manager, your deployment settings. - Check for misuse in the provider's access logs or billing, where available.
- Remove the old value from files, transcripts and notes, and replace it with a placeholder.
- Close the path it came through. Add the ignore rule, move the key file out of the project, or add a line to your instructions.
Rotation is the step that actually protects you. Cleaning up the file matters, but it only prevents the next copy.
How PrjLab handles this
We built the prj CLI to help with secret hygiene, not to replace it. It skips obvious secrets such as .env files, key files and credential folders, and anything listed in .gitignore or .prjignore. That filter works on file names and paths, so it is a safety net, not a complete secret scanner: a key pasted into a session file or a note is not caught. That is why you run prj status to see what would be captured, and review it, before prj push. Global assistant folders, other projects and machine credentials are never scanned, and prj login stores your own sign-in in the operating system's keychain, never in a plain file. Repositories are private by default and files are encrypted at rest; if you make a repository public, its memory and sessions become readable by anyone, so clean them first.
Frequently asked questions
Is it OK to paste a test or sandbox key into a chat? It is better not to. Test keys can still cost money or expose data, and the habit of pasting keys is what causes real leaks.
Does adding .env to .gitignore protect a key I already committed?
No. The value is still in your history. Rotate the key, then clean up.
Will PrjLab stop me from pushing a secret?
It skips .env files, key files, credential folders and your ignored paths. It does not scan file contents, so review prj status and your saved sessions before you push.
Can I tell my assistant not to read .env?
Yes, and it is worth adding to your instructions. Treat it as a request, not a guarantee, and keep real secrets out of reach where you can.
To set up a project with clean context from the start, follow the getting-started guide.