Skip to content
VoidNote
Announcement

2 March 2026

Void Streams: encrypted live chat and a better way to give secrets to AI agents

A Void Stream is a live encrypted channel that self-destructs when it closes. Use it to chat securely between two devices — or to hand a bundle of environment variables to a coding agent that will never actually see the keys.

What is a Void Stream?

A Stream is a one-way or two-way live channel where every message is encrypted before it leaves your device. The server sees only ciphertext. When the stream closes — by your choice, or when it expires — every message is destroyed. There is no history, no replay, no archive.

The decryption key is embedded in the stream URL itself. Messages are encrypted and decrypted in the browser, and the server stores and relays only ciphertext. The stream URL's path, key included, reaches our server with each stream request; the key is never saved.

Optional password protection adds a second layer: even if someone intercepts the stream URL, they still can't join without the password. That password is hashed with PBKDF2 at 100,000 iterations — brute-forcing it is not practical.

Device-to-device secure chat

The simplest use case: you're on your laptop, your phone is in another room (or country), and you need to send something sensitive — a password, an OTP, a code snippet — without it touching iCloud, Google Drive, Slack, or any other service that stores it indefinitely.

Create a stream, share the link, open it on the other device. Type a message, it appears instantly, encrypted in the browser. Close the stream when you're done. Gone.

Streams work in any browser, including the one on your phone. No account needed on the receiving end — just the link. Creating a stream needs a free account.

The problem with giving AI agents secrets

AI coding agents — Claude Code, Cursor, Copilot Workspace, custom agent loops — are genuinely useful for real work now. That means they need access to real secrets: deployment keys, database credentials, API tokens, third-party service keys.

The current options are all bad. Paste secrets into the context window and they end up in logs, conversation history, and model provider infrastructure. Point the agent at a .env file and it's on disk, often accidentally committed. Use a secrets manager and you're granting the agent a long-lived credential to the manager itself, which is now the single point of compromise.

What you actually want is: give the agent exactly the secrets it needs, for exactly as long as it needs them, and have those secrets self-destruct the moment they're consumed.

A VoidNote link as a bundle of environment variables

Here's the pattern. You create a note containing all the environment variables your agent needs for a given project:

# What you put in the note

DEPLOY_KEY=sk-proj-abc123...

DATABASE_URL=postgresql://user:pass@host/db

STRIPE_SECRET=sk_live_xyz789...

SENTRY_DSN=https://abc@sentry.io/123

You get back a URL like https://voidnote.net/n/abc123#secretkey. You paste that single URL into the agent's context, or your project's CLAUDE.md, or a CI environment variable.

The agent reads the note once using the SDK:

import

{ read } from 'voidnote-sdk';

// Agent does this at the start of the session

const { content: env } = await read(process.env.VOIDNOTE_ENV_URL);

// env = "DEPLOY_KEY=sk-proj-abc...\nDATABASE_URL=..."

// Parse and inject into process.env, or use directly

const vars = Object.fromEntries(

  env.split('\n').map(line => line.split('='))

);

The note burns. The agent has the values it needs in memory for the duration of the session. The next time the agent starts, it needs a fresh note — which you create fresh, with whatever keys you want to grant for that session.

The agent never sees a persistent credential. It sees a URL — dead after one read. Rotate credentials by creating a new note. The old URL is useless the moment it's been consumed.

Add a password for a second lock

Notes and streams both support an optional password. When set, even possessing the URL isn't enough — the reader must also know the password before the content is decrypted.

For agent workflows this is powerful: the URL lives in a config file or environment variable (which an attacker might find), but the password lives only in the agent's system prompt or is passed separately via a secure channel. Compromise of either alone yields nothing.

For human-to-human secure chat, you share the stream URL through one channel (say, email) and the password through another (say, SMS). An attacker who intercepts either channel still can't read the messages.

Streams as a live secret channel for agents

Notes are single-shot. Streams are continuous. If your agent workflow involves an ongoing session where you want to push new secrets mid-run — rotate a key, pass a one-time code, send a dynamic credential — a stream gives you a live encrypted channel to do that.

Create a stream, keep it open on your end, and have the agent listen for SSE messages. Every message is encrypted before it leaves your device and decrypted only in the agent process. You can push key=value pairs in real time. Close the stream when the session is done — all messages are gone.

# Push a new secret mid-session

echo "GITHUB_TOKEN=ghp_newtoken123" | voidnote stream write <stream-url>

# Agent picks it up instantly via SSE — encrypted, ephemeral

What the server holds

This isn't a marketing claim. The cryptographic model is auditable:

note URL: voidnote.net/n/<tokenId>#<secret>

stream URL: voidnote.net/stream/<tokenId><secret>

key = SHA-256(secret) ← derived locally, never stored

ciphertext = AES-256-GCM(plaintext, key, random_iv)

server stores: tokenId + ciphertext + iv ← no key stored

The server stores notes and stream messages only as ciphertext, without keys. A subpoena for stored data produces only ciphertext. A breach of our database produces only ciphertext. Note links in the /n/…#secret form never send the key to us; stream links, and older /note/ links, do carry it to our server when used, and it is not saved. The only way to read a note or stream is to have the URL.

The SDKs and the CLI are open source on GitHub, so you can verify the crypto implementation yourself — and on the website, your browser's DevTools show exactly what is sent. You don't have to take our word for it.

Try it

Streams are live now. Create one on the website — or from the CLI if you want to pipe output directly into a stream. The SDKs have full stream support if you want to integrate into your own agent loop.

Everything is free. Notes need no account; streams and the vault come with a free account.