#!/bin/bash # Emit the canonical session-log "## User" attribution block. # # ATTRIBUTION IS NEVER INFERRED. The only sources of truth are: # .claude/identity.json (per-machine, gitignored — who sits at this keyboard) # .claude/users.json (role lookup by user key) # Do NOT derive the user from the hostname, the `# userEmail` context hint, or # from memory. /save calls this script and pastes its output verbatim as the # session log's first section, so every log is stamped identically and correctly. set -e REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) ID="$REPO_ROOT/.claude/identity.json" USERS="$REPO_ROOT/.claude/users.json" if [ ! -f "$ID" ]; then echo "## User" echo "- **User:** UNKNOWN — no .claude/identity.json on this machine." echo "- **Action:** run the first-machine onboarding flow in CLAUDE.md before saving." exit 0 fi PYTHON="" for c in py python3 python; do if command -v "$c" >/dev/null 2>&1 && "$c" -c "import sys" >/dev/null 2>&1; then PYTHON="$c"; break; fi done if [ -z "$PYTHON" ]; then echo "## User" echo "- **User:** (could not render — no Python interpreter found)" exit 0 fi "$PYTHON" - "$ID" "$USERS" <<'PYEOF' import json, sys, socket, re idp, usersp = sys.argv[1], sys.argv[2] try: d = json.load(open(idp)) except Exception as e: print("## User") print(f"- **User:** UNREADABLE — .claude/identity.json failed to parse ({e}).") print("- **Action:** repair identity.json before saving; do not infer the user.") sys.exit(0) full = d.get("full_name") or d.get("user", "unknown") user = d.get("user", "unknown") machine = d.get("machine", "unknown") role = d.get("role", "") if not role: try: role = json.load(open(usersp))["users"].get(user, {}).get("role", "") except Exception: pass def norm(x): return re.sub(r'\.local$', '', (x or '').lower()) host = socket.gethostname() stale = machine and host and norm(machine) != norm(host) print("## User") print(f"- **User:** {full} ({user})") print(f"- **Machine:** {machine}") if role: print(f"- **Role:** {role}") if stale: print(f"- **[WARNING]** identity.json machine '{machine}' != hostname '{host}'. " f"identity.json may be stale on this box — verify before trusting this attribution.") PYEOF