{"id":50989136,"url":"https://github.com/jackofshadowz/envkeep","last_synced_at":"2026-07-07T22:00:47.405Z","repository":{"id":365063546,"uuid":"1270348402","full_name":"jackofshadowz/envkeep","owner":"jackofshadowz","description":"Secure, age-encrypted ENV-secret manager with a native macOS GUI and a CLI built for AI coding agents.","archived":false,"fork":false,"pushed_at":"2026-07-02T12:17:14.000Z","size":3137,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-02T14:17:04.124Z","etag":null,"topics":["age-encryption","cli","developer-tools","env","macos","secrets-management"],"latest_commit_sha":null,"homepage":"https://jackofshadowz.github.io/envkeep/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jackofshadowz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-15T16:15:42.000Z","updated_at":"2026-07-02T12:17:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jackofshadowz/envkeep","commit_stats":null,"previous_names":["jackofshadowz/envkeep"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jackofshadowz/envkeep","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackofshadowz%2Fenvkeep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackofshadowz%2Fenvkeep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackofshadowz%2Fenvkeep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackofshadowz%2Fenvkeep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jackofshadowz","download_url":"https://codeload.github.com/jackofshadowz/envkeep/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackofshadowz%2Fenvkeep/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35243953,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["age-encryption","cli","developer-tools","env","macos","secrets-management"],"created_at":"2026-06-20T00:00:28.873Z","updated_at":"2026-07-07T22:00:47.379Z","avatar_url":"https://github.com/jackofshadowz.png","language":"Python","funding_links":["https://buymeacoffee.com/jackcodes"],"categories":["Security"],"sub_categories":["Text"],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"app/icon.png\" width=\"116\" alt=\"Envkeep logo\" /\u003e\n\n# Envkeep\n\n**A secure, age-encrypted home for your team's ENV secrets — a native macOS app for humans, a CLI for your AI coding agents.**\n\n[![CI](https://github.com/jackofshadowz/envkeep/actions/workflows/ci.yml/badge.svg)](https://github.com/jackofshadowz/envkeep/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-7fee64.svg)](LICENSE)\n![Platform: macOS](https://img.shields.io/badge/platform-macOS-1b1b1f.svg)\n![Encryption: age](https://img.shields.io/badge/encryption-age-16341d.svg)\n![pip deps: 0](https://img.shields.io/badge/pip%20deps-0-2ea043.svg)\n![PRs welcome](https://img.shields.io/badge/PRs-welcome-7fee64.svg)\n[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-%E2%98%95-ffdd00.svg)](https://buymeacoffee.com/jackcodes)\n\n\u003cbr/\u003e\n\n\u003cimg src=\"docs/screenshot.png\" width=\"840\" alt=\"Envkeep app\" /\u003e\n\n\u003c/div\u003e\n\n---\n\nSo you can just tell your coding agent:\n\n\u003e *\"the OpenAI key is in **envkeep** — grab `my-app/OPENAI_API_KEY`.\"*\n\n…and it runs `envkeep get my-app/OPENAI_API_KEY`, pulling exactly one value on demand. No secret pasted into chat, no `.env` lying around, nothing in plaintext at rest.\n\n**Use it with your AI agent:** [Claude Code](docs/guides/claude-code.md) · [Cursor](docs/guides/cursor.md) · [aider](docs/guides/aider.md)\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"docs/demo.gif\" width=\"760\" alt=\"Envkeep CLI demo: get one value, load a project, notes \u0026 fields, audit log\" /\u003e\n\u003c/div\u003e\n\n## ✨ Features\n\n| | |\n|---|---|\n| 🔐 **Encrypted at rest** | An [age](https://github.com/FiloSottile/age)-encrypted `vault.age` — only ciphertext ever hits disk or git. |\n| 🖥️ **Native macOS app** | A real Swift / WKWebView window (not a browser tab) with its own Dock icon and menus. |\n| ⌨️ **CLI for agents** | `envkeep get NAME` prints one value; `envkeep env project` loads a whole project. |\n| 🗂️ **Projects \u0026 folders** | Organise secrets as `project/KEY`; the GUI groups them, the CLI dumps them. |\n| 🏷️ **Tags** | Label secrets (`prod`, `db`, …) across projects; filter by tag in the app or `envkeep list --tag prod`. |\n| 🧭 **Command palette** | ⌘K to jump to any project, secret, or action. Plus `n`, `/`, `l` shortcuts. |\n| ⛔ **Decrypt-on-demand** | No plaintext cache by default; optional Keychain cache + one-click **Lock**. |\n| 📥 **Import** | `envkeep import ./my-app` scans `.env` files and pulls them in (dry-run first). |\n| 📜 **Audit log** | Every read/write is logged — names only, never values. |\n| 👥 **Team-ready** | Share the encrypted vault via a private git repo; add members by public key. |\n| 🪶 **Zero dependencies** | Pure Python 3 stdlib + `age`. No pip, no server, no database. |\n\n## 🚀 Quickstart\n\n**Homebrew (recommended):**\n\n```bash\nbrew install jackofshadowz/tap/envkeep\nenvkeep init          # creates your key, vault, and recipients entry\n```\n\n**curl one-liner:**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/jackofshadowz/envkeep/main/web-install.sh | bash\nenvkeep init\n```\n\n**pipx / pip** (Python tool):\n\n```bash\npipx install envkeep        # or: pip install envkeep\nenvkeep init\n```\n\n**From source** (also builds the native app):\n\n```bash\ngit clone https://github.com/jackofshadowz/envkeep.git\ncd envkeep\n./install.sh          # symlinks `envkeep` onto your PATH, installs age via brew\nenvkeep init\n./build-app.sh \u0026\u0026 open Envkeep.app    # optional native macOS app\n```\n\n\u003e Prefer the app? Download `Envkeep.app` from the\n\u003e [latest release](https://github.com/jackofshadowz/envkeep/releases/latest).\n\nAdd a secret, then read it in a coding session:\n\n```bash\nenvkeep set my-app/OPENAI_API_KEY      # hidden prompt; or pass inline\nenvkeep get my-app/OPENAI_API_KEY      # prints just the value\neval \"$(envkeep env my-app)\"           # load the whole project into your shell\n```\n\n## 🧠 How it works\n\n```\n   GUI  (you)                          CLI  (Claude / coding sessions)\n   Envkeep.app                         envkeep get my-app/OPENAI_API_KEY\n        │                                        │\n        ▼                                        ▼\n  ┌────────────────┐                   ┌───────────────────────┐\n  │   vault.age    │   age-encrypted   │  decrypts ONE value   │\n  │  (source of    │ ◀───────────────▶ │  on demand — nothing  │\n  │  truth, in a   │   to each member  │  persisted in plain   │\n  │  private repo) │                   └───────────────────────┘\n  └────────────────┘\n```\n\n* **Source of truth** — `vault.age`, encrypted to every teammate's age public key (`recipients.txt`). The git host only ever sees ciphertext.\n* **Your private key** lives at `~/.config/envkeep/identity.txt` (`chmod 600`), never committed.\n* **Reads decrypt on demand.** Enable a Keychain cache for speed (`envkeep config cache keychain`); `envkeep lock` purges it.\n\n## 🛠️ CLI reference\n\n```bash\nenvkeep set  my-app/STRIPE_KEY [value]   # add / update (hidden prompt if omitted)\nenvkeep get  my-app/STRIPE_KEY           # print one value\nenvkeep list [project] [--tag prod]      # names only (filter by tag, repeatable)\nenvkeep folders                          # list projects\nenvkeep env  my-app [--dotenv]           # export lines (or .env format)\nenvkeep import ./path [--apply]          # scan .env files (dry-run by default)\nenvkeep rm   my-app/STRIPE_KEY\n\n# metadata (stored with the secret, never injected by `env`)\nenvkeep note  my-app/STRIPE_KEY [text]   # show / set / --clear a note\nenvkeep field my-app/LOGIN [KEY=VAL]     # extra fields (USERNAME, URL, …)\nenvkeep tag   my-app/STRIPE_KEY prod db  # add tags (--rm x, --clear, omit to list)\nenvkeep tags                             # every tag in the vault, with counts\nenvkeep pubkey | members | add-member alice age1…\nenvkeep remove-member alice              # revoke a member + re-encrypt\nenvkeep rotate-identity                  # new vault key + re-encrypt (key rotation)\nenvkeep gui                              # the same UI in your browser\n\n# security\nenvkeep protect-key      # encrypt the vault key with a passphrase\nenvkeep unlock           # unlock the passphrase-protected key for this session\nenvkeep lock             # re-lock the key / 2FA + purge cached plaintext\nenvkeep unprotect-key    # remove passphrase protection\nenvkeep config           # view settings\nenvkeep config cache keychain|none       # plaintext cache vs decrypt-on-demand\nenvkeep config autolock \u003cminutes\u003e        # auto-relock window (cache mode)\nenvkeep config touchid on|off            # Touch ID gate (app)\nenvkeep config log on|off                # access log\nenvkeep log [--tail N]                   # show the access log\n```\n\nGUI shortcuts: **⌘K** palette · **n** new · **/** search · **l** lock · **Esc** close · **⌘↵** save.\n\n## 👥 Sharing with a team\n\n1. A teammate runs `envkeep init` and sends you `envkeep pubkey` → `age1…`.\n2. You run `envkeep add-member alice age1…` (re-encrypts the vault for everyone).\n3. They point their vault dir at the shared private repo. `envkeep members` lists access.\n\n**Revoking \u0026 rotating:** `envkeep remove-member alice` (or the × in Settings → Team)\nre-encrypts the vault for everyone who remains. `envkeep rotate-identity` issues you a\nbrand-new key and re-encrypts — use it if your key may be exposed. After either, rotate\nthe secret *values* a departed member knew.\n\n## 🔒 Security\n\nEnvkeep is layered — turn on as much as you need. Configure it all in **Settings**\n(GUI) or via `envkeep config` / the commands above.\n\n### Security levels\nOne-click presets in Settings:\n\n| Level | Storage | Gate |\n|---|---|---|\n| **Relaxed** | Keychain cache (fast) | none |\n| **Balanced** | decrypt-on-demand | Touch ID |\n| **Strict** | decrypt-on-demand | Touch ID + short auto-relock (add 2FA for max) |\n\n### Storage modes\n- **Decrypt-on-demand** (default) — no plaintext is persisted anywhere; every read decrypts the vault.\n- **Keychain cache** (`envkeep config cache keychain`) — decrypted values cached in the macOS Keychain for speed, purged by **auto-lock** (`config autolock \u003cmin\u003e`) or `envkeep lock`.\n\n### Gates (protect reveal/copy in the app)\n- **Touch ID** (`config touchid on`) — biometric/password before a value is shown or copied.\n- **Two-factor / TOTP** — a 6-digit code from **Authy, Google Authenticator, or 1Password**. Enroll in Settings → Two-factor; reveals are then gated until you enter a code.\n- **Auto-relock** — Touch ID and 2FA sessions expire after the configured window, then re-prompt.\n- **Lock** (`envkeep lock`, or the app button) — immediately re-locks every enabled gate + purges the cache. With **no** gate enabled it only purges the cache (the app warns you).\n\n### At-rest key protection\n- **Passphrase-encrypted key** (`envkeep protect-key`, or Settings → Vault key encryption) — encrypts your age identity itself (openssl AES-256 + PBKDF2). The plaintext key file is removed, so a **stolen key file is useless**. Unlock once per session (`envkeep unlock` or the app's unlock screen). ⚠ No recovery if you forget the passphrase.\n\n### Other\n- **Clipboard auto-clear** — copied secret *values* are wiped from the pasteboard ~45s later (native app).\n- **Audit log** — every read/write is appended to `~/.config/envkeep/access.log` (names + actions, **never values**).\n\n### Honest caveats\n- Only **ciphertext** is ever stored or pushed — a stolen repo / laptop-at-rest exposes nothing.\n- **The CLI runs as you**, so a coding agent you trust to run commands can read any secret it's pointed at. Prefer handing it the *name* (or `envkeep env`) and injecting via the environment rather than printing values into a transcript.\n- The Touch ID / 2FA gates protect the **app reveal path**; they don't gate the CLI (agents need it). For true at-rest protection of the key, use **passphrase encryption**.\n- Removing a member re-encrypts going forward — **rotate** anything they knew.\n- Back up your key/passphrase (e.g. a password manager); lose them and you lose access.\n- Lightweight by design — **not** a replacement for HashiCorp Vault / an HSM.\n\n## 📦 Requirements\n\nmacOS · `age` + `age-keygen` (`brew install age`) · Python 3 (system Python is fine) · `openssl` (ships with macOS; used for passphrase key encryption) · Xcode CLT (`swiftc`) for the native app.\n\n## ☕ Support\n\nIf Envkeep saves you from leaking another API key, you can\n[buy me a coffee](https://buymeacoffee.com/jackcodes).\n\n## 📄 License\n\n[MIT](LICENSE) © 2026 Jack Baum\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackofshadowz%2Fenvkeep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjackofshadowz%2Fenvkeep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackofshadowz%2Fenvkeep/lists"}