diff --git a/plugins/claude-code/commands/oac-setup.md b/plugins/claude-code/commands/oac-setup.md
index 01d0a1d..3b20752 100644
--- a/plugins/claude-code/commands/oac-setup.md
+++ b/plugins/claude-code/commands/oac-setup.md
@@ -11,7 +11,7 @@ Download context files from the OpenAgents Control repository to enable context-
## Download Progress
-!`bash ${CLAUDE_PLUGIN_ROOT}/scripts/download-context.sh $ARGUMENTS`
+!`${CLAUDE_PLUGIN_ROOT}/scripts/download-context.sh $ARGUMENTS`
## What Was Downloaded
diff --git a/plugins/claude-code/hooks/session-start.sh b/plugins/claude-code/hooks/session-start.sh
index 09d397d..521523d 100644
--- a/plugins/claude-code/hooks/session-start.sh
+++ b/plugins/claude-code/hooks/session-start.sh
@@ -1,226 +1,47 @@
-#!/bin/bash
+#!/usr/bin/env bash
# SessionStart hook for OAC plugin
-# Injects using-oac skill and checks .tmp cleanup, .oac config, and context installation
set -euo pipefail
-# Resolve plugin root directory
-PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
+# Determine plugin root directory
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
+PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
SKILL_FILE="${PLUGIN_ROOT}/skills/using-oac/SKILL.md"
-TMP_SESSIONS_DIR=".tmp/sessions"
-CONTEXT_MANIFEST=".context-manifest.json"
-OAC_EXAMPLE="${PLUGIN_ROOT}/.oac.example"
-# Load using-oac skill content
-if [[ ! -f "${SKILL_FILE}" ]]; then
- echo '{"error": "using-oac skill not found at '"${SKILL_FILE}"'"}' >&2
- exit 1
+# Read using-oac content
+using_oac_content=$(cat "${SKILL_FILE}" 2>&1 || echo "Error reading using-oac skill")
+
+# Escape string for JSON embedding using bash parameter substitution
+# Each ${s//old/new} is a single C-level pass - orders of magnitude
+# faster than character-by-character loop
+escape_for_json() {
+ local s="$1"
+ s="${s//\\/\\\\}"
+ s="${s//\"/\\\"}"
+ s="${s//$'\n'/\\n}"
+ s="${s//$'\r'/\\r}"
+ s="${s//$'\t'/\\t}"
+ printf '%s' "$s"
+}
+
+using_oac_escaped=$(escape_for_json "$using_oac_content")
+
+# Build warning message for first-time users
+warning_message=""
+if [[ ! -f ".context-manifest.json" ]]; then
+ warning_message="\n\nIN YOUR FIRST REPLY AFTER SEEING THIS MESSAGE YOU MUST TELL THE USER:👋 **Welcome to OpenAgents Control!** To get started, run /oac:setup to download context files. Then use /oac:help to learn the 6-stage workflow."
fi
-SKILL_CONTENT=$(cat "${SKILL_FILE}")
+warning_escaped=$(escape_for_json "$warning_message")
-# Escape for JSON using parameter substitution (fast method)
-# Replace backslash, double-quote, newline, tab, carriage return
-SKILL_CONTENT="${SKILL_CONTENT//\\/\\\\}" # Backslash
-SKILL_CONTENT="${SKILL_CONTENT//\"/\\\"}" # Double-quote
-SKILL_CONTENT="${SKILL_CONTENT//$'\n'/\\n}" # Newline
-SKILL_CONTENT="${SKILL_CONTENT//$'\t'/\\t}" # Tab
-SKILL_CONTENT="${SKILL_CONTENT//$'\r'/\\r}" # Carriage return
-
-# Check for .oac configuration
-CONFIG_EXISTS=false
-CONFIG_LOCATION=""
-RECOMMENDATIONS=()
-
-if [[ -f ".oac" ]]; then
- CONFIG_EXISTS=true
- CONFIG_LOCATION="project (.oac)"
-elif [[ -f "$HOME/.oac" ]]; then
- CONFIG_EXISTS=true
- CONFIG_LOCATION="global (~/.oac)"
-else
- RECOMMENDATIONS+=("Copy .oac.example to .oac to customize settings")
-fi
-
-# Check for context installation
-CONTEXT_INSTALLED=false
-CONTEXT_AGE_DAYS=0
-CONTEXT_WARNING=""
-
-if [[ -f "${CONTEXT_MANIFEST}" ]]; then
- CONTEXT_INSTALLED=true
-
- # Check age of context manifest (>30 days = suggest update)
- if [[ "$(uname)" == "Darwin" ]]; then
- # macOS
- MANIFEST_MTIME=$(stat -f %m "${CONTEXT_MANIFEST}" 2>/dev/null || echo 0)
- else
- # Linux
- MANIFEST_MTIME=$(stat -c %Y "${CONTEXT_MANIFEST}" 2>/dev/null || echo 0)
- fi
-
- CURRENT_TIME=$(date +%s)
- CONTEXT_AGE_DAYS=$(( (CURRENT_TIME - MANIFEST_MTIME) / 86400 ))
-
- if [[ ${CONTEXT_AGE_DAYS} -gt 30 ]]; then
- CONTEXT_WARNING="⚠️ Context is ${CONTEXT_AGE_DAYS} days old. Consider running /oac:setup --core to update."
- RECOMMENDATIONS+=("Run /oac:setup --core to update context (${CONTEXT_AGE_DAYS} days old)")
- fi
-else
- RECOMMENDATIONS+=("Run /oac:setup --core to download context files")
-fi
-
-# Detect first-time user
-FIRST_TIME_USER=false
-if [[ "${CONFIG_EXISTS}" == "false" ]] && [[ "${CONTEXT_INSTALLED}" == "false" ]]; then
- FIRST_TIME_USER=true
-fi
-
-# Check .tmp/ cleanup needs
-CLEANUP_SCRIPT="${PLUGIN_ROOT}/scripts/cleanup-tmp.sh"
-CLEANUP_WARNING=""
-
-if [[ -x "${CLEANUP_SCRIPT}" ]]; then
- # Check for old .tmp files
- OLD_SESSIONS=0
- OLD_TASKS=0
- OLD_EXTERNAL=0
-
- # Count old sessions (>7 days)
- if [[ -d ".tmp/sessions" ]]; then
- OLD_SESSIONS=$(find ".tmp/sessions" -mindepth 1 -maxdepth 1 -type d -mtime +7 2>/dev/null | wc -l | tr -d ' ')
- fi
-
- # Count old completed tasks (>30 days)
- if [[ -d ".tmp/tasks" ]]; then
- for task_dir in .tmp/tasks/*; do
- if [[ ! -d "$task_dir" ]]; then continue; fi
-
- all_completed=true
- has_subtasks=false
-
- for subtask_file in "$task_dir"/subtask_*.json; do
- if [[ ! -f "$subtask_file" ]]; then continue; fi
- has_subtasks=true
-
- if ! grep -q '"status": "completed"' "$subtask_file" 2>/dev/null; then
- all_completed=false
- break
- fi
-
- if [[ $(find "$subtask_file" -mtime +30 2>/dev/null | wc -l) -eq 0 ]]; then
- all_completed=false
- break
- fi
- done
-
- if [[ "$has_subtasks" == "true" ]] && [[ "$all_completed" == "true" ]]; then
- ((OLD_TASKS++))
- fi
- done
- fi
-
- # Count old external context (>7 days)
- if [[ -d ".tmp/external-context" ]]; then
- OLD_EXTERNAL=$(find ".tmp/external-context" -mindepth 1 -maxdepth 1 -type d -mtime +7 2>/dev/null | wc -l | tr -d ' ')
- fi
-
- TOTAL_OLD=$((OLD_SESSIONS + OLD_TASKS + OLD_EXTERNAL))
-
- if [[ ${TOTAL_OLD} -gt 0 ]]; then
- CLEANUP_WARNING="⚠️ Found ${TOTAL_OLD} old temporary items (${OLD_SESSIONS} sessions, ${OLD_TASKS} tasks, ${OLD_EXTERNAL} external cache). Run cleanup script to review: bash ${CLEANUP_SCRIPT}"
- RECOMMENDATIONS+=("Run cleanup script to remove old temporary files")
- fi
-fi
-
-# Build context injection message
-CONTEXT_MESSAGE="# OpenAgents Control (OAC) Workflow
-
-**EXTREMELY_IMPORTANT**: This skill is automatically loaded for every development task.
-
-${SKILL_CONTENT}"
-
-# Add first-time user welcome
-if [[ "${FIRST_TIME_USER}" == "true" ]]; then
- CONTEXT_MESSAGE="${CONTEXT_MESSAGE}
-
----
-
-## 👋 Welcome to OpenAgents Control!
-
-This appears to be your first time using OAC. Here's how to get started:
-
-1. **Download context files**: Run \`/oac:setup --core\` to get coding standards and patterns
-2. **Customize settings**: Copy \`.oac.example\` to \`.oac\` to configure your preferences
-3. **Learn the workflow**: Run \`/oac:help\` to see the 6-stage development workflow
-
-Once context is installed, OAC will automatically discover relevant standards and patterns for every task."
-fi
-
-# Add context warning if needed
-if [[ -n "${CONTEXT_WARNING}" ]]; then
- CONTEXT_MESSAGE="${CONTEXT_MESSAGE}
-
----
-
-${CONTEXT_WARNING}"
-fi
-
-# Add cleanup warning if needed
-if [[ -n "${CLEANUP_WARNING}" ]]; then
- CONTEXT_MESSAGE="${CONTEXT_MESSAGE}
-
----
-
-${CLEANUP_WARNING}"
-fi
-
-# Escape context message for JSON
-CONTEXT_MESSAGE="${CONTEXT_MESSAGE//\\/\\\\}"
-CONTEXT_MESSAGE="${CONTEXT_MESSAGE//\"/\\\"}"
-CONTEXT_MESSAGE="${CONTEXT_MESSAGE//$'\n'/\\n}"
-CONTEXT_MESSAGE="${CONTEXT_MESSAGE//$'\t'/\\t}"
-CONTEXT_MESSAGE="${CONTEXT_MESSAGE//$'\r'/\\r}"
-
-# Build recommendations JSON array
-RECOMMENDATIONS_JSON="["
-FIRST_REC=true
-for rec in "${RECOMMENDATIONS[@]}"; do
- if [[ "${FIRST_REC}" == "true" ]]; then
- FIRST_REC=false
- else
- RECOMMENDATIONS_JSON="${RECOMMENDATIONS_JSON},"
- fi
- # Escape recommendation for JSON
- REC_ESCAPED="${rec//\\/\\\\}"
- REC_ESCAPED="${REC_ESCAPED//\"/\\\"}"
- RECOMMENDATIONS_JSON="${RECOMMENDATIONS_JSON}\"${REC_ESCAPED}\""
-done
-RECOMMENDATIONS_JSON="${RECOMMENDATIONS_JSON}]"
-
-# Output JSON with hookSpecificOutput format
+# Output context injection as JSON
cat <OAC workflow is active. Follow 6-stage process: Analyze, Plan & Approve, LoadContext, Execute, Validate, Complete.",
- "firstTimeUser": ${FIRST_TIME_USER},
- "contextInstalled": ${CONTEXT_INSTALLED},
- "contextAgeDays": ${CONTEXT_AGE_DAYS},
- "configExists": ${CONFIG_EXISTS},
- "configLocation": "${CONFIG_LOCATION}",
- "recommendations": ${RECOMMENDATIONS_JSON},
- "contextInjection": {
- "priority": "EXTREMELY_IMPORTANT",
- "content": "${CONTEXT_MESSAGE}"
- },
- "tmpCleanup": {
- "oldSessions": ${OLD_SESSIONS:-0},
- "oldTasks": ${OLD_TASKS:-0},
- "oldExternal": ${OLD_EXTERNAL:-0},
- "total": ${TOTAL_OLD:-0},
- "warning": "${CLEANUP_WARNING}"
- }
+ "additionalContext": "\nYou are using OpenAgents Control (OAC).\n\n**Below is the full content of your 'using-oac' skill - your guide to the 6-stage workflow. For all other skills, use the 'Skill' tool:**\n\n${using_oac_escaped}\n\n${warning_escaped}\n"
}
}
EOF
+
+exit 0