https://github.com/doitintl/perfectscale-cli
A cli that uses Perfectscale's public API
https://github.com/doitintl/perfectscale-cli
Last synced: 25 days ago
JSON representation
A cli that uses Perfectscale's public API
- Host: GitHub
- URL: https://github.com/doitintl/perfectscale-cli
- Owner: doitintl
- License: mit
- Created: 2026-05-12T08:46:20.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-22T06:10:36.000Z (29 days ago)
- Last Synced: 2026-06-22T07:25:37.764Z (29 days ago)
- Language: Go
- Size: 90.8 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Perfectscale CLI
`pscli` is a small Go CLI for querying Perfectscale's public API with a UI-generated service token.
It is optimized for fast terminal exploration and agent-friendly output, with:
- stored local auth profiles
- sensible production defaults
- table, JSON, and JSONL output
- workload filtering, sorting, aggregation, and CSV export
- GitHub Actions builds for macOS, Windows, and Linux
## What It Supports
This CLI is intentionally public-API only.
Current command groups:
- `auth`
- `login`
- `status`
- `logout`
- `clusters`
- `list`
- `get`
- `emission`
- `namespaces`
- `list`
- `workloads`
- `list`
- `summary`
- `group-by namespace`
- `group-by type`
- `group-by optimization-policy`
- `group-by risk-severity`
- `group-by label`
- `show`
- `export`
- `risky`
- `labels`
- `muted`
- `automation`
- `audit-logs`
## Authentication
The CLI uses Perfectscale public API service tokens from the Perfectscale UI.
To generate one:
1. Open `app.perfectscale.io`
2. Click the user circle in the bottom left
3. Open `Org Settings`
4. Open `API Tokens`
5. Click `Generate Token`
6. Assign a `Read Only` role
7. Copy the `client_id` and `client_secret`
If you run `pscli auth` without saved credentials, the CLI prints the same setup guide plus a ready-to-copy login example.
Then log in:
```bash
pscli auth login
```
Or pass the credentials directly:
```bash
pscli auth login --client-id 'YOUR_CLIENT_ID' --client-secret 'YOUR_CLIENT_SECRET'
```
The CLI validates the token by calling the public auth endpoint and saves the profile locally.
## Defaults
The CLI is designed so common usage does not require flags.
Default profile:
```text
default
```
Default output:
```text
table
```
Default public API base URL:
```text
https://api.app.perfectscale.io/public/v1
```
If you do not export any environment variables and do not pass any global flags, the CLI will talk to production.
## Environment Variables
Global flags can be set through environment variables:
- `PERFECTSCALE_PROFILE`
- `PERFECTSCALE_OUTPUT`
- `PERFECTSCALE_DEBUG`
- `PERFECTSCALE_PUBLIC_API_URL`
Examples:
```bash
export PERFECTSCALE_PROFILE='dev-public'
export PERFECTSCALE_PUBLIC_API_URL='https://api.dev.perfectscale.click/public/v1'
export PERFECTSCALE_OUTPUT='jsonl'
```
## Local Credential Storage
Profiles are stored under the OS config directory.
On macOS, the default profile path is usually:
```text
~/Library/Application Support/perfectscale-cli/profiles/default.json
```
Storage behavior:
- profile directory permissions: `0700`
- profile file permissions: `0600`
- `auth logout` deletes the selected local profile
## Build And Run
Requirements:
- Go 1.24+
Run directly:
```bash
go run . clusters list
```
Build locally:
```bash
make build
./dist/pscli clusters list
```
Or build the binary directly:
```bash
go build -o pscli .
./pscli clusters list
```
Regenerate the local public API client:
```bash
make openapi
```
Run tests:
```bash
go test ./...
```
## Global Options
These flags work at the top level and on leaf commands.
- `--profile`, `-p`
- `--output`, `-o`
- `--debug`, `-d`
- `--public-api-url`, `-u`
Output modes:
- `table`
- human-friendly terminal output
- `json`
- one JSON document
- `jsonl`
- one JSON object per line for list commands and automation
Example:
```bash
pscli -o jsonl workloads list -c prod-a -s waste -r desc -T 10
```
## Common Short Options
The CLI uses short options consistently across commands:
- `-p` profile
- `-o` output
- `-u` public API URL
- `-d` debug
- `-c` cluster
- `-w` period window
- `-n` namespace
- `-m` workload name
- `-t` workload type
- `-s` sort
- `-r` order
- `-T` top
- `-B` bottom
- `-C` min-cost
- `-W` min-waste
- `-V` workload view
- `-i` id or client-id, depending on command
- `-k` client-secret or label key, depending on command
- `-f` export format
- `-F` export file
- `-S` min-severity
- `-v` label value
## Quick Start
Log in:
```bash
pscli auth login
```
Check auth:
```bash
pscli auth status
```
List clusters:
```bash
pscli clusters list
```
Inspect one cluster:
```bash
pscli clusters get -c prod-a
```
Show top wasteful workloads:
```bash
pscli workloads list -c prod-a -s waste -r desc -T 10
```
Show least wasteful workloads:
```bash
pscli workloads list -c prod-a -s waste -r asc -B 10
```
List namespaces:
```bash
pscli namespaces list -c prod-a -s workloads -r desc
```
## Workload Filtering
`workloads list` supports client-side filtering and ranking with:
- `--cluster`, `-c`
- `--period`, `-w`
- `--namespace`, `-n`
- `--name`, `-m`
- `--type`, `-t`
- `--min-cost`, `-C`
- `--min-waste`, `-W`
- `--sort`, `-s`
- `--order`, `-r`
- `--top`, `-T`
- `--bottom`, `-B`
- `--view`, `-V`
Important:
- the public workloads API is fixed to `30d` today
- the CLI enforces `--period 30d`
- non-cluster filters are applied client-side after the workload list is fetched
Examples:
```bash
pscli workloads list -c prod-a -n kube-system -s waste -r desc
pscli workloads list -c prod-a -m api -t Deployment -C 25 -W 10
pscli workloads list -c prod-a -s cost -r desc -T 20
```
## Workload Views
`workloads list` supports view presets through `--view` or `-V`.
Available views:
- `default`
- cost, waste, namespace, type, and max-indicator overview
- `capacity`
- replica counts and current vs recommended request totals
- `usage`
- summed container usage percentiles
- `policy`
- optimization policy, resilience, and mute state
- `risk`
- risk severity, risk counts, and waste counts
- `all`
- the broadest enriched workload view
Special behavior:
- if `--view all` is used without explicitly setting `--output`, the CLI switches to `jsonl`
- this makes the full enriched workload objects easier to consume in pipelines and by agents
Examples:
```bash
pscli workloads list -c prod-a -V default
pscli workloads list -c prod-a -V capacity
pscli workloads list -c prod-a -V usage
pscli workloads list -c prod-a -V policy
pscli workloads list -c prod-a -V risk
pscli workloads list -c prod-a -V all
pscli -o json workloads list -c prod-a -V all
```
## Workload Aggregations
Cluster summary:
```bash
pscli workloads summary -c prod-a
```
Group by namespace:
```bash
pscli workloads group-by namespace -c prod-a -s waste -r desc -T 10
```
Group by workload type:
```bash
pscli workloads group-by type -c prod-a -s workloads -r desc
```
Group by optimization policy:
```bash
pscli workloads group-by optimization-policy -c prod-a -s waste -r desc
```
Group by risk severity:
```bash
pscli workloads group-by risk-severity -c prod-a -s workloads -r desc
```
Group by label value:
```bash
pscli workloads group-by label -c prod-a -k team -s waste -r desc
```
## Detailed Workload Commands
Show one workload:
```bash
pscli workloads show -c prod-a -i workload-123
pscli workloads show -c prod-a -m api -n backend
```
Export CSV:
```bash
pscli workloads export -c prod-a -F workloads.csv
pscli workloads export -c prod-a -n kube-system -s waste -r desc -T 25
```
List risky workloads:
```bash
pscli workloads risky -c prod-a -S 2 -s severity -r desc -T 10
```
Explore workload labels:
```bash
pscli workloads labels -c prod-a
pscli workloads labels -c prod-a -k app -s waste -r desc -T 20
pscli workloads labels -c prod-a -v production
```
List muted workloads:
```bash
pscli workloads muted -c prod-a -s expires -r asc
```
## Cluster Commands
List clusters:
```bash
pscli clusters list
```
Get cluster details:
```bash
pscli clusters get -c prod-a
```
Show carbon emission metrics:
```bash
pscli clusters emission -c prod-a -s value -r desc
```
## Namespace Commands
Namespaces are derived from workloads.
Examples:
```bash
pscli namespaces list -c prod-a
pscli namespaces list -c prod-a -s workloads -r desc
pscli namespaces list -c prod-a -n kube -T 5
```
## Automation Commands
`automation audit-logs` lists the actions Perfectscale's automation took in your
clusters. The endpoint is cursor-paginated and returns events from the last 30
days.
Examples:
```bash
pscli automation audit-logs
pscli automation audit-logs -c prod-a -c prod-b
pscli automation audit-logs -c prod-a -n kube-system -n default
pscli automation audit-logs --from 2026-04-01T00:00:00Z --to 2026-04-15T00:00:00Z
pscli automation audit-logs --since 24h
pscli automation audit-logs --all -o jsonl
pscli automation audit-logs --page-size 200 --after BASE64CURSOR
```
Notes:
- `--cluster` (`-c`) and `--namespace` (`-n`) are repeatable. Cluster values
may be UID or name.
- `--from` and `--to` accept RFC3339 (UTC). `--since` accepts a relative
duration (`24h`, `7d`, `30m`) and is shorthand for `--from now-since`.
- `--page-size` is 1–5000 (default 1000).
- `--after` / `--before` consume cursor tokens from a previous response's
`pagination.next` / `pagination.prev`.
- `--all` auto-paginates forward until the server reports `has_next=false`,
capped by `--page-cap` (default 50) as a safety net.
- `--execution` filters client-side to one of `regular-eviction`,
`inplace-resize`, or `cleanup`.
## Release Workflow
GitHub Actions is configured in [build.yml](./.github/workflows/build.yml).
Behavior:
- runs tests on every `push` and `pull_request`
- cross-builds binaries for:
- macOS `arm64`
- Windows `amd64`
- Linux `amd64`
- Linux `arm64`
- uploads workflow artifacts for each target
- on pushes to the repository default branch:
- determines the next version starting at `v1.0.0`
- increments the patch version on each new commit
- creates or reuses a GitHub Release
- uploads all built binaries as release assets
Current asset names:
- `pscli-darwin-arm64.tar.gz`
- `pscli-windows-amd64.zip`
- `pscli-linux-amd64.tar.gz`
- `pscli-linux-arm64.tar.gz`
Each release archive contains a `pscli` binary, or `pscli.exe` on Windows.
In addition, every release publishes `perfectscale-skill.zip` — a portable
"skill" bundle for coding agents (Claude Code, OpenAI Agents SDK, etc.) that
teaches them how to drive `pscli`. Source lives under [skill/perfectscale](./skill/perfectscale).
Build it locally with `make skill`.
## OpenAPI Generation
This repo keeps its own local copy of the public OpenAPI spec at:
- [public-api.yaml](./public-api.yaml)
The generated public API client lives at:
- [internal/publicapi/client.gen.go](./internal/publicapi/client.gen.go)
Important rules:
- do not hand-edit the generated client
- update the local YAML spec first
- regenerate with `make openapi`
- the handwritten adapter in [internal/api/client.go](./internal/api/client.go) stays responsible for:
- auth headers
- response validation
- mapping generated types into CLI types
- derived workload fields used by views and summaries
## Known Limits
- only service-token auth is supported
- only the public API is supported
- workloads are fixed to a `30d` period because the public endpoint is fixed-window
- namespace and many workload filters are client-side
- there is no first-class public nodegroup command yet
- CSV is the only export format in v1
## Next Steps
These are the next improvements we discussed, ordered by how much they unlock for the CLI with minimal API churn.
### Public API improvements
1. Add `period` support to public workloads.
This would unlock `1d` and `7d` views for cost and waste instead of the current fixed `30d` behavior.
2. Add a few optional server-side filters to public workloads.
Best first candidates:
- `namespace`
- `name`
- `type`
- `node_group`
- `node_type`
- `reservation_type`
This would reduce payload size, speed up the CLI, and make agent queries more precise.
3. Expose nodegroup placement on each workload.
Best shapes:
- `primaryNodeGroup`
- or better, `runningMinutesByNodeGroup`
This would enable:
- `nodegroups list`
- `group-by nodegroup`
- "top wasteful workloads on nodegroup X"
### CLI follow-ups once the API expands
- add `workloads group-by nodegroup`
- add `nodegroups list --cluster ...`
- allow non-`30d` workload periods
- push more filters server-side when the API supports them
### CLI follow-ups that might still useful even without API changes
- add `--fields` for exact field projection on `workloads list`, `show`, and `export`
- add `--raw` on `workloads show`
- add `workloads containers` for per-container inspection
- add more export formats if needed beyond CSV
## Repo Layout
Key directories and files:
- [main.go](./main.go)
- CLI entrypoint
- [internal/cli](./internal/cli)
- command definitions, runtime, rendering, aggregations
- [internal/api](./internal/api)
- public API adapter and response mapping
- [internal/publicapi](./internal/publicapi)
- generated public OpenAPI client
- [public-api.yaml](./public-api.yaml)
- local public OpenAPI spec copy used for generation
- [internal/auth](./internal/auth)
- service-token exchange and token refresh
- [internal/profile](./internal/profile)
- local profile storage
- [internal/output](./internal/output)
- table, JSON, and JSONL output
- [Makefile](./Makefile)
- OpenAPI regeneration and common developer tasks
- [.github/workflows/build.yml](./.github/workflows/build.yml)
- CI, cross-builds, and releases