#!/usr/bin/env python3 """ Simple workspace search tool. Searches markdown files and returns ranked results. """ import os import sys import re from pathlib import Path from collections import defaultdict WORKSPACE = Path("/home/wdjones/.openclaw/workspace") EXTENSIONS = {'.md', '.txt', '.sh', '.py', '.json'} def search(query: str, max_results: int = 10) -> list: """Search workspace for query, return list of (file, line_num, line, score).""" results = [] query_lower = query.lower() query_words = query_lower.split() for root, dirs, files in os.walk(WORKSPACE): # Skip hidden directories dirs[:] = [d for d in dirs if not d.startswith('.')] for fname in files: fpath = Path(root) / fname if fpath.suffix not in EXTENSIONS: continue try: with open(fpath, 'r', encoding='utf-8', errors='ignore') as f: for i, line in enumerate(f, 1): line_lower = line.lower() # Calculate score score = 0 for word in query_words: if word in line_lower: score += 1 # Bonus for exact phrase if query_lower in line_lower: score += 2 # Bonus for word boundaries if re.search(rf'\b{re.escape(word)}\b', line_lower): score += 1 if score > 0: rel_path = fpath.relative_to(WORKSPACE) results.append((str(rel_path), i, line.strip(), score)) except Exception: continue # Sort by score descending results.sort(key=lambda x: -x[3]) return results[:max_results] def main(): if len(sys.argv) < 2: print("Usage: search.py [max_results]") sys.exit(1) query = sys.argv[1] max_results = int(sys.argv[2]) if len(sys.argv) > 2 else 10 results = search(query, max_results) if not results: print(f"No results for: {query}") return print(f"Results for: {query}\n") for fpath, line_num, line, score in results: # Truncate long lines display = line[:80] + "..." if len(line) > 80 else line print(f"[{fpath}:{line_num}] {display}") if __name__ == "__main__": main()