From 86baab7e968d75d1e46d95aa0caf5fc672a96d0d Mon Sep 17 00:00:00 2001 From: OpenCode Test Date: Thu, 1 Jan 2026 12:25:24 -0800 Subject: [PATCH] Add shell completions and test script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New files: - completions.bash: Bash completions and aliases for automation scripts - completions.zsh: Zsh completions and aliases - test-scripts.sh: Test suite for Python and Bash scripts Test coverage: - Automation scripts (validate-setup, memory-add, memory-list) - Skill scripts (gmail, gcal, usage) - Bash scripts (quick-status, health-check, k8s) All 12 tests pass. Usage: source ~/.claude/automation/completions.bash # or .zsh ~/.claude/automation/test-scripts.sh ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../__pycache__/memory-add.cpython-313.pyc | Bin 0 -> 5116 bytes .../__pycache__/memory-list.cpython-313.pyc | Bin 0 -> 3959 bytes automation/completions.bash | 53 ++++++++ automation/completions.zsh | 60 +++++++++ automation/test-scripts.sh | 114 ++++++++++++++++++ 5 files changed, 227 insertions(+) create mode 100644 automation/__pycache__/memory-add.cpython-313.pyc create mode 100644 automation/__pycache__/memory-list.cpython-313.pyc create mode 100644 automation/completions.bash create mode 100644 automation/completions.zsh create mode 100755 automation/test-scripts.sh diff --git a/automation/__pycache__/memory-add.cpython-313.pyc b/automation/__pycache__/memory-add.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..755df8dbc701d4229af77b5274ac9105e1ace71c GIT binary patch literal 5116 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 literal 0 HcmV?d00001 diff --git a/automation/__pycache__/memory-list.cpython-313.pyc b/automation/__pycache__/memory-list.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85aa25708b0ebd37df69cec928fddeff59817128 GIT binary patch literal 3959 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 literal 0 HcmV?d00001 diff --git a/automation/completions.bash b/automation/completions.bash new file mode 100644 index 0000000..3efb5ec --- /dev/null +++ b/automation/completions.bash @@ -0,0 +1,53 @@ +#!/bin/bash +# Bash completions for Claude Code automation scripts +# Source this file: source ~/.claude/automation/completions.bash + +_claude_automation() { + local cur="${COMP_WORDS[COMP_CWORD]}" + local scripts="validate-setup quick-status backup restore clean memory-add memory-list" + + COMPREPLY=($(compgen -W "${scripts}" -- "${cur}")) +} + +_claude_memory_add() { + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${COMP_CWORD} -eq 1 ]]; then + COMPREPLY=($(compgen -W "preference decision project fact auto" -- "${cur}")) + fi +} + +_claude_memory_list() { + local cur="${COMP_WORDS[COMP_CWORD]}" + + COMPREPLY=($(compgen -W "preferences decisions projects facts --all" -- "${cur}")) +} + +_claude_restore() { + local cur="${COMP_WORDS[COMP_CWORD]}" + local backup_dir="${HOME}/.claude/backups" + + if [[ -d "${backup_dir}" ]]; then + local backups=$(ls -1 "${backup_dir}"/*.tar.gz 2>/dev/null | xargs -n1 basename) + COMPREPLY=($(compgen -W "${backups}" -- "${cur}")) + fi +} + +# Register completions +complete -F _claude_memory_add memory-add.py +complete -F _claude_memory_list memory-list.py +complete -F _claude_restore restore.sh + +# Alias completions for convenience +alias claude-validate='~/.claude/automation/validate-setup.sh' +alias claude-status='~/.claude/automation/quick-status.sh' +alias claude-backup='~/.claude/automation/backup.sh' +alias claude-restore='~/.claude/automation/restore.sh' +alias claude-clean='~/.claude/automation/clean.sh' +alias claude-memory-add='python3 ~/.claude/automation/memory-add.py' +alias claude-memory-list='python3 ~/.claude/automation/memory-list.py' + +echo "Claude Code completions loaded. Available aliases:" +echo " claude-validate, claude-status, claude-backup, claude-restore" +echo " claude-clean, claude-memory-add, claude-memory-list" diff --git a/automation/completions.zsh b/automation/completions.zsh new file mode 100644 index 0000000..da41c58 --- /dev/null +++ b/automation/completions.zsh @@ -0,0 +1,60 @@ +#!/bin/zsh +# Zsh completions for Claude Code automation scripts +# Source this file: source ~/.claude/automation/completions.zsh + +# Memory add completion +_memory_add() { + local -a categories + categories=('preference:Save as preference' 'decision:Save as decision' 'project:Save as project context' 'fact:Save as fact' 'auto:Auto-categorize') + + _arguments \ + '1:category:->category' \ + '*:content:' && return 0 + + case $state in + category) + _describe 'category' categories + ;; + esac +} + +# Memory list completion +_memory_list() { + local -a categories + categories=('preferences' 'decisions' 'projects' 'facts') + + _arguments \ + '1:category:->category' \ + '--all[Include deprecated items]' && return 0 + + case $state in + category) + _describe 'category' categories + ;; + esac +} + +# Restore completion +_claude_restore() { + local backup_dir="${HOME}/.claude/backups" + + if [[ -d "${backup_dir}" ]]; then + _files -g "${backup_dir}/*.tar.gz" + fi +} + +# Register completions +compdef _memory_add memory-add.py +compdef _memory_list memory-list.py +compdef _claude_restore restore.sh + +# Aliases +alias claude-validate='~/.claude/automation/validate-setup.sh' +alias claude-status='~/.claude/automation/quick-status.sh' +alias claude-backup='~/.claude/automation/backup.sh' +alias claude-restore='~/.claude/automation/restore.sh' +alias claude-clean='~/.claude/automation/clean.sh' +alias claude-memory-add='python3 ~/.claude/automation/memory-add.py' +alias claude-memory-list='python3 ~/.claude/automation/memory-list.py' + +echo "Claude Code completions loaded (zsh)" diff --git a/automation/test-scripts.sh b/automation/test-scripts.sh new file mode 100755 index 0000000..da043c3 --- /dev/null +++ b/automation/test-scripts.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# Test automation scripts +# Run: ./test-scripts.sh + +set -euo pipefail + +CLAUDE_DIR="${HOME}/.claude" +AUTOMATION_DIR="${CLAUDE_DIR}/automation" +SKILLS_DIR="${CLAUDE_DIR}/skills" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +PASS=0 +FAIL=0 + +pass() { echo -e "${GREEN}โœ“${NC} $1"; PASS=$((PASS + 1)); } +fail() { echo -e "${RED}โœ—${NC} $1"; FAIL=$((FAIL + 1)); } +skip() { echo -e "${YELLOW}โ—‹${NC} $1 (skipped)"; } + +echo "๐Ÿงช Testing Claude Code Scripts" +echo "" + +# Test 1: validate-setup.sh +echo "=== Automation Scripts ===" +if "${AUTOMATION_DIR}/validate-setup.sh" > /dev/null 2>&1; then + pass "validate-setup.sh runs successfully" +else + fail "validate-setup.sh failed" +fi + +# Test 2: quick-status.sh (may fail without kubectl) +# Skip in automated testing - requires live connections +skip "quick-status.sh (requires live connections)" + +# Test 3: memory-add.py (test syntax only) +if python3 -m py_compile "${AUTOMATION_DIR}/memory-add.py" 2>/dev/null; then + pass "memory-add.py syntax valid" +else + fail "memory-add.py syntax error" +fi + +# Test 4: memory-list.py (test syntax only) +if python3 -m py_compile "${AUTOMATION_DIR}/memory-list.py" 2>/dev/null; then + pass "memory-list.py syntax valid" +else + fail "memory-list.py syntax error" +fi + +# Test 5: usage_report.py (test syntax only) +if python3 -m py_compile "${SKILLS_DIR}/usage/scripts/usage_report.py" 2>/dev/null; then + pass "usage_report.py syntax valid" +else + fail "usage_report.py syntax error" +fi + +echo "" +echo "=== Skill Scripts ===" + +# Test Gmail scripts (syntax only - need credentials to run) +for script in check_unread.py check_urgent.py search.py; do + if python3 -m py_compile "${SKILLS_DIR}/gmail/scripts/${script}" 2>/dev/null; then + pass "gmail/${script} syntax valid" + else + fail "gmail/${script} syntax error" + fi +done + +# Test GCal scripts +for script in agenda.py next_event.py; do + if python3 -m py_compile "${SKILLS_DIR}/gcal/scripts/${script}" 2>/dev/null; then + pass "gcal/${script} syntax valid" + else + fail "gcal/${script} syntax error" + fi +done + +# Test bash scripts (syntax check with bash -n) +echo "" +echo "=== Bash Scripts ===" + +for script in quick-status.sh health-check.sh; do + script_path=$(find "${CLAUDE_DIR}" -name "${script}" -type f | head -1) + if [[ -n "${script_path}" ]]; then + if bash -n "${script_path}" 2>/dev/null; then + pass "${script} syntax valid" + else + fail "${script} syntax error" + fi + fi +done + +# Test k8s quick-status +if bash -n "${SKILLS_DIR}/k8s-quick-status/scripts/quick-status.sh" 2>/dev/null; then + pass "k8s/quick-status.sh syntax valid" +else + fail "k8s/quick-status.sh syntax error" +fi + +echo "" +echo "=== Summary ===" +echo -e "Passed: ${GREEN}${PASS}${NC}" +echo -e "Failed: ${RED}${FAIL}${NC}" + +if [[ ${FAIL} -eq 0 ]]; then + echo -e "\n${GREEN}All tests passed!${NC}" + exit 0 +else + echo -e "\n${RED}${FAIL} test(s) failed${NC}" + exit 1 +fi