#!/usr/bin/env python3 """Ensure .claude/settings.local.json env.CLAUDETOOLS_ROOT matches identity.json. Why: many skill docs invoke `py "$CLAUDETOOLS_ROOT/.claude/skills/.../x.py"`. That env var is per-machine and was never exported, so the commands resolved to the wrong path in fresh Git-bash shells (logged in errorlog.md 2026-06-14). Claude Code injects the `env` block from settings(.local).json into every Bash tool call, so seeding CLAUDETOOLS_ROOT there from identity.json fixes it fleet-wide. Per-machine value, so it lives in the gitignored settings.local.json — sourced here from identity.json. Idempotent. Run from the repo root (or anywhere — paths are resolved off this file). Takes effect at the NEXT Claude Code session start (env is injected at session init). """ import json import os import sys HERE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.normpath(os.path.join(HERE, "..", "..")) IDENT = os.path.join(ROOT, ".claude", "identity.json") LOCAL = os.path.join(ROOT, ".claude", "settings.local.json") def main(): if not os.path.isfile(IDENT): print("[ERROR] .claude/identity.json missing — run onboarding first", file=sys.stderr) return 1 ident = json.load(open(IDENT, encoding="utf-8")) root = ident.get("claudetools_root") if not root: print("[ERROR] identity.json has no 'claudetools_root'", file=sys.stderr) return 1 settings = {} if os.path.isfile(LOCAL): try: settings = json.load(open(LOCAL, encoding="utf-8")) except Exception as e: print(f"[ERROR] settings.local.json is not valid JSON: {e}", file=sys.stderr) return 1 env = settings.setdefault("env", {}) if env.get("CLAUDETOOLS_ROOT") == root: print(f"[OK] CLAUDETOOLS_ROOT already set to {root}") return 0 env["CLAUDETOOLS_ROOT"] = root with open(LOCAL, "w", encoding="utf-8") as f: json.dump(settings, f, indent=2) f.write("\n") print(f"[OK] Set CLAUDETOOLS_ROOT={root} in settings.local.json (effective next session)") return 0 if __name__ == "__main__": sys.exit(main())