Operator CLI for AWS IoT Core cold chain fleets. Queries device status, telemetry history, and excursion events directly from the infrastructure deployed by aws-iot-edge-reference.
Built in Go using AWS SDK v2 and Cobra. No mock data — every command hits real AWS APIs.
iotctl fleet list List all registered Things with status
iotctl fleet status Fleet connectivity summary
iotctl device status <device-id> Latest telemetry for a device
iotctl device logs <device-id> Recent CloudWatch log events for a device
iotctl device history <device-id> Telemetry time-series from DynamoDB
iotctl excursions list Temperature excursion events across the fleet
iotctl config init Configure endpoint, table, and log group
iotctl config show Show current configuration
Every command supports --json for scripting.
$ iotctl fleet list
DEVICE ID STATUS LAST SEEN FIRMWARE TYPE
───────── ────── ───────── ──────── ────
cold-chain-sim-01 ONLINE 1s ago 2.1.0 —
$ iotctl device status cold-chain-sim-01
Device: cold-chain-sim-01
──────────────────────────────────────
Status: ONLINE
Latest telemetry — 2026-05-05T22:27:50Z (1s ago)
──────────────────────────────────────
Temperature: 2.95°C
Humidity: 65.5%
Shock: 0.020g
Battery: 100.0%
GPS: 45.507866, -122.674828
Firmware: 2.1.0
$ iotctl device logs cold-chain-sim-01
TIME EVENT TYPE TEMP °C BATTERY % SHOCK G
──── ────────── ─────── ───────── ───────
22:30:50 TELEMETRY_INGESTED 3.07°C 100.00% 0.02g
22:30:35 TELEMETRY_INGESTED 12.50°C 95.00% 0.01g
22:30:35 TEMPERATURE_EXCURSION 12.50°C — —
22:30:20 TELEMETRY_INGESTED 2.92°C 100.00% 6.38g
22:30:20 SHOCK_EVENT — — 6.38g
$ iotctl excursions list
Temperature excursions — last 24h (1 events)
TIME DEVICE TEMP °C THRESHOLD °C LATITUDE LONGITUDE
──── ────── ─────── ──────────── ──────── ─────────
2026-05-05 22:30:35 cold-chain-sim-01 12.50°C 8.00°C 47.6062 -122.3321
- Go 1.22+
- AWS credentials configured (
aws configure) - Infrastructure deployed — see
aws-iot-edge-reference
git clone https://github.com/JamesIOmete/iotctl.git
cd iotctl
go build -o iotctl .Move the binary to your PATH:
mv iotctl /usr/local/bin/Values come directly from terraform output in the aws-iot-edge-reference repo:
cd aws-iot-edge-reference/terraform
terraform output # copy the values belowiotctl config initAWS region: us-west-2
IoT Core endpoint: <value from iot_endpoint>
DynamoDB table name: <value from dynamodb_table_name>
CloudWatch log group: /aws/lambda/iot-coldchain-dev-telemetry-processor
Configuration is saved to ~/.iotctl/config.yaml.
iotctl is the operator layer that sits on top of the infrastructure in aws-iot-edge-reference. Each command maps to a specific AWS API:
| Command | AWS API |
|---|---|
fleet list |
IoT Core ListThings + DynamoDB Query for last-seen |
fleet status |
IoT Core ListThings + DynamoDB aggregate |
device status |
IoT Core DescribeThing + DynamoDB Query (limit 1) |
device history |
DynamoDB Query (newest-first, configurable depth) |
device logs |
CloudWatch Logs Insights query on Lambda processor log group |
excursions list |
CloudWatch Logs Insights filtered on event_type = TEMPERATURE_EXCURSION |
Device connectivity status is derived from telemetry recency — a device is considered ONLINE if it published within the last 5 minutes, matching the DeviceSilence alarm threshold configured in the infrastructure.
iotctl/
├── main.go
├── cmd/
│ ├── root.go # Cobra root, AWS client initialisation, --json flag
│ ├── config.go # config init / show
│ ├── fleet.go # fleet list / status
│ ├── device.go # device status / logs / history
│ └── excursions.go # excursions list
├── internal/
│ ├── aws/
│ │ ├── iot.go # IoT Core client — ListThings, DescribeThing
│ │ ├── dynamo.go # DynamoDB client — telemetry queries
│ │ └── logs.go # CloudWatch Logs Insights client
│ └── config/
│ └── config.go # config file read/write (~/.iotctl/config.yaml)
└── README.md
aws-iot-edge-reference— the infrastructure this CLI operates againsttf-plan-ai-reviewer— AI-assisted Terraform plan review used in the infrastructure repo's CI workflow
MIT