kip
kip push .env returns a link that expires in an hour and is deleted after one read. No account to send or receive, self-hosted with one compose file, and an 8.7 MB static binary for Linux, macOS and Windows.
The server that stores your .env cannot read it. Even if it wanted to.
The decryption key travels after the # in the URL. Browsers never send the fragment in the HTTP request, and neither does the CLI. A stolen database yields ciphertext and nothing else.
One push, one link, one read
Click through the steps or let them play. Each step lights up the piece it describes.
What the sender sees. The link line is built in the CLI, after the server has returned the id.
Two stores, one domain, zero frameworks
What sits behind the link in a real deployment. The Go server carries no web framework; secrets live in Redis and teams in SQLite.
Without Redis, the server falls back to an in-memory store for development. Without a proxy, docker-compose.yml publishes port 8080 on the host for local testing.
The staging .env crosses Slack without staying in Slack
A made-up case with short timings, to see what happens at each stage. The names are examples.
kip push .env.staging. The CLI generates the key, encrypts, uploads the blob and receives the id. It prints the link with the key after the #. The plaintext file has not left his disk.STRIPE_SECRET_KEY=sk_live… never went through Slack./api/v1/secret/h4l1…. The server hands over the ciphertext, decrements the read count and, at zero, deletes the record. The browser decrypts with the key from the fragment and shows the file with a download button.kip revoke <link> deletes the secret on the server. The link dies before the first read.Four times the obvious solution was wrong
Each challenge follows the same pattern: what anyone would do first, why it does not work, what was done, and the number that proves it. The technical detail stays folded.
The core held up under serious review: correct crypto, clean architecture, real tests. The README did not: it documented an "AI Security Scan" tier, commands like
diff and inbox, and a pricing page with plans that did not exist. Everything was cut down to what was real and the rest moved to an explicit Roadmap before the repository went public.One filter: does this ask the receiver for an account, an install or one more step?
If the answer was yes, it was out. kip lives between "paste it in Slack" and "deploy Vault", and every piece of the stack was measured against that position.
Go deeper
It installs with install.sh, which detects OS and architecture and downloads the release archive, or with go install github.com/kipenv/kip/cmd/kip@latest. The middleware is in-house: logger, CORS and a per-IP token-bucket rate limiter, 30 requests per minute by default.
Go deeper
Teams work like lobbies: one person creates, shares the invite code, the others join. No sign-up, no roles, no dashboard. The API already implements team-level sharing, inbox, audit log and a pinned "official" env per project, with tests. The CLI does not expose those endpoints yet; it is the first item on the roadmap.
CGO_ENABLED=0 on mattn/go-sqlite3: it compiled and crashed on opening the database. Today GoReleaser publishes only the CLI.SubtleCrypto and nothing else. Astro keeps the landing as HTML and Vue enters only where decryption happens.Go deeper
Point the CLI at your own server with kip config set --server, or run it locally with the development compose. When a public instance exists it will be an option, not the default.
.env, MIT. For teams that want the secret to disappear without standing up infrastructure.Five decisions I would make the other way today
Recap
# and the HTTP protocol never sends it. The server stores ciphertext; a stolen database is worthless.