{"id":"d137949b-8de6-45ad-a736-8577c14c2e50","entityType":"agent","slug":"clawhub-wudi488-nas-dashboard","name":"NAS Dashboard","canonicalUrl":"https://www.xpersona.co/agent/clawhub-wudi488-nas-dashboard","canonicalPath":"/agent/clawhub-wudi488-nas-dashboard","generatedAt":"2026-10-11T07:41:39.270Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T05:35:33.156Z","emptyReason":null},"description":"Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Us... Skill: NAS Dashboard Owner: wudi488 Summary: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Us... Tags: latest:3.0.1 Version history: v3.0.1 | 2026-05-31T09:59:24.624Z | user v3.0.1: 📢 更新营销描述——明确目标用户(自建NAS/HomeLab/自托管服务)、最佳使用环境(Ubuntu+ZFS+Docker+UPS)、一句话价值主张(每天早上看一眼🔴红灯，有就照着修)。 v3.0.0 | 2026-05-31T09:58:20.769","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17adk7beyrksqxwmwvwhhe5an83gzyp:nas-dashboard","sourceUrl":"https://clawhub.ai/wudi488/nas-dashboard","homepage":"https://clawhub.ai/wudi488/skills/nas-dashboard","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/wudi488/nas-dashboard","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/wudi488/skills/nas-dashboard","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Us..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T05:35:33.156Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T05:35:33.156Z","emptyReason":null},"stars":null,"forks":null,"downloads":1145,"packageName":null,"latestVersion":"3.0.1","tractionLabel":"1.1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T05:35:33.095Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T05:35:33.156Z","lastCrawledAt":"2026-10-11T05:35:33.095Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T05:35:33.095Z","lastVerifiedAt":null,"highlights":[{"version":"3.0.1","createdAt":"2026-05-31T09:59:24.624Z","changelog":"v3.0.1: 📢 更新营销描述——明确目标用户(自建NAS/HomeLab/自托管服务)、最佳使用环境(Ubuntu+ZFS+Docker+UPS)、一句话价值主张(每天早上看一眼🔴红灯，有就照着修)。","fileCount":6,"zipByteSize":22487},{"version":"3.0.0","createdAt":"2026-05-31T09:58:20.769Z","changelog":"v3.0.0: Environment-aware security assessment, three-tier severity, action guide, compact mode, container image age, SSH/firewall/port audit, all-in-one.sh, fallback chain.","fileCount":6,"zipByteSize":22174},{"version":"2.0.1","createdAt":"2026-05-19T14:18:03.388Z","changelog":"修复 Timeshift 快照计数 bug：RSYNC 模式下误将备份日志文件数当作快照数，改用 sudo timeshift --list 获取真实快照数","fileCount":4,"zipByteSize":13371},{"version":"2.0.0","createdAt":"2026-05-18T08:00:33.634Z","changelog":"v2.0.0 — 异常导向重构 🚨 新增风险预警模块: 全系统异常扫描并置顶展示，无事不显示 🐳 Docker 收敛: 15 容器从逐行罗列压缩为汇总行+仅列无健康检查项 💾 磁盘-ZFS 关联: 每块盘标注所属存储池角色 (tank) 🔍 SMART 细粒度: 新增 realloc/pending/udma 三项核心坏道指标 📹 Frigate 智能过滤: 正常摄像头一行带过，丢帧路展开丢帧率百分比 🔗 联动诊断: xunlei 容器无健康检查+高CPU → 僵死进程预警 ⏱ 时间统一: 全部 YYYY-MM-DD HH:MM 格式 ⚠️ Timeshift 健康检查: >100 警告, >300 严重告警 📐 DISKS 固定列宽表格: │ 分隔符 + 右对齐状态列 📊 进程模块精简: top 3 CPU/MEM 替代 top 5","fileCount":3,"zipByteSize":11930},{"version":"1.0.0","createdAt":"2026-05-17T13:56:39.841Z","changelog":"Initial release: 16-section text dashboard with ZFS, SMART, Docker, Frigate, GPU, UPS, Timeshift. Unicode progress bars + box-drawing layout.","fileCount":3,"zipByteSize":7681}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17adk7beyrksqxwmwvwhhe5an83gzyp:nas-dashboard","setupComplexity":"medium","setupSteps":["Setup complexity is MEDIUM. Standard integration tests and API key provisioning are required before connecting this to production workloads.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T07:41:39.267Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-wudi488-nas-dashboard/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-11T05:35:33.156Z","emptyReason":null},"readme":"Skill: NAS Dashboard\n\nOwner: wudi488\n\nSummary: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Us...\n\nTags: latest:3.0.1\n\nVersion history:\n\nv3.0.1 | 2026-05-31T09:59:24.624Z | user\n\nv3.0.1: 📢 更新营销描述——明确目标用户(自建NAS/HomeLab/自托管服务)、最佳使用环境(Ubuntu+ZFS+Docker+UPS)、一句话价值主张(每天早上看一眼🔴红灯，有就照着修)。\n\nv3.0.0 | 2026-05-31T09:58:20.769Z | user\n\nv3.0.0: Environment-aware security assessment, three-tier severity, action guide, compact mode, container image age, SSH/firewall/port audit, all-in-one.sh, fallback chain.\n\nv2.0.1 | 2026-05-19T14:18:03.388Z | user\n\n修复 Timeshift 快照计数 bug：RSYNC 模式下误将备份日志文件数当作快照数，改用 sudo timeshift --list 获取真实快照数\n\nv2.0.0 | 2026-05-18T08:00:33.634Z | user\n\nv2.0.0 — 异常导向重构\n\n🚨 新增风险预警模块: 全系统异常扫描并置顶展示，无事不显示\n🐳 Docker 收敛: 15 容器从逐行罗列压缩为汇总行+仅列无健康检查项\n💾 磁盘-ZFS 关联: 每块盘标注所属存储池角色 (tank)\n🔍 SMART 细粒度: 新增 realloc/pending/udma 三项核心坏道指标\n📹 Frigate 智能过滤: 正常摄像头一行带过，丢帧路展开丢帧率百分比\n🔗 联动诊断: xunlei 容器无健康检查+高CPU → 僵死进程预警\n⏱ 时间统一: 全部 YYYY-MM-DD HH:MM 格式\n⚠️ Timeshift 健康检查: >100 警告, >300 严重告警\n📐 DISKS 固定列宽表格: │ 分隔符 + 右对齐状态列\n📊 进程模块精简: top 3 CPU/MEM 替代 top 5\n\nv1.0.0 | 2026-05-17T13:56:39.841Z | user\n\nInitial release: 16-section text dashboard with ZFS, SMART, Docker, Frigate, GPU, UPS, Timeshift. Unicode progress bars + box-drawing layout.\n\nArchive index:\n\nArchive v3.0.1: 6 files, 22487 bytes\n\nFiles: all-in-one.sh (439b), scripts/collect.sh (16186b), scripts/format.py (16427b), skill-card.md (2189b), SKILL.md (16593b), _meta.json (132b)\n\nFile v3.0.1:SKILL.md\n\n---\nname: nas-dashboard\ndescription: >-\n  🏠 NAS Dashboard v3 — 环境感知的智能运维仪表盘。\n  \n  **适合谁**：自建 NAS / HomeLab / 家庭服务器用户，跑了 ZFS + Docker + 一堆自托管服务，需要一个\"一眼看清问题、告诉你修什么\"的每日健康报告。\n  \n  **做什么**：一键采集系统全貌（ZFS/磁盘SMART/Docker/Frigate摄像头/GPU/UPS/安全审计），环境感知评估（内网/公网分级），三级严重度（🔴紧急🟡关注🟢参考），每条告警附带评估原因+可执行修复命令。\n  \n  **最佳环境**：Ubuntu/Debian + ZFS + Docker，有 UPS 和 Frigate NVR 效果最佳。支持 Telegram 每日推送。\n  \n  **一句话**：不用天天盯着服务器，每天早上看一眼有没有🔴，有就照着修。\n\n  Triggers: \"nas status\", \"server status\", \"system dashboard\", \"文本仪表盘\", \"服务器状态\", \"系统健康\".\n\n# NAS Dashboard v3\n\nException-driven, alert-first text dashboard for NAS/HomeLab monitoring. Prioritises problems over green lights — if everything is healthy you get a one-liner, if something is wrong you get a surgical report with **severity ratings** and **actionable fix commands**.\n\n**Platform**: Linux (Ubuntu/Debian tested). Partial support: any Linux with ZFS. macOS/Windows: most sections unavailable (ZFS, SMART, systemd, apt, iostat, sensors are Linux-only).\n\n## Design Principles\n\n1. **Alerts First**: ❌/⚠️ always on top. No alerts → no ALERTS section.\n2. **Normal is Invisible**: Don't list 15 healthy containers. Collapse to \"X running (Y OK)\".\n3. **Contextual Correlation**: Disk ↔ ZFS vdev, container unhealthy + CPU process = zombie.\n4. **Actionable Thresholds**: Timeshift >100 warns, SMART realloc>0 alarms, disk>45°C flags.\n5. **Unified Timestamps**: All times in `YYYY-MM-DD HH:MM` or `XdXh` relative.\n\n## Quick Start\n\n### Configure (optional)\n\n```bash\nexport ZPOOL=\"tank\"              # default: auto-detect first pool\nexport DISK_LIST=\"sda sdb sdc\"   # default: auto-detect all /dev/sd?\nexport FRIGATE_CAM_MAP=\"cam_d82e8e00:客厅,cam_ae7e3010:门口,cam_a24a20c0:车库\"\nexport UPS_NAME=\"ups@localhost\"  # default: ups@localhost\n```\n\n### Run\n\n```bash\nbash scripts/collect.sh\n```\n\n### Cron setup\n\n```bash\nopenclaw cron add \\\n  --name \"NAS仪表盘\" \\\n  --schedule \"0 9 * * *\" \\\n  --agent main \\\n  --timeout 180 \\\n  --delivery \"announce:telegram:YOUR_CHAT_ID\" \\\n  --prompt \"Run nas-dashboard skill: collect and format the dashboard report, then send to Telegram.\"\n```\n\n## Workflow\n\n### 1. Collect data\n\nRun `scripts/collect.sh`. Sections: SYSTEM, ZFS, VDEV_DISK (disk→pool mapping), DISKS (incl. SMART realloc/pending/udma), DISKIO, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT.\n\n### 2. Format output — Alert-First Layout\n\n#### Step 0: Scan for Alerts (always do this first)\n\nScan ALL collected data against these thresholds and classify severity:\n\n| Scope | Condition | Severity |\n|-------|-----------|----------|\n| Pool health ≠ ONLINE | any pool | ❌ CRITICAL |\n| Scrub errors > 0 | any pool | ❌ CRITICAL |\n| ZFS_EVENT present | any event | ⚠️ WARNING |\n| Disk health ≠ PASSED | any disk | ❌ CRITICAL |\n| Disk realloc > 0 | any disk | ❌ CRITICAL |\n| Disk pending > 0 | any disk | ⚠️ WARNING |\n| Disk udma_crc > 100 | any disk | ⚠️ WARNING |\n| Disk temp > 45°C | any disk | ⚠️ WARNING |\n| Disk temp > 55°C | any disk | ❌ CRITICAL |\n| Disk r_await > 20ms or w_await > 20ms | any disk | ⚠️ WARNING |\n| Docker container Down/Unhealthy | any ctr | ⚠️ WARNING |\n| Frigate camera skip > 1.0 | any camera | ⚠️ WARNING |\n| Frigate camera fps = 0 | any camera | ❌ CRITICAL |\n| Frigate storage > 80% | any storage | ⚠️ WARNING |\n| Frigate storage > 95% | any storage | ❌ CRITICAL |\n| Timeshift count > 100 | ts active | ⚠️ WARNING |\n| Timeshift count > 300 | ts active | ❌ CRITICAL |\n| CPU temp > 70°C | | ⚠️ WARNING |\n| CPU temp > 85°C | | ❌ CRITICAL |\n| GPU temp > 75°C | | ⚠️ WARNING |\n| GPU temp > 85°C | | ❌ CRITICAL |\n| ARC hit rate < 90% | | ⚠️ WARNING |\n| ZFS capacity > 80% | | ⚠️ WARNING |\n| ZFS capacity > 90% | | ❌ CRITICAL |\n| Root disk > 85% | | ⚠️ WARNING |\n| Root disk > 95% | | ❌ CRITICAL |\n| Failed logins > 0 | today | ⚠️ WARNING |\n| Failed systemd services | any | ⚠️ WARNING |\n| UPS ≠ OL (not Online) | | ⚠️ WARNING |\n| UPS battery < 50% | | ⚠️ WARNING |\n| OOM events present | | ⚠️ WARNING |\n| SSH pass auth on | sshd | ⚠️ WARNING |\n| SSH root login on | sshd | ⚠️ WARNING |\n| Firewall inactive | ufw/iptables | ⚠️ WARNING |\n| Container image >6mo | Docker | ℹ️ INFO |\n| APT updates available | | ℹ️ INFO |\n\nIf **0 alerts**: skip the `🚨 风险预警` section entirely.\n\nIf **alerts exist**: build `🚨 风险预警` section listing every alert, grouped by severity (❌ first, then ⚠️, then ℹ️). Format:\n\n```\n🚨 风险预警\n❌ {description}\n⚠️ {description}\n```\n\n#### Step 1: Build ALERTS Section (if any)\n\nSort by severity: ❌ CRITICAL → ⚠️ WARNING → ℹ️ INFO. One line per alert. Examples:\n- `❌ sde (tank) Reallocated_Sector_Ct: 5 — 坏道增长，建议立即更换`\n- `⚠️ cam_a24a20c0 skip:2.4 — 解码丢帧，检查 GPU 或降低分辨率`\n- `⚠️ nextcloud (Docker) unhealthy — 容器异常`\n- `⚠️ nfs-server (service) inactive — NFS 服务未运行`\n- `⚠️ Timeshift: 430 snaps — 过多，建议清理 (>100)`\n- `⚠️ sde udma_crc:29 — SATA 链路错误`\n- `ℹ️ 0 APT updates pending`\n\n**Correlation rules** (apply these when building alerts):\n- If a Docker container is unhealthy AND a process with the same name has >1% CPU → append `(疑似僵死进程，建议重启容器)`\n- If a Frigate camera has skip>1.0 AND GPU utilization is high → append `(GPU 编码瓶颈)`\n- If a disk has udma>0 → mention potential SATA cable issue\n\n#### Step 2: Build Dashboard Body\n\nUse this compact layout. **Omit sections entirely if no data or all is healthy and not noteworthy.**\n\n```\n╭──────────────────────────────────╮\n│  🏠 NAS Dashboard · {YYYY-MM-DD (周X)}  │\n╰──────────────────────────────────╯\n```\n\nThen sections in order:\n\n**🖥 SYSTEM** — one line:\n```\n🖥 {hostname} · {OS_short} · up {uptime_simplified} · load:{load_1min}\n   CPU:{cpu_used%} ██████░░░░ · RAM:{mem_used}/{mem_total} ({mem_pct}) · / {root_used}/{root_total} ({root_pct})\n   CPU:{cpu_temp°C} · Mobo:{hottest_mobo_temp}°C\n```\n- `uptime_simplified`: convert \"1 week, 2 days, 18 hours\" → \"1w2d18h\"\n- `OS_short`: \"Ubuntu 24.04\" from \"Ubuntu 24.04.4 LTS\"\n- Only show the single highest mobo temp (not all sensors)\n- CPU progress bar: 10 chars, cpu_used/10 → `█` count\n\n**🗄 ZFS** — pool summary line + ARC line:\n```\n🗄 {pool} [{health_emoji} {health}] · {alloc}T/{size}T ({cap}%) ██████░░░░ · frag:{frag}%\n   ARC:{arc_size}GiB/{arc_max}GiB · hit:{arc_hit}% · Scrub:{scrub_summary}\n```\n- Scrub summary: extract \"repaired 0B, 0 errors\" and date from SCRUB field\n- If L2ARC size > 0: append `· L2ARC:{l2_size}GiB hit:{l2_hit}%`\n- ZFS capacity bar: cap/10 → `█` count\n- If ARC hit < 90%: add ⚠️ prefix\n- Snapshots: `Snaps:{count} latest:{yyyy-mm-dd}`\n\n**💾 DISKS** — fixed-width column layout, one line per disk.\n\nUse a mini-table with `│` separators so all status emoji align vertically:\n\n```\n💾 DISKS ───────────────────────────────────\nsda (tank) │ W1003ABYZ-011FA0 │  931G │ 42°C │ 10909h │              ✅\nsdc (tank) │ WD10PURX-78D85Y0 │  931G │ 39°C │  6804h │ r_await:10ms ✅\nsde (tank) │ ST1000DM003-1ER16 │  931G │ 36°C │ 10223h │  udma:29     ✅\n```\n\nColumn widths (pad/crop each field to fit):\n| Col | Field | Width | Align |\n|-----|-------|-------|-------|\n| 1 | `{disk} ({pool_role})` | 9 | left |\n| 2 | model name | 18 | left, truncate if longer |\n| 3 | size | 6 | right |\n| 4 | temp | 5 | right |\n| 5 | hours | 7 | right |\n| 6 | alerts + status | 14 | right |\n\n- Col 6 (alerts + status): padding is dynamic but right-aligned. Contents:\n  - `realloc:X` if > 0 (else pad)\n  - `pending:X` if > 0 (else pad)\n  - `udma:X` if > 0 (else pad)\n  - `r_await:Xms` if > 5ms (else pad)\n  - Always end with `✅` (PASSED) or `❌` (FAIL)\n- Use VDEV_DISK data to annotate pool role: `sda (tank)`, `sdb (tank-cache)` etc.\n- Model: use full model string, crop to 18 chars if longer\n- ⚠️ prefix the whole line if temp>45°C or realloc>0 or pending>0 or udma>100\n- Serial is omitted (model provides enough identification for this view)\n\n**Disk I/O** — only show disks with util>5% or await>10ms:\n```\n   IO: sda r2.5/w4.6ms util5.2% · sdc r10.5/w3.3ms\n```\n\n**🐳 DOCKER** — converged view:\n```\n🐳 {total} running ({healthy_count} healthy) · v{docker_ver} · {image_count} imgs · {volume_gb}GB\n```\nThen only list unhealthy containers explicitly:\n```\n   ⚠️ nextcloud: Up 2 days (no healthcheck)\n   ℹ️ vaultwarden/server:latest: 4 months old (consider updating)\n   ⚠️ xunlei: Up 2 days (no healthcheck) [CPU 11.2% — 疑似僵死]\n```\n- `healthy_count`: count of containers with \"(healthy)\" in status\n- List containers WITHOUT \"(healthy)\" suffix under ⚠️\n- If a container appears in TOP_CPU with same name → add `[CPU X% — 疑似僵死]`\n- **Image staleness**: check IMG_AGE data; flag images older than 6 months with ℹ️\n- Images: extract total size and reclaimable from DOCKER_DF\n- If reclaimable > 10GB: `· {reclaimable} reclaimable ⚠️`\n- If ALL containers are healthy: omit the detail lines, just show the summary\n\n**📹 FRIGATE** — cameras, only expand problem ones:\n```\n📹 3 cams · detection:{det_fps}fps · infer:{infer_ms}ms\n   ✅ cam_d82e8e00: 5.1fps · ✅ cam_ae7e3010: 5.1fps\n   ⚠️ cam_a24a20c0: 4.9fps · skip:2.4 (丢帧 49%)\n```\n- Map camera IDs to friendly names via `FRIGATE_CAM_MAP` env var\n- Show ALL camera names with fps (even healthy, but compact inline)\n- Cameras with skip>0.5: show skip value + calculated drop percentage `(skip/fps*100)`\n- Cameras with skip≤0.5: just show `✅ name: fps`\n- Storage: `📀 {path}: {used}G/{total}G ({pct}%)` for each FRIGATE_STORAGE line. ⚠️ if >80%.\n- If Frigate unreachable: `📹 Frigate: no response ❌`\n\n**🎮 GPU** — one line:\n```\n🎮 {gpu_model} · {temp}°C · {util}% · VRAM:{used}M/{total}M · {proc_count} procs\n```\n- VRAM bar: 10 chars proportional\n- Omit GPU entirely if nvidia-smi not available or no GPU detected\n\n**🌐 NETWORK** — one line per active interface:\n```\n🌐 enp4s0: {ip} · ↓{total_rx} ↑{total_tx}\n```\n- Skip DOWN interfaces\n- Traffic: use TRAFFIC data, convert to human-readable (GB/MB)\n\n**📊 PROCESSES** — top 3 CPU only (compact):\n```\n📊 CPU: xunlei 11.2% · ffmpeg 3.6% · python3 3.1%\n   MEM: python3 3.6% · node 2.8% · gnome-shell 1.4%\n```\n\n**⚙️ SERVICES** — only show non-active or failed:\n```\n⚙️ ⚠️ nfs-server: inactive · 1 failed unit: snap.firmware-updater\n```\n- If all services active and no failed units: omit this section entirely\n\n**🔒 SECURITY** — compact with full audit:\n```\n🔒 Failed logins: {count} · Boot: {boot_time_YYYY-MM-DD HH:MM} ({Xd} ago)\n   SSH: port:{port} · root:{yes/no} · pass:{yes/no} · key:{yes/no}\n   FW: {ufw/iptables status} ({n} rules) · Ports: {open_ports_list}\n```\n- SSH_PASS_AUTH=yes → ⚠️ alert (建议禁密码仅用密钥)\n- SSH_ROOT_LOGIN=yes → ⚠️ alert (建议禁root直接登录)\n- FW_UFW=inactive or FW_TYPE=none → ⚠️ alert (防火墙未启用)\n- Convert OPEN_PORTS comma list to compact format: \"22,80,443,8972,8973\"\n- Last logins: extract latest entry, reformat to \"user from ip at YYYY-MM-DD HH:MM\"\n- If failed_logins = 0 → `Failed logins: 0`\n- If fail2ban active → append `· f2b active`\n\n**🔋 UPS** — one line:\n```\n🔋 {status_icon} {status_text} · charge:{batt_charge}% · load:{ups_load}% · in:{input_v}V · batt:{batt_v}V\n```\n- `OL` → ⚡Online, `OB` → 🪫Battery, `OB DISCHRG` → 🪫Discharging\n\n**💾 TIMESHIFT** — one line with health check:\n```\n💾 Timeshift: {count} snaps · latest:{YYYY-MM-DD HH:MM}\n```\n- If 100 < count ≤ 300: append `⚠️ 过多，建议清理`\n- If count > 300: append `❌ 严重过多 (>300)，立即清理！`\n\n**📦 UPDATES** — only if > 0:\n```\n📦 {count} APT updates available\n```\n\n**🔧 OOM / Logs** — only if data present:\n```\n🔧 OOM: {oom_line_truncated}\n```\n\n#### Step 3: Final Assembly — Compact Mode\n\n1. Title line (single row with date)\n2. 🚨 ALERTS (if any) — combined, no section header duplication\n3. `━━━━` divider (4 chars, not full-width)\n4. Body sections — **merge related sections inline**:\n   - 🖥 SYSTEM + 🌐 NETWORK on one block (host info → IP inline)\n   - 🗄 ZFS + 💾 DISKS as one storage block\n   - 🐳 DOCKER + 📹 FRIGATE as one container block\n   - 🔒 SECURITY as standalone (important)\n   - 📊 PROCESSES: only show if CPU>50% or unusual\n   - ⚙️ SERVICES: only show failed\n   - 🔋 UPS + 💾 TIMESHIFT + 📦 UPDATES as footer row\n5. Keep total output under 2000 chars\n6. **Omitting rules**:\n   - Omit DISKIO if all util<5%\n   - Omit PROCESSES if CPU<50% and no anomalies\n   - Omit SERVICES if all active\n   - Omit LOGS if no errors\n   - Omit UPDATES if 0 pending\n   - Omit GPU if nvidia-smi unavailable\n\n### 3. Deliver\n\nUse `message` tool with `action=send` to the target channel.\n\n## Prerequisites\n\n| Tool | Required for | Package |\n|------|-------------|---------|\n| zpool/zfs | ZFS section | zfsutils-linux |\n| smartctl | Disk health | smartmontools |\n| docker | Docker section | docker-ce |\n| nvidia-smi | GPU section | nvidia-driver |\n| iostat | Disk I/O | sysstat |\n| sensors | Temperatures | lm-sensors |\n| upsc | UPS section | nut-client |\n| journalctl | Logs | systemd (built-in) |\n\nSMART, auth.log, and zpool events need `sudo -n` (passwordless sudo). Sections degrade gracefully if unavailable.\n\n## Threshold Reference\n\n| Metric | ⚠️ Warning | ❌ Critical |\n|--------|-----------|-------------|\n| Disk temp | >45°C | >55°C |\n| CPU temp | >70°C | >85°C |\n| GPU temp | >75°C | >85°C |\n| ZFS capacity | >80% | >90% |\n| Root disk | >85% | >95% |\n| ARC hit rate | <90% | — |\n| Disk r_await/w_await | >20ms | — |\n| Frigate skip | >1.0fps | >3.0fps |\n| Frigate storage | >80% | >95% |\n| Frigate camera fps | <1.0 | =0 |\n| Timeshift snaps | >100 | >300 |\n| realloc (SMART 5) | — | >0 |\n| pending (SMART 197) | >0 | >10 |\n| udma_crc (SMART 199) | >100 | >1000 |\n| UPS battery | <50% | <20% |\n| Disk I/O util | >50% | >80% |\n\n## Notes\n\n- All personal data (hostname, IPs, disk serials) is read at runtime, not hardcoded.\n- Camera name mapping is configurable via `FRIGATE_CAM_MAP` env var: `cam_id:Name,cam_id:Name`\n- Pool name auto-detected from `zpool list`. Override with `ZPOOL` env var.\n- Disk list auto-detected from `lsblk`. Override with `DISK_LIST` env var.\n- Suitable for publishing to ClawHub — contains no credentials, tokens, or fixed identifiers.\n\n## Changelog\n\n### v3.0.0 (2026-05-31)\n- **Environment-aware security assessment**: distinguishes LAN vs public internet, adjusts severity\n- **Three-tier severity**: 🔴 Critical / 🟡 Warning / 🟢 Info with summary count in header\n- **Action guide**: each alert now includes root cause explanation + concrete fix commands\n- **Compact mode**: merged redundant sections, total output under 2000 chars\n- **all-in-one.sh**: collect + format in single script (5s), agent only executes + sends\n- **Container image age tracking**: flags Docker images older than 6 months\n- **SSH config audit**: port, password auth, root login checks\n- **Firewall + open ports audit**: ufw/iptables status, listening port enumeration\n- **Fallback model chain**: Deepseek-Flash → MiniMax on timeout\n\n### v2.0.0 (2026-05-19)\n- Alert-first layout with 🚨 risk warning section\n- Fixed-width DISKS table with SMART realloc/pending/udma columns\n- ZFS ARC/L2ARC hit rate monitoring\n- Docker healthcheck + zombie process correlation\n- Frigate camera skip/drop detection with GPU bottleneck correlation\n\n### v1.0.0 (2026-05-17)\n- Initial release: 16-module text dashboard\n- SYSTEM, ZFS, DISKS, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT\n\nFile v3.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn764er6cp7n2yqb0wch6zx1dn83h07f\",\n  \"slug\": \"nas-dashboard\",\n  \"version\": \"3.0.1\",\n  \"publishedAt\": 1780221564624\n}\n\nFile v3.0.1:skill-card.md\n\n## Description:\n\nGenerates an alert-first text NAS and HomeLab dashboard covering system health, ZFS pools, disk SMART status, Docker, Frigate, GPU, UPS, backups, updates, and security checks.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[wudi488](https://clawhub.ai/user/wudi488)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nNAS, HomeLab, and self-hosted service operators use this skill to collect a daily health report and prioritize issues that need attention. It is best suited for Linux hosts running ZFS, Docker, UPS monitoring, and optional Frigate or NVIDIA GPU workloads.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The report may include sensitive infrastructure and security details, especially when delivered to Telegram.\n\nMitigation: Send reports only to trusted private destinations and treat dashboard output as operationally sensitive.\n\nRisk: Collection depends on passwordless sudo for host, SMART, firewall, SSH, and backup checks.\n\nMitigation: Use a tightly scoped sudoers policy for the required diagnostics instead of broad passwordless sudo.\n\nRisk: The dashboard can print privileged repair commands for storage, SSH, firewall, updates, and backups.\n\nMitigation: Review each command manually before execution and confirm it matches the host's storage, network, and backup configuration.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/wudi488/skills/nas-dashboard)\n- [Packaged skill instructions](artifact/SKILL.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, shell commands, configuration, guidance]\n\n**Output Format:** [Plain text dashboard report with inline shell commands]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Alert-first report intended to stay under 2000 characters, with severity labels and action guidance.]\n\n## Skill Version(s):\n\n3.0.1 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v3.0.0: 6 files, 22174 bytes\n\nFiles: all-in-one.sh (439b), scripts/collect.sh (16186b), scripts/format.py (16427b), skill-card.md (2580b), SKILL.md (16135b), _meta.json (132b)\n\nFile v3.0.0:SKILL.md\n\n---\nname: nas-dashboard\ndescription: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Use when the user asks for NAS status, system overview, dashboard, or wants a comprehensive system monitoring report. Linux/ZFS focused; best on Ubuntu/Debian with ZFS+NUT+Docker. Also triggers on \"文本仪表盘\", \"nas status\", \"server status\", \"system dashboard\".\n---\n\n# NAS Dashboard v3\n\nException-driven, alert-first text dashboard for NAS/HomeLab monitoring. Prioritises problems over green lights — if everything is healthy you get a one-liner, if something is wrong you get a surgical report with **severity ratings** and **actionable fix commands**.\n\n**Platform**: Linux (Ubuntu/Debian tested). Partial support: any Linux with ZFS. macOS/Windows: most sections unavailable (ZFS, SMART, systemd, apt, iostat, sensors are Linux-only).\n\n## Design Principles\n\n1. **Alerts First**: ❌/⚠️ always on top. No alerts → no ALERTS section.\n2. **Normal is Invisible**: Don't list 15 healthy containers. Collapse to \"X running (Y OK)\".\n3. **Contextual Correlation**: Disk ↔ ZFS vdev, container unhealthy + CPU process = zombie.\n4. **Actionable Thresholds**: Timeshift >100 warns, SMART realloc>0 alarms, disk>45°C flags.\n5. **Unified Timestamps**: All times in `YYYY-MM-DD HH:MM` or `XdXh` relative.\n\n## Quick Start\n\n### Configure (optional)\n\n```bash\nexport ZPOOL=\"tank\"              # default: auto-detect first pool\nexport DISK_LIST=\"sda sdb sdc\"   # default: auto-detect all /dev/sd?\nexport FRIGATE_CAM_MAP=\"cam_d82e8e00:客厅,cam_ae7e3010:门口,cam_a24a20c0:车库\"\nexport UPS_NAME=\"ups@localhost\"  # default: ups@localhost\n```\n\n### Run\n\n```bash\nbash scripts/collect.sh\n```\n\n### Cron setup\n\n```bash\nopenclaw cron add \\\n  --name \"NAS仪表盘\" \\\n  --schedule \"0 9 * * *\" \\\n  --agent main \\\n  --timeout 180 \\\n  --delivery \"announce:telegram:YOUR_CHAT_ID\" \\\n  --prompt \"Run nas-dashboard skill: collect and format the dashboard report, then send to Telegram.\"\n```\n\n## Workflow\n\n### 1. Collect data\n\nRun `scripts/collect.sh`. Sections: SYSTEM, ZFS, VDEV_DISK (disk→pool mapping), DISKS (incl. SMART realloc/pending/udma), DISKIO, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT.\n\n### 2. Format output — Alert-First Layout\n\n#### Step 0: Scan for Alerts (always do this first)\n\nScan ALL collected data against these thresholds and classify severity:\n\n| Scope | Condition | Severity |\n|-------|-----------|----------|\n| Pool health ≠ ONLINE | any pool | ❌ CRITICAL |\n| Scrub errors > 0 | any pool | ❌ CRITICAL |\n| ZFS_EVENT present | any event | ⚠️ WARNING |\n| Disk health ≠ PASSED | any disk | ❌ CRITICAL |\n| Disk realloc > 0 | any disk | ❌ CRITICAL |\n| Disk pending > 0 | any disk | ⚠️ WARNING |\n| Disk udma_crc > 100 | any disk | ⚠️ WARNING |\n| Disk temp > 45°C | any disk | ⚠️ WARNING |\n| Disk temp > 55°C | any disk | ❌ CRITICAL |\n| Disk r_await > 20ms or w_await > 20ms | any disk | ⚠️ WARNING |\n| Docker container Down/Unhealthy | any ctr | ⚠️ WARNING |\n| Frigate camera skip > 1.0 | any camera | ⚠️ WARNING |\n| Frigate camera fps = 0 | any camera | ❌ CRITICAL |\n| Frigate storage > 80% | any storage | ⚠️ WARNING |\n| Frigate storage > 95% | any storage | ❌ CRITICAL |\n| Timeshift count > 100 | ts active | ⚠️ WARNING |\n| Timeshift count > 300 | ts active | ❌ CRITICAL |\n| CPU temp > 70°C | | ⚠️ WARNING |\n| CPU temp > 85°C | | ❌ CRITICAL |\n| GPU temp > 75°C | | ⚠️ WARNING |\n| GPU temp > 85°C | | ❌ CRITICAL |\n| ARC hit rate < 90% | | ⚠️ WARNING |\n| ZFS capacity > 80% | | ⚠️ WARNING |\n| ZFS capacity > 90% | | ❌ CRITICAL |\n| Root disk > 85% | | ⚠️ WARNING |\n| Root disk > 95% | | ❌ CRITICAL |\n| Failed logins > 0 | today | ⚠️ WARNING |\n| Failed systemd services | any | ⚠️ WARNING |\n| UPS ≠ OL (not Online) | | ⚠️ WARNING |\n| UPS battery < 50% | | ⚠️ WARNING |\n| OOM events present | | ⚠️ WARNING |\n| SSH pass auth on | sshd | ⚠️ WARNING |\n| SSH root login on | sshd | ⚠️ WARNING |\n| Firewall inactive | ufw/iptables | ⚠️ WARNING |\n| Container image >6mo | Docker | ℹ️ INFO |\n| APT updates available | | ℹ️ INFO |\n\nIf **0 alerts**: skip the `🚨 风险预警` section entirely.\n\nIf **alerts exist**: build `🚨 风险预警` section listing every alert, grouped by severity (❌ first, then ⚠️, then ℹ️). Format:\n\n```\n🚨 风险预警\n❌ {description}\n⚠️ {description}\n```\n\n#### Step 1: Build ALERTS Section (if any)\n\nSort by severity: ❌ CRITICAL → ⚠️ WARNING → ℹ️ INFO. One line per alert. Examples:\n- `❌ sde (tank) Reallocated_Sector_Ct: 5 — 坏道增长，建议立即更换`\n- `⚠️ cam_a24a20c0 skip:2.4 — 解码丢帧，检查 GPU 或降低分辨率`\n- `⚠️ nextcloud (Docker) unhealthy — 容器异常`\n- `⚠️ nfs-server (service) inactive — NFS 服务未运行`\n- `⚠️ Timeshift: 430 snaps — 过多，建议清理 (>100)`\n- `⚠️ sde udma_crc:29 — SATA 链路错误`\n- `ℹ️ 0 APT updates pending`\n\n**Correlation rules** (apply these when building alerts):\n- If a Docker container is unhealthy AND a process with the same name has >1% CPU → append `(疑似僵死进程，建议重启容器)`\n- If a Frigate camera has skip>1.0 AND GPU utilization is high → append `(GPU 编码瓶颈)`\n- If a disk has udma>0 → mention potential SATA cable issue\n\n#### Step 2: Build Dashboard Body\n\nUse this compact layout. **Omit sections entirely if no data or all is healthy and not noteworthy.**\n\n```\n╭──────────────────────────────────╮\n│  🏠 NAS Dashboard · {YYYY-MM-DD (周X)}  │\n╰──────────────────────────────────╯\n```\n\nThen sections in order:\n\n**🖥 SYSTEM** — one line:\n```\n🖥 {hostname} · {OS_short} · up {uptime_simplified} · load:{load_1min}\n   CPU:{cpu_used%} ██████░░░░ · RAM:{mem_used}/{mem_total} ({mem_pct}) · / {root_used}/{root_total} ({root_pct})\n   CPU:{cpu_temp°C} · Mobo:{hottest_mobo_temp}°C\n```\n- `uptime_simplified`: convert \"1 week, 2 days, 18 hours\" → \"1w2d18h\"\n- `OS_short`: \"Ubuntu 24.04\" from \"Ubuntu 24.04.4 LTS\"\n- Only show the single highest mobo temp (not all sensors)\n- CPU progress bar: 10 chars, cpu_used/10 → `█` count\n\n**🗄 ZFS** — pool summary line + ARC line:\n```\n🗄 {pool} [{health_emoji} {health}] · {alloc}T/{size}T ({cap}%) ██████░░░░ · frag:{frag}%\n   ARC:{arc_size}GiB/{arc_max}GiB · hit:{arc_hit}% · Scrub:{scrub_summary}\n```\n- Scrub summary: extract \"repaired 0B, 0 errors\" and date from SCRUB field\n- If L2ARC size > 0: append `· L2ARC:{l2_size}GiB hit:{l2_hit}%`\n- ZFS capacity bar: cap/10 → `█` count\n- If ARC hit < 90%: add ⚠️ prefix\n- Snapshots: `Snaps:{count} latest:{yyyy-mm-dd}`\n\n**💾 DISKS** — fixed-width column layout, one line per disk.\n\nUse a mini-table with `│` separators so all status emoji align vertically:\n\n```\n💾 DISKS ───────────────────────────────────\nsda (tank) │ W1003ABYZ-011FA0 │  931G │ 42°C │ 10909h │              ✅\nsdc (tank) │ WD10PURX-78D85Y0 │  931G │ 39°C │  6804h │ r_await:10ms ✅\nsde (tank) │ ST1000DM003-1ER16 │  931G │ 36°C │ 10223h │  udma:29     ✅\n```\n\nColumn widths (pad/crop each field to fit):\n| Col | Field | Width | Align |\n|-----|-------|-------|-------|\n| 1 | `{disk} ({pool_role})` | 9 | left |\n| 2 | model name | 18 | left, truncate if longer |\n| 3 | size | 6 | right |\n| 4 | temp | 5 | right |\n| 5 | hours | 7 | right |\n| 6 | alerts + status | 14 | right |\n\n- Col 6 (alerts + status): padding is dynamic but right-aligned. Contents:\n  - `realloc:X` if > 0 (else pad)\n  - `pending:X` if > 0 (else pad)\n  - `udma:X` if > 0 (else pad)\n  - `r_await:Xms` if > 5ms (else pad)\n  - Always end with `✅` (PASSED) or `❌` (FAIL)\n- Use VDEV_DISK data to annotate pool role: `sda (tank)`, `sdb (tank-cache)` etc.\n- Model: use full model string, crop to 18 chars if longer\n- ⚠️ prefix the whole line if temp>45°C or realloc>0 or pending>0 or udma>100\n- Serial is omitted (model provides enough identification for this view)\n\n**Disk I/O** — only show disks with util>5% or await>10ms:\n```\n   IO: sda r2.5/w4.6ms util5.2% · sdc r10.5/w3.3ms\n```\n\n**🐳 DOCKER** — converged view:\n```\n🐳 {total} running ({healthy_count} healthy) · v{docker_ver} · {image_count} imgs · {volume_gb}GB\n```\nThen only list unhealthy containers explicitly:\n```\n   ⚠️ nextcloud: Up 2 days (no healthcheck)\n   ℹ️ vaultwarden/server:latest: 4 months old (consider updating)\n   ⚠️ xunlei: Up 2 days (no healthcheck) [CPU 11.2% — 疑似僵死]\n```\n- `healthy_count`: count of containers with \"(healthy)\" in status\n- List containers WITHOUT \"(healthy)\" suffix under ⚠️\n- If a container appears in TOP_CPU with same name → add `[CPU X% — 疑似僵死]`\n- **Image staleness**: check IMG_AGE data; flag images older than 6 months with ℹ️\n- Images: extract total size and reclaimable from DOCKER_DF\n- If reclaimable > 10GB: `· {reclaimable} reclaimable ⚠️`\n- If ALL containers are healthy: omit the detail lines, just show the summary\n\n**📹 FRIGATE** — cameras, only expand problem ones:\n```\n📹 3 cams · detection:{det_fps}fps · infer:{infer_ms}ms\n   ✅ cam_d82e8e00: 5.1fps · ✅ cam_ae7e3010: 5.1fps\n   ⚠️ cam_a24a20c0: 4.9fps · skip:2.4 (丢帧 49%)\n```\n- Map camera IDs to friendly names via `FRIGATE_CAM_MAP` env var\n- Show ALL camera names with fps (even healthy, but compact inline)\n- Cameras with skip>0.5: show skip value + calculated drop percentage `(skip/fps*100)`\n- Cameras with skip≤0.5: just show `✅ name: fps`\n- Storage: `📀 {path}: {used}G/{total}G ({pct}%)` for each FRIGATE_STORAGE line. ⚠️ if >80%.\n- If Frigate unreachable: `📹 Frigate: no response ❌`\n\n**🎮 GPU** — one line:\n```\n🎮 {gpu_model} · {temp}°C · {util}% · VRAM:{used}M/{total}M · {proc_count} procs\n```\n- VRAM bar: 10 chars proportional\n- Omit GPU entirely if nvidia-smi not available or no GPU detected\n\n**🌐 NETWORK** — one line per active interface:\n```\n🌐 enp4s0: {ip} · ↓{total_rx} ↑{total_tx}\n```\n- Skip DOWN interfaces\n- Traffic: use TRAFFIC data, convert to human-readable (GB/MB)\n\n**📊 PROCESSES** — top 3 CPU only (compact):\n```\n📊 CPU: xunlei 11.2% · ffmpeg 3.6% · python3 3.1%\n   MEM: python3 3.6% · node 2.8% · gnome-shell 1.4%\n```\n\n**⚙️ SERVICES** — only show non-active or failed:\n```\n⚙️ ⚠️ nfs-server: inactive · 1 failed unit: snap.firmware-updater\n```\n- If all services active and no failed units: omit this section entirely\n\n**🔒 SECURITY** — compact with full audit:\n```\n🔒 Failed logins: {count} · Boot: {boot_time_YYYY-MM-DD HH:MM} ({Xd} ago)\n   SSH: port:{port} · root:{yes/no} · pass:{yes/no} · key:{yes/no}\n   FW: {ufw/iptables status} ({n} rules) · Ports: {open_ports_list}\n```\n- SSH_PASS_AUTH=yes → ⚠️ alert (建议禁密码仅用密钥)\n- SSH_ROOT_LOGIN=yes → ⚠️ alert (建议禁root直接登录)\n- FW_UFW=inactive or FW_TYPE=none → ⚠️ alert (防火墙未启用)\n- Convert OPEN_PORTS comma list to compact format: \"22,80,443,8972,8973\"\n- Last logins: extract latest entry, reformat to \"user from ip at YYYY-MM-DD HH:MM\"\n- If failed_logins = 0 → `Failed logins: 0`\n- If fail2ban active → append `· f2b active`\n\n**🔋 UPS** — one line:\n```\n🔋 {status_icon} {status_text} · charge:{batt_charge}% · load:{ups_load}% · in:{input_v}V · batt:{batt_v}V\n```\n- `OL` → ⚡Online, `OB` → 🪫Battery, `OB DISCHRG` → 🪫Discharging\n\n**💾 TIMESHIFT** — one line with health check:\n```\n💾 Timeshift: {count} snaps · latest:{YYYY-MM-DD HH:MM}\n```\n- If 100 < count ≤ 300: append `⚠️ 过多，建议清理`\n- If count > 300: append `❌ 严重过多 (>300)，立即清理！`\n\n**📦 UPDATES** — only if > 0:\n```\n📦 {count} APT updates available\n```\n\n**🔧 OOM / Logs** — only if data present:\n```\n🔧 OOM: {oom_line_truncated}\n```\n\n#### Step 3: Final Assembly — Compact Mode\n\n1. Title line (single row with date)\n2. 🚨 ALERTS (if any) — combined, no section header duplication\n3. `━━━━` divider (4 chars, not full-width)\n4. Body sections — **merge related sections inline**:\n   - 🖥 SYSTEM + 🌐 NETWORK on one block (host info → IP inline)\n   - 🗄 ZFS + 💾 DISKS as one storage block\n   - 🐳 DOCKER + 📹 FRIGATE as one container block\n   - 🔒 SECURITY as standalone (important)\n   - 📊 PROCESSES: only show if CPU>50% or unusual\n   - ⚙️ SERVICES: only show failed\n   - 🔋 UPS + 💾 TIMESHIFT + 📦 UPDATES as footer row\n5. Keep total output under 2000 chars\n6. **Omitting rules**:\n   - Omit DISKIO if all util<5%\n   - Omit PROCESSES if CPU<50% and no anomalies\n   - Omit SERVICES if all active\n   - Omit LOGS if no errors\n   - Omit UPDATES if 0 pending\n   - Omit GPU if nvidia-smi unavailable\n\n### 3. Deliver\n\nUse `message` tool with `action=send` to the target channel.\n\n## Prerequisites\n\n| Tool | Required for | Package |\n|------|-------------|---------|\n| zpool/zfs | ZFS section | zfsutils-linux |\n| smartctl | Disk health | smartmontools |\n| docker | Docker section | docker-ce |\n| nvidia-smi | GPU section | nvidia-driver |\n| iostat | Disk I/O | sysstat |\n| sensors | Temperatures | lm-sensors |\n| upsc | UPS section | nut-client |\n| journalctl | Logs | systemd (built-in) |\n\nSMART, auth.log, and zpool events need `sudo -n` (passwordless sudo). Sections degrade gracefully if unavailable.\n\n## Threshold Reference\n\n| Metric | ⚠️ Warning | ❌ Critical |\n|--------|-----------|-------------|\n| Disk temp | >45°C | >55°C |\n| CPU temp | >70°C | >85°C |\n| GPU temp | >75°C | >85°C |\n| ZFS capacity | >80% | >90% |\n| Root disk | >85% | >95% |\n| ARC hit rate | <90% | — |\n| Disk r_await/w_await | >20ms | — |\n| Frigate skip | >1.0fps | >3.0fps |\n| Frigate storage | >80% | >95% |\n| Frigate camera fps | <1.0 | =0 |\n| Timeshift snaps | >100 | >300 |\n| realloc (SMART 5) | — | >0 |\n| pending (SMART 197) | >0 | >10 |\n| udma_crc (SMART 199) | >100 | >1000 |\n| UPS battery | <50% | <20% |\n| Disk I/O util | >50% | >80% |\n\n## Notes\n\n- All personal data (hostname, IPs, disk serials) is read at runtime, not hardcoded.\n- Camera name mapping is configurable via `FRIGATE_CAM_MAP` env var: `cam_id:Name,cam_id:Name`\n- Pool name auto-detected from `zpool list`. Override with `ZPOOL` env var.\n- Disk list auto-detected from `lsblk`. Override with `DISK_LIST` env var.\n- Suitable for publishing to ClawHub — contains no credentials, tokens, or fixed identifiers.\n\n## Changelog\n\n### v3.0.0 (2026-05-31)\n- **Environment-aware security assessment**: distinguishes LAN vs public internet, adjusts severity\n- **Three-tier severity**: 🔴 Critical / 🟡 Warning / 🟢 Info with summary count in header\n- **Action guide**: each alert now includes root cause explanation + concrete fix commands\n- **Compact mode**: merged redundant sections, total output under 2000 chars\n- **all-in-one.sh**: collect + format in single script (5s), agent only executes + sends\n- **Container image age tracking**: flags Docker images older than 6 months\n- **SSH config audit**: port, password auth, root login checks\n- **Firewall + open ports audit**: ufw/iptables status, listening port enumeration\n- **Fallback model chain**: Deepseek-Flash → MiniMax on timeout\n\n### v2.0.0 (2026-05-19)\n- Alert-first layout with 🚨 risk warning section\n- Fixed-width DISKS table with SMART realloc/pending/udma columns\n- ZFS ARC/L2ARC hit rate monitoring\n- Docker healthcheck + zombie process correlation\n- Frigate camera skip/drop detection with GPU bottleneck correlation\n\n### v1.0.0 (2026-05-17)\n- Initial release: 16-module text dashboard\n- SYSTEM, ZFS, DISKS, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT\n\nFile v3.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn764er6cp7n2yqb0wch6zx1dn83h07f\",\n  \"slug\": \"nas-dashboard\",\n  \"version\": \"3.0.0\",\n  \"publishedAt\": 1780221500769\n}\n\nFile v3.0.0:skill-card.md\n\n## Description: <br>\nGenerates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[wudi488](https://clawhub.ai/user/wudi488) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nNAS and HomeLab administrators use this skill to collect local system, storage, container, camera, UPS, and security state and turn it into a compact alert-first operations report. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The report can expose sensitive NAS and network details such as hostnames, IP addresses, open ports, login/security data, service names, storage state, and camera/storage details. <br>\nMitigation: Run it only for trusted NAS administration and review or redact generated reports before sharing them outside the trusted operations channel. <br>\nRisk: The documented workflow encourages delivery to Telegram or another third-party channel, which may copy sensitive infrastructure information outside the NAS environment. <br>\nMitigation: Use private delivery targets, limit recipients, and avoid sending unredacted reports to third-party channels unless that disclosure is acceptable. <br>\nRisk: Collection relies on local administrative visibility, including passwordless sudo for SMART, auth log, firewall, fail2ban, and Timeshift checks. <br>\nMitigation: Install only on systems where the operator accepts that access level, and scope sudo permissions to the commands required for the intended dashboard sections. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/wudi488/nas-dashboard) <br>\n- [Publisher profile](https://clawhub.ai/user/wudi488) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, shell commands, configuration, guidance] <br>\n**Output Format:** [Plain text dashboard with alert summaries and inline remediation commands] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Designed for compact delivery, including scheduled reports to messaging channels.] <br>\n\n## Skill Version(s): <br>\n3.0.0 (source: server release metadata and artifact changelog, released 2026-05-31) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v2.0.1: 4 files, 13371 bytes\n\nFiles: scripts/collect.sh (14322b), skill-card.md (2719b), SKILL.md (13429b), _meta.json (132b)\n\nFile v2.0.1:SKILL.md\n\n---\nname: nas-dashboard\ndescription: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Use when the user asks for NAS status, system overview, dashboard, or wants a comprehensive system monitoring report. Linux/ZFS focused; best on Ubuntu/Debian with ZFS+NUT+Docker. Also triggers on \"文本仪表盘\", \"nas status\", \"server status\", \"system dashboard\".\n---\n\n# NAS Dashboard v2\n\nException-driven, alert-first text dashboard for NAS/HomeLab monitoring. Prioritises problems over green lights — if everything is healthy you get a one-liner, if something is wrong you get a surgical report.\n\n**Platform**: Linux (Ubuntu/Debian tested). Partial support: any Linux with ZFS. macOS/Windows: most sections unavailable (ZFS, SMART, systemd, apt, iostat, sensors are Linux-only).\n\n## Design Principles\n\n1. **Alerts First**: ❌/⚠️ always on top. No alerts → no ALERTS section.\n2. **Normal is Invisible**: Don't list 15 healthy containers. Collapse to \"X running (Y OK)\".\n3. **Contextual Correlation**: Disk ↔ ZFS vdev, container unhealthy + CPU process = zombie.\n4. **Actionable Thresholds**: Timeshift >100 warns, SMART realloc>0 alarms, disk>45°C flags.\n5. **Unified Timestamps**: All times in `YYYY-MM-DD HH:MM` or `XdXh` relative.\n\n## Quick Start\n\n### Configure (optional)\n\n```bash\nexport ZPOOL=\"tank\"              # default: auto-detect first pool\nexport DISK_LIST=\"sda sdb sdc\"   # default: auto-detect all /dev/sd?\nexport FRIGATE_CAM_MAP=\"cam_d82e8e00:客厅,cam_ae7e3010:门口,cam_a24a20c0:车库\"\nexport UPS_NAME=\"ups@localhost\"  # default: ups@localhost\n```\n\n### Run\n\n```bash\nbash scripts/collect.sh\n```\n\n### Cron setup\n\n```bash\nopenclaw cron add \\\n  --name \"NAS仪表盘\" \\\n  --schedule \"0 9 * * *\" \\\n  --agent main \\\n  --timeout 180 \\\n  --delivery \"announce:telegram:YOUR_CHAT_ID\" \\\n  --prompt \"Run nas-dashboard skill: collect and format the dashboard report, then send to Telegram.\"\n```\n\n## Workflow\n\n### 1. Collect data\n\nRun `scripts/collect.sh`. Sections: SYSTEM, ZFS, VDEV_DISK (disk→pool mapping), DISKS (incl. SMART realloc/pending/udma), DISKIO, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT.\n\n### 2. Format output — Alert-First Layout\n\n#### Step 0: Scan for Alerts (always do this first)\n\nScan ALL collected data against these thresholds and classify severity:\n\n| Scope | Condition | Severity |\n|-------|-----------|----------|\n| Pool health ≠ ONLINE | any pool | ❌ CRITICAL |\n| Scrub errors > 0 | any pool | ❌ CRITICAL |\n| ZFS_EVENT present | any event | ⚠️ WARNING |\n| Disk health ≠ PASSED | any disk | ❌ CRITICAL |\n| Disk realloc > 0 | any disk | ❌ CRITICAL |\n| Disk pending > 0 | any disk | ⚠️ WARNING |\n| Disk udma_crc > 100 | any disk | ⚠️ WARNING |\n| Disk temp > 45°C | any disk | ⚠️ WARNING |\n| Disk temp > 55°C | any disk | ❌ CRITICAL |\n| Disk r_await > 20ms or w_await > 20ms | any disk | ⚠️ WARNING |\n| Docker container Down/Unhealthy | any ctr | ⚠️ WARNING |\n| Frigate camera skip > 1.0 | any camera | ⚠️ WARNING |\n| Frigate camera fps = 0 | any camera | ❌ CRITICAL |\n| Frigate storage > 80% | any storage | ⚠️ WARNING |\n| Frigate storage > 95% | any storage | ❌ CRITICAL |\n| Timeshift count > 100 | ts active | ⚠️ WARNING |\n| Timeshift count > 300 | ts active | ❌ CRITICAL |\n| CPU temp > 70°C | | ⚠️ WARNING |\n| CPU temp > 85°C | | ❌ CRITICAL |\n| GPU temp > 75°C | | ⚠️ WARNING |\n| GPU temp > 85°C | | ❌ CRITICAL |\n| ARC hit rate < 90% | | ⚠️ WARNING |\n| ZFS capacity > 80% | | ⚠️ WARNING |\n| ZFS capacity > 90% | | ❌ CRITICAL |\n| Root disk > 85% | | ⚠️ WARNING |\n| Root disk > 95% | | ❌ CRITICAL |\n| Failed logins > 0 | today | ⚠️ WARNING |\n| Failed systemd services | any | ⚠️ WARNING |\n| UPS ≠ OL (not Online) | | ⚠️ WARNING |\n| UPS battery < 50% | | ⚠️ WARNING |\n| OOM events present | | ⚠️ WARNING |\n| APT updates available | | ℹ️ INFO |\n\nIf **0 alerts**: skip the `🚨 风险预警` section entirely.\n\nIf **alerts exist**: build `🚨 风险预警` section listing every alert, grouped by severity (❌ first, then ⚠️, then ℹ️). Format:\n\n```\n🚨 风险预警\n❌ {description}\n⚠️ {description}\n```\n\n#### Step 1: Build ALERTS Section (if any)\n\nSort by severity: ❌ CRITICAL → ⚠️ WARNING → ℹ️ INFO. One line per alert. Examples:\n- `❌ sde (tank) Reallocated_Sector_Ct: 5 — 坏道增长，建议立即更换`\n- `⚠️ cam_a24a20c0 skip:2.4 — 解码丢帧，检查 GPU 或降低分辨率`\n- `⚠️ nextcloud (Docker) unhealthy — 容器异常`\n- `⚠️ nfs-server (service) inactive — NFS 服务未运行`\n- `⚠️ Timeshift: 430 snaps — 过多，建议清理 (>100)`\n- `⚠️ sde udma_crc:29 — SATA 链路错误`\n- `ℹ️ 0 APT updates pending`\n\n**Correlation rules** (apply these when building alerts):\n- If a Docker container is unhealthy AND a process with the same name has >1% CPU → append `(疑似僵死进程，建议重启容器)`\n- If a Frigate camera has skip>1.0 AND GPU utilization is high → append `(GPU 编码瓶颈)`\n- If a disk has udma>0 → mention potential SATA cable issue\n\n#### Step 2: Build Dashboard Body\n\nUse this compact layout. **Omit sections entirely if no data or all is healthy and not noteworthy.**\n\n```\n╭──────────────────────────────────╮\n│  🏠 NAS Dashboard · {YYYY-MM-DD (周X)}  │\n╰──────────────────────────────────╯\n```\n\nThen sections in order:\n\n**🖥 SYSTEM** — one line:\n```\n🖥 {hostname} · {OS_short} · up {uptime_simplified} · load:{load_1min}\n   CPU:{cpu_used%} ██████░░░░ · RAM:{mem_used}/{mem_total} ({mem_pct}) · / {root_used}/{root_total} ({root_pct})\n   CPU:{cpu_temp°C} · Mobo:{hottest_mobo_temp}°C\n```\n- `uptime_simplified`: convert \"1 week, 2 days, 18 hours\" → \"1w2d18h\"\n- `OS_short`: \"Ubuntu 24.04\" from \"Ubuntu 24.04.4 LTS\"\n- Only show the single highest mobo temp (not all sensors)\n- CPU progress bar: 10 chars, cpu_used/10 → `█` count\n\n**🗄 ZFS** — pool summary line + ARC line:\n```\n🗄 {pool} [{health_emoji} {health}] · {alloc}T/{size}T ({cap}%) ██████░░░░ · frag:{frag}%\n   ARC:{arc_size}GiB/{arc_max}GiB · hit:{arc_hit}% · Scrub:{scrub_summary}\n```\n- Scrub summary: extract \"repaired 0B, 0 errors\" and date from SCRUB field\n- If L2ARC size > 0: append `· L2ARC:{l2_size}GiB hit:{l2_hit}%`\n- ZFS capacity bar: cap/10 → `█` count\n- If ARC hit < 90%: add ⚠️ prefix\n- Snapshots: `Snaps:{count} latest:{yyyy-mm-dd}`\n\n**💾 DISKS** — fixed-width column layout, one line per disk.\n\nUse a mini-table with `│` separators so all status emoji align vertically:\n\n```\n💾 DISKS ───────────────────────────────────\nsda (tank) │ W1003ABYZ-011FA0 │  931G │ 42°C │ 10909h │              ✅\nsdc (tank) │ WD10PURX-78D85Y0 │  931G │ 39°C │  6804h │ r_await:10ms ✅\nsde (tank) │ ST1000DM003-1ER16 │  931G │ 36°C │ 10223h │  udma:29     ✅\n```\n\nColumn widths (pad/crop each field to fit):\n| Col | Field | Width | Align |\n|-----|-------|-------|-------|\n| 1 | `{disk} ({pool_role})` | 9 | left |\n| 2 | model name | 18 | left, truncate if longer |\n| 3 | size | 6 | right |\n| 4 | temp | 5 | right |\n| 5 | hours | 7 | right |\n| 6 | alerts + status | 14 | right |\n\n- Col 6 (alerts + status): padding is dynamic but right-aligned. Contents:\n  - `realloc:X` if > 0 (else pad)\n  - `pending:X` if > 0 (else pad)\n  - `udma:X` if > 0 (else pad)\n  - `r_await:Xms` if > 5ms (else pad)\n  - Always end with `✅` (PASSED) or `❌` (FAIL)\n- Use VDEV_DISK data to annotate pool role: `sda (tank)`, `sdb (tank-cache)` etc.\n- Model: use full model string, crop to 18 chars if longer\n- ⚠️ prefix the whole line if temp>45°C or realloc>0 or pending>0 or udma>100\n- Serial is omitted (model provides enough identification for this view)\n\n**Disk I/O** — only show disks with util>5% or await>10ms:\n```\n   IO: sda r2.5/w4.6ms util5.2% · sdc r10.5/w3.3ms\n```\n\n**🐳 DOCKER** — converged view:\n```\n🐳 {total} running ({healthy_count} healthy) · v{docker_ver} · {image_count} imgs · {volume_gb}GB\n```\nThen only list unhealthy containers explicitly:\n```\n   ⚠️ nextcloud: Up 2 days (no healthcheck)\n   ⚠️ xunlei: Up 2 days (no healthcheck) [CPU 11.2% — 疑似僵死]\n```\n- `healthy_count`: count of containers with \"(healthy)\" in status\n- List containers WITHOUT \"(healthy)\" suffix under ⚠️\n- If a container appears in TOP_CPU with same name → add `[CPU X% — 疑似僵死]`\n- Images: extract total size and reclaimable from DOCKER_DF\n- If reclaimable > 10GB: `· {reclaimable} reclaimable ⚠️`\n- If ALL containers are healthy: omit the detail lines, just show the summary\n\n**📹 FRIGATE** — cameras, only expand problem ones:\n```\n📹 3 cams · detection:{det_fps}fps · infer:{infer_ms}ms\n   ✅ cam_d82e8e00: 5.1fps · ✅ cam_ae7e3010: 5.1fps\n   ⚠️ cam_a24a20c0: 4.9fps · skip:2.4 (丢帧 49%)\n```\n- Map camera IDs to friendly names via `FRIGATE_CAM_MAP` env var\n- Show ALL camera names with fps (even healthy, but compact inline)\n- Cameras with skip>0.5: show skip value + calculated drop percentage `(skip/fps*100)`\n- Cameras with skip≤0.5: just show `✅ name: fps`\n- Storage: `📀 {path}: {used}G/{total}G ({pct}%)` for each FRIGATE_STORAGE line. ⚠️ if >80%.\n- If Frigate unreachable: `📹 Frigate: no response ❌`\n\n**🎮 GPU** — one line:\n```\n🎮 {gpu_model} · {temp}°C · {util}% · VRAM:{used}M/{total}M · {proc_count} procs\n```\n- VRAM bar: 10 chars proportional\n- Omit GPU entirely if nvidia-smi not available or no GPU detected\n\n**🌐 NETWORK** — one line per active interface:\n```\n🌐 enp4s0: {ip} · ↓{total_rx} ↑{total_tx}\n```\n- Skip DOWN interfaces\n- Traffic: use TRAFFIC data, convert to human-readable (GB/MB)\n\n**📊 PROCESSES** — top 3 CPU only (compact):\n```\n📊 CPU: xunlei 11.2% · ffmpeg 3.6% · python3 3.1%\n   MEM: python3 3.6% · node 2.8% · gnome-shell 1.4%\n```\n\n**⚙️ SERVICES** — only show non-active or failed:\n```\n⚙️ ⚠️ nfs-server: inactive · 1 failed unit: snap.firmware-updater\n```\n- If all services active and no failed units: omit this section entirely\n\n**🔒 SECURITY** — compact:\n```\n🔒 Failed logins: {count} · Boot: {boot_time_YYYY-MM-DD HH:MM} ({Xd} ago)\n   Last: {user} from {ip} at {YYYY-MM-DD HH:MM}\n```\n- Convert LAST_LOGINS format: extract latest entry, reformat to \"user from ip at YYYY-MM-DD HH:MM\"\n- \"Sun May 17 22:02\" → \"2026-05-17 22:02\"\n- If failed_logins = 0 → `Failed logins: 0`\n\n**🔋 UPS** — one line:\n```\n🔋 {status_icon} {status_text} · charge:{batt_charge}% · load:{ups_load}% · in:{input_v}V · batt:{batt_v}V\n```\n- `OL` → ⚡Online, `OB` → 🪫Battery, `OB DISCHRG` → 🪫Discharging\n\n**💾 TIMESHIFT** — one line with health check:\n```\n💾 Timeshift: {count} snaps · latest:{YYYY-MM-DD HH:MM}\n```\n- If 100 < count ≤ 300: append `⚠️ 过多，建议清理`\n- If count > 300: append `❌ 严重过多 (>300)，立即清理！`\n\n**📦 UPDATES** — only if > 0:\n```\n📦 {count} APT updates available\n```\n\n**🔧 OOM / Logs** — only if data present:\n```\n🔧 OOM: {oom_line_truncated}\n   Logs(1h): {error_count} errors\n```\n\n#### Step 3: Final Assembly\n\n1. Title line\n2. 🚨 ALERTS (if any)\n3. `━━━━━━━━━━━━━━━━━━━━━━━━` divider\n4. All body sections in order\n5. Keep total output under 2500 chars\n\n### 3. Deliver\n\nUse `message` tool with `action=send` to the target channel.\n\n## Prerequisites\n\n| Tool | Required for | Package |\n|------|-------------|---------|\n| zpool/zfs | ZFS section | zfsutils-linux |\n| smartctl | Disk health | smartmontools |\n| docker | Docker section | docker-ce |\n| nvidia-smi | GPU section | nvidia-driver |\n| iostat | Disk I/O | sysstat |\n| sensors | Temperatures | lm-sensors |\n| upsc | UPS section | nut-client |\n| journalctl | Logs | systemd (built-in) |\n\nSMART, auth.log, and zpool events need `sudo -n` (passwordless sudo). Sections degrade gracefully if unavailable.\n\n## Threshold Reference\n\n| Metric | ⚠️ Warning | ❌ Critical |\n|--------|-----------|-------------|\n| Disk temp | >45°C | >55°C |\n| CPU temp | >70°C | >85°C |\n| GPU temp | >75°C | >85°C |\n| ZFS capacity | >80% | >90% |\n| Root disk | >85% | >95% |\n| ARC hit rate | <90% | — |\n| Disk r_await/w_await | >20ms | — |\n| Frigate skip | >1.0fps | >3.0fps |\n| Frigate storage | >80% | >95% |\n| Frigate camera fps | <1.0 | =0 |\n| Timeshift snaps | >100 | >300 |\n| realloc (SMART 5) | — | >0 |\n| pending (SMART 197) | >0 | >10 |\n| udma_crc (SMART 199) | >100 | >1000 |\n| UPS battery | <50% | <20% |\n| Disk I/O util | >50% | >80% |\n\n## Notes\n\n- All personal data (hostname, IPs, disk serials) is read at runtime, not hardcoded.\n- Camera name mapping is configurable via `FRIGATE_CAM_MAP` env var: `cam_id:Name,cam_id:Name`\n- Pool name auto-detected from `zpool list`. Override with `ZPOOL` env var.\n- Disk list auto-detected from `lsblk`. Override with `DISK_LIST` env var.\n- Suitable for publishing to ClawHub — contains no credentials, tokens, or fixed identifiers.\n\nFile v2.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn764er6cp7n2yqb0wch6zx1dn83h07f\",\n  \"slug\": \"nas-dashboard\",\n  \"version\": \"2.0.1\",\n  \"publishedAt\": 1779200283388\n}\n\nFile v2.0.1:skill-card.md\n\n## Description: <br>\nGenerates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART data, Docker containers, GPU status, UPS, backup services, and security signals. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[wudi488](https://clawhub.ai/user/wudi488) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nNAS and homelab operators use this skill to collect local telemetry and produce a compact, alert-first monitoring report for Linux systems, especially Ubuntu/Debian hosts with ZFS, Docker, NUT UPS, and optional NVIDIA GPU tooling. It is intended for recurring operational status checks and issue triage. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The collector reads sensitive local host, storage, security, login, service, and hardware telemetry. <br>\nMitigation: Run it only on NAS or homelab hosts where that telemetry is intentionally collected, and review the report before sharing it outside trusted channels. <br>\nRisk: Cron and Telegram delivery can repeatedly transmit operational details to an external chat destination. <br>\nMitigation: Enable scheduled or Telegram delivery only for trusted chat IDs and accounts, and disable delivery paths that are not needed. <br>\nRisk: Some checks rely on passwordless sudo for SMART, auth log, and Timeshift reads. <br>\nMitigation: Use narrowly scoped sudoers rules for the exact read-only commands required, and avoid broad passwordless sudo access. <br>\nRisk: The release carries purchase and crypto capability tags that do not match the monitoring behavior described in the artifact. <br>\nMitigation: Do not grant purchase or crypto permissions for this skill, and remove unrelated capability tags before deployment. <br>\n\n\n## Reference(s): <br>\n- [ClawHub Skill Page](https://clawhub.ai/wudi488/nas-dashboard) <br>\n- [Publisher Profile](https://clawhub.ai/user/wudi488) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance] <br>\n**Output Format:** [Plain text or Markdown dashboard report with optional shell commands and configuration snippets] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Alert-first NAS monitoring summary, normally kept compact for chat or Telegram delivery.] <br>\n\n## Skill Version(s): <br>\n2.0.1 (source: server release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v2.0.0: 3 files, 11930 bytes\n\nFiles: scripts/collect.sh (14277b), SKILL.md (13429b), _meta.json (132b)\n\nFile v2.0.0:SKILL.md\n\n---\nname: nas-dashboard\ndescription: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Use when the user asks for NAS status, system overview, dashboard, or wants a comprehensive system monitoring report. Linux/ZFS focused; best on Ubuntu/Debian with ZFS+NUT+Docker. Also triggers on \"文本仪表盘\", \"nas status\", \"server status\", \"system dashboard\".\n---\n\n# NAS Dashboard v2\n\nException-driven, alert-first text dashboard for NAS/HomeLab monitoring. Prioritises problems over green lights — if everything is healthy you get a one-liner, if something is wrong you get a surgical report.\n\n**Platform**: Linux (Ubuntu/Debian tested). Partial support: any Linux with ZFS. macOS/Windows: most sections unavailable (ZFS, SMART, systemd, apt, iostat, sensors are Linux-only).\n\n## Design Principles\n\n1. **Alerts First**: ❌/⚠️ always on top. No alerts → no ALERTS section.\n2. **Normal is Invisible**: Don't list 15 healthy containers. Collapse to \"X running (Y OK)\".\n3. **Contextual Correlation**: Disk ↔ ZFS vdev, container unhealthy + CPU process = zombie.\n4. **Actionable Thresholds**: Timeshift >100 warns, SMART realloc>0 alarms, disk>45°C flags.\n5. **Unified Timestamps**: All times in `YYYY-MM-DD HH:MM` or `XdXh` relative.\n\n## Quick Start\n\n### Configure (optional)\n\n```bash\nexport ZPOOL=\"tank\"              # default: auto-detect first pool\nexport DISK_LIST=\"sda sdb sdc\"   # default: auto-detect all /dev/sd?\nexport FRIGATE_CAM_MAP=\"cam_d82e8e00:客厅,cam_ae7e3010:门口,cam_a24a20c0:车库\"\nexport UPS_NAME=\"ups@localhost\"  # default: ups@localhost\n```\n\n### Run\n\n```bash\nbash scripts/collect.sh\n```\n\n### Cron setup\n\n```bash\nopenclaw cron add \\\n  --name \"NAS仪表盘\" \\\n  --schedule \"0 9 * * *\" \\\n  --agent main \\\n  --timeout 180 \\\n  --delivery \"announce:telegram:YOUR_CHAT_ID\" \\\n  --prompt \"Run nas-dashboard skill: collect and format the dashboard report, then send to Telegram.\"\n```\n\n## Workflow\n\n### 1. Collect data\n\nRun `scripts/collect.sh`. Sections: SYSTEM, ZFS, VDEV_DISK (disk→pool mapping), DISKS (incl. SMART realloc/pending/udma), DISKIO, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT.\n\n### 2. Format output — Alert-First Layout\n\n#### Step 0: Scan for Alerts (always do this first)\n\nScan ALL collected data against these thresholds and classify severity:\n\n| Scope | Condition | Severity |\n|-------|-----------|----------|\n| Pool health ≠ ONLINE | any pool | ❌ CRITICAL |\n| Scrub errors > 0 | any pool | ❌ CRITICAL |\n| ZFS_EVENT present | any event | ⚠️ WARNING |\n| Disk health ≠ PASSED | any disk | ❌ CRITICAL |\n| Disk realloc > 0 | any disk | ❌ CRITICAL |\n| Disk pending > 0 | any disk | ⚠️ WARNING |\n| Disk udma_crc > 100 | any disk | ⚠️ WARNING |\n| Disk temp > 45°C | any disk | ⚠️ WARNING |\n| Disk temp > 55°C | any disk | ❌ CRITICAL |\n| Disk r_await > 20ms or w_await > 20ms | any disk | ⚠️ WARNING |\n| Docker container Down/Unhealthy | any ctr | ⚠️ WARNING |\n| Frigate camera skip > 1.0 | any camera | ⚠️ WARNING |\n| Frigate camera fps = 0 | any camera | ❌ CRITICAL |\n| Frigate storage > 80% | any storage | ⚠️ WARNING |\n| Frigate storage > 95% | any storage | ❌ CRITICAL |\n| Timeshift count > 100 | ts active | ⚠️ WARNING |\n| Timeshift count > 300 | ts active | ❌ CRITICAL |\n| CPU temp > 70°C | | ⚠️ WARNING |\n| CPU temp > 85°C | | ❌ CRITICAL |\n| GPU temp > 75°C | | ⚠️ WARNING |\n| GPU temp > 85°C | | ❌ CRITICAL |\n| ARC hit rate < 90% | | ⚠️ WARNING |\n| ZFS capacity > 80% | | ⚠️ WARNING |\n| ZFS capacity > 90% | | ❌ CRITICAL |\n| Root disk > 85% | | ⚠️ WARNING |\n| Root disk > 95% | | ❌ CRITICAL |\n| Failed logins > 0 | today | ⚠️ WARNING |\n| Failed systemd services | any | ⚠️ WARNING |\n| UPS ≠ OL (not Online) | | ⚠️ WARNING |\n| UPS battery < 50% | | ⚠️ WARNING |\n| OOM events present | | ⚠️ WARNING |\n| APT updates available | | ℹ️ INFO |\n\nIf **0 alerts**: skip the `🚨 风险预警` section entirely.\n\nIf **alerts exist**: build `🚨 风险预警` section listing every alert, grouped by severity (❌ first, then ⚠️, then ℹ️). Format:\n\n```\n🚨 风险预警\n❌ {description}\n⚠️ {description}\n```\n\n#### Step 1: Build ALERTS Section (if any)\n\nSort by severity: ❌ CRITICAL → ⚠️ WARNING → ℹ️ INFO. One line per alert. Examples:\n- `❌ sde (tank) Reallocated_Sector_Ct: 5 — 坏道增长，建议立即更换`\n- `⚠️ cam_a24a20c0 skip:2.4 — 解码丢帧，检查 GPU 或降低分辨率`\n- `⚠️ nextcloud (Docker) unhealthy — 容器异常`\n- `⚠️ nfs-server (service) inactive — NFS 服务未运行`\n- `⚠️ Timeshift: 430 snaps — 过多，建议清理 (>100)`\n- `⚠️ sde udma_crc:29 — SATA 链路错误`\n- `ℹ️ 0 APT updates pending`\n\n**Correlation rules** (apply these when building alerts):\n- If a Docker container is unhealthy AND a process with the same name has >1% CPU → append `(疑似僵死进程，建议重启容器)`\n- If a Frigate camera has skip>1.0 AND GPU utilization is high → append `(GPU 编码瓶颈)`\n- If a disk has udma>0 → mention potential SATA cable issue\n\n#### Step 2: Build Dashboard Body\n\nUse this compact layout. **Omit sections entirely if no data or all is healthy and not noteworthy.**\n\n```\n╭──────────────────────────────────╮\n│  🏠 NAS Dashboard · {YYYY-MM-DD (周X)}  │\n╰──────────────────────────────────╯\n```\n\nThen sections in order:\n\n**🖥 SYSTEM** — one line:\n```\n🖥 {hostname} · {OS_short} · up {uptime_simplified} · load:{load_1min}\n   CPU:{cpu_used%} ██████░░░░ · RAM:{mem_used}/{mem_total} ({mem_pct}) · / {root_used}/{root_total} ({root_pct})\n   CPU:{cpu_temp°C} · Mobo:{hottest_mobo_temp}°C\n```\n- `uptime_simplified`: convert \"1 week, 2 days, 18 hours\" → \"1w2d18h\"\n- `OS_short`: \"Ubuntu 24.04\" from \"Ubuntu 24.04.4 LTS\"\n- Only show the single highest mobo temp (not all sensors)\n- CPU progress bar: 10 chars, cpu_used/10 → `█` count\n\n**🗄 ZFS** — pool summary line + ARC line:\n```\n🗄 {pool} [{health_emoji} {health}] · {alloc}T/{size}T ({cap}%) ██████░░░░ · frag:{frag}%\n   ARC:{arc_size}GiB/{arc_max}GiB · hit:{arc_hit}% · Scrub:{scrub_summary}\n```\n- Scrub summary: extract \"repaired 0B, 0 errors\" and date from SCRUB field\n- If L2ARC size > 0: append `· L2ARC:{l2_size}GiB hit:{l2_hit}%`\n- ZFS capacity bar: cap/10 → `█` count\n- If ARC hit < 90%: add ⚠️ prefix\n- Snapshots: `Snaps:{count} latest:{yyyy-mm-dd}`\n\n**💾 DISKS** — fixed-width column layout, one line per disk.\n\nUse a mini-table with `│` separators so all status emoji align vertically:\n\n```\n💾 DISKS ───────────────────────────────────\nsda (tank) │ W1003ABYZ-011FA0 │  931G │ 42°C │ 10909h │              ✅\nsdc (tank) │ WD10PURX-78D85Y0 │  931G │ 39°C │  6804h │ r_await:10ms ✅\nsde (tank) │ ST1000DM003-1ER16 │  931G │ 36°C │ 10223h │  udma:29     ✅\n```\n\nColumn widths (pad/crop each field to fit):\n| Col | Field | Width | Align |\n|-----|-------|-------|-------|\n| 1 | `{disk} ({pool_role})` | 9 | left |\n| 2 | model name | 18 | left, truncate if longer |\n| 3 | size | 6 | right |\n| 4 | temp | 5 | right |\n| 5 | hours | 7 | right |\n| 6 | alerts + status | 14 | right |\n\n- Col 6 (alerts + status): padding is dynamic but right-aligned. Contents:\n  - `realloc:X` if > 0 (else pad)\n  - `pending:X` if > 0 (else pad)\n  - `udma:X` if > 0 (else pad)\n  - `r_await:Xms` if > 5ms (else pad)\n  - Always end with `✅` (PASSED) or `❌` (FAIL)\n- Use VDEV_DISK data to annotate pool role: `sda (tank)`, `sdb (tank-cache)` etc.\n- Model: use full model string, crop to 18 chars if longer\n- ⚠️ prefix the whole line if temp>45°C or realloc>0 or pending>0 or udma>100\n- Serial is omitted (model provides enough identification for this view)\n\n**Disk I/O** — only show disks with util>5% or await>10ms:\n```\n   IO: sda r2.5/w4.6ms util5.2% · sdc r10.5/w3.3ms\n```\n\n**🐳 DOCKER** — converged view:\n```\n🐳 {total} running ({healthy_count} healthy) · v{docker_ver} · {image_count} imgs · {volume_gb}GB\n```\nThen only list unhealthy containers explicitly:\n```\n   ⚠️ nextcloud: Up 2 days (no healthcheck)\n   ⚠️ xunlei: Up 2 days (no healthcheck) [CPU 11.2% — 疑似僵死]\n```\n- `healthy_count`: count of containers with \"(healthy)\" in status\n- List containers WITHOUT \"(healthy)\" suffix under ⚠️\n- If a container appears in TOP_CPU with same name → add `[CPU X% — 疑似僵死]`\n- Images: extract total size and reclaimable from DOCKER_DF\n- If reclaimable > 10GB: `· {reclaimable} reclaimable ⚠️`\n- If ALL containers are healthy: omit the detail lines, just show the summary\n\n**📹 FRIGATE** — cameras, only expand problem ones:\n```\n📹 3 cams · detection:{det_fps}fps · infer:{infer_ms}ms\n   ✅ cam_d82e8e00: 5.1fps · ✅ cam_ae7e3010: 5.1fps\n   ⚠️ cam_a24a20c0: 4.9fps · skip:2.4 (丢帧 49%)\n```\n- Map camera IDs to friendly names via `FRIGATE_CAM_MAP` env var\n- Show ALL camera names with fps (even healthy, but compact inline)\n- Cameras with skip>0.5: show skip value + calculated drop percentage `(skip/fps*100)`\n- Cameras with skip≤0.5: just show `✅ name: fps`\n- Storage: `📀 {path}: {used}G/{total}G ({pct}%)` for each FRIGATE_STORAGE line. ⚠️ if >80%.\n- If Frigate unreachable: `📹 Frigate: no response ❌`\n\n**🎮 GPU** — one line:\n```\n🎮 {gpu_model} · {temp}°C · {util}% · VRAM:{used}M/{total}M · {proc_count} procs\n```\n- VRAM bar: 10 chars proportional\n- Omit GPU entirely if nvidia-smi not available or no GPU detected\n\n**🌐 NETWORK** — one line per active interface:\n```\n🌐 enp4s0: {ip} · ↓{total_rx} ↑{total_tx}\n```\n- Skip DOWN interfaces\n- Traffic: use TRAFFIC data, convert to human-readable (GB/MB)\n\n**📊 PROCESSES** — top 3 CPU only (compact):\n```\n📊 CPU: xunlei 11.2% · ffmpeg 3.6% · python3 3.1%\n   MEM: python3 3.6% · node 2.8% · gnome-shell 1.4%\n```\n\n**⚙️ SERVICES** — only show non-active or failed:\n```\n⚙️ ⚠️ nfs-server: inactive · 1 failed unit: snap.firmware-updater\n```\n- If all services active and no failed units: omit this section entirely\n\n**🔒 SECURITY** — compact:\n```\n🔒 Failed logins: {count} · Boot: {boot_time_YYYY-MM-DD HH:MM} ({Xd} ago)\n   Last: {user} from {ip} at {YYYY-MM-DD HH:MM}\n```\n- Convert LAST_LOGINS format: extract latest entry, reformat to \"user from ip at YYYY-MM-DD HH:MM\"\n- \"Sun May 17 22:02\" → \"2026-05-17 22:02\"\n- If failed_logins = 0 → `Failed logins: 0`\n\n**🔋 UPS** — one line:\n```\n🔋 {status_icon} {status_text} · charge:{batt_charge}% · load:{ups_load}% · in:{input_v}V · batt:{batt_v}V\n```\n- `OL` → ⚡Online, `OB` → 🪫Battery, `OB DISCHRG` → 🪫Discharging\n\n**💾 TIMESHIFT** — one line with health check:\n```\n💾 Timeshift: {count} snaps · latest:{YYYY-MM-DD HH:MM}\n```\n- If 100 < count ≤ 300: append `⚠️ 过多，建议清理`\n- If count > 300: append `❌ 严重过多 (>300)，立即清理！`\n\n**📦 UPDATES** — only if > 0:\n```\n📦 {count} APT updates available\n```\n\n**🔧 OOM / Logs** — only if data present:\n```\n🔧 OOM: {oom_line_truncated}\n   Logs(1h): {error_count} errors\n```\n\n#### Step 3: Final Assembly\n\n1. Title line\n2. 🚨 ALERTS (if any)\n3. `━━━━━━━━━━━━━━━━━━━━━━━━` divider\n4. All body sections in order\n5. Keep total output under 2500 chars\n\n### 3. Deliver\n\nUse `message` tool with `action=send` to the target channel.\n\n## Prerequisites\n\n| Tool | Required for | Package |\n|------|-------------|---------|\n| zpool/zfs | ZFS section | zfsutils-linux |\n| smartctl | Disk health | smartmontools |\n| docker | Docker section | docker-ce |\n| nvidia-smi | GPU section | nvidia-driver |\n| iostat | Disk I/O | sysstat |\n| sensors | Temperatures | lm-sensors |\n| upsc | UPS section | nut-client |\n| journalctl | Logs | systemd (built-in) |\n\nSMART, auth.log, and zpool events need `sudo -n` (passwordless sudo). Sections degrade gracefully if unavailable.\n\n## Threshold Reference\n\n| Metric | ⚠️ Warning | ❌ Critical |\n|--------|-----------|-------------|\n| Disk temp | >45°C | >55°C |\n| CPU temp | >70°C | >85°C |\n| GPU temp | >75°C | >85°C |\n| ZFS capacity | >80% | >90% |\n| Root disk | >85% | >95% |\n| ARC hit rate | <90% | — |\n| Disk r_await/w_await | >20ms | — |\n| Frigate skip | >1.0fps | >3.0fps |\n| Frigate storage | >80% | >95% |\n| Frigate camera fps | <1.0 | =0 |\n| Timeshift snaps | >100 | >300 |\n| realloc (SMART 5) | — | >0 |\n| pending (SMART 197) | >0 | >10 |\n| udma_crc (SMART 199) | >100 | >1000 |\n| UPS battery | <50% | <20% |\n| Disk I/O util | >50% | >80% |\n\n## Notes\n\n- All personal data (hostname, IPs, disk serials) is read at runtime, not hardcoded.\n- Camera name mapping is configurable via `FRIGATE_CAM_MAP` env var: `cam_id:Name,cam_id:Name`\n- Pool name auto-detected from `zpool list`. Override with `ZPOOL` env var.\n- Disk list auto-detected from `lsblk`. Override with `DISK_LIST` env var.\n- Suitable for publishing to ClawHub — contains no credentials, tokens, or fixed identifiers.\n\nFile v2.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn764er6cp7n2yqb0wch6zx1dn83h07f\",\n  \"slug\": \"nas-dashboard\",\n  \"version\": \"2.0.0\",\n  \"publishedAt\": 1779091233634\n}\n\nArchive v1.0.0: 3 files, 7681 bytes\n\nFiles: scripts/collect.sh (12088b), SKILL.md (5146b), _meta.json (132b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: nas-dashboard\ndescription: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Use when the user asks for NAS status, system overview, dashboard, or wants a comprehensive system monitoring report. Linux/ZFS focused; best on Ubuntu/Debian with ZFS+NUT+Docker. Also triggers on \"文本仪表盘\", \"nas status\", \"server status\", \"system dashboard\".\n---\n\n# NAS Dashboard\n\nGenerates a visually rich text dashboard covering 16 system dimensions in a single Telegram-friendly message, comparable to Synology DSM / QNAP QTS / TrueNAS overview pages.\n\n**Platform**: Linux (Ubuntu/Debian tested). Partial support: any Linux with ZFS. macOS/Windows: most sections unavailable (ZFS, SMART, systemd, apt, iostat, sensors are Linux-only).\n\n## Quick Start\n\n### Configure (optional)\n\n```bash\n# Override defaults via env vars\nexport ZPOOL=\"tank\"              # default: auto-detect first pool\nexport DISK_LIST=\"sda sdb sdc\"   # default: auto-detect all /dev/sd?\nexport FRIGATE_CAM_MAP=\"cam_abc:Living Room,cam_xyz:Garage\"\nexport UPS_NAME=\"ups@localhost\"  # default: ups@localhost\n```\n\n### Run\n\n```bash\nbash scripts/collect.sh\n```\n\nOutputs structured `KEY=VALUE` lines for the formatting agent.\n\n### Cron setup\n\n```bash\nopenclaw cron add \\\n  --name \"NAS仪表盘\" \\\n  --schedule \"0 9 * * *\" \\\n  --agent main \\\n  --timeout 180 \\\n  --delivery \"announce:telegram:YOUR_CHAT_ID\" \\\n  --prompt \"Run nas-dashboard skill: collect and format the dashboard report, then send to Telegram.\"\n```\n\n## Workflow\n\n### 1. Collect data\n\nRun `scripts/collect.sh`. See script for full section list (SYSTEM, ZFS, DISKS, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT).\n\n### 2. Format output — Visual Style\n\nUse Unicode box-drawing, progress bars, and compact inline layouts.\n\n#### Dashboard Title\n```\n╭──────────────────────────────────────╮\n│  🏠 NAS Dashboard · {date} {day}       │\n╰──────────────────────────────────────╯\n```\n\n#### Section Template\n\nUse `━━━` dividers with emoji section headers. Progress bars: `████████░░` (10 segments).\n\nKey sections:\n\n- 🖥 SYSTEM — hostname, OS, uptime, load, CPU, memory bar, swap, root disk, mobo temp\n- 🗄 ZFS — pool health, capacity bar, I/O, ARC/L2ARC, snapshots, scrub, top snaps\n- 💾 DISKS — model/serial/size/temp/hours/health + iostat latency\n- 🐳 DOCKER — engine version, container list, images/volumes, tag summary (:latest vs pinned)\n- 📹 FRIGATE — cameras (use cam_names mapping if configured), detection, storage\n- 🎮 GPU — model, temp, utilization, VRAM bar, process count\n- 🌐 NETWORK — interfaces, traffic\n- 📊 PROCESSES — top 5 CPU, top 5 memory\n- ⚙️ SERVICES — ssh/smb/nfs/cockpit status + failed units\n- 🔒 SECURITY — failed logins, boot time, errors/OOM if any\n- 🔋 UPS — status (OL→⚡Online, OB→🪫Battery), charge, load, voltage\n- 💾 TIMESHIFT — cron status, snapshot count, latest backup\n\n#### Formatting Rules\n\n- **Progress bars**: `█` = 10% filled, `░` = empty. 10 chars wide. `mem_pct / 10` → bar length.\n- **Status emoji**: `✅` = OK, `⚠️` = warning (temp>50, cap>80%, ARC<90%, failed>0, latency>20ms, camera skip>0.5), `❌` = error/inactive.\n- **Inline separator**: `·` (U+00B7) between related values.\n- **Compact lists**: Group container families (immich×4), truncate names >20 chars.\n- **Disk serial**: truncate to last 8 chars.\n- **Disk I/O**: show disks with util>1% or await>5ms.\n- **Camera names**: Set `FRIGATE_CAM_MAP` env var for friendly names (`cam_abc:客厅,cam_xyz:车库`). Falls back to raw IDs.\n- **Docker tags**: `{n} latest · {m} pinned`. ⚠️ if latest-tagged containers exist.\n- **Omit**: Swap if 0, GPU procs if none, logs if clean, services if all OK, sections if no data.\n- **Keep under 3000 chars** total.\n\n### 3. Deliver\n\nUse `message` tool with `action=send` to the target channel.\n\n## Prerequisites\n\n| Tool | Required for | Package |\n|------|-------------|---------|\n| zpool/zfs | ZFS section | zfsutils-linux |\n| smartctl | Disk health | smartmontools |\n| docker | Docker section | docker-ce |\n| nvidia-smi | GPU section | nvidia-driver |\n| iostat | Disk I/O | sysstat |\n| sensors | Temperatures | lm-sensors |\n| upsc | UPS section | nut-client |\n| journalctl | Logs | systemd (built-in) |\n\nSMART, auth.log, and zpool events need `sudo -n` (passwordless sudo). Sections degrade gracefully if unavailable.\n\n## Notes\n\n- All personal data (hostname, IPs, disk serials) is read at runtime, not hardcoded.\n- Camera name mapping is configurable via `FRIGATE_CAM_MAP` env var; no camera IDs are hardcoded.\n- Pool name auto-detected from `zpool list`. Override with `ZPOOL` env var.\n- Disk list auto-detected from `lsblk`. Override with `DISK_LIST` env var.\n- Suitable for publishing to ClawHub — contains no credentials, tokens, or fixed identifiers.\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn764er6cp7n2yqb0wch6zx1dn83h07f\",\n  \"slug\": \"nas-dashboard\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1779026199841\n}","readmeExcerpt":"Skill: NAS Dashboard Owner: wudi488 Summary: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Us... Tags: latest:3.0.1 Version history: v3.0.1 | 2026-05-31T09:59:24.624Z | user v3.0.1: 📢 更新营销描述——明确目标用户(自建NAS/HomeLab/自托管服务)、最佳使用环境(Ubuntu+ZFS+Docker+UPS)、一句话价值主张(每天早上看一眼🔴红灯，有就照着修)。 v3.0.0 | 2026-05-31T09:58:20.769","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"export ZPOOL=\"tank\"              # default: auto-detect first pool\nexport DISK_LIST=\"sda sdb sdc\"   # default: auto-detect all /dev/sd?\nexport FRIGATE_CAM_MAP=\"cam_d82e8e00:客厅,cam_ae7e3010:门口,cam_a24a20c0:车库\"\nexport UPS_NAME=\"ups@localhost\"  # default: ups@localhost"},{"language":"bash","snippet":"bash scripts/collect.sh"},{"language":"bash","snippet":"openclaw cron add \\\n  --name \"NAS仪表盘\" \\\n  --schedule \"0 9 * * *\" \\\n  --agent main \\\n  --timeout 180 \\\n  --delivery \"announce:telegram:YOUR_CHAT_ID\" \\\n  --prompt \"Run nas-dashboard skill: collect and format the dashboard report, then send to Telegram.\""},{"language":"text","snippet":"🚨 风险预警\n❌ {description}\n⚠️ {description}"},{"language":"text","snippet":"╭──────────────────────────────────╮\n│  🏠 NAS Dashboard · {YYYY-MM-DD (周X)}  │\n╰──────────────────────────────────╯"},{"language":"text","snippet":"🖥 {hostname} · {OS_short} · up {uptime_simplified} · load:{load_1min}\n   CPU:{cpu_used%} ██████░░░░ · RAM:{mem_used}/{mem_total} ({mem_pct}) · / {root_used}/{root_total} ({root_pct})\n   CPU:{cpu_temp°C} · Mobo:{hottest_mobo_temp}°C"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: nas-dashboard\ndescription: >-\n  🏠 NAS Dashboard v3 — 环境感知的智能运维仪表盘。\n  \n  **适合谁**：自建 NAS / HomeLab / 家庭服务器用户，跑了 ZFS + Docker + 一堆自托管服务，需要一个\"一眼看清问题、告诉你修什么\"的每日健康报告。\n  \n  **做什么**：一键采集系统全貌（ZFS/磁盘SMART/Docker/Frigate摄像头/GPU/UPS/安全审计），环境感知评估（内网/公网分级），三级严重度（🔴紧急🟡关注🟢参考），每条告警附带评估原因+可执行修复命令。\n  \n  **最佳环境**：Ubuntu/Debian + ZFS + Docker，有 UPS 和 Frigate NVR 效果最佳。支持 Telegram 每日推送。\n  \n  **一句话**：不用天天盯着服务器，每天早上看一眼有没有🔴，有就照着修。\n\n  Triggers: \"nas status\", \"server status\", \"system dashboard\", \"文本仪表盘\", \"服务器状态\", \"系统健康\".\n\n# NAS Dashboard v3\n\nException-driven, alert-first text dashboard for NAS/HomeLab monitoring. Prioritises problems over green lights — if everything is healthy you get a one-liner, if something is wrong you get a surgical report with **severity ratings** and **actionable fix commands**.\n\n**Platform**: Linux (Ubuntu/Debian tested). Partial support: any Linux with ZFS. macOS/Windows: most sections unavailable (ZFS, SMART, systemd, apt, iostat, sensors are Linux-only).\n\n## Design Principles\n\n1. **Alerts First**: ❌/⚠️ always on top. No alerts → no ALERTS section.\n2. **Normal is Invisible**: Don't list 15 healthy containers. Collapse to \"X running (Y OK)\".\n3. **Contextual Correlation**: Disk ↔ ZFS vdev, container unhealthy + CPU process = zombie.\n4. **Actionable Thresholds**: Timeshift >100 warns, SMART realloc>0 alarms, disk>45°C flags.\n5. **Unified Timestamps**: All times in `YYYY-MM-DD HH:MM` or `XdXh` relative.\n\n## Quick Start\n\n### Configure (optional)\n\n```bash\nexport ZPOOL=\"tank\"              # default: auto-detect first pool\nexport DISK_LIST=\"sda sdb sdc\"   # default: auto-detect all /dev/sd?\nexport FRIGATE_CAM_MAP=\"cam_d82e8e00:客厅,cam_ae7e3010:门口,cam_a24a20c0:车库\"\nexport UPS_NAME=\"ups@localhost\"  # default: ups@localhost\n```\n\n### Run\n\n```bash\nbash scripts/collect.sh\n```\n\n### Cron setup\n\n```bash\nopenclaw cron add \\\n  --name \"NAS仪表盘\" \\\n  --schedule \"0 9 * * *\" \\\n  --agent main \\\n  --timeout 180 \\\n  --delivery \"announce:telegram:YOUR_CHAT_ID\" \\\n  --prompt \"Run nas-dashboard skill: collect and format the dashboard report, then send to Telegram.\"\n```\n\n## Workflow\n\n### 1. Collect data\n\nRun `scripts/collect.sh`. Sections: SYSTEM, ZFS, VDEV_DISK (disk→pool mapping), DISKS (incl. SMART realloc/pending/udma), DISKIO, DOCKER, FRIGATE, GPU, NETWORK, PROCESSES, SERVICES, LOGS, SHARES, SECURITY, UPDATES, BOOT, UPS, TIMESHIFT.\n\n### 2. Format output — Alert-First Layout\n\n#### Step 0: Scan for Alerts (always do this first)\n\nScan ALL collected data against these thresholds and classify severity:\n\n| Scope | Condition | Severity |\n|-------|-----------|----------|\n| Pool health ≠ ONLINE | any pool | ❌ CRITICAL |\n| Scrub errors > 0 | any pool | ❌ CRITICAL |\n| ZFS_EVENT present | any event | ⚠️ WARNING |\n| Disk health ≠ PASSED | any disk | ❌ CRITICAL |\n| Disk realloc > 0 | any disk | ❌ CRITICAL |\n| Disk pending > 0 | any disk | ⚠️ WARNING |\n| Disk udma_crc > 100 | any disk | ⚠️ WARNING |\n| Disk temp > 45°C | any disk | ⚠️ WARNING |\n| Disk temp > 55°C | any disk | ❌"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn764er6cp7n2yqb0wch6zx1dn83h07f\",\n  \"slug\": \"nas-dashboard\",\n  \"version\": \"3.0.1\",\n  \"publishedAt\": 1780221564624\n}"},{"path":"skill-card.md","content":"## Description:\n\nGenerates an alert-first text NAS and HomeLab dashboard covering system health, ZFS pools, disk SMART status, Docker, Frigate, GPU, UPS, backups, updates, and security checks.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[wudi488](https://clawhub.ai/user/wudi488)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nNAS, HomeLab, and self-hosted service operators use this skill to collect a daily health report and prioritize issues that need attention. It is best suited for Linux hosts running ZFS, Docker, UPS monitoring, and optional Frigate or NVIDIA GPU workloads.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The report may include sensitive infrastructure and security details, especially when delivered to Telegram.\n\nMitigation: Send reports only to trusted private destinations and treat dashboard output as operationally sensitive.\n\nRisk: Collection depends on passwordless sudo for host, SMART, firewall, SSH, and backup checks.\n\nMitigation: Use a tightly scoped sudoers policy for the required diagnostics instead of broad passwordless sudo.\n\nRisk: The dashboard can print privileged repair commands for storage, SSH, firewall, updates, and backups.\n\nMitigation: Review each command manually before execution and confirm it matches the host's storage, network, and backup configuration.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/wudi488/skills/nas-dashboard)\n- [Packaged skill instructions](artifact/SKILL.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, shell commands, configuration, guidance]\n\n**Output Format:** [Plain text dashboard report with inline shell commands]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Alert-first report intended to stay under 2000 characters, with severity labels and action guidance.]\n\n## Skill Version(s):\n\n3.0.1 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Us... Skill: NAS Dashboard Owner: wudi488 Summary: Generates a unified text-based NAS dashboard with system health, ZFS pools, disk SMART, Docker containers, GPU status, UPS, backup services, and security. Us... Tags: latest:3.0.1 Version history: v3.0.1 | 2026-05-31T09:59:24.624Z | user v3.0.1: 📢 更新营销描述——明确目标用户(自建NAS/HomeLab/自托管服务)、最佳使用环境(Ubuntu+ZFS+Docker+UPS)、一句话价值主张(每天早上看一眼🔴红灯，有就照着修)。 v3.0.0 | 2026-05-31T09:58:20.769","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1025,"uniquenessScore":56,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T05:35:33.156Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T05:35:33.156Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:41:39.270Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}