Nodejs Backend Patterns
ever-works/ever-works
Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices.
Search trains, buses, and ferries in Norway (Entur), Sweden (ResRobot), and Denmark (Rejseplanen).
$ npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install borski/travel-hacking-toolkit scandinavia-transit --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/borski/travel-hacking-toolkit.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/travel-hacking-toolkit/skills/scandinavia-transit .claude/skills/scandinavia-transit && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "scandinavia-transit" agent skill from https://github.com/borski/travel-hacking-toolkit/tree/main/plugins/travel-hacking-toolkit/skills/scandinavia-transit into .claude/skills/scandinavia-transit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "scandinavia-transit", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/borski/travel-hacking-toolkit/tree/main/plugins/travel-hacking-toolkit/skills/scandinavia-transitType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install borski/travel-hacking-toolkit scandinavia-transit --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/borski/travel-hacking-toolkit.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/travel-hacking-toolkit/skills/scandinavia-transit .agents/skills/scandinavia-transit && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "scandinavia-transit" agent skill from https://github.com/borski/travel-hacking-toolkit/tree/main/plugins/travel-hacking-toolkit/skills/scandinavia-transit into .agents/skills/scandinavia-transit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "scandinavia-transit", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install borski/travel-hacking-toolkit scandinavia-transit --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/borski/travel-hacking-toolkit.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/travel-hacking-toolkit/skills/scandinavia-transit .cursor/skills/scandinavia-transit && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "scandinavia-transit" agent skill from https://github.com/borski/travel-hacking-toolkit/tree/main/plugins/travel-hacking-toolkit/skills/scandinavia-transit into .cursor/skills/scandinavia-transit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "scandinavia-transit", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/borski/travel-hacking-toolkit.git --path plugins/travel-hacking-toolkit/skills/scandinavia-transit--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install borski/travel-hacking-toolkit scandinavia-transit --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/borski/travel-hacking-toolkit.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/travel-hacking-toolkit/skills/scandinavia-transit .gemini/skills/scandinavia-transit && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "scandinavia-transit" agent skill from https://github.com/borski/travel-hacking-toolkit/tree/main/plugins/travel-hacking-toolkit/skills/scandinavia-transit into .gemini/skills/scandinavia-transit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "scandinavia-transit", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install borski/travel-hacking-toolkit scandinavia-transitInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/borski/travel-hacking-toolkit.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/travel-hacking-toolkit/skills/scandinavia-transit .github/skills/scandinavia-transit && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "scandinavia-transit" agent skill from https://github.com/borski/travel-hacking-toolkit/tree/main/plugins/travel-hacking-toolkit/skills/scandinavia-transit into .github/skills/scandinavia-transit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "scandinavia-transit", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install borski/travel-hacking-toolkit scandinavia-transit --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/borski/travel-hacking-toolkit.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/travel-hacking-toolkit/skills/scandinavia-transit .opencode/skills/scandinavia-transit && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "scandinavia-transit" agent skill from https://github.com/borski/travel-hacking-toolkit/tree/main/plugins/travel-hacking-toolkit/skills/scandinavia-transit into .opencode/skills/scandinavia-transit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "scandinavia-transit", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
scandinavia-transitSearch trains, buses, and ferries in Norway (Entur), Sweden (ResRobot), and Denmark (Rejseplanen).
Scandinavia Transit is an agent skill from borski/travel-hacking-toolkit. Search trains, buses, and ferries in Norway (Entur), Sweden (ResRobot), and Denmark (Rejseplanen). Intra-Scandinavia ground transport with schedules and Danish fare pricing.
Its SKILL.md is about 4.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs. It works with GraphQL. The repository describes itself as: AI-powered travel hacking and search with cash, points, miles, and award flights. Drop-in skills and MCP servers for Claude, Codex, and OpenCode. The licence is MIT.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit db82131. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
curljqFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
rejseplanen.dkapi.entur.ioapi.resrobot.seAlso links to:
labs.rejseplanen.dktrafiklab.sedeveloper.entur.orgFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
REJSEPLANEN_API_KEYRESROBOT_API_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Scandinavia Transit loads about 4.5k tokens when it runs. Until then it costs about 48 tokens; SKILL.md has 1,373 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
`RESROBOT_API_KEY` in `.env`. Use `accessId` query parameter. Free key at [trafiklab.se](https://www.trafiklab.se). 30,0`REJSEPLANEN_API_KEY` in `.env`. Pass as `accessId` query parameter. Apply at [labs.rejseplanen.dk](https://labs.rejseplAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from borski/travel-hacking-toolkit at commit db82131, republished under its MIT licence (© borski). 1,373 words, ~4,508 tokens.
.claude/skills/scandinavia-transit/SKILL.md (or your agent's skills folder).Search ground transport (trains, buses, ferries) within Norway, Sweden, and Denmark using their national transit APIs.
Sources:
Open GraphQL API. No key needed (but a client name header is required). Covers ALL Norwegian transit: Vy trains, buses, ferries, trams, metro. 60+ operators.
curl -s -X POST "https://api.entur.io/journey-planner/v3/graphql" \
-H "Content-Type: application/json" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" \
-d '{"query": "{ trip(from: {place: \"NSR:StopPlace:59872\"}, to: {place: \"NSR:StopPlace:548\"}, numTripPatterns: 5) { tripPatterns { startTime duration legs { mode expectedStartTime expectedEndTime fromPlace { name } toPlace { name } line { publicCode name authority { name } } } } } }"}' | jq '.data.trip.tripPatterns[] | {start: .startTime, duration_min: (.duration / 60), legs: [.legs[] | {mode: .mode, from: .fromPlace.name, to: .toPlace.name, line: .line.publicCode, operator: .line.authority.name, depart: .expectedStartTime, arrive: .expectedEndTime}]}'Stop IDs use the format NSR:StopPlace:XXXXX. Find them via the Geocoder:
curl -s "https://api.entur.io/geocoder/v1/autocomplete?text=Oslo%20S&size=3" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" | jq '[.features[] | {name: .properties.name, id: .properties.id, type: .properties.layer}]'| City | Stop ID | Name |
|---|---|---|
| Oslo S | NSR:StopPlace:59872 | Oslo S |
| Bergen | NSR:StopPlace:548 | Bergen stasjon |
| Stavanger | NSR:StopPlace:4130 | Stavanger |
| Trondheim | NSR:StopPlace:41742 | Trondheim S |
| Bodo | NSR:StopPlace:49484 | Bodo stasjon |
Use the Geocoder to find any stop. Works for airports, ferry terminals, bus stops too.
curl -s -X POST "https://api.entur.io/journey-planner/v3/graphql" \
-H "Content-Type: application/json" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" \
-d '{"query": "{ stopPlace(id: \"NSR:StopPlace:59872\") { name estimatedCalls(numberOfDepartures: 10) { expectedDepartureTime destinationDisplay { frontText } serviceJourney { journeyPattern { line { publicCode name transportMode } } } } } }"}' | jq '.data.stopPlace | {name: .name, departures: [.estimatedCalls[] | {time: .expectedDepartureTime, destination: .destinationDisplay.frontText, line: .serviceJourney.journeyPattern.line.publicCode, mode: .serviceJourney.journeyPattern.line.transportMode}]}'https://api.entur.io/journey-planner/v3/graphqlET-Client-Name header on all requests.REST API via Trafiklab. Covers ALL Swedish transit: SJ trains, regional buses, ferries, metro, commuter rail.
RESROBOT_API_KEY in .env. Use accessId query parameter. Free key at trafiklab.se. 30,000 calls/month.
curl -s "https://api.resrobot.se/v2.1/trip?originId=740000001&destId=740000002&format=json&accessId=$RESROBOT_API_KEY" | jq '[.Trip[] | {start: .LegList.Leg[0].Origin.time, date: .LegList.Leg[0].Origin.date, duration: .duration, legs: [.LegList.Leg[] | {mode: .type, name: .name, from: .Origin.name, to: .Destination.name, depart: .Origin.time, arrive: .Destination.time}]}] | .[0:5]'curl -s "https://api.resrobot.se/v2.1/location.name?input=Stockholm&format=json&accessId=$RESROBOT_API_KEY" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId}] | .[0:5]'| City | Stop ID | Name |
|---|---|---|
| Stockholm C | 740000001 | Stockholm Centralstation |
| Gothenburg C | 740000002 | Goteborg Centralstation |
| Malmo C | 740000003 | Malmo Centralstation |
| Uppsala | 740000025 | Uppsala Centralstation |
| Linkoping | 740000009 | Linkoping Centralstation |
| Param | Required | Description |
|---|---|---|
originId | Yes | Departure stop ID |
destId | Yes | Arrival stop ID |
date | No | YYYY-MM-DD (default today) |
time | No | HH:MM (default now) |
format | No | json or xml |
numTrips | No | Number of results (default 5) |
products | No | Bitmask for transport types |
https://api.resrobot.se/v2.1/REST API (HAFAS v2.50.4.1). Covers ALL Danish transit: DSB InterCity/InterCityLyn, S-Tog, Metro, regional trains, buses, express buses, night buses, ferries, Flextur. Unique: includes fare/zone pricing data.
Docs: https://labs.rejseplanen.dk (login required). XSD schemas: https://www.rejseplanen.dk/api/xsd
REJSEPLANEN_API_KEY in .env. Pass as accessId query parameter. Apply at labs.rejseplanen.dk. 50,000 calls/month free (non-commercial).
| Param | Description |
|---|---|
accessId | Required. API key. |
format | json or xml. Always use format=json. |
lang | Default da. Use lang=en for English. |
| Value | Product | Description |
|---|---|---|
| 1 | IC | InterCity |
| 2 | ICL | InterCityLyn (express) |
| 4 | Re | Regional train |
| 8 | Other | ECE, Eurostar, RailJet, Togbus, DSB Udland |
| 16 | S-Tog | Copenhagen commuter rail |
| 32 | Bus | Local bus |
| 64 | ExpressBus | Express bus (250S, X-bus) |
| 128 | NightBus | Natbus |
| 256 | Flextur | Demand-responsive transport |
| 1024 | Metro | Copenhagen Metro |
Trains only = products=31. All transit = omit param.
| Stop | extId | Name |
|---|---|---|
| København H | 8600626 | København H |
| CPH Lufthavn | 8600858 | CPH Lufthavn |
| Odense St. | 8600512 | Odense St. |
| Aarhus H | 8600053 | Aarhus H |
| Aalborg St. | 8600020 | Aalborg St. |
| Svendborg St. | 8600551 | Svendborg St. |
| Svendborg Færgehavn | 100200261 | Svendborg Færgehavn |
| Ærøskøbing Havn (færge) | 100200222 | Ærøskøbing Havn (færge) |
curl -s "https://www.rejseplanen.dk/api/location.name?accessId=$REJSEPLANEN_API_KEY&input=København&format=json&type=S" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId, lat: .lat, lon: .lon}] | .[0:10]'| Param | Required | Description |
|---|---|---|
input | Yes | Search query |
type | No | S (stops), A (addresses), P (POI), or combine |
maxNo | No | Max results (default 10, max 1000) |
products | No | Product bitmask filter |
r, refCoordLat, refCoordLong | No | Radius + reference coordinate for distance ranking |
curl -s "https://www.rejseplanen.dk/api/location.nearbystops?accessId=$REJSEPLANEN_API_KEY&originCoordLat=55.672793&originCoordLong=12.564590&r=500&format=json" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId, dist: .dist}] | .[0:10]'Requires originCoordLat/originCoordLong. Optional: r (radius, default 1000m), maxNo, type, products.
Single location details by full HAFAS ID (URL-encoded).
Locations in a numeric ID range (llId to urId).
Filtered location search. Same params as location.name plus additional filters.
All stops in a geographic box (llLat/llLon to urLat/urLon).
Addresses near a coordinate. Reverse geocoding. Requires originCoordLat/originCoordLong.
curl -s "https://www.rejseplanen.dk/api/trip?accessId=$REJSEPLANEN_API_KEY&originId=8600626&destId=8600551&date=2026-08-28&time=08:00&format=json&lang=en" | jq '[.TripList.Trip[] | {duration: .duration, legs: [.LegList.Leg[] | {name: .name, type: .type, from: .Origin.name, to: .Destination.name, depTime: .Origin.time, arrTime: .Destination.time, track: .Origin.track}]}] | .[0:3]'| Param | Required | Description |
|---|---|---|
originId | Yes* | Origin stop extId |
destId | Yes* | Destination stop extId |
originCoordLat/Long | Yes* | Origin by coordinate (alt to originId) |
destCoordLat/Long | Yes* | Destination by coordinate (alt to destId) |
date | No | YYYY-MM-DD |
time | No | HH:MM |
searchForArrival | No | 1 = search by arrival time |
numF | No | Forward results (1-6) |
numB | No | Backward results (0-3) |
maxChange | No | Max transfers (0-11) |
products | No | Product bitmask |
operators | No | Comma-separated operator codes |
lines | No | Line filter |
via | No | Via stop ID |
avoid | No | Avoid stop ID |
passlist | No | 1 = include intermediate stops |
tariff | No | 1 = include fare/zone pricing |
poly | No | 1 = include polyline |
context | No | Scroll token for paging |
originWalk/Bike/Car | No | Access mode distance |
destWalk/Bike/Car | No | Egress mode distance |
rtMode | No | FULL, INFOS, OFF, REALTIME, SERVER_DEFAULT |
All departures in a time window. Same params as trip.
Reconstruct trip from ctxRecon token. Params: ctx (required), poly, passlist, tariff.
All stops reachable within time/transfer budget. Params: originId or coordinates, duration (1-1439 min), maxChange (0-11), forward, products.
Default duration: 60 minutes.
curl -s "https://www.rejseplanen.dk/api/departureBoard?accessId=$REJSEPLANEN_API_KEY&id=8600626&date=2026-08-28&time=08:00&format=json&lang=en" | jq '[.DepartureBoard.Departure[] | {name: .name, time: .time, direction: .direction, track: .track, rtTime: .rtTime}] | .[0:10]'Params: id (required), date, time, duration (0-1439), maxJourneys, products, operators, passlist.
Multiple stations in one call. Pass multiple id params.
Stations near a coordinate. Params: originCoordLat/Long, r (default 1000m), maxStops (default 30).
Line details on a date. Requires lineId, date.
Full schedule for a line on a date. Requires lineId, date.
All lines by operator. Requires operators (comma-separated, from datainfo).
Match lines by pattern string.
Find journeys by train name. Returns first/last stop only.
Full stop list for a journey. Requires id (journey ref from trip/board). Optional: fromId/toId, poly, rtMode.
Like trainSearch but full details for first match only.
Real-time vehicle positions in bounding box. Requires llLat/llLon/urLat/urLon.
Denmark uses zone-based pricing via Rejsekort. Unique in Scandinavia.
| Endpoint | Purpose |
|---|---|
trip with tariff=1 | Inline pricing in trip results |
spPrice | Season pass price by origin/destination |
spPriceForZones | Price per day for zone count in fare set |
spDailyZonalPrices | Full zone price matrix, all passenger types |
spPriceReconstruction | Price from trip reconstruction context |
spRefund | Season pass refund calculation |
spCheck | Season pass validation (SELF system) |
spZoneCheck | Check zone connectivity and metro zones |
stRoutes | Tariff routes between origin/destination |
stRoutesAddon | Tariff routes from single origin |
stStops | Tariff zones and stops (mode=DSB) |
trfStop | Default stop for a zone |
convertZones | Tariff details for context |
zoneFromCoordinate | Zone lookup by lat/lon |
Walking/cycling route details from trip result. Requires ctx (GIS reference).
Real-time disruption messages. Filterable by products, operators, lines, dates, stops.
All operators, products, categories. Use to discover operator codes.
curl -s "https://www.rejseplanen.dk/api/datainfo?accessId=$REJSEPLANEN_API_KEY&format=json" | jq '[.DataInfo.operators.Operator[] | {name: .name, id: .id}] | .[0:20]'Timetable data pool info: ID, creation date, type (ST/ADR/POI), validity period.
extId: Numeric stop ID (use for queries). id is the full HAFAS string.rtTime/rtDate: Real-time actual/predicted times (when different from scheduled time/date).type: JNY (journey), WALK (walking), TRSF (transfer).JourneyDetailRef: Use with journeyDetail for full stop list.| Route | Covered By | Notes |
|---|---|---|
| Oslo to Stockholm | Entur + ResRobot | SJ trains, ~6 hours |
| Malmö to Copenhagen | ResRobot + Rejseplanen | Øresund trains, 35 min |
| Gothenburg to Oslo | Entur + ResRobot | Vy/SJ, ~4 hours |
| Stockholm to Copenhagen | ResRobot | SJ/DSB, ~5 hours via Malmö |
| Copenhagen to Malmö | Rejseplanen | Øresund trains from Danish side |
Load this skill when:
himsearch)journeypos)Do not:
Step 1: Pick API by country (Norway=Entur, Sweden=ResRobot, Denmark=Rejseplanen, cross-border=both).
Step 2: Find stop IDs:
# Norway
curl -s "https://api.entur.io/geocoder/v1/autocomplete?text=Flåm&size=3" \
-H "ET-Client-Name: $ENTUR_CLIENT_NAME" | jq '[.features[] | {name: .properties.name, id: .properties.id}]'
# Sweden
curl -s "https://api.resrobot.se/v2.1/location.name?input=Malmö&format=json&accessId=$RESROBOT_API_KEY" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId}] | .[0:5]'
# Denmark
curl -s "https://www.rejseplanen.dk/api/location.name?accessId=$REJSEPLANEN_API_KEY&input=Svendborg&format=json&type=S&lang=en" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId}] | .[0:5]'Step 3: Trip search with date and time. Step 4 (Denmark): Add tariff=1 for pricing.
curl -s "https://www.rejseplanen.dk/api/departureBoard?accessId=$REJSEPLANEN_API_KEY&id=8600626&duration=120&products=31&format=json&lang=en" | jq '[.DepartureBoard.Departure[] | {time: .time, name: .name, direction: .direction, track: .track}]'curl -s "https://www.rejseplanen.dk/api/location.nearbystops?accessId=$REJSEPLANEN_API_KEY&originCoordLat=55.6736&originCoordLong=12.5681&r=500&format=json&lang=en" | jq '[.stopLocationOrCoordLocation[] | .StopLocation | {name: .name, id: .extId, dist: .dist}]'Or nearbyDepartureBoard to skip stop lookup.
curl -s "https://www.rejseplanen.dk/api/trip?accessId=$REJSEPLANEN_API_KEY&originId=100200261&destId=100200222&date=2026-08-28&time=08:00&format=json&lang=en" | jq '[.TripList.Trip[] | {legs: [.LegList.Leg[] | {name: .name, from: .Origin.name, to: .Destination.name, depTime: .Origin.time, arrTime: .Destination.time}]}] | .[0:5]'trainSearch to find it, then journeyDetail with the ref for full stops.
curl -s "https://www.rejseplanen.dk/api/reachability?accessId=$REJSEPLANEN_API_KEY&originId=8600626&duration=120&maxChange=2&format=json" | jq '.'curl -s "https://www.rejseplanen.dk/api/himsearch?accessId=$REJSEPLANEN_API_KEY&format=json&lang=en" | jq '.'Search from both ends. Øresund trains appear in both ResRobot and Rejseplanen.
format=json. Always lang=en for Rejseplanen.extId (numeric) for queries, not the long HAFAS id string.rtTime/rtDate for delays.passlist=1 shows intermediate stops.maxChange=0 for direct connections only.numF/numB or context scroll tokens.© borski, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in plugins/travel-hacking-toolkit/skills/scandinavia-transit of borski/travel-hacking-toolkit.
Open the folder on GitHubat commit db82131
Scandinavia Transit next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Scandinavia Transit this skillborski/travel-hacking-toolkit | 688 | — | ~4.5k | Automated safety check: Notes | MIT | |
| Nodejs Backend Patternsever-works/ever-works | 162 | 18 repos | ~4k | Automated safety check: Pass | AGPL-3.0 | |
| Use Yaakmountain-loop/yaak | 19k | — | ~1.9k | Automated safety check: Pass | MIT | |
| API DesignerJeffallan/claude-skills | 12k | 1 repos | ~2k | Automated safety check: Pass | MIT | |
| GraphQL Operations with CodegenChrisWiles/claude-code-showcase | 6.1k | 3 repos | ~1.5k | Automated safety check: Pass | None | |
| Nestjs Trpctrycompai/crm | 11k | — | ~2.8k | Automated safety check: Pass | MIT |
ever-works/ever-works
Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices.
mountain-loop/yaak
A skill your agent uses when the user mentions Yaak, a Yaak workspace, or the yaak command, or asks to call, hit, or smoke test HTTP/REST endpoints, save or organize API requests for reuse or manual…
Jeffallan/claude-skills
Designs REST and GraphQL APIs from resource modeling to an OpenAPI 3.1 contract, with versioning, pagination and RFC 7807 error handling.
ChrisWiles/claude-code-showcase
Sets the rules for writing GraphQL queries and mutations in .gql files, running codegen, and using generated Apollo hooks with proper error and loading handling.
trycompai/crm
Build end-to-end type-safe tRPC APIs inside NestJS using the nestjs-trpc adapter — @Router/@Query/@Mutation/@Subscription decorators, TRPCModule.forRoot, injectable middlewares and context, Zod…
jh941213/my-cc-harness
REST 및 GraphQL API 설계 원칙 가이드. An agent skill from jh941213/my-cc-harness.
borski/travel-hacking-toolkit
Search Amex travel portal for cash prices, MR points pricing, IAP discounts, and FHR/THC hotel benefits via Patchright.
borski/travel-hacking-toolkit
Search Chase UR travel portal via Patchright for cash prices, points pricing, Points Boost offers, and Chase Edit hotel benefits.
borski/travel-hacking-toolkit
Deutsche Bahn train schedules, journey planning, and departures across Germany and into neighboring countries (Austria, Switzerland, Netherlands, France, Belgium).
borski/travel-hacking-toolkit
Search Sutochno.ru (СУТОЧНО.РУ), a Russian short-term apartment-rental platform where you book directly from owners and pay in rubles (Mir card / bank transfer).
borski/travel-hacking-toolkit
Search TicketsAtWork (EBG corporate perks) for hotels, theme park tickets, attractions, and rental cars via Patchright.
borski/travel-hacking-toolkit
Search VRBO (Vrbo / Expedia Group) vacation rentals including entire homes, condos, and cabins via Patchright browser automation.
Works with
Categories
Search trains, buses, and ferries in Norway (Entur), Sweden (ResRobot), and Denmark (Rejseplanen). Scandinavia Transit is an agent skill from borski/travel-hacking-toolkit. Search trains, buses, and ferries in Norway (Entur), Sweden (ResRobot), and Denmark (Rejseplanen).
Scandinavia Transit fits situations like: backend & APIs work in your project.
Run `npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a claude-code`. Or copy the skill folder (plugins/travel-hacking-toolkit/skills/scandinavia-transit in borski/travel-hacking-toolkit) into .claude/skills/scandinavia-transit in your project. Claude Code loads it when a task matches its description.
Run `npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a codex`. Or copy the skill folder (plugins/travel-hacking-toolkit/skills/scandinavia-transit in borski/travel-hacking-toolkit) into .agents/skills/scandinavia-transit in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add borski/travel-hacking-toolkit --skill scandinavia-transit -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/scandinavia-transit, .gemini/skills/scandinavia-transit, .github/skills/scandinavia-transit and .opencode/skills/scandinavia-transit in your project.
Going by SKILL.md and its folder, Scandinavia Transit needs the command-line tools its instructions call (curl and jq) and credentials named REJSEPLANEN_API_KEY and RESROBOT_API_KEY. Our summary lists: A credential in RESROBOT_API_KEY; A credential in REJSEPLANEN_API_KEY.
SKILL.md names 6 domains. In commands or code: rejseplanen.dk, api.entur.io and api.resrobot.se; the agent is likely to contact these when it follows the instructions. As links in the text: labs.rejseplanen.dk, trafiklab.se and developer.entur.org. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Scandinavia Transit is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.5k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Scandinavia Transit: Nodejs Backend Patterns (ever-works/ever-works, 162 stars), Use Yaak (mountain-loop/yaak, 19k stars), API Designer (Jeffallan/claude-skills, 12k stars) and GraphQL Operations with Codegen (ChrisWiles/claude-code-showcase, 6.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
borski (a GitHub user) maintains it in borski/travel-hacking-toolkit, which has 688 GitHub stars. The repository holds 46 skills in this directory. The repository was last updated on October 5, 2026.
Source: borski/travel-hacking-toolkit on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.