#!/bin/bash # gemini-wrapper - Token-aware wrapper for gemini command # Location: ~/.claude/scripts/gemini-wrapper # # This wrapper automatically manages --all-files flag based on project token count # Usage: gemini-wrapper [all gemini options] set -e # Configuration DEFAULT_TOKEN_LIMIT=2000000 TOKEN_LIMIT=${GEMINI_TOKEN_LIMIT:-$DEFAULT_TOKEN_LIMIT} # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Function to count tokens (approximate: chars/4) count_tokens() { local total_chars=0 local file_count=0 # Count characters in common source files while IFS= read -r -d '' file; do if [[ -f "$file" && -r "$file" ]]; then local chars=$(wc -c < "$file" 2>/dev/null || echo 0) total_chars=$((total_chars + chars)) file_count=$((file_count + 1)) fi done < <(find . -type f \( -name "*.py" -o -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" -o -name "*.java" -o -name "*.cpp" -o -name "*.c" -o -name "*.h" -o -name "*.rs" -o -name "*.go" -o -name "*.md" -o -name "*.txt" -o -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.xml" -o -name "*.html" -o -name "*.css" -o -name "*.scss" -o -name "*.sass" -o -name "*.php" -o -name "*.rb" -o -name "*.sh" -o -name "*.bash" \) -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" -not -path "*/build/*" -not -path "*/.next/*" -not -path "*/.nuxt/*" -not -path "*/target/*" -not -path "*/vendor/*" -print0 2>/dev/null) local estimated_tokens=$((total_chars / 4)) echo "$estimated_tokens $file_count" } # Parse arguments to check for flags has_all_files=false has_approval_mode=false args=() # Check for existing flags for arg in "$@"; do if [[ "$arg" == "--all-files" ]]; then has_all_files=true elif [[ "$arg" == --approval-mode* ]]; then has_approval_mode=true fi args+=("$arg") done # Count tokens echo -e "${YELLOW}🔍 Analyzing project size...${NC}" >&2 read -r token_count file_count <<< "$(count_tokens)" echo -e "${YELLOW}📊 Project stats: ~${token_count} tokens across ${file_count} files${NC}" >&2 # Decision logic for --all-files flag if [[ $token_count -lt $TOKEN_LIMIT ]]; then if [[ "$has_all_files" == false ]]; then echo -e "${GREEN}✅ Small project (${token_count} < ${TOKEN_LIMIT} tokens): Adding --all-files${NC}" >&2 args=("--all-files" "${args[@]}") else echo -e "${GREEN}✅ Small project (${token_count} < ${TOKEN_LIMIT} tokens): Keeping --all-files${NC}" >&2 fi else if [[ "$has_all_files" == true ]]; then echo -e "${RED}⚠️ Large project (${token_count} >= ${TOKEN_LIMIT} tokens): Removing --all-files to avoid token limits${NC}" >&2 echo -e "${YELLOW}💡 Consider using specific @{patterns} for targeted analysis${NC}" >&2 # Remove --all-files from args new_args=() for arg in "${args[@]}"; do if [[ "$arg" != "--all-files" ]]; then new_args+=("$arg") fi done args=("${new_args[@]}") else echo -e "${RED}⚠️ Large project (${token_count} >= ${TOKEN_LIMIT} tokens): Avoiding --all-files${NC}" >&2 echo -e "${YELLOW}💡 Consider using specific @{patterns} for targeted analysis${NC}" >&2 fi fi # Auto-add approval-mode if not specified if [[ "$has_approval_mode" == false ]]; then # Check if this is an analysis task (contains words like "analyze", "review", "understand") prompt_text="${args[*]}" if [[ "$prompt_text" =~ (analyze|analysis|review|understand|inspect|examine) ]]; then echo -e "${GREEN}📋 Analysis task detected: Adding --approval-mode default${NC}" >&2 args=("--approval-mode" "default" "${args[@]}") else echo -e "${YELLOW}⚡ Execution task detected: Adding --approval-mode yolo${NC}" >&2 args=("--approval-mode" "yolo" "${args[@]}") fi fi # Show final command (for transparency) echo -e "${YELLOW}🚀 Executing: gemini ${args[*]}${NC}" >&2 # Execute gemini with adjusted arguments exec gemini "${args[@]}"