ansible-automation-eng…
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
Production-ready hook implementations with all safety patterns.
$ npx -y skills add notque/vexjoy-agent --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Production-ready hook implementations with all safety patterns.
Production-ready hook implementations with all safety patterns.
Complete template with comprehensive error handling and non-blocking execution.
#!/usr/bin/env python3
"""
Hook template with non-blocking execution patterns.
Always exits with code 0 to prevent blocking Claude Code.
"""
import json
import sys
import traceback
from pathlib import Path
from datetime import datetime
def debug_log(message):
"""Log debug information without blocking execution."""
try:
with open('/tmp/claude_hook_debug.log', 'a') as f:
f.write(f"[{datetime.now().isoformat()}] {message}\n")
except Exception:
pass # Never let logging block execution
def process_event(event_data):
"""
Process the event and return result.
Args:
event_data: Parsed JSON from Claude Code event
Returns:
dict: Result to output (or None)
"""
# Implement your hook logic here
tool_name = event_data.get('tool', '')
tool_output = event_data.get('output', '')
debug_log(f"Processing {tool_name} event")
# Example: Detect errors in tool output
if 'error' in tool_output.lower():
debug_log(f"Error detected in {tool_name}")
return {'detected': True, 'tool': tool_name}
return None
def main():
"""Main hook execution with comprehensive error handling."""
try:
# Parse input JSON from Claude Code
input_data = json.loads(sys.stdin.read())
# Process the event (implement specific logic here)
result = process_event(input_data)
# Output result if needed
if result:
print(json.dumps(result))
except json.JSONDecodeError as e:
debug_log(f"JSON parsing error: {e}")
except Exception as e:
debug_log(f"Unexpected error: {e}\\n{traceback.format_exc()}")
finally:
# CRITICAL: Always exit 0 to prevent blocking Claude Code
sys.exit(0)
if __name__ == "__main__":
main()---
Complete PostToolUse:Agent hook that records one dispatch per event.
#!/usr/bin/env python3
"""
PostToolUse:Agent hook. Records one routing decision per Agent dispatch.
Reads the dispatch marker from the tool input, writes one row, exits 0 on
every path. A telemetry write is never worth blocking a tool on.
"""
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent / "lib"))
from learning_db_v2 import record_evidence_route_decision
from stdin_timeout import read_stdin
DEBUG_LOG = Path("/tmp/claude_hook_debug.log")
def debug_log(message):
"""Log without ever raising."""
try:
with DEBUG_LOG.open("a") as f:
f.write(f"{message}\n")
except Exception:
pass
def extract_route(event):
"""Pull agent, skill, and marker out of the event.
Returns None when the event carries no marker: route-fit scoring reads one
marker per event, so an unmarked dispatch is not a recordable decision.
"""
tool_input = event.get("tool_input", {})
marker = tool_input.get("marker") or event.get("marker")
if not marker:
return None
return {
"marker": marker,
"agent": tool_input.get("subagent_type"),
"skill": tool_input.get("skill"),
"session_id": event.get("session_id"),
}
def main():
try:
event = json.loads(read_stdin())
route = extract_route(event)
if route:
record_evidence_route_decision(**route)
debug_log(f"[routing-recorder] recorded {route['agent']}:{route['skill']}")
except Exception as exc:
debug_log(f"[routing-recorder] {exc}")
finally:
sys.exit(0)
if __name__ == "__main__":
main()**What makes this correct**: one marker per event, every failure path swallowed, `sys.exit(0)` in a `finally` so no code path can exit non-zero, and no write outside the telemetry store.
---
Hook that scores a pending outcome on the next user turn.
#!/usr/bin/env python3
"""
UserPromptSubmit hook. Scores the pending routing outcome three ways.
Deterministic and free: failure on errors or rejection, success on explicit
acceptance, neutral otherwise. Silence is neutral, never acceptance.
"""
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent / "lib"))
from learning_db_v2 import update_evidence_route_outcome
from stdin_timeout import read_stdin
REJECTION_MARKERS = ("that's wrong", "no, ", "revert", "undo that")
ACCEPTANCE_MARKERS = ("thanks", "perfect", "ship it")
TASK_VERBS = ("add", "fix", "write", "run", "check", "make")
MAX_CLAUSE_WORDS = 8
def score(prompt, had_errors):
"""Return success, failure, or neutral.
The asymmetry decides the guards: a missed acceptance stays neutral and
costs nothing, while a false acceptance corrupts the telemetry. So the
acceptance path carries stacked precision guards and the neutral path
carries none.
"""
text = prompt.strip().lower()
if had_errors:
return "failure"
if any(text.startswith(m) for m in REJECTION_MARKERS):
return "failure"
for marker in ACCEPTANCE_MARKERS:
if not text.startswith(marker):
continue
rest = text[len(marker):].lstrip(" ,.!")
if not rest:
return "success"
if rest.split()[0] in TASK_VERBS: # new instruction, not praise
return "neutral"
if len(rest.split()) > MAX_CLAUSE_WORDS:
return "neutral"
return "success"
return "neutral"
def main():
try:
event = json.loads(read_stdin())
marker = event.get("pending_marker")
if marker:
outcome = score(event.get("prompt", ""), event.get("had_errors", False))
update_evidence_route_outcome(marker=marker, outcome=outcome)
except Exception:Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.
Repo: notque/vexjoy-agent
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
**Scope**: Module selection patterns, builtin vs command/shell decisions, collection modules, and version-specific module changes **Version range**:…
**Scope**: Molecule test scenarios, ansible-lint rules, idempotency validation, and check-mode patterns **Version range**: Molecule 6.0+ / ansible-lint 6.0+ /…
Universal rules injected by /do at dispatch. Each agent's .md file supplies domain rules.
**Scope**: Failure modes in agent output style — over-reporting, self-congratulation, verbose narration, and hedging. Covers what to detect and how to fix…
Zero-dependency combat visual upgrades: CSS particle replacement, Framer Motion combat juice, CSS 3D card transforms.