You paste a failing request into the session so the assistant can see what the API actually returned. The response block includes the headers, and the headers include Authorization: Bearer sk_live_.... The assistant spots the typo in your retry logic, you fix the bug, the conversation moves on. Three days later you decide that session is worth keeping, because it holds the only written reasoning behind the backoff you chose. The key is still in it, twelve messages up.

Secrets in session transcripts almost always arrive that way. Not through a committed .env, not through a sloppy instruction file, but through the ordinary act of showing the assistant something real so it can be useful.

Advice on keeping secrets out of your AI context tends to cover the source: ignore rules, key folders, environment variables. A transcript is a different kind of artifact. It is a record of everything that entered the conversation, including what entered by accident, and the moment you start keeping sessions it stops scrolling off the screen and starts being a file.

Where secrets in session transcripts actually come from

Three routes, roughly in order of how often they catch people.

What you paste. Stack traces carrying a connection string in the DSN. A curl command copied straight out of your shell history with -H "Authorization: ..." attached. A config file dumped in full "so you can see the shape". A CI log from the job that failed, which prints the environment at startup.

What tool calls return. The assistant runs something and the output lands in the transcript verbatim. printenv, a cat of a compose file with inline credentials, git remote -v on a repo whose origin URL has a token in it, a test that helpfully prints the service account token when the assertion fails.

What the assistant echoes back. This is the one people miss, because nobody typed it on purpose. The assistant confirms "I've set the client to use sk_live_4f8...", or writes an example code block with your real value filled in instead of a placeholder, or quotes your paste back while explaining it. One pasted key can appear four times in a long session.

Scrub before you keep, not after you push

Removing a secret from a file is cheap. Removing it from history is not, and the honest answer to an exposed credential was always rotation rather than deletion.

That matters more once sessions become project history. Every push creates an immutable version, so a key you strip out in version nine is still sitting in version eight, readable by anyone who can read the repository and downloadable as a .zip. Pushing sessions to a repo means a transcript you kept is a transcript you distributed: readers can clone it, and if the repository is ever made public, the contents of .prjcontext/sessions/ go public with everything else.

The CLI helps at the edges. It skips .env files, key files and credential folders, plus anything in .gitignore or .prjignore. It cannot read your transcript and tell that line 340 is a live token, which is why prj status is a list to review rather than a verdict to trust.

So the clean pass belongs at the moment you decide the session is worth keeping, before it becomes a version.

A two-minute pass before you save a session

Work through the transcript file with your editor's search rather than by reading top to bottom. Six passes, in this order:

  1. Known prefixes. sk_, sk-, pk_live, ghp_, github_pat, AKIA, xoxb, eyJ (the start of most JWTs), -----BEGIN. Two minutes of grep catches most of what matters.
  2. Assignment shapes. Search for KEY, TOKEN, SECRET, PASSWORD, CREDENTIAL, and :// for URLs with embedded basic auth. Case-insensitive.
  3. Your own pastes. Scan the blocks you contributed. Long pastes are where whole config files and full HTTP exchanges live.
  4. Tool output blocks. Check every command the assistant ran that touched the environment, a config file, or a remote. These are usually the longest blocks and the least reread.
  5. The assistant's confirmations. Follow each real value you find to every later repetition of it. Redacting the paste and leaving the echo accomplishes nothing.
  6. Names that aren't secrets but still leak. Internal hostnames, a client's staging URL, a colleague's personal email in a git log. Not a credential, still a detail you may not want in a repository you share. Project context leaks are not only about keys.

When you find something, redact with a labelled placeholder instead of deleting the line. The reason you kept the session is reconstructing reasoning, and a bare *** tells a future reader nothing about what was there:

Authorization: Bearer [REDACTED — live payments key, rotated 2026-10-16]
DATABASE_URL=postgres://app:[REDACTED]@[internal-host]/app

If a whole exchange exists only because you were debugging an auth header, trim the exchange. Keeping less of a session is a legitimate option, and often the better one. The value usually sits in four or five turns, not the full forty.

If a secret is already in a session you kept

Fix it in this order:

Rotate the credential first. Treat it as exposed the moment it was written to a file that left your machine, which includes the assistant provider's logs regardless of what you do next. Then find every copy: the kept transcript, any memory note that quoted it, the earlier versions it already exists in. Then redact it in the current version and push, so new clones are clean. Then check who has access, because reader and writer grants both include clone, and removing someone takes effect immediately but does not reach the copy they already pulled. Finally, write one line in project memory saying the credential was rotated on that date and why, which stops a future session from reading the old value out of an older version and trying to use it.

Tie the clean pass to the keep decision

The pass works because it rides along with a decision you are already making. You finish a session, you judge whether it is worth keeping, and the scrub is the second half of that judgment rather than a separate security chore you schedule and skip. If your habit is to turn the session into a decision record before saving it, the rewrite already walks you past the risky blocks.

For a team, make the expectation explicit in your instruction file so nobody has to guess: sessions get a redaction pass before they are pushed, and anything containing a credential gets the credential rotated. That pairs with the broader habits in sharing AI coding context with your team.

We built sessions into a PrjLab repository on purpose, beside the instructions and the memory, because a transcript is often where the reasoning actually lives. The tradeoff is that a kept session is versioned and cloneable rather than ephemeral, so the two minutes before the push are the two minutes that count. The getting-started guide walks through what a push includes and how to check it first.