v1.16.0.0 feat: /env-check — pre-ship env var sanity check (#1106)#1228
Open
gregario wants to merge 3 commits intogarrytan:mainfrom
Open
v1.16.0.0 feat: /env-check — pre-ship env var sanity check (#1106)#1228gregario wants to merge 3 commits intogarrytan:mainfrom
gregario wants to merge 3 commits intogarrytan:mainfrom
Conversation
Closes garrytan#1106. Reported by @tashonna-labs. Env var drift is the quiet bug that breaks deploys: a new `process.env.X` that nobody added to `.env.example`, a stale `.env.example` your teammate clones tomorrow, an API key that drifted into a tracked file. None of it shows up in tests. /cso would catch it eventually but /cso is the deep audit, not the pre-flight. This is the pre-flight. Four steps, three findings sections, one verdict. Run before /ship. Read-only. Persona is "the teammate who reads a PR and asks: did you add this to .env.example?" — derived from the issue's framing ("quiet problems that bites you at deployment time", "Run before /ship to catch ... before they reach CI"). The voice is matter-of-fact, not alarmist; the report is informational, not gating; CRITICAL is reserved for the actual deploy- breaking case (hardcoded secret in tracked source). What it checks: 1. **Drift** — keys in `.env.example` vs `.env` (MEDIUM if missing, LOW if undocumented). 2. **Code references** — `process.env.X`, `os.getenv`, `Deno.env.get`, `ENV[]`, `os.Getenv`, `std::env::var`, `Environment.GetEnvironmentVariable`, `System.getenv`. Cross-referenced against `.env.example`. HIGH for orphaned references (the actual deploy-breaking pattern). 3. **Hardcoded secrets** — `sk-`, `sk-ant-`, `ghp_`, `AKIA`, `xoxb-`, `sk_live_`, `AIza`, JWTs, postgres/mongo/mysql/redis URLs with creds, private key headers. CRITICAL when found in tracked source. What it doesn't do (deferred): - Auto-fix (adding missing keys to .env.example) — issue mentions but scope-cut to keep first PR narrow - Trend tracking via JSONL — audit-skill machinery; this skill is the pre-flight, runs every PR, doesn't need a long history - Git-history archaeology — that's /cso's job Modes: - `/env-check` — full check - `/env-check --drift` — only .env.example ↔ .env comparison - `/env-check --refs` — only orphaned code references - `/env-check --secrets` — only hardcoded-secret scan - `/env-check --diff` — only files changed on this branch (combinable) FP rules cover runtime-provided keys (NODE_ENV, CI/*, cloud-provider auto-injected vars), public-by-design prefixes (NEXT_PUBLIC_*, VITE_*, PUBLIC_*), placeholder values in example files, and test fixtures. Style follows /cso and /health: persona statement, hard gate, scope flags, severity ladder with FP rules, ASCII-art findings table. ~250 lines for the template — calibrated to the issue author's "lightweight script" framing, not a /cso-class deep dive. Auto-discovered by `discoverTemplates` in `scripts/discover-skills.ts` — no setup wiring needed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bun run gen:skill-docs --host all Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #1106. Reported by @tashonna-labs.
Env var drift is the quiet bug that breaks deploys: a new
process.env.Xnobody added to.env.example, a stale.env.exampleyour teammate clones tomorrow, an API key that drifted into a tracked file. None of it shows up in tests./csocatches it eventually but/csois the deep audit, not the pre-flight. New/env-checkis the 5-second pre-flight before/ship.Persona derivation
Tashonna's framing in the issue:
/shipto catch accidental secret commits or undocumented env dependencies before they reach CI."Not a security audit. A pre-ship sanity check. The persona derived from those three signals:
Calm, matter-of-fact, informational. CRITICAL is reserved for the actual deploy-breaking case (hardcoded secret in tracked source). Otherwise the tone is "did you mean to commit this?" not "SECURITY VIOLATION DETECTED."
What it does
Four steps, three findings sections, one verdict.
.env.example/.sample/.template) and stack patterns (Node/TS, Deno, Python, Ruby, Go, Rust, .NET, JVM, shell).env.examplevs.env. MEDIUM if missing from.env, LOW if undocumented in.env.example.process.env.X,os.getenv,Deno.env.get,ENV[],os.Getenv,std::env::var,Environment.GetEnvironmentVariable,System.getenv. Cross-reference against.env.example. HIGH for orphaned references (the actual deploy-breaking pattern).sk-,sk-ant-,ghp_,AKIA,xoxb-,sk_live_,AIza, JWTs, postgres/mongo/mysql/redis URLs with creds, RSA/EC/DSA/OpenSSH private key headers. CRITICAL when found.Then a Pre-Ship Env Check report with three sections, severity counts, and one verdict: SHIP-READY, NEEDS REVIEW, or DO NOT SHIP. Soft verdict — informational, never blocks.
Modes
/env-check— full check/env-check --drift— only.env.example↔.envcomparison/env-check --refs— only orphaned code references/env-check --secrets— only hardcoded-secret scan/env-check --diff— only files changed on this branch (combinable)FP rules built in
NODE_ENV,RAILS_ENV,CI,GITHUB_*,GITLAB_*,VERCEL_*,NETLIFY_*,RENDER_*,FLY_APP_NAME, etc. — never flagged as HIGH (auto-injected, not project-secret)NEXT_PUBLIC_*,VITE_*,REACT_APP_*,PUBLIC_*,EXPO_PUBLIC_*— LOW max*test*,__tests__/*,spec/*,fixtures/*— MEDIUM max unless same fingerprint in non-test code.env.local,.env.*.local,.env.test,.env.development— LOW max regardlessWhat's NOT in this PR (deferred)
.env.example) — issue mentions but kept narrow for first PR/cso's job/cso --envsubphase — let it stand alone; mention the relationship in skill bodyStyle
Follows
/csoand/healthconventions:## User-invocable→## Arguments→ numbered Steps →## Important Rules═══borders{{PREAMBLE}},{{LEARNINGS_SEARCH}},{{LEARNINGS_LOG}}resolver tagsCalibrated to the issue author's "lightweight" framing — 255 lines for the template, not the 600+ that
/csopacks. Different jobs.Test plan
bun run gen:skill-docs --host all— regenerates cleanly for claude, codex, factory, kiro, opencode, slate, cursor, openclaw, hermes, gbrainbun test test/skill-validation.test.ts test/gen-skill-docs.test.ts— 689 pass, 0 faildiscoverTemplatesinscripts/discover-skills.ts— nosetupscript wiring needed beyond droppingenv-check/SKILL.md.tmplBisected commits
feat: /env-check — pre-ship env var sanity check—env-check/SKILL.md.tmplonlychore(env-check): regenerate SKILL.md from template— generated filechore: release v1.16.0.0 (/env-check skill)— VERSION + CHANGELOGFiles
env-check/SKILL.md.tmpl(new, 255 lines)env-check/SKILL.md(regenerated for claude host, ~1300 lines after preamble expansion)VERSION,CHANGELOG.md— release v1.16.0.0🤖 Generated with Claude Code