Back to Skills
    🦞

    tabussen

    Västerbotten & Umeå public transport trip planner.

    By @simskii
    View on GitHub
    SKILL.md
    ---
    name: tabussen
    description: Västerbotten & Umeå public transport trip planner (Tabussen/Ultra). Plans bus journeys using ResRobot API. Supports stops, addresses, coordinates, regional and local routes throughout Västerbotten county.
    license: MIT
    compatibility: Requires curl, jq. Works with Claude Code and compatible agents.
    metadata:
      author: simskii
      version: "1.0.0"
      region: sweden-vasterbotten
    ---
    
    # Tabussen Trip Planner
    
    Plan public transport journeys in Västerbotten, Sweden - including Umeå local traffic (Ultra) and regional routes (Länstrafiken Västerbotten).
    
    ## Overview
    
    This skill uses the **ResRobot API** (Trafiklab) to provide journey planning for Tabussen/Ultra. ResRobot is Sweden's national public transport API covering all operators including Länstrafiken Västerbotten.
    
    **Coverage:**
    - Ultra (Umeå local bus traffic)
    - Länstrafiken Västerbotten (regional buses)
    - Connections to/from other Swedish regions
    - Train connections where applicable
    
    ## Commands
    
    ### 1. Search Location
    
    Search for stops, stations, or points of interest.
    
    ```bash
    ./search-location.sh <query> [limit]
    ```
    
    | Argument | Description |
    |----------|-------------|
    | `query` | Location name to search for (append `?` for fuzzy search) |
    | `limit` | Number of results to show (default: 5, max: 10) |
    
    **Output includes:**
    - `ID` - The stop identifier (use this in journey search)
    - `Name` - Official name of the stop
    - `Coordinates` - Latitude, longitude
    - `Weight` - Traffic volume indicator (higher = more traffic)
    
    **Search tips:**
    - Use `?` suffix for fuzzy/partial matching: `"Vasaplan?"` 
    - Exact search without `?`: `"Vasaplan"`
    - Include municipality for precision: `"Umeå Vasaplan"`
    
    ### 2. Journey Search
    
    Plan a journey between two locations using their IDs.
    
    ```bash
    ./journey.sh <from-id> <to-id> [datetime] [mode]
    ```
    
    | Argument | Description |
    |----------|-------------|
    | `from-id` | Origin stop ID (from search) |
    | `to-id` | Destination stop ID |
    | `datetime` | Optional: `"18:30"`, `"tomorrow 09:00"`, `"2026-01-28 14:00"` |
    | `mode` | Optional: `"depart"` (default) or `"arrive"` |
    
    **Coordinate-based search:**
    ```bash
    ./journey.sh "63.825#20.263" <to-id> [datetime] [mode]
    ```
    Use `lat#lon` format for coordinates (WGS84 decimal degrees).
    
    ---
    
    ## Understanding User Time Intent
    
    Before searching, understand what the user wants:
    
    ### Intent Types
    
    | User Says | Intent | How to Query |
    |-----------|--------|--------------|
    | "now", "next bus", "how do I get to" | **Travel Now** | No datetime parameter |
    | "in 30 minutes", "in 1 hour" | **Depart Later** | Calculate time, use `depart` mode |
    | "around 15:00", "sometime afternoon" | **Around Time** | Query with offset (see below) |
    | "arrive by 18:00", "need to be there at 9" | **Arrive By** | Use `arrive` mode |
    | "tomorrow morning", "on Friday at 10" | **Future Time** | Use specific datetime |
    
    ### Handling "Around Time" Queries
    
    When user wants options "around" a time, query 15-30 minutes earlier to show options before and after:
    
    ```bash
    # User: "I want to travel around 15:00"
    # Query at 14:30 to get options spanning 14:30-16:00+
    ./journey.sh ... "14:30" depart
    ```
    
    ### Relative Time Calculations
    
    Convert relative times to absolute:
    
    | User Says | Current: 14:00 | Query Time |
    |-----------|----------------|------------|
    | "in 30m" | -> | "14:30" |
    | "in 1h" | -> | "15:00" |
    | "in 2 hours" | -> | "16:00" |
    
    ---
    
    ## LLM Response Formatting
    
    When presenting journey results to users, use these emojis and formatting guidelines.
    
    ### Emoji Reference
    
    | Emoji | Use For |
    |-------|---------|
    | `bus` | Bus (Tabussen/Ultra) |
    | `train` | Train |
    | `walk` | Walking segment |
    | `clock` | Time/duration |
    | `clock1` | Departure time |
    | `goal` | Arrival time |
    | `pin` | Stop/station |
    | `house` | Origin (home/start) |
    | `target` | Destination |
    | `warning` | Delay or disruption |
    | `check` | On time |
    | `arrows_counterclockwise` | Transfer/change |
    
    ### Response Structure
    
    **Always include these key elements from the tool output:**
    
    1. **When to leave** - The actual time user needs to start (including walking)
    2. **Walking segments** - Distance and time for any walking
    3. **Transport departure** - When the bus actually leaves
    4. **Arrival time** - When user reaches destination
    5. **Line number and direction** - Which bus to take
    
    ### Example Response Format
    
    **For a simple direct journey:**
    ```
    **Leave now** from Vasaplan
    
    **Vasaplan** -> **Universitetet**
    Bus 1 (mot Mariehem) departs 09:07
    Arrives 09:18 at Universitetet
    
    Total: 11 min
    ```
    
    **For a journey with transfer:**
    ```
    **Leave at 08:45**
    
    Walk 300m to Vasaplan (~4 min)
    
    **Vasaplan** -> **Umeå C** -> **Skellefteå**
    
    **Leg 1:**
    Bus 1 departs 08:51
    Arrives Umeå C 09:05
    
    Transfer at Umeå C (15 min)
    
    **Leg 2:**
    Bus 100 (mot Skellefteå) departs 09:20
    Arrives Skellefteå busstation 11:45
    
    Total: 3h | 1 change
    ```
    
    ### Walking Segment Details
    
    **Always show walking details:**
    - Distance in meters
    - Include walking in the "leave time" calculation
    - Walk time estimate: ~100m per minute (normal walking speed)
    
    ### Presenting Multiple Options
    
    When showing journey options, make timing crystal clear:
    
    ```
    I found 3 options for you:
    
    **Option 1 - Leave now (09:00)** Recommended
    Walk 5 min -> Bus 1 at 09:07 -> arrives 09:25
    Total: 25 min
    
    **Option 2 - Leave in 15m (09:15)**
    Walk 5 min -> Bus 1 at 09:22 -> arrives 09:40
    Total: 25 min
    
    **Option 3 - Leave in 30m (09:30)**
    Walk 5 min -> Bus 8 at 09:37 -> arrives 09:48
    Total: 18 min | Faster but later departure
    
    Which works best for you?
    ```
    
    ---
    
    ## LLM Workflow: How to Plan a Trip
    
    Follow this workflow when a user asks for a trip:
    
    ### Step 1: Understand Time Intent
    
    Parse what the user wants:
    - **"How do I get to..."** -> Travel now
    - **"I need to be there at 18:00"** -> Arrive mode
    - **"Sometime around 3pm"** -> Query 14:30, show range
    - **"In about an hour"** -> Calculate from current time
    
    ### Step 2: Search for Both Locations
    
    Search for origin and destination separately:
    
    ```bash
    ./search-location.sh "Vasaplan?"
    ./search-location.sh "Universitetet?"
    ```
    
    ### Step 3: Validate Search Results
    
    **Check each result carefully:**
    
    1. **Exact or close match?** - If the name matches what the user asked for, proceed.
    
    2. **Multiple results returned?** - The script shows up to 10 matches. If the first result isn't clearly correct, ask the user to confirm.
    
    3. **Name significantly different?** - If user asked for "university" and result shows "Umeå Universitet", confirm with user.
    
    4. **No results found?** - Try alternative strategies (see below).
    
    ### Step 4: Handle Ambiguous or Failed Searches
    
    **When results don't match or are ambiguous, ask clarifying questions:**
    
    ```
    I searched for "centrum" and found multiple locations:
    1. Umeå Vasaplan (central bus hub)
    2. Skellefteå centrum
    3. Lycksele centrum
    
    Which one did you mean?
    ```
    
    **When no results are found, try these strategies:**
    
    1. **Try with city name:**
       ```bash
       # If "Storgatan 10" fails, try:
       ./search-location.sh "Storgatan 10, Umeå?"
       ```
    
    2. **Try common variations:**
       ```bash
       # "Universitetet" -> "Umeå universitet"
       # "Sjukhuset" -> "NUS" or "Norrlands universitetssjukhus"
       ```
    
    3. **Use fuzzy search (add ?):**
       ```bash
       ./search-location.sh "univ?"
       ```
    
    ### Step 5: Execute Journey Search
    
    Once you have confirmed IDs for both locations:
    
    ```bash
    ./journey.sh <from-id> <to-id> [datetime] [mode]
    ```
    
    ### Step 6: Format Response
    
    Use the formatting guide above to present results clearly. **Always use actual numbers from the tool output - never estimate or speculate.**
    
    ---
    
    ## Query Formatting Rules
    
    **The search API is sensitive to formatting. Follow these rules:**
    
    ### Common Stop Names in Umeå
    
    | User Says | Search For |
    |-----------|------------|
    | "Vasaplan", "centrum" | `"Umeå Vasaplan?"` |
    | "Universitetet", "uni" | `"Umeå universitet?"` |
    | "NUS", "sjukhuset" | `"Norrlands universitetssjukhus?"` |
    | "Ikea" | `"IKEA Umeå?"` |
    | "Flygplatsen" | `"Umeå Airport?"` |
    | "Järnvägsstationen", "tåget" | `"Umeå centralstation?"` |
    
    ### Regional Destinations
    
    | Destination | Search For |
    |-------------|------------|
    | Skellefteå | `"Skellefteå busstation?"` |
    | Lycksele | `"Lycksele busstation?"` |
    | Vindeln | `"Vindeln station?"` |
    | Robertsfors | `"Robertsfors centrum?"` |
    | Holmsund | `"Holmsund centrum?"` |
    
    ### Street Addresses
    
    Include city name for better accuracy:
    ```bash
    ./search-location.sh "Storgatan 25, Umeå?"
    ./search-location.sh "Kungsgatan 10, Skellefteå?"
    ```
    
    ---
    
    ## Examples
    
    ### Example 1: Travel Now (Umeå Local)
    
    User: "How do I get from Vasaplan to NUS?"
    
    ```bash
    ./search-location.sh "Umeå Vasaplan"
    ./search-location.sh "NUS?"
    ./journey.sh 740020116 740023840
    ```
    
    **Response:**
    ```
    **Leave now** from Vasaplan
    
    **Vasaplan** -> **Universitetssjukhuset**
    Bus 8 (mot Lyktvägen) departs 11:01
    Arrives 11:06
    
    Total: 5 min | Direct, no changes
    ```
    
    ### Example 2: Regional Journey
    
    User: "I need to get to Skellefteå from Umeå tomorrow at 8"
    
    ```bash
    ./search-location.sh "Umeå Vasaplan"
    ./search-location.sh "Skellefteå?"
    ./journey.sh 740020116 740000053 "tomorrow 08:00"
    ```
    
    **Response:**
    ```
    **Depart tomorrow at 08:04** from Vasaplan
    
    Walk 766m to Umeå Busstation (~11 min)
    
    **Umeå Busstation** -> **Skellefteå busstation**
    Bus 20 (Länstrafik mot Haparanda) departs 08:15
    Arrives 10:40 at Skellefteå busstation
    
    Total: 2h 36min | Direct (with walk)
    ```
    
    ### Example 3: Arrive By Time
    
    User: "I need to be at NUS by 08:00 tomorrow"
    
    ```bash
    ./search-location.sh "Umeå Vasaplan"
    ./search-location.sh "NUS?"
    ./journey.sh 740020116 740023840 "tomorrow 08:00" arrive
    ```
    
    **Response:**
    ```
    **Arrive by 08:00** at NUS
    
    **Vasaplan** -> **Universitetssjukhuset**
    Bus 9 departs **07:51**
    Arrives **07:56** - 4 min buffer
    
    Leave Vasaplan by 07:51 to arrive on time!
    ```
    
    ### Example 4: From Address/Coordinates
    
    User: "I'm at Storgatan 50 in Umeå, how do I get to IKEA?"
    
    ```bash
    ./search-location.sh "Storgatan 50, Umeå?"
    # If no resul
    
    ... (truncated)