feat: tmux orchestrator start/stop/status

This commit is contained in:
2026-04-04 16:02:10 +02:00
parent d523272cd7
commit 3dc002fbb5
Executable
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env bash
# autoresearch tmux session orchestrator
# Usage: start.sh [start|stop|status]
set -euo pipefail
SESSION="autoresearch"
CONFIG="${HOME}/.claude/autoresearch.yaml"
LOGDIR="${HOME}/.claude/autoresearch"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
get_projects() {
python3 -c "
import yaml, os, sys
try:
cfg = yaml.safe_load(open('${CONFIG}'))
for p in cfg.get('projects', []):
print(os.path.expanduser(p['path']))
except Exception as e:
print(f'ERROR: {e}', file=sys.stderr)
sys.exit(1)
"
}
cmd_start() {
if tmux has-session -t "$SESSION" 2>/dev/null; then
echo "autoresearch: session '$SESSION' already running"
echo " attach: tmux attach -t $SESSION"
return 0
fi
mkdir -p "$LOGDIR"
# Window 0: overview — left: log viewer, right (30%): metrics
tmux new-session -d -s "$SESSION" -n "overview" -x 220 -y 50
tmux split-window -h -t "${SESSION}:overview" -p 30
tmux send-keys -t "${SESSION}:overview.left" \
"watch -n5 python3 '${SCRIPT_DIR}/log_view.py'" Enter
tmux send-keys -t "${SESSION}:overview.right" \
"watch -n10 python3 '${SCRIPT_DIR}/metrics.py'" Enter
# One window per project
local win=1
while IFS= read -r project_path; do
local project_name
project_name=$(basename "$project_path")
tmux new-window -t "${SESSION}:${win}" -n "$project_name"
# Start claude in the project directory
tmux send-keys -t "${SESSION}:${win}" \
"cd '${project_path}' && claude --name 'autoresearch-${project_name}'" Enter
# Wait for claude to initialize, then invoke the loop skill
sleep 3
tmux send-keys -t "${SESSION}:${win}" \
"/ralph-loop Run one autoresearch experiment iteration per the autoresearch-loop skill. --completion-promise STOP" Enter
win=$((win + 1))
done < <(get_projects)
tmux select-window -t "${SESSION}:0"
local project_count=$(( win - 1 ))
echo "autoresearch: started — ${project_count} project window(s)"
echo " attach: tmux attach -t $SESSION"
}
cmd_stop() {
if ! tmux has-session -t "$SESSION" 2>/dev/null; then
echo "autoresearch: not running"
return 0
fi
tmux kill-session -t "$SESSION"
echo "autoresearch: stopped"
}
cmd_status() {
if ! tmux has-session -t "$SESSION" 2>/dev/null; then
echo "autoresearch: not running"
return 1
fi
echo "autoresearch: running"
tmux list-windows -t "$SESSION"
echo ""
echo "Last experiment per project:"
python3 - <<'PYEOF'
import json, os
from collections import OrderedDict
log = os.path.expanduser('~/.claude/autoresearch/log.jsonl')
if not os.path.exists(log):
print(" (no experiments yet)")
else:
latest = OrderedDict()
with open(log) as f:
for line in f:
try:
e = json.loads(line)
latest[e.get('project')] = e
except Exception:
pass
for proj, e in latest.items():
kept = '✓' if e.get('kept') else '✗'
desc = (e.get('description') or '')[:50]
print(f" {proj}: exp {e.get('exp', '?')} {kept} — {desc}")
PYEOF
}
case "${1:-start}" in
start) cmd_start ;;
stop) cmd_stop ;;
status) cmd_status ;;
*)
echo "Usage: $(basename "$0") [start|stop|status]"
exit 1
;;
esac