Help us shape the future of Go! Take the 2026 Go Developer Survey

fuu

command module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 25, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

README



GitHub Tag GitHub License GitHub Issues or Pull Requests

fuu

TPM-sealed secrets for your shell. One file, no server, no key material on disk.

fuu keeps a repository's secrets in one encrypted .fuu.toml and loads them into your shell as you move between directories. The file is meant to be committed and shared in public, like a sops file. Names and values stay sealed without the vault key, and that key is sealed to a TPM 2.0 chip, so a copied file is useless on any other machine.

Install

go install github.com/mizuchilabs/fuu@latest

Needs a TPM 2.0. Linux reads /dev/tpmrm0 and falls back to /dev/tpm0, Windows goes through TBS. There is no software fallback on purpose, the chip is the point.

Quick start

fuu init      # creates .fuu.toml, prints a recovery passphrase once
fuu set DATABASE_URL postgres://localhost/mydb
fuu set API_KEY s3cret

eval "$(fuu hook bash)"   # goes into your rc file, see Shells

Walk into the repository and the hook loads what it finds, direnv style:

fuu: loading ~/project/.fuu.toml
fuu: export +DATABASE_URL +API_KEY

Walk out and they are gone again:

fuu: unloading -DATABASE_URL -API_KEY
fuu run npm start   # one command, no shell integration at all

Keep the recovery passphrase somewhere safe. It is the only way to enroll another machine or to recover from a cleared TPM, and nobody can recover it for you. Commit .fuu.toml, the file holds no readable secrets.

Shells

shell add to your rc file
bash eval "$(fuu hook bash)"
zsh eval "$(fuu hook zsh)"
fish fuu hook fish | source

Guard the line if your rc file runs where fuu may not be installed:

command -v fuu >/dev/null 2>&1 && eval "$(fuu hook bash)"

How it fits together

The vault. One .fuu.toml per repository. fuu looks for the nearest one up to and including the git root, and never walks above it. Point --vault or FUU_VAULT at a file to override.

Trust. A vault only loads from a folder this machine has trusted to hold that vault key. fuu init and fuu trust trust the folder they run in. Everywhere else the first load is one fuu trust that asks for the recovery passphrase. There is no trust on first use, so a stranger's repository cannot hand you values or reach into yours.

Devices. A device is one machine's TPM. Each holds its own unexportable key, and the vault key is sealed to every enrolled device plus your recovery passphrase. A second machine clones, runs fuu trust once, and types the passphrase.

fuu device ls          # what is enrolled, this machine marked with *
fuu device rm <name>   # remove a device and rotate the vault key

Removing a device cuts it off from future values, not from what it already read. After a real leak, rotate the credentials at their issuers too.

Editing

fuu edit opens the vault in $VISUAL or $EDITOR as plain TOML and writes back only what changed when you save and close. The variable is a whitespace-separated command and its arguments, there is no shell and no quoting.

API_KEY = "s3cret"
DATABASE_URL = "postgres://localhost/mydb"

Change a line to change a value, add one to add a key, delete one to drop it. Comment a line out to disable a key instead. It stays sealed but never loads into a shell. Keys you leave alone keep their entries, so a git diff shows exactly which line changed. Nothing is written if the TOML is invalid or a name is not a valid shell variable name. Names that would configure the shell itself, PATH, PROMPT_COMMAND and about fifty others, are refused outright.

Store a value from stdin when it is long or starts with a dash:

fuu set CERT < cert.pem

A value typed straight onto the command line works too, but it then sits in the process list and your shell history. fuu says so when that happens.

Commands

command what it does
fuu init [--name] create a vault in this repository and enroll this machine
fuu trust [--name] trust this vault in this folder and enroll this machine
fuu set KEY [value] store a secret, reads stdin or prompts when omitted
fuu unset KEY delete a secret
fuu get KEY print one value
fuu ls list the keys in this vault
fuu edit edit this vault's secrets in your editor
fuu run <command> [args...] run a command with this vault's secrets in its env
fuu env print shell lines loading the vault for the current directory
fuu hook bash|zsh|fish the shell hook
fuu rotate replace the vault key and rewrap everything
fuu device ls|rm manage enrolled devices

Developing

go test ./...   # tests
task lint       # fmt, vet, govulncheck, tests, golangci-lint
task fuzz       # fuzz the untrusted parsers

Security

What the attack surface is, what fuu handles and what it accepts on purpose all live in SECURITY.md. It is the truth for anything crypto related.

License

Apache 2.0 License - see LICENSE for details

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
devkey
Package devkey is this machine's TPM-resident ECDH P-256 identity, derived fresh on every open and never persisted, with no software fallback.
Package devkey is this machine's TPM-resident ECDH P-256 identity, derived fresh on every open and never persisted, with no software fallback.
vault
Package vault is the on disk vault: one TOML file per repository, meant to be committed in public.
Package vault is the on disk vault: one TOML file per repository, meant to be committed in public.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL