Getting it into your agent
It runs from inside its repository, so the clone comes first — what it calls does not travel with the file alone.
git clone --depth 1 https://github.com/pangzhenying2025/hermes-automotive-skillsnpx agentmods add skills/pangzhenying2025/hermes-automotive-skills/automotive-sdvWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/pangzhenying2025/hermes-automotive-skills/automotive-sdv)<a href="https://agentmods.dev/skills/pangzhenying2025/hermes-automotive-skills/automotive-sdv"><img src="https://agentmods.dev/badge/skills/pangzhenying2025/hermes-automotive-skills/automotive-sdv/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/pangzhenying2025/hermes-automotive-skills/automotive-sdv"><img src="https://agentmods.dev/badge/skills/pangzhenying2025/hermes-automotive-skills/automotive-sdv.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00038 | $0.36167 |
| Opus 5 | $0.00019 | $0.18083 |
| Sonnet 5 | $0.00008 | $0.07233 |
| Haiku 4.5 | $0.00004 | $0.03617 |
Grade A, and why
automotive-sdv scanned grade A with 2 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 9d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Makes network callslowCapability
Not a fault in itself. Listed so you know the mod talks to something, and to what.
curl -L https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-arm64-v1.3.0.tgz | \ Runs shell commandslowCapability
Expected in a hook, worth knowing in a rule or an instructions file.
subprocess.run(cmd, check=True) How it starts
The opening of the file, as written. The whole thing — 5,356 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Automotive Sdv
Cloud Vehicle Integration
Cloud-Vehicle Integration — Connected Vehicle Platforms
Expert knowledge of vehicle-to-cloud connectivity (MQTT, AMQP, HTTP/2), telemetry streaming, remote diagnostics, cloud-based fleet management, and API gateways.
Core Concepts
Communication Protocols
- MQTT: Lightweight pub/sub for telemetry (Eclipse Mosquitto, AWS IoT Core)
- AMQP: Reliable message queuing (RabbitMQ, Azure Service Bus)
- HTTP/2: RESTful APIs with server push
- WebSocket: Real-time bidirectional communication
- gRPC: High-performance RPC for services
Architecture Patterns
- Edge Computing: Process data locally before cloud
- Digital Twin: Virtual representation of vehicle in cloud
- Command & Control: Remote vehicle operations
- Fleet Management: Aggregate analytics across vehicles
- OTA Coordination: Centralized update management
Production-Ready Implementation
1. Vehicle Telemetry Client (Python/MQTT)
#!/usr/bin/env python3
"""
Vehicle telemetry client using MQTT.
Streams vehicle data to cloud platform with offline buffering.
"""
import json
import time
import sqlite3
from dataclasses import dataclass, asdict
from datetime import datetime
from typing import Optional, List
import paho.mqtt.client as mqtt
import can
@dataclass
class TelemetryMessage:
"""Vehicle telemetry data point."""
vin: str
timestamp: str
message_type: str
data: dict
class VehicleTelemetryClient:
"""
MQTT-based telemetry client.
Features:
- Real-time telemetry streaming
- Offline buffering with SQLite
- Automatic reconnection
- QoS levels for reliability
- Compression for bandwidth optimization
"""
def __init__(self, config_path: str = "/etc/vehicle/telemetry-config.json"):
self.config = self._load_config(config_path)
self.vin = self._get_vin()
self.mqtt_client = None
self.can_bus = None
self.offline_buffer = OfflineBuffer()
self.connected = False
def _load_config(self, path: str) -> dict:
"""Load configuration."""
with open(path, 'r') as f:
return json.load(f)
def _get_vin(self) -> str:
"""Get vehicle VIN."""
with open('/sys/firmware/devicetree/base/serial-number', 'r') as f:
return f.read().strip()
def connect(self):
"""Connect to MQTT broker."""
self.mqtt_client = mqtt.Client(
client_id=f"vehicle-{self.vin}",
clean_session=False, # Maintain session across reconnects
protocol=mqtt.MQTTv5
)
# Set credentials
self.mqtt_client.username_pw_set(
self.config['mqtt_username'],
self.config['mqtt_password']
)
# Configure TLS
if self.config.get('mqtt_tls', True):
self.mqtt_client.tls_set(
ca_certs=self.config['mqtt_ca_cert'],
certfile=self.config.get('mqtt_client_cert'),
keyfile=self.config.get('mqtt_client_key')
)
# Set callbacks
self.mqtt_client.on_connect = self._on_connect
self.mqtt_client.on_disconnect = self._on_disconnect
self.mqtt_client.on_message = self._on_message
self.mqtt_client.on_publish = self._on_publish
# Set last will (notify cloud if vehicle disconnects unexpectedly)
self.mqtt_client.will_set(
f"vehicles/{self.vin}/status",
payload=json.dumps({
"status": "offline",
"timestamp": datetime.utcnow().isoformat()
}),
qos=1,
retain=True
)
# Connect
print(f"[Telemetry] Connecting to {self.config['mqtt_broker']}:{self.config['mqtt_port']}")
self.mqtt_client.connect(
self.config['mqtt_broker'],
self.config['mqtt_port'],
keepalive=60
)
# Start network loop in background
self.mqtt_client.loop_start()
def _on_connect(self, client, userdata, flags, rc, properties=None):
"""Handle MQTT connection."""
if rc == 0:
print("[Telemetry] Connected to MQTT broker")
self.connected = True
# Publish online status
self.mqtt_client.publish(
f"vehicles/{self.vin}/status",
payload=json.dumps({
"status": "online",
"timestamp": datetime.utcnow().isoformat(),
"sw_version": self._get_software_version()
}),
qos=1,
retain=True
)
# Subscribe to command topics
self.mqtt_client.subscribe(f"vehicles/{self.vin}/commands/#", qos=1)
# Send buffered messages
self._flush_offline_buffer()
else:
print(f"[Telemetry] Connection failed: {rc}")
self.connected = False
def _on_disconnect(self, client, userdata, rc):
"""Handle MQTT disconnection."""
print(f"[Telemetry] Disconnected from broker: {rc}")
self.connected = False
if rc != 0:
print("[Telemetry] Unexpected disconnect, will reconnect")
def _on_message(self, client, userdata, msg):
"""Handle incoming command messages."""
print(f"[Telemetry] Received command: {msg.topic}")
try:
payload = json.loads(msg.payload.decode())
self._handle_command(msg.topic, payload)
except Exception as e:
print(f"[Telemetry] Error processing command: {e}")
def _on_publish(self, client, userdata, mid):
"""Handle successful publish."""
# Remove from offline buffer if it was buffered
pass
def _handle_command(self, topic: str, payload: dict):
"""Handle remote commands from cloud."""
command_type = topic.split('/')[-1]
if command_type == "diagnostics":
# Trigger diagnostic data collection
print("[Telemetry] Starting diagnostic data collection")
self._collect_diagnostics()
elif command_type == "update":
# Trigger OTA update check
print("[Telemetry] Checking for updates")
# Integration with OTA system
elif command_type == "lock":
# Remote lock command
print("[Telemetry] Remote lock requested")
self._remote_lock()
elif command_type == "honk":
# Remote horn activation
print("[Telemetry] Remote honk requested")
self._remote_honk()
def publish_telemetry(self, message_type: str, data: dict, qos: int = 0):
"""
Publish telemetry message.
Args:
message_type: Type of telemetry (battery, location, speed, etc.)
data: Telemetry data
qos: MQTT QoS level (0, 1, or 2)
"""
msg = TelemetryMessage(
vin=self.vin,
timestamp=datetime.utcnow().isoformat(),
message_type=message_type,
data=data
)
topic = f"vehicles/{self.vin}/telemetry/{message_type}"
payload = json.dumps(asdict(msg))
if self.connected:
result = self.mqtt_client.publish(topic, payload, qos=qos)
if result.rc == mqtt.MQTT_ERR_SUCCESS:
print(f"[Telemetry] Published {message_type}")
else:
print(f"[Telemetry] Publish failed: {result.rc}")
# Buffer for later
self.offline_buffer.store(topic, payload, qos)
else:
# Store in offline buffer
self.offline_buffer.store(topic, payload, qos)
print(f"[Telemetry] Buffered {message_type} (offline)")
def _flush_offline_buffer(self):
"""Send buffered messages when connection restored."""
messages = self.offline_buffer.retrieve_all()
print(f"[Telemetry] Flushing {len(messages)} buffered messages")
for msg in messages:
self.mqtt_client.publish(msg['topic'], msg['payload'], qos=msg['qos'])
self.offline_buffer.delete(msg['id'])
def start_can_monitoring(self):
"""Start monitoring CAN bus and streaming telemetry."""
print("[Telemetry] Starting CAN bus monitoring")
# Connect to CAN bus
self.can_bus = can.interface.Bus(channel='can0', bustype='socketcan')
# Define telemetry intervals
intervals = {
'battery': 60, # Every minute
'location': 300, # Every 5 minutes
'speed': 10, # Every 10 seconds
'diagnostics': 3600, # Every hour
}
last_publish = {k: 0 for k in intervals.keys()}
while True:
# Read CAN messages
msg = self.can_bus.recv(timeout=1.0)
if msg is None:
continue
current_time = time.time()
# Process specific CAN IDs
if msg.arbitration_id == 0x123: # Battery telemetry
if current_time - last_publish['battery'] >= intervals['battery']:
battery_data = self._parse_battery_can(msg.data)
self.publish_telemetry('battery', battery_data, qos=1)
last_publish['battery'] = current_time
elif msg.arbitration_id == 0x456: # Speed/location
if current_time - last_publish['speed'] >= intervals['speed']:
speed_data = self._parse_speed_can(msg.data)
self.publish_telemetry('speed', speed_data, qos=0)
last_publish['speed'] = current_time
# Periodic location publish
if current_time - last_publish['location'] >= intervals['location']:
location_data = self._get_gps_location()
self.publish_telemetry('location', location_data, qos=1)
last_publish['location'] = current_time
def _parse_battery_can(self, data: bytes) -> dict:
"""Parse battery telemetry from CAN message."""
return {
'soc': int.from_bytes(data[0:2], 'big') / 100, # State of charge %
'voltage': int.from_bytes(data[2:4], 'big') / 10, # Volts
'current': int.from_bytes(data[4:6], 'big', signed=True) / 10, # Amps
'temperature': int.from_bytes(data[6:8], 'big') / 10 - 40, # Celsius
}
def _parse_speed_can(self, data: bytes) -> dict:
"""Parse speed telemetry from CAN message."""
return {
'speed': int.from_bytes(data[0:2], 'big') / 100, # km/h
'odometer': int.from_bytes(data[2:6], 'big') / 10, # km
}
def _get_gps_location(self) -> dict:
"""Get GPS location from GNSS receiver."""
# Read from gpsd or similar
return {
'latitude': 37.7749,
'longitude': -122.4194,
'altitude': 16.0,
'heading': 270.0,
'accuracy': 3.5
}
def _get_software_version(self) -> str:
"""Get vehicle software version."""
with open('/etc/vehicle/version', 'r') as f:
return f.read().strip()
def _collect_diagnostics(self):
"""Collect comprehensive diagnostic data."""
diagnostics = {
'dtcs': [], # Diagnostic Trouble Codes
'ecu_status': {},
'battery_health': {},
'sensor_status': {},
}
# Publish diagnostic report
self.publish_telemetry('diagnostics', diagnostics, qos=1)
def _remote_lock(self):
"""Execute remote lock command."""
# Send CAN command to lock doors
pass
def _remote_honk(self):
"""Execute remote horn activation."""
# Send CAN command to honk
pass
def disconnect(self):
"""Disconnect from MQTT broker."""
if self.mqtt_client:
self.mqtt_client.loop_stop()
self.mqtt_client.disconnect()
if self.can_bus:
self.can_bus.shutdown()
class OfflineBuffer:
"""SQLite-based offline message buffer."""
def __init__(self, db_path: str = "/var/lib/vehicle/telemetry-buffer.db"):
self.db_path = db_path
self._init_db()
def _init_db(self):
"""Initialize SQLite database."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS buffer (
id INTEGER PRIMARY KEY AUTOINCREMENT,
topic TEXT NOT NULL,
payload TEXT NOT NULL,
qos INTEGER NOT NULL,
timestamp REAL NOT NULL
)
''')
conn.commit()
conn.close()
def store(self, topic: str, payload: str, qos: int):
"""Store message in buffer."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute(
'INSERT INTO buffer (topic, payload, qos, timestamp) VALUES (?, ?, ?, ?)',
(topic, payload, qos, time.time())
)
conn.commit()
conn.close()
def retrieve_all(self) -> List[dict]:
"""Retrieve all buffered messages."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('SELECT id, topic, payload, qos FROM buffer ORDER BY timestamp')
rows = cursor.fetchall()
conn.close()
return [
{'id': row[0], 'topic': row[1], 'payload': row[2], 'qos': row[3]}
for row in rows
]
def delete(self, msg_id: int):
"""Delete message from buffer."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('DELETE FROM buffer WHERE id = ?', (msg_id,))
conn.commit()
conn.close()
def main():
"""Main telemetry client loop."""
client = VehicleTelemetryClient()
try:
client.connect()
client.start_can_monitoring()
except KeyboardInterrupt:
print("\n[Telemetry] Shutting down")
client.disconnect()
if __name__ == "__main__":
main()
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 9d ago First seen · 5,356 lines · 38 tokens per session scan A d7a4e1a98718
automotive-sdv is a skill published in the GitHub repository pangzhenying2025/hermes-automotive-skills (5 stars, last pushed 3mo ago), licensed MIT. It adds 38 tokens to every session and 36,167 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 2 findings (makes network calls, runs shell commands). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-03.
Other skills, from other repositories
apify-actor-development
Important: Before you begin, fill in the generatedBy property in the meta section of .actor/actor.json. Replace it with the tool and model you're currently using, such as "Claude Code with Claude Sonnet 4.5". This helps Apify monitor and improve AGENTS.md for specific AI tools and models.
dynamo-recipe-runner
Select, validate, patch, and deploy existing NVIDIA Dynamo Kubernetes recipes. Use for model/backend/GPU/deployment-mode recipe bring-up; use router-starter for router-only mode work and troubleshoot for broken deployments.
enterprise
Enterprise-grade systems with microservices, Kubernetes, Terraform, and AI Native methodology. For multi-feature initiatives spanning a release timeline, combine with /sprint master-plan (v2.1.13) to group features into a single 8-phase sprint container with shared scope/budget and 4 auto-pause triggers…
gcp-essentials
Use when running a small product on core Google Cloud via the gcloud CLI: a project, Cloud Run deploys, a locked-down Cloud Storage bucket, managed Cloud SQL, and least-privilege IAM wiring them together. NOT AWS (that is aws-essentials), NOT the CI pipeline that ships the image (that is deployment), NOT Postgres…
model-deployment
Deploy trained machine learning models as production-ready services using REST APIs, containers, serverless functions, and orchestration platforms. Use when the user requests model deployment or provides relevant inputs for this workflow.
configure-reverse-proxy
Configure reverse proxy patterns across multiple tools including Nginx, Traefik, and ShinyProxy. Covers WebSocket proxying, path-based and host-based routing, SSL termination, and Docker label auto-discovery. Use when routing multiple services behind a single entry point, proxying WebSocket connections (Shiny…