{"id":49291344,"url":"https://github.com/k-krew/hanoi-cli","last_synced_at":"2026-04-26T00:04:53.530Z","repository":{"id":345326333,"uuid":"1185183866","full_name":"k-krew/hanoi-cli","owner":"k-krew","description":"Interactive rebalance advisor for Kubernetes","archived":false,"fork":false,"pushed_at":"2026-04-22T21:54:23.000Z","size":68,"stargazers_count":16,"open_issues_count":1,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-22T23:29:30.790Z","etag":null,"topics":["cli","devops","failure-simulation","infrastructure","kubernetes","resource-management","simulation"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/k-krew.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-18T10:20:28.000Z","updated_at":"2026-04-22T21:56:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/k-krew/hanoi-cli","commit_stats":null,"previous_names":["k-krew/hanoi-cli"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/k-krew/hanoi-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-krew%2Fhanoi-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-krew%2Fhanoi-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-krew%2Fhanoi-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-krew%2Fhanoi-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k-krew","download_url":"https://codeload.github.com/k-krew/hanoi-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-krew%2Fhanoi-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32280982,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","devops","failure-simulation","infrastructure","kubernetes","resource-management","simulation"],"created_at":"2026-04-26T00:04:52.756Z","updated_at":"2026-04-26T00:04:53.525Z","avatar_url":"https://github.com/k-krew.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hanoi-cli\n\n![Claude Assisted](https://img.shields.io/badge/Made%20with-Claude-8A2BE2?logo=anthropic)\n![CI](https://github.com/k-krew/hanoi-cli/actions/workflows/release.yml/badge.svg)\n\nhanoi-cli analyzes pod distribution across nodes, detects resource imbalance, generates safe redistribution plans, and simulates node failures - all without touching your cluster. The name is inspired by the Tower of Hanoi puzzle: controlled movement of workloads between constrained pegs.\n\n## Example\n\n```bash\n$ hanoi-cli analyze\n\nCluster Imbalance Score: 42.3% -\u003e 9.1%\nImprovement: 33.2%\n\nNodes:\n  node-1               CPU:  82.5%  MEM:  71.0%  pods: 14 [HOTSPOT]\n  node-2               CPU:  35.0%  MEM:  28.0%  pods: 6\n  node-3               CPU:  20.0%  MEM:  15.0%  pods: 3\n\nSuggested Moves: 2\n  1. default/api-xyz: node-1 -\u003e node-3\n  2. default/worker-abc: node-1 -\u003e node-2\n...\n```\n\n## Features\n\n- **Imbalance detection** - CPU and memory utilization per node, standard deviation, hotspot flagging (\u003e=80%)\n- **Redistribution planning** - greedy optimizer that suggests pod moves to reduce cluster drift while respecting all scheduling constraints\n- **Node failure simulation** - remove a node, see which pods can be rescheduled and which become homeless\n- **Move explanations** - deep-dive into *why* a specific move was chosen, which nodes were rejected and why, and whether preferred anti-affinity is violated\n- **Full constraint awareness** - nodeSelector, node affinity, pod affinity/anti-affinity (required and preferred), taints/tolerations, DaemonSets, init containers\n- **Multiple output formats** - detailed text, JSON, compact summary, or a colored pseudo-GUI with dynamic-width progress bars\n\n## Installation\n\n### Homebrew (macOS / Linux)\n\n```bash\nbrew tap k-krew/tap\nbrew install hanoi-cli\n```\n\n### From source\n\n```bash\ngit clone https://github.com/k-krew/hanoi-cli.git \u0026\u0026 cd hanoi-cli\ngo build -o hanoi-cli .\n```\n\n### Binary download\n\nGrab the latest binary from [GitHub Releases](https://github.com/k-krew/hanoi-cli/releases) and place it in your `$PATH`.\n\n## Quick Start\n\n```bash\n# Analyze current cluster state and suggest rebalancing moves\nhanoi-cli analyze\n\n# Focus on memory instead of CPU\nhanoi-cli analyze --resource memory\n\n# Limit to 5 suggested moves\nhanoi-cli analyze --max-moves 5\n\n# Simulate what happens if node-3 goes down\nhanoi-cli simulate node-3\n\n# Explain why move #2 was suggested\nhanoi-cli analyze --explain 2\n```\n\n## Commands\n\n### `analyze`\n\nScans the cluster, computes per-node utilization, and generates a redistribution plan.\n\n```bash\nhanoi-cli analyze [flags]\n```\n\n\n| Flag          | Default | Description                             |\n| ------------- | ------- | --------------------------------------- |\n| `--resource`  | `cpu`   | Resource to optimize: `cpu` or `memory` |\n| `--max-moves` | `0`     | Max moves to suggest (0 = unlimited)    |\n\n\n### `simulate \u003cnode-name\u003e`\n\nRemoves a node from the cluster model, attempts to reschedule its pods onto surviving nodes, and reports feasibility.\n\n```bash\nhanoi-cli simulate node-3 [flags]\n```\n\n### Global Flags\n\n\n| Flag           | Short | Default          | Description                                  |\n| -------------- | ----- | ---------------- | -------------------------------------------- |\n| `--kubeconfig` |       | `~/.kube/config` | Path to kubeconfig file                      |\n| `--context`    |       | current context  | Kubernetes context to use                    |\n| `--namespace`  | `-n`  | all namespaces   | Limit to a specific namespace                |\n| `--output`     | `-o`  | `text`           | Output format: `text`, `json`, `short`, `ui`, `md` |\n| `--explain`    |       |                  | Explain why move N was chosen (1-based)      |\n\n\n## Output Formats\n\n### `text` - Detailed plain text\n\n```\nCluster Imbalance Score: 42.3% -\u003e 9.1%\nImprovement: 33.2%\n\nNodes:\n  node-1               CPU:  82.5%  MEM:  71.0%  pods: 14 [HOTSPOT]\n  node-2               CPU:  35.0%  MEM:  28.0%  pods: 6\n  node-3               CPU:  20.0%  MEM:  15.0%  pods: 3\n\nSuggested Moves: 2\n  1. default/api-xyz: node-1 -\u003e node-3\n  2. default/worker-abc: node-1 -\u003e node-2\n```\n\n### `json` - Machine-readable\n\n```bash\nhanoi-cli analyze -o json | jq .\n```\n\n```json\n{\n  \"imbalance_score_before\": 42.3,\n  \"imbalance_score_after\": 9.1,\n  \"nodes\": [\n    {\n      \"name\": \"node-1\",\n      \"cpu_percent\": 82.5,\n      \"mem_percent\": 71.0,\n      \"pod_count\": 14,\n      \"is_hotspot\": true,\n      \"cordoned\": false\n    }\n  ],\n  \"moves\": [\n    {\n      \"pod\": \"api-server-xyz\",\n      \"namespace\": \"default\",\n      \"from\": \"node-1\",\n      \"to\": \"node-3\"\n    }\n  ]\n}\n```\n\n### `short` - Compact summary\n\n```\nScore: 42.3% -\u003e 9.1% (improvement: 33.2%)\n\nSuggested Moves (2):\n  1. default/api-server-xyz: node-1 -\u003e node-3\n  2. default/worker-abc: node-1 -\u003e node-2\n```\n\n### `ui` - Colored pseudo-GUI with progress bars\n\n```\n  Cluster Imbalance Score:\n    Before: 42.3%\n    After:  9.1%\n    Improvement: 33.2%\n\n  Current State:\n  ! node-1  CPU [######################....] 82.5%  MEM [###################.......] 71.0%  pods: 14\n    node-2  CPU [########..................] 35.0%  MEM [######....................] 28.0%  pods: 6\n    node-3  CPU [####......................] 20.0%  MEM [####......................] 15.0%  pods: 3\n```\n\nCordoned nodes appear in dark grey with a `C` marker. Hotspot nodes appear in red with a `!` marker.\n\n### `md` - Markdown format for CI/CD integration\n\nPerfect for GitHub Actions, GitLab CI, and other platforms that support Markdown rendering.\n\n```bash\nhanoi-cli analyze -o md\nhanoi-cli simulate node-3 -o md\n```\n\nExample output:\n\n```markdown\n### Hanoi-CLI Cluster Analysis\n**Imbalance Score:** 42.3% -\u003e 9.1% (Improvement: **33.2%**)\n\n**Hotspots:** 1\n  - node-1\n\n#### Nodes State\n| Node | CPU | Memory | Pods | Status |\n|------|-----|--------|------|--------|\n| node-1 | 82.5% | 71.0% | 14 | HOTSPOT |\n| node-2 | 35.0% | 28.0% | 6 | OK |\n| node-3 | 20.0% | 15.0% | 3 | OK |\n\n#### Suggested Moves (2)\n1. `default/api-xyz`: `node-1` -\u003e `node-3`\n2. `default/worker-abc`: `node-1` -\u003e `node-2`\n\n#### Projected State\n| Node | CPU | Memory | Pods | Status |\n|------|-----|--------|------|--------|\n| node-1 | 45.0% | 42.0% | 10 | OK |\n| node-2 | 52.5% | 45.0% | 9 | OK |\n| node-3 | 42.5% | 38.0% | 7 | OK |\n```\n\n## Move Explanation\n\nUse `--explain N` to understand why a specific move was recommended:\n\n```bash\nhanoi-cli analyze --explain 1\nhanoi-cli simulate node-3 --explain 2\n```\n\n```\n--- Explanation for move #1 ---\n\nPod:    default/api-xyz\nOwner:  Deployment/api-server\nCPU:    500m    MEM: 256Mi\nMove:   node-1 -\u003e node-3\n\nSource node (node-1) utilization: CPU 82.5%, MEM 71.0%\nCluster score: 42.3% -\u003e 28.7%\n\nCandidate nodes:\n  node-2               eligible CPU: 35.0% -\u003e 47.5%  MEM: 28.0% -\u003e 38.2%  score: 30.1%\n  node-3               CHOSEN   CPU: 20.0% -\u003e 32.5%  MEM: 15.0% -\u003e 25.2%  score: 28.7%\n  node-4               REJECTED: node is cordoned (unschedulable)\n  node-5               REJECTED: taint gpu=true:NoSchedule not tolerated\n\nVerdict: node-3 produces the lowest imbalance score (28.7%) among all eligible nodes.\n```\n\nIn simulation context, the failed node is clearly marked:\n\n```\nSource node (node-3): FAILED (simulated)\n```\n\nWorks with `simulate` too - `--explain 1` explains why a displaced pod was rescheduled to a particular node. The simulate explain correctly accounts for prior moves in the sequence, so move #4's explanation reflects pods already placed by moves 1-3.\n\nWhen a pod has preferred anti-affinity rules, eligible nodes show whether they're violated:\n\n```\n  node-2               CHOSEN   CPU: 47.3% -\u003e 49.8%  ...  score: 36.0%  (preferred-anti-affinity: VIOLATED weight=100)\n```\n\nThis means the move is allowed (soft constraint), but the Kubernetes scheduler would normally penalize this placement.\n\n## Constraints\n\nhanoi-cli respects Kubernetes scheduling rules:\n\n- **DaemonSet pods** are never moved\n- **Cordoned nodes** (unschedulable) never receive pods\n- **Node selectors** and **node affinity** rules are enforced\n- **Pod affinity/anti-affinity** (required) is enforced; preferred rules are reported in explain\n- **Taints and tolerations** are checked (including `Exists` operator edge cases)\n- **Capacity limits** are respected - both CPU and memory (no overcommit on simulated reschedules)\n- **Init containers** are accounted for using `max(sum(containers), max(initContainers))`\n\n## Environment Variables\n\n\n| Variable           | Overrides                                      |\n| ------------------ | ---------------------------------------------- |\n| `HANOI_KUBECONFIG` | `--kubeconfig` default (highest priority)      |\n| `KUBECONFIG`       | `--kubeconfig` default (standard k8s variable) |\n| `HANOI_CONTEXT`    | `--context` default                            |\n\n\nKubeconfig resolution order: `HANOI_KUBECONFIG` \u003e `KUBECONFIG` \u003e `~/.kube/config`\n\n## Contributing\n\nContributions are welcome! Feel free to open issues and pull requests. Whether it's a bug fix, new feature, documentation improvement, or just a question - all input is appreciated.\n\n## License\n\nApache License 2.0 - see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-krew%2Fhanoi-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk-krew%2Fhanoi-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-krew%2Fhanoi-cli/lists"}