Hooks & Session Intelligence

AgentUX uses Claude Code hooks to prime every session with essential knowledge, capture learnings automatically, and detect when you paste AI assistant output.

On This Page


Overview

AgentUX configures five Claude Code hooks that work together to create an intelligent session loop:

HookEventPurpose
CheatsheetSessionStartDisplay essential patterns, gotchas, and commands on every session start and /clear
Keyword IndexSessionStartBuild a keyword index mapping 698 keywords to 86 skills for intent detection
GraphRAG NudgeUserPromptSubmitMatch every prompt against the keyword index, query Neo4j for relevant methods/knowledge, inject context, and auto-detect DA output
PostTool CapturePostToolUseDetect errors in Bash tool output (tracebacks, shell errors, build failures) and auto-capture structured entries to the knowledge queue
Session CloseStopScan transcript for discoveries, enrich auto-captured entries, ingest queue to Neo4j, prune stale/duplicate entries

All hooks are configured in the project-level .claude/settings.json and run automatically. They are additive to any user-level hooks in ~/.claude/settings.json.


Session Startup Cheatsheet

Every new session and every /clear command displays a compact cheatsheet covering:

  • GraphRAG Tools -- Top 5 tools for verifying UE APIs before guessing
  • Critical Gotchas -- The 5 most common mistakes (mesh RC, viewport position, float/real, BeginPlay, PIE delay)
  • Path Rules -- Full UObject paths, component paths, subobject paths
  • Error Codes -- Standard JSON-RPC error codes and their meanings
  • Knowledge Capture Mandate -- When to record learnings (see below)
  • Neo4j Status -- Live health check with 2-second timeout

The cheatsheet is injected into Claude's context, ensuring every session starts with essential knowledge regardless of conversation history.

Script: .claude/hooks/agentux-cheatsheet.py


Knowledge Capture Pipeline

AgentUX implements a continuous learning loop that captures session discoveries automatically and makes them available to future sessions:

SessionStart              UserPromptSubmit         PostToolUse (Bash)       SessionEnd (Stop)
+--------------+         +----------------+       +------------------+     +---------------------+
| Build        |         | Query Neo4j    |       | Detect errors    |     | 1. Scan transcript  |
| keyword      |         | for experience |       | (tracebacks,     |     |    for discoveries   |
| index        |         | hints          |       |  shell, build)   |     | 2. Enrich pending   |
|              |         | Prepend to     |       | Auto-capture to  |     |    entries with fix  |
| Display      |         | prompt         |       | knowledge-queue  |     | 3. Ingest to Neo4j  |
| cheatsheet   |         |                |       | .md (max 5/sess) |     | 4. Prune stale/dups |
+--------------+         +----------------+       +------------------+     +---------------------+

The PostTool Capture hook is the key innovation: errors are captured automatically without Claude needing to manually write queue entries. The session-close hook then enriches these entries with fix context from the transcript before ingesting them into Neo4j.

Knowledge Importance Tiers

Every piece of captured knowledge is classified with an importance tier that controls how aggressively the maintenance system can prune it. This prevents long-running sessions from treating hard-won debugging knowledge as "self-evident."

TierProtectionExample
quick-tipNone -- all pruning checks apply"use -nocef flag for tests"
life-experiencePartial -- only contradictions can trigger drop"PIE transitions need 2s sleep"
hard-wonReview only -- flagged for human review, never auto-deleted"StaticEnum linker errors for non-exported enums"
never-forgetImmune -- never pruned, never demoted"DEPLOY DLL after every build"

When Claude captures knowledge, it assigns a tier based on how the knowledge was acquired. Users can override: saying "never forget this" or "this is critical" automatically sets the tier to never-forget. If the importance field is omitted, it defaults to life-experience.

Capture Criteria

Claude is instructed to RECORD when:

  • API behavior differs from documentation or reasonable expectation
  • A call failed and the fix was non-obvious
  • Parameter name/type is case-sensitive, version-dependent, or misleading
  • Specific call ordering is required (A must happen before B)
  • Silent failure: input accepted, no error, but output was wrong
  • When in doubt, RECORD -- the maintenance skill prunes later

Claude is instructed to SKIP when:

  • Routine API usage that worked on first try
  • Information already documented
  • Temporary debugging steps or one-off investigations
  • User preferences or project-specific configuration

PostTool Error Auto-Capture

The PostTool Capture hook fires after every Bash tool execution and inspects the output for actionable errors. When an error is detected, it writes a structured ## gotcha: entry directly to the knowledge queue, with no manual intervention required.

Error Categories Detected

  • Python tracebacks: TypeError, ImportError, KeyError, ValueError, AttributeError, and 15+ other exception types
  • Shell errors: "command not found", "Permission denied", git fatal errors
  • Build errors: MSVC compiler errors (error C####), cmake failures, build "FAILED" (with build context verification)

Safeguards

  • Suppression: Benign patterns are never captured ("No matches found", Neo4j cosmetic warnings, git info messages, py_compile "Syntax OK")
  • Deduplication: Same error signature is only captured once per session (tracked via .claude/session-errors.log)
  • Queue dedup: Entries with the same gotcha name already in the queue are skipped
  • Session cap: Maximum 5 auto-captures per session (prevents queue bloat from build error loops)
  • Performance: Must complete in under 50ms. Actual overhead is approximately 5ms.

Auto-captured entries include an auto-captured: true marker and a placeholder correct: [pending] field. The session-close hook attempts to fill in the fix from transcript context.

Script: .claude/hooks/agentux-posttool-capture.py


Knowledge Queue Format

Entries are added to .claude/knowledge-queue.md during sessions, both automatically (by the PostTool Capture hook) and manually (by Claude when instructed). Each entry follows this format:

## pattern: Descriptive Name
category: Blueprint API
handler: editor.blueprint
importance: life-experience
description: When creating variables, UE 5.7.4 returns "real" instead of "float" for the type field.
```
var_type = result.get("type", "").lower()
assert var_type in ("float", "real")  # Accept both
```

For handler-specific gotchas:

## gotcha: Mesh Component Path
handler: staticmesh
importance: hard-won
description: Direct property set on StaticMeshComponent doesn't trigger render proxy
correct: Use editor.rc.call with SetStaticMesh function instead

The importance field is optional (defaults to life-experience). Valid values: quick-tip, life-experience, hard-won, never-forget.

The queue file includes the full capture criteria as HTML comments at the top. Entries are appended below the marker line.


Session Close Hook

When a session ends (via /exit, /clear, or terminal close), the SessionEnd hook runs a 5-phase pipeline:

  1. Transcript scanning: Scans the session transcript for discovery signals ("turns out", "the fix was", "silent failure", etc.). Messages with 1+ signals and 200+ characters are appended to the knowledge queue.
  2. Entry enrichment: Auto-captured entries with correct: [pending] are searched against the transcript for fix patterns. If a fix is found, the correct: field is filled in.
  3. Neo4j ingest: Parses all ## pattern: and ## gotcha: entries, MERGEs each into Neo4j as ProductCommand nodes with importance tiers and provenance='learned'. Clears the queue on success.
  4. Error reporting: Checks .claude/session-errors.log for tool errors that were not captured, reports them for next session.
  5. Automated pruning: Runs the pruning pipeline (cross-type dedup at 70% word overlap, staleness check at 30 days, orphan cleanup). Tier shields protect hard-won and never-forget entries.

Graceful Failure

  • Neo4j offline: Queue is preserved for the next session. No data is lost.
  • Empty queue: Hook exits silently (no output, no errors).
  • Invalid entries: Skipped individually; valid entries still ingested.
  • Pruning failure: Does not block session close. Errors are caught silently.
  • Always exits 0: Never blocks session termination.

Script: .claude/hooks/agentux-session-close.py


Automatic Knowledge Injection

Every prompt you send goes through the GraphRAG Nudge hook, which automatically injects relevant AgentUX methods and skill knowledge into the conversation context. Claude sees this as additional context prepended to your message.

How It Works

  1. Keyword matching: Your prompt is matched against 698 keywords mapped to 85 skills and 45 handler namespaces.
  2. Neo4j lookup: When 2+ keywords match a domain, the hook queries Neo4j for relevant ProductCommand nodes (method names, descriptions, known pitfalls).
  3. Fulltext search: Significant words from your prompt run through a fulltext index for broader matches.
  4. Context injection: Up to 500 characters of relevant method/knowledge context is prepended to your message.

If Neo4j is unavailable, the hook falls back to static domain guidance text that points Claude to the right GraphRAG tools.

Learning Moment Detection

The hook also detects prompts that describe errors, workarounds, or API surprises (2+ signal words like "failed," "workaround," "silent failure"). When detected, Claude receives a reminder to capture the gotcha in the knowledge queue.

System Prompt Intelligence

The in-editor chat system prompt automatically detects whether GraphRAG is available. When GraphRAG tools are present, the system prompt includes:

  • A list of the 8 most important GraphRAG MCP tools (get_class_details, find_api_surface, search_ue_source, etc.)
  • A research-then-act workflow: Research (query GraphRAG) → Discover (find handler methods) → Plan → Execute → Verify
  • An explicit instruction to never guess UE property names or function signatures

When GraphRAG is not installed, the system prompt shows only the core editor control tools.


DA Bridge Auto-Detection

When you paste output from Epic's Developer Assistant (or any AI assistant with UE instructions), AgentUX automatically detects it and suggests the DA Bridge skill. This detection runs as part of the GraphRAG Nudge hook on every prompt.

How It Works

The hook scores each prompt against 6 signal categories:

#SignalTrigger
1Numbered steps with UE verbs3+ lines like "1. Create a...", "2. Set the..."
2Blueprint creation language2+ phrases: "create a blueprint", "add a variable", "compile the blueprint"
3Property-setting directives2+ phrases: "set the intensity", "enable real time", "set the exposure"
4Material pipeline language2+ phrases: "create a material", "blend mode", "connect to the"
5UE structure terms3+ terms: "content browser", "details panel", "world outliner"
6Multi-paragraph structure4+ paragraphs (typical of DA-generated instructions)

Threshold: 2 or more signals triggers detection. Prompts under 200 characters are never checked. This prevents false positives on normal prompts while catching genuine DA output.

On detection, Claude receives: "DA Assistant output detected. Use the da-bridge skill to parse and execute it."

Script: .claude/hooks/agentux-graphrag-nudge.py (DA detection is integrated into the GraphRAG nudge hook)


Knowledge Maintenance

Over time, the knowledge base accumulates entries that may overlap, become stale, or contradict updated code. The /knowledge-maintenance skill handles cleanup with tier-aware pruning:

Six Pruning Checks

CheckWhat It DetectsTier Shield
ContradictoryConflicting advice for the same handlerAll tiers except never-forget
Self-evidentKnowledge Claude already knows from trainingquick-tip only
UnverifiableReferences handlers that no longer existquick-tip only
DuplicateOverlaps with another entry or seed dataquick-tip only
Low-valueVague, empty, or generic entriesquick-tip only
UncertainUnclear if it prevents a real mistakequick-tip only

Grace Period

Maintenance never deletes on the first pass. Instead it uses a two-session grace period:

  1. First run: Entry is marked as marked-for-pruning with a timestamp. Not deleted.
  2. Next run: If still marked, the entry is deleted. If it survived re-review, the mark is cleared.

Demotions (e.g., life-experience to quick-tip) follow the same two-session pattern. Escalations (promoting an entry to a higher tier) are always immediate.

The skill defaults to dry-run mode -- it reports what it would do without making changes. Confirm to apply.

Recurring Schedule

The startup hook automatically triggers maintenance when 24+ hours have elapsed. You can also run it manually or on a loop:

/knowledge-maintenance          # Manual run
/loop 24h /knowledge-maintenance  # Recurring

Automated Pruning

The session-close hook runs an automated pruning pipeline after every successful ingest. This keeps the experience cache lean without manual intervention.

Three Pruning Checks

CheckWhat It DetectsAction
Cross-type dedupEntries with >70% word overlap across all experience node types (ProductCommand, TaskRecipe, SymptomSolution, QueryPattern)Delete the lower-importance entry (or older if tied)
StalenessLearned entries older than 30 daysquick-tip: delete. life-experience: demote to quick-tip
Orphan cleanupEntries with empty name AND empty descriptionDelete (garbage from failed captures)

Tier Shields

  • never-forget entries are immune to all pruning checks
  • hard-won entries are immune to automatic deletion and demotion
  • Entries with provenance='taught' (shipped content) are never deleted

Both thresholds are configurable: STALE_DAYS (default 30) and DEDUP_THRESHOLD (default 0.70). Manual pruning with preview is available via python curate_knowledge.py prune --dry-run.

Script: GraphRAG/scripts/prune_experience.py


Skill Knowledge Pipeline

AgentUX skills use a GraphRAG-backed knowledge architecture. Instead of storing all domain knowledge in static files, skills are slim stubs that query the Neo4j knowledge graph for relevant concepts on demand.

Architecture

LayerWhat It DoesLocation
Slim StubsSkill identity, interaction checkpoints, execution referenceSkills/*/SKILL.md (~60-150 lines each)
SkillKnowledge NodesConcept-anchored domain knowledge (patterns, anti-patterns, queries, escalation rules) with importance tiersNeo4j :SkillKnowledge:GraphRAG (1,400+ nodes)
MCP ToolQuery interface for Claude to load conceptsget_skill_knowledge (tool #30)

How It Works

  1. Claude triggers a skill via keyword detection (e.g., "lighting" triggers lighting-fundamentals)
  2. The slim stub loads -- Claude sees the skill identity, interaction checkpoints, and execution steps
  3. For domain knowledge, Claude queries get_skill_knowledge with the task-relevant terms
  4. Neo4j returns self-contained concept nodes -- each one is independently actionable
  5. Claude loads only what's relevant, not the entire skill's knowledge base

Example Queries

get_skill_knowledge(skill_name="lighting-fundamentals")              # All concepts for a skill
get_skill_knowledge(query="Lumen indoor lighting")                    # Cross-skill search
get_skill_knowledge(skill_name="lighting-fundamentals", topic="pattern")  # Just patterns
get_skill_knowledge(query="shadow cascade", topic="anti-pattern")     # Pitfalls about shadows

Concept Types

Each SkillKnowledge node is one of six concept types:

  • Pattern -- Named setup recipes with step-by-step instructions and bundled pitfalls
  • Anti-pattern -- Common mistakes with explanations and correct approaches
  • Identity -- What the skill covers and doesn't cover
  • Query -- GraphRAG queries to verify UE API details before acting
  • Escalation -- When to hand off to a related skill
  • Output -- Deliverable templates and naming conventions

Graceful Degradation

If Neo4j is unavailable, skills still provide their identity, interaction checkpoints, and execution steps. Claude falls back to training knowledge for domain concepts and notes the limitation to the user.

Extending Skills

Adding knowledge to a skill means adding Neo4j nodes, not editing files. Run migrate_skills_to_graphrag.py after updating SKILL.md content, or create SkillKnowledge nodes directly via Cypher. Skills are now open-ended knowledge domains with no file size limit.


Configuration

All hooks are configured in .claude/settings.json (project-level):

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [{ "type": "command", "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/agentux-cheatsheet.py\"" }]
      },
      {
        "matcher": "",
        "hooks": [{ "type": "command", "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/agentux-keyword-index.py\"" }]
      }
    ],
    "UserPromptSubmit": [{
      "matcher": "",
      "hooks": [{ "type": "command", "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/agentux-graphrag-nudge.py\"" }]
    }],
    "PostToolUse": [{
      "matcher": "Bash",
      "hooks": [{ "type": "command", "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/agentux-posttool-capture.py\"" }]
    }],
    "Stop": [{
      "matcher": "",
      "hooks": [{ "type": "command", "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/agentux-session-close.py\"" }]
    }]
  }
}

Important: Use $CLAUDE_PROJECT_DIR

Hook commands must use $CLAUDE_PROJECT_DIR instead of relative paths like .claude/hooks/.... Relative paths break when Claude Code's working directory changes (e.g., when opening a subdirectory). The $CLAUDE_PROJECT_DIR environment variable always resolves to the project root where .claude/settings.json lives.

Customizing

  • Disable a hook: Remove its entry from settings.json
  • SessionEnd timeout: Set CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 for longer Neo4j ingest
  • Neo4j credentials: Hooks read from GraphRAG/config.yaml automatically

Troubleshooting

Cheatsheet not appearing

  • Verify .claude/settings.json exists in the project root (not user home)
  • Run manually: python .claude/hooks/agentux-cheatsheet.py
  • Check for Python errors (encoding issues on Windows are handled by the UTF-8 wrapper)

Knowledge queue not clearing

  • Check Neo4j is running: python neo4j_check.py
  • Entries persist when Neo4j is offline -- they will be processed next session
  • Run the ingest manually: python Scripts/import_test_knowledge.py

DA detection false positives

  • The threshold (3 indicators) can be raised by editing THRESHOLD in agentux-da-detect.py
  • Prompts under 100 characters are never checked

"can't open file" error in subdirectory

  • If you see can't open file '.claude/hooks/agentux-*.py': No such file or directory, your hook commands are using relative paths
  • Fix: Change all hook commands in .claude/settings.json to use $CLAUDE_PROJECT_DIR: python "$CLAUDE_PROJECT_DIR/.claude/hooks/agentux-cheatsheet.py"
  • This ensures hooks resolve correctly regardless of which directory Claude Code is working in

Hook not firing

  • Type /hooks in Claude Code to verify hooks are loaded
  • Project-level settings.json must be valid JSON
  • Python must be on PATH