{"id":"71c3c3dc-a796-4e28-b362-704233a6f81b","entityType":"agent","slug":"clawhub-zw008-vmware-vks","name":"vmware-vks","canonicalUrl":"https://www.xpersona.co/agent/clawhub-zw008-vmware-vks","canonicalPath":"/agent/clawhub-zw008-vmware-vks","generatedAt":"2026-10-09T19:37:45.946Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:14:22.565Z","emptyReason":null},"description":"Use this skill whenever the user needs to manage vSphere Kubernetes Service (VKS) — Supervisor clusters, vSphere Namespaces, and TKC cluster lifecycle. Directly handles: check VKS compatibility, create/delete namespaces, create/scale/upgrade/delete TKC clusters, get kubeconfig, check Harbor registry. Always use this skill for \"create Kubernetes cluster\", \"scale workers\", \"upgrade K8s version\", \"create namespace\", \"get kubeconfig\", or any VKS/TKC task. Do NOT use for vanilla VM operations (use vmware-aiops), non-vSphere Kubernetes (e.g., kubeadm, EKS, AKS), or AVI/AKO load balancing (use vmware-avi). For networking use vmware-nsx.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 5.2K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-vks","sourceUrl":"https://clawhub.ai/zw008/vmware-vks","homepage":"https://clawhub.ai/zw008/skills/vmware-vks","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/zw008/vmware-vks","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/zw008/skills/vmware-vks","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":49,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"vmware-vks 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-09T04:14:22.565Z","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-09T04:14:22.565Z","emptyReason":null},"stars":null,"forks":null,"downloads":5242,"packageName":null,"latestVersion":"1.12.0","tractionLabel":"5.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:14:22.565Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T04:14:22.565Z","lastCrawledAt":"2026-10-09T04:14:22.565Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T04:14:22.565Z","lastVerifiedAt":null,"highlights":[{"version":"1.12.0","createdAt":"2026-09-20T14:52:58.167Z","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":8,"zipByteSize":26185},{"version":"1.11.0","createdAt":"2026-09-19T03:56:14.946Z","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":8,"zipByteSize":26092},{"version":"1.10.3","createdAt":"2026-09-16T05:19:28.037Z","changelog":"A stopped MCP server exits within five seconds even if its logout hangs","fileCount":8,"zipByteSize":25944},{"version":"1.10.2","createdAt":"2026-09-15T14:40:30.082Z","changelog":"Stopping the MCP server now logs out its vCenter session.","fileCount":8,"zipByteSize":25807},{"version":"1.10.1","createdAt":"2026-09-15T06:09:08.288Z","changelog":"CLI reads are audited under their MCP tool names; every CLI command declares what it reaches (needs vmware-policy 1.15.0)","fileCount":8,"zipByteSize":25683},{"version":"1.10.0","createdAt":"2026-09-12T00:14:41.719Z","changelog":"A kubeconfig is credential access on every surface: the kubeconfig tools are no longer annotated read-only and carry a medium risk level, and -o writes the file atomically and owner-only. CLI writes are authorised and audited under their MCP tool names.","fileCount":8,"zipByteSize":25662},{"version":"1.9.4","createdAt":"2026-09-05T01:06:34.694Z","changelog":"a dropped connection no longer keeps itself alive","fileCount":8,"zipByteSize":23281},{"version":"1.9.3","createdAt":"2026-09-03T02:03:29.090Z","changelog":"two documented flags that do not exist","fileCount":8,"zipByteSize":23378}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-vks","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:vmware-vks` 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-vks 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-vks/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/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-09T19:37:45.942Z"}},"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-vks/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-vmware-vks/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-09T04:14:22.565Z","emptyReason":null},"readme":"Skill: vmware-vks\n\nOwner: zw008\n\nSummary: Use this skill whenever the user needs to manage vSphere Kubernetes Service (VKS) — Supervisor clusters, vSphere Namespaces, and TKC cluster lifecycle. Directly handles: check VKS compatibility, create/delete namespaces, create/scale/upgrade/delete TKC clusters, get kubeconfig, check Harbor registry. Always use this skill for \"create Kubernetes cluster\", \"scale workers\", \"upgrade K8s version\", \"create namespace\", \"get kubeconfig\", or any VKS/TKC task. Do NOT use for vanilla VM operations (use vmware-aiops), non-vSphere Kubernetes (e.g., kubeadm, EKS, AKS), or AVI/AKO load balancing (use vmware-avi). For networking use vmware-nsx.\n\nTags: latest:1.12.0\n\nVersion history:\n\nv1.12.0 | 2026-09-20T14:52:58.167Z | 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.11.0 | 2026-09-19T03:56:14.946Z | 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.10.3 | 2026-09-16T05:19:28.037Z | user\n\nA stopped MCP server exits within five seconds even if its logout hangs\n\nv1.10.2 | 2026-09-15T14:40:30.082Z | user\n\nStopping the MCP server now logs out its vCenter session.\n\nv1.10.1 | 2026-09-15T06:09:08.288Z | 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.10.0 | 2026-09-12T00:14:41.719Z | user\n\nA kubeconfig is credential access on every surface: the kubeconfig tools are no longer annotated read-only and carry a medium risk level, and -o writes the file atomically and owner-only. CLI writes are authorised and audited under their MCP tool names.\n\nv1.9.4 | 2026-09-05T01:06:34.694Z | user\n\na dropped connection no longer keeps itself alive\n\nv1.9.3 | 2026-09-03T02:03:29.090Z | user\n\ntwo documented flags that do not exist\n\nv1.9.2 | 2026-09-02T14:43:07.100Z | user\n\na kubeconfig fetch is not destructive, and never defaulted to ~/.kube/config\n\nv1.9.1 | 2026-08-31T07:25:30.190Z | user\n\n`doctor` as a name for the check that was already there\n\nv1.9.0 | 2026-08-31T00:38:23.775Z | user\n\nfix: run the suite on a non-UTF-8 machine, and stop one skill answering for another\n\nv1.8.15 | 2026-08-30T15:21:00.475Z | 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.8.14 | 2026-08-30T09:34:23.807Z | user\n\nKubeconfig session tokens no longer stored in the audit database. Parameter descriptions now reach the MCP JSON schema (0% -> 100% coverage); additionalProperties closed; vmware-policy floor raised to 1.10.0.\n\nv1.8.13 | 2026-08-30T07:43:27.618Z | user\n\nSix independent copies of the config-path rule reduced to one; the CLI now honours VMWARE_VKS_CONFIG; server.json starts the MCP server; Dockerfile can build.\n\nv1.8.12 | 2026-08-30T01:22:59.542Z | user\n\nA Workload Management failure was labelled a connectivity failure, because one try wrapped three checks. Failures are now attributed to the stage that raised them.\n\nv1.8.11 | 2026-08-28T02:57:38.508Z | user\n\nFixes the server's self-reported version and the advertised tool count; adds a Claude Code plugin manifest.\n\nv1.8.10 | 2026-08-06T09:44:22.322Z | user\n\nSupervisor VM Service reads — VM snapshot / multi-NIC / VM groups via vm-operator CRDs (20→23), runtime-discovered version. Container Service not built (no CRD).\n\nv1.8.9 | 2026-08-01T03:13:05.074Z | user\n\nMoved to vmware-skills GitHub org; MCP Registry namespace → io.github.vmware-skills. Links updated.\n\nv1.8.8 | 2026-07-21T15:43:24.177Z | user\n\nCLI writes now route through the shared guard()+audit_call() core via @guarded, exactly like the MCP tools (HLD I-1/I-8). Requires vmware-policy>=1.8.8.\n\nv1.8.7 | 2026-07-21T11:39:33.391Z | user\n\nRemove read-only switch and approval tiers; read/write authz delegated to RBAC. Plus accumulated fixes since 1.8.5.\n\nv1.8.5 | 2026-07-20T13:03:55.376Z | user\n\nA failure that is returned is now audited as a failure, and certificate/URL detail no longer reaches the agent. Both fixes v1.8.4 announced were incomplete.\n\nv1.8.4 | 2026-07-20T08:25:32.342Z | user\n\nTeaching error messages, domain exceptions no longer redacted on the way to the agent, and tool descriptions that state when to use each tool and what to call next.\n\nv1.8.3 | 2026-07-20T03:42:11.861Z | user\n\nPer-target username can now come from an env var, resolved per access like the password; documented credential variables corrected against what each repo's code actually reads\n\nv1.8.2 | 2026-07-19T18:02:42.737Z | user\n\nMCP server moved into the package namespace — fixes two skills in one environment silently overwriting each other's server; agent-guardrails.md for local/small models now ships in every skill\n\nv1.8.1 | 2026-07-19T11:25:02.837Z | user\n\nRead-only mode now documented on every surface that teaches it (SKILL.md, setup-guide, capabilities) and reported by doctor\n\nv1.8.0 | 2026-07-19T09:42:54.482Z | user\n\nRead-only mode (9 tools withheld — both kubeconfig tools force-classified as writes), list-result envelope, declared environments\n\nv1.7.7 | 2026-07-17T06:56:18.662Z | user\n\nSession-probe eviction fix (dead cached sessions were never evicted; None currentSession now treated as dead) + lockfile mcp 1.28.1 clearing three GHSA HIGH advisories.\n\nv1.7.5 | 2026-07-13T07:17:25.196Z | user\n\nfamily version alignment (no code change)\n\nv1.7.4 | 2026-07-13T04:52:13.130Z | user\n\nFamily version alignment to 1.7.4 (substantive change this cycle is in vmware-monitor: host-check boundary read batching).\n\nv1.7.3 | 2026-07-03T00:48:36.648Z | user\n\nFamily version alignment (v1.7.3)\n\nv1.7.2 | 2026-07-02T14:31:05.090Z | user\n\nGraceful harbor listing + paginated TKC/workload lists\n\nv1.7.1 | 2026-07-02T10:53:14.929Z | user\n\nFamily version alignment with v1.7.1 (AIops/Monitor large-inventory scale fix, issue #31).\n\nv1.7.0 | 2026-06-27T01:01:23.270Z | user\n\nguided init wizard + multi-path auth teaching\n\nv1.6.1 | 2026-06-24T00:00:54.240Z | user\n\nv1.6.1 .env password b64 obfuscation\n\nv1.6.0 | 2026-06-22T09:17:17.687Z | user\n\nv1.6.0 trust architecture: undo tokens + governance harness (budget/audit/risk-tiers)\n\nv1.5.39 | 2026-06-22T00:42:14.703Z | user\n\nv1.5.39: AIops snapshot-delete async + honest timeout (token-burn fix), Storage browse timeout fix; others version-aligned\n\nv1.5.38 | 2026-06-12T07:00:05.132Z | user\n\nbacklog finish: one-command Supervisor auth preflight\n\nv1.5.37 | 2026-06-12T01:58:46.377Z | user\n\nbacklog: fewer Supervisor round-trips\n\nv1.5.36 | 2026-06-11T23:22:15.738Z | user\n\ncorrect Supervisor authentication + safety fixes\n\nv1.5.35 | 2026-06-10T00:45:26.022Z | user\n\nSecurity hardening: safe error handling, TLS/path/permission fixes\n\nv1.5.32 | 2026-06-08T02:47:25.514Z | user\n\nv1.5.32: invented Supervisor REST endpoint + wire-field fixes\n\nv1.5.30 | 2026-06-07T13:23:06.412Z | user\n\nv1.5.30: Glama TDQS tool description quality rewrite\n\nv1.5.29 | 2026-05-29T02:20:04.705Z | user\n\nVCF 9 verification caveat; TKC api_version auto-detection docs; in-memory kubeconfig security note; Python 3.10\n\nv1.5.28 | 2026-05-20T10:00:25.175Z | user\n\nFix subclass() arg 1 must be a class in goose/old-mcp environments. v1.5.25-1.5.27 only addressed PEP 604 X|None -> Optional[X] but kept 'from __future__ import annotations'; under mcp 1.10-1.13 FastMCP's issubclass() on string annotations crashed server load. This release removes the future import. CLAUDE.md pitfall #33 updated.\n\nv1.5.27 | 2026-05-20T06:57:29.949Z | user\n\nLoosen Python requirement to >= 3.10 (was >=3.11). v1.5.25/26 PEP 604 fix already enables 3.10 at runtime; this release lifts pip download/install block.\n\nv1.5.26 | 2026-05-20T06:17:34.787Z | user\n\nMCP server Python 3.10 compatibility (踩坑 #33): PEP 604 X|None → Optional[X] in tool signatures; mcp_cmd Python version guard; mcp[cli]>=1.10\n\nv1.5.23 | 2026-05-19T02:58:19.592Z | user\n\nVCF 9.0 / 9.1 compatibility declared. README version-compat tables updated. Added Official Broadcom References (VCF Python SDK, REST APIs, CLI tools).\n\nv1.5.22 | 2026-05-08T23:25:07.961Z | user\n\nv1.5.22 family alignment for Smithery rollout\n\nv1.5.21 | 2026-05-08T23:20:33.446Z | user\n\nv1.5.21 family alignment + python-multipart 0.0.27\n\nv1.5.20 | 2026-05-08T22:39:54.065Z | user\n\nv1.5.20 family alignment + MCP Registry mcp-name markers\n\nArchive index:\n\nArchive v1.12.0: 8 files, 26185 bytes\n\nFiles: evals/evals.json (1387b), references/agent-guardrails.md (9340b), references/capabilities.md (9864b), references/cli-reference.md (4661b), references/setup-guide.md (10305b), skill-card.md (2696b), SKILL.md (19882b), _meta.json (130b)\n\nFile v1.12.0:SKILL.md\n\n---\nname: vmware-vks\ndescription: >\n  Use this skill whenever the user needs to manage vSphere Kubernetes Service (VKS) — Supervisor clusters, vSphere Namespaces, and TKC cluster lifecycle.\n  Directly handles: check VKS compatibility, create/delete namespaces, create/scale/upgrade/delete TKC clusters, get kubeconfig, check Harbor registry.\n  Always use this skill for \"create Kubernetes cluster\", \"scale workers\", \"upgrade K8s version\", \"create namespace\", \"get kubeconfig\", or any VKS/TKC task.\n  Do NOT use for vanilla VM operations (use vmware-aiops), non-vSphere Kubernetes (e.g., kubeadm, EKS, AKS), or AVI/AKO load balancing (use vmware-avi).\n  For networking use vmware-nsx.\ninstaller:\n  kind: uv\n  package: vmware-vks\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vks\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VKS_CONFIG\",\"VMWARE_VKS_<TARGET>_PASSWORD\",\"VMWARE_VKS_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-VKS\",\"emoji\":\"☸️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). MCP tool calls and remote CLI commands audited to ~/.vmware/audit.db (SQLite, via vmware-policy); write operations also mirrored to ~/.vmware-vks/audit.log.\n  Credentials: Each vCenter target requires a per-target password env var in ~/.vmware-vks/.env following the pattern VMWARE_VKS_<TARGET_NAME_UPPER>_PASSWORD (e.g., target \"vcenter-01\" → VMWARE_VKS_VCENTER_01_PASSWORD). Passwords are never logged, never echoed, never included in audit entries. get_supervisor_kubeconfig and get_tkc_kubeconfig are credential access, not reads: the kubeconfig embeds a Supervisor bearer token (JWT from /wcp/login) that acts as the configured vCenter account until it expires (typically hours, independent of this process). Both are annotated readOnlyHint=false so MCP clients ask before running them; call them only on explicit user request and write the result to an owner-only (0600) file with output_path / -o rather than printing it. The audit log records the call but redacts the returned kubeconfig.\n---\n\n# VMware VKS\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS) under the MIT license.\n\nAI-powered VMware vSphere Kubernetes Service (VKS) management — 23 MCP tools.\n\n> Requires vSphere 8.x+ with Workload Management enabled.\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (monitoring), [vmware-storage](https://github.com/vmware-skills/VMware-Storage) (storage), [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (NSX networking), [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (DFW/firewall), [vmware-aria](https://github.com/vmware-skills/VMware-Aria) (metrics/alerts/capacity), [vmware-avi](https://github.com/vmware-skills/VMware-AVI) (AVI/ALB/AKO), [vmware-harden](https://github.com/vmware-skills/VMware-Harden) (compliance baselines).\n> | [vmware-pilot](../vmware-pilot/SKILL.md) (workflow orchestration) | [vmware-policy](../vmware-policy/SKILL.md) (audit/policy)\n\n## What This Skill Does\n\n| Category | Capabilities | Count |\n|----------|-------------|:-----:|\n| **Supervisor** | Compatibility check, status, storage policies | 3 |\n| **Namespace** | List, get, create with quotas, update, delete with TKC guard, VM classes | 6 |\n| **TKC Clusters** | List, get, versions, create, scale, upgrade, delete with workload guard | 7 |\n| **VM Service** | VM snapshots, VM groups + bootOrder, VM multi-NIC readout (vm-operator CRDs, read-only) | 3 |\n| **Access** | Supervisor kubeconfig, TKC kubeconfig, Harbor registry, storage usage | 4 |\n\n## Quick Install\n\n```bash\nuv tool install vmware-vks==1.12.0\nvmware-vks check\n```\n\n## When to Use This Skill\n\n- Check if vSphere environment supports VKS\n- Create, update, or delete Supervisor Namespaces with resource quotas\n- Deploy, scale, upgrade, or delete TKC (TanzuKubernetesCluster) clusters\n- Get kubeconfig for Supervisor or TKC clusters\n- Check Harbor registry info or storage usage\n\n**Use companion skills for**:\n- VM lifecycle, deployment → `vmware-aiops`\n- Inventory, health, alarms → `vmware-monitor`\n- iSCSI, vSAN, datastore → `vmware-storage`\n- Load balancing, AVI/ALB, AKO, Ingress → `vmware-avi`\n\n## Related Skills — Skill Routing\n\n| User Intent | Recommended Skill |\n|-------------|------------------|\n| Read-only monitoring | **vmware-monitor** |\n| Storage: iSCSI, vSAN | **vmware-storage** |\n| VM lifecycle, deployment | **vmware-aiops** |\n| vSphere Kubernetes Service (vSphere 8.x+) | **vmware-vks** ← this skill |\n| NSX networking: segments, gateways, NAT | **vmware-nsx** |\n| NSX security: DFW rules, security groups | **vmware-nsx-security** |\n| Aria Ops: metrics, alerts, capacity planning | **vmware-aria** |\n| Multi-step workflows with approval | **vmware-pilot** |\n| Compliance baselines (CIS / 等保 / PCI-DSS), drift detection, LLM remediation advisor | **vmware-harden** (`uv tool install vmware-harden`) |\n| Load balancer, AVI, ALB, AKO, Ingress | **vmware-avi** (`uv tool install vmware-avi`) |\n| Audit log query | **vmware-policy** (`vmware-audit` CLI) |\n\n## Common Workflows\n\n### Deploy a New TKC Cluster\n\n**Pre-flight (judgment)**:\n- Supervisor must be vSphere 8.x+ with WCP enabled — `supervisor check` returns pass/fail. If fail, no amount of TKC commands will work; resolve at vSphere/WCP layer first.\n- K8s version: pick a TKR version that's still supported by VMware (not EOL). New clusters on EOL versions look fine until you need a CVE patch and there isn't one.\n- VM class sizing: `best-effort-*` for dev, `guaranteed-*` for prod. A `best-effort` worker can be evicted under host pressure — production workloads need guaranteed.\n- Storage policy: must already exist in vCenter. `list_supervisor_storage_policies` first and pass the returned `policy` ID (not the display name); creating a TKC against a missing policy fails after CP boot, leaving partial state.\n- Control-plane count: `1` for dev, `3` for prod (HA). Cannot upgrade from 1→3 without recreating; choose right the first time.\n- Namespace quota: TKC consumes CP + worker × (cpu, memory) from namespace quota. If quota is too tight, workers fail to schedule with no obvious error.\n- TKC API version: auto-detected at runtime via the K8s discovery API (prefers `cluster.x-k8s.io/v1` when the Supervisor serves it, falls back to `v1beta1` on vSphere 8.0). No manual selection needed; advanced callers can override via the `api_version` parameter on `generate_tkc_yaml()`.\n\n**Steps**:\n1. `vmware-vks supervisor check --target prod` → must pass\n2. `vmware-vks tkc versions -n <ns>` → pick a non-EOL TKR\n3. (If new namespace) `vmware-vks namespace create dev --storage-policy <policy> --cpu <enough-for-cp+workers>` (a dry run by default), then the same with `--apply`\n4. `vmware-vks tkc create dev-cluster -n dev --version <tkr> --control-plane 1 --workers 3 --vm-class best-effort-large` (a dry run by default), then the same with `--apply`\n5. Wait for `phase=running` (typically 10-15 min); do not assume success on apply return\n6. Only if the user asked for cluster access: `vmware-vks kubeconfig get dev-cluster -n dev -o ./kubeconfig` — writes an owner-only file; report the path, never paste the token into the agent context\n\n### Scale Workers for Load Testing\n\n**Judgment**: scaling is fast but reverse-scaling is destructive — workers are deleted, in-flight pods lost. Treat scale-down like a delete.\n\n1. `tkc get dev-cluster -n dev` → record current worker count and any pending pods\n2. **Scale-up**: `tkc scale dev-cluster -n dev --workers 6` → safe, additive operation\n3. Verify new workers reach `Ready` in `kubectl get nodes` before sending traffic\n4. **Scale-down**: drain pods first via `kubectl drain` on the to-be-deleted nodes, THEN `tkc scale --workers 3`. Skipping drain causes pod restarts on remaining nodes — measurable user impact.\n5. Confirm namespace quota leftover supports the new size — quota is enforced at scheduling, not at scale request\n\n### Namespace Resource Management\n\n**Judgment**: quota changes are atomic but consequences are not. Reducing quota below current usage doesn't evict pods — they keep running, but no new pods schedule, looking like a \"namespace is broken\" symptom.\n\n1. `namespace list` → see all namespaces and their phase\n2. `storage -n dev` → check current CPU/memory/storage usage; **never reduce quota below current usage + 20% headroom**\n3. `namespace update dev --cpu <new> --memory <new> --dry-run` → preview, then real\n4. Validate by attempting a small pod scale-up; if it pends with `Insufficient cpu`, quota is still the bottleneck\n\n## Architecture\n\n```\nUser (Natural Language)\n  ↓\nAI Agent (Claude Code / Goose / Cursor)\n  ↓ reads SKILL.md\n  ↓\nvmware-vks CLI  ─── or ───  vmware-vks MCP Server (stdio)\n  │\n  ├─ Layer 1: pyVmomi → vCenter REST API\n  │   Supervisor status, storage policies, Namespace CRUD, VM classes, Harbor\n  │\n  └─ Layer 2: kubernetes client → Supervisor K8s API endpoint\n      TKC CR apply / get / delete  (cluster.x-k8s.io/v1beta1)\n      Kubeconfig bearer token from POST /wcp/login (Supervisor JWT)\n  ↓\nvCenter Server 8.x+ (Workload Management enabled)\n  ↓\nSupervisor Cluster → vSphere Namespaces → TanzuKubernetesCluster\n```\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models (Ollama, Qwen) | **CLI** | ~2K tokens vs ~8K for MCP |\n| Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | Type-safe parameters, structured output |\n\n## MCP Tools (23 — 14 read, 9 write)\n\nAll accept optional `target` parameter to specify a named vCenter.\n\n`list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return the family\nlist envelope — `{items, returned, limit, total, truncated, hint}` — rather than a bare array.\nRead the rows from `items`; `truncated` says whether the listing is complete, so it never has\nto be guessed from the row count. These three read their collection in one un-paged call, so\n`total` is the real count and `truncated` is always `false`.\n\n| Category | Tool | Type |\n|----------|------|:----:|\n| **Supervisor** | `check_vks_compatibility` | Read |\n| | `get_supervisor_status` | Read |\n| | `list_supervisor_storage_policies` | Read |\n| **Namespace** | `list_namespaces` | Read |\n| | `get_namespace` | Read |\n| | `create_namespace` | Write |\n| | `update_namespace` | Write |\n| | `delete_namespace` | Write |\n| | `list_vm_classes` | Read |\n| **TKC** | `list_tkc_clusters` | Read |\n| | `get_tkc_cluster` | Read |\n| | `get_tkc_available_versions` | Read |\n| | `create_tkc_cluster` | Write |\n| | `scale_tkc_cluster` | Write |\n| | `upgrade_tkc_cluster` | Write |\n| | `delete_tkc_cluster` | Write |\n| **VM Service** | `list_vm_snapshots` | Read |\n| | `list_vm_groups` | Read |\n| | `list_vm_network_interfaces` | Read |\n| **Access** | `get_supervisor_kubeconfig` | Write (credential) |\n| | `get_tkc_kubeconfig` | Write (credential) |\n| | `get_harbor_info` | Read |\n| | `list_namespace_storage_usage` | Read |\n\n`create_namespace`, `create_tkc_cluster`, `delete_namespace`, `delete_tkc_cluster` take `confirm` (default False). Without it they change nothing and return `blast_radius`: the spec or YAML plan to be created, or what a delete destroys (TKC clusters, VMs and PVCs in the namespace; node counts and running workloads of a cluster). Show it to the user; pass `confirm=True` only after they decide on what they saw.\n\n`confirm=True` is refused while a blocker stands — TKC clusters inside a namespace, running workloads in a cluster (unless `force=True`), a name already taken — or when any part of the blast radius could not be read. `confirmed` and `dry_run` are deprecated aliases until the next minor release.\n\n**Credential access**: `get_supervisor_kubeconfig` and `get_tkc_kubeconfig` are not reads. The kubeconfig embeds a Supervisor bearer token (JWT from `/wcp/login`) that acts as the configured vCenter account until it expires — typically hours, and not revoked when vmware-vks exits. So:\n- Run them only when the user explicitly asks for a kubeconfig; never auto-run them or fetch one as a side step. Both are annotated `readOnlyHint: false` (MCP clients ask first) and `risk_level: medium` (so an operator's `min_risk_level: medium` deny rule covers them).\n- Always pass `output_path` (MCP) or `-o <path>` (CLI) and report only the path. The file is created owner-only (0600) — also when it replaces an existing file — and a symlink target is refused. Delete it when no longer needed.\n- The audit row records who fetched which kubeconfig, but the returned kubeconfig is redacted (`sensitive_result=True`).\n\n> Full capability details and safety features: see `references/capabilities.md`\n\n## CLI Quick Reference\n\n```bash\n# Supervisor\nvmware-vks check [--config <path>]\nvmware-vks preflight-auth [--target <name>]   # live-validate POST /wcp/login (issue #13)\nvmware-vks supervisor status <cluster-id> [--target <name>]\nvmware-vks supervisor storage-policies [--target <name>]\n\n# Namespace\nvmware-vks namespace list [--target <name>]\nvmware-vks namespace get <name> [--target <name>]\nvmware-vks namespace create <name> --cluster <id> [--cpu <n>] [--memory <mb>] [--storage-policy <name>] [--apply]\nvmware-vks namespace update <name> [--cpu <n>] [--memory <mb>] [--target <name>]\nvmware-vks namespace delete <name> [--target <name>]\n\n# TKC Clusters\nvmware-vks tkc list [-n <namespace>] [--target <name>]\nvmware-vks tkc create <name> -n <ns> [--version <v>] [--workers <n>] [--vm-class <name>] [--apply]\nvmware-vks tkc scale <name> -n <ns> --workers <n> [--pool <name>] [--target <name>]\nvmware-vks tkc upgrade <name> -n <ns> --version <v> [--target <name>]\nvmware-vks tkc delete <name> -n <ns> [--skip-workload-check] [--target <name>]\n\n# Kubeconfig\nvmware-vks kubeconfig supervisor -n <namespace> [-o <path>] [--target <name>]\nvmware-vks kubeconfig get <cluster-name> -n <namespace> [-o <path>] [--target <name>]\n\n# Harbor & Storage\nvmware-vks harbor [--target <name>]\nvmware-vks storage -n <namespace> [--target <name>]\n```\n\n> Full CLI reference with all flags and interactive creation: see `references/cli-reference.md`\n\n## Troubleshooting\n\n### \"VKS not compatible\" error\n\nWorkload Management must be enabled in vCenter. Check: vCenter UI → Workload Management. Requires vSphere 8.x+ with Enterprise Plus or VCF license.\n\n### Namespace creation fails with \"storage policy not found\"\n\nList policies first: `vmware-vks supervisor storage-policies`, then pass the **Policy ID** column value (not the display name) as `--storage-policy`.\n\n### TKC cluster stuck in \"Creating\" phase\n\nCheck Supervisor events in vCenter. Common causes: insufficient resources on ESXi hosts, network issues with NSX-T, or storage policy not available on target datastore.\n\n### Every REST tool returns 401\n\nvCenter keeps two independent session stores, and this skill uses both. Namespace, storage-policy and Supervisor-status tools call the vSphere Automation REST API under `/api`, which authenticates with a session id from `POST https://<vcenter>/api/session` (HTTP Basic on that one call, then the id in a `vmware-api-session-id` header). The pyVmomi SOAP session under `/sdk` is a different store and its key is rejected there — sending it produced a 401 on every REST tool. A 401 is refreshed automatically once; if it persists, check whether a proxy between you and vCenter strips the `vmware-api-session-id` header. A **403**, not a 401, is what an account short of Workload Management permissions gets.\n\n### Validating Supervisor auth (POST /wcp/login)\n\nSupervisor/TKC Kubernetes auth uses a JWT obtained from `POST https://<vcenter>/wcp/login` (HTTP Basic → JSON `session_id` bearer token), not the pyVmomi SOAP session key, and not the `/api/session` id above either — three separate credentials. To validate this end-to-end against your real Supervisor, run:\n\n```bash\nvmware-vks preflight-auth [--target <name>]\n```\n\nIt performs the **real** login (no mocks) and reports, per target: vCenter reachable → `/wcp/login` HTTP status → parseable `session_id` → does the JWT authenticate a trivial Supervisor K8s API call. A healthy result is all four steps `✓ PASS` ending in `target '<name>': /wcp/login auth flow validated end-to-end.` (exit code 0). On failure each step prints a teaching message — e.g. a 404 on `/wcp/login` means the endpoint path differs on your Supervisor version (capture the real path), a 401 on the K8s probe means `session_id` is not the bearer token on your version. It never tracebacks — every failure is status output.\n\n### Kubeconfig retrieval fails\n\nSupervisor API endpoint must be reachable from the machine running vmware-vks. Check firewall rules for port 6443.\n\n### Scale operation has no effect\n\nVerify the cluster is in \"Running\" phase before scaling. Clusters in \"Creating\" or \"Updating\" phase reject scale operations.\n\n### Delete namespace rejected unexpectedly\n\nThe namespace delete guard prevents deletion when TKC clusters exist inside. Delete all TKC clusters in the namespace first, then retry.\n\n## Prerequisites\n\n- vSphere 8.x+ with Workload Management enabled\n- Enterprise Plus or VCF license\n- NSX-T (recommended) or VDS + HAProxy networking\n- Supervisor Cluster configured and running\n\n## Setup\n\n```bash\nuv tool install vmware-vks==1.12.0\nmkdir -p ~/.vmware-vks\nvmware-vks init\n```\n\n> All tools are automatically audited via vmware-policy. Audit logs: `vmware-audit log --last 20`\n\n> Full setup guide, security details, and AI platform compatibility: see `references/setup-guide.md`\n\n## Audit & Safety\n\nOperations are audited via vmware-policy:\n- Every MCP tool call, and every CLI command that reaches vCenter or the Supervisor (`@guarded` writes and credential reads, `@audited` reads), is logged to `~/.vmware/audit.db` (SQLite). The seven namespace/TKC write operations are also mirrored to `~/.vmware-vks/audit.log` (JSON Lines)\n- Policy rules enforced via `~/.vmware/rules.yaml` (deny rules, maintenance windows, risk levels)\n- Risk classification: each tool tagged as low/medium/high/critical\n- View recent operations: `vmware-audit log --last 20`\n- View denied operations: `vmware-audit log --status denied`\n\n**Local files (sensitive, keep owner-only)**: `~/.vmware-vks/.env` holds per-target passwords (b64-obfuscated, not encrypted; created 0600, `vmware-vks doctor` flags a wider mode). `~/.vmware/audit.db` (+ WAL/SHM, 0600 in a 0700 directory) keeps operation history — resource names, parameters, results with credentials redacted — and rotates at 100 MB, keeping 5 archives. `~/.vmware-vks/audit.log` (0600) is never rotated or pruned. Exported kubeconfigs are 0600 and are never cleaned up by the skill. Delete or rotate these yourself per your retention policy.\n\n**In-memory kubeconfig (v1.5.18+)**: for its own API calls the skill builds the Supervisor/TKC kubeconfig as a Python dict and loads it with `load_kube_config_from_dict()`; the bearer token (also cached in process memory, up to 8 h) is never written to a temp file. Only an explicit export (`output_path` / `-o`) puts it on disk.\n\nvmware-policy is automatically installed as a dependency — no manual setup needed.\n\n## License\n\nMIT — [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS)\n\nFile v1.12.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vks\",\n  \"version\": \"1.12.0\",\n  \"publishedAt\": 1789915978167\n}\n\nFile v1.12.0:references/agent-guardrails.md\n\n# Operating vmware-vks with a local / small model\n\nClaude-class models drive this skill without special instruction. Smaller and\nlocally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served\nthrough Goose, Ollama, or OpenShift AI — need explicit operating rules to call\ntools reliably.\n\nThis page exists because an operator wrote those rules by hand first. The\nguardrails below are adapted, with thanks, from the working configuration\n[@juanpf-ha](https://github.com/juanpf-ha) developed while running\nvmware-monitor and vmware-aria against a production vSphere estate with Llama\n3.3 70B FP8 on an on-prem H100\n([VMware-AIops#31](https://github.com/vmware-skills/VMware-AIops/issues/31)). The\ncross-skill rules are identical across this family; the parts below marked\nvmware-vks are specific to this skill.\n\nvmware-vks exposes 23 MCP tools. Two things make it distinctive for a small\nmodel: deleting a namespace or a Tanzu Kubernetes cluster destroys running\nworkloads, and two of its tools hand back live credentials — a kubeconfig\nwhose bearer token acts as the configured vCenter account for hours.\n`get_supervisor_kubeconfig` and `get_tkc_kubeconfig` are credential access, not\nreads: both are annotated `readOnlyHint: false`, so an MCP client that honours\nthe annotation asks before running them.\n\n> **Disclaimer**: This is a community-maintained open-source project and is\n> **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom\n> Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\n---\n\n## First: the rules you no longer need to write\n\nSeveral guardrails from the original configuration are now enforced by the\nskill itself. Prompt instructions are advisory — a model can ignore them.\nThese are structural, so it cannot.\n\n| Guardrail you would otherwise prompt for | Now enforced by |\n|---|---|\n| \"Preview a namespace or cluster creation before applying it\" | **`confirm` defaults to false.** `create_namespace` and `create_tkc_cluster` return `blast_radius` (spec / YAML plan) and change nothing unless `confirm=True`. Preview is the default path, not a habit the model must maintain. |\n| \"Confirm before deleting anything\" | **A bare delete only previews.** `delete_namespace` and `delete_tkc_cluster` return what they would destroy; `confirm=True` is refused while TKC clusters exist inside the namespace, while workloads run (unless `force=True`), or when any part of the blast radius could not be read. |\n| \"Use explicit limits for queries that may return large amounts of data\" | **The list envelope.** `list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. These three read their collection in one un-paged call, so `total` is the real count and `truncated` is always `false`. |\n| \"If a listing came back empty, say so rather than claiming the call failed\" | Same envelope. Empty `items` with `truncated: false` means checked-and-none — a stated result, not a silence the model has to interpret. |\n| \"Log every state change you make\" | **The `@vmware_tool` decorator.** Every write is recorded to `~/.vmware/audit.db` before the model sees the result, and policy rules are evaluated ahead of execution. |\n| \"Don't leave a token lying around in a readable file\" | **Owner-only export.** A kubeconfig written with `output_path` / `-o` is created 0600 — also when it replaces an existing file — and a symlink target is refused. The audit row records the retrieval but redacts the returned kubeconfig. |\n\n---\n\n## The system prompt\n\nEverything below still benefits from being stated explicitly. Copy this into\nyour agent's instruction block.\n\n```text\n## Tool use\n\n- Always call an MCP tool before answering any question about the current\n  VMware environment. Never answer from memory or assumption.\n- Never describe a tool call, and never output a JSON example, instead of\n  executing the tool. If you intend to call a tool, call it.\n- If a tool fails, report the actual error text. Do not complete the answer\n  with assumptions about what the result would have been.\n- Use explicit limits on queries that may return large amounts of data. Do not\n  request unlimited results unless the user asks for them.\n- Namespace, cluster and storage-policy names are exact strings. Resolve them\n  with a list tool before use; do not correct or reformat what the user typed.\n\n## Skill routing\n\n- vmware-vks: Supervisor status and compatibility, vSphere namespaces, VM\n  classes, Tanzu Kubernetes clusters, kubeconfig retrieval, Harbor registry.\n- vmware-monitor: read-only vCenter inventory, hosts, alarms, events. Prefer it\n  for any question that only reads about the underlying vSphere estate.\n- vmware-aiops: VM lifecycle for ordinary VMs, not Supervisor-managed ones.\n- vmware-storage: datastores, iSCSI, vSAN backing the Supervisor.\n- vmware-nsx / vmware-nsx-security: the networking and firewall a TKC sits on.\n- vmware-pilot: multi-step workflows that need approval gates.\n\n## Data fidelity\n\n- Never invent namespaces, clusters, VM classes, storage policies, or node\n  counts. If a tool did not return it, it does not exist for this answer.\n- Preserve the exact phase and condition values the tools return (Creating,\n  Running, Updating, and so on). Do not translate, normalise, or prettify them.\n- A cluster's phase is not its health. Report the phase the tool gave you.\n- If a requested field was not returned, show it as \"not available\". Do not\n  infer it from other fields.\n- Preserve the original order and the full set of fields when the user asks\n  for specific ones.\n- When a response is long, report every item it contains. If a result is\n  truncated, the tool says so explicitly — report the truncation rather than\n  describing the visible subset as the whole.\n\n## Analysis discipline\n\n- Separate observed data from interpretation. State which is which.\n- Do not claim a capacity, scheduling, or networking problem unless the tool\n  output contains explicit supporting evidence.\n- Avoid generic recommendations that are not directly supported by the results.\n\n## Credentials and writes in vmware-vks\n\n- get_supervisor_kubeconfig and get_tkc_kubeconfig return credentials. Call\n  them only when the user explicitly asks for a kubeconfig — never as a step\n  you decided on yourself, and never to \"check access\".\n- Never print a kubeconfig, session token or bearer token into the conversation.\n  Always pass output_path (MCP) or -o (CLI) and report the path only.\n- Storage policies are selected by Policy ID, not display name. Call\n  list_supervisor_storage_policies and use the ID column.\n- Call create_namespace, create_tkc_cluster, delete_namespace and\n  delete_tkc_cluster without confirm first, show the returned blast_radius to\n  the user, and pass confirm=True only after they decide on what they saw.\n- Scale and upgrade operations are rejected unless the cluster is in Running\n  phase. Check the phase before proposing one.\n```\n\n---\n\n## Known failure modes on small models\n\nObserved with Llama 3.3 70B FP8 (Goose, on-prem H100), and useful as a\nchecklist when evaluating any local model against these skills:\n\n| Symptom | Mitigation |\n|---|---|\n| Describes a tool call, or emits a JSON example, instead of executing it | The \"never describe a tool call\" rule above. Also check your harness is not echoing tool schemas into context — models imitate the nearest format they see. |\n| Long tool responses: omits items, or reports \"no data returned\" when data was present | Ask for explicit limits so responses stay small. Check the envelope's `truncated` / `returned` / `total` fields rather than trusting the model's summary — a \"no data\" claim is checkable against `returned`. |\n| Adds generic recommendations unsupported by results | The \"analysis discipline\" rules. |\n| Drops requested fields or reorders results | State the required fields and ordering in the request itself, not only in the system prompt. |\n| Multi-tool workflows take 30–50s end to end | `get_supervisor_status` and `get_tkc_cluster` each answer a whole question in one call — prefer them over rebuilding the same picture from several list tools. |\n| Echoes a kubeconfig into the conversation, leaking a live token into context and logs | The credential rule above. |\n| Passes a storage policy's display name where the Policy ID is required | The `list_supervisor_storage_policies` rule above. The failure text is \"storage policy not found\", which reads like a missing object rather than a wrong identifier. |\n| Reads \"Creating\" as \"created\" and reports success | The \"a cluster's phase is not its health\" rule. Have the model quote the phase verbatim. |\n| Retries a delete that was refused for a stated reason | The refusals are guards: a namespace with clusters in it, a cluster with running workloads. Report the reason instead of retrying with `force`. |\n\n## Reporting results\n\nLocal-model compatibility is an explicit design constraint for this family, and\nthe evidence base is small. If you evaluate a model against this skill —\nQwen, Mistral, Granite, or anything else — a report of what worked and what did\nnot is genuinely useful:\n[github.com/vmware-skills/VMware-VKS/issues](https://github.com/vmware-skills/VMware-VKS/issues).\n\nFile v1.12.0:references/capabilities.md\n\n# Capabilities\n\nDetailed capability breakdown for all 23 MCP tools.\n\n## Automation Level Reference\n\nEach operation is classified by autonomy level per the Enterprise Harness Engineering framework:\n\n| Level | Meaning | Agent autonomy | Examples in this skill |\n|:-:|---|---|---|\n| **L1** | Read-only, raw data | Always auto-run | `check_vks_compatibility`, `get_supervisor_status`, `list_supervisor_storage_policies`, `list_namespaces`, `get_namespace`, TKC list/get, `get_harbor_info`, `list_namespace_storage_usage` |\n| **L2** | Read + analysis / recommendation | Always auto-run | namespace quota analysis, TKC health correlation, storage policy compatibility checks |\n| **Credential** | Returns live access material (bearer token) | **Never auto-run** — only on explicit user request; write to a file, report the path | `get_supervisor_kubeconfig`, `get_tkc_kubeconfig` |\n| **L3** | Single write — user must approve | Only after explicit confirmation; destructive ops require double-confirm + `--dry-run` | `create_namespace`, `update_namespace`, `delete_namespace`, `create_tkc_cluster`, `upgrade_tkc_cluster`, `scale_tkc_cluster`, `delete_tkc_cluster` |\n| **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — TKC fleet upgrades, multi-namespace bootstrapping plans)* |\n| **L5** | Auto-remediation from learned pattern | Pattern library only; requires `risk:low` + `reversible:true` + `repeatable:true` | *(roadmap — candidates: stuck TKC reconciliation, namespace quota bumps)* |\n\n**Notes**:\n- L1/L2 tools are always safe for agents to call without confirmation. Credential tools are not: they are annotated `readOnlyHint: false`, so an MCP client asks before running them.\n- L3 tools always pass through the `@vmware_tool` decorator: connection check → policy check → audit log → double-confirm.\n- Kubeconfig retrieval is credential access. The kubeconfig embeds a Supervisor bearer token (JWT from `/wcp/login`) that acts as the configured vCenter account until it expires — typically hours, not tied to the vmware-vks process. Both tools are `readOnlyHint: false`, `risk_level: medium`, and `sensitive_result=True` (the audit row records the call; the returned kubeconfig is redacted). Always pass `output_path` (MCP) / `-o <path>` (CLI): the file is created owner-only (0600), including when it replaces an existing file, and a symlink target is refused. `output_path` truncates the named file, so `~/.kube/config` would be replaced.\n\n## 1. Supervisor Layer (Read-Only)\n\n| Tool | What it returns |\n|------|----------------|\n| `check_vks_compatibility` | vCenter version (pass/fail for 8.x+), WCP enabled status, network backend type |\n| `get_supervisor_status` | Cluster ID, config status, Kubernetes status, API endpoint URL, network provider, and `kubernetes_version` (read from the `software/clusters` endpoint; null with a `kubernetes_version_hint` if that call fails) |\n| `list_supervisor_storage_policies` | List envelope; `items` holds vCenter storage policies: `policy` (ID), `name`, `description`. Pass the `policy` ID (not the display name) when creating a Namespace or TKC |\n\n**List envelope**: `list_supervisor_storage_policies`, `list_namespaces` and `list_vm_classes`\nreturn `{items, returned, limit, total, truncated, hint}` instead of a bare array, so an agent\ncan tell a complete answer from a first page rather than inferring it (VMware-AIops issue #31).\nAll three fetch their collection in a single un-paged REST call, so `total` is the real count\nand `truncated` is always `false`.\n\n## 2. Namespace Layer\n\n| Operation | CLI | MCP Tool | Confirmation | Details |\n|-----------|-----|----------|:------------:|---------|\n| List all | `namespace list` | `list_namespaces` | -- | Status, resource usage, phase |\n| Get detail | `namespace get <name>` | `get_namespace` | -- | Quotas, storage bindings, role bindings |\n| Create | `namespace create <name> --apply` | `create_namespace` | `confirm` | Preview first; CPU/memory quotas, storage policy |\n| Update quotas | `namespace update <name>` | `update_namespace` | -- | CPU (MHz), memory (MB) |\n| Delete | `namespace delete <name>` | `delete_namespace` | `confirm` | Preview lists TKC clusters, VMs, PVCs; rejects if TKC clusters exist |\n| VM classes | `namespace vm-classes` | `list_vm_classes` | -- | `id`, `cpu_count`, `memory_mb`, `gpu_count` (derived from vGPU + dynamic DirectPath I/O device lists) |\n\n## 3. TKC Layer\n\n| Operation | CLI | MCP Tool | Confirmation | Details |\n|-----------|-----|----------|:------------:|---------|\n| List clusters | `tkc list [-n ns]` | `list_tkc_clusters` | -- | Status, node counts, K8s version |\n| Get detail | `tkc get <name> -n <ns>` | `get_tkc_cluster` | -- | Nodes, versions, health conditions |\n| Available versions | `tkc versions -n <ns>` | `get_tkc_available_versions` | -- | Supported K8s versions for Supervisor |\n| Create | `tkc create <name> -n <ns> --apply` | `create_tkc_cluster` | `confirm` | YAML plan -> confirm -> apply |\n| Scale workers | `tkc scale <name> -n <ns> --workers N` | `scale_tkc_cluster` | -- | Adjust worker node count |\n| Upgrade | `tkc upgrade <name> -n <ns> --version X.Y` | `upgrade_tkc_cluster` | -- | List available versions first |\n| Delete | `tkc delete <name> -n <ns>` | `delete_tkc_cluster` | `confirm` | Preview lists nodes and workloads; rejects if workloads running |\n\n### TKC API Version Auto-Detection (v1.5.18+)\n\nAll TKC operations resolve the `cluster.x-k8s.io` API version at runtime via the Kubernetes discovery API (`/apis`). `_resolve_tkc_version()` walks the Supervisor's served versions for the `cluster.x-k8s.io` group and picks the first match from the preference order:\n\n1. `v1` — used when the Supervisor has promoted Cluster API to v1 (later vSphere / VCF releases).\n2. `v1beta1` — fallback for vSphere 8.0, which is also the default for `generate_tkc_yaml()` when called without an explicit `api_version`.\n\nThe result is cached per vCenter host, so the discovery call happens at most once per session. If discovery fails (e.g. network blip), the code logs a warning and falls back to `v1beta1` rather than throwing.\n\n**Override** — `generate_tkc_yaml()` accepts an optional `api_version` parameter; pass `\"v1\"` (or any future version) explicitly when you want to pin a particular API surface for a generated TKC manifest. Most callers do not need this — auto-detection is the supported path.\n\n## 4. Access Layer\n\n| Tool | What it returns |\n|------|----------------|\n| `get_supervisor_kubeconfig` | **Credential.** Kubeconfig for the Supervisor K8s API (bearer token); inline or written to an owner-only file |\n| `get_tkc_kubeconfig` | **Credential.** Kubeconfig for one TKC cluster (bearer token); inline or written to an owner-only file |\n| `get_harbor_info` | Per registry: `id`, `cluster`, `version`, `url`, `status` (health), `storage_used_mb` — status/storage come from a per-registry detail call and are null if it fails. Never returns credentials |\n| `list_namespace_storage_usage` | PVC list and usage stats per Namespace |\n\n## Safety Features\n\n| Feature | Details |\n|---------|---------|\n| Plan -> Confirm -> Execute -> Log | Structured workflow: show YAML plan, confirm, execute, audit log |\n| Preview Default | The two creates and two deletes take `confirm` (default `False`) -- a call without it returns `blast_radius` and changes nothing |\n| Refusal When Unmeasured | `confirm=True` is refused while a blocker stands or when any part of the blast radius could not be read; `confirmed` / `dry_run` are deprecated aliases |\n| Namespace Delete Guard | Rejects if TKC clusters exist inside -- prevents orphaned clusters |\n| TKC Delete Guard | Rejects if Deployments/StatefulSets/DaemonSets are running -- prevents data loss |\n| Force Override | `force=True` on `delete_tkc_cluster` bypasses workload guard (explicit acknowledgement) |\n| Audit Trail | Every MCP call and every CLI command that reaches vCenter or the Supervisor logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy); write operations also mirrored to `~/.vmware-vks/audit.log`, with timestamp, target, operation, parameters, result, user |\n| Read-Only Majority | 14/23 tools are read-only |\n| SSL Support | `verify_ssl: false` supported for self-signed vCenter certs (enterprise standard) |\n| In-Memory Kubeconfig | For the skill's own API calls the Supervisor/TKC kubeconfig is constructed as a Python dict and loaded via `load_kube_config_from_dict()`; the Supervisor bearer token is never written to a temp file (the pre-v1.5.18 TOCTOU window is gone). Only an explicit export (`output_path` / `-o <path>`) writes it, to an owner-only file. |\n\n## Version Compatibility\n\n| vSphere Version | TKC API | Support |\n|----------------|---------|---------|\n| 8.0 / 8.0U1-U3 | `cluster.x-k8s.io/v1beta1` (ClusterClass) | Full |\n| 9.0 / 9.1 (VCF 9) | `cluster.x-k8s.io/v1` preferred (auto-detected), `v1beta1` fallback | ⚠ Not yet verified — Workload Management API surface in vSphere 9 has not been tested by maintainers. Existing 8.x code paths should work but corner cases may need testing. File issues with `check_vks_compatibility` output if you run this on VCF 9. |\n| 7.0 U3 | `run.tanzu.vmware.com/v1alpha3` | Not supported |\n| 7.0 U1-U2 | `run.tanzu.vmware.com/v1alpha1` | Not supported |\n\n> This skill targets vSphere 8.x+ exclusively. vSphere 7.x uses a different TKC API version -- use `kubectl` directly for 7.x environments. TKC API version is auto-detected at runtime (see \"TKC API Version Auto-Detection\" above).\n\n## Prerequisites\n\n- vCenter Server (no direct ESXi support -- VKS requires vCenter)\n- vSphere Kubernetes Service license (Enterprise Plus or VCF)\n- Workload Management (WCP) enabled on at least one cluster\n- Network backend: NSX (recommended) or VDS + Avi Networks (7.x alternative, 8.x limited)\n\nFile v1.12.0:references/cli-reference.md\n\n# CLI Reference\n\nFull command reference for `vmware-vks` CLI.\n\nAll commands accept an optional `--target <name>` parameter to specify a named vCenter from your config.\n\n## Pre-flight Check\n\n```bash\nvmware-vks check   # or: vmware-vks doctor — same checks, both names\n```\n\nVerifies connectivity, credentials, and WCP status for all configured vCenters (or a specific target).\n\n## Supervisor\n\n```bash\n# Get Supervisor cluster status (ID, API endpoint, K8s version, state)\nvmware-vks supervisor status <cluster-id> [--target <name>]\n\n# List vCenter storage policies (Policy ID / Name / Description).\n# Pass the Policy ID — not the display name — when creating a Namespace or TKC.\nvmware-vks supervisor storage-policies [--target <name>]\n```\n\n## Namespace\n\n```bash\n# List all vSphere Namespaces\nvmware-vks namespace list [--target <name>]\n\n# Get Namespace detail (quotas, storage bindings, role bindings)\nvmware-vks namespace get <name> [--target <name>]\n\n# Create Namespace with resource quotas and storage policy\n# Defaults to dry-run (shows plan). Pass --apply to execute.\nvmware-vks namespace create <name> --cluster <id> \\\n  [--cpu <mhz>] [--memory <mb>] \\\n  [--storage-policy <name>] [--apply]\n\n# Update Namespace CPU/memory quotas\nvmware-vks namespace update <name> \\\n  [--cpu <mhz>] [--memory <mb>] [--target <name>]\n\n# Delete Namespace (rejects if TKC clusters exist inside)\nvmware-vks namespace delete <name> [--target <name>]\n\n# List available VM classes for TKC nodes (ID / CPU / Memory (MB) / GPU)\nvmware-vks namespace vm-classes [--target <name>]\n```\n\n## TKC (TanzuKubernetesCluster)\n\n```bash\n# List TKC clusters (all namespaces or specific)\nvmware-vks tkc list [-n <namespace>] [--target <name>]\n\n# Get TKC cluster detail (nodes, versions, health conditions)\nvmware-vks tkc get <cluster-name> -n <namespace> [--target <name>]\n\n# List available K8s versions for a namespace\nvmware-vks tkc versions -n <namespace> [--target <name>]\n\n# Create TKC cluster (defaults to dry-run, pass --apply to execute)\nvmware-vks tkc create <cluster-name> -n <namespace> \\\n  [--version <k8s-ver>] \\\n  [--control-plane <n>] [--workers <n>] \\\n  [--vm-class <name>] [--storage-policy <name>] \\\n  [--apply]\n\n# Scale worker node count\nvmware-vks tkc scale <cluster-name> -n <namespace> \\\n  --workers <n> [--target <name>]\n\n# Upgrade TKC cluster to a newer K8s version\nvmware-vks tkc upgrade <cluster-name> -n <namespace> \\\n  --version <k8s-ver> [--target <name>]\n\n# Delete TKC cluster (rejects if workloads running, use --force to override)\nvmware-vks tkc delete <cluster-name> -n <namespace> \\\n  [--skip-workload-check] [--target <name>]\n# Asks you to type the cluster name back before it deletes. No bypass flag;\n# --skip-workload-check only skips the running-workload guard.\n```\n\n## Kubeconfig\n\n```bash\n# Get Supervisor-level kubeconfig (stdout, or -o to write a file)\nvmware-vks kubeconfig supervisor -n <namespace> [-o <output-path>] [--target <name>]\n\n# Get TKC cluster kubeconfig (stdout, or -o to write a file)\nvmware-vks kubeconfig get <cluster-name> -n <namespace> \\\n  [-o <output-path>] [--target <name>]\n```\n\nBoth commands are **credential access**: the kubeconfig embeds a Supervisor\nbearer token (JWT from `/wcp/login`) that acts as your vCenter account until it\nexpires (typically hours). Run them only when the user asked for a kubeconfig,\nand pass `-o`: the file is created owner-only (0600), also when it replaces an\nexisting file, and a symlink target is refused. Both are `@guarded`, so the\nretrieval is recorded in `~/.vmware/audit.db` (the token is not). Delete the\nfile when you no longer need it.\n\n## Harbor & Storage\n\n```bash\n# Get Harbor registry info (ID, cluster, version, UI URL, health status,\n# storage used in MB; status/storage are null if the detail call fails)\nvmware-vks harbor [--target <name>]\n\n# List PVC usage statistics per Namespace\nvmware-vks storage -n <namespace> [--target <name>]\n```\n\n## Interactive TKC Creation\n\nWhen parameters are missing, the CLI guides interactively:\n\n```\n$ vmware-vks tkc create my-cluster -n dev\n? K8s version (v1.27 / v1.28 / v1.29): v1.28\n? VM class (best-effort-small / best-effort-large / guaranteed-large): best-effort-large\n? Control plane nodes (1 / 3): 1\n? Worker nodes [3]: 3\n? Storage policy (vsphere-storage / vsphere-gold): vsphere-storage\n\nPlan:\n  Cluster   : my-cluster\n  Namespace : dev\n  K8s       : v1.28.4+vmware.1\n  Control   : 1x best-effort-large\n  Workers   : 3x best-effort-large\n  Storage   : vsphere-storage\n\nApply? [y/N]: y\n```\n\nThe same guided flow applies in MCP: the AI model collects missing params through follow-up questions before generating the YAML and applying.\n\nFile v1.12.0:references/setup-guide.md\n\n# Setup Guide\n\nFull setup, security details, and AI platform compatibility for `vmware-vks`.\n\n## Installation\n\nAll install methods fetch from the same source: [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS) (MIT licensed). We recommend reviewing the source code before installing.\n\n```bash\n# Via Skills.sh (fetches from GitHub)\nnpx skills add vmware-skills/VMware-VKS#v1.12.0\n\n# Via ClawHub (fetches from ClawHub registry snapshot of GitHub)\nclawhub install @zw008/vmware-vks --version 1.12.0\n\n# Via PyPI (recommended for version pinning)\nuv tool install vmware-vks==1.12.0\n```\n\n### Claude Code\n\n`npx skills add` and `clawhub install` both place the skill in Claude Code's skills\ndirectory. To install it manually from a clone:\n\n```bash\nmkdir -p ~/.claude/skills/vmware-vks\ncp -r skills/vmware-vks/. ~/.claude/skills/vmware-vks/\n```\n\nFor tool access (not just skill context), register the MCP server:\n\n```bash\nclaude mcp add vmware-vks -- vmware-vks mcp\n```\n\n### What Gets Installed\n\nThe `vmware-vks` package installs a Python CLI binary and its dependencies (pyVmomi, kubernetes Python client, Typer, Rich, python-dotenv, mcp). No background services or daemons are started during installation.\n\n### Development Install\n\n```bash\ngit clone --branch v1.12.0 https://github.com/vmware-skills/VMware-VKS.git\ncd VMware-VKS\nuv venv && source .venv/bin/activate\nuv pip install -e .\n```\n\n## Version Compatibility\n\n| vSphere / VCF | Support | Notes |\n|---------|---------|-------|\n| 8.0 / 8.0U1-U3 | Full | Workload Management APIs available; TKC uses `cluster.x-k8s.io/v1beta1`. |\n| 9.0 / 9.1 (VCF 9) | ⚠ Not yet verified | Workload Management (Supervisor / WCP) API surface in vSphere 9 has not been tested by maintainers. Existing vSphere 8.x code paths should work — basic CRUD likely works, corner cases may need testing. TKC API version is auto-detected (`v1` preferred when served, otherwise `v1beta1`). File issues with `check_vks_compatibility` output if you run this on VCF 9. |\n| 7.x | Not supported | WCP API surface is different; use vSphere 8.x+. |\n\n## Configuration\n\n```bash\n# 1. Install from PyPI\nuv tool install vmware-vks==1.12.0\n\n# 2. Configure\nmkdir -p ~/.vmware-vks\ncat > ~/.vmware-vks/config.yaml << 'EOF'\ntargets:\n  - name: vcenter01\n    host: vcenter.example.com\n    username: admin@vsphere.local\n    port: 443\n    verify_ssl: false\n    environment: production\nEOF\n\necho \"VMWARE_VKS_VCENTER01_PASSWORD=your_password\" > ~/.vmware-vks/.env\nchmod 600 ~/.vmware-vks/.env\n\n# 3. Verify\nvmware-vks check\n```\n\n**`environment` (optional label)**: policy scopes its rules by this value, so an environment-scoped `deny` rule in `~/.vmware/rules.yaml` can match on it — for example, to freeze state-changing writes on `production`. Any label you like works (`production`, `staging`, `lab`, `dc2-prod`); the target's *name* is not used for it.\n\nA target with no label is simply not matched by such a rule. Read-only operations are never affected either way. Run `vmware-audit policy` to see the rules currently in force.\n\n## MCP Mode (Optional)\n\nFor Claude Code / Cursor users who prefer structured tool calls, add to `~/.claude/settings.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vks\": {\n      \"command\": \"vmware-vks\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"VMWARE_VKS_CONFIG\": \"/Users/you/.vmware-vks/config.yaml\",\n        \"VMWARE_VKS_VCENTER01_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n> v1.5.15+ recommends the single-command form `vmware-vks mcp`. Pre-1.5.15 used\n> `uvx --from vmware-vks vmware-vks-mcp`, which still works but re-resolves from <!-- install-pin: historical -->\n> PyPI on each launch and breaks behind corporate TLS proxies. The legacy\n> `vmware-vks-mcp` entry point is also kept for backward compatibility.\n\n## Usage Mode\n\nChoose the best mode based on your environment:\n\n| Scenario | Recommended Mode | Why |\n|----------|-----------------|-----|\n| **Cloud models** (Claude, GPT-4o, Gemini) | MCP or CLI | Both work well; MCP gives structured JSON I/O |\n| **Local/small models** (Ollama, Llama, Qwen <32B) | **CLI** | Lower token cost (~2K vs ~8K), higher accuracy -- small models struggle with 23 MCP tool schemas |\n| **Token-sensitive workflows** | **CLI** | CLI via SKILL.md uses ~2K tokens; MCP loads ~8K tokens of tool definitions into every conversation |\n| **Automated pipelines / Agent chaining** | **MCP** | Structured JSON input/output, type-safe parameters, no shell parsing |\n\n### Calling Priority\n\n- **MCP-native tools** (Claude Code, Cursor): MCP first, CLI fallback\n- **Local models / Token-sensitive**: CLI first (MCP not needed)\n\n### Password obfuscation at rest\n\nOn first load, any plaintext `*_PASSWORD` value in `.env` is automatically\nrewritten to a grep-safe `b64:<encoded>` form and decoded transparently at\nruntime, so a casual `grep` of the file no longer reveals the password. Values\nare read and written through python-dotenv's own parser, so the stored secret\nnever drifts from what you configured (quotes, inline comments, and trailing\nwhitespace are handled correctly).\n\n> **This is obfuscation, not encryption.** Anyone who can read the file can\n> still decode it. For real secrecy at rest, do not store the password in `.env`\n> at all — inject it from a secret manager (HashiCorp Vault, CyberArk, AWS\n> Secrets Manager, or a Kubernetes Secret) into the `*_PASSWORD` environment\n> variable at process start. The code reads the env var either way.\n\n### Local files, permissions and retention\n\nEverything this skill keeps on disk is sensitive. Nothing is deleted\nautomatically except audit-DB archives beyond the newest five.\n\n| Path | Contents | Permissions | Retention |\n|---|---|---|---|\n| `~/.vmware-vks/.env` | Per-target passwords (`b64:`-obfuscated, not encrypted) | Created 0600 by `vmware-vks init`; `vmware-vks doctor` and every CLI/MCP start warn if it is wider | Until you remove it |\n| `~/.vmware-vks/config.yaml` | Hostnames, usernames, `verify_ssl` — no passwords | Your umask | Until you remove it |\n| `~/.vmware/audit.db` (+ `-wal`, `-shm`) | Every MCP tool call and every `@guarded` CLI command: tool, parameters, result (credentials redacted), status, OS user | 0600, directory 0700 | Rotated at 100 MB; the 5 newest archives are kept |\n| `~/.vmware-vks/audit.log` | JSON-Lines mirror of namespace/TKC write operations | 0600, directory 0700 | Never rotated or pruned |\n| Exported kubeconfig (`output_path` / `-o`) | Supervisor bearer token, valid until the JWT expires (typically hours) | 0600, also when replacing an existing file; symlink targets refused | Never cleaned up — delete it when done |\n\nPrune the audit files according to your own retention policy; for the kubeconfig,\nprefer a short-lived path and delete it after use.\n\n## Read-Only Operation\n\nTo run the agent read-only, give it a read-only vCenter/Supervisor service account (RBAC).\n\n## Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\nThis skill follows a defense-in-depth approach with six security properties:\n\n1. **Source Code** -- MIT-licensed, fully auditable. No obfuscated logic. Source at [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS). The `uv` installer fetches the `vmware-vks` package from PyPI, which is built from this GitHub repository.\n\n2. **Credentials** -- `config.yaml` contains vCenter hostnames and usernames only. Passwords are loaded exclusively from `~/.vmware-vks/.env` (read via `python-dotenv`). Passwords are never logged, never echoed to CLI output, and never included in audit log entries. **Kubeconfig retrieval is credential access**: `get_supervisor_kubeconfig` / `get_tkc_kubeconfig` (CLI: `kubeconfig supervisor` / `kubeconfig get`) return a kubeconfig embedding a Supervisor bearer token (JWT from `POST /wcp/login`) that acts as the configured vCenter account until it expires — typically hours, not tied to the vmware-vks process. Both MCP tools are annotated `readOnlyHint: false` and `risk_level: medium`; run them only on explicit user request and always export with `output_path` / `-o <path>` (owner-only 0600 file) instead of printing the token. Their audit rows redact the returned kubeconfig. **In-memory kubeconfig (v1.5.18+)**: for the skill's own API calls the kubeconfig is built as a Python dict and handed to the kubernetes client via `load_kube_config_from_dict()`, so the token is never written to a temp file; only an explicit export writes it to disk.\n\n3. **Network Scope** -- No webhook, HTTP listener, or inbound network connection is ever started. MCP transport is stdio only. Outbound connections go to the user-configured vCenter, to the Supervisor Kubernetes API endpoint that vCenter reports for the cluster (`api_server_cluster_endpoint`), and — for `delete_tkc_cluster`'s running-workload check only — to that TKC cluster's control-plane endpoint as recorded on the Supervisor.\n\n4. **TLS Verification** -- `verify_ssl: false` is supported for self-signed vCenter certificates (standard in enterprise environments). Set `verify_ssl: true` in config for CA-signed certificates. Applies to both the SOAP API and REST API connections.\n\n5. **Prompt Injection Protection** -- All tool inputs are passed as typed Python parameters (`str`, `int`, `bool`), never interpolated into shell commands. No `eval`, `exec`, or subprocess calls with user-controlled data.\n\n6. **Least Privilege** -- 14/23 tools are read-only. `create_namespace`, `create_tkc_cluster`, `delete_namespace` and `delete_tkc_cluster` preview by default: without `confirm=True` they change nothing and return the blast radius, and `confirm=True` is refused while a blocker stands or part of the blast radius could not be read. The running-workload guard on `delete_tkc_cluster` can only be skipped with `force=True`. All write operations are audit-logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy).\n\n## Supported AI Platforms\n\n| Platform | Status |\n|----------|--------|\n| Claude Code | Native Skill |\n| Goose (Block) | MCP via stdio |\n| Cursor | MCP mode |\n| Continue | MCP mode |\n| VS Code Copilot | MCP mode |\n| Python CLI | Standalone |\n\nFile v1.12.0:skill-card.md\n\n## Description:\n\nvmware-vks helps agents manage vSphere Kubernetes Service environments, including Supervisor checks, vSphere Namespaces, TKC cluster lifecycle tasks, kubeconfig retrieval, Harbor registry checks, and storage usage review.\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, platform engineers, and VMware operators use this skill to inspect VKS readiness and manage vSphere Namespaces and Tanzu Kubernetes clusters through CLI or MCP workflows. It is intended for environments where an agent may need to plan, preview, and execute Kubernetes cluster lifecycle operations against configured vCenter targets.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can administer VMware VKS/TKC resources and may affect namespaces, clusters, and running workloads.\n\nMitigation: Use a least-privilege vCenter account and review each write preview or blast-radius summary before approving execution.\n\nRisk: Kubeconfig retrieval returns live bearer-token credentials for Supervisor or TKC access.\n\nMitigation: Fetch kubeconfigs only on explicit request, write them to short-lived owner-only files, report only the path, and avoid printing tokens into chat.\n\nRisk: Local .env files, exported kubeconfigs, and audit logs can contain sensitive operational data or credentials.\n\nMitigation: Keep these files owner-only, rotate or delete them according to retention policy, and avoid long-lived exported kubeconfig files.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/vmware-vks)\n- [VMware VKS homepage](https://github.com/vmware-skills/VMware-VKS)\n- [Capabilities](artifact/references/capabilities.md)\n- [Setup Guide](artifact/references/setup-guide.md)\n- [CLI Reference](artifact/references/cli-reference.md)\n- [Agent Guardrails](artifact/references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with CLI commands, configuration snippets, and structured MCP tool recommendations]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May direct credential exports to owner-only files and should report file paths rather than secret material.]\n\n## Skill Version(s):\n\n1.12.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\nFile v1.12.0:evals/evals.json\n\n{\n  \"skill_name\": \"vmware-vks\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"Create a new Kubernetes namespace 'dev-team' and deploy a 3-worker TKC cluster running K8s 1.28\",\n      \"expected_output\": \"Namespace created, TKC cluster deployed\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses create_namespace with cluster_id and storage_policy\",\n        \"Uses create_tkc_cluster with k8s_version, worker_count=3\",\n        \"Shows the confirm=False preview (blast_radius) before actual creation\"\n      ]\n    },\n    {\n      \"id\": 2,\n      \"prompt\": \"Scale the production TKC cluster to 5 workers and get me the kubeconfig\",\n      \"expected_output\": \"Cluster scaled, kubeconfig written to a file\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses scale_tkc_cluster with worker_count=5\",\n        \"Uses get_tkc_kubeconfig with output_path to write the kubeconfig to a file\",\n        \"Reports the file path and does not print the kubeconfig or its token\"\n      ]\n    },\n    {\n      \"id\": 3,\n      \"prompt\": \"Is our vSphere cluster ready for Tanzu? Check compatibility and list available K8s versions\",\n      \"expected_output\": \"Compatibility check results and version list\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses check_vks_compatibility\",\n        \"Uses get_tkc_available_versions\",\n        \"Clearly reports whether VKS is supported\"\n      ]\n    }\n  ]\n}\n\nArchive v1.11.0: 8 files, 26092 bytes\n\nFiles: evals/evals.json (1387b), references/agent-guardrails.md (9340b), references/capabilities.md (9864b), references/cli-reference.md (4661b), references/setup-guide.md (10305b), skill-card.md (2522b), SKILL.md (19882b), _meta.json (130b)\n\nFile v1.11.0:SKILL.md\n\n---\nname: vmware-vks\ndescription: >\n  Use this skill whenever the user needs to manage vSphere Kubernetes Service (VKS) — Supervisor clusters, vSphere Namespaces, and TKC cluster lifecycle.\n  Directly handles: check VKS compatibility, create/delete namespaces, create/scale/upgrade/delete TKC clusters, get kubeconfig, check Harbor registry.\n  Always use this skill for \"create Kubernetes cluster\", \"scale workers\", \"upgrade K8s version\", \"create namespace\", \"get kubeconfig\", or any VKS/TKC task.\n  Do NOT use for vanilla VM operations (use vmware-aiops), non-vSphere Kubernetes (e.g., kubeadm, EKS, AKS), or AVI/AKO load balancing (use vmware-avi).\n  For networking use vmware-nsx.\ninstaller:\n  kind: uv\n  package: vmware-vks\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vks\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VKS_CONFIG\",\"VMWARE_VKS_<TARGET>_PASSWORD\",\"VMWARE_VKS_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-VKS\",\"emoji\":\"☸️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). MCP tool calls and remote CLI commands audited to ~/.vmware/audit.db (SQLite, via vmware-policy); write operations also mirrored to ~/.vmware-vks/audit.log.\n  Credentials: Each vCenter target requires a per-target password env var in ~/.vmware-vks/.env following the pattern VMWARE_VKS_<TARGET_NAME_UPPER>_PASSWORD (e.g., target \"vcenter-01\" → VMWARE_VKS_VCENTER_01_PASSWORD). Passwords are never logged, never echoed, never included in audit entries. get_supervisor_kubeconfig and get_tkc_kubeconfig are credential access, not reads: the kubeconfig embeds a Supervisor bearer token (JWT from /wcp/login) that acts as the configured vCenter account until it expires (typically hours, independent of this process). Both are annotated readOnlyHint=false so MCP clients ask before running them; call them only on explicit user request and write the result to an owner-only (0600) file with output_path / -o rather than printing it. The audit log records the call but redacts the returned kubeconfig.\n---\n\n# VMware VKS\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS) under the MIT license.\n\nAI-powered VMware vSphere Kubernetes Service (VKS) management — 23 MCP tools.\n\n> Requires vSphere 8.x+ with Workload Management enabled.\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (monitoring), [vmware-storage](https://github.com/vmware-skills/VMware-Storage) (storage), [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (NSX networking), [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (DFW/firewall), [vmware-aria](https://github.com/vmware-skills/VMware-Aria) (metrics/alerts/capacity), [vmware-avi](https://github.com/vmware-skills/VMware-AVI) (AVI/ALB/AKO), [vmware-harden](https://github.com/vmware-skills/VMware-Harden) (compliance baselines).\n> | [vmware-pilot](../vmware-pilot/SKILL.md) (workflow orchestration) | [vmware-policy](../vmware-policy/SKILL.md) (audit/policy)\n\n## What This Skill Does\n\n| Category | Capabilities | Count |\n|----------|-------------|:-----:|\n| **Supervisor** | Compatibility check, status, storage policies | 3 |\n| **Namespace** | List, get, create with quotas, update, delete with TKC guard, VM classes | 6 |\n| **TKC Clusters** | List, get, versions, create, scale, upgrade, delete with workload guard | 7 |\n| **VM Service** | VM snapshots, VM groups + bootOrder, VM multi-NIC readout (vm-operator CRDs, read-only) | 3 |\n| **Access** | Supervisor kubeconfig, TKC kubeconfig, Harbor registry, storage usage | 4 |\n\n## Quick Install\n\n```bash\nuv tool install vmware-vks==1.11.0\nvmware-vks check\n```\n\n## When to Use This Skill\n\n- Check if vSphere environment supports VKS\n- Create, update, or delete Supervisor Namespaces with resource quotas\n- Deploy, scale, upgrade, or delete TKC (TanzuKubernetesCluster) clusters\n- Get kubeconfig for Supervisor or TKC clusters\n- Check Harbor registry info or storage usage\n\n**Use companion skills for**:\n- VM lifecycle, deployment → `vmware-aiops`\n- Inventory, health, alarms → `vmware-monitor`\n- iSCSI, vSAN, datastore → `vmware-storage`\n- Load balancing, AVI/ALB, AKO, Ingress → `vmware-avi`\n\n## Related Skills — Skill Routing\n\n| User Intent | Recommended Skill |\n|-------------|------------------|\n| Read-only monitoring | **vmware-monitor** |\n| Storage: iSCSI, vSAN | **vmware-storage** |\n| VM lifecycle, deployment | **vmware-aiops** |\n| vSphere Kubernetes Service (vSphere 8.x+) | **vmware-vks** ← this skill |\n| NSX networking: segments, gateways, NAT | **vmware-nsx** |\n| NSX security: DFW rules, security groups | **vmware-nsx-security** |\n| Aria Ops: metrics, alerts, capacity planning | **vmware-aria** |\n| Multi-step workflows with approval | **vmware-pilot** |\n| Compliance baselines (CIS / 等保 / PCI-DSS), drift detection, LLM remediation advisor | **vmware-harden** (`uv tool install vmware-harden`) |\n| Load balancer, AVI, ALB, AKO, Ingress | **vmware-avi** (`uv tool install vmware-avi`) |\n| Audit log query | **vmware-policy** (`vmware-audit` CLI) |\n\n## Common Workflows\n\n### Deploy a New TKC Cluster\n\n**Pre-flight (judgment)**:\n- Supervisor must be vSphere 8.x+ with WCP enabled — `supervisor check` returns pass/fail. If fail, no amount of TKC commands will work; resolve at vSphere/WCP layer first.\n- K8s version: pick a TKR version that's still supported by VMware (not EOL). New clusters on EOL versions look fine until you need a CVE patch and there isn't one.\n- VM class sizing: `best-effort-*` for dev, `guaranteed-*` for prod. A `best-effort` worker can be evicted under host pressure — production workloads need guaranteed.\n- Storage policy: must already exist in vCenter. `list_supervisor_storage_policies` first and pass the returned `policy` ID (not the display name); creating a TKC against a missing policy fails after CP boot, leaving partial state.\n- Control-plane count: `1` for dev, `3` for prod (HA). Cannot upgrade from 1→3 without recreating; choose right the first time.\n- Namespace quota: TKC consumes CP + worker × (cpu, memory) from namespace quota. If quota is too tight, workers fail to schedule with no obvious error.\n- TKC API version: auto-detected at runtime via the K8s discovery API (prefers `cluster.x-k8s.io/v1` when the Supervisor serves it, falls back to `v1beta1` on vSphere 8.0). No manual selection needed; advanced callers can override via the `api_version` parameter on `generate_tkc_yaml()`.\n\n**Steps**:\n1. `vmware-vks supervisor check --target prod` → must pass\n2. `vmware-vks tkc versions -n <ns>` → pick a non-EOL TKR\n3. (If new namespace) `vmware-vks namespace create dev --storage-policy <policy> --cpu <enough-for-cp+workers>` (a dry run by default), then the same with `--apply`\n4. `vmware-vks tkc create dev-cluster -n dev --version <tkr> --control-plane 1 --workers 3 --vm-class best-effort-large` (a dry run by default), then the same with `--apply`\n5. Wait for `phase=running` (typically 10-15 min); do not assume success on apply return\n6. Only if the user asked for cluster access: `vmware-vks kubeconfig get dev-cluster -n dev -o ./kubeconfig` — writes an owner-only file; report the path, never paste the token into the agent context\n\n### Scale Workers for Load Testing\n\n**Judgment**: scaling is fast but reverse-scaling is destructive — workers are deleted, in-flight pods lost. Treat scale-down like a delete.\n\n1. `tkc get dev-cluster -n dev` → record current worker count and any pending pods\n2. **Scale-up**: `tkc scale dev-cluster -n dev --workers 6` → safe, additive operation\n3. Verify new workers reach `Ready` in `kubectl get nodes` before sending traffic\n4. **Scale-down**: drain pods first via `kubectl drain` on the to-be-deleted nodes, THEN `tkc scale --workers 3`. Skipping drain causes pod restarts on remaining nodes — measurable user impact.\n5. Confirm namespace quota leftover supports the new size — quota is enforced at scheduling, not at scale request\n\n### Namespace Resource Management\n\n**Judgment**: quota changes are atomic but consequences are not. Reducing quota below current usage doesn't evict pods — they keep running, but no new pods schedule, looking like a \"namespace is broken\" symptom.\n\n1. `namespace list` → see all namespaces and their phase\n2. `storage -n dev` → check current CPU/memory/storage usage; **never reduce quota below current usage + 20% headroom**\n3. `namespace update dev --cpu <new> --memory <new> --dry-run` → preview, then real\n4. Validate by attempting a small pod scale-up; if it pends with `Insufficient cpu`, quota is still the bottleneck\n\n## Architecture\n\n```\nUser (Natural Language)\n  ↓\nAI Agent (Claude Code / Goose / Cursor)\n  ↓ reads SKILL.md\n  ↓\nvmware-vks CLI  ─── or ───  vmware-vks MCP Server (stdio)\n  │\n  ├─ Layer 1: pyVmomi → vCenter REST API\n  │   Supervisor status, storage policies, Namespace CRUD, VM classes, Harbor\n  │\n  └─ Layer 2: kubernetes client → Supervisor K8s API endpoint\n      TKC CR apply / get / delete  (cluster.x-k8s.io/v1beta1)\n      Kubeconfig bearer token from POST /wcp/login (Supervisor JWT)\n  ↓\nvCenter Server 8.x+ (Workload Management enabled)\n  ↓\nSupervisor Cluster → vSphere Namespaces → TanzuKubernetesCluster\n```\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models (Ollama, Qwen) | **CLI** | ~2K tokens vs ~8K for MCP |\n| Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | Type-safe parameters, structured output |\n\n## MCP Tools (23 — 14 read, 9 write)\n\nAll accept optional `target` parameter to specify a named vCenter.\n\n`list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return the family\nlist envelope — `{items, returned, limit, total, truncated, hint}` — rather than a bare array.\nRead the rows from `items`; `truncated` says whether the listing is complete, so it never has\nto be guessed from the row count. These three read their collection in one un-paged call, so\n`total` is the real count and `truncated` is always `false`.\n\n| Category | Tool | Type |\n|----------|------|:----:|\n| **Supervisor** | `check_vks_compatibility` | Read |\n| | `get_supervisor_status` | Read |\n| | `list_supervisor_storage_policies` | Read |\n| **Namespace** | `list_namespaces` | Read |\n| | `get_namespace` | Read |\n| | `create_namespace` | Write |\n| | `update_namespace` | Write |\n| | `delete_namespace` | Write |\n| | `list_vm_classes` | Read |\n| **TKC** | `list_tkc_clusters` | Read |\n| | `get_tkc_cluster` | Read |\n| | `get_tkc_available_versions` | Read |\n| | `create_tkc_cluster` | Write |\n| | `scale_tkc_cluster` | Write |\n| | `upgrade_tkc_cluster` | Write |\n| | `delete_tkc_cluster` | Write |\n| **VM Service** | `list_vm_snapshots` | Read |\n| | `list_vm_groups` | Read |\n| | `list_vm_network_interfaces` | Read |\n| **Access** | `get_supervisor_kubeconfig` | Write (credential) |\n| | `get_tkc_kubeconfig` | Write (credential) |\n| | `get_harbor_info` | Read |\n| | `list_namespace_storage_usage` | Read |\n\n`create_namespace`, `create_tkc_cluster`, `delete_namespace`, `delete_tkc_cluster` take `confirm` (default False). Without it they change nothing and return `blast_radius`: the spec or YAML plan to be created, or what a delete destroys (TKC clusters, VMs and PVCs in the namespace; node counts and running workloads of a cluster). Show it to the user; pass `confirm=True` only after they decide on what they saw.\n\n`confirm=True` is refused while a blocker stands — TKC clusters inside a namespace, running workloads in a cluster (unless `force=True`), a name already taken — or when any part of the blast radius could not be read. `confirmed` and `dry_run` are deprecated aliases until the next minor release.\n\n**Credential access**: `get_supervisor_kubeconfig` and `get_tkc_kubeconfig` are not reads. The kubeconfig embeds a Supervisor bearer token (JWT from `/wcp/login`) that acts as the configured vCenter account until it expires — typically hours, and not revoked when vmware-vks exits. So:\n- Run them only when the user explicitly asks for a kubeconfig; never auto-run them or fetch one as a side step. Both are annotated `readOnlyHint: false` (MCP clients ask first) and `risk_level: medium` (so an operator's `min_risk_level: medium` deny rule covers them).\n- Always pass `output_path` (MCP) or `-o <path>` (CLI) and report only the path. The file is created owner-only (0600) — also when it replaces an existing file — and a symlink target is refused. Delete it when no longer needed.\n- The audit row records who fetched which kubeconfig, but the returned kubeconfig is redacted (`sensitive_result=True`).\n\n> Full capability details and safety features: see `references/capabilities.md`\n\n## CLI Quick Reference\n\n```bash\n# Supervisor\nvmware-vks check [--config <path>]\nvmware-vks preflight-auth [--target <name>]   # live-validate POST /wcp/login (issue #13)\nvmware-vks supervisor status <cluster-id> [--target <name>]\nvmware-vks supervisor storage-policies [--target <name>]\n\n# Namespace\nvmware-vks namespace list [--target <name>]\nvmware-vks namespace get <name> [--target <name>]\nvmware-vks namespace create <name> --cluster <id> [--cpu <n>] [--memory <mb>] [--storage-policy <name>] [--apply]\nvmware-vks namespace update <name> [--cpu <n>] [--memory <mb>] [--target <name>]\nvmware-vks namespace delete <name> [--target <name>]\n\n# TKC Clusters\nvmware-vks tkc list [-n <namespace>] [--target <name>]\nvmware-vks tkc create <name> -n <ns> [--version <v>] [--workers <n>] [--vm-class <name>] [--apply]\nvmware-vks tkc scale <name> -n <ns> --workers <n> [--pool <name>] [--target <name>]\nvmware-vks tkc upgrade <name> -n <ns> --version <v> [--target <name>]\nvmware-vks tkc delete <name> -n <ns> [--skip-workload-check] [--target <name>]\n\n# Kubeconfig\nvmware-vks kubeconfig supervisor -n <namespace> [-o <path>] [--target <name>]\nvmware-vks kubeconfig get <cluster-name> -n <namespace> [-o <path>] [--target <name>]\n\n# Harbor & Storage\nvmware-vks harbor [--target <name>]\nvmware-vks storage -n <namespace> [--target <name>]\n```\n\n> Full CLI reference with all flags and interactive creation: see `references/cli-reference.md`\n\n## Troubleshooting\n\n### \"VKS not compatible\" error\n\nWorkload Management must be enabled in vCenter. Check: vCenter UI → Workload Management. Requires vSphere 8.x+ with Enterprise Plus or VCF license.\n\n### Namespace creation fails with \"storage policy not found\"\n\nList policies first: `vmware-vks supervisor storage-policies`, then pass the **Policy ID** column value (not the display name) as `--storage-policy`.\n\n### TKC cluster stuck in \"Creating\" phase\n\nCheck Supervisor events in vCenter. Common causes: insufficient resources on ESXi hosts, network issues with NSX-T, or storage policy not available on target datastore.\n\n### Every REST tool returns 401\n\nvCenter keeps two independent session stores, and this skill uses both. Namespace, storage-policy and Supervisor-status tools call the vSphere Automation REST API under `/api`, which authenticates with a session id from `POST https://<vcenter>/api/session` (HTTP Basic on that one call, then the id in a `vmware-api-session-id` header). The pyVmomi SOAP session under `/sdk` is a different store and its key is rejected there — sending it produced a 401 on every REST tool. A 401 is refreshed automatically once; if it persists, check whether a proxy between you and vCenter strips the `vmware-api-session-id` header. A **403**, not a 401, is what an account short of Workload Management permissions gets.\n\n### Validating Supervisor auth (POST /wcp/login)\n\nSupervisor/TKC Kubernetes auth uses a JWT obtained from `POST https://<vcenter>/wcp/login` (HTTP Basic → JSON `session_id` bearer token), not the pyVmomi SOAP session key, and not the `/api/session` id above either — three separate credentials. To validate this end-to-end against your real Supervisor, run:\n\n```bash\nvmware-vks preflight-auth [--target <name>]\n```\n\nIt performs the **real** login (no mocks) and reports, per target: vCenter reachable → `/wcp/login` HTTP status → parseable `session_id` → does the JWT authenticate a trivial Supervisor K8s API call. A healthy result is all four steps `✓ PASS` ending in `target '<name>': /wcp/login auth flow validated end-to-end.` (exit code 0). On failure each step prints a teaching message — e.g. a 404 on `/wcp/login` means the endpoint path differs on your Supervisor version (capture the real path), a 401 on the K8s probe means `session_id` is not the bearer token on your version. It never tracebacks — every failure is status output.\n\n### Kubeconfig retrieval fails\n\nSupervisor API endpoint must be reachable from the machine running vmware-vks. Check firewall rules for port 6443.\n\n### Scale operation has no effect\n\nVerify the cluster is in \"Running\" phase before scaling. Clusters in \"Creating\" or \"Updating\" phase reject scale operations.\n\n### Delete namespace rejected unexpectedly\n\nThe namespace delete guard prevents deletion when TKC clusters exist inside. Delete all TKC clusters in the namespace first, then retry.\n\n## Prerequisites\n\n- vSphere 8.x+ with Workload Management enabled\n- Enterprise Plus or VCF license\n- NSX-T (recommended) or VDS + HAProxy networking\n- Supervisor Cluster configured and running\n\n## Setup\n\n```bash\nuv tool install vmware-vks==1.11.0\nmkdir -p ~/.vmware-vks\nvmware-vks init\n```\n\n> All tools are automatically audited via vmware-policy. Audit logs: `vmware-audit log --last 20`\n\n> Full setup guide, security details, and AI platform compatibility: see `references/setup-guide.md`\n\n## Audit & Safety\n\nOperations are audited via vmware-policy:\n- Every MCP tool call, and every CLI command that reaches vCenter or the Supervisor (`@guarded` writes and credential reads, `@audited` reads), is logged to `~/.vmware/audit.db` (SQLite). The seven namespace/TKC write operations are also mirrored to `~/.vmware-vks/audit.log` (JSON Lines)\n- Policy rules enforced via `~/.vmware/rules.yaml` (deny rules, maintenance windows, risk levels)\n- Risk classification: each tool tagged as low/medium/high/critical\n- View recent operations: `vmware-audit log --last 20`\n- View denied operations: `vmware-audit log --status denied`\n\n**Local files (sensitive, keep owner-only)**: `~/.vmware-vks/.env` holds per-target passwords (b64-obfuscated, not encrypted; created 0600, `vmware-vks doctor` flags a wider mode). `~/.vmware/audit.db` (+ WAL/SHM, 0600 in a 0700 directory) keeps operation history — resource names, parameters, results with credentials redacted — and rotates at 100 MB, keeping 5 archives. `~/.vmware-vks/audit.log` (0600) is never rotated or pruned. Exported kubeconfigs are 0600 and are never cleaned up by the skill. Delete or rotate these yourself per your retention policy.\n\n**In-memory kubeconfig (v1.5.18+)**: for its own API calls the skill builds the Supervisor/TKC kubeconfig as a Python dict and loads it with `load_kube_config_from_dict()`; the bearer token (also cached in process memory, up to 8 h) is never written to a temp file. Only an explicit export (`output_path` / `-o`) puts it on disk.\n\nvmware-policy is automatically installed as a dependency — no manual setup needed.\n\n## License\n\nMIT — [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS)\n\nFile v1.11.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vks\",\n  \"version\": \"1.11.0\",\n  \"publishedAt\": 1789790174946\n}\n\nFile v1.11.0:references/agent-guardrails.md\n\n# Operating vmware-vks with a local / small model\n\nClaude-class models drive this skill without special instruction. Smaller and\nlocally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served\nthrough Goose, Ollama, or OpenShift AI — need explicit operating rules to call\ntools reliably.\n\nThis page exists because an operator wrote those rules by hand first. The\nguardrails below are adapted, with thanks, from the working configuration\n[@juanpf-ha](https://github.com/juanpf-ha) developed while running\nvmware-monitor and vmware-aria against a production vSphere estate with Llama\n3.3 70B FP8 on an on-prem H100\n([VMware-AIops#31](https://github.com/vmware-skills/VMware-AIops/issues/31)). The\ncross-skill rules are identical across this family; the parts below marked\nvmware-vks are specific to this skill.\n\nvmware-vks exposes 23 MCP tools. Two things make it distinctive for a small\nmodel: deleting a namespace or a Tanzu Kubernetes cluster destroys running\nworkloads, and two of its tools hand back live credentials — a kubeconfig\nwhose bearer token acts as the configured vCenter account for hours.\n`get_supervisor_kubeconfig` and `get_tkc_kubeconfig` are credential access, not\nreads: both are annotated `readOnlyHint: false`, so an MCP client that honours\nthe annotation asks before running them.\n\n> **Disclaimer**: This is a community-maintained open-source project and is\n> **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom\n> Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\n---\n\n## First: the rules you no longer need to write\n\nSeveral guardrails from the original configuration are now enforced by the\nskill itself. Prompt instructions are advisory — a model can ignore them.\nThese are structural, so it cannot.\n\n| Guardrail you would otherwise prompt for | Now enforced by |\n|---|---|\n| \"Preview a namespace or cluster creation before applying it\" | **`confirm` defaults to false.** `create_namespace` and `create_tkc_cluster` return `blast_radius` (spec / YAML plan) and change nothing unless `confirm=True`. Preview is the default path, not a habit the model must maintain. |\n| \"Confirm before deleting anything\" | **A bare delete only previews.** `delete_namespace` and `delete_tkc_cluster` return what they would destroy; `confirm=True` is refused while TKC clusters exist inside the namespace, while workloads run (unless `force=True`), or when any part of the blast radius could not be read. |\n| \"Use explicit limits for queries that may return large amounts of data\" | **The list envelope.** `list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. These three read their collection in one un-paged call, so `total` is the real count and `truncated` is always `false`. |\n| \"If a listing came back empty, say so rather than claiming the call failed\" | Same envelope. Empty `items` with `truncated: false` means checked-and-none — a stated result, not a silence the model has to interpret. |\n| \"Log every state change you make\" | **The `@vmware_tool` decorator.** Every write is recorded to `~/.vmware/audit.db` before the model sees the result, and policy rules are evaluated ahead of execution. |\n| \"Don't leave a token lying around in a readable file\" | **Owner-only export.** A kubeconfig written with `output_path` / `-o` is created 0600 — also when it replaces an existing file — and a symlink target is refused. The audit row records the retrieval but redacts the returned kubeconfig. |\n\n---\n\n## The system prompt\n\nEverything below still benefits from being stated explicitly. Copy this into\nyour agent's instruction block.\n\n```text\n## Tool use\n\n- Always call an MCP tool before answering any question about the current\n  VMware environment. Never answer from memory or assumption.\n- Never describe a tool call, and never output a JSON example, instead of\n  executing the tool. If you intend to call a tool, call it.\n- If a tool fails, report the actual error text. Do not complete the answer\n  with assumptions about what the result would have been.\n- Use explicit limits on queries that may return large amounts of data. Do not\n  request unlimited results unless the user asks for them.\n- Namespace, cluster and storage-policy names are exact strings. Resolve them\n  with a list tool before use; do not correct or reformat what the user typed.\n\n## Skill routing\n\n- vmware-vks: Supervisor status and compatibility, vSphere namespaces, VM\n  classes, Tanzu Kubernetes clusters, kubeconfig retrieval, Harbor registry.\n- vmware-monitor: read-only vCenter inventory, hosts, alarms, events. Prefer it\n  for any question that only reads about the underlying vSphere estate.\n- vmware-aiops: VM lifecycle for ordinary VMs, not Supervisor-managed ones.\n- vmware-storage: datastores, iSCSI, vSAN backing the Supervisor.\n- vmware-nsx / vmware-nsx-security: the networking and firewall a TKC sits on.\n- vmware-pilot: multi-step workflows that need approval gates.\n\n## Data fidelity\n\n- Never invent namespaces, clusters, VM classes, storage policies, or node\n  counts. If a tool did not return it, it does not exist for this answer.\n- Preserve the exact phase and condition values the tools return (Creating,\n  Running, Updating, and so on). Do not translate, normalise, or prettify them.\n- A cluster's phase is not its health. Report the phase the tool gave you.\n- If a requested field was not returned, show it as \"not available\". Do not\n  infer it from other fields.\n- Preserve the original order and the full set of fields when the user asks\n  for specific ones.\n- When a response is long, report every item it contains. If a result is\n  truncated, the tool says so explicitly — report the truncation rather than\n  describing the visible subset as the whole.\n\n## Analysis discipline\n\n- Separate observed data from interpretation. State which is which.\n- Do not claim a capacity, scheduling, or networking problem unless the tool\n  output contains explicit supporting evidence.\n- Avoid generic recommendations that are not directly supported by the results.\n\n## Credentials and writes in vmware-vks\n\n- get_supervisor_kubeconfig and get_tkc_kubeconfig return credentials. Call\n  them only when the user explicitly asks for a kubeconfig — never as a step\n  you decided on yourself, and never to \"check access\".\n- Never print a kubeconfig, session token or bearer token into the conversation.\n  Always pass output_path (MCP) or -o (CLI) and report the path only.\n- Storage policies are selected by Policy ID, not display name. Call\n  list_supervisor_storage_policies and use the ID column.\n- Call create_namespace, create_tkc_cluster, delete_namespace and\n  delete_tkc_cluster without confirm first, show the returned blast_radius to\n  the user, and pass confirm=True only after they decide on what they saw.\n- Scale and upgrade operations are rejected unless the cluster is in Running\n  phase. Check the phase before proposing one.\n```\n\n---\n\n## Known failure modes on small models\n\nObserved with Llama 3.3 70B FP8 (Goose, on-prem H100), and useful as a\nchecklist when evaluating any local model against these skills:\n\n| Symptom | Mitigation |\n|---|---|\n| Describes a tool call, or emits a JSON example, instead of executing it | The \"never describe a tool call\" rule above. Also check your harness is not echoing tool schemas into context — models imitate the nearest format they see. |\n| Long tool responses: omits items, or reports \"no data returned\" when data was present | Ask for explicit limits so responses stay small. Check the envelope's `truncated` / `returned` / `total` fields rather than trusting the model's summary — a \"no data\" claim is checkable against `returned`. |\n| Adds generic recommendations unsupported by results | The \"analysis discipline\" rules. |\n| Drops requested fields or reorders results | State the required fields and ordering in the request itself, not only in the system prompt. |\n| Multi-tool workflows take 30–50s end to end | `get_supervisor_status` and `get_tkc_cluster` each answer a whole question in one call — prefer them over rebuilding the same picture from several list tools. |\n| Echoes a kubeconfig into the conversation, leaking a live token into context and logs | The credential rule above. |\n| Passes a storage policy's display name where the Policy ID is required | The `list_supervisor_storage_policies` rule above. The failure text is \"storage policy not found\", which reads like a missing object rather than a wrong identifier. |\n| Reads \"Creating\" as \"created\" and reports success | The \"a cluster's phase is not its health\" rule. Have the model quote the phase verbatim. |\n| Retries a delete that was refused for a stated reason | The refusals are guards: a namespace with clusters in it, a cluster with running workloads. Report the reason instead of retrying with `force`. |\n\n## Reporting results\n\nLocal-model compatibility is an explicit design constraint for this family, and\nthe evidence base is small. If you evaluate a model against this skill —\nQwen, Mistral, Granite, or anything else — a report of what worked and what did\nnot is genuinely useful:\n[github.com/vmware-skills/VMware-VKS/issues](https://github.com/vmware-skills/VMware-VKS/issues).\n\nFile v1.11.0:references/capabilities.md\n\n# Capabilities\n\nDetailed capability breakdown for all 23 MCP tools.\n\n## Automation Level Reference\n\nEach operation is classified by autonomy level per the Enterprise Harness Engineering framework:\n\n| Level | Meaning | Agent autonomy | Examples in this skill |\n|:-:|---|---|---|\n| **L1** | Read-only, raw data | Always auto-run | `check_vks_compatibility`, `get_supervisor_status`, `list_supervisor_storage_policies`, `list_namespaces`, `get_namespace`, TKC list/get, `get_harbor_info`, `list_namespace_storage_usage` |\n| **L2** | Read + analysis / recommendation | Always auto-run | namespace quota analysis, TKC health correlation, storage policy compatibility checks |\n| **Credential** | Returns live access material (bearer token) | **Never auto-run** — only on explicit user request; write to a file, report the path | `get_supervisor_kubeconfig`, `get_tkc_kubeconfig` |\n| **L3** | Single write — user must approve | Only after explicit confirmation; destructive ops require double-confirm + `--dry-run` | `create_namespace`, `update_namespace`, `delete_namespace`, `create_tkc_cluster`, `upgrade_tkc_cluster`, `scale_tkc_cluster`, `delete_tkc_cluster` |\n| **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — TKC fleet upgrades, multi-namespace bootstrapping plans)* |\n| **L5** | Auto-remediation from learned pattern | Pattern library only; requires `risk:low` + `reversible:true` + `repeatable:true` | *(roadmap — candidates: stuck TKC reconciliation, namespace quota bumps)* |\n\n**Notes**:\n- L1/L2 tools are always safe for agents to call without confirmation. Credential tools are not: they are annotated `readOnlyHint: false`, so an MCP client asks before running them.\n- L3 tools always pass through the `@vmware_tool` decorator: connection check → policy check → audit log → double-confirm.\n- Kubeconfig retrieval is credential access. The kubeconfig embeds a Supervisor bearer token (JWT from `/wcp/login`) that acts as the configured vCenter account until it expires — typically hours, not tied to the vmware-vks process. Both tools are `readOnlyHint: false`, `risk_level: medium`, and `sensitive_result=True` (the audit row records the call; the returned kubeconfig is redacted). Always pass `output_path` (MCP) / `-o <path>` (CLI): the file is created owner-only (0600), including when it replaces an existing file, and a symlink target is refused. `output_path` truncates the named file, so `~/.kube/config` would be replaced.\n\n## 1. Supervisor Layer (Read-Only)\n\n| Tool | What it returns |\n|------|----------------|\n| `check_vks_compatibility` | vCenter version (pass/fail for 8.x+), WCP enabled status, network backend type |\n| `get_supervisor_status` | Cluster ID, config status, Kubernetes status, API endpoint URL, network provider, and `kubernetes_version` (read from the `software/clusters` endpoint; null with a `kubernetes_version_hint` if that call fails) |\n| `list_supervisor_storage_policies` | List envelope; `items` holds vCenter storage policies: `policy` (ID), `name`, `description`. Pass the `policy` ID (not the display name) when creating a Namespace or TKC |\n\n**List envelope**: `list_supervisor_storage_policies`, `list_namespaces` and `list_vm_classes`\nreturn `{items, returned, limit, total, truncated, hint}` instead of a bare array, so an agent\ncan tell a complete answer from a first page rather than inferring it (VMware-AIops issue #31).\nAll three fetch their collection in a single un-paged REST call, so `total` is the real count\nand `truncated` is always `false`.\n\n## 2. Namespace Layer\n\n| Operation | CLI | MCP Tool | Confirmation | Details |\n|-----------|-----|----------|:------------:|---------|\n| List all | `namespace list` | `list_namespaces` | -- | Status, resource usage, phase |\n| Get detail | `namespace get <name>` | `get_namespace` | -- | Quotas, storage bindings, role bindings |\n| Create | `namespace create <name> --apply` | `create_namespace` | `confirm` | Preview first; CPU/memory quotas, storage policy |\n| Update quotas | `namespace update <name>` | `update_namespace` | -- | CPU (MHz), memory (MB) |\n| Delete | `namespace delete <name>` | `delete_namespace` | `confirm` | Preview lists TKC clusters, VMs, PVCs; rejects if TKC clusters exist |\n| VM classes | `namespace vm-classes` | `list_vm_classes` | -- | `id`, `cpu_count`, `memory_mb`, `gpu_count` (derived from vGPU + dynamic DirectPath I/O device lists) |\n\n## 3. TKC Layer\n\n| Operation | CLI | MCP Tool | Confirmation | Details |\n|-----------|-----|----------|:------------:|---------|\n| List clusters | `tkc list [-n ns]` | `list_tkc_clusters` | -- | Status, node counts, K8s version |\n| Get detail | `tkc get <name> -n <ns>` | `get_tkc_cluster` | -- | Nodes, versions, health conditions |\n| Available versions | `tkc versions -n <ns>` | `get_tkc_available_versions` | -- | Supported K8s versions for Supervisor |\n| Create | `tkc create <name> -n <ns> --apply` | `create_tkc_cluster` | `confirm` | YAML plan -> confirm -> apply |\n| Scale workers | `tkc scale <name> -n <ns> --workers N` | `scale_tkc_cluster` | -- | Adjust worker node count |\n| Upgrade | `tkc upgrade <name> -n <ns> --version X.Y` | `upgrade_tkc_cluster` | -- | List available versions first |\n| Delete | `tkc delete <name> -n <ns>` | `delete_tkc_cluster` | `confirm` | Preview lists nodes and workloads; rejects if workloads running |\n\n### TKC API Version Auto-Detection (v1.5.18+)\n\nAll TKC operations resolve the `cluster.x-k8s.io` API version at runtime via the Kubernetes discovery API (`/apis`). `_resolve_tkc_version()` walks the Supervisor's served versions for the `cluster.x-k8s.io` group and picks the first match from the preference order:\n\n1. `v1` — used when the Supervisor has promoted Cluster API to v1 (later vSphere / VCF releases).\n2. `v1beta1` — fallback for vSphere 8.0, which is also the default for `generate_tkc_yaml()` when called without an explicit `api_version`.\n\nThe result is cached per vCenter host, so the discovery call happens at most once per session. If discovery fails (e.g. network blip), the code logs a warning and falls back to `v1beta1` rather than throwing.\n\n**Override** — `generate_tkc_yaml()` accepts an optional `api_version` parameter; pass `\"v1\"` (or any future version) explicitly when you want to pin a particular API surface for a generated TKC manifest. Most callers do not need this — auto-detection is the supported path.\n\n## 4. Access Layer\n\n| Tool | What it returns |\n|------|----------------|\n| `get_supervisor_kubeconfig` | **Credential.** Kubeconfig for the Supervisor K8s API (bearer token); inline or written to an owner-only file |\n| `get_tkc_kubeconfig` | **Credential.** Kubeconfig for one TKC cluster (bearer token); inline or written to an owner-only file |\n| `get_harbor_info` | Per registry: `id`, `cluster`, `version`, `url`, `status` (health), `storage_used_mb` — status/storage come from a per-registry detail call and are null if it fails. Never returns credentials |\n| `list_namespace_storage_usage` | PVC list and usage stats per Namespace |\n\n## Safety Features\n\n| Feature | Details |\n|---------|---------|\n| Plan -> Confirm -> Execute -> Log | Structured workflow: show YAML plan, confirm, execute, audit log |\n| Preview Default | The two creates and two deletes take `confirm` (default `False`) -- a call without it returns `blast_radius` and changes nothing |\n| Refusal When Unmeasured | `confirm=True` is refused while a blocker stands or when any part of the blast radius could not be read; `confirmed` / `dry_run` are deprecated aliases |\n| Namespace Delete Guard | Rejects if TKC clusters exist inside -- prevents orphaned clusters |\n| TKC Delete Guard | Rejects if Deployments/StatefulSets/DaemonSets are running -- prevents data loss |\n| Force Override | `force=True` on `delete_tkc_cluster` bypasses workload guard (explicit acknowledgement) |\n| Audit Trail | Every MCP call and every CLI command that reaches vCenter or the Supervisor logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy); write operations also mirrored to `~/.vmware-vks/audit.log`, with timestamp, target, operation, parameters, result, user |\n| Read-Only Majority | 14/23 tools are read-only |\n| SSL Support | `verify_ssl: false` supported for self-signed vCenter certs (enterprise standard) |\n| In-Memory Kubeconfig | For the skill's own API calls the Supervisor/TKC kubeconfig is constructed as a Python dict and loaded via `load_kube_config_from_dict()`; the Supervisor bearer token is never written to a temp file (the pre-v1.5.18 TOCTOU window is gone). Only an explicit export (`output_path` / `-o <path>`) writes it, to an owner-only file. |\n\n## Version Compatibility\n\n| vSphere Version | TKC API | Support |\n|----------------|---------|---------|\n| 8.0 / 8.0U1-U3 | `cluster.x-k8s.io/v1beta1` (ClusterClass) | Full |\n| 9.0 / 9.1 (VCF 9) | `cluster.x-k8s.io/v1` preferred (auto-detected), `v1beta1` fallback | ⚠ Not yet verified — Workload Management API surface in vSphere 9 has not been tested by maintainers. Existing 8.x code paths should work but corner cases may need testing. File issues with `check_vks_compatibility` output if you run this on VCF 9. |\n| 7.0 U3 | `run.tanzu.vmware.com/v1alpha3` | Not supported |\n| 7.0 U1-U2 | `run.tanzu.vmware.com/v1alpha1` | Not supported |\n\n> This skill targets vSphere 8.x+ exclusively. vSphere 7.x uses a different TKC API version -- use `kubectl` directly for 7.x environments. TKC API version is auto-detected at runtime (see \"TKC API Version Auto-Detection\" above).\n\n## Prerequisites\n\n- vCenter Server (no direct ESXi support -- VKS requires vCenter)\n- vSphere Kubernetes Service license (Enterprise Plus or VCF)\n- Workload Management (WCP) enabled on at least one cluster\n- Network backend: NSX (recommended) or VDS + Avi Networks (7.x alternative, 8.x limited)\n\nFile v1.11.0:references/cli-reference.md\n\n# CLI Reference\n\nFull command reference for `vmware-vks` CLI.\n\nAll commands accept an optional `--target <name>` parameter to specify a named vCenter from your config.\n\n## Pre-flight Check\n\n```bash\nvmware-vks check   # or: vmware-vks doctor — same checks, both names\n```\n\nVerifies connectivity, credentials, and WCP status for all configured vCenters (or a specific target).\n\n## Supervisor\n\n```bash\n# Get Supervisor cluster status (ID, API endpoint, K8s version, state)\nvmware-vks supervisor status <cluster-id> [--target <name>]\n\n# List vCenter storage policies (Policy ID / Name / Description).\n# Pass the Policy ID — not the display name — when creating a Namespace or TKC.\nvmware-vks supervisor storage-policies [--target <name>]\n```\n\n## Namespace\n\n```bash\n# List all vSphere Namespaces\nvmware-vks namespace list [--target <name>]\n\n# Get Namespace detail (quotas, storage bindings, role bindings)\nvmware-vks namespace get <name> [--target <name>]\n\n# Create Namespace with resource quotas and storage policy\n# Defaults to dry-run (shows plan). Pass --apply to execute.\nvmware-vks namespace create <name> --cluster <id> \\\n  [--cpu <mhz>] [--memory <mb>] \\\n  [--storage-policy <name>] [--apply]\n\n# Update Namespace CPU/memory quotas\nvmware-vks namespace update <name> \\\n  [--cpu <mhz>] [--memory <mb>] [--target <name>]\n\n# Delete Namespace (rejects if TKC clusters exist inside)\nvmware-vks namespace delete <name> [--target <name>]\n\n# List available VM classes for TKC nodes (ID / CPU / Memory (MB) / GPU)\nvmware-vks namespace vm-classes [--target <name>]\n```\n\n## TKC (TanzuKubernetesCluster)\n\n```bash\n# List TKC clusters (all namespaces or specific)\nvmware-vks tkc list [-n <namespace>] [--target <name>]\n\n# Get TKC cluster detail (nodes, versions, health conditions)\nvmware-vks tkc get <cluster-name> -n <namespace> [--target <name>]\n\n# List available K8s versions for a namespace\nvmware-vks tkc versions -n <namespace> [--target <name>]\n\n# Create TKC cluster (defaults to dry-run, pass --apply to execute)\nvmware-vks tkc create <cluster-name> -n <namespace> \\\n  [--version <k8s-ver>] \\\n  [--control-plane <n>] [--workers <n>] \\\n  [--vm-class <name>] [--storage-policy <name>] \\\n  [--apply]\n\n# Scale worker node count\nvmware-vks tkc scale <cluster-name> -n <namespace> \\\n  --workers <n> [--target <name>]\n\n# Upgrade TKC cluster to a newer K8s version\nvmware-vks tkc upgrade <cluster-name> -n <namespace> \\\n  --version <k8s-ver> [--target <name>]\n\n# Delete TKC cluster (rejects if workloads running, use --force to override)\nvmware-vks tkc delete <cluster-name> -n <namespace> \\\n  [--skip-workload-check] [--target <name>]\n# Asks you to type the cluster name back before it deletes. No bypass flag;\n# --skip-workload-check only skips the running-workload guard.\n```\n\n## Kubeconfig\n\n```bash\n# Get Supervisor-level kubeconfig (stdout, or -o to write a file)\nvmware-vks kubeconfig supervisor -n <namespace> [-o <output-path>] [--target <name>]\n\n# Get TKC cluster kubeconfig (stdout, or -o to write a file)\nvmware-vks kubeconfig get <cluster-name> -n <namespace> \\\n  [-o <output-path>] [--target <name>]\n```\n\nBoth commands are **credential access**: the kubeconfig embeds a Supervisor\nbearer token (JWT from `/wcp/login`) that acts as your vCenter account until it\nexpires (typically hours). Run them only when the user asked for a kubeconfig,\nand pass `-o`: the file is created owner-only (0600), also when it replaces an\nexisting file, and a symlink target is refused. Both are `@guarded`, so the\nretrieval is recorded in `~/.vmware/audit.db` (the token is not). Delete the\nfile when you no longer need it.\n\n## Harbor & Storage\n\n```bash\n# Get Harbor registry info (ID, cluster, version, UI URL, health status,\n# storage used in MB; status/storage are null if the detail call fails)\nvmware-vks harbor [--target <name>]\n\n# List PVC usage statistics per Namespace\nvmware-vks storage -n <namespace> [--target <name>]\n```\n\n## Interactive TKC Creation\n\nWhen parameters are missing, the CLI guides interactively:\n\n```\n$ vmware-vks tkc create my-cluster -n dev\n? K8s version (v1.27 / v1.28 / v1.29): v1.28\n? VM class (best-effort-small / best-effort-large / guaranteed-large): best-effort-large\n? Control plane nodes (1 / 3): 1\n? Worker nodes [3]: 3\n? Storage policy (vsphere-storage / vsphere-gold): vsphere-storage\n\nPlan:\n  Cluster   : my-cluster\n  Namespace : dev\n  K8s       : v1.28.4+vmware.1\n  Control   : 1x best-effort-large\n  Workers   : 3x best-effort-large\n  Storage   : vsphere-storage\n\nApply? [y/N]: y\n```\n\nThe same guided flow applies in MCP: the AI model collects missing params through follow-up questions before generating the YAML and applying.\n\nFile v1.11.0:references/setup-guide.md\n\n# Setup Guide\n\nFull setup, security details, and AI platform compatibility for `vmware-vks`.\n\n## Installation\n\nAll install methods fetch from the same source: [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS) (MIT licensed). We recommend reviewing the source code before installing.\n\n```bash\n# Via Skills.sh (fetches from GitHub)\nnpx skills add vmware-skills/VMware-VKS#v1.11.0\n\n# Via ClawHub (fetches from ClawHub registry snapshot of GitHub)\nclawhub install @zw008/vmware-vks --version 1.11.0\n\n# Via PyPI (recommended for version pinning)\nuv tool install vmware-vks==1.11.0\n```\n\n### Claude Code\n\n`npx skills add` and `clawhub install` both place the skill in Claude Code's skills\ndirectory. To install it manually from a clone:\n\n```bash\nmkdir -p ~/.claude/skills/vmware-vks\ncp -r skills/vmware-vks/. ~/.claude/skills/vmware-vks/\n```\n\nFor tool access (not just skill context), register the MCP server:\n\n```bash\nclaude mcp add vmware-vks -- vmware-vks mcp\n```\n\n### What Gets Installed\n\nThe `vmware-vks` package installs a Python CLI binary and its dependencies (pyVmomi, kubernetes Python client, Typer, Rich, python-dotenv, mcp). No background services or daemons are started during installation.\n\n### Development Install\n\n```bash\ngit clone --branch v1.11.0 https://github.com/vmware-skills/VMware-VKS.git\ncd VMware-VKS\nuv venv && source .venv/bin/activate\nuv pip install -e .\n```\n\n## Version Compatibility\n\n| vSphere / VCF | Support | Notes |\n|---------|---------|-------|\n| 8.0 / 8.0U1-U3 | Full | Workload Management APIs available; TKC uses `cluster.x-k8s.io/v1beta1`. |\n| 9.0 / 9.1 (VCF 9) | ⚠ Not yet verified | Workload Management (Supervisor / WCP) API surface in vSphere 9 has not been tested by maintainers. Existing vSphere 8.x code paths should work — basic CRUD likely works, corner cases may need testing. TKC API version is auto-detected (`v1` preferred when served, otherwise `v1beta1`). File issues with `check_vks_compatibility` output if you run this on VCF 9. |\n| 7.x | Not supported | WCP API surface is different; use vSphere 8.x+. |\n\n## Configuration\n\n```bash\n# 1. Install from PyPI\nuv tool install vmware-vks==1.11.0\n\n# 2. Configure\nmkdir -p ~/.vmware-vks\ncat > ~/.vmware-vks/config.yaml << 'EOF'\ntargets:\n  - name: vcenter01\n    host: vcenter.example.com\n    username: admin@vsphere.local\n    port: 443\n    verify_ssl: false\n    environment: production\nEOF\n\necho \"VMWARE_VKS_VCENTER01_PASSWORD=your_password\" > ~/.vmware-vks/.env\nchmod 600 ~/.vmware-vks/.env\n\n# 3. Verify\nvmware-vks check\n```\n\n**`environment` (optional label)**: policy scopes its rules by this value, so an environment-scoped `deny` rule in `~/.vmware/rules.yaml` can match on it — for example, to freeze state-changing writes on `production`. Any label you like works (`production`, `staging`, `lab`, `dc2-prod`); the target's *name* is not used for it.\n\nA target with no label is simply not matched by such a rule. Read-only operations are never affected either way. Run `vmware-audit policy` to see the rules currently in force.\n\n## MCP Mode (Optional)\n\nFor Claude Code / Cursor users who prefer structured tool calls, add to `~/.claude/settings.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"vmware-vks\": {\n      \"command\": \"vmware-vks\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"VMWARE_VKS_CONFIG\": \"/Users/you/.vmware-vks/config.yaml\",\n        \"VMWARE_VKS_VCENTER01_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n> v1.5.15+ recommends the single-command form `vmware-vks mcp`. Pre-1.5.15 used\n> `uvx --from vmware-vks vmware-vks-mcp`, which still works but re-resolves from <!-- install-pin: historical -->\n> PyPI on each launch and breaks behind corporate TLS proxies. The legacy\n> `vmware-vks-mcp` entry point is also kept for backward compatibility.\n\n## Usage Mode\n\nChoose the best mode based on your environment:\n\n| Scenario | Recommended Mode | Why |\n|----------|-----------------|-----|\n| **Cloud models** (Claude, GPT-4o, Gemini) | MCP or CLI | Both work well; MCP gives structured JSON I/O |\n| **Local/small models** (Ollama, Llama, Qwen <32B) | **CLI** | Lower token cost (~2K vs ~8K), higher accuracy -- small models struggle with 23 MCP tool schemas |\n| **Token-sensitive workflows** | **CLI** | CLI via SKILL.md uses ~2K tokens; MCP loads ~8K tokens of tool definitions into every conversation |\n| **Automated pipelines / Agent chaining** | **MCP** | Structured JSON input/output, type-safe parameters, no shell parsing |\n\n### Calling Priority\n\n- **MCP-native tools** (Claude Code, Cursor): MCP first, CLI fallback\n- **Local models / Token-sensitive**: CLI first (MCP not needed)\n\n### Password obfuscation at rest\n\nOn first load, any plaintext `*_PASSWORD` value in `.env` is automatically\nrewritten to a grep-safe `b64:<encoded>` form and decoded transparently at\nruntime, so a casual `grep` of the file no longer reveals the password. Values\nare read and written through python-dotenv's own parser, so the stored secret\nnever drifts from what you configured (quotes, inline comments, and trailing\nwhitespace are handled correctly).\n\n> **This is obfuscation, not encryption.** Anyone who can read the file can\n> still decode it. For real secrecy at rest, do not store the password in `.env`\n> at all — inject it from a secret manager (HashiCorp Vault, CyberArk, AWS\n> Secrets Manager, or a Kubernetes Secret) into the `*_PASSWORD` environment\n> variable at process start. The code reads the env var either way.\n\n### Local files, permissions and retention\n\nEverything this skill keeps on disk is sensitive. Nothing is deleted\nautomatically except audit-DB archives beyond the newest five.\n\n| Path | Contents | Permissions | Retention |\n|---|---|---|---|\n| `~/.vmware-vks/.env` | Per-target passwords (`b64:`-obfuscated, not encrypted) | Created 0600 by `vmware-vks init`; `vmware-vks doctor` and every CLI/MCP start warn if it is wider | Until you remove it |\n| `~/.vmware-vks/config.yaml` | Hostnames, usernames, `verify_ssl` — no passwords | Your umask | Until you remove it |\n| `~/.vmware/audit.db` (+ `-wal`, `-shm`) | Every MCP tool call and every `@guarded` CLI command: tool, parameters, result (credentials redacted), status, OS user | 0600, directory 0700 | Rotated at 100 MB; the 5 newest archives are kept |\n| `~/.vmware-vks/audit.log` | JSON-Lines mirror of namespace/TKC write operations | 0600, directory 0700 | Never rotated or pruned |\n| Exported kubeconfig (`output_path` / `-o`) | Supervisor bearer token, valid until the JWT expires (typically hours) | 0600, also when replacing an existing file; symlink targets refused | Never cleaned up — delete it when done |\n\nPrune the audit files according to your own retention policy; for the kubeconfig,\nprefer a short-lived path and delete it after use.\n\n## Read-Only Operation\n\nTo run the agent read-only, give it a read-only vCenter/Supervisor service account (RBAC).\n\n## Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\nThis skill follows a defense-in-depth approach with six security properties:\n\n1. **Source Code** -- MIT-licensed, fully auditable. No obfuscated logic. Source at [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS). The `uv` installer fetches the `vmware-vks` package from PyPI, which is built from this GitHub repository.\n\n2. **Credentials** -- `config.yaml` contains vCenter hostnames and usernames only. Passwords are loaded exclusively from `~/.vmware-vks/.env` (read via `python-dotenv`). Passwords are never logged, never echoed to CLI output, and never included in audit log entries. **Kubeconfig retrieval is credential access**: `get_supervisor_kubeconfig` / `get_tkc_kubeconfig` (CLI: `kubeconfig supervisor` / `kubeconfig get`) return a kubeconfig embedding a Supervisor bearer token (JWT from `POST /wcp/login`) that acts as the configured vCenter account until it expires — typically hours, not tied to the vmware-vks process. Both MCP tools are annotated `readOnlyHint: false` and `risk_level: medium`; run them only on explicit user request and always export with `output_path` / `-o <path>` (owner-only 0600 file) instead of printing the token. Their audit rows redact the returned kubeconfig. **In-memory kubeconfig (v1.5.18+)**: for the skill's own API calls the kubeconfig is built as a Python dict and handed to the kubernetes client via `load_kube_config_from_dict()`, so the token is never written to a temp file; only an explicit export writes it to disk.\n\n3. **Network Scope** -- No webhook, HTTP listener, or inbound network connection is ever started. MCP transport is stdio only. Outbound connections go to the user-configured vCenter, to the Supervisor Kubernetes API endpoint that vCenter reports for the cluster (`api_server_cluster_endpoint`), and — for `delete_tkc_cluster`'s running-workload check only — to that TKC cluster's control-plane endpoint as recorded on the Supervisor.\n\n4. **TLS Verification** -- `verify_ssl: false` is supported for self-signed vCenter certificates (standard in enterprise environments). Set `verify_ssl: true` in config for CA-signed certificates. Applies to both the SOAP API and REST API connections.\n\n5. **Prompt Injection Protection** -- All tool inputs are passed as typed Python parameters (`str`, `int`, `bool`), never interpolated into shell commands. No `eval`, `exec`, or subprocess calls with user-controlled data.\n\n6. **Least Privilege** -- 14/23 tools are read-only. `create_namespace`, `create_tkc_cluster`, `delete_namespace` and `delete_tkc_cluster` preview by default: without `confirm=True` they change nothing and return the blast radius, and `confirm=True` is refused while a blocker stands or part of the blast radius could not be read. The running-workload guard on `delete_tkc_cluster` can only be skipped with `force=True`. All write operations are audit-logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy).\n\n## Supported AI Platforms\n\n| Platform | Status |\n|----------|--------|\n| Claude Code | Native Skill |\n| Goose (Block) | MCP via stdio |\n| Cursor | MCP mode |\n| Continue | MCP mode |\n| VS Code Copilot | MCP mode |\n| Python CLI | Standalone |\n\nFile v1.11.0:skill-card.md\n\n## Description:\n\nManages vSphere Kubernetes Service environments, including Supervisor clusters, vSphere Namespaces, TKC cluster lifecycle, kubeconfig access, and Harbor registry checks.\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 and platform operators use this skill to check VKS readiness and administer Supervisor Namespaces and TKC clusters in configured vCenter environments.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: High-impact VKS administration actions can create, update, scale, upgrade, or delete namespaces and TKC clusters.\n\nMitigation: Install only for authorized vCenter/VKS operators, use least-privilege service accounts, and require explicit approval before cluster writes.\n\nRisk: Kubeconfig retrieval exposes bearer-token access to Supervisor or TKC Kubernetes APIs.\n\nMitigation: Run credential access only on explicit user request, write kubeconfigs to owner-only files, avoid printing token contents, and delete exported files after use.\n\nRisk: Local configuration, password files, exported kubeconfigs, and audit logs contain sensitive operational data.\n\nMitigation: Keep local files owner-only, prefer a secret manager for passwords, and rotate or delete retained files according to the operator's policy.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/vmware-vks)\n- [VMware VKS source homepage](https://github.com/vmware-skills/VMware-VKS)\n- [Capabilities](references/capabilities.md)\n- [Setup Guide](references/setup-guide.md)\n- [CLI Reference](references/cli-reference.md)\n- [Agent Guardrails](references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with CLI commands, MCP tool guidance, and structured command or tool results when executed by the agent.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May direct the agent to create owner-only kubeconfig files when explicitly requested; credential contents should not be printed.]\n\n## Skill Version(s):\n\n1.11.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\nFile v1.11.0:evals/evals.json\n\n{\n  \"skill_name\": \"vmware-vks\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"Create a new Kubernetes namespace 'dev-team' and deploy a 3-worker TKC cluster running K8s 1.28\",\n      \"expected_output\": \"Namespace created, TKC cluster deployed\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses create_namespace with cluster_id and storage_policy\",\n        \"Uses create_tkc_cluster with k8s_version, worker_count=3\",\n        \"Shows the confirm=False preview (blast_radius) before actual creation\"\n      ]\n    },\n    {\n      \"id\": 2,\n      \"prompt\": \"Scale the production TKC cluster to 5 workers and get me the kubeconfig\",\n      \"expected_output\": \"Cluster scaled, kubeconfig written to a file\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses scale_tkc_cluster with worker_count=5\",\n        \"Uses get_tkc_kubeconfig with output_path to write the kubeconfig to a file\",\n        \"Reports the file path and does not print the kubeconfig or its token\"\n      ]\n    },\n    {\n      \"id\": 3,\n      \"prompt\": \"Is our vSphere cluster ready for Tanzu? Check compatibility and list available K8s versions\",\n      \"expected_output\": \"Compatibility check results and version list\",\n      \"files\": [],\n      \"expectations\": [\n        \"Uses check_vks_compatibility\",\n        \"Uses get_tkc_available_versions\",\n        \"Clearly reports whether VKS is supported\"\n      ]\n    }\n  ]\n}\n\nArchive v1.10.3: 8 files, 25944 bytes\n\nFiles: evals/evals.json (1362b), references/agent-guardrails.md (9181b), references/capabilities.md (9629b), references/cli-reference.md (4661b), references/setup-guide.md (10179b), skill-card.md (3132b), SKILL.md (19549b), _meta.json (130b)\n\nFile v1.10.3:SKILL.md\n\n---\nname: vmware-vks\ndescription: >\n  Use this skill whenever the user needs to manage vSphere Kubernetes Service (VKS) — Supervisor clusters, vSphere Namespaces, and TKC cluster lifecycle.\n  Directly handles: check VKS compatibility, create/delete namespaces, create/scale/upgrade/delete TKC clusters, get kubeconfig, check Harbor registry.\n  Always use this skill for \"create Kubernetes cluster\", \"scale workers\", \"upgrade K8s version\", \"create namespace\", \"get kubeconfig\", or any VKS/TKC task.\n  Do NOT use for vanilla VM operations (use vmware-aiops), non-vSphere Kubernetes (e.g., kubeadm, EKS, AKS), or AVI/AKO load balancing (use vmware-avi).\n  For networking use vmware-nsx.\ninstaller:\n  kind: uv\n  package: vmware-vks\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vks\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VKS_CONFIG\",\"VMWARE_VKS_<TARGET>_PASSWORD\",\"VMWARE_VKS_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-VKS\",\"emoji\":\"☸️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). MCP tool calls and remote CLI commands audited to ~/.vmware/audit.db (SQLite, via vmware-policy); write operations also mirrored to ~/.vmware-vks/audit.log.\n  Credentials: Each vCenter target requires a per-target password env var in ~/.vmware-vks/.env following the pattern VMWARE_VKS_<TARGET_NAME_UPPER>_PASSWORD (e.g., target \"vcenter-01\" → VMWARE_VKS_VCENTER_01_PASSWORD). Passwords are never logged, never echoed, never included in audit entries. get_supervisor_kubeconfig and get_tkc_kubeconfig are credential access, not reads: the kubeconfig embeds a Supervisor bearer token (JWT from /wcp/login) that acts as the configured vCenter account until it expires (typically hours, independent of this process). Both are annotated readOnlyHint=false so MCP clients ask before running them; call them only on explicit user request and write the result to an owner-only (0600) file with output_path / -o rather than printing it. The audit log records the call but redacts the returned kubeconfig.\n---\n\n# VMware VKS\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS) under the MIT license.\n\nAI-powered VMware vSphere Kubernetes Service (VKS) management — 23 MCP tools.\n\n> Requires vSphere 8.x+ with Workload Management enabled.\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (monitoring), [vmware-storage](https://github.com/vmware-skills/VMware-Storage) (storage), [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (NSX networking), [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (DFW/firewall), [vmware-aria](https://github.com/vmware-skills/VMware-Aria) (metrics/alerts/capacity), [vmware-avi](https://github.com/vmware-skills/VMware-AVI) (AVI/ALB/AKO), [vmware-harden](https://github.com/vmware-skills/VMware-Harden) (compliance baselines).\n> | [vmware-pilot](../vmware-pilot/SKILL.md) (workflow orchestration) | [vmware-policy](../vmware-policy/SKILL.md) (audit/policy)\n\n## What This Skill Does\n\n| Category | Capabilities | Count |\n|----------|-------------|:-----:|\n| **Supervisor** | Compatibility check, status, storage policies | 3 |\n| **Namespace** | List, get, create with quotas, update, delete with TKC guard, VM classes | 6 |\n| **TKC Clusters** | List, get, versions, create, scale, upgrade, delete with workload guard | 7 |\n| **VM Service** | VM snapshots, VM groups + bootOrder, VM multi-NIC readout (vm-operator CRDs, read-only) | 3 |\n| **Access** | Supervisor kubeconfig, TKC kubeconfig, Harbor registry, storage usage | 4 |\n\n## Quick Install\n\n```bash\nuv tool install vmware-vks==1.10.3\nvmware-vks check\n```\n\n## When to Use This Skill\n\n- Check if vSphere environment supports VKS\n- Create, update, or delete Supervisor Namespaces with resource quotas\n- Deploy, scale, upgrade, or delete TKC (TanzuKubernetesCluster) clusters\n- Get kubeconfig for Supervisor or TKC clusters\n- Check Harbor registry info or storage usage\n\n**Use companion skills for**:\n- VM lifecycle, deployment → `vmware-aiops`\n- Inventory, health, alarms → `vmware-monitor`\n- iSCSI, vSAN, datastore → `vmware-storage`\n- Load balancing, AVI/ALB, AKO, Ingress → `vmware-avi`\n\n## Related Skills — Skill Routing\n\n| User Intent | Recommended Skill |\n|-------------|------------------|\n| Read-only monitoring | **vmware-monitor** |\n| Storage: iSCSI, vSAN | **vmware-storage** |\n| VM lifecycle, deployment | **vmware-aiops** |\n| vSphere Kubernetes Service (vSphere 8.x+) | **vmware-vks** ← this skill |\n| NSX networking: segments, gateways, NAT | **vmware-nsx** |\n| NSX security: DFW rules, security groups | **vmware-nsx-security** |\n| Aria Ops: metrics, alerts, capacity planning | **vmware-aria** |\n| Multi-step workflows with approval | **vmware-pilot** |\n| Compliance baselines (CIS / 等保 / PCI-DSS), drift detection, LLM remediation advisor | **vmware-harden** (`uv tool install vmware-harden`) |\n| Load balancer, AVI, ALB, AKO, Ingress | **vmware-avi** (`uv tool install vmware-avi`) |\n| Audit log query | **vmware-policy** (`vmware-audit` CLI) |\n\n## Common Workflows\n\n### Deploy a New TKC Cluster\n\n**Pre-flight (judgment)**:\n- Supervisor must be vSphere 8.x+ with WCP enabled — `supervisor check` returns pass/fail. If fail, no amount of TKC commands will work; resolve at vSphere/WCP layer first.\n- K8s version: pick a TKR version that's still supported by VMware (not EOL). New clusters on EOL versions look fine until you need a CVE patch and there isn't one.\n- VM class sizing: `best-effort-*` for dev, `guaranteed-*` for prod. A `best-effort` worker can be evicted under host pressure — production workloads need guaranteed.\n- Storage policy: must already exist in vCenter. `list_supervisor_storage_policies` first and pass the returned `policy` ID (not the display name); creating a TKC against a missing policy fails after CP boot, leaving partial state.\n- Control-plane count: `1` for dev, `3` for prod (HA). Cannot upgrade from 1→3 without recreating; choose right the first time.\n- Namespace quota: TKC consumes CP + worker × (cpu, memory) from namespace quota. If quota is too tight, workers fail to schedule with no obvious error.\n- TKC API version: auto-detected at runtime via the K8s discovery API (prefers `cluster.x-k8s.io/v1` when the Supervisor serves it, falls back to `v1beta1` on vSphere 8.0). No manual selection needed; advanced callers can override via the `api_version` parameter on `generate_tkc_yaml()`.\n\n**Steps**:\n1. `vmware-vks supervisor check --target prod` → must pass\n2. `vmware-vks tkc versions -n <ns>` → pick a non-EOL TKR\n3. (If new namespace) `vmware-vks namespace create dev --storage-policy <policy> --cpu <enough-for-cp+workers>` (a dry run by default), then the same with `--apply`\n4. `vmware-vks tkc create dev-cluster -n dev --version <tkr> --control-plane 1 --workers 3 --vm-class best-effort-large` (a dry run by default), then the same with `--apply`\n5. Wait for `phase=running` (typically 10-15 min); do not assume success on apply return\n6. Only if the user asked for cluster access: `vmware-vks kubeconfig get dev-cluster -n dev -o ./kubeconfig` — writes an owner-only file; report the path, never paste the token into the agent context\n\n### Scale Workers for Load Testing\n\n**Judgment**: scaling is fast but reverse-scaling is destructive — workers are deleted, in-flight pods lost. Treat scale-down like a delete.\n\n1. `tkc get dev-cluster -n dev` → record current worker count and any pending pods\n2. **Scale-up**: `tkc scale dev-cluster -n dev --workers 6` → safe, additive operation\n3. Verify new workers reach `Ready` in `kubectl get nodes` before sending traffic\n4. **Scale-down**: drain pods first via `kubectl drain` on the to-be-deleted nodes, THEN `tkc scale --workers 3`. Skipping drain causes pod restarts on remaining nodes — measurable user impact.\n5. Confirm namespace quota leftover supports the new size — quota is enforced at scheduling, not at scale request\n\n### Namespace Resource Management\n\n**Judgment**: quota changes are atomic but consequences are not. Reducing quota below current usage doesn't evict pods — they keep running, but no new pods schedule, looking like a \"namespace is broken\" symptom.\n\n1. `namespace list` → see all namespaces and their phase\n2. `storage -n dev` → check current CPU/memory/storage usage; **never reduce quota below current usage + 20% headroom**\n3. `namespace update dev --cpu <new> --memory <new> --dry-run` → preview, then real\n4. Validate by attempting a small pod scale-up; if it pends with `Insufficient cpu`, quota is still the bottleneck\n\n## Architecture\n\n```\nUser (Natural Language)\n  ↓\nAI Agent (Claude Code / Goose / Cursor)\n  ↓ reads SKILL.md\n  ↓\nvmware-vks CLI  ─── or ───  vmware-vks MCP Server (stdio)\n  │\n  ├─ Layer 1: pyVmomi → vCenter REST API\n  │   Supervisor status, storage policies, Namespace CRUD, VM classes, Harbor\n  │\n  └─ Layer 2: kubernetes client → Supervisor K8s API endpoint\n      TKC CR apply / get / delete  (cluster.x-k8s.io/v1beta1)\n      Kubeconfig bearer token from POST /wcp/login (Supervisor JWT)\n  ↓\nvCenter Server 8.x+ (Workload Management enabled)\n  ↓\nSupervisor Cluster → vSphere Namespaces → TanzuKubernetesCluster\n```\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models (Ollama, Qwen) | **CLI** | ~2K tokens vs ~8K for MCP |\n| Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | Type-safe parameters, structured output |\n\n## MCP Tools (23 — 14 read, 9 write)\n\nAll accept optional `target` parameter to specify a named vCenter.\n\n`list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return the family\nlist envelope — `{items, returned, limit, total, truncated, hint}` — rather than a bare array.\nRead the rows from `items`; `truncated` says whether the listing is complete, so it never has\nto be guessed from the row count. These three read their collection in one un-paged call, so\n`total` is the real count and `truncated` is always `false`.\n\n| Category | Tool | Type |\n|----------|------|:----:|\n| **Supervisor** | `check_vks_compatibility` | Read |\n| | `get_supervisor_status` | Read |\n| | `list_supervisor_storage_policies` | Read |\n| **Namespace** | `list_namespaces` | Read |\n| | `get_namespace` | Read |\n| | `create_namespace` | Write |\n| | `update_namespace` | Write |\n| | `delete_namespace` | Write |\n| | `list_vm_classes` | Read |\n| **TKC** | `list_tkc_clusters` | Read |\n| | `get_tkc_cluster` | Read |\n| | `get_tkc_available_versions` | Read |\n| | `create_tkc_cluster` | Write |\n| | `scale_tkc_cluster` | Write |\n| | `upgrade_tkc_cluster` | Write |\n| | `delete_tkc_cluster` | Write |\n| **VM Service** | `list_vm_snapshots` | Read |\n| | `list_vm_groups` | Read |\n| | `list_vm_network_interfaces` | Read |\n| **Access** | `get_supervisor_kubeconfig` | Write (credential) |\n| | `get_tkc_kubeconfig` | Write (credential) |\n| | `get_harbor_info` | Read |\n| | `list_namespace_storage_usage` | Read |\n\n`create_namespace` / `create_tkc_cluster` — defaults to `dry_run=True`, returns a YAML plan for review. Pass `dry_run=False` to apply.\n\n`delete_namespace` — requires `confirmed=True` and rejects if TKC clusters still exist (prevents orphaned clusters).\n\n`delete_tkc_cluster` — requires `confirmed=True` and checks for running workloads. Rejects if found unless `force=True`.\n\n**Credential access**: `get_supervisor_kubeconfig` and `get_tkc_kubeconfig` are not reads. The kubeconfig embeds a Supervisor bearer token (JWT from `/wcp/login`) that acts as the configured vCenter account until it expires — typically hours, and not revoked when vmware-vks exits. So:\n- Run them only when the user explicitly asks for a kubeconfig; never auto-run them or fetch one as a side step. Both are annotated `readOnlyHint: false` (MCP clients ask first) and `risk_level: medium` (so an operator's `min_risk_level: medium` deny rule covers them).\n- Always pass `output_path` (MCP) or `-o <path>` (CLI) and report only the path. The file is created owner-only (0600) — also when it replaces an existing file — and a symlink target is refused. Delete it when no longer needed.\n- The audit row records who fetched which kubeconfig, but the returned kubeconfig is redacted (`sensitive_result=True`).\n\n> Full capability details and safety features: see `references/capabilities.md`\n\n## CLI Quick Reference\n\n```bash\n# Supervisor\nvmware-vks check [--config <path>]\nvmware-vks preflight-auth [--target <name>]   # live-validate POST /wcp/login (issue #13)\nvmware-vks supervisor status <cluster-id> [--target <name>]\nvmware-vks supervisor storage-policies [--target <name>]\n\n# Namespace\nvmware-vks namespace list [--target <name>]\nvmware-vks namespace get <name> [--target <name>]\nvmware-vks namespace create <name> --cluster <id> [--cpu <n>] [--memory <mb>] [--storage-policy <name>] [--apply]\nvmware-vks namespace update <name> [--cpu <n>] [--memory <mb>] [--target <name>]\nvmware-vks namespace delete <name> [--target <name>]\n\n# TKC Clusters\nvmware-vks tkc list [-n <namespace>] [--target <name>]\nvmware-vks tkc create <name> -n <ns> [--version <v>] [--workers <n>] [--vm-class <name>] [--apply]\nvmware-vks tkc scale <name> -n <ns> --workers <n> [--pool <name>] [--target <name>]\nvmware-vks tkc upgrade <name> -n <ns> --version <v> [--target <name>]\nvmware-vks tkc delete <name> -n <ns> [--skip-workload-check] [--target <name>]\n\n# Kubeconfig\nvmware-vks kubeconfig supervisor -n <namespace> [-o <path>] [--target <name>]\nvmware-vks kubeconfig get <cluster-name> -n <namespace> [-o <path>] [--target <name>]\n\n# Harbor & Storage\nvmware-vks harbor [--target <name>]\nvmware-vks storage -n <namespace> [--target <name>]\n```\n\n> Full CLI reference with all flags and interactive creation: see `references/cli-reference.md`\n\n## Troubleshooting\n\n### \"VKS not compatible\" error\n\nWorkload Management must be enabled in vCenter. Check: vCenter UI → Workload Management. Requires vSphere 8.x+ with Enterprise Plus or VCF license.\n\n### Namespace creation fails with \"storage policy not found\"\n\nList policies first: `vmware-vks supervisor storage-policies`, then pass the **Policy ID** column value (not the display name) as `--storage-policy`.\n\n### TKC cluster stuck in \"Creating\" phase\n\nCheck Supervisor events in vCenter. Common causes: insufficient resources on ESXi hosts, network issues with NSX-T, or storage policy not available on target datastore.\n\n### Every REST tool returns 401\n\nvCenter keeps two independent session stores, and this skill uses both. Namespace, storage-policy and Supervisor-status tools call the vSphere Automation REST API under `/api`, which authenticates with a session id from `POST https://<vcenter>/api/session` (HTTP Basic on that one call, then the id in a `vmware-api-session-id` header). The pyVmomi SOAP session under `/sdk` is a different store and its key is rejected there — sending it produced a 401 on every REST tool. A 401 is refreshed automatically once; if it persists, check whether a proxy between you and vCenter strips the `vmware-api-session-id` header. A **403**, not a 401, is what an account short of Workload Management permissions gets.\n\n### Validating Supervisor auth (POST /wcp/login)\n\nSupervisor/TKC Kubernetes auth uses a JWT obtained from `POST https://<vcenter>/wcp/login` (HTTP Basic → JSON `session_id` bearer token), not the pyVmomi SOAP session key, and not the `/api/session` id above either — three separate credentials. To validate this end-to-end against your real Supervisor, run:\n\n```bash\nvmware-vks preflight-auth [--target <name>]\n```\n\nIt performs the **real** login (no mocks) and reports, per target: vCenter reachable → `/wcp/login` HTTP status → parseable `session_id` → does the JWT authenticate a trivial Supervisor K8s API call. A healthy result is all four steps `✓ PASS` ending in `target '<name>': /wcp/login auth flow validated end-to-end.` (exit code 0). On failure each step prints a teaching message — e.g. a 404 on `/wcp/login` means the endpoint path differs on your Supervisor version (capture the real path), a 401 on the K8s probe means `session_id` is not the bearer token on your version. It never tracebacks — every failure is status output.\n\n### Kubeconfig retrieval fails\n\nSupervisor API endpoint must be reachable from the machine running vmware-vks. Check firewall rules for port 6443.\n\n### Scale operation has no effect\n\nVerify the cluster is in \"Running\" phase before scaling. Clusters in \"Creating\" or \"Updating\" phase reject scale operations.\n\n### Delete namespace rejected unexpectedly\n\nThe namespace delete guard prevents deletion when TKC clusters exist inside. Delete all TKC clusters in the namespace first, then retry.\n\n## Prerequisites\n\n- vSphere 8.x+ with Workload Management enabled\n- Enterprise Plus or VCF license\n- NSX-T (recommended) or VDS + HAProxy networking\n- Supervisor Cluster configured and running\n\n## Setup\n\n```bash\nuv tool install vmware-vks==1.10.3\nmkdir -p ~/.vmware-vks\nvmware-vks init\n```\n\n> All tools are automatically audited via vmware-policy. Audit logs: `vmware-audit log --last 20`\n\n> Full setup guide, security details, and AI platform compatibility: see `references/setup-guide.md`\n\n## Audit & Safety\n\nOperations are audited via vmware-policy:\n- Every MCP tool call, and every CLI command that reaches vCenter or the Supervisor (`@guarded` writes and credential reads, `@audited` reads), is logged to `~/.vmware/audit.db` (SQLite). The seven namespace/TKC write operations are also mirrored to `~/.vmware-vks/audit.log` (JSON Lines)\n- Policy rules enforced via `~/.vmware/rules.yaml` (deny rules, maintenance windows, risk levels)\n- Risk classification: each tool tagged as low/medium/high/critical\n- View recent operations: `vmware-audit log --last 20`\n- View denied operations: `vmware-audit log --status denied`\n\n**Local files (sensitive, keep owner-only)**: `~/.vmware-vks/.env` holds per-target passwords (b64-obfuscated, not encrypted; created 0600, `vmware-vks doctor` flags a wider mode). `~/.vmware/audit.db` (+ WAL/SHM, 0600 in a 0700 directory) keeps operation history — resource names, parameters, results with credentials redacted — and rotates at 100 MB, keeping 5 archives. `~/.vmware-vks/audit.log` (0600) is never rotated or pruned. Exported kubeconfigs are 0600 and are never cleaned up by the skill. Delete or rotate these yourself per your retention policy.\n\n**In-memory kubeconfig (v1.5.18+)**: for its own API calls the skill builds the Supervisor/TKC kubeconfig as a Python dict and loads it with `load_kube_config_from_dict()`; the bearer token (also cached in process memory, up to 8 h) is never written to a temp file. Only an explicit export (`output_path` / `-o`) puts it on disk.\n\nvmware-policy is automatically installed as a dependency — no manual setup needed.\n\n## License\n\nMIT — [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS)\n\nFile v1.10.3:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vks\",\n  \"version\": \"1.10.3\",\n  \"publishedAt\": 1789535968037\n}\n\nFile v1.10.3:references/agent-guardrails.md\n\n# Operating vmware-vks with a local / small model\n\nClaude-class models drive this skill without special instruction. Smaller and\nlocally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served\nthrough Goose, Ollama, or OpenShift AI — need explicit operating rules to call\ntools reliably.\n\nThis page exists because an operator wrote those rules by hand first. The\nguardrails below are adapted, with thanks, from the working configuration\n[@juanpf-ha](https://github.com/juanpf-ha) developed while running\nvmware-monitor and vmware-aria against a production vSphere estate with Llama\n3.3 70B FP8 on an on-prem H100\n([VMware-AIops#31](https://github.com/vmware-skills/VMware-AIops/issues/31)). The\ncross-skill rules are identical across this family; the parts below marked\nvmware-vks are specific to this skill.\n\nvmware-vks exposes 23 MCP tools. Two things make it distinctive for a small\nmodel: deleting a namespace or a Tanzu Kubernetes cluster destroys running\nworkloads, and two of its tools hand back live credentials — a kubeconfig\nwhose bearer token acts as the configured vCenter account for hours.\n`get_supervisor_kubeconfig` and `get_tkc_kubeconfig` are credential access, not\nreads: both are annotated `readOnlyHint: false`, so an MCP client that honours\nthe annotation asks before running them.\n\n> **Disclaimer**: This is a community-maintained open-source project and is\n> **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom\n> Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\n---\n\n## First: the rules you no longer need to write\n\nSeveral guardrails from the original configuration are now enforced by the\nskill itself. Prompt instructions are advisory — a model can ignore them.\nThese are structural, so it cannot.\n\n| Guardrail you would otherwise prompt for | Now enforced by |\n|---|---|\n| \"Preview a namespace or cluster creation before applying it\" | **`dry_run` defaults to true.** `create_namespace` and `create_tkc_cluster` return a YAML plan for review unless you explicitly pass `dry_run=False`. Preview is the default path, not a habit the model must maintain. |\n| \"Confirm before deleting anything\" | **`confirmed=True` is required.** `delete_namespace` additionally refuses while TKC clusters still exist inside it, and `delete_tkc_cluster` refuses while workloads are running unless `force=True`. |\n| \"Use explicit limits for queries that may return large amounts of data\" | **The list envelope.** `list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. These three read their collection in one un-paged call, so `total` is the real count and `truncated` is always `false`. |\n| \"If a listing came back empty, say so rather than claiming the call failed\" | Same envelope. Empty `items` with `truncated: false` means checked-and-none — a stated result, not a silence the model has to interpret. |\n| \"Log every state change you make\" | **The `@vmware_tool` decorator.** Every write is recorded to `~/.vmware/audit.db` before the model sees the result, and policy rules are evaluated ahead of execution. |\n| \"Don't leave a token lying around in a readable file\" | **Owner-only export.** A kubeconfig written with `output_path` / `-o` is created 0600 — also when it replaces an existing file — and a symlink target is refused. The audit row records the retrieval but redacts the returned kubeconfig. |\n\n---\n\n## The system prompt\n\nEverything below still benefits from being stated explicitly. Copy this into\nyour agent's instruction block.\n\n```text\n## Tool use\n\n- Always call an MCP tool before answering any question about the current\n  VMware environment. Never answer from memory or assumption.\n- Never describe a tool call, and never output a JSON example, instead of\n  executing the tool. If you intend to call a tool, call it.\n- If a tool fails, report the actual error text. Do not complete the answer\n  with assumptions about what the result would have been.\n- Use explicit limits on queries that may return large amounts of data. Do not\n  request unlimited results unless the user asks for them.\n- Namespace, cluster and storage-policy names are exact strings. Resolve them\n  with a list tool before use; do not correct or reformat what the user typed.\n\n## Skill routing\n\n- vmware-vks: Supervisor status and compatibility, vSphere namespaces, VM\n  classes, Tanzu Kubernetes clusters, kubeconfig retrieval, Harbor registry.\n- vmware-monitor: read-only vCenter inventory, hosts, al\n\nArchive v1.10.2: 8 files, 25807 bytes\n\nFiles: evals/evals.json (1362b), references/agent-guardrails.md (9181b), references/capabilities.md (9629b), references/cli-reference.md (4661b), references/setup-guide.md (10179b), skill-card.md (2814b), SKILL.md (19549b), _meta.json (130b)\n\nArchive v1.10.1: 8 files, 25683 bytes\n\nFiles: evals/evals.json (1362b), references/agent-guardrails.md (9181b), references/capabilities.md (9629b), references/cli-reference.md (4661b), references/setup-guide.md (10179b), skill-card.md (2620b), SKILL.md (19549b), _meta.json (130b)\n\nArchive v1.10.0: 8 files, 25662 bytes\n\nFiles: evals/evals.json (1362b), references/agent-guardrails.md (9181b), references/capabilities.md (9573b), references/cli-reference.md (4661b), references/setup-guide.md (10179b), skill-card.md (2598b), SKILL.md (19434b), _meta.json (130b)\n\nArchive v1.9.4: 8 files, 23281 bytes\n\nFiles: evals/evals.json (1296b), references/agent-guardrails.md (8389b), references/capabilities.md (8867b), references/cli-reference.md (4103b), references/setup-guide.md (8113b), skill-card.md (2506b), SKILL.md (17977b), _meta.json (129b)\n\nArchive v1.9.3: 8 files, 23378 bytes\n\nFiles: evals/evals.json (1296b), references/agent-guardrails.md (8389b), references/capabilities.md (8867b), references/cli-reference.md (4103b), references/setup-guide.md (8113b), skill-card.md (2826b), SKILL.md (17977b), _meta.json (129b)\n\nArchive v1.9.2: 8 files, 23356 bytes\n\nFiles: evals/evals.json (1296b), references/agent-guardrails.md (8389b), references/capabilities.md (8867b), references/cli-reference.md (3914b), references/setup-guide.md (8113b), skill-card.md (2953b), SKILL.md (17977b), _meta.json (129b)\n\nArchive v1.9.1: 8 files, 23376 bytes\n\nFiles: evals/evals.json (1296b), references/agent-guardrails.md (8389b), references/capabilities.md (8867b), references/cli-reference.md (3914b), references/setup-guide.md (8113b), skill-card.md (2945b), SKILL.md (17977b), _meta.json (129b)","readmeExcerpt":"Skill: vmware-vks Owner: zw008 Summary: Use this skill whenever the user needs to manage vSphere Kubernetes Service (VKS) — Supervisor clusters, vSphere Namespaces, and TKC cluster lifecycle. Directly handles: check VKS compatibility, create/delete namespaces, create/scale/upgrade/delete TKC clusters, get kubeconfig, check Harbor registry. Always use this skill for \"create Kubernetes cluster\", \"scale workers\", \"upgra","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"uv tool install vmware-vks==1.12.0\nvmware-vks check"},{"language":"text","snippet":"User (Natural Language)\n  ↓\nAI Agent (Claude Code / Goose / Cursor)\n  ↓ reads SKILL.md\n  ↓\nvmware-vks CLI  ─── or ───  vmware-vks MCP Server (stdio)\n  │\n  ├─ Layer 1: pyVmomi → vCenter REST API\n  │   Supervisor status, storage policies, Namespace CRUD, VM classes, Harbor\n  │\n  └─ Layer 2: kubernetes client → Supervisor K8s API endpoint\n      TKC CR apply / get / delete  (cluster.x-k8s.io/v1beta1)\n      Kubeconfig bearer token from POST /wcp/login (Supervisor JWT)\n  ↓\nvCenter Server 8.x+ (Workload Management enabled)\n  ↓\nSupervisor Cluster → vSphere Namespaces → TanzuKubernetesCluster"},{"language":"bash","snippet":"# Supervisor\nvmware-vks check [--config <path>]\nvmware-vks preflight-auth [--target <name>]   # live-validate POST /wcp/login (issue #13)\nvmware-vks supervisor status <cluster-id> [--target <name>]\nvmware-vks supervisor storage-policies [--target <name>]\n\n# Namespace\nvmware-vks namespace list [--target <name>]\nvmware-vks namespace get <name> [--target <name>]\nvmware-vks namespace create <name> --cluster <id> [--cpu <n>] [--memory <mb>] [--storage-policy <name>] [--apply]\nvmware-vks namespace update <name> [--cpu <n>] [--memory <mb>] [--target <name>]\nvmware-vks namespace delete <name> [--target <name>]\n\n# TKC Clusters\nvmware-vks tkc list [-n <namespace>] [--target <name>]\nvmware-vks tkc create <name> -n <ns> [--version <v>] [--workers <n>] [--vm-class <name>] [--apply]\nvmware-vks tkc scale <name> -n <ns> --workers <n> [--pool <name>] [--target <name>]\nvmware-vks tkc upgrade <name> -n <ns> --version <v> [--target <name>]\nvmware-vks tkc delete <name> -n <ns> [--skip-workload-check] [--target <name>]\n\n# Kubeconfig\nvmware-vks kubeconfig supervisor -n <namespace> [-o <path>] [--target <name>]\nvmware-vks kubeconfig get <cluster-name> -n <namespace> [-o <path>] [--target <name>]\n\n# Harbor & Storage\nvmware-vks harbor [--target <name>]\nvmware-vks storage -n <namespace> [--target <name>]"},{"language":"bash","snippet":"vmware-vks preflight-auth [--target <name>]"},{"language":"bash","snippet":"uv tool install vmware-vks==1.12.0\nmkdir -p ~/.vmware-vks\nvmware-vks init"},{"language":"text","snippet":"## Tool use\n\n- Always call an MCP tool before answering any question about the current\n  VMware environment. Never answer from memory or assumption.\n- Never describe a tool call, and never output a JSON example, instead of\n  executing the tool. If you intend to call a tool, call it.\n- If a tool fails, report the actual error text. Do not complete the answer\n  with assumptions about what the result would have been.\n- Use explicit limits on queries that may return large amounts of data. Do not\n  request unlimited results unless the user asks for them.\n- Namespace, cluster and storage-policy names are exact strings. Resolve them\n  with a list tool before use; do not correct or reformat what the user typed.\n\n## Skill routing\n\n- vmware-vks: Supervisor status and compatibility, vSphere namespaces, VM\n  classes, Tanzu Kubernetes clusters, kubeconfig retrieval, Harbor registry.\n- vmware-monitor: read-only vCenter inventory, hosts, alarms, events. Prefer it\n  for any question that only reads about the underlying vSphere estate.\n- vmware-aiops: VM lifecycle for ordinary VMs, not Supervisor-managed ones.\n- vmware-storage: datastores, iSCSI, vSAN backing the Supervisor.\n- vmware-nsx / vmware-nsx-security: the networking and firewall a TKC sits on.\n- vmware-pilot: multi-step workflows that need approval gates.\n\n## Data fidelity\n\n- Never invent namespaces, clusters, VM classes, storage policies, or node\n  counts. If a tool did not return it, it does not exist for this answer.\n- Preserve the exact phase and condition values the tools return (Creating,\n  Running, Updating, and so on). Do not translate, normalise, or prettify them.\n- A cluster's phase is not its health. Report the phase the tool gave you.\n- If a requested field was not returned, show it as \"not available\". Do not\n  infer it from other fields.\n- Preserve the original order and the full set of fields when the user asks\n  for specific ones.\n- When a response is long, report every item it contains. If a result is\n  trun"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: vmware-vks\ndescription: >\n  Use this skill whenever the user needs to manage vSphere Kubernetes Service (VKS) — Supervisor clusters, vSphere Namespaces, and TKC cluster lifecycle.\n  Directly handles: check VKS compatibility, create/delete namespaces, create/scale/upgrade/delete TKC clusters, get kubeconfig, check Harbor registry.\n  Always use this skill for \"create Kubernetes cluster\", \"scale workers\", \"upgrade K8s version\", \"create namespace\", \"get kubeconfig\", or any VKS/TKC task.\n  Do NOT use for vanilla VM operations (use vmware-aiops), non-vSphere Kubernetes (e.g., kubeadm, EKS, AKS), or AVI/AKO load balancing (use vmware-avi).\n  For networking use vmware-nsx.\ninstaller:\n  kind: uv\n  package: vmware-vks\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"vmware-vks\",\"uvx\"]},\"optional\":{\"env\":[\"VMWARE_VKS_CONFIG\",\"VMWARE_VKS_<TARGET>_PASSWORD\",\"VMWARE_VKS_<TARGET>_USERNAME\",\"VMWARE_AUDIT_APPROVED_BY\"],\"bins\":[\"vmware-policy\"]},\"homepage\":\"https://github.com/vmware-skills/VMware-VKS\",\"emoji\":\"☸️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  vmware-policy auto-installed as Python dependency (provides @vmware_tool decorator and audit logging). MCP tool calls and remote CLI commands audited to ~/.vmware/audit.db (SQLite, via vmware-policy); write operations also mirrored to ~/.vmware-vks/audit.log.\n  Credentials: Each vCenter target requires a per-target password env var in ~/.vmware-vks/.env following the pattern VMWARE_VKS_<TARGET_NAME_UPPER>_PASSWORD (e.g., target \"vcenter-01\" → VMWARE_VKS_VCENTER_01_PASSWORD). Passwords are never logged, never echoed, never included in audit entries. get_supervisor_kubeconfig and get_tkc_kubeconfig are credential access, not reads: the kubeconfig embeds a Supervisor bearer token (JWT from /wcp/login) that acts as the configured vCenter account until it expires (typically hours, independent of this process). Both are annotated readOnlyHint=false so MCP clients ask before running them; call them only on explicit user request and write the result to an owner-only (0600) file with output_path / -o rather than printing it. The audit log records the call but redacts the returned kubeconfig.\n---\n\n# VMware VKS\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-VKS](https://github.com/vmware-skills/VMware-VKS) under the MIT license.\n\nAI-powered VMware vSphere Kubernetes Service (VKS) management — 23 MCP tools.\n\n> Requires vSphere 8.x+ with Workload Management enabled.\n> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (monitoring), [vmware-storage](https://github.com/vmware-skills/VMware-Storage) (storage), [vmware-nsx](https://github.com/vmware-ski"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"vmware-vks\",\n  \"version\": \"1.12.0\",\n  \"publishedAt\": 1789915978167\n}"},{"path":"references/agent-guardrails.md","content":"# Operating vmware-vks with a local / small model\n\nClaude-class models drive this skill without special instruction. Smaller and\nlocally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served\nthrough Goose, Ollama, or OpenShift AI — need explicit operating rules to call\ntools reliably.\n\nThis page exists because an operator wrote those rules by hand first. The\nguardrails below are adapted, with thanks, from the working configuration\n[@juanpf-ha](https://github.com/juanpf-ha) developed while running\nvmware-monitor and vmware-aria against a production vSphere estate with Llama\n3.3 70B FP8 on an on-prem H100\n([VMware-AIops#31](https://github.com/vmware-skills/VMware-AIops/issues/31)). The\ncross-skill rules are identical across this family; the parts below marked\nvmware-vks are specific to this skill.\n\nvmware-vks exposes 23 MCP tools. Two things make it distinctive for a small\nmodel: deleting a namespace or a Tanzu Kubernetes cluster destroys running\nworkloads, and two of its tools hand back live credentials — a kubeconfig\nwhose bearer token acts as the configured vCenter account for hours.\n`get_supervisor_kubeconfig` and `get_tkc_kubeconfig` are credential access, not\nreads: both are annotated `readOnlyHint: false`, so an MCP client that honours\nthe annotation asks before running them.\n\n> **Disclaimer**: This is a community-maintained open-source project and is\n> **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom\n> Inc.** \"VMware\" and \"vSphere\" are trademarks of Broadcom.\n\n---\n\n## First: the rules you no longer need to write\n\nSeveral guardrails from the original configuration are now enforced by the\nskill itself. Prompt instructions are advisory — a model can ignore them.\nThese are structural, so it cannot.\n\n| Guardrail you would otherwise prompt for | Now enforced by |\n|---|---|\n| \"Preview a namespace or cluster creation before applying it\" | **`confirm` defaults to false.** `create_namespace` and `create_tkc_cluster` return `blast_radius` (spec / YAML plan) and change nothing unless `confirm=True`. Preview is the default path, not a habit the model must maintain. |\n| \"Confirm before deleting anything\" | **A bare delete only previews.** `delete_namespace` and `delete_tkc_cluster` return what they would destroy; `confirm=True` is refused while TKC clusters exist inside the namespace, while workloads run (unless `force=True`), or when any part of the blast radius could not be read. |\n| \"Use explicit limits for queries that may return large amounts of data\" | **The list envelope.** `list_namespaces`, `list_supervisor_storage_policies` and `list_vm_classes` return `{items, returned, limit, total, truncated, hint}`, so the model reads truncation instead of guessing at it. These three read their collection in one un-paged call, so `total` is the real count and `truncated` is always `false`. |\n| \"If a listing came back empty, say so rather than claiming the call failed\" | Same envelope. Empty `items` with `truncated: fa"},{"path":"references/capabilities.md","content":"# Capabilities\n\nDetailed capability breakdown for all 23 MCP tools.\n\n## Automation Level Reference\n\nEach operation is classified by autonomy level per the Enterprise Harness Engineering framework:\n\n| Level | Meaning | Agent autonomy | Examples in this skill |\n|:-:|---|---|---|\n| **L1** | Read-only, raw data | Always auto-run | `check_vks_compatibility`, `get_supervisor_status`, `list_supervisor_storage_policies`, `list_namespaces`, `get_namespace`, TKC list/get, `get_harbor_info`, `list_namespace_storage_usage` |\n| **L2** | Read + analysis / recommendation | Always auto-run | namespace quota analysis, TKC health correlation, storage policy compatibility checks |\n| **Credential** | Returns live access material (bearer token) | **Never auto-run** — only on explicit user request; write to a file, report the path | `get_supervisor_kubeconfig`, `get_tkc_kubeconfig` |\n| **L3** | Single write — user must approve | Only after explicit confirmation; destructive ops require double-confirm + `--dry-run` | `create_namespace`, `update_namespace`, `delete_namespace`, `create_tkc_cluster`, `upgrade_tkc_cluster`, `scale_tkc_cluster`, `delete_tkc_cluster` |\n| **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — TKC fleet upgrades, multi-namespace bootstrapping plans)* |\n| **L5** | Auto-remediation from learned pattern | Pattern library only; requires `risk:low` + `reversible:true` + `repeatable:true` | *(roadmap — candidates: stuck TKC reconciliation, namespace quota bumps)* |\n\n**Notes**:\n- L1/L2 tools are always safe for agents to call without confirmation. Credential tools are not: they are annotated `readOnlyHint: false`, so an MCP client asks before running them.\n- L3 tools always pass through the `@vmware_tool` decorator: connection check → policy check → audit log → double-confirm.\n- Kubeconfig retrieval is credential access. The kubeconfig embeds a Supervisor bearer token (JWT from `/wcp/login`) that acts as the configured vCenter account until it expires — typically hours, not tied to the vmware-vks process. Both tools are `readOnlyHint: false`, `risk_level: medium`, and `sensitive_result=True` (the audit row records the call; the returned kubeconfig is redacted). Always pass `output_path` (MCP) / `-o <path>` (CLI): the file is created owner-only (0600), including when it replaces an existing file, and a symlink target is refused. `output_path` truncates the named file, so `~/.kube/config` would be replaced.\n\n## 1. Supervisor Layer (Read-Only)\n\n| Tool | What it returns |\n|------|----------------|\n| `check_vks_compatibility` | vCenter version (pass/fail for 8.x+), WCP enabled status, network backend type |\n| `get_supervisor_status` | Cluster ID, config status, Kubernetes status, API endpoint URL, network provider, and `kubernetes_version` (read from the `software/clusters` endpoint; null with a `kubernetes_version_hint` if that call fails) |\n| `list_supervisor_storage_policies` | List envelope; `items"},{"path":"references/cli-reference.md","content":"# CLI Reference\n\nFull command reference for `vmware-vks` CLI.\n\nAll commands accept an optional `--target <name>` parameter to specify a named vCenter from your config.\n\n## Pre-flight Check\n\n```bash\nvmware-vks check   # or: vmware-vks doctor — same checks, both names\n```\n\nVerifies connectivity, credentials, and WCP status for all configured vCenters (or a specific target).\n\n## Supervisor\n\n```bash\n# Get Supervisor cluster status (ID, API endpoint, K8s version, state)\nvmware-vks supervisor status <cluster-id> [--target <name>]\n\n# List vCenter storage policies (Policy ID / Name / Description).\n# Pass the Policy ID — not the display name — when creating a Namespace or TKC.\nvmware-vks supervisor storage-policies [--target <name>]\n```\n\n## Namespace\n\n```bash\n# List all vSphere Namespaces\nvmware-vks namespace list [--target <name>]\n\n# Get Namespace detail (quotas, storage bindings, role bindings)\nvmware-vks namespace get <name> [--target <name>]\n\n# Create Namespace with resource quotas and storage policy\n# Defaults to dry-run (shows plan). Pass --apply to execute.\nvmware-vks namespace create <name> --cluster <id> \\\n  [--cpu <mhz>] [--memory <mb>] \\\n  [--storage-policy <name>] [--apply]\n\n# Update Namespace CPU/memory quotas\nvmware-vks namespace update <name> \\\n  [--cpu <mhz>] [--memory <mb>] [--target <name>]\n\n# Delete Namespace (rejects if TKC clusters exist inside)\nvmware-vks namespace delete <name> [--target <name>]\n\n# List available VM classes for TKC nodes (ID / CPU / Memory (MB) / GPU)\nvmware-vks namespace vm-classes [--target <name>]\n```\n\n## TKC (TanzuKubernetesCluster)\n\n```bash\n# List TKC clusters (all namespaces or specific)\nvmware-vks tkc list [-n <namespace>] [--target <name>]\n\n# Get TKC cluster detail (nodes, versions, health conditions)\nvmware-vks tkc get <cluster-name> -n <namespace> [--target <name>]\n\n# List available K8s versions for a namespace\nvmware-vks tkc versions -n <namespace> [--target <name>]\n\n# Create TKC cluster (defaults to dry-run, pass --apply to execute)\nvmware-vks tkc create <cluster-name> -n <namespace> \\\n  [--version <k8s-ver>] \\\n  [--control-plane <n>] [--workers <n>] \\\n  [--vm-class <name>] [--storage-policy <name>] \\\n  [--apply]\n\n# Scale worker node count\nvmware-vks tkc scale <cluster-name> -n <namespace> \\\n  --workers <n> [--target <name>]\n\n# Upgrade TKC cluster to a newer K8s version\nvmware-vks tkc upgrade <cluster-name> -n <namespace> \\\n  --version <k8s-ver> [--target <name>]\n\n# Delete TKC cluster (rejects if workloads running, use --force to override)\nvmware-vks tkc delete <cluster-name> -n <namespace> \\\n  [--skip-workload-check] [--target <name>]\n# Asks you to type the cluster name back before it deletes. No bypass flag;\n# --skip-workload-check only skips the running-workload guard.\n```\n\n## Kubeconfig\n\n```bash\n# Get Supervisor-level kubeconfig (stdout, or -o to write a file)\nvmware-vks kubeconfig supervisor -n <namespace> [-o <output-path>] [--target <name>]\n\n# Get TKC cluster kubeconfig (stdout, or -o to write a f"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1828,"uniquenessScore":41,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T04:14:22.565Z","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-09T04:14:22.565Z","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-09T19:37:45.946Z","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"}]}}}