Initial sandbox buildout - Structure: projects, docs, inbox, archive, templates, scripts, tools - Tools: search.py, inbox-processor.py, daily-digest.py - Shell aliases and bashrc integration - Templates for projects and notes - MEMORY.md, TASKS.md, STRUCTURE.md - tmux config

This commit is contained in:
2026-01-30 23:14:35 -06:00
commit f18a1944d6
19 changed files with 828 additions and 0 deletions

81
tools/search.py Executable file
View File

@ -0,0 +1,81 @@
#!/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 <query> [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()