Something went wrong. Try again.
Identities for entities did.bot
agent llm did
Something went wrong. Try again.
Python
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110#!/usr/bin/env python3"""Record the shape of a hook payload, never its contents.
`plan/harnesses.md` lists what this project takes from a harness and marksseveral entries inferred: they were seen on the headless CLI and assumed tohold in an editor extension, which is the only surface this deploymentactually has. This closes that by observing rather than assuming.
What lands in the log is field *names*, not field values. A payload carriesprompts, tool arguments and file paths; none of that is needed to answerwhich events fire and what they carry, so none of it is written down. Theexceptions are three opaque identifiers -- the session, the agent and thetool call -- which are what the join in `plan/cred-delivery.md` is built on,and a handful of scalars that name a mechanism rather than describe work."""
import jsonimport osimport sysimport time
# Values safe to record: identifiers with no content in them, and names of# mechanisms. Everything else in a payload is the session's own material.SCALARS = ( "hook_event_name", "session_id", "agent_id", "agent_type", "tool_use_id", "tool_name", "permission_mode", "source", "prompt_id",)
# Whether these are set, and never what they hold: the first two are what# `plan/cred-delivery.md` publishes a socket path through, and the last says# which surface the session is running on.ENV = ( "CLAUDE_ENV_FILE", "CLAUDE_PLUGIN_DATA", "CLAUDE_PLUGIN_ROOT", "CLAUDE_CODE_ENTRYPOINT", "CLAUDE_PROJECT_DIR",)
# The label of the run this event belongs to, so rows from a matrix of runs# can be told apart in one log.RUN = "DIDBOT_PROBE_RUN"
def log_path(): base = os.environ.get("CLAUDE_PLUGIN_DATA") or os.environ.get("TMPDIR") or "/tmp" return os.path.join(base, "didbot-probe.jsonl")
def effort(payload): """`effort` arrives as an object on some events and is absent on others.""" value = payload.get("effort") if isinstance(value, dict): return value.get("level") return value if isinstance(value, str) else None
def main(): try: payload = json.load(sys.stdin) except Exception: payload = {} if not isinstance(payload, dict): payload = {}
record = { "at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), # Fractional, because comparing when a hook fired against when the # harness wrote a file is a question about tenths of a second. "epoch": round(time.time(), 3), "keys": sorted(payload), "effort": effort(payload), "env": {name: name in os.environ for name in ENV}, # A `SessionStart` hook is handed a path whose file does not exist yet, # so presence of the variable and existence of the file are different # facts and both are worth having. "env_file_exists": os.path.exists(os.environ.get("CLAUDE_ENV_FILE", "")), "run": os.environ.get(RUN, ""), } # A subagent's own transcript is written at a path derived from its id. # An internal fork of the harness is given an id and no transcript, so # the file's existence tells a dispatched agent from a fork -- see # `plan/harnesses.md`. agent_transcript = payload.get("agent_transcript_path") if isinstance(agent_transcript, str) and agent_transcript: record["agent_transcript_exists"] = os.path.exists(agent_transcript) for name in SCALARS: value = payload.get(name) if isinstance(value, (str, int, bool)): record[name] = value
path = log_path() try: os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "a", encoding="utf-8") as handle: handle.write(json.dumps(record, sort_keys=True) + "\n") except OSError: pass
if __name__ == "__main__": main()