Secrets and safe mode
A password, a token or a key used to reach a chat one way only: you typed it as a message. From there it lived in the transcript on disk, in the model's context and in every following request to the provider — and there was no taking it back.
Now the agent has a separate path: it asks for the value as a card, and you hand it over so that it never enters the conversation.
How it looks
- The agent needs a password — it asks for it by name and explains what for.
- The reply stops, and a card appears above the composer: a password field, "Done" and "Refuse". The eye icon inside the field shows what you typed, if you need to check.
- The value goes to the server and lives in its memory only. The agent gets the answer "accepted" — it knows the name, not the value.
- From then on the agent writes
{{secret:name}}in a command, and the server substitutes the value at launch.
While the card hangs there, the work is stopped. The same notifications that announce a model's question call you to it: a push in the browser, a tray toast, the Android shade, a bot message — and in the chat lists such a session stands with a 🔑, the secret's name and an amber frame. Answering from a notification is impossible everywhere, and on purpose: the value is typed only in the card in the chat itself. A password sent to the bot would land on Telegram's servers.
A note next to the value
The card's second field is a note to the agent, and it travels in plain text. A secret is rarely self-sufficient: "this one is temporary, until the evening", "VPN first", "this database is on a different port". Without the note the card had exactly two answers — "accepted" and "refused" — and everything else had to be typed as a message.
The password goes in the password field, the conditions go in the note. Not the other way round.
What happens to the value
- The value is never written to disk and never reaches the transcript: it lives in the server's memory while this session runs.
- The command receives it through the shell's input, not as an argument:
psshows other processes' command lines to the whole machine, and a password in an argument is a password in plain sight. - The output is scrubbed: if the command prints back what it was given, the feed and the model will see
•••. - A newline inside a value is rejected — line-by-line delivery wouldn't survive it, and instead of quietly mangling the value you get a refusal.
A command can pass the secret on by itself
What is protected is our shell's command line, not the command line of whatever it launches. ssh host "… $PASS", docker run -e PASS=$PASS, wsl.exe -- bash -lc "PASS='$PASS' …" expand the value into another process's ps. The agent is warned about this, but if you are writing such a command yourself — remember it.
Safe mode
A switch on the chat itself, next to the permission mode — both in the web UI and on Android. On by default, turned off deliberately and one chat at a time: a secret that has once entered the conversation can no longer be taken out of it.
What it does:
- tells the agent how to ask — don't hunt for passwords in files and environment variables, don't ask you to send them as a message, raise a card instead;
- closes the storage files —
.env,.credentials.json, ssh keys,*.pem,.aws/**,.npmrc,.netrc,.docker/config.json: reading such paths with the file tools is refused, with an explanation of what to do instead.
What it does not do:
- it doesn't lock down the shell —
Bashcan read a file in a hundred ways, and banningcatwould draw a border where there is none. The real border is elsewhere: the secret isn't on disk at all, and a key need not be given a terminal; - it doesn't protect you from yourself — a password typed as a message sits in the transcript, and the mode has nothing to do with it;
- it doesn't encrypt the server's memory — whoever reads the process memory reads the secrets. What protects you there is not the mode but the fact that only you have access to the machine.
In the terminal a password doesn't stick either
ssh, sudo, gh auth login ask for passwords themselves. The terminal sees that a hidden input is going on — by the terminal's real signal, not by the wording of the prompt — and what you type stays neither on the screen nor in the client's history.
What is missing so far
- Secrets across sessions. Every new chat asks again: keeping them longer would mean a store on disk, which is exactly what all this was built to avoid.
- Substitution in your own commands.
{{secret:name}}is understood by the agent only; a command you type yourself in the terminal or through!will ask for the password the ordinary way.