status

Check GDL health and diagnose issues — platform diagnostics, root resolution, setup status, scope conflicts, artifact inventory, and interactive investigation tools

/greppable:status — Health Check

Check GDL configuration, platform compatibility, and artifact health for the current project. Before running any bash blocks, tell the user: "Gathering status information..."

Run the bash block below, then present the results as a condensed summary table (one row per category: Platform, Root, Mode, Version, Artifacts, Memory, Duplicates, Hooks, Setup). Keep it tight — the user wants a quick health check, not verbose output.

Status Dump

# Resolve plugin root with fallback (MUST be before any source calls)
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/greppable*/greppable/[0-9]* 2>/dev/null | sort -V | tail -1)}"
if [[ -z "$PLUGIN_ROOT" || ! -d "$PLUGIN_ROOT" ]]; then
  echo "Error: Cannot resolve plugin root (CLAUDE_PLUGIN_ROOT=${CLAUDE_PLUGIN_ROOT:-unset}, cache lookup failed)." >&2
  echo "  Reinstall greppable: claude plugins install greppable" >&2
  exit 1
fi
source "${PLUGIN_ROOT}/lib/session-context.sh"
RESOLVED_ROOT=$(gdl_find_root ".")
PROJECT_CFG="$RESOLVED_ROOT/.claude/greppable.local.md"
GLOBAL_CFG="$HOME/.claude/greppable.local.md"
echo "=== GDL Status ==="
echo ""
echo "## Platform"
OS=$(uname -s)
case "$OS" in
  MINGW*|MSYS*) echo "  OS: Windows (Git Bash)" ;;
  Darwin*)      echo "  OS: macOS" ;;
  Linux*)       echo "  OS: Linux" ;;
  *)            echo "  OS: $OS" ;;
esac
echo "  Bash: $BASH_VERSION"
if command -v node &>/dev/null; then
  echo "  Node.js: $(node --version)"
else
  echo "  Node.js: not found (needed for session2gdlm)"
fi
CLAUDE_PATH="not found"
if command -v claude &>/dev/null; then
  CLAUDE_PATH=$(command -v claude)
elif command -v claude.exe &>/dev/null; then
  CLAUDE_PATH=$(command -v claude.exe)
fi
echo "  Claude CLI: $CLAUDE_PATH"
echo ""
echo "## Root Resolution"
echo "  CWD: $(pwd)"
echo "  Resolved root: $RESOLVED_ROOT"
if [[ -f "$RESOLVED_ROOT/.claude/greppable.local.md" ]]; then
  echo "  Method: config-walk (.claude/greppable.local.md found)"
elif git -C "$RESOLVED_ROOT" rev-parse --show-toplevel &>/dev/null; then
  echo "  Method: git-root fallback"
else
  echo "  Method: cwd-fallback (no config or git repo found)"
fi
echo ""
echo "## Configuration"
if [[ -f "$GLOBAL_CFG" ]]; then
  echo "  Global config: $GLOBAL_CFG"
  echo "    gdl_root: $(gdl_config_val "$GLOBAL_CFG" gdl_root)"
else
  echo "  Global config: not found"
fi
if [[ -f "$PROJECT_CFG" ]]; then
  echo "  Project config: $PROJECT_CFG (wins on conflict)"
  echo "    gdl_root: $(gdl_config_val "$PROJECT_CFG" gdl_root)"
else
  echo "  Project config: not found"
fi
echo ""
echo "## Hook Health"
HOOKS_JSON="${PLUGIN_ROOT}/hooks/hooks.json"
SESSION_START="${PLUGIN_ROOT}/hooks/session-start.sh"
HOOK_MJS="${PLUGIN_ROOT}/scripts/session2gdlm/dist/hook.mjs"
[[ -f "$HOOKS_JSON" ]] && echo "  hooks.json: OK" || echo "  hooks.json: MISSING"
[[ -f "$SESSION_START" ]] && echo "  session-start.sh: OK" || echo "  session-start.sh: MISSING"
[[ -f "$HOOK_MJS" ]] && echo "  hook.mjs (bundle): OK" || echo "  hook.mjs (bundle): MISSING"
echo ""
PLUGIN_JSON="${PLUGIN_ROOT}/.claude-plugin/plugin.json"
if [[ -f "$PLUGIN_JSON" ]]; then
  VERSION=$(grep '"version"' "$PLUGIN_JSON" | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
  echo "## Version: $VERSION"
else
  echo "## Version: unknown"
fi
echo ""
echo "## Scope Check"
PLUGIN_CACHE_BASE=$(dirname "${PLUGIN_ROOT}" 2>/dev/null)
if [[ -d "$PLUGIN_CACHE_BASE" ]]; then
  INSTALLED_VERSIONS=()
  INSTALLED_PATHS=()
  while IFS= read -r ver_dir; do
    [[ -z "$ver_dir" ]] && continue
    ver_pj="$ver_dir/.claude-plugin/plugin.json"
    if [[ -f "$ver_pj" ]]; then
      ver=$(grep '"version"' "$ver_pj" | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
      INSTALLED_VERSIONS+=("$ver")
      INSTALLED_PATHS+=("$ver_dir")
    fi
  done <<< "$(find "$PLUGIN_CACHE_BASE" -maxdepth 1 -mindepth 1 -type d 2>/dev/null)"
  if (( ${#INSTALLED_VERSIONS[@]} > 1 )); then
    echo "  Multiple installations detected:"
    for i in "${!INSTALLED_VERSIONS[@]}"; do
      active=""
      [[ "${INSTALLED_PATHS[$i]}" == "${PLUGIN_ROOT}" ]] && active=" <- active"
      echo "    v${INSTALLED_VERSIONS[$i]} at ${INSTALLED_PATHS[$i]}${active}"
    done
  elif (( ${#INSTALLED_VERSIONS[@]} == 1 )); then
    echo "  v${INSTALLED_VERSIONS[0]} -- single installation, no conflicts"
  else
    echo "  Could not detect installed versions"
  fi
else
  echo "  Plugin cache not accessible"
fi
echo ""
SCOPE=""
if [[ -f "$PROJECT_CFG" ]]; then
  SCOPE="project"
elif [[ -f "$GLOBAL_CFG" ]]; then
  SCOPE="global"
fi
echo "## Scope"
if [[ -z "$SCOPE" ]]; then
  echo "  Config: unconfigured (auto-enabled if artifacts exist)"
else
  echo "  Config: $SCOPE scope"
fi
echo ""
echo "## Artifacts"
GDL_ROOT_VAL=$(gdl_config_val "$PROJECT_CFG" gdl_root 2>/dev/null)
[[ -z "$GDL_ROOT_VAL" ]] && GDL_ROOT_VAL=$(gdl_config_val "$GLOBAL_CFG" gdl_root 2>/dev/null)
[[ -z "$GDL_ROOT_VAL" ]] && GDL_ROOT_VAL="docs/gdl"
ARTIFACT_DIR="$RESOLVED_ROOT/$GDL_ROOT_VAL"
echo "  Root: $ARTIFACT_DIR"
gdl_scan_artifacts "$ARTIFACT_DIR"
echo ""
echo "## Memory Extraction"
MEMORY_VAL=""
if [[ -f "$PROJECT_CFG" ]]; then
  MEMORY_VAL=$(gdl_config_val "$PROJECT_CFG" memory 2>/dev/null)
fi
if [[ -z "$MEMORY_VAL" && -f "$GLOBAL_CFG" ]]; then
  MEMORY_VAL=$(gdl_config_val "$GLOBAL_CFG" memory 2>/dev/null)
fi
SESSION_GDLM_COUNT=$(find "$ARTIFACT_DIR" -name '*.session.gdlm' 2>/dev/null | wc -l | tr -d ' ')
if [ "$MEMORY_VAL" = "true" ]; then
  if (( SESSION_GDLM_COUNT > 0 )); then
    echo "  Memory extraction: working ($SESSION_GDLM_COUNT .session.gdlm files)"
  else
    echo "  Memory extraction: enabled but not yet active (no .session.gdlm files)"
  fi
else
  echo "  Memory extraction: disabled (memory: ${MEMORY_VAL:-unset}) -- toggle with /greppable:memory"
fi
echo ""
echo "## Duplicate Detection"
DUPES=$(find "$RESOLVED_ROOT" -type d -name "gdl" -path "*/docs/gdl" 2>/dev/null | grep -v "$GDL_ROOT_VAL" || true)
if [[ -n "$DUPES" ]]; then
  echo "  WARNING: GDL artifact directories found outside resolved root:"
  echo "$DUPES" | sed 's/^/    /'
else
  echo "  No duplicate artifact directories found"
fi
echo ""
echo "## Setup Status"
if [[ -f "$PROJECT_CFG" ]] || [[ -f "$RESOLVED_ROOT/.claude/greppable.project.md" ]]; then
  echo "  Onboarding: complete"
else
  echo "  Onboarding: not done -- Run /greppable:onboard"
fi
if find "$ARTIFACT_DIR" \( -name '*.gdlc' -o -name '*.gdls' \) -print -quit 2>/dev/null | grep -q .; then
  echo "  Discovery: complete"
else
  echo "  Discovery: not done -- Run /greppable:discover"
fi

Interactive Investigation

After presenting the status dump above, offer the user these investigation options:


Want to investigate further?

[1] Check hooks firing -- execute session-start.sh and report output/errors [2] Check latest version -- fetch latest GitHub release and compare (requires gh auth or public repo) [3] Inspect memory extraction -- review session2gdlm logs and recent extraction output [4] Check stale code maps -- scan .gdlc files against source for staleness [5] GDL validation (lint check) -- run format validation across all artifacts

Wait for the user to pick an option before running anything below.

Option 1: Check Hooks Firing

Run this bash script and report the results to the user:

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/greppable*/greppable/[0-9]* 2>/dev/null | sort -V | tail -1)}"
if [[ -z "$PLUGIN_ROOT" || ! -d "$PLUGIN_ROOT" ]]; then echo "Error: plugin root not found" >&2; exit 1; fi
source "${PLUGIN_ROOT}/lib/session-context.sh"
echo "### Hook Firing Test"
echo ""
SESSION_START="${PLUGIN_ROOT}/hooks/session-start.sh"
if [ -f "$SESSION_START" ]; then
  echo "Executing session-start.sh..."
else
  echo "BLOCKED: session-start.sh not found at $SESSION_START"
  echo "  Reinstall greppable plugin"
  exit 1
fi
echo ""
START_TIME=$(date +%s%N 2>/dev/null || date +%s)
OUTPUT=$(bash "$SESSION_START" 2>&1)
EXIT_CODE=$?
END_TIME=$(date +%s%N 2>/dev/null || date +%s)
if [[ "$START_TIME" =~ ^[0-9]{10,}$ ]]; then
  DURATION_MS=$(( (END_TIME - START_TIME) / 1000000 ))
  echo "Duration: ${DURATION_MS}ms"
else
  echo "Duration: <1s"
fi
echo "Exit code: $EXIT_CODE"
echo ""
if [ "$EXIT_CODE" -eq 0 ]; then
  echo "Hook executed successfully"
  echo ""
  if [ -z "$OUTPUT" ]; then
    echo "No output (normal for new/unconfigured projects -- hook exits silently when no config found)"
  else
    echo "Output preview:"
    echo "$OUTPUT" | head -30
    echo ""
    if echo "$OUTPUT" | grep -q "hookSpecificOutput"; then
      echo "Output contains hookSpecificOutput (context injection working)"
    else
      echo "WARNING: Output present but missing hookSpecificOutput -- context may not be injected"
    fi
  fi
else
  echo "Hook FAILED (exit code $EXIT_CODE)"
  echo ""
  echo "Error output:"
  echo "$OUTPUT"
  echo ""
  if echo "$OUTPUT" | grep -qi "permission denied"; then
    echo "Diagnosis: Permission denied -- chmod +x $SESSION_START"
  elif echo "$OUTPUT" | grep -qi "command not found"; then
    echo "Diagnosis: Missing dependency -- a required command is not installed"
  elif echo "$OUTPUT" | grep -qi "CLAUDE_PLUGIN_ROOT"; then
    echo "Diagnosis: CLAUDE_PLUGIN_ROOT not set (see greppable#77)"
  elif echo "$OUTPUT" | grep -qi "No such file"; then
    echo "Diagnosis: File not found -- plugin installation may be incomplete"
  else
    echo "Diagnosis: Unknown error -- review the output above"
  fi
fi

Option 2: Check Latest Version

Run this bash script and report the results to the user. Note: requires gh CLI authenticated against the greppable repo (works once repo is public, or if user has private access).

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/greppable*/greppable/[0-9]* 2>/dev/null | sort -V | tail -1)}"
if [[ -z "$PLUGIN_ROOT" || ! -d "$PLUGIN_ROOT" ]]; then echo "Error: plugin root not found" >&2; exit 1; fi
echo "### Version Check"
echo ""
PLUGIN_JSON="${PLUGIN_ROOT}/.claude-plugin/plugin.json"
INSTALLED="unknown"
if [ -f "$PLUGIN_JSON" ]; then
  INSTALLED=$(grep '"version"' "$PLUGIN_JSON" | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
fi
echo "Installed: $INSTALLED"
if command -v gh &>/dev/null; then
  LATEST_JSON=$(gh api repos/greppable/greppable/releases/latest 2>/dev/null)
  if [ -n "$LATEST_JSON" ]; then
    LATEST=$(echo "$LATEST_JSON" | node -e "process.stdin.on('data',d=>{try{console.log(JSON.parse(d).tag_name.replace(/^v/,''))}catch{console.log('unknown')}})" 2>/dev/null)
    echo "Latest:    $LATEST"
    echo ""
    if [ "$INSTALLED" = "$LATEST" ]; then
      echo "You are running the latest version"
    elif [ "$LATEST" != "unknown" ]; then
      echo "Update available"
      echo ""
      echo "To upgrade, run:"
      echo "  claude plugins update greppable"
      echo ""
      echo "Release notes: https://github.com/greppable/greppable-cc-plugin/releases/tag/v${LATEST}"
      echo ""
      echo "Note: Local patches (e.g. Windows fixes from greppable#76) will be overwritten."
    fi
  else
    echo "Latest:    could not fetch (no GitHub releases found, or repo is private)"
    echo "  Requires: gh auth with repo access, and at least one GitHub Release"
  fi
else
  echo "Latest:    cannot check (gh CLI not available)"
fi

Option 3: Inspect Memory Extraction

Run this bash script and report the results to the user:

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/greppable*/greppable/[0-9]* 2>/dev/null | sort -V | tail -1)}"
if [[ -z "$PLUGIN_ROOT" || ! -d "$PLUGIN_ROOT" ]]; then echo "Error: plugin root not found" >&2; exit 1; fi
source "${PLUGIN_ROOT}/lib/session-context.sh"
echo "### Memory Extraction Inspector"
echo ""
RESOLVED_ROOT=$(gdl_find_root ".")
PROJECT_CFG="$RESOLVED_ROOT/.claude/greppable.local.md"
GLOBAL_CFG="$HOME/.claude/greppable.local.md"
MEMORY_ENABLED="false"
if [ -f "$PROJECT_CFG" ]; then
  val=$(gdl_config_val "$PROJECT_CFG" memory 2>/dev/null)
  [ -n "$val" ] && MEMORY_ENABLED="$val"
fi
if [ "$MEMORY_ENABLED" = "false" ] && [ -f "$GLOBAL_CFG" ]; then
  val=$(gdl_config_val "$GLOBAL_CFG" memory 2>/dev/null)
  [ -n "$val" ] && MEMORY_ENABLED="$val"
fi
echo "Memory enabled: $MEMORY_ENABLED"
if [ "$MEMORY_ENABLED" != "true" ]; then
  echo "  Memory extraction is OFF. Enable with /greppable:memory"
  echo ""
fi
LOG_FILE="$RESOLVED_ROOT/.claude/session2gdlm.log"
test -f "$LOG_FILE" || LOG_FILE="$HOME/.claude/session2gdlm.log"
if [ -f "$LOG_FILE" ]; then
  echo "Log file: $LOG_FILE"
  LINE_COUNT=$(wc -l < "$LOG_FILE" | tr -d ' ')
  echo "Log lines: $LINE_COUNT"
  echo ""
  HOOK_STARTS=$(grep -c "hook started" "$LOG_FILE" 2>/dev/null || echo "0")
  echo "Total hook starts: $HOOK_STARTS"
  SUCCESSES=$(grep -ci "wrote.*session.gdlm" "$LOG_FILE" 2>/dev/null || echo "0")
  echo "Successful extractions: $SUCCESSES"
  FALLBACKS=$(grep -c "fallback\|LLM.*unavailable\|Auto-extracted" "$LOG_FILE" 2>/dev/null || echo "0")
  if [ "$FALLBACKS" -gt 0 ]; then
    echo "WARNING: Fallback stubs: $FALLBACKS (LLM summarisation failed)"
  fi
  RACE_SKIPS=$(grep -c "skipped.*lock\|EEXIST" "$LOG_FILE" 2>/dev/null || echo "0")
  if [ "$RACE_SKIPS" -gt 0 ]; then
    echo "Lock skips: $RACE_SKIPS (expected — dedup working correctly)"
  fi
  META_SKIPS=$(grep -c "meta-session\|self-exclusion\|extraction marker" "$LOG_FILE" 2>/dev/null || echo "0")
  if [ "$META_SKIPS" -gt 0 ]; then
    echo "Meta-session skips: $META_SKIPS (correctly self-excluded)"
  fi
  echo ""
  echo "Last 10 log entries:"
  tail -10 "$LOG_FILE"
else
  echo "Log file: not found"
  echo "  Memory extraction may not have run yet."
  echo "  Expected locations:"
  echo "    $RESOLVED_ROOT/.claude/session2gdlm.log"
  echo "    $HOME/.claude/session2gdlm.log"
fi
echo ""
GDL_ROOT_VAL=$(gdl_config_val "$PROJECT_CFG" gdl_root 2>/dev/null)
test -z "$GDL_ROOT_VAL" && GDL_ROOT_VAL=$(gdl_config_val "$GLOBAL_CFG" gdl_root 2>/dev/null)
test -z "$GDL_ROOT_VAL" && GDL_ROOT_VAL="docs/gdl"
MEMORY_DIR="$RESOLVED_ROOT/$GDL_ROOT_VAL/memory/active"
echo "Memory output dir: $MEMORY_DIR"
if [ -d "$MEMORY_DIR" ]; then
  SESSION_FILES=$(find "$MEMORY_DIR" -name '*.session.gdlm' 2>/dev/null | sort -t/ -k99 | tail -5)
  SEED_FILES=$(find "$MEMORY_DIR" -name '*.seed.gdlm' 2>/dev/null)
  test -n "$SEED_FILES" && echo "  Seed files: $(echo "$SEED_FILES" | wc -l | tr -d ' ')"
  if [ -n "$SESSION_FILES" ]; then
    echo "  Session files (most recent 5):"
    while IFS= read -r f; do
      test -z "$f" && continue
      RECORDS=$(grep -c '^@memory' "$f" 2>/dev/null || echo "0")
      CONFIDENCE=$(grep -o 'confidence:[a-z]*' "$f" 2>/dev/null | sort | uniq -c | tr '\n' ', ' | sed 's/, $//')
      echo "    $(basename "$f") -- $RECORDS records ($CONFIDENCE)"
    done <<< "$SESSION_FILES"
  else
    echo "  No .session.gdlm files found"
  fi
else
  echo "  Directory does not exist"
  echo "  Run /greppable:discover to create the directory structure"
fi

Option 4: Check Stale Code Maps

Run this bash script and report the results to the user. Note: this can take a while on large projects as it scans source directories for each .gdlc module.

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/greppable*/greppable/[0-9]* 2>/dev/null | sort -V | tail -1)}"
if [[ -z "$PLUGIN_ROOT" || ! -d "$PLUGIN_ROOT" ]]; then echo "Error: plugin root not found" >&2; exit 1; fi
source "${PLUGIN_ROOT}/lib/session-context.sh"
echo "### Stale Code Map Detection"
echo ""
RESOLVED_ROOT=$(gdl_find_root ".")
PROJECT_CFG="$RESOLVED_ROOT/.claude/greppable.local.md"
GLOBAL_CFG="$HOME/.claude/greppable.local.md"
GDL_ROOT_VAL=$(gdl_config_val "$PROJECT_CFG" gdl_root 2>/dev/null)
test -z "$GDL_ROOT_VAL" && GDL_ROOT_VAL=$(gdl_config_val "$GLOBAL_CFG" gdl_root 2>/dev/null)
test -z "$GDL_ROOT_VAL" && GDL_ROOT_VAL="docs/gdl"
ARTIFACT_DIR="$RESOLVED_ROOT/$GDL_ROOT_VAL"
stale_count=0
total_count=0
while IFS= read -r gdlc_file; do
  [ -z "$gdlc_file" ] && continue
  total_count=$((total_count + 1))
  while IFS= read -r mod_line; do
    [ -z "$mod_line" ] && continue
    mod_path=$(echo "$mod_line" | sed 's/^@D //' | sed 's/|.*//')
    [ -z "$mod_path" ] && continue
    abs_mod_path="$RESOLVED_ROOT/$mod_path"
    test -d "$abs_mod_path" || test -f "$abs_mod_path" || continue
    newest_source=$(find "$abs_mod_path" -type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.py' -o -name '*.go' -o -name '*.java' -o -name '*.rs' -o -name '*.rb' -o -name '*.php' -o -name '*.cs' -o -name '*.c' -o -name '*.cpp' -o -name '*.kt' -o -name '*.swift' \) -newer "$gdlc_file" 2>/dev/null | head -1)
    if [ -n "$newest_source" ]; then
      echo "  STALE: $(basename "$gdlc_file") -- source in $mod_path is newer"
      stale_count=$((stale_count + 1))
      break
    fi
  done <<< "$(grep '^@D ' "$gdlc_file" 2>/dev/null || true)"
done <<< "$(find "$ARTIFACT_DIR" -name '*.gdlc' 2>/dev/null || true)"
echo ""
if [ "$stale_count" -eq 0 ]; then
  echo "All $total_count .gdlc code maps are current"
else
  echo "$stale_count of $total_count code map(s) are stale -- consider re-running /greppable:discover"
fi

Option 5: GDL Validation (Lint Check)

Run this bash script and report the results to the user. Note: validates every line of every GDL artifact file — can be slow on large projects.

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/greppable*/greppable/[0-9]* 2>/dev/null | sort -V | tail -1)}"
if [[ -z "$PLUGIN_ROOT" || ! -d "$PLUGIN_ROOT" ]]; then echo "Error: plugin root not found" >&2; exit 1; fi
source "${PLUGIN_ROOT}/lib/session-context.sh"
echo "### GDL Validation (Lint Check)"
echo ""
RESOLVED_ROOT=$(gdl_find_root ".")
PROJECT_CFG="$RESOLVED_ROOT/.claude/greppable.local.md"
GLOBAL_CFG="$HOME/.claude/greppable.local.md"
GDL_ROOT_VAL=$(gdl_config_val "$PROJECT_CFG" gdl_root 2>/dev/null)
test -z "$GDL_ROOT_VAL" && GDL_ROOT_VAL=$(gdl_config_val "$GLOBAL_CFG" gdl_root 2>/dev/null)
test -z "$GDL_ROOT_VAL" && GDL_ROOT_VAL="docs/gdl"
ARTIFACT_DIR="$RESOLVED_ROOT/$GDL_ROOT_VAL"
if [ -d "$ARTIFACT_DIR" ]; then
  echo "Scanning: $ARTIFACT_DIR"
  echo ""
  bash "${PLUGIN_ROOT}/scripts/gdl-lint.sh" --all "$ARTIFACT_DIR" --strict --exclude='*/tests/fixtures/*' 2>&1
else
  echo "No artifact directory found at $ARTIFACT_DIR"
fi