{"id":48914526,"url":"https://github.com/afadesigns/envkeep","last_synced_at":"2026-04-17T01:11:22.875Z","repository":{"id":318339697,"uuid":"1061413964","full_name":"afadesigns/envkeep","owner":"afadesigns","description":"Typed environment specifications, drift detection, and CLI tooling for devs who rely on .env files. ","archived":false,"fork":false,"pushed_at":"2026-01-22T00:08:34.000Z","size":647,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-14T07:04:16.362Z","etag":null,"topics":["cli","env","security","toolkit","uv"],"latest_commit_sha":null,"homepage":"","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/afadesigns.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":"SUPPORT.md","governance":"GOVERNANCE.md","roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["rtx-labs"],"open_collective":"envkeep"}},"created_at":"2025-09-21T21:17:48.000Z","updated_at":"2025-11-25T16:57:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"607c52b4-9508-40e9-94fb-d6eb31a4b6d2","html_url":"https://github.com/afadesigns/envkeep","commit_stats":null,"previous_names":["afadesigns/envkeep"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/afadesigns/envkeep","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/afadesigns%2Fenvkeep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/afadesigns%2Fenvkeep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/afadesigns%2Fenvkeep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/afadesigns%2Fenvkeep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/afadesigns","download_url":"https://codeload.github.com/afadesigns/envkeep/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/afadesigns%2Fenvkeep/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31910618,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"ssl_error","status_checked_at":"2026-04-16T18:21:47.142Z","response_time":69,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cli","env","security","toolkit","uv"],"created_at":"2026-04-17T01:11:19.032Z","updated_at":"2026-04-17T01:11:22.861Z","avatar_url":"https://github.com/afadesigns.png","language":"Python","funding_links":["https://github.com/sponsors/rtx-labs","https://opencollective.com/envkeep"],"categories":[],"sub_categories":[],"readme":"# Envkeep\n\n[![CI](https://github.com/afadesigns/envkeep/actions/workflows/ci.yml/badge.svg)](https://github.com/afadesigns/envkeep/actions/workflows/ci.yml)\n[![Release](https://github.com/afadesigns/envkeep/actions/workflows/release.yml/badge.svg)](https://github.com/afadesigns/envkeep/actions/workflows/release.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Docs](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://afadesigns.github.io/envkeep)\n\nTyped environment specifications, drift detection, and CLI tooling for teams who rely on `.env` files. Envkeep keeps every environment stage aligned without adopting a heavyweight configuration framework.\n\n## Why Envkeep?\n- Typed guarantees with strict types, patterns, and enumerated choices defined once in `envkeep.toml`.\n- Drift detection that normalizes values before diffing and respects secret redaction.\n- Secrets hygiene that highlights undeclared variables and generates sanitized `.env.example` files.\n- Library and CLI parity so CI pipelines and local workflows share the same engine.\n- Cross-platform support validated on Linux, macOS, and Windows.\n\n## Demo\n```\n$ envkeep check examples/basic/.env.dev\nValidating examples/basic/.env.dev\nAll checks passed.\n\n$ envkeep diff examples/basic/.env.dev examples/basic/.env.prod\nDiffing examples/basic/.env.dev -\u003e examples/basic/.env.prod\nChanged\n┏━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓\n┃ Variable      ┃ Change  ┃ Left                ┃ Right           ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩\n│ ALLOWED_HOSTS │ CHANGED │ localhost,api.local │ app.example.com │\n│ API_TOKEN     │ CHANGED │ ***                 │ ***             │\n│ DATABASE_URL  │ CHANGED │ ***                 │ ***             │\n│ DEBUG         │ CHANGED │ true                │ false           │\n└───────────────┴─────────┴─────────────────────┴─────────────────┘\nChanged: 4 · Impacted: ALLOWED_HOSTS, API_TOKEN, DATABASE_URL\nTotal differences: 4\n\n$ envkeep generate --output .env.example\nWrote example to .env.example\n```\n\nTune the summary footprint with `--summary-top`: raise it to see more impacted variables or set it to `0` to hide the list entirely (available on `check`, `diff`, and `doctor`).\n\n## Quickstart\n1. Install: `pip install envkeep`\n2. Create `envkeep.toml`:\n   ```toml\n   version = 1\n\n   [[variables]]\n   name = \"DATABASE_URL\"\n   type = \"url\"\n   required = true\n   secret = true\n   description = \"Primary Postgres DSN\"\n   ```\n3. Validate: `envkeep check .env`\n4. Diff environments: `envkeep diff .env staging.env`\n5. Generate example: `envkeep generate --output .env.example`\n\nPipe specs directly from tooling with `--spec -` (for example, `cat envkeep.toml | envkeep check .env --spec -`) and explore metadata via `envkeep inspect --format json` when automating reviews.\n\nSee [`examples/basic`](examples/basic) for a complete spec and environment pair and [`examples/socialsense`](examples/socialsense) for a multi-profile demo with bundled `.env` fixtures.\n\n## Configuration\n\n`envkeep` can be configured via a `[tool.envkeep]` section in your `pyproject.toml` file. This is useful for setting project-wide defaults.\n\n-   `spec`: Path to the `envkeep.toml` spec file.\n-   `profile_base`: The base directory for resolving relative `env_file` paths in profiles.\n\n**Example `pyproject.toml`:**\n\n```toml\n[tool.envkeep]\nspec = \"config/envkeep.toml\"\nprofile_base = \"config/profiles\"\n```\n\nCommand-line options will always override settings in `pyproject.toml`.\n\n## Hierarchical Specs\n\n`envkeep` supports splitting your specifications across multiple files using the `imports` key. This allows you to create a base spec and extend it in other specs, promoting reuse and better organization.\n\n**Example `base.toml`:**\n\n```toml\n[[variables]]\nname = \"DATABASE_URL\"\ntype = \"url\"\nrequired = true\nsecret = true\n```\n\n**Example `envkeep.toml`:**\n\n```toml\nimports = [\"base.toml\"]\n\n[[variables]]\nname = \"API_KEY\"\nsecret = true\n```\n\nWhen you run `envkeep`, it will load `envkeep.toml`, see the `imports` key, and then load `base.toml`. The variables and profiles from `base.toml` will be merged into the main spec. If a variable or profile is defined in both the main spec and an imported spec, the definition in the main spec will take precedence.\n\n## Validation Rules\n\nIn addition to types, `envkeep` supports several other validation rules:\n\n-   `choices`: A list of allowed values for a variable.\n-   `pattern`: A regular expression that the variable's value must match.\n-   `min_length`: The minimum allowed length for a string variable.\n-   `max_length`: The maximum allowed length for a string variable.\n-   `min_value`: The minimum allowed value for an `int` or `float` variable.\n-   `max_value`: The maximum allowed value for an `int` or `float` variable.\n\n**Example `envkeep.toml`:**\n\n```toml\n[[variables]]\nname = \"LOG_LEVEL\"\nchoices = [\"debug\", \"info\", \"warning\", \"error\"]\n\n[[variables]]\nname = \"API_KEY\"\nmin_length = 32\nmax_length = 32\n\n[[variables]]\nname = \"PORT\"\ntype = \"int\"\nmin_value = 1024\nmax_value = 65535\n```\n\n## Shell Completion\n\n`envkeep` supports shell completion for Bash, Zsh, and Fish. To install, run the following command for your shell:\n\n**Bash:**\n```bash\nenvkeep --install-completion bash \u003e\u003e ~/.bashrc\n```\n\n**Zsh:**\n```bash\nenvkeep --install-completion zsh \u003e\u003e ~/.zshrc\n```\n\n**Fish:**\n```bash\nenvkeep --install-completion fish \u003e\u003e ~/.config/fish/completions/envkeep.fish\n```\n\nYou may need to restart your shell for the changes to take effect.\n\n## Features\n- Automatic `envkeep.toml` discovery by searching the current and parent directories.\n- Typed spec parsing with validation for defaults, patterns, and enumerated values.\n- Human-friendly and machine-readable reports (`--format text|json`).\n- Rich inspection tooling to summarize variables and profiles (`envkeep inspect`, JSON-ready output plus resolved profile paths).\n- Secrets-aware diffing that redacts sensitive values.\n- Robust `.env` parser that understands `export` syntax, quotes, escapes, and UTF-8 BOM-prefixed files.\n- Profiles support for multi-stage environments validated via `envkeep doctor`; relative profile paths resolve against the spec (override with `--profile-base`).\n- Configurable summaries that bound the \"top variables\" lists via `--summary-top` in `check`, `diff`, and `doctor`.\n- MkDocs-powered documentation with mkdocstrings API reference.\n- First-class CI workflows for linting, typing, testing, docs, and release automation.\n\n### Doctor\n\nThe `doctor` command validates profiles against the spec. You can check all profiles at once or target a specific one.\n\n**Check all profiles:**\n\n```bash\nenvkeep doctor\n```\n\n**Check a single profile:**\n\n```bash\nenvkeep doctor --profile staging\n```\n\n**Performance Caching:**\n\nTo improve performance, `envkeep` caches the results of `doctor` validations. If neither the `envkeep.toml` spec nor the profile's `.env` file has changed since the last run, `envkeep` will use the cached report instead of re-validating.\n\nTo bypass this cache and force a fresh validation, use the `--no-cache` flag:\n\n```bash\nenvkeep doctor --no-cache\n```\n\n### Diff\n\nThe `diff` command compares two environment files, using the spec to normalize values and identify meaningful differences. This is useful for comparing local changes against a deployed environment.\n\nYou can also get the output in JSON format by using the `--format json` flag. This is useful for programmatic analysis of the diff.\n\n## GitHub Action\n\nYou can use `envkeep` in your GitHub Actions workflows to automatically validate environment profiles on pull requests. Create a file named `.github/workflows/envkeep.yml` with the following content:\n\n```yaml\nname: Envkeep CI\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  validate-profiles:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: '3.11'\n      - name: Install envkeep\n        run: pip install envkeep\n      - name: Run envkeep doctor\n        run: envkeep doctor --fail-on-warnings\n**JSON Output:**\n\n```json\n{\n  \"report\": {\n    \"is_clean\": false,\n    \"by_kind\": {\n      \"missing\": 0,\n      \"extra\": 0,\n      \"changed\": 4\n    },\n    \"variables\": [\n      \"ALLOWED_HOSTS\",\n      \"API_TOKEN\",\n      \"DATABASE_URL\",\n      \"DEBUG\"\n    ],\n    \"top_variables\": [\n      [\n        \"ALLOWED_HOSTS\",\n        1\n      ],\n      [\n        \"API_TOKEN\",\n        1\n      ],\n      [\n        \"DATABASE_URL\",\n        1\n      ]\n    ],\n    \"entries\": [\n      {\n        \"variable\": \"ALLOWED_HOSTS\",\n        \"kind\": \"changed\",\n        \"left\": \"localhost,api.local\",\n        \"right\": \"app.example.com\"\n      },\n      {\n        \"variable\": \"API_TOKEN\",\n        \"kind\": \"changed\",\n        \"left\": \"***\",\n        \"right\": \"***\"\n      },\n      {\n        \"variable\": \"DATABASE_URL\",\n        \"kind\": \"changed\",\n        \"left\": \"***\",\n        \"right\": \"***\"\n      },\n      {\n        \"variable\": \"DEBUG\",\n        \"kind\": \"changed\",\n        \"left\": \"true\",\n        \"right\": \"false\"\n      }\n    ]\n  },\n  \"summary\": {\n    \"is_clean\": false,\n    \"by_kind\": {\n      \"missing\": 0,\n      \"extra\": 0,\n      \"changed\": 4\n    },\n    \"non_empty_kinds\": [\n      \"changed\"\n    ],\n    \"variables\": [\n      \"ALLOWED_HOSTS\",\n      \"API_TOKEN\",\n      \"DATABASE_URL\",\n      \"DEBUG\"\n    ],\n    \"top_variables\": [\n      [\n        \"ALLOWED_HOSTS\",\n        1\n      ],\n      [\n        \"API_TOKEN\",\n        1\n      ],\n      [\n        \"DATABASE_URL\",\n        1\n      ]\n    ]\n  }\n}\n```\n\n## Architecture\n- `envkeep.toml` defines variables, metadata, and environment profiles.\n- The core library normalizes values, produces validation reports, and renders diffs.\n- The Typer CLI wraps the library for local and CI usage.\n- Tests (pytest plus pytest-benchmark) protect correctness and performance targets.\n\n## Roadmap Highlights\n- Remote secret backends (Vault, AWS SSM) as optional providers.\n- IDE integrations for inline validation while editing `.env` files.\n- GitHub and GitLab Actions wrappers to enforce Envkeep in CI.\nSee [ROADMAP.md](ROADMAP.md) for the full backlog.\n\n## Plugin System\nEnvkeep supports a plugin system for fetching variables from remote backends like cloud secret managers or configuration servers.\n\n### AWS Secrets Manager\n\nTo use the AWS Secrets Manager backend, first install the necessary dependencies:\n\n```bash\npip install envkeep[aws]\n```\n\nThen, in your `envkeep.toml`, add a `source` attribute to any variable you want to fetch from Secrets Manager. The source format is `aws-sm:\u003csecret-id\u003e`, where `\u003csecret-id\u003e` is the name or ARN of the secret.\n\n```toml\n[[variables]]\nname = \"DATABASE_URL\"\ntype = \"url\"\nsecret = true\nsource = \"aws-sm:prod/database/url\" # Fetched via the 'aws-sm' backend\n```\n\n### HashiCorp Vault\n\nTo use the HashiCorp Vault backend, first install the necessary dependencies:\n\n```bash\npip install envkeep[vault]\n```\n\nThe Vault backend authenticates using the `VAULT_ADDR` and `VAULT_TOKEN` environment variables. Make sure these are set in your environment before running `envkeep`.\n\nIn your `envkeep.toml`, add a `source` attribute with the format `vault:\u003cmount-point\u003e/\u003csecret-path\u003e`. This backend assumes you are using a KVv2 secrets engine.\n\n```toml\n[[variables]]\nname = \"API_KEY\"\nsecret = true\nsource = \"vault:kv/data/api-keys\" # Fetched via the 'vault' backend\n```\n\n### Google Cloud Secret Manager\n\nTo use the Google Cloud Secret Manager backend, first install the necessary dependencies:\n\n```bash\npip install envkeep[gcp]\n```\n\nThe backend authenticates using the standard Google Cloud authentication methods (e.g., `gcloud auth application-default login`).\n\nIn your `envkeep.toml`, add a `source` attribute with the format `gcp-sm:\u003cresource-id\u003e`, where `\u003cresource-id\u003e` is the full resource name of the secret version.\n\n```toml\n[[variables]]\nname = \"GOOGLE_API_KEY\"\nsecret = true\nsource = \"gcp-sm:projects/my-project/secrets/my-api-key/versions/latest\" # Fetched via the 'gcp-sm' backend\n```\n\nWhen you run `envkeep check`, the tool will automatically discover and invoke the plugin. Remotely fetched values take precedence over values in the local `.env` file.\n\nSee the [plugin development guide](docs/plugins.md) for details on creating your own backends.\n\n## FAQ\n**Is Envkeep a secret manager?** No. Envkeep verifies configuration contracts; storage and rotation stay with your existing tooling.\n\n**Can I load from `os.environ` instead of files?** Yes, use `EnvSnapshot.from_process()`.\n\n**Does Envkeep support YAML specs?** Not yet. TOML keeps dependencies minimal in v1.0.\n\n**Will it slow down CI?** Validation of 500 variables completes in under 120 ms on a 2022 developer laptop (benchmarked via `pytest --benchmark-only`).\n\n## Contributing\n1. Fork and clone the repository.\n2. Run `make install` to install development dependencies.\n3. Use `make lint`, `make typecheck`, and `make test` before submitting a pull request.\n4. Review [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).\n\n## Launch and Growth Plan\n- Launch Day: publish v1.0.0 on PyPI, post to r/Python, Hacker News (Show HN), Dev.to, and LinkedIn with demo clips.\n- Discoverability: add GitHub topics (`dotenv`, `configuration`, `devops`, `sre`, `python`, `security`, `cli`, `typed-settings`, `ci`, `workflow`).\n- Community: seed “good first issue” tasks (spec lint rules, editor integrations) and open GitHub Discussions for Q\u0026A.\n- Credibility: publish benchmarks, migration guide, and testimonials from early adopters in docs.\n\n## Support\nNeed help or commercial support? Check [SUPPORT.md](SUPPORT.md) or open a GitHub Discussion.\n\n## License\nEnvkeep is available under the [MIT License](LICENSE).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fafadesigns%2Fenvkeep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fafadesigns%2Fenvkeep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fafadesigns%2Fenvkeep/lists"}