Oebb ScottySAFE
High-performance AI coding agent CLI written in Rust with zero unsafe code
Overview
High-performance AI coding agent CLI written in Rust with zero unsafe code
46a2537504c9OBSERVED · 2026-10-10What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: oebb-scotty
description: Austrian rail travel planner (ÖBB Scotty). Use when planning train journeys in Austria, checking departures/arrivals at stations, or looking for service disruptions. Covers ÖBB trains, S-Bahn, regional trains, and connections to neighboring countries.
---
# ÖBB Scotty API
Query Austria's public transport for trip planning, station departures, and service alerts via the HAFAS mgate API.
## Quick Reference
| Method | Purpose |
|--------|---------|
| `LocMatch` | Search for stations/stops by name |
| `TripSearch` | Plan a journey between two locations |
| `StationBoard` | Get departures/arrivals at a station |
| `HimSearch` | Get service alerts and disruptions |
**Base URL:** `https://fahrplan.oebb.at/bin/mgate.exe`
---
## Authentication
All requests require these headers in the JSON body:
```json
{
"id": "1",
"ver": "1.67",
"lang": "deu",
"auth": {"type": "AID", "aid": "OWDL4fE4ixNiPBBm"},
"client": {"id": "OEBB", "type": "WEB", "name": "webapp", "l": "vs_webapp"},
"formatted": false,
"svcReqL": [...]
}
```
---
## 1. Location Search (`LocMatch`)
Search for stations, stops, addresses, or POIs by name.
### Request
```bash
curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
-H "Content-Type: application/json" \
-d '{
"id":"1","ver":"1.67","lang":"deu",
"auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
"client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
"formatted":false,
"svcReqL":[{
"req":{"input":{"field":"S","loc":{"name":"Wien Hbf","type":"ALL"},"maxLoc":10}},
"meth":"LocMatch"
}]
}'
```
### Response Structure
```json
{
"svcResL": [{
"res": {
"match": {
"locL": [{
"lid": "A=1@O=Wien Hbf (U)@X=16377950@Y=48184986@U=181@L=1290401@",
"type": "S",
"name": "Wien Hbf (U)",
"extId": "1290401",
"crd": { "x": 16377950, "y": 48184986 },
"pCls": 6015
}]
}
}
}]
}
```
### Location Types
| Type | Description |
|------|-------------|
| `S` | Station/Stop |
| `A` | Address |
| `P` | POI (Point of Interest) |
### Key Fields
| Field | Description |
|-------|-------------|
| `lid` | Location ID string (use in TripSearch) |
| `extId` | External station ID |
| `name` | Station name |
| `crd.x/y` | Coordinates (x=lon, y=lat, scaled by 10^6) |
| `pCls` | Product class bitmask |
---
## 2. Trip Search (`TripSearch`)
Plan a journey between two locations.
### Request
```bash
curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
-H "Content-Type: application/json" \
-d '{
"id":"1","ver":"1.67","lang":"deu",
"auth":{"type":"AID","aid":"OWDL4fE4ixNiPBBm"},
"client":{"id":"OEBB","type":"WEB","name":"webapp","l":"vs_webapp"},
"formatted":false,
"svcReqL":[{
"req":{
"depLocL":[{"lid":"A=1@O=Wien Hbf@L=8103000@","type":"S"}],
"arrLocL":[{"lid":"A=1@O=Salzburg Hbf@L=8100002@","type":"S"}],
"jnyFltrL":[{"type":"PROD","mode":"INC","value":"1023"}],
"getPolyline":false,
"getPasslist":true,
"outDate":"20260109",
"outTime":"080000",
"outFrwd":true,
"numF":5
},
"meth":"TripSearch"
}]
}'
```
### Parameters
| Param | Description |
|-------|-------------|
| `depLocL` | Departure location(s) - use `lid` from LocMatch |
| `arrLocL` | Arrival location(s) |
| `outDate` | Departure date (YYYYMMDD) |
| `outTime` | Departure time (HHMMSS) |
| `outFrwd` | `true` = search forward, `false` = search backward |
| `numF` | Number of connections to return |
| `jnyFltrL` | Product filter (see below) |
| `getPasslist` | Include intermediate stops |
### Product Filter Values
| Bit | Value | Product |
|-----|-------|---------|
| 0 | 1 | ICE/RJX (High-speed) |
| 1 | 2 | IC/EC (InterCity) |
| 2 | 4 | NJ (Night trains) |
| 3 | 8 | D/EN (Express) |
| 4 | 16 | REX/R (Regional Express) |
| 5 | 32 | S-Bahn |
| 6 | 64 | Bus |
| 7 | 128 | Ferry |
| 8 | 256 | U-Bahn |
| 9 | 512 | Tram |
Use `1023` for all products, or sum specific bits.
### Response Structure
```json
{
"svcResL": [{
"res": {
"outConL": [{
"date": "20260109",
"dur": "025200",
"chg": 0,
"dep": {
"dTimeS": "075700",
"dPltfS": {"txt": "8A-B"}
},
"arr": {
"aTimeS": "104900",
"aPltfS": {"txt": "7"}
},
"secL": [{
"type": "JNY",
"jny": {
"prodX": 0,
"dirTxt": "Salzburg Hbf",
"stopL": [...]
}
}]
}],
"common": {
"locL": [...],
"prodL": [...]
}
}
}]
}
```
### Key Connection Fields
| Field | Description |
|-------|-------------|
| `dur` | Duration (HHMMSS) |
| `chg` | Number of changes |
| `dTimeS` | Scheduled departure |
| `dTimeR` | Real-time departure (if available) |
| `aTimeS` | Scheduled arrival |
| `aTimeR` | Real-time arrival (if available) |
| `dPltfS.txt` | Departure platform |
| `aPltfS.txt` | Arrival platform |
| `secL` | Journey sections (legs) |
| `secL[].jny.prodX` | Index into `common.prodL[]` for train name |
### Understanding prodX (Product Index)
**Important:** The `prodX` field in journey sections is an index into the `common.prodL[]` array, NOT the train name itself. To get the actual train name (e.g., "S7", "RJX 662"), you must look up `common.prodL[prodX].name`.
### Extracting Trip Summaries with jq
The raw TripSearch response is very verbose. Use this jq filter to extract a concise summary with resolved train names:
```bash
curl -s -X POST "https://fahrplan.oebb.at/bin/mgate.exe" \
-H "Content-Type: application/json" \
-d '{ ... }' | jq '
.svcResL[0].res as $r |
$r.common.prodL as $prods |
[$r.outConL[] | {
dep: .dep.dTimeS,
arr: .arr.aTimeS,
depPlatform: .dep.dPltfS.txt,
arrPlatform: .arr.aPltfS.txt,
dur: .dur,
chg: .chg,
legs:Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- declared (5 observation(s))
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (1)
.beads/beads.jsonl
Gates applied: no_behavioural_pass.
46a2537504c9full audit observations/trust-audit/skill/dicklesworthstone__oebb-scotty.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-10 | 46a2537504c9 | SAFE | B | 89 | first audit |
Questions
What does the Oebb Scotty skill do?
High-performance AI coding agent CLI written in Rust with zero unsafe code
Is Oebb Scotty safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Oebb Scotty access on my machine?
The audit observed that it reaches the network. Each of those is consistent with what it says it does. Secrets in the source: none found.
How current is this page?
The grade is for one exact copy of the source (46a2537504c9), read on 2026-10-10. The repository is watched, and a new audit runs when it changes — this is the first audit.