rivit is a small, opinionated CLI for managing local development workspaces.
It keeps track of which Git repositories belong to each workspace, where they should live on disk, and how repo-local .env files are managed as SOPS-encrypted secrets.
At a high level, rivit helps you:
- catalog repositories into named workspaces
- validate local drift against your config
- hydrate local state (directories, clones, secrets)
- absorb local
.envupdates back into encrypted secret files
This project is intentionally focused and is not intended to replace Git, task runners, or general environment management tools.
Install the latest CLI directly from this repo:
go install github.com/jonsampson/rivit/cmd/rivit@latestThen verify:
rivit --helprivit assumes these tools are available in your environment:
git(discover and clone repositories)sops(encrypt/decrypt secret files)
For SOPS with age recipients, ensure your age key setup is already working in your shell/session.
rivit uses SOPS for all secret encryption/decryption:
scancan auto-absorb.envfiles found in discovered repositorieshydratedecrypts stored secrets back to local.envabsorbencrypts local.envfiles from managed workspace checkouts into your secret store
Before using scan/hydrate/absorb, ensure SOPS works in your shell with your chosen recipients/key material.
Important: today, scan is the only command that can auto-absorb .env files from repositories outside the workspace checkout layout.
rivit initThis creates ~/.config/rivit/config.yaml and the base config directory ~/.config/rivit/.
Create ~/.config/rivit/.sops.yaml:
creation_rules:
- path_regex: secrets/.*\.env\.sops$
age: >-
age1examplepublickeyreplacewithyourownrecipientReplace the age recipient with your own public key/recipient(s).
Why this matters: rivit writes encrypted files under ~/.config/rivit/secrets/.... If the creation rule does not match, encryption operations fail with errors like no matching creation rules found.
This rule should match files under the default secrets directory (~/.config/rivit/secrets).
rivit workspace add personal ~/Coderivit scan ~/dev --workspace personalWhat scan does:
- finds Git repos under
~/dev - adds discovered remotes to workspace config
- if a discovered repo contains a local
.env, attempts to absorb it into~/.config/rivit/secrets/...env.sops
List repositories now tracked by rivit:
rivit repo listInspect the generated config:
cat ~/.config/rivit/config.yamlYou should see entries like:
version: 1
workspaces:
"personal":
path: /home/you/Code
repos:
- url: git@github.com:you/project.git
secret:
source: github.com/you/project/.env.sops
target: .env
secrets:
provider: sops
path: /home/you/.config/rivit/secretsAnd on disk you should see encrypted secret files under:
~/.config/rivit/secrets/Repository checkout paths are derived from logical repository identity, not the exact clone transport. HTTPS, SCP-style SSH, and ssh:// URLs for the same host/path hydrate to the same workspace path; user, scheme, and port are ignored for layout. Generated secret sources use {repo-id}/{target}.sops, such as github.com/you/project/.env.sops.
# validate local drift
rivit validate
# materialize local state (directories, clones, secrets)
rivit hydrate personal
# absorb local .env changes back into encrypted secrets
rivit absorb personalTip: use --config to keep experiments isolated:
rivit --config /tmp/rivit.yaml init- Rivit does not inspect or merge individual environment variables.
.envhandling is whole-file only.validateis read-only.hydrate --dry-runandabsorb --dry-runshow intended changes.absorbrequires confirmation unless--yesis passed.- Secrets are encrypted through SOPS; Rivit shells out to
sops.
| Command | Purpose |
|---|---|
rivit init |
Create the config and initialize secrets settings |
rivit workspace add <name> <path> |
Register a workspace |
rivit workspace list |
List workspaces |
rivit workspace remove <name> |
Remove a workspace |
rivit repo add <url> --workspace <name> |
Add a repo to a workspace |
rivit repo list |
List registered repos |
rivit repo remove <repo-url> |
Remove a repo by URL |
rivit validate [target] |
Check local drift |
rivit hydrate [target] [--dry-run] [--repos-only] [--secrets-only] [--force-env] |
Create dirs, clone repos, decrypt env files |
rivit absorb [target] [--dry-run] [--yes] |
Encrypt local .env files back into secrets |
rivit scan <path> --workspace <name> [--dry-run] |
Discover repos and add/absorb them |