feat: tmux orchestrator start/stop/status
This commit is contained in:
Executable
+112
@@ -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
|
||||||
Reference in New Issue
Block a user