{"id":51161568,"url":"https://github.com/doitintl/perfectscale-cli","last_synced_at":"2026-06-26T14:01:44.129Z","repository":{"id":357327778,"uuid":"1236439296","full_name":"doitintl/perfectscale-cli","owner":"doitintl","description":"A cli that uses Perfectscale's public API ","archived":false,"fork":false,"pushed_at":"2026-06-22T06:10:36.000Z","size":93,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T07:25:37.764Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/doitintl.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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-12T08:46:20.000Z","updated_at":"2026-06-22T06:10:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/doitintl/perfectscale-cli","commit_stats":null,"previous_names":["doitintl/perfectscale-cli"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/doitintl/perfectscale-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2Fperfectscale-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2Fperfectscale-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2Fperfectscale-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2Fperfectscale-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doitintl","download_url":"https://codeload.github.com/doitintl/perfectscale-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doitintl%2Fperfectscale-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34819597,"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-06-26T02:00:06.560Z","response_time":106,"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":[],"created_at":"2026-06-26T14:01:43.579Z","updated_at":"2026-06-26T14:01:44.105Z","avatar_url":"https://github.com/doitintl.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Perfectscale CLI\n\n`pscli` is a small Go CLI for querying Perfectscale's public API with a UI-generated service token.\n\nIt is optimized for fast terminal exploration and agent-friendly output, with:\n\n- stored local auth profiles\n- sensible production defaults\n- table, JSON, and JSONL output\n- workload filtering, sorting, aggregation, and CSV export\n- GitHub Actions builds for macOS, Windows, and Linux\n\n## What It Supports\n\nThis CLI is intentionally public-API only.\n\nCurrent command groups:\n\n- `auth`\n  - `login`\n  - `status`\n  - `logout`\n- `clusters`\n  - `list`\n  - `get`\n  - `emission`\n- `namespaces`\n  - `list`\n- `workloads`\n  - `list`\n  - `summary`\n  - `group-by namespace`\n  - `group-by type`\n  - `group-by optimization-policy`\n  - `group-by risk-severity`\n  - `group-by label`\n  - `show`\n  - `export`\n  - `risky`\n  - `labels`\n  - `muted`\n- `automation`\n  - `audit-logs`\n\n## Authentication\n\nThe CLI uses Perfectscale public API service tokens from the Perfectscale UI.\n\nTo generate one:\n\n1. Open `app.perfectscale.io`\n2. Click the user circle in the bottom left\n3. Open `Org Settings`\n4. Open `API Tokens`\n5. Click `Generate Token`\n6. Assign a `Read Only` role\n7. Copy the `client_id` and `client_secret`\n\nIf you run `pscli auth` without saved credentials, the CLI prints the same setup guide plus a ready-to-copy login example.\n\nThen log in:\n\n```bash\npscli auth login\n```\n\nOr pass the credentials directly:\n\n```bash\npscli auth login --client-id 'YOUR_CLIENT_ID' --client-secret 'YOUR_CLIENT_SECRET'\n```\n\nThe CLI validates the token by calling the public auth endpoint and saves the profile locally.\n\n## Defaults\n\nThe CLI is designed so common usage does not require flags.\n\nDefault profile:\n\n```text\ndefault\n```\n\nDefault output:\n\n```text\ntable\n```\n\nDefault public API base URL:\n\n```text\nhttps://api.app.perfectscale.io/public/v1\n```\n\nIf you do not export any environment variables and do not pass any global flags, the CLI will talk to production.\n\n## Environment Variables\n\nGlobal flags can be set through environment variables:\n\n- `PERFECTSCALE_PROFILE`\n- `PERFECTSCALE_OUTPUT`\n- `PERFECTSCALE_DEBUG`\n- `PERFECTSCALE_PUBLIC_API_URL`\n\nExamples:\n\n```bash\nexport PERFECTSCALE_PROFILE='dev-public'\nexport PERFECTSCALE_PUBLIC_API_URL='https://api.dev.perfectscale.click/public/v1'\nexport PERFECTSCALE_OUTPUT='jsonl'\n```\n\n## Local Credential Storage\n\nProfiles are stored under the OS config directory.\n\nOn macOS, the default profile path is usually:\n\n```text\n~/Library/Application Support/perfectscale-cli/profiles/default.json\n```\n\nStorage behavior:\n\n- profile directory permissions: `0700`\n- profile file permissions: `0600`\n- `auth logout` deletes the selected local profile\n\n## Build And Run\n\nRequirements:\n\n- Go 1.24+\n\nRun directly:\n\n```bash\ngo run . clusters list\n```\n\nBuild locally:\n\n```bash\nmake build\n./dist/pscli clusters list\n```\n\nOr build the binary directly:\n\n```bash\ngo build -o pscli .\n./pscli clusters list\n```\n\nRegenerate the local public API client:\n\n```bash\nmake openapi\n```\n\nRun tests:\n\n```bash\ngo test ./...\n```\n\n## Global Options\n\nThese flags work at the top level and on leaf commands.\n\n- `--profile`, `-p`\n- `--output`, `-o`\n- `--debug`, `-d`\n- `--public-api-url`, `-u`\n\nOutput modes:\n\n- `table`\n  - human-friendly terminal output\n- `json`\n  - one JSON document\n- `jsonl`\n  - one JSON object per line for list commands and automation\n\nExample:\n\n```bash\npscli -o jsonl workloads list -c prod-a -s waste -r desc -T 10\n```\n\n## Common Short Options\n\nThe CLI uses short options consistently across commands:\n\n- `-p` profile\n- `-o` output\n- `-u` public API URL\n- `-d` debug\n- `-c` cluster\n- `-w` period window\n- `-n` namespace\n- `-m` workload name\n- `-t` workload type\n- `-s` sort\n- `-r` order\n- `-T` top\n- `-B` bottom\n- `-C` min-cost\n- `-W` min-waste\n- `-V` workload view\n- `-i` id or client-id, depending on command\n- `-k` client-secret or label key, depending on command\n- `-f` export format\n- `-F` export file\n- `-S` min-severity\n- `-v` label value\n\n## Quick Start\n\nLog in:\n\n```bash\npscli auth login\n```\n\nCheck auth:\n\n```bash\npscli auth status\n```\n\nList clusters:\n\n```bash\npscli clusters list\n```\n\nInspect one cluster:\n\n```bash\npscli clusters get -c prod-a\n```\n\nShow top wasteful workloads:\n\n```bash\npscli workloads list -c prod-a -s waste -r desc -T 10\n```\n\nShow least wasteful workloads:\n\n```bash\npscli workloads list -c prod-a -s waste -r asc -B 10\n```\n\nList namespaces:\n\n```bash\npscli namespaces list -c prod-a -s workloads -r desc\n```\n\n## Workload Filtering\n\n`workloads list` supports client-side filtering and ranking with:\n\n- `--cluster`, `-c`\n- `--period`, `-w`\n- `--namespace`, `-n`\n- `--name`, `-m`\n- `--type`, `-t`\n- `--min-cost`, `-C`\n- `--min-waste`, `-W`\n- `--sort`, `-s`\n- `--order`, `-r`\n- `--top`, `-T`\n- `--bottom`, `-B`\n- `--view`, `-V`\n\nImportant:\n\n- the public workloads API is fixed to `30d` today\n- the CLI enforces `--period 30d`\n- non-cluster filters are applied client-side after the workload list is fetched\n\nExamples:\n\n```bash\npscli workloads list -c prod-a -n kube-system -s waste -r desc\npscli workloads list -c prod-a -m api -t Deployment -C 25 -W 10\npscli workloads list -c prod-a -s cost -r desc -T 20\n```\n\n## Workload Views\n\n`workloads list` supports view presets through `--view` or `-V`.\n\nAvailable views:\n\n- `default`\n  - cost, waste, namespace, type, and max-indicator overview\n- `capacity`\n  - replica counts and current vs recommended request totals\n- `usage`\n  - summed container usage percentiles\n- `policy`\n  - optimization policy, resilience, and mute state\n- `risk`\n  - risk severity, risk counts, and waste counts\n- `all`\n  - the broadest enriched workload view\n\nSpecial behavior:\n\n- if `--view all` is used without explicitly setting `--output`, the CLI switches to `jsonl`\n- this makes the full enriched workload objects easier to consume in pipelines and by agents\n\nExamples:\n\n```bash\npscli workloads list -c prod-a -V default\npscli workloads list -c prod-a -V capacity\npscli workloads list -c prod-a -V usage\npscli workloads list -c prod-a -V policy\npscli workloads list -c prod-a -V risk\npscli workloads list -c prod-a -V all\npscli -o json workloads list -c prod-a -V all\n```\n\n## Workload Aggregations\n\nCluster summary:\n\n```bash\npscli workloads summary -c prod-a\n```\n\nGroup by namespace:\n\n```bash\npscli workloads group-by namespace -c prod-a -s waste -r desc -T 10\n```\n\nGroup by workload type:\n\n```bash\npscli workloads group-by type -c prod-a -s workloads -r desc\n```\n\nGroup by optimization policy:\n\n```bash\npscli workloads group-by optimization-policy -c prod-a -s waste -r desc\n```\n\nGroup by risk severity:\n\n```bash\npscli workloads group-by risk-severity -c prod-a -s workloads -r desc\n```\n\nGroup by label value:\n\n```bash\npscli workloads group-by label -c prod-a -k team -s waste -r desc\n```\n\n## Detailed Workload Commands\n\nShow one workload:\n\n```bash\npscli workloads show -c prod-a -i workload-123\npscli workloads show -c prod-a -m api -n backend\n```\n\nExport CSV:\n\n```bash\npscli workloads export -c prod-a -F workloads.csv\npscli workloads export -c prod-a -n kube-system -s waste -r desc -T 25\n```\n\nList risky workloads:\n\n```bash\npscli workloads risky -c prod-a -S 2 -s severity -r desc -T 10\n```\n\nExplore workload labels:\n\n```bash\npscli workloads labels -c prod-a\npscli workloads labels -c prod-a -k app -s waste -r desc -T 20\npscli workloads labels -c prod-a -v production\n```\n\nList muted workloads:\n\n```bash\npscli workloads muted -c prod-a -s expires -r asc\n```\n\n## Cluster Commands\n\nList clusters:\n\n```bash\npscli clusters list\n```\n\nGet cluster details:\n\n```bash\npscli clusters get -c prod-a\n```\n\nShow carbon emission metrics:\n\n```bash\npscli clusters emission -c prod-a -s value -r desc\n```\n\n## Namespace Commands\n\nNamespaces are derived from workloads.\n\nExamples:\n\n```bash\npscli namespaces list -c prod-a\npscli namespaces list -c prod-a -s workloads -r desc\npscli namespaces list -c prod-a -n kube -T 5\n```\n\n## Automation Commands\n\n`automation audit-logs` lists the actions Perfectscale's automation took in your\nclusters. The endpoint is cursor-paginated and returns events from the last 30\ndays.\n\nExamples:\n\n```bash\npscli automation audit-logs\npscli automation audit-logs -c prod-a -c prod-b\npscli automation audit-logs -c prod-a -n kube-system -n default\npscli automation audit-logs --from 2026-04-01T00:00:00Z --to 2026-04-15T00:00:00Z\npscli automation audit-logs --since 24h\npscli automation audit-logs --all -o jsonl\npscli automation audit-logs --page-size 200 --after BASE64CURSOR\n```\n\nNotes:\n\n- `--cluster` (`-c`) and `--namespace` (`-n`) are repeatable. Cluster values\n  may be UID or name.\n- `--from` and `--to` accept RFC3339 (UTC). `--since` accepts a relative\n  duration (`24h`, `7d`, `30m`) and is shorthand for `--from now-since`.\n- `--page-size` is 1–5000 (default 1000).\n- `--after` / `--before` consume cursor tokens from a previous response's\n  `pagination.next` / `pagination.prev`.\n- `--all` auto-paginates forward until the server reports `has_next=false`,\n  capped by `--page-cap` (default 50) as a safety net.\n- `--execution` filters client-side to one of `regular-eviction`,\n  `inplace-resize`, or `cleanup`.\n\n## Release Workflow\n\nGitHub Actions is configured in [build.yml](./.github/workflows/build.yml).\n\nBehavior:\n\n- runs tests on every `push` and `pull_request`\n- cross-builds binaries for:\n  - macOS `arm64`\n  - Windows `amd64`\n  - Linux `amd64`\n  - Linux `arm64`\n- uploads workflow artifacts for each target\n- on pushes to the repository default branch:\n  - determines the next version starting at `v1.0.0`\n  - increments the patch version on each new commit\n  - creates or reuses a GitHub Release\n  - uploads all built binaries as release assets\n\nCurrent asset names:\n\n- `pscli-darwin-arm64.tar.gz`\n- `pscli-windows-amd64.zip`\n- `pscli-linux-amd64.tar.gz`\n- `pscli-linux-arm64.tar.gz`\n\nEach release archive contains a `pscli` binary, or `pscli.exe` on Windows.\n\nIn addition, every release publishes `perfectscale-skill.zip` — a portable\n\"skill\" bundle for coding agents (Claude Code, OpenAI Agents SDK, etc.) that\nteaches them how to drive `pscli`. Source lives under [skill/perfectscale](./skill/perfectscale).\nBuild it locally with `make skill`.\n\n## OpenAPI Generation\n\nThis repo keeps its own local copy of the public OpenAPI spec at:\n\n- [public-api.yaml](./public-api.yaml)\n\nThe generated public API client lives at:\n\n- [internal/publicapi/client.gen.go](./internal/publicapi/client.gen.go)\n\nImportant rules:\n\n- do not hand-edit the generated client\n- update the local YAML spec first\n- regenerate with `make openapi`\n- the handwritten adapter in [internal/api/client.go](./internal/api/client.go) stays responsible for:\n  - auth headers\n  - response validation\n  - mapping generated types into CLI types\n  - derived workload fields used by views and summaries\n\n## Known Limits\n\n- only service-token auth is supported\n- only the public API is supported\n- workloads are fixed to a `30d` period because the public endpoint is fixed-window\n- namespace and many workload filters are client-side\n- there is no first-class public nodegroup command yet\n- CSV is the only export format in v1\n\n## Next Steps\n\nThese are the next improvements we discussed, ordered by how much they unlock for the CLI with minimal API churn.\n\n### Public API improvements\n\n1. Add `period` support to public workloads.\n   This would unlock `1d` and `7d` views for cost and waste instead of the current fixed `30d` behavior.\n\n2. Add a few optional server-side filters to public workloads.\n   Best first candidates:\n   - `namespace`\n   - `name`\n   - `type`\n   - `node_group`\n   - `node_type`\n   - `reservation_type`\n\n   This would reduce payload size, speed up the CLI, and make agent queries more precise.\n\n3. Expose nodegroup placement on each workload.\n   Best shapes:\n   - `primaryNodeGroup`\n   - or better, `runningMinutesByNodeGroup`\n\n   This would enable:\n   - `nodegroups list`\n   - `group-by nodegroup`\n   - \"top wasteful workloads on nodegroup X\"\n\n### CLI follow-ups once the API expands\n\n- add `workloads group-by nodegroup`\n- add `nodegroups list --cluster ...`\n- allow non-`30d` workload periods\n- push more filters server-side when the API supports them\n\n### CLI follow-ups that might still useful even without API changes\n\n- add `--fields` for exact field projection on `workloads list`, `show`, and `export`\n- add `--raw` on `workloads show`\n- add `workloads containers` for per-container inspection\n- add more export formats if needed beyond CSV\n\n## Repo Layout\n\nKey directories and files:\n\n- [main.go](./main.go)\n  - CLI entrypoint\n- [internal/cli](./internal/cli)\n  - command definitions, runtime, rendering, aggregations\n- [internal/api](./internal/api)\n  - public API adapter and response mapping\n- [internal/publicapi](./internal/publicapi)\n  - generated public OpenAPI client\n- [public-api.yaml](./public-api.yaml)\n  - local public OpenAPI spec copy used for generation\n- [internal/auth](./internal/auth)\n  - service-token exchange and token refresh\n- [internal/profile](./internal/profile)\n  - local profile storage\n- [internal/output](./internal/output)\n  - table, JSON, and JSONL output\n- [Makefile](./Makefile)\n  - OpenAPI regeneration and common developer tasks\n- [.github/workflows/build.yml](./.github/workflows/build.yml)\n  - CI, cross-builds, and releases\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoitintl%2Fperfectscale-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoitintl%2Fperfectscale-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoitintl%2Fperfectscale-cli/lists"}