HookStack
Back to catalogue
WorkflowInstructionsLoaded

Audit log for CLAUDE.md file loads

Know exactly which CLAUDE.md governed a session

Records every CLAUDE.md and .claude/rules/*.md file loaded into context to a timestamped audit log. Captures the file path, memory scope (User/Project/Local/Managed) and load reason, providing full traceability of which instructions governed each session.

What does the Audit log for CLAUDE.md file loads hook do?

Audit log for CLAUDE.md file loads is a Claude Code InstructionsLoaded hook. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Know exactly which CLAUDE.md governed a session.

Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.

Use cases

  • Audit which CLAUDE.md files were active during a session for compliance reviews
  • Debug unexpected model behaviour by reviewing which instruction files were loaded
  • Track lazy-loaded nested CLAUDE.md files in monorepos for instruction coverage

Tags

#audit#claude-md#instructions#compliance#traceability

settings.json fragment

{
  "hooks": {
    "InstructionsLoaded": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/instructions-loaded-audit-log.mjs",
            "type": "command"
          }
        ]
      }
    ]
  }
}

Script · .claude/hooks/instructions-loaded-audit-log.mjs

#!/usr/bin/env node
// @hookstack instructions-loaded-audit-log
// Journalise le chargement d'instructions / mémoire (InstructionsLoaded)
import { appendFileSync, mkdirSync, readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

export function run(
	input,
	{
		append = appendFileSync,
		mkdir = mkdirSync,
		projectDir = process.env.CLAUDE_PROJECT_DIR ?? ".",
		now = () => new Date().toISOString(),
	} = {},
) {
	const logPath = join(projectDir, ".claude", "instructions-audit.log");
	try {
		mkdir(dirname(logPath), { recursive: true });
	} catch {
		/* exists */
	}

	const line = `${now()} | ${input.memory_type} | ${input.load_reason} | ${input.file_path}\n`;
	append(logPath, line);
	return line;
}

/* v8 ignore next 4 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
	const input = JSON.parse(readFileSync(0, "utf8"));
	run(input);
}

Learn more

Related hooks