Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ autopilot restart abc123 # Restart a stopped task

# Monitoring
autopilot status # Show all task statuses (rich table)
autopilot status --watch # Auto-refreshing live dashboard
autopilot status --watch # Interactive dashboard with keybindings
autopilot status --json # JSON output for scripting
autopilot logs # Show latest task log
autopilot logs --session abc123 # Show specific task log
Expand All @@ -65,6 +65,30 @@ autopilot attach abc123 # Attach to a task's tmux session
autopilot next # Jump to next session needing attention
```

### Interactive Dashboard (`--watch`)

Full-screen TUI with animated spinners for active sessions:

```
╭─ autopilot-loop — Sessions ──────────────────────────────────────────────────╮
│ # Task ID Mode Branch State PR Iter Age │
│► 1 a1b2c3d4 review autopilot/a1b2c3d4 ⠹ IMPLEMENT - 0/5 < 1m │
│ 2 e5f6g7h8 ci autopilot/e5f6g7h8 ◐ WAIT_CI #43 1/5 3m │
│ 3 i9j0k1l2 review autopilot/i9j0k1l2 ■ STOPPED #44 3/5 45m │
│ 4 m3n4o5p6 review autopilot/m3n4o5p6 ✓ COMPLETE #45 2/5 1h │
╰──────────────────────────────────────────────────────────────────────────────╯
j/k navigate Enter attach x stop r refresh q quit
```

| Key | Action |
|-----|--------|
| `j` / `↓` | Move selection down |
| `k` / `↑` | Move selection up |
| `Enter` | Attach to selected tmux session |
| `x` | Stop selected session |
| `r` | Force refresh |
| `q` / `Esc` | Quit |

## Configuration

Create `autopilot.json` in your repo root or `~/.autopilot-loop/config.json`:
Expand Down
32 changes: 29 additions & 3 deletions src/autopilot_loop/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,30 @@ def _launch_in_tmux(task_id, mode="review", branch=None, pr_number=None):
sessions_dir = get_sessions_dir(task_id)
log_file = os.path.join(sessions_dir, "orchestrator.log")
tmux_session = "autopilot-%s" % task_id
run_cmd = "autopilot _run --task-id %s 2>&1 | tee -a %s" % (task_id, log_file)

# Run orchestrator, then print summary and keep pane alive (#15)
run_cmd = (
"autopilot _run --task-id %s 2>&1 | tee -a %s; "
"echo ''; echo '=== Task %s finished ==='; "
"echo 'Run: autopilot status or autopilot logs --session %s'; "
"echo 'Press Enter to close this pane.'; read _dummy"
% (task_id, log_file, task_id, task_id)
)

try:
subprocess.run(
["tmux", "new-session", "-d", "-s", tmux_session, run_cmd],
check=True,
)
# Enable mouse scrolling and increase scrollback buffer (#14)
subprocess.run(
["tmux", "set-option", "-t", tmux_session, "mouse", "on"],
check=False, capture_output=True,
)
subprocess.run(
["tmux", "set-option", "-t", tmux_session, "history-limit", "50000"],
check=False, capture_output=True,
)
except FileNotFoundError:
logger.warning("tmux not found, running in foreground")
cmd_run(argparse.Namespace(task_id=task_id))
Expand Down Expand Up @@ -232,14 +249,23 @@ def cmd_resume(args):

def cmd_status(args):
"""Show status of all autopilot tasks."""
from autopilot_loop.dashboard import status_json, status_table, status_watch
from autopilot_loop.dashboard import (
status_interactive,
status_json,
status_table,
status_watch,
)

if getattr(args, "json", False):
status_json()
return

if getattr(args, "watch", False):
status_watch(interval=getattr(args, "interval", 5))
interval = getattr(args, "interval", 2)
if sys.stdout.isatty():
status_interactive(interval=interval)
else:
status_watch(interval=interval)
return

status_table()
Expand Down
Loading
Loading