env-check
Probe the dev environment for the recurring Windows quirks documented in `.claude/rules/environment.md` — Python version + 3.13 dep gaps, stdout encoding (cp1252 trap, tested by actually writing a non
SKILL.md.agent-bus/skills/env-check/SKILL.md
GitHubEnv Check
Codifies the environment friction surfaced across 4+ recent sessions so we stop re-discovering it. Read-only — never installs, never restarts. Run anomalies past the user before continuing whatever work is queued.
When to use
- A non-ASCII
print()just crashed withUnicodeEncodeError - A
pip installsucceeded but the import still fails - A daemon call returned an unexpected error
- Beginning of a session that will touch pronounce/voice/non-ASCII work
- User says "env-check"
Probes (in order)
1. Python version + 3.13 dep gaps
python --version
If 3.13.x, flag the known wheel gaps before they bite:
python -c "import g2p_en" 2>&1 | head -1
python -c "import phonemizer" 2>&1 | head -1
where espeak-ng 2>&1 | head -1
Known: g2p_en has no Python 3.13 wheel as of recent sessions; espeak-ng needs a separate Windows install. Apps depending on these (apps/pronounce, apps/public/standard/voice-assistant listen path) gate imports behind try/except. Surface gaps; do NOT install.
2. Encoding — actively write a non-ASCII char
Reading sys.stdout.encoding is the indirect test. The direct test is to write a non-ASCII char and see if the subprocess crashes:
python -c "import sys; print('encoding:', sys.stdout.encoding); print('é α 中 ✓')"
Expected with the .claude/settings.json env.PYTHONIOENCODING=utf-8 hook active: encoding: utf-8 followed by the four chars rendering cleanly. If you see UnicodeEncodeError or cp1252 in the first line, the hook isn't taking effect — flag it and tell the user to write non-ASCII via open(path, "w", encoding="utf-8") rather than print() until the hook is fixed.
3. Daemons
curl -s -o /dev/null -w "main :9000 = %{http_code}\n" http://localhost:9000/api/health
curl -s -o /dev/null -w "dogfood :9001 = %{http_code}\n" http://localhost:9001/api/health
Anything other than 200 → report, don't act (.claude/rules/daemon-handling.md). Connection refused on :9001 is fine if dogfood-demo is disabled in emptyos.toml.
4. Sandbox pool (only if test-fix work is queued)
curl -s http://localhost:9000/sandbox/api/status
Look for at least one idle member. If pool_full or every member is dead, surface so the user can restart the main daemon (which re-seeds the pool).
Report shape
Two or three lines is fine — skip rows that aren't relevant to the current task. Surface anomalies before starting work, not after.
Env check:
python: 3.13.x · stdout=utf-8 · non-ASCII print ok
pronounce stack: g2p_en MISSING (3.13 wheel gap) · espeak-ng ok
:9000: 200 · :9001: refused (dogfood off)
sandbox: 2 idle / 0 leased
If any row is anomalous, lead with it and ask the user how to proceed:
Env check anomaly:
stdout=cp1252 — PYTHONIOENCODING hook not active
Any non-ASCII print() from a Bash tool will crash.
Proceed with file-only I/O, or stop and fix the hook?
What this skill is NOT
- Not a fixer. It surfaces; the user (or a separate skill) acts.
- Not a daemon manager — never restart anything.
- Not a replacement for
/preflight— preflight is broader (git + daemon + env); env-check is the deep-dive when the env is the suspected cause.