Skill: rogueecho/moonraker (version 1.0.0)

--- name: moonraker description: Control and monitor a Klipper 3D printer via the Moonraker API — print status, temps, pause, resume, cancel, emergency stop. metadata: {"openclaw":{"requires":{"env":["MOONRAKER_HOST"],"bins":["curl"]},"primaryEnv":"MOONRAKER_HOST","emoji":"🖨️"}} --- Control your 3D printer via the Moonraker REST API. - **Host:** `http://$MOONRAKER_HOST:7125` - **Helper script:** `{baseDir}/moonraker.sh` --- ## Quick Commands (via moonraker.sh) ```bash moonraker.sh status # print progress, temps, state moonraker.sh pause # pause current print moonraker.sh resume # resume paused print moonraker.sh cancel # cancel current print moonraker.sh estop # EMERGENCY STOP (firmware restart required after) moonraker.sh files # list gcode files on printer ``` --- ## API Reference Base URL: `http://$MOONRAKER_HOST:7125` ### Get Printer State ``` GET /printer/info ``` Returns firmware version, Klipper state (`ready`, `error`, `shutdown`, etc.), hostname. ### Get Print Stats + Temperatures ``` GET /printer/objects/query?print_stats&heater_bed&extruder ``` Returns: - `print_stats.state` — `standby`, `printing`, `paused`, `complete`, `error` - `print_stats.filename` — currently loaded file - `print_stats.print_duration` — seconds elapsed - `print_stats.total_duration` — total time since start - `extruder.temperature` / `extruder.target` — hotend actual/target °C - `heater_bed.temperature` / `heater_bed.target` — bed actual/target °C ### Pause Print ``` POST /printer/print/pause ``` ### Resume Print ``` POST /printer/print/resume ``` ### Cancel Print ``` POST /printer/print/cancel ``` ### Emergency Stop ``` POST /printer/emergency_stop ``` ⚠️ Immediately halts all motion and heaters. Klipper must be restarted via `POST /printer/firmware_restart` before printing again. ### List GCode Files ``` GET /server/files/list ``` Returns array of files in the `gcodes` directory with name, size, and modified time. ### Firmware Restart (after emergency stop) ``` POST /printer/firmware_restart ``` --- ## Raw curl Examples ```bash # Printer state curl -s http://$MOONRAKER_HOST:7125/printer/info | jq . # Temps + print stats curl -s "http://$MOONRAKER_HOST:7125/printer/objects/query?print_stats&heater_bed&extruder" | jq . # Pause curl -s -X POST http://$MOONRAKER_HOST:7125/printer/print/pause | jq . # Resume curl -s -X POST http://$MOONRAKER_HOST:7125/printer/print/resume | jq . # Cancel curl -s -X POST http://$MOONRAKER_HOST:7125/printer/print/cancel | jq . # Emergency stop curl -s -X POST http://$MOONRAKER_HOST:7125/printer/emergency_stop | jq . # List files curl -s http://$MOONRAKER_HOST:7125/server/files/list | jq . ``` --- ## Notes - All POST endpoints return `{"result": "ok"}` on success. - If Klipper is in error/shutdown state, most commands will fail until a firmware restart. - Progress percentage = `print_stats.print_duration / print_stats.total_duration * 100` (approximate; more accurate progress available via `virtual_sdcard` object). - For precise progress: `GET /printer/objects/query?virtual_sdcard` → `virtual_sdcard.progress` (0.0–1.0).

path: moonraker.sh
content: #!/usr/bin/env bash

HOST="http://$MOONRAKER_HOST:7125"

usage() {
    echo "Usage: moonraker.sh <command>"
    echo ""
    echo "Commands:"
    echo "  status   — show print state, progress, and temperatures"
    echo "  pause    — pause current print"
    echo "  resume   — resume paused print"
    echo "  cancel   — cancel current print"
    echo "  estop    — EMERGENCY STOP (requires firmware restart to recover)"
    echo "  files    — list gcode files on printer"
    exit 1
}

require_jq() {
    if ! command -v jq &>/dev/null; then
        echo "[warn] jq not found — raw JSON output will be shown"
        JQ_MISSING=1
    fi
}

jq_or_cat() {
    if [ "${JQ_MISSING:-0}" = "1" ]; then
        cat
    else
        jq "$@"
    fi
}

cmd_status() {
    RAW=$(curl -sf "${HOST}/printer/objects/query?print_stats&heater_bed&extruder&virtual_sdcard")
    if [ $? -ne 0 ]; then
        echo "ERROR: Could not reach Moonraker at ${HOST}"
        exit 1
    fi

    if command -v jq &>/dev/null; then
        STATE=$(echo "$RAW" | jq -r '.result.status.print_stats.state // "unknown"')
        FILENAME=$(echo "$RAW" | jq -r '.result.status.print_stats.filename // "none"')
        PROGRESS=$(echo "$RAW" | jq -r '(.result.status.virtual_sdcard.progress // 0) * 100 | floor | tostring + "%"')
        HOTEND=$(echo "$RAW" | jq -r '.result.status.extruder.temperature // 0 | floor | tostring')
        HOTEND_TARGET=$(echo "$RAW" | jq -r '.result.status.extruder.target // 0 | floor | tostring')
        BED=$(echo "$RAW" | jq -r '.result.status.heater_bed.temperature // 0 | floor | tostring')
        BED_TARGET=$(echo "$RAW" | jq -r '.result.status.heater_bed.target // 0 | floor | tostring')

        echo "=== Printer Status ==="
        echo "State      : ${STATE}"
        echo "File       : ${FILENAME}"
        echo "Progress   : ${PROGRESS}"
        echo "Hotend     : ${HOTEND}°C / ${HOTEND_TARGET}°C (target)"
        echo "Bed        : ${BED}°C / ${BED_TARGET}°C (target)"
    else
        echo "$RAW"
    fi
}

cmd_pause() {
    echo "Pausing print..."
    curl -sf -X POST "${HOST}/printer/print/pause" | jq_or_cat .
}

cmd_resume() {
    echo "Resuming print..."
    curl -sf -X POST "${HOST}/printer/print/resume" | jq_or_cat .
}

cmd_cancel() {
    echo "Cancelling print..."
    curl -sf -X POST "${HOST}/printer/print/cancel" | jq_or_cat .
}

cmd_estop() {
    echo "⚠️  EMERGENCY STOP — all motion and heaters will halt immediately."
    echo "    Run 'curl -X POST ${HOST}/printer/firmware_restart' to recover."
    curl -sf -X POST "${HOST}/printer/emergency_stop" | jq_or_cat .
}

cmd_files() {
    RAW=$(curl -sf "${HOST}/server/files/list")
    if [ $? -ne 0 ]; then
        echo "ERROR: Could not reach Moonraker at ${HOST}"
        exit 1
    fi

    if command -v jq &>/dev/null; then
        echo "=== GCode Files ==="
        echo "$RAW" | jq -r '.result[] | "\(.filename)  (\(.size / 1024 | floor) KB)"' 2>/dev/null \
            || echo "$RAW" | jq -r '.result[].filename'
    else
        echo "$RAW"
    fi
}

require_jq

case "${1:-}" in
    status) cmd_status ;;
    pause)  cmd_pause ;;
    resume) cmd_resume ;;
    cancel) cmd_cancel ;;
    estop)  cmd_estop ;;
    files)  cmd_files ;;
    *)      usage ;;
esac


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)