Install
openclaw skills install @voronindenis5/errand-routerPlan the optimal order for a multi-stop errand run: groceries, pharmacy, post office, pickup, drop-off. Computes distance (haversine) and travel time between stops, respects opening-hours time windows, adds service/dwell time per stop, and optimizes the visit order with nearest-neighbor + 2-opt. Outputs a timed itinerary with ETAs, wait time, and flags for stops you'd arrive at after closing. Use when someone asks what order to run errands in, whether several stops fit before closing time, or how to route a day of pickups and deliveries.
openclaw skills install @voronindenis5/errand-router"Drop package at post office, pick up prescription, return library books, groceries, and the hardware store closes at 6 — what order do I go in?"
Most people solve this by vibes and end up backtracking across town. This skill treats a Saturday errand run as what it mathematically is: a small Traveling Salesperson Problem with Time Windows (TSPTW) — small enough to solve optimally in milliseconds with construction + local search, no OR-tools required.
scripts/errand_router.py takes a list of stops (name, lat/lon or x/y,
dwell minutes, opening hours) plus a start point and departure time, then:
Don't use for: road-navigation turn-by-turn (no live traffic, no one-ways), >15 stops with tight windows (that needs a real solver / OR-tools), or multi-day logistics fleets.
--stop repeated flags):
{
"start": {"name": "home", "lat": 52.52, "lon": 13.405},
"depart": "09:30",
"speed_kmh": 30,
"stops": [
{"name": "post office", "lat": 52.51, "lon": 13.39,
"dwell_min": 10, "open": "09:00", "close": "18:00"},
{"name": "pharmacy", "lat": 52.54, "lon": 13.42,
"dwell_min": 15, "open": "10:00", "close": "20:00"}
]
}
python3 scripts/errand_router.py plan errands.json
python3 scripts/errand_router.py plan errands.json --end home --json
--depart 09:00), or relax the constraint and re-run until clean.--json for agent consumption of the route legs.travel_time(a,b) = haversine(a,b) × ROAD_FACTOR(1.3) / speed
construction : nearest feasible neighbor by time
improvement : 2-opt segment reversal, keep if shorter AND feasible
feasibility : arrival + dwell ≤ close (hard), open (soft: wait)
Haversine uses R = 6371 km. 2-opt runs to convergence (no improving move); for n ≤ 12 stops this is effectively instant and near-optimal.
5 errands from home at 09:30, two afternoon-only stops:
order: post office → bank → pharmacy → grocery → hardware
total: 11.2 km · 1h 55m (incl. 12 min waiting + 55 min dwell)
✅ all stops open on arrival
Re-run with --depart 15:30:
🚨 hardware store closes 18:00, arrival 18:12 — leave ≥35 min earlier
close (or explicitly flagged)start and ends at start or --endQuick 3-stop check from the CLI (no JSON file):
python3 scripts/errand_router.py quick \
--start "home,52.52,13.405" \
--stop "pharmacy,52.54,13.42,10,09:00,20:00" \
--stop "post,52.51,13.39,10,09:00,18:00" \
--depart 17:00
Morning run with a forced last stop (pick-up before dinner):
python3 scripts/errand_router.py plan errands.json --end grocery