Skip to main content

Encrypted secrets, no infrastructure, no plaintext on disk.

Project description

notenv

CI Release Docs Go Reference Go Report Card License

Encrypted secrets, no infrastructure, no plaintext on disk.

notenv replaces .env files: secrets are encrypted on your machine with age, kept as ciphertext in a local vault or on storage you already own (Backblaze B2, S3, Google Drive, SFTP, WebDAV, anything rclone speaks), and decrypted only into the environment of the command you run. Plaintext never touches disk.

Why

A .env file is plaintext: everything on your machine can read it, and sharing it means pasting it somewhere it will outlive. notenv removes the file instead of guarding it.

  • Nothing on disk to leak. A test runner, a package's postinstall script, or a coding agent in your checkout cannot read a secret that exists only inside the process you ran, only while it runs.
  • You hold the key, not a provider. Secrets are age-encrypted locally; storage only ever sees ciphertext, so it can live anywhere: a local vault, the NAS under your desk, B2, S3, Drive, dozens more.
  • Nothing to operate. No server, no SaaS, no cloud account to stand up and babysit. notenv setup is one passphrase and zero accounts.
  • Joining and leaving are one command. Onboard a teammate with a string over chat; their first run swaps it for a credential only they know. Offboarding re-encrypts everything, so leaving actually revokes.
  • Built for AI agents. notenv run lets a process use a secret without seeing it, and captured output is masked, so an agent runs your commands without a value ever entering its context.

Not this if you want a platform: there is no web console or SSO, and access is scoped per vault, not per secret (everyone in a vault can read that vault). If a platform team already runs Vault, keep Vault.

Install

uv tool install notenv                                  # also: pipx install notenv, or pip
go install github.com/DvGils/notenv/cmd/notenv@latest   # with Go

Or download a prebuilt binary for Linux, macOS, or Windows (amd64 / arm64) from Releases and put notenv on your PATH. Releases are reproducible, signed with cosign (keyless), and carry SLSA build provenance; the installation guide shows how to verify a download.

Quick start

notenv setup                   # 1. set up this machine once (local vault by default)
cd my-project && notenv init   # 2. declare the project (writes notenv.toml, which you commit)
notenv import .env && rm .env  # 3. import existing secrets (or `notenv set KEY` one at a time)
notenv run -- npm run dev      # 4. run anything with the secrets injected

That is the whole loop. notenv is a process wrapper, so it works with any language that reads environment variables. On a new machine: git clone, then notenv setup with your escrowed passphrase, and you are ready. When syncing across machines starts to matter, notenv vault copy moves the same vault to a cloud remote in one command.

Documentation

Full docs live at dvgils.github.io/notenv:

How it works

notenv run -- cmd
  |
  |-- fetch ciphertext   <- rclone <-  your B2 / S3 / Drive / ...
  |-- unlock the master key (from your passphrase; cached after first use)
  |-- decrypt secrets in memory
  |-- build the child environment from notenv.toml
  |-- exec cmd, stream its I/O, exit with its code
        nothing written to disk

A random master key encrypts every secret and never exists in plaintext at rest: a small header holds it wrapped under one or more key slots (a person's passphrase or a machine's age public key), the way LUKS and restic do it. The header is authenticated and version-pinned, so a party who can write your storage but holds no key cannot tamper with it or roll it back undetected. Full detail in Concepts.

For AI agents

A .env on disk eventually lands in a coding agent's context. notenv gives the agent a verb that separates using a credential from knowing it:

  • notenv run -- cmd injects secrets into the child only; the value never appears in what the model reads, and captured output is masked.
  • notenv list shows which secrets exist and what they are for, never their values.

For a scoped session, notenv handoff -- <agent> runs the agent against an ephemeral vault holding only one namespace, so it never holds the key to the rest of your vault. An installable agent skill (skills/notenv/) teaches it the commands. See the AI agents guide.

How it compares

SOPS + age nail client-side encryption and process injection but leave storage and onboarding to you; Teller brokers cloud secret managers, where the provider holds your secrets. notenv is client-side encryption with the storage and the onboarding built in, and no provider in the loop.

notenv teller SOPS + age (DIY)
Plaintext on disk never never never
You hold the key yes no (provider does) yes
Storage backends local vault or any rclone remote per-provider code you wire it up
Infrastructure to run none none (uses your cloud) none
One-command onboarding yes partial no

Security

At rest, anywhere, only age ciphertext exists; it is useless without your key, which lives in your password manager and never on the storage backend. The threat model covers what notenv defends, against whom, and the explicit non-goals. To report a vulnerability, see SECURITY.md.

Building from source

git clone https://github.com/DvGils/notenv
cd notenv
make build       # compile ./notenv
make test        # run the test suite
make install     # install into $(go env GOPATH)/bin

Releases are produced with GoReleaser; make snapshot builds the full set of release artifacts locally without publishing.

Status

Actively developed and being tested. See the roadmap for what works today, what is planned, and the non-goals.

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

notenv-0.19.1-py3-none-win_arm64.whl (2.3 MB view details)

Uploaded Python 3Windows ARM64

notenv-0.19.1-py3-none-win_amd64.whl (2.6 MB view details)

Uploaded Python 3Windows x86-64

notenv-0.19.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl (2.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64musllinux: musl 1.1+ x86-64

notenv-0.19.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl (2.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64musllinux: musl 1.1+ ARM64

notenv-0.19.1-py3-none-macosx_11_0_arm64.whl (2.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

notenv-0.19.1-py3-none-macosx_10_12_x86_64.whl (2.6 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file notenv-0.19.1-py3-none-win_arm64.whl.

File metadata

  • Download URL: notenv-0.19.1-py3-none-win_arm64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for notenv-0.19.1-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 06c8e09fd03936bc89337d375e26c9a936ccf0976b35dd179782a3b9c7da263d
MD5 baab0985784715168319bdc35d3a8b9a
BLAKE2b-256 2f3bd3acbab865119610668b0152640c95bb97053d280fdcca5083e74ae6545d

See more details on using hashes here.

Provenance

The following attestation bundles were made for notenv-0.19.1-py3-none-win_arm64.whl:

Publisher: release.yml on DvGils/notenv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file notenv-0.19.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: notenv-0.19.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for notenv-0.19.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 a578c8c9fc6e224a0520e8a099b31bd82501571b421976d299b1f0d2d278512c
MD5 88fba019710778a3f46bae7a57ac4699
BLAKE2b-256 dc3c45d890b9861b99c2fc77a469ba731306b35beabefc472e8723c89e7ad98b

See more details on using hashes here.

Provenance

The following attestation bundles were made for notenv-0.19.1-py3-none-win_amd64.whl:

Publisher: release.yml on DvGils/notenv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file notenv-0.19.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for notenv-0.19.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 624c27198d4d3da7e1ca80c145d0e23f86a372966f5b948d1dade0dd9ad667e9
MD5 1b51c48aeb1200c66c2d98dcb8037ce0
BLAKE2b-256 948fd26fb48580b7362506b560b63890d1ba71e2aca5c15550ad5914b3db2c12

See more details on using hashes here.

Provenance

The following attestation bundles were made for notenv-0.19.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_1_x86_64.whl:

Publisher: release.yml on DvGils/notenv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file notenv-0.19.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for notenv-0.19.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 cb2faa07334fbe82c4841aae3a198218bbf0afd6904032afeebbf8237d2cd129
MD5 0f7587bf12b8a9d74f40724e4eade0ae
BLAKE2b-256 d4377a686a44e8f256e2091db48ac6111a1adcc1fb4c4e2a7e5d6c3bab1cd963

See more details on using hashes here.

Provenance

The following attestation bundles were made for notenv-0.19.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl:

Publisher: release.yml on DvGils/notenv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file notenv-0.19.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for notenv-0.19.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 102ac92fcfd48999bb0de8b0b68fa56c8c274e868f39d5c06c64bfcbf432e096
MD5 109bd8b71826e8b8ecbc647186f85afd
BLAKE2b-256 9eecad5d7707f847a0f46e12334c0b8d904ab67b5be08980e558026ae23e4b5b

See more details on using hashes here.

Provenance

The following attestation bundles were made for notenv-0.19.1-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on DvGils/notenv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file notenv-0.19.1-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for notenv-0.19.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c7c6142ce0801323c0cd5a85aa5e548cb160a967e5623ee3ab8a21065be67076
MD5 e50179ae029c30e7aa174948fbead113
BLAKE2b-256 2c9316f452fad0c95441b2bdbf76d8d511ab921766a781f70236afd4d351dc18

See more details on using hashes here.

Provenance

The following attestation bundles were made for notenv-0.19.1-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on DvGils/notenv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page