{"id":50251757,"url":"https://github.com/jingle2008/toolkit","last_synced_at":"2026-05-27T02:04:21.237Z","repository":{"id":296570743,"uuid":"993788278","full_name":"jingle2008/toolkit","owner":"jingle2008","description":"Toolkit — Cross-platform CLI for cloud \u0026 infrastructure automation, written in Go.  Fast filtering, templating, Kubernetes helpers, Terraform tooling, rich TUI, and more — one binary for everyday DevOps tasks.","archived":false,"fork":false,"pushed_at":"2026-05-25T06:08:02.000Z","size":1429,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T06:40:14.420Z","etag":null,"topics":["automation","cli","command-line","devops","go","kubernetes","terraform","toolkit","tui"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jingle2008.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-05-31T14:23:51.000Z","updated_at":"2026-05-25T06:08:06.000Z","dependencies_parsed_at":"2025-07-20T05:10:01.725Z","dependency_job_id":"04bbf827-1c98-4857-baa8-39cb5c1fdc8f","html_url":"https://github.com/jingle2008/toolkit","commit_stats":null,"previous_names":["jingle2008/toolkit"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/jingle2008/toolkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingle2008%2Ftoolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingle2008%2Ftoolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingle2008%2Ftoolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingle2008%2Ftoolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jingle2008","download_url":"https://codeload.github.com/jingle2008/toolkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jingle2008%2Ftoolkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33546836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["automation","cli","command-line","devops","go","kubernetes","terraform","toolkit","tui"],"created_at":"2026-05-27T02:04:15.620Z","updated_at":"2026-05-27T02:04:21.215Z","avatar_url":"https://github.com/jingle2008.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Toolkit\n\n[![CI](https://github.com/jingle2008/toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/jingle2008/toolkit/actions/workflows/ci.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/jingle2008/toolkit)](https://goreportcard.com/report/github.com/jingle2008/toolkit)\n[![Go Reference](https://pkg.go.dev/badge/github.com/jingle2008/toolkit.svg)](https://pkg.go.dev/github.com/jingle2008/toolkit)\n[![codecov](https://codecov.io/gh/jingle2008/toolkit/branch/main/graph/badge.svg)](https://codecov.io/gh/jingle2008/toolkit)\n\nToolkit is a collection of reusable Go components exposed through a modular CLI and optional TUI (built with [Bubble Tea](https://github.com/charmbracelet/bubbletea)).  \nIt targets day-to-day DevOps \u0026 development automation: querying Kubernetes, parsing Terraform plans, mass-editing config files, and inspecting large data tables directly in your terminal.\n\n- [User Manual](docs/USER_MANUAL.md)\n- [Kubernetes Client Fakes \u0026 Testing Patterns](docs/guide/k8s-fake-patterns.md)\n\n---\n\n## Feature Highlights\n\n| Area           | Packages                        | Notes |\n| -------------- | ------------------------------- | ----- |\n| **CLI core**   | `internal/cli`                  | Cobra-based, flags auto-generated |\n| **Interactive TUI** | `internal/ui/tui`             | Sort/search/filter large tabular datasets |\n| **Infrastructure loaders** | `internal/infra/k8s`, `internal/infra/terraform` | Uniform abstraction for K8s \u0026 TF |\n| **Config loading \u0026 validation** | `internal/config`, `internal/configloader` | JSON / YAML with defaulting \u0026 schema checks |\n| **Collections helpers** | `internal/collections` | Generic filter/sort with predicates |\n| **Encoding helpers** | `internal/encoding/jsonutil` | Fast JSON pointer traversal |\n| **Error \u0026 logging** | `pkg/infra/logging` | Typed errors via std errors; zap logger |\n\n## Architecture at a glance\n\n```mermaid\nflowchart LR\n    subgraph CFG [\"Config sources\"]\n        flags[\"CLI flags\u003cbr/\u003eTOOLKIT_* env\"]\n        file[\"~/.config/toolkit/config.yaml\"]\n    end\n    flags --\u003e viper((viper\u003cbr/\u003emerge))\n    file --\u003e viper\n    viper --\u003e Cfg[\"config.Config\"]\n\n    subgraph SRC [\"Data sources\"]\n        tf[\"Terraform repo\u003cbr/\u003e(repo-path)\"]\n        k8s[\"Kubernetes API\u003cbr/\u003e(kubeconfig)\"]\n        oci[\"OCI APIs\u003cbr/\u003e(env-realm)\"]\n    end\n\n    Cfg --\u003e Loader\n    tf --\u003e Loader\n    k8s --\u003e Loader\n    oci --\u003e Loader\n    Loader[\"internal/infra/loader\u003cbr/\u003e(composite)\"]\n\n    Loader --\u003e TUI[\"TUI\u003cbr/\u003etoolkit\"]\n    Loader --\u003e Get[\"Headless\u003cbr/\u003etoolkit get / config / doctor\"]\n    Loader --\u003e MCP[\"MCP server\u003cbr/\u003etoolkit mcp\"]\n    Loader --\u003e Mut[\"Mutations\u003cbr/\u003ecordon · drain · reboot\u003cbr/\u003escale · delete · terminate\"]\n```\n\nThe loader composite is the single funnel every entry point goes through, so the four surfaces (TUI, headless `get`, MCP, mutations) all see identical data and the same partial-load semantics.\n\n---\n\n## Install\n\n```bash\n# Latest release\ngo install github.com/jingle2008/toolkit/cmd/toolkit@latest\n\n# From source\ngit clone https://github.com/jingle2008/toolkit.git\ncd toolkit \u0026\u0026 make\n```\n\n```zsh\n# From Homebrew (macOS/Linux)\nbrew install jingle2008/tap/toolkit\n```\n\n\u003e **Already on the old `jingle2008/homebrew-toolkit` tap?** It's archived as of v0.3.x and won't receive new releases. Migrate with (order matters — `brew untap` refuses while the formula is still installed):\n\u003e ```zsh\n\u003e brew uninstall toolkit\n\u003e brew untap jingle2008/toolkit              # canonical short name; the homebrew- prefix is implied\n\u003e brew install jingle2008/tap/toolkit\n\u003e ```\n\n---\n\n## Getting Started\n\nAfter installation, try these quick commands:\n\n```sh\ntoolkit init\n# Scaffold an example config file at ~/.config/toolkit/config.yaml\n\ntoolkit config --validate\n# Sanity-check the effective config; exits non-zero on failure\n\ntoolkit completion bash   # or zsh/fish\n# Output shell completion script for your shell\n\ntoolkit version --check-updates\n# Print your installed version and check for updates\n```\n\n---\n\n## Usage\n\n```bash\ntoolkit --help                # all global flags\n```\n\n### Global Flags\n\n| Flag | Default | Description |\n| ---- | ------- | ----------- |\n| `--config` | `~/.config/toolkit/config.yaml` | Path to config file (YAML or JSON) |\n| `--repo-path` |  | Path to the repository |\n| `--env-type` |  | Environment type (e.g. dev, prod) |\n| `--env-region` |  | Environment region |\n| `--env-realm` |  | Environment realm |\n| `--category, -c` |  | Category to display |\n| `--filter, -f` |  | Initial filter for current category |\n| `--metadata-file` | `~/.config/toolkit/metadata.yaml` | Optional additional metadata file |\n| `--kubeconfig` | `~/.kube/config` | Path to kubeconfig file |\n| `--log-file` | `toolkit.log` | Path to log file |\n| `--debug` | `false` | Enable debug logging |\n| `--log-format` | `console` | Log format: `console`, `json`, or `slog` |\n| `--log-level` | | Minimum log level: `debug`, `info`, `warn`, `error` (empty uses `--debug` flag) |\n| `--mutation-env-override-allowed` | `false` | Allow MCP mutation tools to override the startup env per call (off by default for safety) |\n\n*(See `internal/cli/flags.go` for the authoritative list.)*\n\n### Headless `get` (for scripts and LLM integration)\n\n`toolkit get \u003ccategory\u003e` is the non-TUI equivalent of selecting a category in the interactive UI. It uses the same loaders and emits machine-friendly output for piping into `jq`, posting to LLM tools, feeding spreadsheets, or driving shell pipelines.\n\nSupported formats (`-o`): `table` (default), `json`, `jsonl`, `yaml`, `csv`, `tsv`.\n\n```bash\n# JSON array (default pretty-printed)\ntoolkit get tenant -o json\n\n# Line-delimited JSON (great for streaming / `xargs`)\ntoolkit get gpunode -f us-ashburn-1 -o jsonl\n\n# Plain table (default)\ntoolkit get dac\n\n# YAML\ntoolkit get basemodel -f cohere -o yaml\n\n# CSV for spreadsheets (proper quoting via encoding/csv)\ntoolkit get tenant -o csv \u003e tenants.csv\n\n# TSV for `cut` / `awk` pipelines\ntoolkit get gpupool -o tsv | cut -f1,3\n\n# Suppress headers (table/csv/tsv)\ntoolkit get tenant --no-headers\n```\n\nCategory aliases match the TUI (`t`, `bm`, `gn`, `dac`, …). Run `toolkit get alias` for the full list, or enable shell completion (`toolkit completion zsh`) for tab-completion. Logs are written to `--log-file` (default `toolkit.log`) so stdout stays clean for parsing.\n\nFor `gpunode`, `dac`, `modelartifact`, and the tenancy-override categories, the structured outputs (`json`, `jsonl`, `yaml`) are a flat array of objects with the originating group key injected as `pool`, `tenant`, or `model` — easier for `jq` and LLM consumers than the previous map-shaped output.\n\n### Inspect effective config (`toolkit config`)\n\n`toolkit config` prints the merged view every other subcommand sees — defaults + `TOOLKIT_*` env + config file + flags — so you can see what's actually in effect without opening the YAML by hand:\n\n```bash\ntoolkit config                    # YAML (default)\ntoolkit config -o json            # JSON for `jq`\ntoolkit config --pretty=false     # compact JSON\ntoolkit config --validate         # run config.Validate(); exit non-zero on failure\n```\n\n`--validate` mode emits a structured `{valid, config_file, error?}` payload and exits non-zero on failure — suitable for `if ! toolkit config --validate; then abort; fi` precondition checks in CI/scripts.\n\n### Cluster mutations\n\nMaintenance operations the TUI exposes via keyboard shortcuts are also available as scriptable subcommands. All mutations support `--dry-run` (preview the action) and `--yes` / `-y` (skip the interactive prompt). Each call writes a JSON line to the audit log.\n\n| Command | Effect |\n| ------- | ------ |\n| `toolkit cordon \u003cnode\u003e` / `toolkit uncordon \u003cnode\u003e` | Toggle scheduling on a Kubernetes node |\n| `toolkit drain \u003cnode\u003e` | Evict pods and cordon |\n| `toolkit reboot \u003cnode\u003e` | Reboot the underlying instance |\n| `toolkit scale gpu-pool \u003cname\u003e` | Sync OCI instance-pool size to the Terraform-declared `pool.Size` (no `--size` flag — Terraform is the source of truth). The `gpupool` alias is accepted for back-compat. |\n| `toolkit delete dac \u003cname\u003e` | Delete a dedicated AI cluster (destructive — requires `--yes`) |\n| `toolkit terminate \u003cnode\u003e` | Terminate the underlying OCI instance (destructive — requires `--yes`) |\n\nExample:\n\n```bash\ntoolkit drain node-42 --dry-run     # preview\ntoolkit drain node-42 -y            # run without prompt\n```\n\nSee [docs/recipes.md](docs/recipes.md) for end-to-end flows (MCP setup, maintenance windows, audit exports, Slack digests).\n\n### MCP server (`toolkit mcp`)\n\nFor agent integration via the [Model Context Protocol](https://modelcontextprotocol.io), `toolkit mcp` boots a stdio MCP server that exposes the same loader surface as `get` — but as typed tools an AI agent can call directly, no shell-out needed.\n\nConfigure once in your MCP client. Claude Desktop / Claude Code use JSON:\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"toolkit\": {\n      \"command\": \"toolkit\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\nCodex CLI (`~/.codex/config.toml`) uses TOML:\n\n```toml\n[mcp_servers.toolkit]\ncommand = \"toolkit\"\nargs = [\"mcp\"]\n```\n\nSee [docs/recipes.md](docs/recipes.md) for the per-client file paths and first prompts to try.\n\n**Read tools** — return a `{ \"items\": [...], \"count\": N, \"warnings\": [...] }` envelope:\n\n| Tool | Description |\n| ---- | ----------- |\n| `list_tenants` | Tenants in the configured realm |\n| `list_base_models` | Base models from the cluster |\n| `list_gpu_pools` | GPU pools (partial-load warnings surfaced) |\n| `list_gpu_nodes` | GPU nodes (flat, with `pool` field) |\n| `list_dacs` | Dedicated AI clusters (flat, with `tenant` field) |\n| `list_environments` | All known toolkit environments |\n| `list_service_tenancies` | Service tenancies from the repo |\n| `list_model_artifacts` | Model artifacts (flat, with `model` field) |\n| `list_definitions` | `kind`: `limit` / `console_property` / `property` |\n| `list_tenancy_overrides` | Same `kind` enum, tenancy-scoped |\n| `list_regional_overrides` | Same `kind` enum, region-scoped |\n| `list_aliases` | Discovery — every category alias |\n\nEvery read tool takes an optional `filter` (fuzzy substring) and optional `env_type` / `env_region` / `env_realm` to override the startup env per-call, so a single running server can answer questions across multiple environments.\n\n**Mutation tools** — gated on `confirm: true`. The same safety model as the CLI: failures surface via `notifications/message`, every call writes to the audit log:\n\n| Tool | Effect |\n| ---- | ------ |\n| `cordon_node` / `uncordon_node` | Toggle Kubernetes node scheduling |\n| `drain_node` | Evict pods and cordon |\n| `reboot_node` | Reboot the underlying instance |\n| `scale_gpu_pool` | Resize an OCI GPU instance pool |\n| `delete_dac` | Delete a dedicated AI cluster |\n| `terminate_node` | Terminate the underlying OCI instance |\n\nBy default, mutation tools ignore any per-call `env_type` / `env_region` / `env_realm` (MCP tool input fields — these stay snake_case as the JSON-schema field names) and only act in the startup env — the operator's credentials decide the maximum blast radius, not the agent. Pass `--mutation-env-override-allowed` at server start to opt in to per-call env routing.\n\n---\n\n## Project Layout\n\n```\n.\n├── cmd/\n│   └── toolkit/            # main()\n├── internal/\n│   ├── cli/                # cobra root \u0026 sub-commands\n│   ├── ui/tui/             # Bubble Tea models \u0026 views\n│   ├── infra/\n│   │   ├── k8s/            # K8s data sources\n│   │   └── terraform/      # Terraform provider\n│   ├── config/             # typed config structs\n│   ├── configloader/       # env + file loader\n│   ├── collections/        # generic filter/sort\n│   └── encoding/jsonutil/  # JSON helpers\n├── pkg/\n│   ├── infra/logging/      # zap-based logging\n│   └── models/             # domain models and types\n└── test/\n    └── integration/\n```\n\n---\n\n### Build\n\n```sh\nmake\n```\nor\n```sh\ngo build -o bin/toolkit ./cmd/toolkit\n```\n\n### Run\n\n```sh\n./bin/toolkit --help\n```\nor, if built with Go:\n```sh\ngo run ./cmd/toolkit --help\n```\n\n## Testing\n\nRun all tests with:\n```sh\ngo test ./...\n```\n\n#### Running tests\n\n- Unit tests (default):\n  ```sh\n  make test\n  ```\n- Integration tests (with build tag):\n  ```sh\n  make test-int\n  ```\n- Coverage reports:\n  ```sh\n  make cover      # unit test coverage\n  make cover-int  # integration test coverage\n  ```\n\n#### Continuous Integration\n\n- **Unit tests** run on all pushes and pull requests.\n- **Integration tests** run on pushes to `main` and nightly (see `.github/workflows/ci.yml`).\n- **CI target**: Run `make ci` to execute both lint and test in one step (recommended for local and CI use).\n\n## Developer Workflow\n\n- One-time setup: `make setup` (installs golangci-lint, gofumpt, goimports)\n- Optional: enable git hooks with pre-commit: `pre-commit install`\n- Run `make ci` before pushing to ensure code passes lint and tests.\n- Use `make lint` to check for style and static analysis issues.\n- Use `make test` for a full race-enabled test run.\n- Use `make fmt` and `make tidy` to auto-format and tidy dependencies.\n\n## Architecture Overview\n\nToolkit follows a modular, testable architecture:\n- **Loaders**: `internal/infra/loader` provides concrete and interface-based loaders for datasets (K8s, Terraform, OCI), enabling dependency injection and testability.\n- **TUI Model**: `internal/ui/tui` contains Bubble Tea models, views, and update loop; composed via functional options.\n- **Domain types**: `pkg/models` defines strongly-typed domain models used across loaders and UI.\n- **Category enum**: `internal/domain/category.go` provides strongly-typed categories and parsing.\n- **Logging**: `pkg/infra/logging` wraps zap for structured logs with configurable format and file path.\n\n## Logging\n\nToolkit uses [zap](https://github.com/uber-go/zap) for structured, machine-readable logging. By default logs are written to `toolkit.log` (configurable via `--log-file`) and support `--log-format` of `console`, `json`, or `slog`. The minimum log level can be set via `--log-level` (`debug`, `info`, `warn`, `error`).\n\n## Contributing\n\nContributions are welcome! Please open issues or submit pull requests for new features, bug fixes, or improvements.\n\n---\n\n## License\n\nThis project is licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjingle2008%2Ftoolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjingle2008%2Ftoolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjingle2008%2Ftoolkit/lists"}