CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/nanoclaw-travel

Travel assistant for NanoClaw: byAir flight notifications (delay, gate, connection risk, inbound aircraft delay, time-to-leave, arrival logistics), traffic-aware drive planning for in-person meetings (auto drive blocks + leave-by traffic rechecks), travel-booking gap checks, and nightly TripIt sync. Per-chat overlay plugin.

72

Quality

91%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

SKILL.mdskills/drive-engine/

name:
drive-engine
description:
The unified drive-block engine. Manages the travel-time / driving blocks on your primary calendar from one place: drives to your flights, to your in-person meetings, and to a trip you drive to rather than fly. On a schedule it plans all three, diffs them against the blocks already there, and adds, updates, and removes its own blocks, suppressing drives you can't make (an airport reached by a connection, a home meeting while you're travelling). Use when the user asks about drive blocks, driving time, commute or travel-time blocks on their calendar, or drives to the airport, to a meeting, or to a hotel; when the operator replies to a drive notification to skip a meeting drive ('skip', 'skip 1', 'skip 2 and 3', 'skip the Massage drive'); when the operator says whether a trip is a drive or a flight ('drive', 'fly'); when the operator reports a drive block that looks wrong or missing. Also runs on its own schedule. That sweep delivers its notice without waking you. Only an operator reply activates a step.
cadence:
*/30 * * * *
agentModel:
claude-haiku-4-5-20251001
script:
reconcile_sweep.py

Drive Engine

This skill is an action router — pick the step that matches the situation and execute only that step. Do not run other steps; do not parallelize.

The precheck (reconcile_sweep.py) plans and applies every Drive: block change — airport, meeting, and lodging drives — every ~30 minutes, diffing against the calendar and touching only its own blocks. It leaves legacy drive-planner / flight-assist blocks alone (you clean those up). Its contract — inputs, apply counts, the fail-closed no-wake payload on error, and the wake gating — lives in reconcile_sweep.py (module docstring, build_sweep_payload) and calendar_apply.apply_plan. Do not restate its logic here.

The cadence sweep activates no step. Its precheck renders the operator notice and returns wake_agent: false. The host delivers data.message verbatim. No step below relays it. The steps below are the operator's replies to that notice. They wake normally.

Step 1 — Skip a meeting drive the operator declined

Run this when the operator replies to a drive notification to skip one — "skip", "skip 1", "skip 2 and 3", "skip the Massage drive". Map each local index to the meeting NAME from the message you sent (index 1 = the first meeting listed); a bare "skip" refers to the single meeting just offered. Never surface an internal id — the operator only ever named the drive by its position or name. For each named meeting, invoke:

python3 /home/node/.claude/skills/tessl__drive-engine/skip_drive.py '{"summary": "<meeting name>"}'

The script deletes that meeting's drive blocks and records a skip so no future sweep recreates them. It always prints a JSON result on stdout; read it (do not treat a non-zero exit as "no result"):

  • {"skipped": true, "meeting": ...} (exit 0) — confirm what you skipped.
  • {"skipped": false, "unmatched": ...} (exit 0) — the name wasn't found; say so.
  • {"skipped": false, "ambiguous": ..., "candidates": [...]} (exit 0) — several same-named meetings; ask the operator which when they mean, then re-invoke.
  • {"skipped": false, "error": ...} (exit 1) — an operational failure (an unauthenticated gateway, transport error); tell the operator the skip couldn't be recorded and to retry. Exit 2 is a usage/JSON error in how it was invoked — fix the call.

Reply in one message. Finish here.

Step 2 — Record a drive-or-fly answer

Run this when the operator answers a drive-or-fly question the sweep asked about a trip with no flight booked — "drive", "fly", "we're driving", "I'll fly that one". Map the answer to the trip NAME from the message you sent; a bare "drive" or "fly" refers to the single trip just asked about. Never surface an internal key — the operator only ever saw the trip name. Invoke:

python3 /home/node/.claude/skills/tessl__drive-engine/answer_drive_or_fly.py '{"trip": "<trip name>", "answer": "drive"}'

answer is drive or fly, nothing else. The script records the answer so it outranks the drive time from then on and the question is not repeated. It always prints a JSON result on stdout; read it (do not treat a non-zero exit as "no result"):

  • {"recorded": true, "trip": ..., "answer": ...} (exit 0) — confirm what you recorded. On drive, the next sweep adds the drives; on fly, the booking check reports the missing flight.
  • {"recorded": false, "unmatched": ...} (exit 0) — the trip name wasn't found; say so.
  • {"recorded": false, "ambiguous": ..., "candidates": [...]} (exit 0) — several same-named trips; ask the operator which when they mean, then re-invoke.
  • {"recorded": false, "error": ...} (exit 1) — an operational failure; tell the operator the answer couldn't be recorded and to retry. Exit 2 is a usage error in how it was invoked — fix the call.

Reply in one message. Finish here.

Step 3 — Flag a block that looks wrong

Run this when a block looks like an engine bug — a drive for a meeting you are travelling away from, a wrong-timezone block, a missing drive for a real trip. Send one message via mcp__nanoclaw__send_message naming the block's summary and leg identity (e.g. meeting_outbound mtg123 or airport_departure BNA-STN-...) and what looks wrong, so it can be fixed in code. Never edit the calendar by hand to compensate. Finish here.

README.md

tile.json