{"id":"2da26ffd-1a2e-49df-9da8-7ee9ee9bf36a","entityType":"agent","slug":"clawhub-zw008-vmware-vdi","name":"vmware-vdi","canonicalUrl":"https://www.xpersona.co/agent/clawhub-zw008-vmware-vdi","canonicalPath":"/agent/clawhub-zw008-vmware-vdi","generatedAt":"2026-10-12T19:18:44.692Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T21:42:45.205Z","emptyReason":null},"description":"Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance, remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool / RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops), read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security). This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 989 downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-vdi","sourceUrl":"https://clawhub.ai/zw008/vmware-vdi","homepage":"https://clawhub.ai/zw008/skills/vmware-vdi","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/zw008/vmware-vdi","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/zw008/skills/vmware-vdi","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"vmware-vdi technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T21:42:45.205Z","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-11T21:42:45.205Z","emptyReason":null},"stars":null,"forks":null,"downloads":989,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"1.3.0","tractionLabel":"989 downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T21:42:45.134Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T21:42:45.205Z","lastCrawledAt":"2026-10-11T21:42:45.134Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T21:42:45.134Z","lastVerifiedAt":null,"highlights":[{"version":"1.3.0","createdAt":"2026-09-20T14:52:21.854Z","changelog":"MCP instructions now name the configured targets and how to choose one; a config that cannot be read says so instead of falling silent.","fileCount":6,"zipByteSize":12189},{"version":"1.2.0","createdAt":"2026-09-19T03:56:05.655Z","changelog":"Destructive MCP tools preview by default (confirm=False) and state their blast radius; confirm=True refuses on blockers or unreadable measurements. Requires vmware-policy>=1.17.0.","fileCount":6,"zipByteSize":12054},{"version":"1.1.1","createdAt":"2026-09-15T06:08:19.846Z","changelog":"CLI reads are audited under their MCP tool names; every CLI command declares what it reaches (needs vmware-policy 1.15.0)","fileCount":6,"zipByteSize":11125},{"version":"1.1.0","createdAt":"2026-09-12T00:20:07.979Z","changelog":"CLI writes are authorised and audited under their MCP tool names, and a policy denial prints the rule and its reason and exits 1 instead of raising a traceback.","fileCount":6,"zipByteSize":11112},{"version":"1.0.7","createdAt":"2026-08-31T07:25:17.290Z","changelog":"one answer per .env, on every platform","fileCount":6,"zipByteSize":11130},{"version":"1.0.6","createdAt":"2026-08-31T00:37:00.174Z","changelog":"fix: run the suite on a non-UTF-8 machine, and stop one skill answering for another","fileCount":6,"zipByteSize":11017},{"version":"1.0.5","createdAt":"2026-08-30T15:20:16.045Z","changelog":"Second-round fixes from the 2026-08-30 VCF 9.1 re-test; vmware-policy floor raised to 1.11.0 (the engine no longer fails open when rules.yaml cannot be read).","fileCount":6,"zipByteSize":11040},{"version":"1.0.4","createdAt":"2026-08-30T09:35:29.589Z","changelog":"Parameter descriptions now reach the MCP JSON schema (0% -> 100% coverage); additionalProperties closed; vmware-policy floor raised to 1.10.0.","fileCount":6,"zipByteSize":10960}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-vdi","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-vdi` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/zw008/vmware-vdi before using production credentials."],"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-zw008-vmware-vdi/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/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-12T19:18:44.690Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vdi/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":"medium","updatedAt":"2026-10-11T21:42:45.205Z","emptyReason":null},"readme":"Skill: vmware-vdi\n\nOwner: zw008\n\nSummary: Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance, remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool / RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops), read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security). This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\n\nTags: latest:1.3.0\n\nVersion history:\n\nv1.3.0 | 2026-09-20T14:52:21.854Z | user\n\nMCP instructions now name the configured targets and how to choose one; a config that cannot be read says so instead of falling silent.\n\nv1.2.0 | 2026-09-19T03:56:05.655Z | user\n\nDestructive MCP tools preview by default (confirm=False) and state their blast radius; confirm=True refuses on blockers or unreadable measurements. Requires vmware-policy>=1.17.0.\n\nv1.1.1 | 2026-09-15T06:08:19.846Z | user\n\nCLI reads are audited under their MCP tool names; every CLI command declares what it reaches (needs vmware-policy 1.15.0)\n\nv1.1.0 | 2026-09-12T00:20:07.979Z | user\n\nCLI writes are authorised and audited under their MCP tool names, and a policy denial prints the rule and its reason and exits 1 instead of raising a traceback.\n\nv1.0.7 | 2026-08-31T07:25:17.290Z | user\n\none answer per .env, on every platform\n\nv1.0.6 | 2026-08-31T00:37:00.174Z | user\n\nfix: run the suite on a non-UTF-8 machine, and stop one skill answering for another\n\nv1.0.5 | 2026-08-30T15:20:16.045Z | user\n\nSecond-round fixes from the 2026-08-30 VCF 9.1 re-test; vmware-policy floor raised to 1.11.0 (the engine no longer fails open when rules.yaml cannot be read).\n\nv1.0.4 | 2026-08-30T09:35:29.589Z | user\n\nParameter descriptions now reach the MCP JSON schema (0% -> 100% coverage); additionalProperties closed; vmware-policy floor raised to 1.10.0.\n\nv1.0.3 | 2026-08-30T07:45:25.714Z | user\n\nA 404 on login no longer tells you to run the call that just failed; doctor no longer reports the config missing while reading it; server.json starts the MCP server.\n\nv1.0.2 | 2026-08-28T02:57:19.493Z | user\n\nFixes the server's self-reported version and the advertised tool count; adds a Claude Code plugin manifest.\n\nv1.0.1 | 2026-08-01T03:12:49.297Z | user\n\nMoved to vmware-skills GitHub org; MCP Registry namespace → io.github.vmware-skills. Links updated.\n\nv1.0.0 | 2026-07-31T12:44:12.832Z | user\n\nFirst release (beta): 27 MCP tools for VMware/Omnissa Horizon VDI — sessions, machines, pools, image push, entitlements, tasks. Endpoints verified vs official API; field projections pending live-Horizon validation.\n\nArchive index:\n\nArchive v1.3.0: 6 files, 12189 bytes\n\nFiles: references/capabilities.md (5018b), references/cli-reference.md (2713b), references/setup-guide.md (2984b), skill-card.md (2784b), SKILL.md (12714b), _meta.json (129b)\n\nFile v1.3.0:SKILL.md\n\n---\nname: vmware-vdi\ndescription: >\n  Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its\n  Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on\n  user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance,\n  remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone\n  golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop\n  pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to\n  the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool /\n  RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops),\n  read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security).\n  This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\ninstaller:\n  kind: uv\n  package: vmware-vdi\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vdi\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VDI_CONFIG\"]}}}\n---\n\n# VMware VDI (Horizon)\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.** \"VMware\", \"Horizon\", and \"Omnissa\" are\n> trademarks of their respective owners. Source is publicly auditable under the MIT license.\n\nHorizon VDI intelligent operations for the VMware skill family — desktop pools, RDS farms, **user\nsessions**, desktop machines, entitlements, events/health/statistics, and instant-clone image push,\nthrough the **Horizon 8 Connection Server REST API** (primary; also targets the latest Omnissa Horizon,\nwhich shares the same `/rest/v1` API lineage).\n\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (the vCenter VMs backing\n> the desktops), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only vSphere),\n> [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (desktop microsegmentation).\n\n> **Status: v1.0.0 (beta).** Endpoints are verified against the official Horizon Server API; GET-response\n> field projections are defensive and pending validation against a live Connection Server (run\n> `vmware-vdi init` on a real Horizon once to confirm). Governed by the family harness (audit + policy +\n> teaching errors); authorization is delegated to the Horizon admin account's role.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read/Write |\n|----------|-------|:-----:|:----------:|\n| **Monitoring** | health summary, session list/get, machine list/get, event list | 6 | 6 R |\n| **Statistics** | session concurrency stats, per-pool utilization | 2 | 2 R |\n| **Management** | pool list/get, farm list, app-pool list, entitlement list, image list, AD search; pool enable/disable, entitlement add/remove | 9 | 7 R / 2 W |\n| **Ops actions** | session logoff/disconnect/message, machine reset/maintenance/remove | 6 | 6 W |\n| **Tasks** | task status; image push, task cancel | 3 | 1 R / 2 W |\n\n**27 MCP tools (16 read / 11 write).** Reads are strictly non-destructive. Writes preview their blast\nradius, are double-confirmed at the CLI, and are audit-logged.\n\n## Quick Install\n\n```bash\nuv tool install vmware-vdi==1.3.0\nvmware-vdi init      # friendly setup: connect to a Connection Server + discover your pools\nvmware-vdi doctor    # verify config / credentials / connectivity\n```\n\n## When to Use This Skill\n\nUse vmware-vdi for the **Horizon broker layer**: desktop pools, RDS farms, published apps, **user\nsessions** (logoff/disconnect/message), desktop machine state (reset/maintenance/remove), entitlements,\nHorizon events/health/statistics, and **instant-clone image push** — when the context is explicitly\nHorizon / Omnissa / VDI / desktop-pool / RDS-farm.\n\n**Do NOT use when**: the task is the underlying vCenter VM (power/snapshot/clone/migrate → **vmware-aiops**),\nread-only vSphere inventory/alarms (→ **vmware-monitor**), or NSX microsegmentation of the desktops\n(→ **vmware-nsx-security**). A Horizon desktop's *backing VM* is aiops; the *session/pool/broker* is vdi.\n\n## Related Skills — Skill Routing\n\n| The user wants… | Skill |\n|-----------------|-------|\n| Log off / reset / re-image a Horizon desktop or session | **vmware-vdi** (this) |\n| Power/snapshot/clone/migrate the backing vCenter VM | vmware-aiops |\n| Read-only vSphere inventory / alarms / host health | vmware-monitor |\n| Microsegment the desktop pool network | vmware-nsx-security |\n| Multi-step VDI workflow with approval + rollback | vmware-pilot |\n\n## Common Workflows\n\n**1. Help-desk: a user's desktop is stuck.**\n```\nvmware-vdi session list --user alice          # find their session + state\nvmware-vdi machine list --state AGENT_UNREACHABLE   # is the desktop broken?\nvmware-vdi session logoff --user alice --dry-run    # preview blast radius (which sessions)\nvmware-vdi session logoff --user alice        # double-confirm, then logs off + audits\n```\n*Failure branch*: if `session list` returns a teaching 404/auth error, run `vmware-vdi doctor` — a\nread-only Horizon role is enough for the reads but the account must be able to reach the Connection Server.\n\n**2. Patch night: push a new golden image to a pool.**\n```\nvmware-vdi image list                         # find the base VM + snapshot\nvmware-vdi pool push-image --id pool-fin --dry-run   # BLAST RADIUS: N desktops, M logged-in users\nvmware-vdi pool set-enabled --id pool-fin --disable  # optional: stop new logins first\nvmware-vdi pool push-image --id pool-fin      # double-confirm; returns a task\nvmware-vdi task status --pool pool-fin         # track progress\n```\n*Failure branch*: if the preview shows logged-in users you did not expect, `session send-message --user …`\nto warn them, or push with `--force-logoff` only after confirming impact.\n\n**3. Onboard a group to a pool.**\n```\nvmware-vdi ad-search \"Finance\"                # resolve the AD group → its SID\nvmware-vdi entitlement add --pool pool-fin --sid <SID>\nvmware-vdi entitlement list --pool pool-fin   # verify\n```\n*Failure branch*: `ad-search` returning nothing usually means the domain in `~/.vmware-vdi/config.yaml`\nis wrong — re-run `vmware-vdi init --force`.\n\n## Usage Mode\n\n- **CLI** — interactive help-desk work, scripting, small/local models (lower context cost).\n- **MCP** — agent-driven operations with structured output; run `vmware-vdi mcp` (an installed console\n  script, so no `uvx` network re-resolve — works through enterprise TLS proxies).\n\n## MCP Tools (27 — 16 read, 11 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Monitoring | `health_summary`, `session_list`, `session_get`, `machine_list`, `machine_get`, `event_list` | Read |\n| Statistics | `session_stats`, `pool_utilization` | Read |\n| Management (read) | `pool_list`, `pool_get`, `farm_list`, `app_pool_list`, `entitlement_list`, `image_list`, `ad_user_search` | Read |\n| Tasks (read) | `task_status` | Read |\n| Ops actions | `session_logoff`, `session_disconnect`, `session_send_message`, `machine_reset`, `machine_maintenance`, `machine_remove` | Write |\n| Management (write) | `pool_set_enabled`, `entitlement_add`, `entitlement_remove` | Write |\n| Tasks (write) | `pool_push_image`, `task_cancel` | Write |\n\n**List envelope**: every `*_list` tool returns `{items, returned, limit, total, truncated, hint}` — read\nrows from `items` and check `truncated` before concluding a listing is complete; empty `items` with\n`truncated:false` means checked-and-none, not a failure. Lists are fetched with server-side pagination.\n\n**Blast radius (normative)**: `pool_push_image` recreates **every desktop in the pool** — the highest\nsingle-call blast radius in the family. Its preview states affected-desktop and in-session counts\nbefore any confirm, plus `blast_radius.occupancy`: `determined` when those counts can be believed,\n`unknown` when session rows exist that belong to neither a desktop pool nor a farm and so cannot be\nruled out of this pool. An `unknown` occupancy makes `in_session_count` a lower bound and refuses\n`confirm=true` — check `session_list`, or pass `acknowledge_unknown_occupancy=true`, which is audited.\nMachines that name no desktop pool (`unattributed_desktops`) make the desktop count \"at least N\" and\nrefuse `confirm=true` with no override.\n\n**Confirmation gate (MCP)**: the ten gated writes (`session_logoff`/`disconnect`, `machine_reset`/\n`maintenance`/`remove`, `pool_set_enabled`, `pool_push_image`, `task_cancel`, `entitlement_add`/`remove`)\ntake `confirm` (default `false`). A call without it returns `blast_radius` — identity, counts, ids (up to\n20), `blockers`, `unmeasured` — and changes nothing; the acting response carries it too. Show it to the\nuser and pass `confirm=true` only after they agree: the user asking earlier is not agreement, they have\nnot seen it. If anything the blast radius depends on could not be read (a machine's state, a session's\nuser, a task's state, a pool's enabled flag, the pool's entitlements), `confirm=true` is refused.\n\n**Read/write split**: 16 read-only tools (`[READ]` docstring marker), 11 modify state. All writes are\naudit-logged; destructive ones (`session_logoff`, `machine_reset`, `machine_remove`, `pool_set_enabled`\ndisable, `entitlement_remove`, `pool_push_image`, `task_cancel`) require CLI double-confirmation and\nsupport `--dry-run`.\n\n## CLI Quick Reference\n\n```bash\nvmware-vdi init                                          # friendly setup + pool discovery\nvmware-vdi health                                        # one-glance VDI health\nvmware-vdi stats                                         # session concurrency statistics\nvmware-vdi utilization                                   # per-pool desktop utilization\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED]\nvmware-vdi session logoff --user U [--dry-run]           # double-confirm\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE]\nvmware-vdi machine reset --id M [--dry-run]              # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]   # highest blast radius\nvmware-vdi task status --pool P [--task T]\nvmware-vdi ad-search \"<name>\"                            # resolve AD SID for entitlement\nvmware-vdi entitlement add|remove --pool P --sid <SID>\n```\nFull list: `references/cli-reference.md`.\n\n## Troubleshooting\n\n- **`Password not found. Set environment variable: VMWARE_VDI_<TARGET>_PASSWORD`** — run `vmware-vdi init`\n  (writes `~/.vmware-vdi/.env`, 0600), or export the var manually.\n- **Login fails (HTTP 401/400)** — check `username`/`domain` in `~/.vmware-vdi/config.yaml`; Horizon\n  authenticates against the AD `domain`. A local Connection Server admin leaves `domain` blank.\n- **`certificate could not be verified`** — for a self-signed lab cert set `verify_ssl: false` for that\n  target in the config.\n- **A write is refused with \"read-only role\"** — that is RBAC working as designed. Point the target at a\n  Horizon admin role with write privilege, or keep the read-only account for read commands only.\n- **`session list --pool` or a push-image preview shows 0 where you expect users** — on your Horizon\n  version a field name may differ; this is a beta known-limitation, please file an issue with the raw\n  `session_get` output so the projection can be pinned.\n\n## Audit & Safety\n\n1. **Source Code** — https://github.com/vmware-skills/VMware-VDI (MIT).\n2. **Config File Contents** — `config.yaml` holds host/username/domain only; passwords live in\n   `~/.vmware-vdi/.env` (0600, obfuscated to `b64:` at rest — obfuscation, not encryption).\n3. **Webhook Data Scope** — none. This skill makes no outbound calls except to the configured\n   Connection Server.\n4. **TLS Verification** — on by default; `verify_ssl: false` is per-target and only for self-signed labs.\n5. **Prompt Injection Protection** — all Connection-Server-supplied text (user names, machine/pool names,\n   event messages) passes through `vmware_policy.sanitize()` (truncation + control-char stripping).\n6. **Least Privilege** — authorization is the Horizon account's job: a read-only Horizon admin role\n   refuses every write at the Connection Server, un-bypassably. All writes are recorded in\n   `~/.vmware/audit.db`. See `references/setup-guide.md`.\n\n## License\n\nMIT\n\nFile v1.3.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vdi\",\n  \"version\": \"1.3.0\",\n  \"publishedAt\": 1789915941854\n}\n\nFile v1.3.0:references/capabilities.md\n\n# vmware-vdi — Capabilities\n\n27 MCP tools (16 read / 11 write) over the Horizon 8 Connection Server REST API. Every tool accepts an\noptional `target`. Typical response tokens are estimates for a small estate; lists paginate at 50.\n\n## Monitoring (6 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `health_summary` | R | session totals by state, problem-machine count, pool enabled/disabled | 80–200 |\n| `session_list` | R | id, user, type, state, protocol, pool_id, machine_id, start_time (filter user/pool/state) | 60–500 |\n| `session_get` | R | one session's projection | 40–100 |\n| `machine_list` | R | id, name, pool_id, state, user, agent_version, base_image (filter pool/state) | 60–500 |\n| `machine_get` | R | one machine's projection | 40–100 |\n| `event_list` | R | time, severity, type, module, user, machine, message (filter severity) | 100–600 |\n\n## Statistics (2 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `session_stats` | R | current concurrent, by-state, by-protocol, top pools | 80–200 |\n| `pool_utilization` | R | per-pool total/available/in-use/error + utilization % | 80–300 |\n\n## Management (7 read / 2 write)\n| Tool | R/W | Notes | ~tokens |\n|------|:---:|-------|:------:|\n| `pool_list` / `pool_get` | R | pools: type, enabled, assignment | 60–300 |\n| `farm_list` | R | RDS farms: type, enabled, server count | 40–200 |\n| `app_pool_list` | R | published apps: farm, enabled, executable | 40–300 |\n| `entitlement_list` | R | AD principals entitled to a pool | 40–300 |\n| `image_list` | R | instant-clone base VMs + snapshots | 60–400 |\n| `ad_user_search` | R | resolve AD name → SID (for `entitlement_add`) | 40–200 |\n| `pool_set_enabled` | W | enable/disable pool (idempotent, preview) | 40–120 |\n| `entitlement_add` / `entitlement_remove` | W | grant/revoke pool access by SID (preview) | 40–120 |\n\n## Ops actions (6 write) — help-desk\n| Tool | R/W | Risk | Blast radius |\n|------|:---:|:----:|--------------|\n| `session_send_message` | W | low | informational, no disruption |\n| `session_disconnect` | W | medium | one session, state preserved |\n| `session_logoff` | W | high | kicks the user (profile write-back) |\n| `machine_maintenance` | W | medium | drains a machine (no new sessions) |\n| `machine_reset` | W | high | hard reset — user loses unsaved state |\n| `machine_remove` | W | high | removes from pool; deletes VM for instant clones |\n\n## Tasks (1 read / 2 write)\n| Tool | R/W | Notes |\n|------|:---:|-------|\n| `task_status` | R | pool-scoped task status/progress (or all tasks for the pool) |\n| `pool_push_image` | W | **critical** — apply pending image; recreates EVERY desktop; preview states affected desktops + in-session users |\n| `task_cancel` | W | cancel a running pool task (applied work is not rolled back) |\n\n**Confirmation gate (MCP)**: every write above except `session_send_message` takes `confirm`\n(default `false`). Without it the tool returns `{\"action\": \"preview\", \"blast_radius\": {...}, \"hint\": ...}`\nand changes nothing; with it the response carries the same `blast_radius`. The older per-tool keys\n(`would_affect`, `would_set`, `would_cancel`, `would_entitle`, `would_unentitle`) are still returned and\nare removed in the next minor release. What each blast radius measures, and what refuses `confirm=true`\nwhen it cannot be read:\n\n| Tool | `blast_radius` | Refused when unreadable |\n|------|----------------|-------------------------|\n| `machine_reset` / `machine_maintenance` / `machine_remove` | machine count, ids, names, states, assigned users, pool ids; `assignment_unread` lists machines whose row has no `user`/`assigned_user` field (not read ≠ nobody assigned; reported, not refused) | a machine's `state` |\n| `session_logoff` / `session_disconnect` | session count, ids, affected users | a session's user |\n| `task_cancel` | task type, state, progress (read via the task GET) | task type or state |\n| `pool_set_enabled` | pool id/name/type, current and new enabled state | the current enabled flag |\n| `pool_push_image` | pool id/name, affected desktops + ids, `unattributed_desktops` (+ ids: machines that name no pool, so the desktop count is a lower bound), in-session count/users, occupancy | occupancy (override: `acknowledge_unknown_occupancy`); machines with no pool id (no override) |\n| `entitlement_add` / `entitlement_remove` | pool id/name, principal ids, already entitled / newly entitled, or losing access / not entitled (a list-shaped entitlement answer is read across every page) | the pool's current entitlements |\n\n**Beta note (踩坑 #36)**: REST endpoints are verified against the official Horizon Server API operation\nindex. GET-response *field names* are defensive (`.get()` with fallbacks) and pending validation against a\nlive Connection Server — a mismatch yields empty results, not a crash. First real-Horizon use should\nconfirm the `session`/`machine`/`pool` projections and the `apply-image` / entitlement bodies.\n\nFile v1.3.0:references/cli-reference.md\n\n# vmware-vdi — CLI Reference\n\nAll commands accept `--target/-t <name>` (config target) and `--config/-c <path>` (alternate config file).\nDestructive commands accept `--dry-run` (preview only) and interactively double-confirm.\n\n## Setup & diagnostics\n```bash\nvmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point\n```\n\n## Monitoring & statistics (read-only)\n```bash\nvmware-vdi health                           # session totals, problem machines, pool availability\nvmware-vdi stats                            # concurrency by state/protocol, busiest pools\nvmware-vdi utilization                      # per-pool total/available/in-use/error + utilization %\nvmware-vdi events [--severity ERROR]        # recent Horizon audit events (newest first)\n```\n\n## Sessions\n```bash\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED|DISCONNECTED|PENDING]\nvmware-vdi session logoff [--id S] [--user U] [--dry-run]        # kicks the user; double-confirm\nvmware-vdi session disconnect [--id S] [--user U] [--dry-run]    # state preserved; double-confirm\nvmware-vdi session message \"<text>\" [--user U] [--id S] [--type INFO|WARNING|ERROR]\n```\n\n## Machines\n```bash\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE|ERROR|...]\nvmware-vdi machine reset --id M [--dry-run]                      # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit [--dry-run] # double-confirm\nvmware-vdi machine remove --id M [--dry-run]                     # deletes VM (instant clone); double-confirm\n```\n\n## Pools, images, tasks\n```bash\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable [--dry-run]  # disable stops NEW sessions\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]     # recreates EVERY desktop; double-confirm\nvmware-vdi images                                                  # instant-clone base VMs + snapshots\nvmware-vdi task status --pool P [--task T]                        # track an image push / provisioning\nvmware-vdi task cancel --pool P --task T [--dry-run]              # double-confirm\n```\n\n## Farms, apps, entitlements\n```bash\nvmware-vdi farm list\nvmware-vdi app-pool list\nvmware-vdi ad-search \"<name>\"                                     # resolve AD user/group → SID\nvmware-vdi entitlement list --pool P\nvmware-vdi entitlement add --pool P --sid <SID> [--sid <SID> ...] [--dry-run]\nvmware-vdi entitlement remove --pool P --sid <SID> [--dry-run]   # double-confirm\n```\n\nFile v1.3.0:references/setup-guide.md\n\n# vmware-vdi — Setup Guide\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.**\n\n## 1. Install\n```bash\nuv tool install vmware-vdi==1.3.0\n```\n\n## 2. Connect (friendly wizard)\n```bash\nvmware-vdi init\n```\nPrompts for the **Connection Server host**, admin **username**, AD **domain** (blank for a local admin),\n**password**, target name, and TLS verification. It writes `~/.vmware-vdi/config.yaml` +\n`~/.vmware-vdi/.env` (chmod 600), tests `/rest/login`, and on success **discovers your pools/machines/\nsessions** and prints the next commands to try. Re-run with `--force` to add another Connection Server\n(existing targets are preserved; the default is repointed to the new one).\n\nManual config (`~/.vmware-vdi/config.yaml`):\n```yaml\ndefault_target: prod\ntargets:\n  prod:\n    host: horizon-cs1.example.com\n    username: svc-vdi-ro          # a read-only Horizon role for read commands\n    domain: ACME                  # AD domain; blank for a local Connection Server admin\n    port: 443\n    verify_ssl: true              # false only for a self-signed lab cert\n```\nPassword (never in config.yaml): `~/.vmware-vdi/.env`\n```\nVMWARE_VDI_PROD_PASSWORD=b64:...    # written by `init`; or export it yourself (plaintext auto-obfuscated)\n```\n\n## 3. Verify\n```bash\nvmware-vdi doctor        # config / credentials / connectivity\n```\n\n## 4. Supported versions\n- **Primary: VMware Horizon 8.x** (Connection Server REST API `/rest/v1`).\n- **Latest Omnissa Horizon** (2406/2412+) — same `/rest/v1` lineage.\n- Requires the Connection Server REST API enabled (Horizon 8.0+; audit-events since 2106).\n\n## 5. MCP server\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vdi\": {\n      \"command\": \"vmware-vdi\",\n      \"args\": [\"mcp\"],\n      \"env\": { \"VMWARE_VDI_CONFIG\": \"~/.vmware-vdi/config.yaml\" }\n    }\n  }\n}\n```\nUsing the installed `vmware-vdi mcp` console script (not `uvx`) avoids a PyPI re-resolve on every launch —\nimportant behind enterprise TLS proxies.\n\n## Security\n> **Disclaimer**: not affiliated with VMware/Broadcom/Omnissa.\n\n- **Credentials**: password only in `~/.vmware-vdi/.env` (chmod 600, obfuscated `b64:` at rest —\n  obfuscation, not encryption). For real secrecy, inject `VMWARE_VDI_<TARGET>_PASSWORD` from a secret\n  manager (Vault / CyberArk / AWS SM / K8s Secret).\n- **Authorization = RBAC**: the skill does not gate read vs write itself. Point a target at a **read-only\n  Horizon admin role** and every write is refused at the Connection Server, un-bypassably.\n- **TLS**: verification on by default; `verify_ssl: false` is per-target, for self-signed labs only.\n- **Prompt-injection**: Connection-Server text is `sanitize()`d (truncated + control chars stripped).\n- **Audit**: all writes recorded in `~/.vmware/audit.db` (SQLite WAL) via the shared `@vmware_tool` guard.\n- **No outbound calls** other than to the configured Connection Server; no webhooks, no telemetry.\n\nFile v1.3.0:skill-card.md\n\n## Description:\n\nUse this skill to operate a VMware/Omnissa Horizon VDI environment through its Connection Server, including desktop pools, RDS farms, published apps, user sessions, desktop machines, entitlements, events, health, statistics, and instant-clone image pushes.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, IT operations staff, and help-desk operators use this skill to inspect and administer Horizon VDI broker-layer resources, troubleshoot user sessions and pool health, manage entitlements, and carry out controlled operational actions such as logoff, desktop reset, task cancellation, and golden-image push.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can perform powerful Horizon administration actions, including logging off users, resetting or removing desktops, changing entitlements, cancelling tasks, and pushing images.\n\nMitigation: Use least-privilege Horizon accounts, prefer read-only roles for monitoring, grant write privileges only to authorized operators, and require review of blast-radius previews before confirmed actions.\n\nRisk: Golden-image pushes and some desktop operations can affect many desktops or active user sessions.\n\nMitigation: Use dry-run or preview flows, check session and occupancy data, warn affected users when appropriate, and rely on the documented confirmation gates and audit logging.\n\nRisk: Local password storage is documented as b64 obfuscation rather than encryption.\n\nMitigation: Prefer a real secret manager for production credentials and protect local configuration and environment files with restrictive filesystem permissions.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/zw008/skills/vmware-vdi)\n- [Capabilities Reference](artifact/references/capabilities.md)\n- [CLI Reference](artifact/references/cli-reference.md)\n- [Setup Guide](artifact/references/setup-guide.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline shell commands and JSON/YAML configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Horizon resource identifiers, blast-radius previews, troubleshooting steps, and setup or MCP configuration guidance.]\n\n## Skill Version(s):\n\n1.3.0 (source: ClawHub release metadata and artifact install instructions)\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 v1.2.0: 6 files, 12054 bytes\n\nFiles: references/capabilities.md (5018b), references/cli-reference.md (2713b), references/setup-guide.md (2984b), skill-card.md (2449b), SKILL.md (12714b), _meta.json (129b)\n\nFile v1.2.0:SKILL.md\n\n---\nname: vmware-vdi\ndescription: >\n  Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its\n  Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on\n  user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance,\n  remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone\n  golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop\n  pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to\n  the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool /\n  RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops),\n  read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security).\n  This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\ninstaller:\n  kind: uv\n  package: vmware-vdi\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vdi\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VDI_CONFIG\"]}}}\n---\n\n# VMware VDI (Horizon)\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.** \"VMware\", \"Horizon\", and \"Omnissa\" are\n> trademarks of their respective owners. Source is publicly auditable under the MIT license.\n\nHorizon VDI intelligent operations for the VMware skill family — desktop pools, RDS farms, **user\nsessions**, desktop machines, entitlements, events/health/statistics, and instant-clone image push,\nthrough the **Horizon 8 Connection Server REST API** (primary; also targets the latest Omnissa Horizon,\nwhich shares the same `/rest/v1` API lineage).\n\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (the vCenter VMs backing\n> the desktops), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only vSphere),\n> [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (desktop microsegmentation).\n\n> **Status: v1.0.0 (beta).** Endpoints are verified against the official Horizon Server API; GET-response\n> field projections are defensive and pending validation against a live Connection Server (run\n> `vmware-vdi init` on a real Horizon once to confirm). Governed by the family harness (audit + policy +\n> teaching errors); authorization is delegated to the Horizon admin account's role.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read/Write |\n|----------|-------|:-----:|:----------:|\n| **Monitoring** | health summary, session list/get, machine list/get, event list | 6 | 6 R |\n| **Statistics** | session concurrency stats, per-pool utilization | 2 | 2 R |\n| **Management** | pool list/get, farm list, app-pool list, entitlement list, image list, AD search; pool enable/disable, entitlement add/remove | 9 | 7 R / 2 W |\n| **Ops actions** | session logoff/disconnect/message, machine reset/maintenance/remove | 6 | 6 W |\n| **Tasks** | task status; image push, task cancel | 3 | 1 R / 2 W |\n\n**27 MCP tools (16 read / 11 write).** Reads are strictly non-destructive. Writes preview their blast\nradius, are double-confirmed at the CLI, and are audit-logged.\n\n## Quick Install\n\n```bash\nuv tool install vmware-vdi==1.2.0\nvmware-vdi init      # friendly setup: connect to a Connection Server + discover your pools\nvmware-vdi doctor    # verify config / credentials / connectivity\n```\n\n## When to Use This Skill\n\nUse vmware-vdi for the **Horizon broker layer**: desktop pools, RDS farms, published apps, **user\nsessions** (logoff/disconnect/message), desktop machine state (reset/maintenance/remove), entitlements,\nHorizon events/health/statistics, and **instant-clone image push** — when the context is explicitly\nHorizon / Omnissa / VDI / desktop-pool / RDS-farm.\n\n**Do NOT use when**: the task is the underlying vCenter VM (power/snapshot/clone/migrate → **vmware-aiops**),\nread-only vSphere inventory/alarms (→ **vmware-monitor**), or NSX microsegmentation of the desktops\n(→ **vmware-nsx-security**). A Horizon desktop's *backing VM* is aiops; the *session/pool/broker* is vdi.\n\n## Related Skills — Skill Routing\n\n| The user wants… | Skill |\n|-----------------|-------|\n| Log off / reset / re-image a Horizon desktop or session | **vmware-vdi** (this) |\n| Power/snapshot/clone/migrate the backing vCenter VM | vmware-aiops |\n| Read-only vSphere inventory / alarms / host health | vmware-monitor |\n| Microsegment the desktop pool network | vmware-nsx-security |\n| Multi-step VDI workflow with approval + rollback | vmware-pilot |\n\n## Common Workflows\n\n**1. Help-desk: a user's desktop is stuck.**\n```\nvmware-vdi session list --user alice          # find their session + state\nvmware-vdi machine list --state AGENT_UNREACHABLE   # is the desktop broken?\nvmware-vdi session logoff --user alice --dry-run    # preview blast radius (which sessions)\nvmware-vdi session logoff --user alice        # double-confirm, then logs off + audits\n```\n*Failure branch*: if `session list` returns a teaching 404/auth error, run `vmware-vdi doctor` — a\nread-only Horizon role is enough for the reads but the account must be able to reach the Connection Server.\n\n**2. Patch night: push a new golden image to a pool.**\n```\nvmware-vdi image list                         # find the base VM + snapshot\nvmware-vdi pool push-image --id pool-fin --dry-run   # BLAST RADIUS: N desktops, M logged-in users\nvmware-vdi pool set-enabled --id pool-fin --disable  # optional: stop new logins first\nvmware-vdi pool push-image --id pool-fin      # double-confirm; returns a task\nvmware-vdi task status --pool pool-fin         # track progress\n```\n*Failure branch*: if the preview shows logged-in users you did not expect, `session send-message --user …`\nto warn them, or push with `--force-logoff` only after confirming impact.\n\n**3. Onboard a group to a pool.**\n```\nvmware-vdi ad-search \"Finance\"                # resolve the AD group → its SID\nvmware-vdi entitlement add --pool pool-fin --sid <SID>\nvmware-vdi entitlement list --pool pool-fin   # verify\n```\n*Failure branch*: `ad-search` returning nothing usually means the domain in `~/.vmware-vdi/config.yaml`\nis wrong — re-run `vmware-vdi init --force`.\n\n## Usage Mode\n\n- **CLI** — interactive help-desk work, scripting, small/local models (lower context cost).\n- **MCP** — agent-driven operations with structured output; run `vmware-vdi mcp` (an installed console\n  script, so no `uvx` network re-resolve — works through enterprise TLS proxies).\n\n## MCP Tools (27 — 16 read, 11 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Monitoring | `health_summary`, `session_list`, `session_get`, `machine_list`, `machine_get`, `event_list` | Read |\n| Statistics | `session_stats`, `pool_utilization` | Read |\n| Management (read) | `pool_list`, `pool_get`, `farm_list`, `app_pool_list`, `entitlement_list`, `image_list`, `ad_user_search` | Read |\n| Tasks (read) | `task_status` | Read |\n| Ops actions | `session_logoff`, `session_disconnect`, `session_send_message`, `machine_reset`, `machine_maintenance`, `machine_remove` | Write |\n| Management (write) | `pool_set_enabled`, `entitlement_add`, `entitlement_remove` | Write |\n| Tasks (write) | `pool_push_image`, `task_cancel` | Write |\n\n**List envelope**: every `*_list` tool returns `{items, returned, limit, total, truncated, hint}` — read\nrows from `items` and check `truncated` before concluding a listing is complete; empty `items` with\n`truncated:false` means checked-and-none, not a failure. Lists are fetched with server-side pagination.\n\n**Blast radius (normative)**: `pool_push_image` recreates **every desktop in the pool** — the highest\nsingle-call blast radius in the family. Its preview states affected-desktop and in-session counts\nbefore any confirm, plus `blast_radius.occupancy`: `determined` when those counts can be believed,\n`unknown` when session rows exist that belong to neither a desktop pool nor a farm and so cannot be\nruled out of this pool. An `unknown` occupancy makes `in_session_count` a lower bound and refuses\n`confirm=true` — check `session_list`, or pass `acknowledge_unknown_occupancy=true`, which is audited.\nMachines that name no desktop pool (`unattributed_desktops`) make the desktop count \"at least N\" and\nrefuse `confirm=true` with no override.\n\n**Confirmation gate (MCP)**: the ten gated writes (`session_logoff`/`disconnect`, `machine_reset`/\n`maintenance`/`remove`, `pool_set_enabled`, `pool_push_image`, `task_cancel`, `entitlement_add`/`remove`)\ntake `confirm` (default `false`). A call without it returns `blast_radius` — identity, counts, ids (up to\n20), `blockers`, `unmeasured` — and changes nothing; the acting response carries it too. Show it to the\nuser and pass `confirm=true` only after they agree: the user asking earlier is not agreement, they have\nnot seen it. If anything the blast radius depends on could not be read (a machine's state, a session's\nuser, a task's state, a pool's enabled flag, the pool's entitlements), `confirm=true` is refused.\n\n**Read/write split**: 16 read-only tools (`[READ]` docstring marker), 11 modify state. All writes are\naudit-logged; destructive ones (`session_logoff`, `machine_reset`, `machine_remove`, `pool_set_enabled`\ndisable, `entitlement_remove`, `pool_push_image`, `task_cancel`) require CLI double-confirmation and\nsupport `--dry-run`.\n\n## CLI Quick Reference\n\n```bash\nvmware-vdi init                                          # friendly setup + pool discovery\nvmware-vdi health                                        # one-glance VDI health\nvmware-vdi stats                                         # session concurrency statistics\nvmware-vdi utilization                                   # per-pool desktop utilization\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED]\nvmware-vdi session logoff --user U [--dry-run]           # double-confirm\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE]\nvmware-vdi machine reset --id M [--dry-run]              # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]   # highest blast radius\nvmware-vdi task status --pool P [--task T]\nvmware-vdi ad-search \"<name>\"                            # resolve AD SID for entitlement\nvmware-vdi entitlement add|remove --pool P --sid <SID>\n```\nFull list: `references/cli-reference.md`.\n\n## Troubleshooting\n\n- **`Password not found. Set environment variable: VMWARE_VDI_<TARGET>_PASSWORD`** — run `vmware-vdi init`\n  (writes `~/.vmware-vdi/.env`, 0600), or export the var manually.\n- **Login fails (HTTP 401/400)** — check `username`/`domain` in `~/.vmware-vdi/config.yaml`; Horizon\n  authenticates against the AD `domain`. A local Connection Server admin leaves `domain` blank.\n- **`certificate could not be verified`** — for a self-signed lab cert set `verify_ssl: false` for that\n  target in the config.\n- **A write is refused with \"read-only role\"** — that is RBAC working as designed. Point the target at a\n  Horizon admin role with write privilege, or keep the read-only account for read commands only.\n- **`session list --pool` or a push-image preview shows 0 where you expect users** — on your Horizon\n  version a field name may differ; this is a beta known-limitation, please file an issue with the raw\n  `session_get` output so the projection can be pinned.\n\n## Audit & Safety\n\n1. **Source Code** — https://github.com/vmware-skills/VMware-VDI (MIT).\n2. **Config File Contents** — `config.yaml` holds host/username/domain only; passwords live in\n   `~/.vmware-vdi/.env` (0600, obfuscated to `b64:` at rest — obfuscation, not encryption).\n3. **Webhook Data Scope** — none. This skill makes no outbound calls except to the configured\n   Connection Server.\n4. **TLS Verification** — on by default; `verify_ssl: false` is per-target and only for self-signed labs.\n5. **Prompt Injection Protection** — all Connection-Server-supplied text (user names, machine/pool names,\n   event messages) passes through `vmware_policy.sanitize()` (truncation + control-char stripping).\n6. **Least Privilege** — authorization is the Horizon account's job: a read-only Horizon admin role\n   refuses every write at the Connection Server, un-bypassably. All writes are recorded in\n   `~/.vmware/audit.db`. See `references/setup-guide.md`.\n\n## License\n\nMIT\n\nFile v1.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vdi\",\n  \"version\": \"1.2.0\",\n  \"publishedAt\": 1789790165655\n}\n\nFile v1.2.0:references/capabilities.md\n\n# vmware-vdi — Capabilities\n\n27 MCP tools (16 read / 11 write) over the Horizon 8 Connection Server REST API. Every tool accepts an\noptional `target`. Typical response tokens are estimates for a small estate; lists paginate at 50.\n\n## Monitoring (6 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `health_summary` | R | session totals by state, problem-machine count, pool enabled/disabled | 80–200 |\n| `session_list` | R | id, user, type, state, protocol, pool_id, machine_id, start_time (filter user/pool/state) | 60–500 |\n| `session_get` | R | one session's projection | 40–100 |\n| `machine_list` | R | id, name, pool_id, state, user, agent_version, base_image (filter pool/state) | 60–500 |\n| `machine_get` | R | one machine's projection | 40–100 |\n| `event_list` | R | time, severity, type, module, user, machine, message (filter severity) | 100–600 |\n\n## Statistics (2 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `session_stats` | R | current concurrent, by-state, by-protocol, top pools | 80–200 |\n| `pool_utilization` | R | per-pool total/available/in-use/error + utilization % | 80–300 |\n\n## Management (7 read / 2 write)\n| Tool | R/W | Notes | ~tokens |\n|------|:---:|-------|:------:|\n| `pool_list` / `pool_get` | R | pools: type, enabled, assignment | 60–300 |\n| `farm_list` | R | RDS farms: type, enabled, server count | 40–200 |\n| `app_pool_list` | R | published apps: farm, enabled, executable | 40–300 |\n| `entitlement_list` | R | AD principals entitled to a pool | 40–300 |\n| `image_list` | R | instant-clone base VMs + snapshots | 60–400 |\n| `ad_user_search` | R | resolve AD name → SID (for `entitlement_add`) | 40–200 |\n| `pool_set_enabled` | W | enable/disable pool (idempotent, preview) | 40–120 |\n| `entitlement_add` / `entitlement_remove` | W | grant/revoke pool access by SID (preview) | 40–120 |\n\n## Ops actions (6 write) — help-desk\n| Tool | R/W | Risk | Blast radius |\n|------|:---:|:----:|--------------|\n| `session_send_message` | W | low | informational, no disruption |\n| `session_disconnect` | W | medium | one session, state preserved |\n| `session_logoff` | W | high | kicks the user (profile write-back) |\n| `machine_maintenance` | W | medium | drains a machine (no new sessions) |\n| `machine_reset` | W | high | hard reset — user loses unsaved state |\n| `machine_remove` | W | high | removes from pool; deletes VM for instant clones |\n\n## Tasks (1 read / 2 write)\n| Tool | R/W | Notes |\n|------|:---:|-------|\n| `task_status` | R | pool-scoped task status/progress (or all tasks for the pool) |\n| `pool_push_image` | W | **critical** — apply pending image; recreates EVERY desktop; preview states affected desktops + in-session users |\n| `task_cancel` | W | cancel a running pool task (applied work is not rolled back) |\n\n**Confirmation gate (MCP)**: every write above except `session_send_message` takes `confirm`\n(default `false`). Without it the tool returns `{\"action\": \"preview\", \"blast_radius\": {...}, \"hint\": ...}`\nand changes nothing; with it the response carries the same `blast_radius`. The older per-tool keys\n(`would_affect`, `would_set`, `would_cancel`, `would_entitle`, `would_unentitle`) are still returned and\nare removed in the next minor release. What each blast radius measures, and what refuses `confirm=true`\nwhen it cannot be read:\n\n| Tool | `blast_radius` | Refused when unreadable |\n|------|----------------|-------------------------|\n| `machine_reset` / `machine_maintenance` / `machine_remove` | machine count, ids, names, states, assigned users, pool ids; `assignment_unread` lists machines whose row has no `user`/`assigned_user` field (not read ≠ nobody assigned; reported, not refused) | a machine's `state` |\n| `session_logoff` / `session_disconnect` | session count, ids, affected users | a session's user |\n| `task_cancel` | task type, state, progress (read via the task GET) | task type or state |\n| `pool_set_enabled` | pool id/name/type, current and new enabled state | the current enabled flag |\n| `pool_push_image` | pool id/name, affected desktops + ids, `unattributed_desktops` (+ ids: machines that name no pool, so the desktop count is a lower bound), in-session count/users, occupancy | occupancy (override: `acknowledge_unknown_occupancy`); machines with no pool id (no override) |\n| `entitlement_add` / `entitlement_remove` | pool id/name, principal ids, already entitled / newly entitled, or losing access / not entitled (a list-shaped entitlement answer is read across every page) | the pool's current entitlements |\n\n**Beta note (踩坑 #36)**: REST endpoints are verified against the official Horizon Server API operation\nindex. GET-response *field names* are defensive (`.get()` with fallbacks) and pending validation against a\nlive Connection Server — a mismatch yields empty results, not a crash. First real-Horizon use should\nconfirm the `session`/`machine`/`pool` projections and the `apply-image` / entitlement bodies.\n\nFile v1.2.0:references/cli-reference.md\n\n# vmware-vdi — CLI Reference\n\nAll commands accept `--target/-t <name>` (config target) and `--config/-c <path>` (alternate config file).\nDestructive commands accept `--dry-run` (preview only) and interactively double-confirm.\n\n## Setup & diagnostics\n```bash\nvmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point\n```\n\n## Monitoring & statistics (read-only)\n```bash\nvmware-vdi health                           # session totals, problem machines, pool availability\nvmware-vdi stats                            # concurrency by state/protocol, busiest pools\nvmware-vdi utilization                      # per-pool total/available/in-use/error + utilization %\nvmware-vdi events [--severity ERROR]        # recent Horizon audit events (newest first)\n```\n\n## Sessions\n```bash\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED|DISCONNECTED|PENDING]\nvmware-vdi session logoff [--id S] [--user U] [--dry-run]        # kicks the user; double-confirm\nvmware-vdi session disconnect [--id S] [--user U] [--dry-run]    # state preserved; double-confirm\nvmware-vdi session message \"<text>\" [--user U] [--id S] [--type INFO|WARNING|ERROR]\n```\n\n## Machines\n```bash\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE|ERROR|...]\nvmware-vdi machine reset --id M [--dry-run]                      # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit [--dry-run] # double-confirm\nvmware-vdi machine remove --id M [--dry-run]                     # deletes VM (instant clone); double-confirm\n```\n\n## Pools, images, tasks\n```bash\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable [--dry-run]  # disable stops NEW sessions\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]     # recreates EVERY desktop; double-confirm\nvmware-vdi images                                                  # instant-clone base VMs + snapshots\nvmware-vdi task status --pool P [--task T]                        # track an image push / provisioning\nvmware-vdi task cancel --pool P --task T [--dry-run]              # double-confirm\n```\n\n## Farms, apps, entitlements\n```bash\nvmware-vdi farm list\nvmware-vdi app-pool list\nvmware-vdi ad-search \"<name>\"                                     # resolve AD user/group → SID\nvmware-vdi entitlement list --pool P\nvmware-vdi entitlement add --pool P --sid <SID> [--sid <SID> ...] [--dry-run]\nvmware-vdi entitlement remove --pool P --sid <SID> [--dry-run]   # double-confirm\n```\n\nFile v1.2.0:references/setup-guide.md\n\n# vmware-vdi — Setup Guide\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.**\n\n## 1. Install\n```bash\nuv tool install vmware-vdi==1.2.0\n```\n\n## 2. Connect (friendly wizard)\n```bash\nvmware-vdi init\n```\nPrompts for the **Connection Server host**, admin **username**, AD **domain** (blank for a local admin),\n**password**, target name, and TLS verification. It writes `~/.vmware-vdi/config.yaml` +\n`~/.vmware-vdi/.env` (chmod 600), tests `/rest/login`, and on success **discovers your pools/machines/\nsessions** and prints the next commands to try. Re-run with `--force` to add another Connection Server\n(existing targets are preserved; the default is repointed to the new one).\n\nManual config (`~/.vmware-vdi/config.yaml`):\n```yaml\ndefault_target: prod\ntargets:\n  prod:\n    host: horizon-cs1.example.com\n    username: svc-vdi-ro          # a read-only Horizon role for read commands\n    domain: ACME                  # AD domain; blank for a local Connection Server admin\n    port: 443\n    verify_ssl: true              # false only for a self-signed lab cert\n```\nPassword (never in config.yaml): `~/.vmware-vdi/.env`\n```\nVMWARE_VDI_PROD_PASSWORD=b64:...    # written by `init`; or export it yourself (plaintext auto-obfuscated)\n```\n\n## 3. Verify\n```bash\nvmware-vdi doctor        # config / credentials / connectivity\n```\n\n## 4. Supported versions\n- **Primary: VMware Horizon 8.x** (Connection Server REST API `/rest/v1`).\n- **Latest Omnissa Horizon** (2406/2412+) — same `/rest/v1` lineage.\n- Requires the Connection Server REST API enabled (Horizon 8.0+; audit-events since 2106).\n\n## 5. MCP server\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vdi\": {\n      \"command\": \"vmware-vdi\",\n      \"args\": [\"mcp\"],\n      \"env\": { \"VMWARE_VDI_CONFIG\": \"~/.vmware-vdi/config.yaml\" }\n    }\n  }\n}\n```\nUsing the installed `vmware-vdi mcp` console script (not `uvx`) avoids a PyPI re-resolve on every launch —\nimportant behind enterprise TLS proxies.\n\n## Security\n> **Disclaimer**: not affiliated with VMware/Broadcom/Omnissa.\n\n- **Credentials**: password only in `~/.vmware-vdi/.env` (chmod 600, obfuscated `b64:` at rest —\n  obfuscation, not encryption). For real secrecy, inject `VMWARE_VDI_<TARGET>_PASSWORD` from a secret\n  manager (Vault / CyberArk / AWS SM / K8s Secret).\n- **Authorization = RBAC**: the skill does not gate read vs write itself. Point a target at a **read-only\n  Horizon admin role** and every write is refused at the Connection Server, un-bypassably.\n- **TLS**: verification on by default; `verify_ssl: false` is per-target, for self-signed labs only.\n- **Prompt-injection**: Connection-Server text is `sanitize()`d (truncated + control chars stripped).\n- **Audit**: all writes recorded in `~/.vmware/audit.db` (SQLite WAL) via the shared `@vmware_tool` guard.\n- **No outbound calls** other than to the configured Connection Server; no webhooks, no telemetry.\n\nFile v1.2.0:skill-card.md\n\n## Description:\n\nOperates VMware/Omnissa Horizon VDI environments through the Connection Server, including desktop pools, RDS farms, published apps, sessions, desktop machines, entitlements, events, health, statistics, and instant-clone image pushes.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nIT administrators, help-desk staff, and developers use this skill to inspect Horizon health and sessions, run diagnostics, and perform controlled VDI administration actions such as logoff, reset, entitlement updates, pool enablement, task cancellation, and instant-clone image pushes.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Write-capable operations can log off sessions, reset or remove desktops, modify entitlements, cancel tasks, or push images across a pool.\n\nMitigation: Use a read-only Horizon account for monitoring, separate write-capable credentials for administration, and review blast-radius previews before approving write actions.\n\nRisk: The skill stores Horizon connection credentials locally for configured targets.\n\nMitigation: Protect ~/.vmware-vdi/.env, keep configuration permissions restrictive, and prefer secret-manager injection for production credentials.\n\nRisk: Pool image pushes can affect many desktops and active users.\n\nMitigation: Review affected desktop and in-session user counts before approval, communicate planned maintenance, and avoid proceeding when occupancy or attribution is unknown.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/vmware-vdi)\n- [Capabilities](references/capabilities.md)\n- [CLI Reference](references/cli-reference.md)\n- [Setup Guide](references/setup-guide.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown with inline shell commands and configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include MCP tool calls and blast-radius previews for write operations.]\n\n## Skill Version(s):\n\n1.2.0 (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 v1.1.1: 6 files, 11125 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2984b), skill-card.md (2528b), SKILL.md (11983b), _meta.json (129b)\n\nFile v1.1.1:SKILL.md\n\n---\nname: vmware-vdi\ndescription: >\n  Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its\n  Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on\n  user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance,\n  remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone\n  golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop\n  pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to\n  the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool /\n  RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops),\n  read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security).\n  This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\ninstaller:\n  kind: uv\n  package: vmware-vdi\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vdi\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VDI_CONFIG\"]}}}\n---\n\n# VMware VDI (Horizon)\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.** \"VMware\", \"Horizon\", and \"Omnissa\" are\n> trademarks of their respective owners. Source is publicly auditable under the MIT license.\n\nHorizon VDI intelligent operations for the VMware skill family — desktop pools, RDS farms, **user\nsessions**, desktop machines, entitlements, events/health/statistics, and instant-clone image push,\nthrough the **Horizon 8 Connection Server REST API** (primary; also targets the latest Omnissa Horizon,\nwhich shares the same `/rest/v1` API lineage).\n\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (the vCenter VMs backing\n> the desktops), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only vSphere),\n> [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (desktop microsegmentation).\n\n> **Status: v1.0.0 (beta).** Endpoints are verified against the official Horizon Server API; GET-response\n> field projections are defensive and pending validation against a live Connection Server (run\n> `vmware-vdi init` on a real Horizon once to confirm). Governed by the family harness (audit + policy +\n> teaching errors); authorization is delegated to the Horizon admin account's role.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read/Write |\n|----------|-------|:-----:|:----------:|\n| **Monitoring** | health summary, session list/get, machine list/get, event list | 6 | 6 R |\n| **Statistics** | session concurrency stats, per-pool utilization | 2 | 2 R |\n| **Management** | pool list/get, farm list, app-pool list, entitlement list, image list, AD search; pool enable/disable, entitlement add/remove | 9 | 7 R / 2 W |\n| **Ops actions** | session logoff/disconnect/message, machine reset/maintenance/remove | 6 | 6 W |\n| **Tasks** | task status; image push, task cancel | 3 | 1 R / 2 W |\n\n**27 MCP tools (16 read / 11 write).** Reads are strictly non-destructive. Writes preview their blast\nradius, are double-confirmed at the CLI, and are audit-logged.\n\n## Quick Install\n\n```bash\nuv tool install vmware-vdi==1.1.1\nvmware-vdi init      # friendly setup: connect to a Connection Server + discover your pools\nvmware-vdi doctor    # verify config / credentials / connectivity\n```\n\n## When to Use This Skill\n\nUse vmware-vdi for the **Horizon broker layer**: desktop pools, RDS farms, published apps, **user\nsessions** (logoff/disconnect/message), desktop machine state (reset/maintenance/remove), entitlements,\nHorizon events/health/statistics, and **instant-clone image push** — when the context is explicitly\nHorizon / Omnissa / VDI / desktop-pool / RDS-farm.\n\n**Do NOT use when**: the task is the underlying vCenter VM (power/snapshot/clone/migrate → **vmware-aiops**),\nread-only vSphere inventory/alarms (→ **vmware-monitor**), or NSX microsegmentation of the desktops\n(→ **vmware-nsx-security**). A Horizon desktop's *backing VM* is aiops; the *session/pool/broker* is vdi.\n\n## Related Skills — Skill Routing\n\n| The user wants… | Skill |\n|-----------------|-------|\n| Log off / reset / re-image a Horizon desktop or session | **vmware-vdi** (this) |\n| Power/snapshot/clone/migrate the backing vCenter VM | vmware-aiops |\n| Read-only vSphere inventory / alarms / host health | vmware-monitor |\n| Microsegment the desktop pool network | vmware-nsx-security |\n| Multi-step VDI workflow with approval + rollback | vmware-pilot |\n\n## Common Workflows\n\n**1. Help-desk: a user's desktop is stuck.**\n```\nvmware-vdi session list --user alice          # find their session + state\nvmware-vdi machine list --state AGENT_UNREACHABLE   # is the desktop broken?\nvmware-vdi session logoff --user alice --dry-run    # preview blast radius (which sessions)\nvmware-vdi session logoff --user alice        # double-confirm, then logs off + audits\n```\n*Failure branch*: if `session list` returns a teaching 404/auth error, run `vmware-vdi doctor` — a\nread-only Horizon role is enough for the reads but the account must be able to reach the Connection Server.\n\n**2. Patch night: push a new golden image to a pool.**\n```\nvmware-vdi image list                         # find the base VM + snapshot\nvmware-vdi pool push-image --id pool-fin --dry-run   # BLAST RADIUS: N desktops, M logged-in users\nvmware-vdi pool set-enabled --id pool-fin --disable  # optional: stop new logins first\nvmware-vdi pool push-image --id pool-fin      # double-confirm; returns a task\nvmware-vdi task status --pool pool-fin         # track progress\n```\n*Failure branch*: if the preview shows logged-in users you did not expect, `session send-message --user …`\nto warn them, or push with `--force-logoff` only after confirming impact.\n\n**3. Onboard a group to a pool.**\n```\nvmware-vdi ad-search \"Finance\"                # resolve the AD group → its SID\nvmware-vdi entitlement add --pool pool-fin --sid <SID>\nvmware-vdi entitlement list --pool pool-fin   # verify\n```\n*Failure branch*: `ad-search` returning nothing usually means the domain in `~/.vmware-vdi/config.yaml`\nis wrong — re-run `vmware-vdi init --force`.\n\n## Usage Mode\n\n- **CLI** — interactive help-desk work, scripting, small/local models (lower context cost).\n- **MCP** — agent-driven operations with structured output; run `vmware-vdi mcp` (an installed console\n  script, so no `uvx` network re-resolve — works through enterprise TLS proxies).\n\n## MCP Tools (27 — 16 read, 11 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Monitoring | `health_summary`, `session_list`, `session_get`, `machine_list`, `machine_get`, `event_list` | Read |\n| Statistics | `session_stats`, `pool_utilization` | Read |\n| Management (read) | `pool_list`, `pool_get`, `farm_list`, `app_pool_list`, `entitlement_list`, `image_list`, `ad_user_search` | Read |\n| Tasks (read) | `task_status` | Read |\n| Ops actions | `session_logoff`, `session_disconnect`, `session_send_message`, `machine_reset`, `machine_maintenance`, `machine_remove` | Write |\n| Management (write) | `pool_set_enabled`, `entitlement_add`, `entitlement_remove` | Write |\n| Tasks (write) | `pool_push_image`, `task_cancel` | Write |\n\n**List envelope**: every `*_list` tool returns `{items, returned, limit, total, truncated, hint}` — read\nrows from `items` and check `truncated` before concluding a listing is complete; empty `items` with\n`truncated:false` means checked-and-none, not a failure. Lists are fetched with server-side pagination.\n\n**Blast radius (normative)**: `pool_push_image` recreates **every desktop in the pool** — the highest\nsingle-call blast radius in the family. Its preview states affected-desktop and in-session counts\nbefore any confirm, plus `blast_radius.occupancy`: `determined` when those counts can be believed,\n`unknown` when session rows exist that belong to neither a desktop pool nor a farm and so cannot be\nruled out of this pool. An `unknown` occupancy makes `in_session_count` a lower bound and refuses\n`confirm=true` — check `session_list`, or pass `acknowledge_unknown_occupancy=true`, which is audited.\n`session_logoff` / `machine_reset` / `machine_remove` state their affected users/\nmachines and require double confirmation at the CLI.\n\n**Read/write split**: 16 read-only tools (`[READ]` docstring marker), 11 modify state. All writes are\naudit-logged; destructive ones (`session_logoff`, `machine_reset`, `machine_remove`, `pool_set_enabled`\ndisable, `entitlement_remove`, `pool_push_image`, `task_cancel`) require CLI double-confirmation and\nsupport `--dry-run`.\n\n## CLI Quick Reference\n\n```bash\nvmware-vdi init                                          # friendly setup + pool discovery\nvmware-vdi health                                        # one-glance VDI health\nvmware-vdi stats                                         # session concurrency statistics\nvmware-vdi utilization                                   # per-pool desktop utilization\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED]\nvmware-vdi session logoff --user U [--dry-run]           # double-confirm\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE]\nvmware-vdi machine reset --id M [--dry-run]              # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]   # highest blast radius\nvmware-vdi task status --pool P [--task T]\nvmware-vdi ad-search \"<name>\"                            # resolve AD SID for entitlement\nvmware-vdi entitlement add|remove --pool P --sid <SID>\n```\nFull list: `references/cli-reference.md`.\n\n## Troubleshooting\n\n- **`Password not found. Set environment variable: VMWARE_VDI_<TARGET>_PASSWORD`** — run `vmware-vdi init`\n  (writes `~/.vmware-vdi/.env`, 0600), or export the var manually.\n- **Login fails (HTTP 401/400)** — check `username`/`domain` in `~/.vmware-vdi/config.yaml`; Horizon\n  authenticates against the AD `domain`. A local Connection Server admin leaves `domain` blank.\n- **`certificate could not be verified`** — for a self-signed lab cert set `verify_ssl: false` for that\n  target in the config.\n- **A write is refused with \"read-only role\"** — that is RBAC working as designed. Point the target at a\n  Horizon admin role with write privilege, or keep the read-only account for read commands only.\n- **`session list --pool` or a push-image preview shows 0 where you expect users** — on your Horizon\n  version a field name may differ; this is a beta known-limitation, please file an issue with the raw\n  `session_get` output so the projection can be pinned.\n\n## Audit & Safety\n\n1. **Source Code** — https://github.com/vmware-skills/VMware-VDI (MIT).\n2. **Config File Contents** — `config.yaml` holds host/username/domain only; passwords live in\n   `~/.vmware-vdi/.env` (0600, obfuscated to `b64:` at rest — obfuscation, not encryption).\n3. **Webhook Data Scope** — none. This skill makes no outbound calls except to the configured\n   Connection Server.\n4. **TLS Verification** — on by default; `verify_ssl: false` is per-target and only for self-signed labs.\n5. **Prompt Injection Protection** — all Connection-Server-supplied text (user names, machine/pool names,\n   event messages) passes through `vmware_policy.sanitize()` (truncation + control-char stripping).\n6. **Least Privilege** — authorization is the Horizon account's job: a read-only Horizon admin role\n   refuses every write at the Connection Server, un-bypassably. All writes are recorded in\n   `~/.vmware/audit.db`. See `references/setup-guide.md`.\n\n## License\n\nMIT\n\nFile v1.1.1:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vdi\",\n  \"version\": \"1.1.1\",\n  \"publishedAt\": 1789452499846\n}\n\nFile v1.1.1:references/capabilities.md\n\n# vmware-vdi — Capabilities\n\n27 MCP tools (16 read / 11 write) over the Horizon 8 Connection Server REST API. Every tool accepts an\noptional `target`. Typical response tokens are estimates for a small estate; lists paginate at 50.\n\n## Monitoring (6 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `health_summary` | R | session totals by state, problem-machine count, pool enabled/disabled | 80–200 |\n| `session_list` | R | id, user, type, state, protocol, pool_id, machine_id, start_time (filter user/pool/state) | 60–500 |\n| `session_get` | R | one session's projection | 40–100 |\n| `machine_list` | R | id, name, pool_id, state, user, agent_version, base_image (filter pool/state) | 60–500 |\n| `machine_get` | R | one machine's projection | 40–100 |\n| `event_list` | R | time, severity, type, module, user, machine, message (filter severity) | 100–600 |\n\n## Statistics (2 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `session_stats` | R | current concurrent, by-state, by-protocol, top pools | 80–200 |\n| `pool_utilization` | R | per-pool total/available/in-use/error + utilization % | 80–300 |\n\n## Management (7 read / 2 write)\n| Tool | R/W | Notes | ~tokens |\n|------|:---:|-------|:------:|\n| `pool_list` / `pool_get` | R | pools: type, enabled, assignment | 60–300 |\n| `farm_list` | R | RDS farms: type, enabled, server count | 40–200 |\n| `app_pool_list` | R | published apps: farm, enabled, executable | 40–300 |\n| `entitlement_list` | R | AD principals entitled to a pool | 40–300 |\n| `image_list` | R | instant-clone base VMs + snapshots | 60–400 |\n| `ad_user_search` | R | resolve AD name → SID (for `entitlement_add`) | 40–200 |\n| `pool_set_enabled` | W | enable/disable pool (idempotent, preview) | 40–120 |\n| `entitlement_add` / `entitlement_remove` | W | grant/revoke pool access by SID (preview) | 40–120 |\n\n## Ops actions (6 write) — help-desk\n| Tool | R/W | Risk | Blast radius |\n|------|:---:|:----:|--------------|\n| `session_send_message` | W | low | informational, no disruption |\n| `session_disconnect` | W | medium | one session, state preserved |\n| `session_logoff` | W | high | kicks the user (profile write-back) |\n| `machine_maintenance` | W | medium | drains a machine (no new sessions) |\n| `machine_reset` | W | high | hard reset — user loses unsaved state |\n| `machine_remove` | W | high | removes from pool; deletes VM for instant clones |\n\n## Tasks (1 read / 2 write)\n| Tool | R/W | Notes |\n|------|:---:|-------|\n| `task_status` | R | pool-scoped task status/progress (or all tasks for the pool) |\n| `pool_push_image` | W | **critical** — apply pending image; recreates EVERY desktop; preview states affected desktops + in-session users |\n| `task_cancel` | W | cancel a running pool task (applied work is not rolled back) |\n\n**Beta note (踩坑 #36)**: REST endpoints are verified against the official Horizon Server API operation\nindex. GET-response *field names* are defensive (`.get()` with fallbacks) and pending validation against a\nlive Connection Server — a mismatch yields empty results, not a crash. First real-Horizon use should\nconfirm the `session`/`machine`/`pool` projections and the `apply-image` / entitlement bodies.\n\nFile v1.1.1:references/cli-reference.md\n\n# vmware-vdi — CLI Reference\n\nAll commands accept `--target/-t <name>` (config target) and `--config/-c <path>` (alternate config file).\nDestructive commands accept `--dry-run` (preview only) and interactively double-confirm.\n\n## Setup & diagnostics\n```bash\nvmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point\n```\n\n## Monitoring & statistics (read-only)\n```bash\nvmware-vdi health                           # session totals, problem machines, pool availability\nvmware-vdi stats                            # concurrency by state/protocol, busiest pools\nvmware-vdi utilization                      # per-pool total/available/in-use/error + utilization %\nvmware-vdi events [--severity ERROR]        # recent Horizon audit events (newest first)\n```\n\n## Sessions\n```bash\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED|DISCONNECTED|PENDING]\nvmware-vdi session logoff [--id S] [--user U] [--dry-run]        # kicks the user; double-confirm\nvmware-vdi session disconnect [--id S] [--user U] [--dry-run]    # state preserved; double-confirm\nvmware-vdi session message \"<text>\" [--user U] [--id S] [--type INFO|WARNING|ERROR]\n```\n\n## Machines\n```bash\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE|ERROR|...]\nvmware-vdi machine reset --id M [--dry-run]                      # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit [--dry-run] # double-confirm\nvmware-vdi machine remove --id M [--dry-run]                     # deletes VM (instant clone); double-confirm\n```\n\n## Pools, images, tasks\n```bash\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable [--dry-run]  # disable stops NEW sessions\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]     # recreates EVERY desktop; double-confirm\nvmware-vdi images                                                  # instant-clone base VMs + snapshots\nvmware-vdi task status --pool P [--task T]                        # track an image push / provisioning\nvmware-vdi task cancel --pool P --task T [--dry-run]              # double-confirm\n```\n\n## Farms, apps, entitlements\n```bash\nvmware-vdi farm list\nvmware-vdi app-pool list\nvmware-vdi ad-search \"<name>\"                                     # resolve AD user/group → SID\nvmware-vdi entitlement list --pool P\nvmware-vdi entitlement add --pool P --sid <SID> [--sid <SID> ...] [--dry-run]\nvmware-vdi entitlement remove --pool P --sid <SID> [--dry-run]   # double-confirm\n```\n\nFile v1.1.1:references/setup-guide.md\n\n# vmware-vdi — Setup Guide\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.**\n\n## 1. Install\n```bash\nuv tool install vmware-vdi==1.1.1\n```\n\n## 2. Connect (friendly wizard)\n```bash\nvmware-vdi init\n```\nPrompts for the **Connection Server host**, admin **username**, AD **domain** (blank for a local admin),\n**password**, target name, and TLS verification. It writes `~/.vmware-vdi/config.yaml` +\n`~/.vmware-vdi/.env` (chmod 600), tests `/rest/login`, and on success **discovers your pools/machines/\nsessions** and prints the next commands to try. Re-run with `--force` to add another Connection Server\n(existing targets are preserved; the default is repointed to the new one).\n\nManual config (`~/.vmware-vdi/config.yaml`):\n```yaml\ndefault_target: prod\ntargets:\n  prod:\n    host: horizon-cs1.example.com\n    username: svc-vdi-ro          # a read-only Horizon role for read commands\n    domain: ACME                  # AD domain; blank for a local Connection Server admin\n    port: 443\n    verify_ssl: true              # false only for a self-signed lab cert\n```\nPassword (never in config.yaml): `~/.vmware-vdi/.env`\n```\nVMWARE_VDI_PROD_PASSWORD=b64:...    # written by `init`; or export it yourself (plaintext auto-obfuscated)\n```\n\n## 3. Verify\n```bash\nvmware-vdi doctor        # config / credentials / connectivity\n```\n\n## 4. Supported versions\n- **Primary: VMware Horizon 8.x** (Connection Server REST API `/rest/v1`).\n- **Latest Omnissa Horizon** (2406/2412+) — same `/rest/v1` lineage.\n- Requires the Connection Server REST API enabled (Horizon 8.0+; audit-events since 2106).\n\n## 5. MCP server\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vdi\": {\n      \"command\": \"vmware-vdi\",\n      \"args\": [\"mcp\"],\n      \"env\": { \"VMWARE_VDI_CONFIG\": \"~/.vmware-vdi/config.yaml\" }\n    }\n  }\n}\n```\nUsing the installed `vmware-vdi mcp` console script (not `uvx`) avoids a PyPI re-resolve on every launch —\nimportant behind enterprise TLS proxies.\n\n## Security\n> **Disclaimer**: not affiliated with VMware/Broadcom/Omnissa.\n\n- **Credentials**: password only in `~/.vmware-vdi/.env` (chmod 600, obfuscated `b64:` at rest —\n  obfuscation, not encryption). For real secrecy, inject `VMWARE_VDI_<TARGET>_PASSWORD` from a secret\n  manager (Vault / CyberArk / AWS SM / K8s Secret).\n- **Authorization = RBAC**: the skill does not gate read vs write itself. Point a target at a **read-only\n  Horizon admin role** and every write is refused at the Connection Server, un-bypassably.\n- **TLS**: verification on by default; `verify_ssl: false` is per-target, for self-signed labs only.\n- **Prompt-injection**: Connection-Server text is `sanitize()`d (truncated + control chars stripped).\n- **Audit**: all writes recorded in `~/.vmware/audit.db` (SQLite WAL) via the shared `@vmware_tool` guard.\n- **No outbound calls** other than to the configured Connection Server; no webhooks, no telemetry.\n\nFile v1.1.1:skill-card.md\n\n## Description:\n\nOperates VMware/Omnissa Horizon VDI through a Connection Server for desktop pools, RDS farms, published apps, sessions, machines, entitlements, health, events, statistics, and instant-clone image updates.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nIT help-desk and VDI operations teams use this skill to inspect Horizon environments and perform broker-layer actions such as session logoff, desktop reset, entitlement changes, and image pushes through CLI or MCP workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Write actions can disrupt users or infrastructure by logging off sessions, resetting or removing machines, canceling tasks, or pushing images across an entire desktop pool.\n\nMitigation: Use a read-only Horizon admin role by default, enable write-capable credentials only for intended maintenance, and review dry-run output before approving disruptive commands.\n\nRisk: The generated password file stores an obfuscated b64 value, which is not encryption.\n\nMitigation: Prefer secret-manager environment injection for production credentials and restrict local credential files to the documented 0600 permissions.\n\nRisk: Server-resolved provenance is unavailable for this release.\n\nMitigation: Verify the vmware-vdi package source and release provenance before production deployment.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/vmware-vdi)\n- [Capabilities reference](artifact/references/capabilities.md)\n- [CLI reference](artifact/references/cli-reference.md)\n- [Setup guide](artifact/references/setup-guide.md)\n- [Source repository cited by artifact](https://github.com/vmware-skills/VMware-VDI)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown with inline shell commands and configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include structured MCP guidance, dry-run review steps, and operational cautions for write actions.]\n\n## Skill Version(s):\n\n1.1.1 (source: server release metadata and artifact install command)\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 v1.1.0: 6 files, 11112 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2984b), skill-card.md (2664b), SKILL.md (11983b), _meta.json (129b)\n\nFile v1.1.0:SKILL.md\n\n---\nname: vmware-vdi\ndescription: >\n  Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its\n  Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on\n  user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance,\n  remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone\n  golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop\n  pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to\n  the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool /\n  RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops),\n  read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security).\n  This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\ninstaller:\n  kind: uv\n  package: vmware-vdi\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vdi\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VDI_CONFIG\"]}}}\n---\n\n# VMware VDI (Horizon)\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.** \"VMware\", \"Horizon\", and \"Omnissa\" are\n> trademarks of their respective owners. Source is publicly auditable under the MIT license.\n\nHorizon VDI intelligent operations for the VMware skill family — desktop pools, RDS farms, **user\nsessions**, desktop machines, entitlements, events/health/statistics, and instant-clone image push,\nthrough the **Horizon 8 Connection Server REST API** (primary; also targets the latest Omnissa Horizon,\nwhich shares the same `/rest/v1` API lineage).\n\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (the vCenter VMs backing\n> the desktops), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only vSphere),\n> [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (desktop microsegmentation).\n\n> **Status: v1.0.0 (beta).** Endpoints are verified against the official Horizon Server API; GET-response\n> field projections are defensive and pending validation against a live Connection Server (run\n> `vmware-vdi init` on a real Horizon once to confirm). Governed by the family harness (audit + policy +\n> teaching errors); authorization is delegated to the Horizon admin account's role.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read/Write |\n|----------|-------|:-----:|:----------:|\n| **Monitoring** | health summary, session list/get, machine list/get, event list | 6 | 6 R |\n| **Statistics** | session concurrency stats, per-pool utilization | 2 | 2 R |\n| **Management** | pool list/get, farm list, app-pool list, entitlement list, image list, AD search; pool enable/disable, entitlement add/remove | 9 | 7 R / 2 W |\n| **Ops actions** | session logoff/disconnect/message, machine reset/maintenance/remove | 6 | 6 W |\n| **Tasks** | task status; image push, task cancel | 3 | 1 R / 2 W |\n\n**27 MCP tools (16 read / 11 write).** Reads are strictly non-destructive. Writes preview their blast\nradius, are double-confirmed at the CLI, and are audit-logged.\n\n## Quick Install\n\n```bash\nuv tool install vmware-vdi==1.1.0\nvmware-vdi init      # friendly setup: connect to a Connection Server + discover your pools\nvmware-vdi doctor    # verify config / credentials / connectivity\n```\n\n## When to Use This Skill\n\nUse vmware-vdi for the **Horizon broker layer**: desktop pools, RDS farms, published apps, **user\nsessions** (logoff/disconnect/message), desktop machine state (reset/maintenance/remove), entitlements,\nHorizon events/health/statistics, and **instant-clone image push** — when the context is explicitly\nHorizon / Omnissa / VDI / desktop-pool / RDS-farm.\n\n**Do NOT use when**: the task is the underlying vCenter VM (power/snapshot/clone/migrate → **vmware-aiops**),\nread-only vSphere inventory/alarms (→ **vmware-monitor**), or NSX microsegmentation of the desktops\n(→ **vmware-nsx-security**). A Horizon desktop's *backing VM* is aiops; the *session/pool/broker* is vdi.\n\n## Related Skills — Skill Routing\n\n| The user wants… | Skill |\n|-----------------|-------|\n| Log off / reset / re-image a Horizon desktop or session | **vmware-vdi** (this) |\n| Power/snapshot/clone/migrate the backing vCenter VM | vmware-aiops |\n| Read-only vSphere inventory / alarms / host health | vmware-monitor |\n| Microsegment the desktop pool network | vmware-nsx-security |\n| Multi-step VDI workflow with approval + rollback | vmware-pilot |\n\n## Common Workflows\n\n**1. Help-desk: a user's desktop is stuck.**\n```\nvmware-vdi session list --user alice          # find their session + state\nvmware-vdi machine list --state AGENT_UNREACHABLE   # is the desktop broken?\nvmware-vdi session logoff --user alice --dry-run    # preview blast radius (which sessions)\nvmware-vdi session logoff --user alice        # double-confirm, then logs off + audits\n```\n*Failure branch*: if `session list` returns a teaching 404/auth error, run `vmware-vdi doctor` — a\nread-only Horizon role is enough for the reads but the account must be able to reach the Connection Server.\n\n**2. Patch night: push a new golden image to a pool.**\n```\nvmware-vdi image list                         # find the base VM + snapshot\nvmware-vdi pool push-image --id pool-fin --dry-run   # BLAST RADIUS: N desktops, M logged-in users\nvmware-vdi pool set-enabled --id pool-fin --disable  # optional: stop new logins first\nvmware-vdi pool push-image --id pool-fin      # double-confirm; returns a task\nvmware-vdi task status --pool pool-fin         # track progress\n```\n*Failure branch*: if the preview shows logged-in users you did not expect, `session send-message --user …`\nto warn them, or push with `--force-logoff` only after confirming impact.\n\n**3. Onboard a group to a pool.**\n```\nvmware-vdi ad-search \"Finance\"                # resolve the AD group → its SID\nvmware-vdi entitlement add --pool pool-fin --sid <SID>\nvmware-vdi entitlement list --pool pool-fin   # verify\n```\n*Failure branch*: `ad-search` returning nothing usually means the domain in `~/.vmware-vdi/config.yaml`\nis wrong — re-run `vmware-vdi init --force`.\n\n## Usage Mode\n\n- **CLI** — interactive help-desk work, scripting, small/local models (lower context cost).\n- **MCP** — agent-driven operations with structured output; run `vmware-vdi mcp` (an installed console\n  script, so no `uvx` network re-resolve — works through enterprise TLS proxies).\n\n## MCP Tools (27 — 16 read, 11 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Monitoring | `health_summary`, `session_list`, `session_get`, `machine_list`, `machine_get`, `event_list` | Read |\n| Statistics | `session_stats`, `pool_utilization` | Read |\n| Management (read) | `pool_list`, `pool_get`, `farm_list`, `app_pool_list`, `entitlement_list`, `image_list`, `ad_user_search` | Read |\n| Tasks (read) | `task_status` | Read |\n| Ops actions | `session_logoff`, `session_disconnect`, `session_send_message`, `machine_reset`, `machine_maintenance`, `machine_remove` | Write |\n| Management (write) | `pool_set_enabled`, `entitlement_add`, `entitlement_remove` | Write |\n| Tasks (write) | `pool_push_image`, `task_cancel` | Write |\n\n**List envelope**: every `*_list` tool returns `{items, returned, limit, total, truncated, hint}` — read\nrows from `items` and check `truncated` before concluding a listing is complete; empty `items` with\n`truncated:false` means checked-and-none, not a failure. Lists are fetched with server-side pagination.\n\n**Blast radius (normative)**: `pool_push_image` recreates **every desktop in the pool** — the highest\nsingle-call blast radius in the family. Its preview states affected-desktop and in-session counts\nbefore any confirm, plus `blast_radius.occupancy`: `determined` when those counts can be believed,\n`unknown` when session rows exist that belong to neither a desktop pool nor a farm and so cannot be\nruled out of this pool. An `unknown` occupancy makes `in_session_count` a lower bound and refuses\n`confirm=true` — check `session_list`, or pass `acknowledge_unknown_occupancy=true`, which is audited.\n`session_logoff` / `machine_reset` / `machine_remove` state their affected users/\nmachines and require double confirmation at the CLI.\n\n**Read/write split**: 16 read-only tools (`[READ]` docstring marker), 11 modify state. All writes are\naudit-logged; destructive ones (`session_logoff`, `machine_reset`, `machine_remove`, `pool_set_enabled`\ndisable, `entitlement_remove`, `pool_push_image`, `task_cancel`) require CLI double-confirmation and\nsupport `--dry-run`.\n\n## CLI Quick Reference\n\n```bash\nvmware-vdi init                                          # friendly setup + pool discovery\nvmware-vdi health                                        # one-glance VDI health\nvmware-vdi stats                                         # session concurrency statistics\nvmware-vdi utilization                                   # per-pool desktop utilization\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED]\nvmware-vdi session logoff --user U [--dry-run]           # double-confirm\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE]\nvmware-vdi machine reset --id M [--dry-run]              # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]   # highest blast radius\nvmware-vdi task status --pool P [--task T]\nvmware-vdi ad-search \"<name>\"                            # resolve AD SID for entitlement\nvmware-vdi entitlement add|remove --pool P --sid <SID>\n```\nFull list: `references/cli-reference.md`.\n\n## Troubleshooting\n\n- **`Password not found. Set environment variable: VMWARE_VDI_<TARGET>_PASSWORD`** — run `vmware-vdi init`\n  (writes `~/.vmware-vdi/.env`, 0600), or export the var manually.\n- **Login fails (HTTP 401/400)** — check `username`/`domain` in `~/.vmware-vdi/config.yaml`; Horizon\n  authenticates against the AD `domain`. A local Connection Server admin leaves `domain` blank.\n- **`certificate could not be verified`** — for a self-signed lab cert set `verify_ssl: false` for that\n  target in the config.\n- **A write is refused with \"read-only role\"** — that is RBAC working as designed. Point the target at a\n  Horizon admin role with write privilege, or keep the read-only account for read commands only.\n- **`session list --pool` or a push-image preview shows 0 where you expect users** — on your Horizon\n  version a field name may differ; this is a beta known-limitation, please file an issue with the raw\n  `session_get` output so the projection can be pinned.\n\n## Audit & Safety\n\n1. **Source Code** — https://github.com/vmware-skills/VMware-VDI (MIT).\n2. **Config File Contents** — `config.yaml` holds host/username/domain only; passwords live in\n   `~/.vmware-vdi/.env` (0600, obfuscated to `b64:` at rest — obfuscation, not encryption).\n3. **Webhook Data Scope** — none. This skill makes no outbound calls except to the configured\n   Connection Server.\n4. **TLS Verification** — on by default; `verify_ssl: false` is per-target and only for self-signed labs.\n5. **Prompt Injection Protection** — all Connection-Server-supplied text (user names, machine/pool names,\n   event messages) passes through `vmware_policy.sanitize()` (truncation + control-char stripping).\n6. **Least Privilege** — authorization is the Horizon account's job: a read-only Horizon admin role\n   refuses every write at the Connection Server, un-bypassably. All writes are recorded in\n   `~/.vmware/audit.db`. See `references/setup-guide.md`.\n\n## License\n\nMIT\n\nFile v1.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vdi\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1789172407979\n}\n\nFile v1.1.0:references/capabilities.md\n\n# vmware-vdi — Capabilities\n\n27 MCP tools (16 read / 11 write) over the Horizon 8 Connection Server REST API. Every tool accepts an\noptional `target`. Typical response tokens are estimates for a small estate; lists paginate at 50.\n\n## Monitoring (6 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `health_summary` | R | session totals by state, problem-machine count, pool enabled/disabled | 80–200 |\n| `session_list` | R | id, user, type, state, protocol, pool_id, machine_id, start_time (filter user/pool/state) | 60–500 |\n| `session_get` | R | one session's projection | 40–100 |\n| `machine_list` | R | id, name, pool_id, state, user, agent_version, base_image (filter pool/state) | 60–500 |\n| `machine_get` | R | one machine's projection | 40–100 |\n| `event_list` | R | time, severity, type, module, user, machine, message (filter severity) | 100–600 |\n\n## Statistics (2 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `session_stats` | R | current concurrent, by-state, by-protocol, top pools | 80–200 |\n| `pool_utilization` | R | per-pool total/available/in-use/error + utilization % | 80–300 |\n\n## Management (7 read / 2 write)\n| Tool | R/W | Notes | ~tokens |\n|------|:---:|-------|:------:|\n| `pool_list` / `pool_get` | R | pools: type, enabled, assignment | 60–300 |\n| `farm_list` | R | RDS farms: type, enabled, server count | 40–200 |\n| `app_pool_list` | R | published apps: farm, enabled, executable | 40–300 |\n| `entitlement_list` | R | AD principals entitled to a pool | 40–300 |\n| `image_list` | R | instant-clone base VMs + snapshots | 60–400 |\n| `ad_user_search` | R | resolve AD name → SID (for `entitlement_add`) | 40–200 |\n| `pool_set_enabled` | W | enable/disable pool (idempotent, preview) | 40–120 |\n| `entitlement_add` / `entitlement_remove` | W | grant/revoke pool access by SID (preview) | 40–120 |\n\n## Ops actions (6 write) — help-desk\n| Tool | R/W | Risk | Blast radius |\n|------|:---:|:----:|--------------|\n| `session_send_message` | W | low | informational, no disruption |\n| `session_disconnect` | W | medium | one session, state preserved |\n| `session_logoff` | W | high | kicks the user (profile write-back) |\n| `machine_maintenance` | W | medium | drains a machine (no new sessions) |\n| `machine_reset` | W | high | hard reset — user loses unsaved state |\n| `machine_remove` | W | high | removes from pool; deletes VM for instant clones |\n\n## Tasks (1 read / 2 write)\n| Tool | R/W | Notes |\n|------|:---:|-------|\n| `task_status` | R | pool-scoped task status/progress (or all tasks for the pool) |\n| `pool_push_image` | W | **critical** — apply pending image; recreates EVERY desktop; preview states affected desktops + in-session users |\n| `task_cancel` | W | cancel a running pool task (applied work is not rolled back) |\n\n**Beta note (踩坑 #36)**: REST endpoints are verified against the official Horizon Server API operation\nindex. GET-response *field names* are defensive (`.get()` with fallbacks) and pending validation against a\nlive Connection Server — a mismatch yields empty results, not a crash. First real-Horizon use should\nconfirm the `session`/`machine`/`pool` projections and the `apply-image` / entitlement bodies.\n\nFile v1.1.0:references/cli-reference.md\n\n# vmware-vdi — CLI Reference\n\nAll commands accept `--target/-t <name>` (config target) and `--config/-c <path>` (alternate config file).\nDestructive commands accept `--dry-run` (preview only) and interactively double-confirm.\n\n## Setup & diagnostics\n```bash\nvmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point\n```\n\n## Monitoring & statistics (read-only)\n```bash\nvmware-vdi health                           # session totals, problem machines, pool availability\nvmware-vdi stats                            # concurrency by state/protocol, busiest pools\nvmware-vdi utilization                      # per-pool total/available/in-use/error + utilization %\nvmware-vdi events [--severity ERROR]        # recent Horizon audit events (newest first)\n```\n\n## Sessions\n```bash\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED|DISCONNECTED|PENDING]\nvmware-vdi session logoff [--id S] [--user U] [--dry-run]        # kicks the user; double-confirm\nvmware-vdi session disconnect [--id S] [--user U] [--dry-run]    # state preserved; double-confirm\nvmware-vdi session message \"<text>\" [--user U] [--id S] [--type INFO|WARNING|ERROR]\n```\n\n## Machines\n```bash\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE|ERROR|...]\nvmware-vdi machine reset --id M [--dry-run]                      # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit [--dry-run] # double-confirm\nvmware-vdi machine remove --id M [--dry-run]                     # deletes VM (instant clone); double-confirm\n```\n\n## Pools, images, tasks\n```bash\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable [--dry-run]  # disable stops NEW sessions\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]     # recreates EVERY desktop; double-confirm\nvmware-vdi images                                                  # instant-clone base VMs + snapshots\nvmware-vdi task status --pool P [--task T]                        # track an image push / provisioning\nvmware-vdi task cancel --pool P --task T [--dry-run]              # double-confirm\n```\n\n## Farms, apps, entitlements\n```bash\nvmware-vdi farm list\nvmware-vdi app-pool list\nvmware-vdi ad-search \"<name>\"                                     # resolve AD user/group → SID\nvmware-vdi entitlement list --pool P\nvmware-vdi entitlement add --pool P --sid <SID> [--sid <SID> ...] [--dry-run]\nvmware-vdi entitlement remove --pool P --sid <SID> [--dry-run]   # double-confirm\n```\n\nFile v1.1.0:references/setup-guide.md\n\n# vmware-vdi — Setup Guide\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.**\n\n## 1. Install\n```bash\nuv tool install vmware-vdi==1.1.0\n```\n\n## 2. Connect (friendly wizard)\n```bash\nvmware-vdi init\n```\nPrompts for the **Connection Server host**, admin **username**, AD **domain** (blank for a local admin),\n**password**, target name, and TLS verification. It writes `~/.vmware-vdi/config.yaml` +\n`~/.vmware-vdi/.env` (chmod 600), tests `/rest/login`, and on success **discovers your pools/machines/\nsessions** and prints the next commands to try. Re-run with `--force` to add another Connection Server\n(existing targets are preserved; the default is repointed to the new one).\n\nManual config (`~/.vmware-vdi/config.yaml`):\n```yaml\ndefault_target: prod\ntargets:\n  prod:\n    host: horizon-cs1.example.com\n    username: svc-vdi-ro          # a read-only Horizon role for read commands\n    domain: ACME                  # AD domain; blank for a local Connection Server admin\n    port: 443\n    verify_ssl: true              # false only for a self-signed lab cert\n```\nPassword (never in config.yaml): `~/.vmware-vdi/.env`\n```\nVMWARE_VDI_PROD_PASSWORD=b64:...    # written by `init`; or export it yourself (plaintext auto-obfuscated)\n```\n\n## 3. Verify\n```bash\nvmware-vdi doctor        # config / credentials / connectivity\n```\n\n## 4. Supported versions\n- **Primary: VMware Horizon 8.x** (Connection Server REST API `/rest/v1`).\n- **Latest Omnissa Horizon** (2406/2412+) — same `/rest/v1` lineage.\n- Requires the Connection Server REST API enabled (Horizon 8.0+; audit-events since 2106).\n\n## 5. MCP server\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vdi\": {\n      \"command\": \"vmware-vdi\",\n      \"args\": [\"mcp\"],\n      \"env\": { \"VMWARE_VDI_CONFIG\": \"~/.vmware-vdi/config.yaml\" }\n    }\n  }\n}\n```\nUsing the installed `vmware-vdi mcp` console script (not `uvx`) avoids a PyPI re-resolve on every launch —\nimportant behind enterprise TLS proxies.\n\n## Security\n> **Disclaimer**: not affiliated with VMware/Broadcom/Omnissa.\n\n- **Credentials**: password only in `~/.vmware-vdi/.env` (chmod 600, obfuscated `b64:` at rest —\n  obfuscation, not encryption). For real secrecy, inject `VMWARE_VDI_<TARGET>_PASSWORD` from a secret\n  manager (Vault / CyberArk / AWS SM / K8s Secret).\n- **Authorization = RBAC**: the skill does not gate read vs write itself. Point a target at a **read-only\n  Horizon admin role** and every write is refused at the Connection Server, un-bypassably.\n- **TLS**: verification on by default; `verify_ssl: false` is per-target, for self-signed labs only.\n- **Prompt-injection**: Connection-Server text is `sanitize()`d (truncated + control chars stripped).\n- **Audit**: all writes recorded in `~/.vmware/audit.db` (SQLite WAL) via the shared `@vmware_tool` guard.\n- **No outbound calls** other than to the configured Connection Server; no webhooks, no telemetry.\n\nFile v1.1.0:skill-card.md\n\n## Description:\n\nvmware-vdi helps agents operate VMware/Omnissa Horizon VDI through a Connection Server, including desktop pools, RDS farms, published apps, sessions, machines, entitlements, health, events, statistics, and instant-clone image pushes.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nIT operations, help-desk, and VDI platform engineers use this skill to inspect and administer Horizon broker-layer resources, troubleshoot user sessions and desktop pools, and perform controlled operational actions such as logoff, reset, entitlement changes, and image pushes.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can administer VMware Horizon environments and may use production admin credentials.\n\nMitigation: Use a dedicated least-privilege Horizon account and verify the package or source before using it with production credentials.\n\nRisk: Local credential handling can expose Horizon passwords if the generated environment file is treated as secret storage.\n\nMitigation: Prefer environment variables or a secret manager, and keep any local password file permission-restricted.\n\nRisk: Disabling TLS verification can weaken connection security.\n\nMitigation: Keep TLS verification enabled except in isolated self-signed lab environments.\n\n## Reference(s):\n\n- [vmware-vdi ClawHub skill page](https://clawhub.ai/zw008/skills/vmware-vdi)\n- [vmware-vdi declared source code](https://github.com/vmware-skills/VMware-VDI)\n- [Capabilities](references/capabilities.md)\n- [CLI Reference](references/cli-reference.md)\n- [Setup Guide](references/setup-guide.md)\n- [vmware-aiops companion skill](https://github.com/vmware-skills/VMware-AIops)\n- [vmware-monitor companion skill](https://github.com/vmware-skills/VMware-Monitor)\n- [vmware-nsx-security companion skill](https://github.com/vmware-skills/VMware-NSX-Security)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands and configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include structured MCP-oriented operational guidance for Horizon administration tasks.]\n\n## Skill Version(s):\n\n1.1.0 (source: ClawHub 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 v1.0.7: 6 files, 11130 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2977b), skill-card.md (2578b), SKILL.md (12026b), _meta.json (129b)\n\nFile v1.0.7:SKILL.md\n\n---\nname: vmware-vdi\ndescription: >\n  Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its\n  Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on\n  user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance,\n  remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone\n  golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop\n  pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to\n  the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool /\n  RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops),\n  read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security).\n  This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\ninstaller:\n  kind: uv\n  package: vmware-vdi\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"env\":[\"VMWARE_VDI_CONFIG\"],\"bins\":[\"vmware-vdi\"],\"config\":[\"~/.vmware-vdi/config.yaml\"]},\"primaryEnv\":\"VMWARE_VDI_CONFIG\"}}\n---\n\n# VMware VDI (Horizon)\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.** \"VMware\", \"Horizon\", and \"Omnissa\" are\n> trademarks of their respective owners. Source is publicly auditable under the MIT license.\n\nHorizon VDI intelligent operations for the VMware skill family — desktop pools, RDS farms, **user\nsessions**, desktop machines, entitlements, events/health/statistics, and instant-clone image push,\nthrough the **Horizon 8 Connection Server REST API** (primary; also targets the latest Omnissa Horizon,\nwhich shares the same `/rest/v1` API lineage).\n\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (the vCenter VMs backing\n> the desktops), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only vSphere),\n> [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (desktop microsegmentation).\n\n> **Status: v1.0.0 (beta).** Endpoints are verified against the official Horizon Server API; GET-response\n> field projections are defensive and pending validation against a live Connection Server (run\n> `vmware-vdi init` on a real Horizon once to confirm). Governed by the family harness (audit + policy +\n> teaching errors); authorization is delegated to the Horizon admin account's role.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read/Write |\n|----------|-------|:-----:|:----------:|\n| **Monitoring** | health summary, session list/get, machine list/get, event list | 6 | 6 R |\n| **Statistics** | session concurrency stats, per-pool utilization | 2 | 2 R |\n| **Management** | pool list/get, farm list, app-pool list, entitlement list, image list, AD search; pool enable/disable, entitlement add/remove | 9 | 7 R / 2 W |\n| **Ops actions** | session logoff/disconnect/message, machine reset/maintenance/remove | 6 | 6 W |\n| **Tasks** | task status; image push, task cancel | 3 | 1 R / 2 W |\n\n**27 MCP tools (16 read / 11 write).** Reads are strictly non-destructive. Writes preview their blast\nradius, are double-confirmed at the CLI, and are audit-logged.\n\n## Quick Install\n\n```bash\nuv tool install vmware-vdi\nvmware-vdi init      # friendly setup: connect to a Connection Server + discover your pools\nvmware-vdi doctor    # verify config / credentials / connectivity\n```\n\n## When to Use This Skill\n\nUse vmware-vdi for the **Horizon broker layer**: desktop pools, RDS farms, published apps, **user\nsessions** (logoff/disconnect/message), desktop machine state (reset/maintenance/remove), entitlements,\nHorizon events/health/statistics, and **instant-clone image push** — when the context is explicitly\nHorizon / Omnissa / VDI / desktop-pool / RDS-farm.\n\n**Do NOT use when**: the task is the underlying vCenter VM (power/snapshot/clone/migrate → **vmware-aiops**),\nread-only vSphere inventory/alarms (→ **vmware-monitor**), or NSX microsegmentation of the desktops\n(→ **vmware-nsx-security**). A Horizon desktop's *backing VM* is aiops; the *session/pool/broker* is vdi.\n\n## Related Skills — Skill Routing\n\n| The user wants… | Skill |\n|-----------------|-------|\n| Log off / reset / re-image a Horizon desktop or session | **vmware-vdi** (this) |\n| Power/snapshot/clone/migrate the backing vCenter VM | vmware-aiops |\n| Read-only vSphere inventory / alarms / host health | vmware-monitor |\n| Microsegment the desktop pool network | vmware-nsx-security |\n| Multi-step VDI workflow with approval + rollback | vmware-pilot |\n\n## Common Workflows\n\n**1. Help-desk: a user's desktop is stuck.**\n```\nvmware-vdi session list --user alice          # find their session + state\nvmware-vdi machine list --state AGENT_UNREACHABLE   # is the desktop broken?\nvmware-vdi session logoff --user alice --dry-run    # preview blast radius (which sessions)\nvmware-vdi session logoff --user alice        # double-confirm, then logs off + audits\n```\n*Failure branch*: if `session list` returns a teaching 404/auth error, run `vmware-vdi doctor` — a\nread-only Horizon role is enough for the reads but the account must be able to reach the Connection Server.\n\n**2. Patch night: push a new golden image to a pool.**\n```\nvmware-vdi image list                         # find the base VM + snapshot\nvmware-vdi pool push-image --id pool-fin --dry-run   # BLAST RADIUS: N desktops, M logged-in users\nvmware-vdi pool set-enabled --id pool-fin --disable  # optional: stop new logins first\nvmware-vdi pool push-image --id pool-fin      # double-confirm; returns a task\nvmware-vdi task status --pool pool-fin         # track progress\n```\n*Failure branch*: if the preview shows logged-in users you did not expect, `session send-message --user …`\nto warn them, or push with `--force-logoff` only after confirming impact.\n\n**3. Onboard a group to a pool.**\n```\nvmware-vdi ad-search \"Finance\"                # resolve the AD group → its SID\nvmware-vdi entitlement add --pool pool-fin --sid <SID>\nvmware-vdi entitlement list --pool pool-fin   # verify\n```\n*Failure branch*: `ad-search` returning nothing usually means the domain in `~/.vmware-vdi/config.yaml`\nis wrong — re-run `vmware-vdi init --force`.\n\n## Usage Mode\n\n- **CLI** — interactive help-desk work, scripting, small/local models (lower context cost).\n- **MCP** — agent-driven operations with structured output; run `vmware-vdi mcp` (an installed console\n  script, so no `uvx` network re-resolve — works through enterprise TLS proxies).\n\n## MCP Tools (27 — 16 read, 11 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Monitoring | `health_summary`, `session_list`, `session_get`, `machine_list`, `machine_get`, `event_list` | Read |\n| Statistics | `session_stats`, `pool_utilization` | Read |\n| Management (read) | `pool_list`, `pool_get`, `farm_list`, `app_pool_list`, `entitlement_list`, `image_list`, `ad_user_search` | Read |\n| Tasks (read) | `task_status` | Read |\n| Ops actions | `session_logoff`, `session_disconnect`, `session_send_message`, `machine_reset`, `machine_maintenance`, `machine_remove` | Write |\n| Management (write) | `pool_set_enabled`, `entitlement_add`, `entitlement_remove` | Write |\n| Tasks (write) | `pool_push_image`, `task_cancel` | Write |\n\n**List envelope**: every `*_list` tool returns `{items, returned, limit, total, truncated, hint}` — read\nrows from `items` and check `truncated` before concluding a listing is complete; empty `items` with\n`truncated:false` means checked-and-none, not a failure. Lists are fetched with server-side pagination.\n\n**Blast radius (normative)**: `pool_push_image` recreates **every desktop in the pool** — the highest\nsingle-call blast radius in the family. Its preview states affected-desktop and in-session counts\nbefore any confirm, plus `blast_radius.occupancy`: `determined` when those counts can be believed,\n`unknown` when session rows exist that belong to neither a desktop pool nor a farm and so cannot be\nruled out of this pool. An `unknown` occupancy makes `in_session_count` a lower bound and refuses\n`confirm=true` — check `session_list`, or pass `acknowledge_unknown_occupancy=true`, which is audited.\n`session_logoff` / `machine_reset` / `machine_remove` state their affected users/\nmachines and require double confirmation at the CLI.\n\n**Read/write split**: 16 read-only tools (`[READ]` docstring marker), 11 modify state. All writes are\naudit-logged; destructive ones (`session_logoff`, `machine_reset`, `machine_remove`, `pool_set_enabled`\ndisable, `entitlement_remove`, `pool_push_image`, `task_cancel`) require CLI double-confirmation and\nsupport `--dry-run`.\n\n## CLI Quick Reference\n\n```bash\nvmware-vdi init                                          # friendly setup + pool discovery\nvmware-vdi health                                        # one-glance VDI health\nvmware-vdi stats                                         # session concurrency statistics\nvmware-vdi utilization                                   # per-pool desktop utilization\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED]\nvmware-vdi session logoff --user U [--dry-run]           # double-confirm\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE]\nvmware-vdi machine reset --id M [--dry-run]              # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]   # highest blast radius\nvmware-vdi task status --pool P [--task T]\nvmware-vdi ad-search \"<name>\"                            # resolve AD SID for entitlement\nvmware-vdi entitlement add|remove --pool P --sid <SID>\n```\nFull list: `references/cli-reference.md`.\n\n## Troubleshooting\n\n- **`Password not found. Set environment variable: VMWARE_VDI_<TARGET>_PASSWORD`** — run `vmware-vdi init`\n  (writes `~/.vmware-vdi/.env`, 0600), or export the var manually.\n- **Login fails (HTTP 401/400)** — check `username`/`domain` in `~/.vmware-vdi/config.yaml`; Horizon\n  authenticates against the AD `domain`. A local Connection Server admin leaves `domain` blank.\n- **`certificate could not be verified`** — for a self-signed lab cert set `verify_ssl: false` for that\n  target in the config.\n- **A write is refused with \"read-only role\"** — that is RBAC working as designed. Point the target at a\n  Horizon admin role with write privilege, or keep the read-only account for read commands only.\n- **`session list --pool` or a push-image preview shows 0 where you expect users** — on your Horizon\n  version a field name may differ; this is a beta known-limitation, please file an issue with the raw\n  `session_get` output so the projection can be pinned.\n\n## Audit & Safety\n\n1. **Source Code** — https://github.com/vmware-skills/VMware-VDI (MIT).\n2. **Config File Contents** — `config.yaml` holds host/username/domain only; passwords live in\n   `~/.vmware-vdi/.env` (0600, obfuscated to `b64:` at rest — obfuscation, not encryption).\n3. **Webhook Data Scope** — none. This skill makes no outbound calls except to the configured\n   Connection Server.\n4. **TLS Verification** — on by default; `verify_ssl: false` is per-target and only for self-signed labs.\n5. **Prompt Injection Protection** — all Connection-Server-supplied text (user names, machine/pool names,\n   event messages) passes through `vmware_policy.sanitize()` (truncation + control-char stripping).\n6. **Least Privilege** — authorization is the Horizon account's job: a read-only Horizon admin role\n   refuses every write at the Connection Server, un-bypassably. All writes are recorded in\n   `~/.vmware/audit.db`. See `references/setup-guide.md`.\n\n## License\n\nMIT\n\nFile v1.0.7:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vdi\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1788161117290\n}\n\nFile v1.0.7:references/capabilities.md\n\n# vmware-vdi — Capabilities\n\n27 MCP tools (16 read / 11 write) over the Horizon 8 Connection Server REST API. Every tool accepts an\noptional `target`. Typical response tokens are estimates for a small estate; lists paginate at 50.\n\n## Monitoring (6 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `health_summary` | R | session totals by state, problem-machine count, pool enabled/disabled | 80–200 |\n| `session_list` | R | id, user, type, state, protocol, pool_id, machine_id, start_time (filter user/pool/state) | 60–500 |\n| `session_get` | R | one session's projection | 40–100 |\n| `machine_list` | R | id, name, pool_id, state, user, agent_version, base_image (filter pool/state) | 60–500 |\n| `machine_get` | R | one machine's projection | 40–100 |\n| `event_list` | R | time, severity, type, module, user, machine, message (filter severity) | 100–600 |\n\n## Statistics (2 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `session_stats` | R | current concurrent, by-state, by-protocol, top pools | 80–200 |\n| `pool_utilization` | R | per-pool total/available/in-use/error + utilization % | 80–300 |\n\n## Management (7 read / 2 write)\n| Tool | R/W | Notes | ~tokens |\n|------|:---:|-------|:------:|\n| `pool_list` / `pool_get` | R | pools: type, enabled, assignment | 60–300 |\n| `farm_list` | R | RDS farms: type, enabled, server count | 40–200 |\n| `app_pool_list` | R | published apps: farm, enabled, executable | 40–300 |\n| `entitlement_list` | R | AD principals entitled to a pool | 40–300 |\n| `image_list` | R | instant-clone base VMs + snapshots | 60–400 |\n| `ad_user_search` | R | resolve AD name → SID (for `entitlement_add`) | 40–200 |\n| `pool_set_enabled` | W | enable/disable pool (idempotent, preview) | 40–120 |\n| `entitlement_add` / `entitlement_remove` | W | grant/revoke pool access by SID (preview) | 40–120 |\n\n## Ops actions (6 write) — help-desk\n| Tool | R/W | Risk | Blast radius |\n|------|:---:|:----:|--------------|\n| `session_send_message` | W | low | informational, no disruption |\n| `session_disconnect` | W | medium | one session, state preserved |\n| `session_logoff` | W | high | kicks the user (profile write-back) |\n| `machine_maintenance` | W | medium | drains a machine (no new sessions) |\n| `machine_reset` | W | high | hard reset — user loses unsaved state |\n| `machine_remove` | W | high | removes from pool; deletes VM for instant clones |\n\n## Tasks (1 read / 2 write)\n| Tool | R/W | Notes |\n|------|:---:|-------|\n| `task_status` | R | pool-scoped task status/progress (or all tasks for the pool) |\n| `pool_push_image` | W | **critical** — apply pending image; recreates EVERY desktop; preview states affected desktops + in-session users |\n| `task_cancel` | W | cancel a running pool task (applied work is not rolled back) |\n\n**Beta note (踩坑 #36)**: REST endpoints are verified against the official Horizon Server API operation\nindex. GET-response *field names* are defensive (`.get()` with fallbacks) and pending validation against a\nlive Connection Server — a mismatch yields empty results, not a crash. First real-Horizon use should\nconfirm the `session`/`machine`/`pool` projections and the `apply-image` / entitlement bodies.\n\nFile v1.0.7:references/cli-reference.md\n\n# vmware-vdi — CLI Reference\n\nAll commands accept `--target/-t <name>` (config target) and `--config/-c <path>` (alternate config file).\nDestructive commands accept `--dry-run` (preview only) and interactively double-confirm.\n\n## Setup & diagnostics\n```bash\nvmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point\n```\n\n## Monitoring & statistics (read-only)\n```bash\nvmware-vdi health                           # session totals, problem machines, pool availability\nvmware-vdi stats                            # concurrency by state/protocol, busiest pools\nvmware-vdi utilization                      # per-pool total/available/in-use/error + utilization %\nvmware-vdi events [--severity ERROR]        # recent Horizon audit events (newest first)\n```\n\n## Sessions\n```bash\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED|DISCONNECTED|PENDING]\nvmware-vdi session logoff [--id S] [--user U] [--dry-run]        # kicks the user; double-confirm\nvmware-vdi session disconnect [--id S] [--user U] [--dry-run]    # state preserved; double-confirm\nvmware-vdi session message \"<text>\" [--user U] [--id S] [--type INFO|WARNING|ERROR]\n```\n\n## Machines\n```bash\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE|ERROR|...]\nvmware-vdi machine reset --id M [--dry-run]                      # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit [--dry-run] # double-confirm\nvmware-vdi machine remove --id M [--dry-run]                     # deletes VM (instant clone); double-confirm\n```\n\n## Pools, images, tasks\n```bash\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable [--dry-run]  # disable stops NEW sessions\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]     # recreates EVERY desktop; double-confirm\nvmware-vdi images                                                  # instant-clone base VMs + snapshots\nvmware-vdi task status --pool P [--task T]                        # track an image push / provisioning\nvmware-vdi task cancel --pool P --task T [--dry-run]              # double-confirm\n```\n\n## Farms, apps, entitlements\n```bash\nvmware-vdi farm list\nvmware-vdi app-pool list\nvmware-vdi ad-search \"<name>\"                                     # resolve AD user/group → SID\nvmware-vdi entitlement list --pool P\nvmware-vdi entitlement add --pool P --sid <SID> [--sid <SID> ...] [--dry-run]\nvmware-vdi entitlement remove --pool P --sid <SID> [--dry-run]   # double-confirm\n```\n\nFile v1.0.7:references/setup-guide.md\n\n# vmware-vdi — Setup Guide\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.**\n\n## 1. Install\n```bash\nuv tool install vmware-vdi\n```\n\n## 2. Connect (friendly wizard)\n```bash\nvmware-vdi init\n```\nPrompts for the **Connection Server host**, admin **username**, AD **domain** (blank for a local admin),\n**password**, target name, and TLS verification. It writes `~/.vmware-vdi/config.yaml` +\n`~/.vmware-vdi/.env` (chmod 600), tests `/rest/login`, and on success **discovers your pools/machines/\nsessions** and prints the next commands to try. Re-run with `--force` to add another Connection Server\n(existing targets are preserved; the default is repointed to the new one).\n\nManual config (`~/.vmware-vdi/config.yaml`):\n```yaml\ndefault_target: prod\ntargets:\n  prod:\n    host: horizon-cs1.example.com\n    username: svc-vdi-ro          # a read-only Horizon role for read commands\n    domain: ACME                  # AD domain; blank for a local Connection Server admin\n    port: 443\n    verify_ssl: true              # false only for a self-signed lab cert\n```\nPassword (never in config.yaml): `~/.vmware-vdi/.env`\n```\nVMWARE_VDI_PROD_PASSWORD=b64:...    # written by `init`; or export it yourself (plaintext auto-obfuscated)\n```\n\n## 3. Verify\n```bash\nvmware-vdi doctor        # config / credentials / connectivity\n```\n\n## 4. Supported versions\n- **Primary: VMware Horizon 8.x** (Connection Server REST API `/rest/v1`).\n- **Latest Omnissa Horizon** (2406/2412+) — same `/rest/v1` lineage.\n- Requires the Connection Server REST API enabled (Horizon 8.0+; audit-events since 2106).\n\n## 5. MCP server\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vdi\": {\n      \"command\": \"vmware-vdi\",\n      \"args\": [\"mcp\"],\n      \"env\": { \"VMWARE_VDI_CONFIG\": \"~/.vmware-vdi/config.yaml\" }\n    }\n  }\n}\n```\nUsing the installed `vmware-vdi mcp` console script (not `uvx`) avoids a PyPI re-resolve on every launch —\nimportant behind enterprise TLS proxies.\n\n## Security\n> **Disclaimer**: not affiliated with VMware/Broadcom/Omnissa.\n\n- **Credentials**: password only in `~/.vmware-vdi/.env` (chmod 600, obfuscated `b64:` at rest —\n  obfuscation, not encryption). For real secrecy, inject `VMWARE_VDI_<TARGET>_PASSWORD` from a secret\n  manager (Vault / CyberArk / AWS SM / K8s Secret).\n- **Authorization = RBAC**: the skill does not gate read vs write itself. Point a target at a **read-only\n  Horizon admin role** and every write is refused at the Connection Server, un-bypassably.\n- **TLS**: verification on by default; `verify_ssl: false` is per-target, for self-signed labs only.\n- **Prompt-injection**: Connection-Server text is `sanitize()`d (truncated + control chars stripped).\n- **Audit**: all writes recorded in `~/.vmware/audit.db` (SQLite WAL) via the shared `@vmware_tool` guard.\n- **No outbound calls** other than to the configured Connection Server; no webhooks, no telemetry.\n\nFile v1.0.7:skill-card.md\n\n## Description:\n\nOperates VMware/Omnissa Horizon VDI environments through a Connection Server for pool, farm, app, session, machine, entitlement, event, health, statistics, and instant-clone image workflows.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nIT administrators, help-desk engineers, and infrastructure operators use this skill to inspect and manage Horizon VDI broker-layer resources, troubleshoot sessions and machines, manage entitlements, and coordinate image-push operations.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can perform write operations against Horizon VDI resources, including disruptive actions such as session logoff, machine reset or removal, disabling pools, task cancellation, and image pushes.\n\nMitigation: Install only where the operator is authorized to administer Horizon VDI, prefer read-only Horizon roles for monitoring, use write-capable credentials only when needed, and review dry-run or blast-radius output before disruptive actions.\n\nRisk: Production credentials and Connection Server access can expose administrative authority over VDI resources.\n\nMitigation: Keep TLS verification enabled outside labs and use a real secret manager for production passwords.\n\nRisk: Instant-clone image pushes can affect every desktop in a pool and may disrupt active users.\n\nMitigation: Check pool occupancy and session information before confirming image pushes, warn users when needed, and proceed only after the reported blast radius is understood.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/zw008/skills/vmware-vdi)\n- [Capabilities](artifact/references/capabilities.md)\n- [CLI Reference](artifact/references/cli-reference.md)\n- [Setup Guide](artifact/references/setup-guide.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown with inline shell commands and configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include dry-run guidance, blast-radius review, and operational next steps for Horizon VDI tasks.]\n\n## Skill Version(s):\n\n1.0.7 (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 v1.0.6: 6 files, 11017 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2977b), skill-card.md (2326b), SKILL.md (12026b), _meta.json (129b)\n\nFile v1.0.6:SKILL.md\n\n---\nname: vmware-vdi\ndescription: >\n  Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its\n  Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on\n  user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance,\n  remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone\n  golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop\n  pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to\n  the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool /\n  RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops),\n  read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security).\n  This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\ninstaller:\n  kind: uv\n  package: vmware-vdi\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"env\":[\"VMWARE_VDI_CONFIG\"],\"bins\":[\"vmware-vdi\"],\"config\":[\"~/.vmware-vdi/config.yaml\"]},\"primaryEnv\":\"VMWARE_VDI_CONFIG\"}}\n---\n\n# VMware VDI (Horizon)\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.** \"VMware\", \"Horizon\", and \"Omnissa\" are\n> trademarks of their respective owners. Source is publicly auditable under the MIT license.\n\nHorizon VDI intelligent operations for the VMware skill family — desktop pools, RDS farms, **user\nsessions**, desktop machines, entitlements, events/health/statistics, and instant-clone image push,\nthrough the **Horizon 8 Connection Server REST API** (primary; also targets the latest Omnissa Horizon,\nwhich shares the same `/rest/v1` API lineage).\n\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (the vCenter VMs backing\n> the desktops), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only vSphere),\n> [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (desktop microsegmentation).\n\n> **Status: v1.0.0 (beta).** Endpoints are verified against the official Horizon Server API; GET-response\n> field projections are defensive and pending validation against a live Connection Server (run\n> `vmware-vdi init` on a real Horizon once to confirm). Governed by the family harness (audit + policy +\n> teaching errors); authorization is delegated to the Horizon admin account's role.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read/Write |\n|----------|-------|:-----:|:----------:|\n| **Monitoring** | health summary, session list/get, machine list/get, event list | 6 | 6 R |\n| **Statistics** | session concurrency stats, per-pool utilization | 2 | 2 R |\n| **Management** | pool list/get, farm list, app-pool list, entitlement list, image list, AD search; pool enable/disable, entitlement add/remove | 9 | 7 R / 2 W |\n| **Ops actions** | session logoff/disconnect/message, machine reset/maintenance/remove | 6 | 6 W |\n| **Tasks** | task status; image push, task cancel | 3 | 1 R / 2 W |\n\n**27 MCP tools (16 read / 11 write).** Reads are strictly non-destructive. Writes preview their blast\nradius, are double-confirmed at the CLI, and are audit-logged.\n\n## Quick Install\n\n```bash\nuv tool install vmware-vdi\nvmware-vdi init      # friendly setup: connect to a Connection Server + discover your pools\nvmware-vdi doctor    # verify config / credentials / connectivity\n```\n\n## When to Use This Skill\n\nUse vmware-vdi for the **Horizon broker layer**: desktop pools, RDS farms, published apps, **user\nsessions** (logoff/disconnect/message), desktop machine state (reset/maintenance/remove), entitlements,\nHorizon events/health/statistics, and **instant-clone image push** — when the context is explicitly\nHorizon / Omnissa / VDI / desktop-pool / RDS-farm.\n\n**Do NOT use when**: the task is the underlying vCenter VM (power/snapshot/clone/migrate → **vmware-aiops**),\nread-only vSphere inventory/alarms (→ **vmware-monitor**), or NSX microsegmentation of the desktops\n(→ **vmware-nsx-security**). A Horizon desktop's *backing VM* is aiops; the *session/pool/broker* is vdi.\n\n## Related Skills — Skill Routing\n\n| The user wants… | Skill |\n|-----------------|-------|\n| Log off / reset / re-image a Horizon desktop or session | **vmware-vdi** (this) |\n| Power/snapshot/clone/migrate the backing vCenter VM | vmware-aiops |\n| Read-only vSphere inventory / alarms / host health | vmware-monitor |\n| Microsegment the desktop pool network | vmware-nsx-security |\n| Multi-step VDI workflow with approval + rollback | vmware-pilot |\n\n## Common Workflows\n\n**1. Help-desk: a user's desktop is stuck.**\n```\nvmware-vdi session list --user alice          # find their session + state\nvmware-vdi machine list --state AGENT_UNREACHABLE   # is the desktop broken?\nvmware-vdi session logoff --user alice --dry-run    # preview blast radius (which sessions)\nvmware-vdi session logoff --user alice        # double-confirm, then logs off + audits\n```\n*Failure branch*: if `session list` returns a teaching 404/auth error, run `vmware-vdi doctor` — a\nread-only Horizon role is enough for the reads but the account must be able to reach the Connection Server.\n\n**2. Patch night: push a new golden image to a pool.**\n```\nvmware-vdi image list                         # find the base VM + snapshot\nvmware-vdi pool push-image --id pool-fin --dry-run   # BLAST RADIUS: N desktops, M logged-in users\nvmware-vdi pool set-enabled --id pool-fin --disable  # optional: stop new logins first\nvmware-vdi pool push-image --id pool-fin      # double-confirm; returns a task\nvmware-vdi task status --pool pool-fin         # track progress\n```\n*Failure branch*: if the preview shows logged-in users you did not expect, `session send-message --user …`\nto warn them, or push with `--force-logoff` only after confirming impact.\n\n**3. Onboard a group to a pool.**\n```\nvmware-vdi ad-search \"Finance\"                # resolve the AD group → its SID\nvmware-vdi entitlement add --pool pool-fin --sid <SID>\nvmware-vdi entitlement list --pool pool-fin   # verify\n```\n*Failure branch*: `ad-search` returning nothing usually means the domain in `~/.vmware-vdi/config.yaml`\nis wrong — re-run `vmware-vdi init --force`.\n\n## Usage Mode\n\n- **CLI** — interactive help-desk work, scripting, small/local models (lower context cost).\n- **MCP** — agent-driven operations with structured output; run `vmware-vdi mcp` (an installed console\n  script, so no `uvx` network re-resolve — works through enterprise TLS proxies).\n\n## MCP Tools (27 — 16 read, 11 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Monitoring | `health_summary`, `session_list`, `session_get`, `machine_list`, `machine_get`, `event_list` | Read |\n| Statistics | `session_stats`, `pool_utilization` | Read |\n| Management (read) | `pool_list`, `pool_get`, `farm_list`, `app_pool_list`, `entitlement_list`, `image_list`, `ad_user_search` | Read |\n| Tasks (read) | `task_status` | Read |\n| Ops actions | `session_logoff`, `session_disconnect`, `session_send_message`, `machine_reset`, `machine_maintenance`, `machine_remove` | Write |\n| Management (write) | `pool_set_enabled`, `entitlement_add`, `entitlement_remove` | Write |\n| Tasks (write) | `pool_push_image`, `task_cancel` | Write |\n\n**List envelope**: every `*_list` tool returns `{items, returned, limit, total, truncated, hint}` — read\nrows from `items` and check `truncated` before concluding a listing is complete; empty `items` with\n`truncated:false` means checked-and-none, not a failure. Lists are fetched with server-side pagination.\n\n**Blast radius (normative)**: `pool_push_image` recreates **every desktop in the pool** — the highest\nsingle-call blast radius in the family. Its preview states affected-desktop and in-session counts\nbefore any confirm, plus `blast_radius.occupancy`: `determined` when those counts can be believed,\n`unknown` when session rows exist that belong to neither a desktop pool nor a farm and so cannot be\nruled out of this pool. An `unknown` occupancy makes `in_session_count` a lower bound and refuses\n`confirm=true` — check `session_list`, or pass `acknowledge_unknown_occupancy=true`, which is audited.\n`session_logoff` / `machine_reset` / `machine_remove` state their affected users/\nmachines and require double confirmation at the CLI.\n\n**Read/write split**: 16 read-only tools (`[READ]` docstring marker), 11 modify state. All writes are\naudit-logged; destructive ones (`session_logoff`, `machine_reset`, `machine_remove`, `pool_set_enabled`\ndisable, `entitlement_remove`, `pool_push_image`, `task_cancel`) require CLI double-confirmation and\nsupport `--dry-run`.\n\n## CLI Quick Reference\n\n```bash\nvmware-vdi init                                          # friendly setup + pool discovery\nvmware-vdi health                                        # one-glance VDI health\nvmware-vdi stats                                         # session concurrency statistics\nvmware-vdi utilization                                   # per-pool desktop utilization\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED]\nvmware-vdi session logoff --user U [--dry-run]           # double-confirm\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE]\nvmware-vdi machine reset --id M [--dry-run]              # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]   # highest blast radius\nvmware-vdi task status --pool P [--task T]\nvmware-vdi ad-search \"<name>\"                            # resolve AD SID for entitlement\nvmware-vdi entitlement add|remove --pool P --sid <SID>\n```\nFull list: `references/cli-reference.md`.\n\n## Troubleshooting\n\n- **`Password not found. Set environment variable: VMWARE_VDI_<TARGET>_PASSWORD`** — run `vmware-vdi init`\n  (writes `~/.vmware-vdi/.env`, 0600), or export the var manually.\n- **Login fails (HTTP 401/400)** — check `username`/`domain` in `~/.vmware-vdi/config.yaml`; Horizon\n  authenticates against the AD `domain`. A local Connection Server admin leaves `domain` blank.\n- **`certificate could not be verified`** — for a self-signed lab cert set `verify_ssl: false` for that\n  target in the config.\n- **A write is refused with \"read-only role\"** — that is RBAC working as designed. Point the target at a\n  Horizon admin role with write privilege, or keep the read-only account for read commands only.\n- **`session list --pool` or a push-image preview shows 0 where you expect users** — on your Horizon\n  version a field name may differ; this is a beta known-limitation, please file an issue with the raw\n  `session_get` output so the projection can be pinned.\n\n## Audit & Safety\n\n1. **Source Code** — https://github.com/vmware-skills/VMware-VDI (MIT).\n2. **Config File Contents** — `config.yaml` holds host/username/domain only; passwords live in\n   `~/.vmware-vdi/.env` (0600, obfuscated to `b64:` at rest — obfuscation, not encryption).\n3. **Webhook Data Scope** — none. This skill makes no outbound calls except to the configured\n   Connection Server.\n4. **TLS Verification** — on by default; `verify_ssl: false` is per-target and only for self-signed labs.\n5. **Prompt Injection Protection** — all Connection-Server-supplied text (user names, machine/pool names,\n   event messages) passes through `vmware_policy.sanitize()` (truncation + control-char stripping).\n6. **Least Privilege** — authorization is the Horizon account's job: a read-only Horizon admin role\n   refuses every write at the Connection Server, un-bypassably. All writes are recorded in\n   `~/.vmware/audit.db`. See `references/setup-guide.md`.\n\n## License\n\nMIT\n\nFile v1.0.6:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vdi\",\n  \"version\": \"1.0.6\",\n  \"publishedAt\": 1788136620174\n}\n\nFile v1.0.6:references/capabilities.md\n\n# vmware-vdi — Capabilities\n\n27 MCP tools (16 read / 11 write) over the Horizon 8 Connection Server REST API. Every tool accepts an\noptional `target`. Typical response tokens are estimates for a small estate; lists paginate at 50.\n\n## Monitoring (6 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `health_summary` | R | session totals by state, problem-machine count, pool enabled/disabled | 80–200 |\n| `session_list` | R | id, user, type, state, protocol, pool_id, machine_id, start_time (filter user/pool/state) | 60–500 |\n| `session_get` | R | one session's projection | 40–100 |\n| `machine_list` | R | id, name, pool_id, state, user, agent_version, base_image (filter pool/state) | 60–500 |\n| `machine_get` | R | one machine's projection | 40–100 |\n| `event_list` | R | time, severity, type, module, user, machine, message (filter severity) | 100–600 |\n\n## Statistics (2 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `session_stats` | R | current concurrent, by-state, by-protocol, top pools | 80–200 |\n| `pool_utilization` | R | per-pool total/available/in-use/error + utilization % | 80–300 |\n\n## Management (7 read / 2 write)\n| Tool | R/W | Notes | ~tokens |\n|------|:---:|-------|:------:|\n| `pool_list` / `pool_get` | R | pools: type, enabled, assignment | 60–300 |\n| `farm_list` | R | RDS farms: type, enabled, server count | 40–200 |\n| `app_pool_list` | R | published apps: farm, enabled, executable | 40–300 |\n| `entitlement_list` | R | AD principals entitled to a pool | 40–300 |\n| `image_list` | R | instant-clone base VMs + snapshots | 60–400 |\n| `ad_user_search` | R | resolve AD name → SID (for `entitlement_add`) | 40–200 |\n| `pool_set_enabled` | W | enable/disable pool (idempotent, preview) | 40–120 |\n| `entitlement_add` / `entitlement_remove` | W | grant/revoke pool access by SID (preview) | 40–120 |\n\n## Ops actions (6 write) — help-desk\n| Tool | R/W | Risk | Blast radius |\n|------|:---:|:----:|--------------|\n| `session_send_message` | W | low | informational, no disruption |\n| `session_disconnect` | W | medium | one session, state preserved |\n| `session_logoff` | W | high | kicks the user (profile write-back) |\n| `machine_maintenance` | W | medium | drains a machine (no new sessions) |\n| `machine_reset` | W | high | hard reset — user loses unsaved state |\n| `machine_remove` | W | high | removes from pool; deletes VM for instant clones |\n\n## Tasks (1 read / 2 write)\n| Tool | R/W | Notes |\n|------|:---:|-------|\n| `task_status` | R | pool-scoped task status/progress (or all tasks for the pool) |\n| `pool_push_image` | W | **critical** — apply pending image; recreates EVERY desktop; preview states affected desktops + in-session users |\n| `task_cancel` | W | cancel a running pool task (applied work is not rolled back) |\n\n**Beta note (踩坑 #36)**: REST endpoints are verified against the official Horizon Server API operation\nindex. GET-response *field names* are defensive (`.get()` with fallbacks) and pending validation against a\nlive Connection Server — a mismatch yields empty results, not a crash. First real-Horizon use should\nconfirm the `session`/`machine`/`pool` projections and the `apply-image` / entitlement bodies.\n\nFile v1.0.6:references/cli-reference.md\n\n# vmware-vdi — CLI Reference\n\nAll commands accept `--target/-t <name>` (config target) and `--config/-c <path>` (alternate config file).\nDestructive commands accept `--dry-run` (preview only) and interactively double-confirm.\n\n## Setup & diagnostics\n```bash\nvmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point\n```\n\n## Monitoring & statistics (read-only)\n```bash\nvmware-vdi health                           # session totals, problem machines, pool availability\nvmware-vdi stats                            # concurrency by state/protocol, busiest pools\nvmware-vdi utilization                      # per-pool total/available/in-use/error + utilization %\nvmware-vdi events [--severity ERROR]        # recent Horizon audit events (newest first)\n```\n\n## Sessions\n```bash\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED|DISCONNECTED|PENDING]\nvmware-vdi session logoff [--id S] [--user U] [--dry-run]        # kicks the user; double-confirm\nvmware-vdi session disconnect [--id S] [--user U] [--dry-run]    # state preserved; double-confirm\nvmware-vdi session message \"<text>\" [--user U] [--id S] [--type INFO|WARNING|ERROR]\n```\n\n## Machines\n```bash\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE|ERROR|...]\nvmware-vdi machine reset --id M [--dry-run]                      # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit [--dry-run] # double-confirm\nvmware-vdi machine remove --id M [--dry-run]                     # deletes VM (instant clone); double-confirm\n```\n\n## Pools, images, tasks\n```bash\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable [--dry-run]  # disable stops NEW sessions\nvmware-vdi pool p\n\nArchive v1.0.5: 6 files, 11040 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2977b), skill-card.md (2434b), SKILL.md (12026b), _meta.json (129b)\n\nArchive v1.0.4: 6 files, 10960 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2977b), skill-card.md (2528b), SKILL.md (11649b), _meta.json (129b)\n\nArchive v1.0.3: 6 files, 10964 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2977b), skill-card.md (2497b), SKILL.md (11649b), _meta.json (129b)\n\nArchive v1.0.2: 6 files, 10988 bytes\n\nFiles: references/capabilities.md (3273b), references/cli-reference.md (2713b), references/setup-guide.md (2977b), skill-card.md (2646b), SKILL.md (11649b), _meta.json (129b)","readmeExcerpt":"Skill: vmware-vdi Owner: zw008 Summary: Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance, remove), view and change entitlements, read Horizon events/health/statistics, and push","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"uv tool install vmware-vdi==1.3.0\nvmware-vdi init      # friendly setup: connect to a Connection Server + discover your pools\nvmware-vdi doctor    # verify config / credentials / connectivity"},{"language":"text","snippet":"vmware-vdi session list --user alice          # find their session + state\nvmware-vdi machine list --state AGENT_UNREACHABLE   # is the desktop broken?\nvmware-vdi session logoff --user alice --dry-run    # preview blast radius (which sessions)\nvmware-vdi session logoff --user alice        # double-confirm, then logs off + audits"},{"language":"text","snippet":"vmware-vdi image list                         # find the base VM + snapshot\nvmware-vdi pool push-image --id pool-fin --dry-run   # BLAST RADIUS: N desktops, M logged-in users\nvmware-vdi pool set-enabled --id pool-fin --disable  # optional: stop new logins first\nvmware-vdi pool push-image --id pool-fin      # double-confirm; returns a task\nvmware-vdi task status --pool pool-fin         # track progress"},{"language":"text","snippet":"vmware-vdi ad-search \"Finance\"                # resolve the AD group → its SID\nvmware-vdi entitlement add --pool pool-fin --sid <SID>\nvmware-vdi entitlement list --pool pool-fin   # verify"},{"language":"bash","snippet":"vmware-vdi init                                          # friendly setup + pool discovery\nvmware-vdi health                                        # one-glance VDI health\nvmware-vdi stats                                         # session concurrency statistics\nvmware-vdi utilization                                   # per-pool desktop utilization\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED]\nvmware-vdi session logoff --user U [--dry-run]           # double-confirm\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE]\nvmware-vdi machine reset --id M [--dry-run]              # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]   # highest blast radius\nvmware-vdi task status --pool P [--task T]\nvmware-vdi ad-search \"<name>\"                            # resolve AD SID for entitlement\nvmware-vdi entitlement add|remove --pool P --sid <SID>"},{"language":"bash","snippet":"vmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: vmware-vdi\ndescription: >\n  Use this skill whenever the user needs to operate a VMware/Omnissa Horizon VDI environment via its\n  Connection Server: list and manage desktop pools, RDS farms and published apps, inspect and act on\n  user sessions (log off, disconnect, send message), manage desktop machines (reset, maintenance,\n  remove), view and change entitlements, read Horizon events/health/statistics, and push instant-clone\n  golden images. Always use this skill for \"log off VDI user\", \"reset this desktop\", \"why is the desktop\n  pool not provisioning\", \"push the new image to the pool\", \"list Horizon sessions\", \"who is entitled to\n  the pool\", \"VDI health\" — when the context is explicitly Horizon / Omnissa / VDI / desktop-pool /\n  RDS-farm. Do NOT use for the underlying vCenter VM lifecycle/power/snapshot/migrate (use vmware-aiops),\n  read-only vSphere monitoring (use vmware-monitor), or NSX microsegmentation (use vmware-nsx-security).\n  This skill manages the Horizon broker layer; vmware-aiops manages the vCenter VMs backing the desktops.\ninstaller:\n  kind: uv\n  package: vmware-vdi\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vdi\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VDI_CONFIG\"]}}}\n---\n\n# VMware VDI (Horizon)\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.** \"VMware\", \"Horizon\", and \"Omnissa\" are\n> trademarks of their respective owners. Source is publicly auditable under the MIT license.\n\nHorizon VDI intelligent operations for the VMware skill family — desktop pools, RDS farms, **user\nsessions**, desktop machines, entitlements, events/health/statistics, and instant-clone image push,\nthrough the **Horizon 8 Connection Server REST API** (primary; also targets the latest Omnissa Horizon,\nwhich shares the same `/rest/v1` API lineage).\n\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (the vCenter VMs backing\n> the desktops), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only vSphere),\n> [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (desktop microsegmentation).\n\n> **Status: v1.0.0 (beta).** Endpoints are verified against the official Horizon Server API; GET-response\n> field projections are defensive and pending validation against a live Connection Server (run\n> `vmware-vdi init` on a real Horizon once to confirm). Governed by the family harness (audit + policy +\n> teaching errors); authorization is delegated to the Horizon admin account's role.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read/Write |\n|----------|-------|:-----:|:----------:|\n| **Monitoring** | health summary, session list/get, machine list/get, event list | 6 | 6 R |\n| **Statistics** | session concurrency stats, per-pool utilization | 2 | 2 R |\n| **Management** | pool list/get, farm list, app-pool list, entitlement list, image li"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vdi\",\n  \"version\": \"1.3.0\",\n  \"publishedAt\": 1789915941854\n}"},{"path":"references/capabilities.md","content":"# vmware-vdi — Capabilities\n\n27 MCP tools (16 read / 11 write) over the Horizon 8 Connection Server REST API. Every tool accepts an\noptional `target`. Typical response tokens are estimates for a small estate; lists paginate at 50.\n\n## Monitoring (6 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `health_summary` | R | session totals by state, problem-machine count, pool enabled/disabled | 80–200 |\n| `session_list` | R | id, user, type, state, protocol, pool_id, machine_id, start_time (filter user/pool/state) | 60–500 |\n| `session_get` | R | one session's projection | 40–100 |\n| `machine_list` | R | id, name, pool_id, state, user, agent_version, base_image (filter pool/state) | 60–500 |\n| `machine_get` | R | one machine's projection | 40–100 |\n| `event_list` | R | time, severity, type, module, user, machine, message (filter severity) | 100–600 |\n\n## Statistics (2 read)\n| Tool | R/W | Returns | ~tokens |\n|------|:---:|---------|:------:|\n| `session_stats` | R | current concurrent, by-state, by-protocol, top pools | 80–200 |\n| `pool_utilization` | R | per-pool total/available/in-use/error + utilization % | 80–300 |\n\n## Management (7 read / 2 write)\n| Tool | R/W | Notes | ~tokens |\n|------|:---:|-------|:------:|\n| `pool_list` / `pool_get` | R | pools: type, enabled, assignment | 60–300 |\n| `farm_list` | R | RDS farms: type, enabled, server count | 40–200 |\n| `app_pool_list` | R | published apps: farm, enabled, executable | 40–300 |\n| `entitlement_list` | R | AD principals entitled to a pool | 40–300 |\n| `image_list` | R | instant-clone base VMs + snapshots | 60–400 |\n| `ad_user_search` | R | resolve AD name → SID (for `entitlement_add`) | 40–200 |\n| `pool_set_enabled` | W | enable/disable pool (idempotent, preview) | 40–120 |\n| `entitlement_add` / `entitlement_remove` | W | grant/revoke pool access by SID (preview) | 40–120 |\n\n## Ops actions (6 write) — help-desk\n| Tool | R/W | Risk | Blast radius |\n|------|:---:|:----:|--------------|\n| `session_send_message` | W | low | informational, no disruption |\n| `session_disconnect` | W | medium | one session, state preserved |\n| `session_logoff` | W | high | kicks the user (profile write-back) |\n| `machine_maintenance` | W | medium | drains a machine (no new sessions) |\n| `machine_reset` | W | high | hard reset — user loses unsaved state |\n| `machine_remove` | W | high | removes from pool; deletes VM for instant clones |\n\n## Tasks (1 read / 2 write)\n| Tool | R/W | Notes |\n|------|:---:|-------|\n| `task_status` | R | pool-scoped task status/progress (or all tasks for the pool) |\n| `pool_push_image` | W | **critical** — apply pending image; recreates EVERY desktop; preview states affected desktops + in-session users |\n| `task_cancel` | W | cancel a running pool task (applied work is not rolled back) |\n\n**Confirmation gate (MCP)**: every write above except `session_send_message` takes `confirm`\n(default `false`). Without it the tool returns `{\"action\": \"preview\", \"blast_radius\": {"},{"path":"references/cli-reference.md","content":"# vmware-vdi — CLI Reference\n\nAll commands accept `--target/-t <name>` (config target) and `--config/-c <path>` (alternate config file).\nDestructive commands accept `--dry-run` (preview only) and interactively double-confirm.\n\n## Setup & diagnostics\n```bash\nvmware-vdi init [--force] [--skip-test]     # friendly setup: prompt, write config + .env, test, discover pools\nvmware-vdi doctor                           # config / credentials / connectivity checks\nvmware-vdi mcp                              # run the MCP server (stdio) — the primary MCP entry point\n```\n\n## Monitoring & statistics (read-only)\n```bash\nvmware-vdi health                           # session totals, problem machines, pool availability\nvmware-vdi stats                            # concurrency by state/protocol, busiest pools\nvmware-vdi utilization                      # per-pool total/available/in-use/error + utilization %\nvmware-vdi events [--severity ERROR]        # recent Horizon audit events (newest first)\n```\n\n## Sessions\n```bash\nvmware-vdi session list [--user U] [--pool P] [--state CONNECTED|DISCONNECTED|PENDING]\nvmware-vdi session logoff [--id S] [--user U] [--dry-run]        # kicks the user; double-confirm\nvmware-vdi session disconnect [--id S] [--user U] [--dry-run]    # state preserved; double-confirm\nvmware-vdi session message \"<text>\" [--user U] [--id S] [--type INFO|WARNING|ERROR]\n```\n\n## Machines\n```bash\nvmware-vdi machine list [--pool P] [--state AGENT_UNREACHABLE|ERROR|...]\nvmware-vdi machine reset --id M [--dry-run]                      # hard reset; double-confirm\nvmware-vdi machine maintenance --id M --enter|--exit [--dry-run] # double-confirm\nvmware-vdi machine remove --id M [--dry-run]                     # deletes VM (instant clone); double-confirm\n```\n\n## Pools, images, tasks\n```bash\nvmware-vdi pool list\nvmware-vdi pool set-enabled --id P --enable|--disable [--dry-run]  # disable stops NEW sessions\nvmware-vdi pool push-image --id P [--force-logoff] [--dry-run]     # recreates EVERY desktop; double-confirm\nvmware-vdi images                                                  # instant-clone base VMs + snapshots\nvmware-vdi task status --pool P [--task T]                        # track an image push / provisioning\nvmware-vdi task cancel --pool P --task T [--dry-run]              # double-confirm\n```\n\n## Farms, apps, entitlements\n```bash\nvmware-vdi farm list\nvmware-vdi app-pool list\nvmware-vdi ad-search \"<name>\"                                     # resolve AD user/group → SID\nvmware-vdi entitlement list --pool P\nvmware-vdi entitlement add --pool P --sid <SID> [--sid <SID> ...] [--dry-run]\nvmware-vdi entitlement remove --pool P --sid <SID> [--dry-run]   # double-confirm\n```"},{"path":"references/setup-guide.md","content":"# vmware-vdi — Setup Guide\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or\n> sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC.**\n\n## 1. Install\n```bash\nuv tool install vmware-vdi==1.3.0\n```\n\n## 2. Connect (friendly wizard)\n```bash\nvmware-vdi init\n```\nPrompts for the **Connection Server host**, admin **username**, AD **domain** (blank for a local admin),\n**password**, target name, and TLS verification. It writes `~/.vmware-vdi/config.yaml` +\n`~/.vmware-vdi/.env` (chmod 600), tests `/rest/login`, and on success **discovers your pools/machines/\nsessions** and prints the next commands to try. Re-run with `--force` to add another Connection Server\n(existing targets are preserved; the default is repointed to the new one).\n\nManual config (`~/.vmware-vdi/config.yaml`):\n```yaml\ndefault_target: prod\ntargets:\n  prod:\n    host: horizon-cs1.example.com\n    username: svc-vdi-ro          # a read-only Horizon role for read commands\n    domain: ACME                  # AD domain; blank for a local Connection Server admin\n    port: 443\n    verify_ssl: true              # false only for a self-signed lab cert\n```\nPassword (never in config.yaml): `~/.vmware-vdi/.env`\n```\nVMWARE_VDI_PROD_PASSWORD=b64:...    # written by `init`; or export it yourself (plaintext auto-obfuscated)\n```\n\n## 3. Verify\n```bash\nvmware-vdi doctor        # config / credentials / connectivity\n```\n\n## 4. Supported versions\n- **Primary: VMware Horizon 8.x** (Connection Server REST API `/rest/v1`).\n- **Latest Omnissa Horizon** (2406/2412+) — same `/rest/v1` lineage.\n- Requires the Connection Server REST API enabled (Horizon 8.0+; audit-events since 2106).\n\n## 5. MCP server\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vdi\": {\n      \"command\": \"vmware-vdi\",\n      \"args\": [\"mcp\"],\n      \"env\": { \"VMWARE_VDI_CONFIG\": \"~/.vmware-vdi/config.yaml\" }\n    }\n  }\n}\n```\nUsing the installed `vmware-vdi mcp` console script (not `uvx`) avoids a PyPI re-resolve on every launch —\nimportant behind enterprise TLS proxies.\n\n## Security\n> **Disclaimer**: not affiliated with VMware/Broadcom/Omnissa.\n\n- **Credentials**: password only in `~/.vmware-vdi/.env` (chmod 600, obfuscated `b64:` at rest —\n  obfuscation, not encryption). For real secrecy, inject `VMWARE_VDI_<TARGET>_PASSWORD` from a secret\n  manager (Vault / CyberArk / AWS SM / K8s Secret).\n- **Authorization = RBAC**: the skill does not gate read vs write itself. Point a target at a **read-only\n  Horizon admin role** and every write is refused at the Connection Server, un-bypassably.\n- **TLS**: verification on by default; `verify_ssl: false` is per-target, for self-signed labs only.\n- **Prompt-injection**: Connection-Server text is `sanitize()`d (truncated + control chars stripped).\n- **Audit**: all writes recorded in `~/.vmware/audit.db` (SQLite WAL) via the shared `@vmware_tool` guard.\n- **No outbound calls** other than to the configured Connection Server; no webhooks, no telemetry."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1786,"uniquenessScore":42,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T21:42:45.205Z","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-11T21:42:45.205Z","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-12T19:18:44.692Z","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"}]}}}