Add /log and /debug commands for troubleshooting
- /log command to view and analyze automation logs - Filter by pattern, date, or log type - List available log files - /debug command generates comprehensive debug report - Version, core files, state, memory, scripts status - Environment info (Python, kubectl) - Disk usage by directory - JSON output mode for scripting - Updated shell completions with 13 aliases total - Test suite now covers 21 tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,18 @@ _claude_history() {
|
||||
COMPREPLY=($(compgen -W "--list --show --stats --unsummarized --all --limit" -- "${cur}"))
|
||||
}
|
||||
|
||||
_claude_log() {
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
COMPREPLY=($(compgen -W "--list --tail --grep --since --type" -- "${cur}"))
|
||||
}
|
||||
|
||||
_claude_debug() {
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
COMPREPLY=($(compgen -W "--full --json --paths" -- "${cur}"))
|
||||
}
|
||||
|
||||
_claude_memory_add() {
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
local prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
@@ -52,6 +64,8 @@ complete -F _claude_memory_list memory-list.py
|
||||
complete -F _claude_restore restore.sh
|
||||
complete -F _claude_search search.py
|
||||
complete -F _claude_history history-browser.py
|
||||
complete -F _claude_log log-viewer.py
|
||||
complete -F _claude_debug debug.sh
|
||||
|
||||
# Alias completions for convenience
|
||||
alias claude-validate='~/.claude/automation/validate-setup.sh'
|
||||
@@ -66,8 +80,9 @@ alias claude-history='python3 ~/.claude/automation/history-browser.py'
|
||||
alias claude-install='~/.claude/automation/install.sh'
|
||||
alias claude-test='~/.claude/automation/test-scripts.sh'
|
||||
alias claude-maintenance='~/.claude/automation/daily-maintenance.sh'
|
||||
alias claude-log='python3 ~/.claude/automation/log-viewer.py'
|
||||
alias claude-debug='~/.claude/automation/debug.sh'
|
||||
|
||||
echo "Claude Code completions loaded. Available aliases:"
|
||||
echo " claude-validate, claude-status, claude-backup, claude-restore, claude-clean"
|
||||
echo " claude-memory-add, claude-memory-list, claude-search, claude-history"
|
||||
echo " claude-install, claude-test, claude-maintenance"
|
||||
echo " claude-{validate,status,backup,restore,clean,memory-add,memory-list}"
|
||||
echo " claude-{search,history,install,test,maintenance,log,debug}"
|
||||
|
||||
@@ -64,12 +64,33 @@ _claude_history() {
|
||||
'--limit[Limit results]:count:'
|
||||
}
|
||||
|
||||
# Log viewer completion
|
||||
_claude_log() {
|
||||
_arguments \
|
||||
'--list[List log files]' \
|
||||
'--tail[Number of lines]:count:' \
|
||||
'--grep[Filter pattern]:pattern:' \
|
||||
'--since[Since date]:date:' \
|
||||
'--type[Log type]:type:' \
|
||||
'*:file:'
|
||||
}
|
||||
|
||||
# Debug completion
|
||||
_claude_debug() {
|
||||
_arguments \
|
||||
'--full[Full debug report]' \
|
||||
'--json[JSON output]' \
|
||||
'--paths[Show paths only]'
|
||||
}
|
||||
|
||||
# Register completions
|
||||
compdef _memory_add memory-add.py
|
||||
compdef _memory_list memory-list.py
|
||||
compdef _claude_restore restore.sh
|
||||
compdef _claude_search search.py
|
||||
compdef _claude_history history-browser.py
|
||||
compdef _claude_log log-viewer.py
|
||||
compdef _claude_debug debug.sh
|
||||
|
||||
# Aliases
|
||||
alias claude-validate='~/.claude/automation/validate-setup.sh'
|
||||
@@ -84,7 +105,9 @@ alias claude-history='python3 ~/.claude/automation/history-browser.py'
|
||||
alias claude-install='~/.claude/automation/install.sh'
|
||||
alias claude-test='~/.claude/automation/test-scripts.sh'
|
||||
alias claude-maintenance='~/.claude/automation/daily-maintenance.sh'
|
||||
alias claude-log='python3 ~/.claude/automation/log-viewer.py'
|
||||
alias claude-debug='~/.claude/automation/debug.sh'
|
||||
|
||||
echo "Claude Code completions loaded (zsh)"
|
||||
echo " Aliases: claude-{validate,status,backup,restore,clean,memory-add,memory-list}"
|
||||
echo " claude-{search,history,install,test,maintenance}"
|
||||
echo " claude-{search,history,install,test,maintenance,log,debug}"
|
||||
|
||||
230
automation/debug.sh
Executable file
230
automation/debug.sh
Executable file
@@ -0,0 +1,230 @@
|
||||
#!/bin/bash
|
||||
# Debug script for troubleshooting Claude Code configuration
|
||||
# Usage: ./debug.sh [--full|--json|--paths]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CLAUDE_DIR="${HOME}/.claude"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { echo -e "${BLUE}ℹ${NC} $1"; }
|
||||
ok() { echo -e "${GREEN}✓${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}⚠${NC} $1"; }
|
||||
error() { echo -e "${RED}✗${NC} $1"; }
|
||||
|
||||
show_paths() {
|
||||
echo ""
|
||||
echo "=== Configuration Paths ==="
|
||||
echo ""
|
||||
echo "CLAUDE_DIR: ${CLAUDE_DIR}"
|
||||
echo ""
|
||||
echo "Key files:"
|
||||
echo " CLAUDE.md: ${CLAUDE_DIR}/CLAUDE.md"
|
||||
echo " plugin.json: ${CLAUDE_DIR}/.claude-plugin/plugin.json"
|
||||
echo " hooks.json: ${CLAUDE_DIR}/hooks/hooks.json"
|
||||
echo " registry.json: ${CLAUDE_DIR}/state/component-registry.json"
|
||||
echo ""
|
||||
echo "Memory:"
|
||||
echo " preferences: ${CLAUDE_DIR}/state/personal-assistant/memory/preferences.json"
|
||||
echo " decisions: ${CLAUDE_DIR}/state/personal-assistant/memory/decisions.json"
|
||||
echo " history index: ${CLAUDE_DIR}/state/personal-assistant/history/index.json"
|
||||
echo ""
|
||||
echo "Logs:"
|
||||
echo " maintenance: ${CLAUDE_DIR}/logs/maintenance-*.log"
|
||||
echo ""
|
||||
}
|
||||
|
||||
check_file() {
|
||||
local path="$1"
|
||||
local name="$2"
|
||||
if [[ -f "$path" ]]; then
|
||||
local size=$(stat -c %s "$path" 2>/dev/null || stat -f %z "$path" 2>/dev/null || echo "?")
|
||||
ok "$name ($size bytes)"
|
||||
return 0
|
||||
else
|
||||
error "$name (missing)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_json() {
|
||||
local path="$1"
|
||||
local name="$2"
|
||||
if [[ -f "$path" ]]; then
|
||||
if python3 -c "import json; json.load(open('$path'))" 2>/dev/null; then
|
||||
ok "$name (valid JSON)"
|
||||
return 0
|
||||
else
|
||||
error "$name (invalid JSON)"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
warn "$name (file missing)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_script() {
|
||||
local path="$1"
|
||||
local name="$2"
|
||||
if [[ -f "$path" ]]; then
|
||||
if [[ -x "$path" ]]; then
|
||||
ok "$name (executable)"
|
||||
else
|
||||
warn "$name (not executable)"
|
||||
fi
|
||||
else
|
||||
error "$name (missing)"
|
||||
fi
|
||||
}
|
||||
|
||||
show_summary() {
|
||||
echo ""
|
||||
echo "🔍 Claude Code Debug Report"
|
||||
echo " Generated: $(date)"
|
||||
echo ""
|
||||
|
||||
# Version
|
||||
echo "=== Version ==="
|
||||
if [[ -f "${CLAUDE_DIR}/VERSION" ]]; then
|
||||
echo " Version: $(cat "${CLAUDE_DIR}/VERSION")"
|
||||
else
|
||||
echo " Version: unknown"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Core files
|
||||
echo "=== Core Files ==="
|
||||
check_file "${CLAUDE_DIR}/CLAUDE.md" "CLAUDE.md"
|
||||
check_json "${CLAUDE_DIR}/.claude-plugin/plugin.json" "plugin.json"
|
||||
check_json "${CLAUDE_DIR}/hooks/hooks.json" "hooks.json"
|
||||
check_json "${CLAUDE_DIR}/state/component-registry.json" "component-registry.json"
|
||||
echo ""
|
||||
|
||||
# State files
|
||||
echo "=== State Files ==="
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant-preferences.json" "PA preferences"
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant/session-context.json" "Session context"
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant/general-instructions.json" "General instructions"
|
||||
check_json "${CLAUDE_DIR}/state/sysadmin/session-autonomy.json" "Sysadmin autonomy"
|
||||
echo ""
|
||||
|
||||
# Memory
|
||||
echo "=== Memory Files ==="
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant/memory/preferences.json" "Memory: preferences"
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant/memory/decisions.json" "Memory: decisions"
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant/memory/projects.json" "Memory: projects"
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant/memory/facts.json" "Memory: facts"
|
||||
check_json "${CLAUDE_DIR}/state/personal-assistant/history/index.json" "History index"
|
||||
echo ""
|
||||
|
||||
# Scripts
|
||||
echo "=== Key Scripts ==="
|
||||
check_script "${CLAUDE_DIR}/automation/validate-setup.sh" "validate-setup.sh"
|
||||
check_script "${CLAUDE_DIR}/automation/quick-status.sh" "quick-status.sh"
|
||||
check_script "${CLAUDE_DIR}/automation/backup.sh" "backup.sh"
|
||||
check_script "${CLAUDE_DIR}/automation/install.sh" "install.sh"
|
||||
check_script "${CLAUDE_DIR}/hooks/scripts/session-start.sh" "session-start.sh"
|
||||
echo ""
|
||||
|
||||
# Skills
|
||||
echo "=== Skills ==="
|
||||
skill_count=$(find "${CLAUDE_DIR}/skills" -name "SKILL.md" 2>/dev/null | wc -l)
|
||||
echo " Skills found: $skill_count"
|
||||
find "${CLAUDE_DIR}/skills" -name "SKILL.md" -exec dirname {} \; 2>/dev/null | while read dir; do
|
||||
echo " - $(basename "$dir")"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Commands
|
||||
echo "=== Commands ==="
|
||||
cmd_count=$(find "${CLAUDE_DIR}/commands" -name "*.md" ! -name "README.md" 2>/dev/null | wc -l)
|
||||
echo " Commands found: $cmd_count"
|
||||
echo ""
|
||||
|
||||
# Agents
|
||||
echo "=== Agents ==="
|
||||
agent_count=$(find "${CLAUDE_DIR}/agents" -name "*.md" ! -name "README.md" 2>/dev/null | wc -l)
|
||||
echo " Agent files found: $agent_count"
|
||||
echo ""
|
||||
|
||||
# Environment
|
||||
echo "=== Environment ==="
|
||||
echo " HOME: $HOME"
|
||||
echo " USER: ${USER:-$(whoami)}"
|
||||
echo " Shell: ${SHELL:-unknown}"
|
||||
echo " Python: $(python3 --version 2>&1 || echo 'not found')"
|
||||
if command -v kubectl &> /dev/null; then
|
||||
ok "kubectl installed"
|
||||
else
|
||||
warn "kubectl not found"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Disk usage
|
||||
echo "=== Disk Usage ==="
|
||||
total=$(du -sh "${CLAUDE_DIR}" 2>/dev/null | cut -f1)
|
||||
echo " Total: $total"
|
||||
echo ""
|
||||
echo " By directory:"
|
||||
du -sh "${CLAUDE_DIR}"/{agents,automation,commands,hooks,mcp,skills,state,workflows,logs,backups} 2>/dev/null | while read size dir; do
|
||||
echo " $(basename "$dir"): $size"
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
show_json() {
|
||||
echo "{"
|
||||
echo " \"version\": \"$(cat "${CLAUDE_DIR}/VERSION" 2>/dev/null || echo 'unknown')\","
|
||||
echo " \"timestamp\": \"$(date -Iseconds)\","
|
||||
echo " \"paths\": {"
|
||||
echo " \"claude_dir\": \"${CLAUDE_DIR}\","
|
||||
echo " \"home\": \"$HOME\""
|
||||
echo " },"
|
||||
|
||||
# Count components
|
||||
skill_count=$(find "${CLAUDE_DIR}/skills" -name "SKILL.md" 2>/dev/null | wc -l | tr -d ' ')
|
||||
cmd_count=$(find "${CLAUDE_DIR}/commands" -name "*.md" ! -name "README.md" 2>/dev/null | wc -l | tr -d ' ')
|
||||
agent_count=$(find "${CLAUDE_DIR}/agents" -name "*.md" ! -name "README.md" 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
echo " \"components\": {"
|
||||
echo " \"skills\": $skill_count,"
|
||||
echo " \"commands\": $cmd_count,"
|
||||
echo " \"agents\": $agent_count"
|
||||
echo " },"
|
||||
|
||||
# Check files
|
||||
files_ok=true
|
||||
for f in CLAUDE.md .claude-plugin/plugin.json hooks/hooks.json state/component-registry.json; do
|
||||
if [[ ! -f "${CLAUDE_DIR}/$f" ]]; then
|
||||
files_ok=false
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo " \"status\": {"
|
||||
echo " \"core_files\": $files_ok,"
|
||||
echo " \"python\": $(python3 --version &>/dev/null && echo true || echo false),"
|
||||
echo " \"kubectl\": $(command -v kubectl &>/dev/null && echo true || echo false)"
|
||||
echo " }"
|
||||
echo "}"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
case "${1:-}" in
|
||||
--paths)
|
||||
show_paths
|
||||
;;
|
||||
--json)
|
||||
show_json
|
||||
;;
|
||||
--full|*)
|
||||
show_summary
|
||||
;;
|
||||
esac
|
||||
213
automation/log-viewer.py
Executable file
213
automation/log-viewer.py
Executable file
@@ -0,0 +1,213 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
View and analyze Claude Code logs.
|
||||
Usage: python3 log-viewer.py [--tail N] [--grep PATTERN] [--since DATE] [--type TYPE]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
CLAUDE_DIR = Path.home() / ".claude"
|
||||
LOG_DIR = CLAUDE_DIR / "logs"
|
||||
|
||||
|
||||
def get_log_files(log_type: Optional[str] = None) -> List[Path]:
|
||||
"""Get list of log files, optionally filtered by type."""
|
||||
if not LOG_DIR.exists():
|
||||
return []
|
||||
|
||||
files = list(LOG_DIR.glob("*.log"))
|
||||
|
||||
if log_type:
|
||||
files = [f for f in files if log_type in f.name]
|
||||
|
||||
return sorted(files, key=lambda f: f.stat().st_mtime, reverse=True)
|
||||
|
||||
|
||||
def parse_log_line(line: str) -> Optional[dict]:
|
||||
"""Parse a log line into structured data."""
|
||||
# Try JSON format
|
||||
try:
|
||||
return json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
# Try timestamp format: [YYYY-MM-DD HH:MM:SS] message
|
||||
match = re.match(r'\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (.+)', line)
|
||||
if match:
|
||||
return {
|
||||
"timestamp": match.group(1),
|
||||
"message": match.group(2)
|
||||
}
|
||||
|
||||
# Plain text
|
||||
return {"message": line.strip()} if line.strip() else None
|
||||
|
||||
|
||||
def filter_by_date(entries: List[dict], since: str) -> List[dict]:
|
||||
"""Filter entries by date."""
|
||||
try:
|
||||
since_date = datetime.strptime(since, "%Y-%m-%d")
|
||||
except ValueError:
|
||||
try:
|
||||
# Try relative (e.g., "1d", "7d", "1h")
|
||||
if since.endswith("d"):
|
||||
days = int(since[:-1])
|
||||
since_date = datetime.now() - timedelta(days=days)
|
||||
elif since.endswith("h"):
|
||||
hours = int(since[:-1])
|
||||
since_date = datetime.now() - timedelta(hours=hours)
|
||||
else:
|
||||
return entries
|
||||
except ValueError:
|
||||
return entries
|
||||
|
||||
result = []
|
||||
for entry in entries:
|
||||
ts = entry.get("timestamp", "")
|
||||
if ts:
|
||||
try:
|
||||
entry_date = datetime.strptime(ts[:19], "%Y-%m-%d %H:%M:%S")
|
||||
if entry_date >= since_date:
|
||||
result.append(entry)
|
||||
except ValueError:
|
||||
result.append(entry) # Include if can't parse
|
||||
else:
|
||||
result.append(entry)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def grep_entries(entries: List[dict], pattern: str) -> List[dict]:
|
||||
"""Filter entries by grep pattern."""
|
||||
regex = re.compile(pattern, re.IGNORECASE)
|
||||
result = []
|
||||
for entry in entries:
|
||||
message = entry.get("message", "")
|
||||
if regex.search(message):
|
||||
result.append(entry)
|
||||
return result
|
||||
|
||||
|
||||
def tail_file(path: Path, n: int = 50) -> List[str]:
|
||||
"""Get last N lines from a file."""
|
||||
try:
|
||||
with open(path) as f:
|
||||
lines = f.readlines()
|
||||
return lines[-n:]
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
|
||||
def format_entry(entry: dict) -> str:
|
||||
"""Format a log entry for display."""
|
||||
ts = entry.get("timestamp", "")
|
||||
msg = entry.get("message", "")
|
||||
|
||||
if ts:
|
||||
return f"[{ts}] {msg}"
|
||||
return msg
|
||||
|
||||
|
||||
def list_logs():
|
||||
"""List available log files."""
|
||||
files = get_log_files()
|
||||
|
||||
if not files:
|
||||
print("No log files found.")
|
||||
return
|
||||
|
||||
print(f"\n📋 Log Files ({len(files)})\n")
|
||||
print(f"{'File':<40} {'Size':<10} {'Modified'}")
|
||||
print("-" * 70)
|
||||
|
||||
for f in files:
|
||||
stat = f.stat()
|
||||
size = stat.st_size
|
||||
if size > 1024 * 1024:
|
||||
size_str = f"{size / 1024 / 1024:.1f}M"
|
||||
elif size > 1024:
|
||||
size_str = f"{size / 1024:.1f}K"
|
||||
else:
|
||||
size_str = f"{size}B"
|
||||
|
||||
mtime = datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %H:%M")
|
||||
print(f"{f.name:<40} {size_str:<10} {mtime}")
|
||||
|
||||
print("")
|
||||
|
||||
|
||||
def view_log(filename: str, tail: int = 50, grep: Optional[str] = None,
|
||||
since: Optional[str] = None):
|
||||
"""View a specific log file."""
|
||||
# Find the log file
|
||||
log_path = LOG_DIR / filename
|
||||
if not log_path.exists():
|
||||
# Try with .log extension
|
||||
log_path = LOG_DIR / f"{filename}.log"
|
||||
|
||||
if not log_path.exists():
|
||||
print(f"Log file not found: {filename}")
|
||||
return
|
||||
|
||||
lines = tail_file(log_path, tail * 2 if grep else tail) # Get more if filtering
|
||||
|
||||
entries = []
|
||||
for line in lines:
|
||||
entry = parse_log_line(line)
|
||||
if entry:
|
||||
entries.append(entry)
|
||||
|
||||
if since:
|
||||
entries = filter_by_date(entries, since)
|
||||
|
||||
if grep:
|
||||
entries = grep_entries(entries, grep)
|
||||
|
||||
# Limit to tail after filtering
|
||||
entries = entries[-tail:]
|
||||
|
||||
print(f"\n📜 {log_path.name} (last {len(entries)} entries)\n")
|
||||
print("-" * 70)
|
||||
|
||||
for entry in entries:
|
||||
print(format_entry(entry))
|
||||
|
||||
print("")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="View Claude Code logs")
|
||||
parser.add_argument("file", nargs="?", help="Log file to view")
|
||||
parser.add_argument("--list", "-l", action="store_true", help="List log files")
|
||||
parser.add_argument("--tail", "-n", type=int, default=50,
|
||||
help="Number of lines to show (default: 50)")
|
||||
parser.add_argument("--grep", "-g", type=str, help="Filter by pattern")
|
||||
parser.add_argument("--since", "-s", type=str,
|
||||
help="Show entries since date (YYYY-MM-DD or 1d/7d/1h)")
|
||||
parser.add_argument("--type", "-t", type=str,
|
||||
help="Filter log files by type (maintenance, etc.)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.list:
|
||||
list_logs()
|
||||
elif args.file:
|
||||
view_log(args.file, tail=args.tail, grep=args.grep, since=args.since)
|
||||
else:
|
||||
# Default: show most recent log
|
||||
files = get_log_files(args.type)
|
||||
if files:
|
||||
view_log(files[0].name, tail=args.tail, grep=args.grep, since=args.since)
|
||||
else:
|
||||
print("No log files found. Run some automation scripts first.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -71,6 +71,13 @@ else
|
||||
fail "history-browser.py syntax error"
|
||||
fi
|
||||
|
||||
# Test 8: log-viewer.py
|
||||
if python3 -m py_compile "${AUTOMATION_DIR}/log-viewer.py" 2>/dev/null; then
|
||||
pass "log-viewer.py syntax valid"
|
||||
else
|
||||
fail "log-viewer.py syntax error"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Skill Scripts ==="
|
||||
|
||||
@@ -115,7 +122,7 @@ else
|
||||
fi
|
||||
|
||||
# Test automation bash scripts
|
||||
for script in install.sh daily-maintenance.sh backup.sh restore.sh clean.sh; do
|
||||
for script in install.sh daily-maintenance.sh backup.sh restore.sh clean.sh debug.sh; do
|
||||
if [[ -f "${AUTOMATION_DIR}/${script}" ]]; then
|
||||
if bash -n "${AUTOMATION_DIR}/${script}" 2>/dev/null; then
|
||||
pass "${script} syntax valid"
|
||||
|
||||
@@ -15,6 +15,8 @@ Slash commands for quick actions. User-invoked (type `/command` to trigger).
|
||||
| `/remember` | `/save`, `/note` | Quick save to memory |
|
||||
| `/config` | `/settings`, `/prefs` | View/manage configuration |
|
||||
| `/search` | `/find`, `/lookup` | Search memory, history, config |
|
||||
| `/log` | `/logs`, `/logview` | View and analyze logs |
|
||||
| `/debug` | `/diag`, `/diagnose` | Debug and troubleshoot config |
|
||||
| `/maintain` | `/maintenance`, `/admin` | Configuration maintenance |
|
||||
| `/programmer` | | Code development tasks |
|
||||
| `/gcal` | `/calendar`, `/cal` | Google Calendar access |
|
||||
|
||||
48
commands/debug.md
Normal file
48
commands/debug.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: debug
|
||||
description: Debug and troubleshoot Claude Code configuration
|
||||
aliases: [diag, diagnose]
|
||||
invokes: skill:debug
|
||||
---
|
||||
|
||||
# Debug Command
|
||||
|
||||
Generate a debug report for troubleshooting.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/debug # Full debug report
|
||||
/debug --paths # Show configuration paths
|
||||
/debug --json # Output as JSON
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
Run the debug script:
|
||||
|
||||
```bash
|
||||
~/.claude/automation/debug.sh [options]
|
||||
```
|
||||
|
||||
## Report Sections
|
||||
|
||||
| Section | Contents |
|
||||
|---------|----------|
|
||||
| Version | Current configuration version |
|
||||
| Core Files | Status of essential files |
|
||||
| State Files | PA preferences, session context, autonomy |
|
||||
| Memory Files | Preferences, decisions, projects, facts |
|
||||
| Key Scripts | Executable status of automation scripts |
|
||||
| Skills | List of available skills |
|
||||
| Commands | Count of slash commands |
|
||||
| Agents | Count of agent files |
|
||||
| Environment | Shell, Python, kubectl status |
|
||||
| Disk Usage | Space used by each directory |
|
||||
|
||||
## JSON Output
|
||||
|
||||
Use `--json` for machine-readable output, useful for:
|
||||
- Automated health checks
|
||||
- Monitoring integration
|
||||
- Scripting
|
||||
39
commands/log.md
Normal file
39
commands/log.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: log
|
||||
description: View and analyze Claude Code logs
|
||||
aliases: [logs, logview]
|
||||
invokes: skill:log-viewer
|
||||
---
|
||||
|
||||
# Log Command
|
||||
|
||||
View and analyze automation logs.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/log # Show most recent log
|
||||
/log --list # List all log files
|
||||
/log <filename> # View specific log
|
||||
/log --tail 100 # Show last 100 lines
|
||||
/log --grep "error" # Filter by pattern
|
||||
/log --since 1d # Show entries from last day
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
Run the log viewer script:
|
||||
|
||||
```bash
|
||||
python3 ~/.claude/automation/log-viewer.py [options]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--list` | List available log files |
|
||||
| `--tail N` | Number of lines to show (default: 50) |
|
||||
| `--grep PATTERN` | Filter by regex pattern |
|
||||
| `--since DATE` | Filter by date (YYYY-MM-DD or 1d/7d/1h) |
|
||||
| `--type TYPE` | Filter log files by type |
|
||||
@@ -164,6 +164,16 @@
|
||||
"description": "Search memory, history, and configuration",
|
||||
"aliases": ["/find", "/lookup"],
|
||||
"invokes": "command:search"
|
||||
},
|
||||
"/log": {
|
||||
"description": "View and analyze logs",
|
||||
"aliases": ["/logs", "/logview"],
|
||||
"invokes": "command:log"
|
||||
},
|
||||
"/debug": {
|
||||
"description": "Debug and troubleshoot configuration",
|
||||
"aliases": ["/diag", "/diagnose"],
|
||||
"invokes": "command:debug"
|
||||
}
|
||||
},
|
||||
"agents": {
|
||||
@@ -292,7 +302,10 @@
|
||||
"memory-add": "~/.claude/automation/memory-add.py",
|
||||
"memory-list": "~/.claude/automation/memory-list.py",
|
||||
"search": "~/.claude/automation/search.py",
|
||||
"history-browser": "~/.claude/automation/history-browser.py"
|
||||
"history-browser": "~/.claude/automation/history-browser.py",
|
||||
"log-viewer": "~/.claude/automation/log-viewer.py",
|
||||
"debug": "~/.claude/automation/debug.sh",
|
||||
"daily-maintenance": "~/.claude/automation/daily-maintenance.sh"
|
||||
},
|
||||
"completions": {
|
||||
"bash": "~/.claude/automation/completions.bash",
|
||||
|
||||
Reference in New Issue
Block a user