Skip to content
Conduit

skill

envguard

Environment-variable audit CLI with Supabase Edge Functions support

Tresnanda/envguardcommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/Tresnanda/envguard itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 25, 2026

envguard

Environment-variable audits for Python, JavaScript, shell, PowerShell, and Supabase Edge Function projects.

envguard scans a codebase for environment variable references, compares those references with .env.example, and can optionally include Supabase Edge Function secrets in the same audit. It helps catch stale config, missing deployment secrets, and undocumented variables before they become production incidents.

Why Use It

Environment variables tend to drift as projects grow. Old keys stay in example files, new keys are added directly to code, and serverless secrets can linger after features are removed. envguard gives you a fast local check that is easy to run before deploys or in CI.

It reports six classes of findings:

IssueMeaning
UNUSEDA key exists in .env.example but is not referenced in the scanned code.
MISSINGA required key is referenced in code but is not present in .env.example or fetched Supabase secrets. This is blocking by default.
OPTIONALA defaulted/guarded key is absent from config. This is advisory and does not fail CI.
EXTERNALA key appears to belong to another runtime/container, such as an embedded script executed over SSH. This is advisory and does not fail CI.
IGNOREDA missing key was explicitly ignored by project config or CLI flags.
ORPHANEDA Supabase secret exists but is not referenced in code or documented in .env.example.

Installation

Requires Python 3.9 or newer.

macOS/Linux:

curl -fsSL https://raw.githubusercontent.com/Tresnanda/envguard/main/install.sh | bash

Windows PowerShell:

irm https://raw.githubusercontent.com/Tresnanda/envguard/main/install.ps1 | iex

For unattended installs, pass --yes:

curl -fsSL https://raw.githubusercontent.com/Tresnanda/envguard/main/install.sh | bash -s -- --yes

The installer uses pipx, checks Python and optional Supabase tooling, then offers a simple numbered Supabase token setup. If you paste SUPABASE_ACCESS_TOKEN during install, it is saved to your user shell environment, not to project config. It may ask whether to star the GitHub repo, defaulting to yes; if it cannot star from the terminal, it prints the repo link instead. After install, run envguard in your terminal to start the guided audit. The wizard checks for a newer GitHub version and asks before updating.

Manual install:

pipx install .

For local development:

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Quick Start

Run the audit from the root of a project that contains .env.example:

envguard

On an interactive terminal, the bare command opens a guided command builder. It detects dotenv files including .env.example and real .env, Supabase Edge Function projects, and existing project config, then shows the generated command before running it. To force the immediate current-directory scan, use:

envguard --no-wizard

You can also open the guide explicitly:

envguard wizard

Update to the latest GitHub version at any time:

envguard update

Agent Skill

envguard includes an optional agent skill for Codex and other agents that use the open Skills CLI. The skill teaches agents to run envguard before changing environment files, deployment config, Supabase Edge Functions, or CI secrets, and to report findings without exposing secret values.

Install the skill:

npx skills add Tresnanda/envguard --skill envguard

Install globally for all projects:

npx skills add Tresnanda/envguard --skill envguard -g

List the skill without installing:

npx skills add Tresnanda/envguard -l

Scan another directory:

envguard /path/to/project

Emit machine-readable JSON:

envguard --json

Emit a compact one-line terminal summary for chat or CI step summaries:

envguard --summary
# envguard: red — 2 missing, 1 unused, 3 optional (exit 1)

Inspect secret readiness across dotenv, the current shell environment, and Supabase secret names without printing any values:

envguard doctor
envguard matrix apps/web --json

The doctor/matrix command is opt-in and reports one row per referenced key with its requirement class (required, optional, external, or ignored), whether the key name is present in the selected dotenv file, the current process environment, and fetched Supabase secrets, plus a readiness status. It never prints dotenv values, shell environment values, Supabase token values, or Supabase secret values. It exits non-zero when a required key is missing from all checked sources unless --allow-missing is used.

Map provider ownership for referenced key names without fetching or printing secret values:

envguard ownership
envguard owners apps/web --json

The ownership map shows each key name, its inferred owner, where it should live, where the key name was observed, and orphaned-looking names. It recognizes source/owner contexts such as Supabase Edge Function secrets, GitHub Actions secrets.KEY references, Vercel/Netlify/Cloudflare project config, dotenv templates, the current process environment, and well-known runtime built-ins like GITHUB_*, VERCEL_*, NETLIFY, and CF_PAGES_*. Provider CLIs are not queried for values; Supabase remote names are included only through the same opt-in/auto-safe secret-name checks used by doctor.

Print a proposal-only remediation plan for missing or orphaned secret findings:

envguard plan
envguard doctor --plan apps/web

Plan mode builds on the doctor matrix and emits redacted, copy-pasteable next steps such as adding empty placeholders to .env.example, setting a Supabase secret placeholder, marking a key optional/external, or reviewing an orphaned Supabase secret. It is dry by default: no prompts, backups, dotenv writes, or secret writes are performed, and real dotenv values or shell/Supabase secret values are never printed.

Create a baseline for existing drift, then fail only on new findings:

envguard --write-baseline .envguard-baseline.json
envguard --baseline .envguard-baseline.json

Emit GitHub Actions annotations in CI logs:

envguard ci

Generate a copy-pasteable GitHub Actions workflow without writing files:

envguard ci-template
envguard ci-template apps/web

The generator reuses [tool.envguard] defaults, prefers committed dotenv templates such as .env.example, avoids referencing a real .env by default, and prints only secret names or GitHub secret placeholders — never dotenv values.

Use a custom dotenv file:

envguard --dotenv config/example.env

Exclude generated or noisy paths:

envguard --exclude "fixtures/**" --exclude "docs/examples/**"

Allow advisory findings without failing a workflow:

envguard --allow-unused
envguard --allow-missing

Mark known project-specific runtime behavior without hiding other real issues:

envguard --optional CONVO_BOT
envguard --external SUPABASE_SERVICE_ROLE_KEY
envguard --ignore-missing LEGACY_FLAG

By default, terminal output summarizes issue counts without printing long reference tables. Show the full tables when you need file and line details:

envguard --details

Interactively prune unused keys from .env.example:

envguard --fix

Supabase Edge Functions

envguard can include Supabase Edge Function secrets in the audit. This is useful when some production-only values should not appear in .env.example but still need to satisfy references in Edge Function code.

export SUPABASE_ACCESS_TOKEN="sbp_..."
envguard supabase your-project-ref

When Supabase secrets are included:

  • Referenced keys are considered available if they exist in either .env.example or Supabase.
  • Supabase secrets that are not referenced and not documented in .env.example are reported as ORPHANED.
  • .env.example keys that are not referenced are still reported as UNUSED.

Create an access token at app.supabase.com/account/tokens. Your project reference is the ID in a Supabase project URL such as https://app.supabase.com/project/your-project-ref.

envguard also detects Supabase projects automatically from [tool.envguard], the Supabase CLI linked-project file at supabase/.temp/project-ref, supabase/config.toml, SUPABASE_PROJECT_REF, or SUPABASE_PROJECT_ID. Remote secrets are fetched only when a project ref is known, local Edge Functions are present, and either SUPABASE_ACCESS_TOKEN is available or an authenticated supabase CLI can run supabase secrets list --project-ref <ref> --output json, so ordinary scans stay predictable.

The Supabase access token can come from SUPABASE_ACCESS_TOKEN in your shell, the selected dotenv file, the project .env, or a secure prompt in envguard wizard. Tokens entered in the wizard are used only for that run. They are not printed, written to pyproject.toml, or included in the generated command preview. If you prefer Supabase CLI auth, run supabase login and supabase link in the project; envguard will use the CLI when no access token is available.

Set scan_supabase = false in [tool.envguard] to opt out of Supabase-specific behavior for a project. This disables Supabase project detection, remote secret fetching, and local supabase/functions/** scanning unless you explicitly pass --supabase-project for a one-off run.

CI Onboarding Generator

Run envguard ci-template [path] from your repository root to print a ready-to-paste GitHub Actions workflow:

envguard ci-template > /tmp/envguard-workflow.yml

The command is dry-output only: it prints YAML to stdout and does not create .github/workflows or edit your project. The generated workflow:

  • Installs envguard from the GitHub repo.
  • Runs envguard ci so findings appear as GitHub annotations.
  • Adds the project path when you pass one, for monorepos such as apps/web.
  • Includes a safe --dotenv argument when a committed template like .env.example, .env.sample, or .env.template is detected.
  • Reuses [tool.envguard] in pyproject.toml automatically instead of duplicating config in CI.
  • Adds a SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} placeholder only when Supabase Edge Functions and a project ref are detected.
  • Avoids printing dotenv values or local secret values. If only a real .env exists locally, the workflow leaves it out and suggests committing a template contract.

Example output:

# Generated by `envguard ci-template` (dry output; no files were written).
# Paste this into .github/workflows/envguard.yml and adjust branch/install pinning as needed.
name: Envguard

on:
  pull_request:
  push:
    branches: [main]

jobs:
  envguard:
    name: Env var drift check
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"
      - name: Install envguard
        run: python -m pip install git+https://github.com/Tresnanda/envguard.git
      - name: 🛡️ Scan env contracts
        run: |
          envguard ci apps/web --dotenv apps/web/.env.example

Dotenv Format

envguard accepts standard dotenv-style keys from .env.example, .env.sample, .env.template, or a real .env file passed with --dotenv .env:

DATABASE_URL=postgres://localhost
API_KEY=
BARE_SECRET
export SUPABASE_URL=https://example.supabase.co
SUPABASE_ACCESS_TOKEN="sbp_..." # comments are fine

Comments and blank lines are ignored. Invalid variable names are skipped. Values are used only to discover sensitive integration tokens such as SUPABASE_ACCESS_TOKEN; envguard does not print dotenv values in audit output.

Project Configuration

You can store team defaults in pyproject.toml so developers and CI use the same scan settings without wrapper scripts:

envguard init --dotenv config/example.env --exclude "fixtures/**"
[tool.envguard]
dotenv = "config/example.env"
exclude = ["fixtures/**", "docs/examples/**"]
supabase_project = "your-project-ref"
scan_supabase = true
optional = ["CLI_DEFAULT_BOT"]
external = ["REMOTE_CONTAINER_SECRET"]
ignore_missing = ["LEGACY_FLAG"]

CLI flags still work on top of this configuration. For example, --exclude adds more ignore patterns, --optional / --external / --ignore-missing add per-run requirement overrides, and --supabase-project overrides the configured project. Use scan_supabase = false when a repository keeps Supabase examples or vendored functions locally but should not include supabase/functions/** or remote Supabase secrets in normal audits.

Supported Reference Patterns

envguard detects common direct environment-variable access patterns:

RuntimePatternExample
Pythonos.getenv("KEY")os.getenv("DATABASE_URL")
Pythonos.environ["KEY"]os.environ["SECRET_KEY"]
Pythonos.environ.get("KEY")os.environ.get("DEBUG")
JavaScriptprocess.env.KEYprocess.env.API_KEY
JavaScriptprocess.env["KEY"]process.env["API_KEY"]
DenoDeno.env.get("KEY")Deno.env.get("SUPABASE_URL")
Shell${KEY}${DATABASE_URL}
Shell$KEY$PATH
PowerShell$env:KEY$env:SUPABASE_ACCESS_TOKEN
PowerShell${env:KEY}${env:SUPABASE_URL}
PowerShell[Environment]::GetEnvironmentVariable("KEY")[Environment]::GetEnvironmentVariable("DATABASE_URL")
Genericenv("KEY")env("LOG_LEVEL")
Windows-style%KEY%%USERNAME%

Dynamic expressions such as os.getenv(prefix + "_TOKEN") are intentionally not inferred.

CLI Reference

usage: envguard [-h] [--path PATH] [--json] [--summary]
                [--github-annotations] [--plan] [--fix] [--fix-dry-run]
                [--fix-real-env]
                [--supabase-project SUPABASE_PROJECT]
                [--dotenv DOTENV] [--baseline BASELINE]
                [--write-baseline WRITE_BASELINE] [--debug] [--details]
                [--exclude PATTERN]
                [--optional KEY] [--external KEY] [--ignore-missing KEY]
                [--allow-unused] [--allow-missing] [--no-wizard]
                [path|wizard|doctor|matrix|plan|ci|ci-template|supabase|init|update] [...]

options:
  path                  Optional project path, e.g. envguard apps/web.
  wizard                Build and optionally run an audit command interactively.
  doctor [path]         Show key readiness across dotenv/env/Supabase sources.
  matrix [path]         Alias for doctor.
  plan [path]           Print dry remediation proposals from doctor findings.
  ci [path]             Shortcut for GitHub Actions annotations.
  ci-template [path]    Print a copy-pasteable GitHub Actions workflow.
  supabase ID [path]    Shortcut for Supabase secret comparison.
  init [path]           Write or update [tool.envguard] in pyproject.toml.
  update                Update envguard from GitHub.
  -h, --help            Show help and exit.
  --path PATH           Project path to scan. Defaults to the current directory.
  --json                Print a JSON report.
  --summary             Print one compact terminal summary line.
  --github-annotations  Print GitHub Actions annotations for CI logs.
  --plan                Print dry, copy-pasteable remediation proposals for doctor findings.
  --fix                 Interactively remove unused keys from .env.example.
  --fix-dry-run         Preview unused dotenv entries that --fix would prune without writing files.
  --fix-real-env        Allow --fix to edit a real .env file instead of only templates.
  --supabase-project ID Fetch Supabase Edge Function secrets for this project.
  --dotenv PATH         Path to dotenv file. Defaults to auto-detected templates or .env.
  --baseline PATH       Suppress known findings listed in an envguard baseline JSON file.
  --write-baseline PATH Write current findings to a secret-safe baseline JSON file and exit.
  --exclude PATTERN     Glob pattern to exclude from scanning. Can be repeated.
  --optional KEY        Mark a missing key as optional/defaulted. Can be repeated.
  --external KEY        Mark a missing key as owned by another runtime/container. Can be repeated.
  --ignore-missing KEY  Ignore a missing key entirely. Can be repeated.
  --allow-unused        Do not fail on unused keys or orphaned Supabase secrets.
  --allow-missing       Do not fail on missing referenced variables.
  --details             Show detailed issue tables with file references.
  --no-wizard           Run the default scan instead of the interactive guide.
  --debug               Print detected references and parsed keys.

Summary Output

--summary prints exactly one plain-text line and uses the same exit-code rules as the default report:

envguard: red — 2 missing, 1 unused, 3 optional (exit 1)

The status is red when blocking findings would make envguard exit non-zero, yellow when findings are present but allowed/advisory, and green when the scan is clean. Counts include nonzero missing, unused, optional, external, ignored, and Supabase orphaned findings.

Baselines

Baselines let legacy projects adopt envguard incrementally. Write the current findings once, commit the generated JSON, and keep CI strict for any new drift:

envguard --write-baseline .envguard-baseline.json
envguard --baseline .envguard-baseline.json

Baseline files store only finding classes and key names — no dotenv values, reference paths, Supabase tokens, or secret values:

{
  "version": 1,
  "findings": {
    "unused": ["OLD_API_KEY"],
    "missing": ["DATABASE_URL"],
    "optional_missing": [],
    "external_missing": [],
    "ignored_missing": [],
    "supabase_orphans": []
  }
}

You can also store the path in project config:

[tool.envguard]
baseline = ".envguard-baseline.json"

Matching findings are suppressed before output and exit-code calculation. New unbaselined MISSING, UNUSED, or ORPHANED findings still fail unless you also pass the existing --allow-* flags.

JSON Output

{
  "unused": ["OLD_API_KEY"],
  "missing": ["NEW_SECRET"],
  "optional_missing": ["LOCAL_TIMEOUT_MS"],
  "external_missing": ["REMOTE_CONTAINER_SECRET"],
  "ignored_missing": ["LEGACY_FLAG"],
  "supabase_orphans": ["LEGACY_EDGE_SECRET"],
  "references": {
    "DATABASE_URL": [
      {
        "file": "/path/to/app.py",
        "line": 12,
        "pattern": "os.getenv",
        "requirement": "required",
        "reason": ""
      }
    ]
  }
}

Exit Codes

CodeMeaning
0No blocking findings were found. Advisory optional/external/ignored findings may still be present.
1The audit found blocking issues or could not complete.

--allow-unused suppresses failure for unused .env.example keys and orphaned Supabase secrets. --allow-missing suppresses failure for required missing referenced keys. Optional, external, and ignored missing keys are advisory by default and still appear in the selected output format.

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
ruff check .

License

MIT. See LICENSE.

↑↓ navigate openesc close