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.
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
This skill is an action router — pick the step that matches the user's intent and execute only that step. Do not run other steps; do not parallelize.
Available actions:
Run the env-presence check (scripts/check-env.py relative to this skill; the NanoClaw runtime mounts every tessl__* skill at /home/node/.claude/skills/tessl__<skill-name>/, so the absolute path the agent must literally invoke is):
python3 /home/node/.claude/skills/tessl__flight-assist/scripts/check-env.pyThe script reads BYAIR_MCP_URL and GOOGLE_MAPS_API_KEY, prints single-line JSON on stdout, exits 0.
Parse the JSON. All true: emit flight-assist credentials present. Any false: emit one line per missing variable:
BYAIR_MCP_URL missing. Add personal MCP link from https://byairapp.com/mcp/ to OneCLI vault and restart container.GOOGLE_MAPS_API_KEY missing. Create a Distance Matrix API key at https://console.cloud.google.com/apis/credentials and add to OneCLI vault.
Calendar access has no flag: OneCLI's gateway injects the Google OAuth Bearer on the wire, so no credential lives in this container and no env var gates it (nanoclaw#638). If the user is diagnosing calendar writes specifically, tell them to run the reconcile (Step 3) and read its error — gateway means the gateway is not authenticating the requests, tier means this agent's tier is gated from Google by design.Finish here.
When the user provides their home address (e.g., "set my home base to 1 Infinite Loop, Cupertino, CA"), invoke the set-home-base.py script to persist it to the plugin-wide config the precheck reads for time_to_leave queries as the fallback origin when no fresh live-location snapshot is available (see Step 3's time_to_leave row for the origin-resolution ladder). While a TripIt trip is active the precheck swaps the current trip lodging in for this address (trip_origin.py, #122) — the config value is the off-trip base, not a hard override.
python3 /home/node/.claude/skills/tessl__flight-assist/scripts/set-home-base.py "<address from user>"The script writes the address to /workspace/state/flight-assist/config.json (atomic, idempotent), preserves any other config keys, and prints {"home_address": "..."} to stdout. Exit 0 on success, exit 2 on usage/validation failure.
Emit one confirmation line to the user: Home base set: <address>. Finish here.
The precheck delivers every notice itself (#370): it renders the event's template (notices.py), sends it through the host and confirms it in notifications.json only on the host's success. It then runs scripts/reconcile.py for the calendar. Its run log data carries sent, send_failed (the notification ids still pending) and reconcile. A pending notice is offered again after five minutes until it expires.
To see a flight's current state:
python3 /home/node/.claude/skills/tessl__flight-assist/scripts/get-flight-state.py <flight_id>To rerun the calendar reconcile by hand:
python3 /home/node/.claude/skills/tessl__flight-assist/scripts/reconcile.pyReport what the run log and state show: the notice went out, is still pending, or never fired. Never send a flight notice yourself. Finish here.
.tessl-plugin
rules
skills
check-travel-bookings
drive-engine
expertflyer
flight-assist
references
nightly-travel-sync
sync-tripit