Skip to content

Repository files navigation

treblle

The command-line interface for the Treblle Platform.

List the APIs in your workspace, inspect the requests and endpoints Treblle has observed, upload OpenAPI specifications, and score them against Treblle's governance rules — from your terminal or from CI.

$ treblle apis list
┌───────────────┬───────────┬────────────┬────────┬─────────┬───────────────┐
│NAME           │SDK        │REQUESTS    │SCORE   │ISSUES   │LAST REQUEST   │
├───────────────┼───────────┼────────────┼────────┼─────────┼───────────────┤
│Billing API    │laravel    │1.2M        │A       │0        │2m ago         │
│Identity API   │express    │410K        │C       │7        │11m ago        │
└───────────────┴───────────┴────────────┴────────┴─────────┴───────────────┘

$ treblle governance design-time --api api_xxx --fail-under 80
Grade:         A
Score:         91.5%
Spec version:  2.1.0
Uploaded:      2d ago

Contents


Install

With Go

go install github.com/Treblle/cli/cmd/treblle@latest

Requires Go 1.25 or newer. The binary lands in $(go env GOPATH)/bin — make sure that directory is on your PATH.

Download a release binary

Prebuilt binaries for macOS, Linux and Windows (amd64 and arm64) are attached to every release. No runtime is needed — it is a single static binary.

VERSION=0.1.2          # see the releases page for the latest
OS=darwin              # darwin | linux | windows
ARCH=arm64             # amd64 | arm64

curl -sSLO "https://github.com/Treblle/cli/releases/download/v${VERSION}/treblle_${VERSION}_${OS}_${ARCH}.tar.gz"
tar -xzf "treblle_${VERSION}_${OS}_${ARCH}.tar.gz"
sudo mv treblle /usr/local/bin/

treblle --version

Every release also publishes a checksums.txt if you want to verify the download. On Windows the archive is a .zip instead of a .tar.gz.

From source

git clone https://github.com/Treblle/cli.git
cd cli

make build      # -> ./bin/treblle
make install    # -> $GOPATH/bin/treblle

Quickstart

Three commands and you are running:

treblle auth login     # paste a personal access token
treblle configure      # choose the workspace to work in
treblle apis list      # confirm it works

treblle configure also runs the login step if you have not authenticated yet, so it works as a single entry point too.

Creating a token

treblle auth login prints a link to your Treblle developer settings. Two details there are easy to miss, and both stop the token from working:

Important

  • Set the app to platform. A token scoped to a different Treblle app authenticates fine but carries no permissions here, so every command fails with 403. treblle auth login catches this and refuses the token rather than saving something that cannot work.
  • Multi-factor authentication must be enabled on your account, or token creation is silently refused.

Choosing Never for the expiry means you never have to repeat this.

Check where you stand at any time:

treblle auth status

Command reference

Command What it does
treblle auth login Authenticate with a personal access token
treblle auth status Show the active profile, user, app scope and token expiry
treblle configure Authenticate if needed, then choose and save a workspace
treblle apis list List the APIs in the active workspace
treblle apis get <id> Show one API
treblle requests list --api <id> List the requests logged for an API
treblle requests get <id> --api <id> Show one logged request
treblle endpoints list --api <id> List the endpoints discovered for an API
treblle endpoints get <id> --api <id> Show one endpoint
treblle specs list --api <id> List the specifications uploaded to an API
treblle specs get <id> --api <id> Show one specification
treblle specs upload <file> --api <id> Upload an OpenAPI specification
treblle governance design-time --api <id> Score the uploaded specification
treblle governance run-time --api <id> Score the observed traffic

Every command supports --help. Most have short aliases — api, request, endpoint, spec, gov, and show in place of get.

Global flags

Flag Purpose
--profile <name> Use a named configuration profile (default default)
--workspace <id> Operate on a specific workspace, ignoring the saved one
-o, --output <format> table (default) or json
--version Print the CLI version

Every list command (apis, requests, endpoints, specs) also takes --limit and --all.

Note

The API caps a page at 100 results. Use --all to fetch every page rather than passing a large --limit.

Tip

-o json returns the API response unchanged, which is exactly what you want for jq and for scripting. Note that it includes fields the tables deliberately leave out — api_key, ip_address, external_user_id — so tables stay safe to show on a shared screen.


Using the CLI

Everything except apis is scoped to a single API, so those commands need --api. Get an id from treblle apis list.

Listing APIs

treblle apis list
treblle apis list --search billing --sdk laravel
treblle apis list --sort -requests --limit 50
treblle apis list --all -o json | jq '.data[].attributes.name'
Flag Filter
--search name or URL
--sdk SDK, for example laravel, express, django
--type API type
--category category id
--environment environment id

Sort by name, score, issues, requests, latency, created, updated or last-request. Prefix with - for descending.

treblle apis get api_xxx
treblle apis get api_xxx -o json | jq '.data.attributes.api_key'

Inspecting requests

treblle requests list --api api_xxx
treblle requests list --api api_xxx --method POST --status 500,4xx
treblle requests list --api api_xxx --period hour,24 --sort -latency
treblle requests list --api api_xxx --all -o json | jq '.data[].attributes.path'
Flag Filter
--search request path, at least 3 characters
--status status code — comma-separated, and 4xx-style classes work
--method HTTP method, comma-separated
--endpoint endpoint id, comma-separated
--period time window, as unit,valueminute, hour, day, week, month (e.g. hour,24)
--user external user id

Sort by created, path, method, endpoint, latency, threat, device or location. Newest first unless you say otherwise.

treblle requests get req_xxx --api api_xxx
treblle requests get req_xxx --api api_xxx -o json | jq '.data.attributes.request.headers'

The detail view prints identity and timing. The captured traffic itself — headers, bodies, queries, server data — routinely carries Authorization headers and cookies, so it is left to -o json.

Exploring endpoints

treblle endpoints list --api api_xxx
treblle endpoints list --api api_xxx --zombie
treblle endpoints list --api api_xxx --period day,7 --sort -requests
treblle endpoints get ep_xxx --api api_xxx
Flag Filter
--search endpoint path
--method HTTP method, comma-separated
--in-docs only endpoints in the docs (--in-docs=false for those excluded)
--has-problems only endpoints with problems (--has-problems=false for those without)
--zombie only zombie endpoints — no traffic in 30 days

Sort by path, rpm, requests, latency, created or updated.

Warning

endpoints --period changes the numbers, not which rows appear — it sets the window that request counts and load times are measured over, defaulting to 90 days. It also accepts only a fixed set of windows (minute,1, minute,5, hour,1, hour,24, hour,48, hour,72, day,1 through day,180, week,1, week,2, month,1 to month,3); anything else is rejected rather than silently falling back to 90 days. This is unlike governance run-time --period, which is free-form.

Managing specifications

treblle specs list --api api_xxx
treblle specs list --api api_xxx --sort -score
treblle specs get spec_xxx --api api_xxx

treblle specs upload openapi.yaml --api api_xxx
treblle specs upload openapi.json --api api_xxx --yes    # no prompt, for CI

Uploads accept .json, .yaml and .yml up to 15 MB, and add a version rather than replacing anything — the API rejects a version it already holds. The version comes from info.version in the document and must read as 1.0.0 or v1.

specs list takes --search to filter by file name or version, and sorts by file, version, created, source, score or uploader. A specification that is still being generated is not listed until it completes.

Important

specs upload is the one command that writes, so it asks for confirmation. With no terminal attached it refuses instead of guessing — pass --yes in a pipeline. Uploading also queues a governance run, so neither the new version nor its score is readable immediately.


Governance and failing a build

Governance is two separate reports:

  • design-time scores the OpenAPI specification you uploaded.
  • run-time scores the traffic Treblle has actually observed.
treblle governance design-time --api api_xxx
treblle governance design-time --api api_xxx --tests
treblle governance design-time --api api_xxx --spec-version 1.2.0

treblle governance run-time --api api_xxx
treblle governance run-time --api api_xxx --period day,30 --tests

Both print an overall grade, then a per-category breakdown with a count of tests that did not pass. --tests lists those findings in full, with the reason and the remediation attached to each.

Grade:         C
Score:         72.5%
Spec version:  1.4.0
Uploaded:      2d ago

┌───────────────┬───────┬───────┬───────┬─────────┐
│CATEGORY       │GRADE  │SCORE  │TESTS  │FAILING  │
├───────────────┼───────┼───────┼───────┼─────────┤
│Security       │D      │50%    │2      │1        │
│Documentation  │A      │95%    │2      │1        │
└───────────────┴───────┴───────┴───────┴─────────┘

run-time --period takes any unit,value and defaults to day,7.

--fail-under

--fail-under turns either report into a build step. It takes a percentage against the overall score, and it is under — a score exactly on the threshold passes.

treblle governance design-time --api api_xxx --fail-under 80 --tests
treblle governance run-time --api api_xxx --fail-under 90 --period day,30

The report is printed before the verdict, so a failing gate still leaves the score and its categories in the log. -o json is unaffected: stdout stays parseable either way, and the verdict goes to stderr and the exit code.

Warning

An API that was never scored fails the gate, even at --fail-under 0. Design-time answers an API with no uploaded specification with a zero score and an F, and run-time answers a window with no governance runs the same way. Those are exactly the states a pipeline should catch — but note the consequence: a freshly deployed API with a short --period legitimately has no data yet, and will fail.

Grades are not accepted as a threshold; the API documents grade as an unconstrained string, so ordering the letters would be a contract the CLI cannot actually check.


Running in CI/CD

The CLI is built for pipelines: a single static binary, environment variables instead of config files, and no prompts when there is no terminal.

1. Set two secrets

Environment variables override the config files entirely, so CI needs no ~/.treblle at all:

Variable Value
TREBLLE_TOKEN A personal access token scoped to the platform app
TREBLLE_WORKSPACE The workspace id (from treblle configure)

2. Know the exit codes

Code Meaning
0 Success
1 The command failed — no credentials, no workspace, a bad flag, a network or API error
2 A governance threshold was not met

2 exists so a pipeline can tell a verdict about the API from a fault in the run: a --fail-under breach is a real result and should fail the build, while an expired token failing the same step means the build never got an answer at all. Nothing but --fail-under returns 2.

GitHub Actions

Gate a pull request on the design-time score:

name: API governance

on: pull_request

jobs:
  governance:
    runs-on: ubuntu-latest
    env:
      TREBLLE_TOKEN: ${{ secrets.TREBLLE_TOKEN }}
      TREBLLE_WORKSPACE: ${{ secrets.TREBLLE_WORKSPACE }}
      TREBLLE_API: ${{ vars.TREBLLE_API }}
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-go@v5
        with:
          go-version: '1.25'

      - name: Install the Treblle CLI
        run: go install github.com/Treblle/cli/cmd/treblle@latest

      - name: Score the API specification
        run: treblle governance design-time --api "$TREBLLE_API" --fail-under 80 --tests

Publish the specification once the change is merged:

name: Publish API specification

on:
  push:
    branches: [main]
    paths: ['openapi.yaml']

jobs:
  upload:
    runs-on: ubuntu-latest
    env:
      TREBLLE_TOKEN: ${{ secrets.TREBLLE_TOKEN }}
      TREBLLE_WORKSPACE: ${{ secrets.TREBLLE_WORKSPACE }}
      TREBLLE_API: ${{ vars.TREBLLE_API }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.25'
      - run: go install github.com/Treblle/cli/cmd/treblle@latest
      - run: treblle specs upload openapi.yaml --api "$TREBLLE_API" --yes

Important

Keep upload and scoring in separate runs. An upload queues a governance run asynchronously, so scoring in the very next step would grade the previous version and report a stale result as if it were the new one.

GitLab CI

api-governance:
  image: golang:1.25
  variables:
    TREBLLE_API: api_xxx
  before_script:
    - go install github.com/Treblle/cli/cmd/treblle@latest
  script:
    - treblle governance design-time --api "$TREBLLE_API" --fail-under 80 --tests

Add TREBLLE_TOKEN and TREBLLE_WORKSPACE as masked, protected CI/CD variables.

Any other runner

Nothing above is GitHub- or GitLab-specific. Download the release binary and export the two variables:

# Pin whichever version you want from the releases page.
curl -sSL https://github.com/Treblle/cli/releases/download/v0.1.2/treblle_0.1.2_linux_amd64.tar.gz | tar -xz
export TREBLLE_TOKEN="$MY_SECRET_TOKEN"
export TREBLLE_WORKSPACE=wsp_xxx

./treblle governance run-time --api api_xxx --period day,30 --fail-under 90

Without a terminal

With no TTY attached the CLI never prompts:

echo "$TREBLLE_PAT" | treblle auth login    # reads the token from stdin
treblle configure --workspace wsp_xxx       # --workspace instead of a picker
treblle specs upload openapi.yaml --api api_xxx --yes

Configuration

Settings live in two files under ~/.treblle, split so the secret can carry a stricter mode:

# ~/.treblle/config.yaml  (0644)
default:
  base_url:     https://api.treblle.com/v1
  identity_url: https://auth.treblle.com
  workspace:    wsp_xxx
  output:       table
# ~/.treblle/credentials.yaml  (0600)
default:
  token:      "..."
  expires_at: null    # null means the token never expires
  app:        platform

credentials.yaml is written 0600, and the CLI refuses to read it if anyone else can.

Profiles

Profiles work like the AWS CLI's: a named block in both files, selected with --profile, TREBLLE_PROFILE, or defaulting to default.

treblle configure --profile staging
treblle apis list --profile staging

Environment variables

These override the files entirely.

Variable Purpose
TREBLLE_TOKEN Personal access token
TREBLLE_WORKSPACE Workspace id
TREBLLE_BASE_URL API base URL
TREBLLE_PROFILE Profile to use
TREBLLE_CONFIG_DIR Config directory (default ~/.treblle)

Development

make check    # fmt, vet, test, verify-spec
make test
make build

Contributions are welcome — open an issue or a pull request. CI runs formatting, go vet, the race-enabled test suite, and the spec check on every pull request.

Keeping up with the platform API

api/openapi.json is a synced copy of the platform repository's spec. make verify-spec checks that every route the CLI calls still exists in it, so an upstream rename fails in CI rather than in someone's terminal. Refresh it with make sync-spec (set PLATFORM_REPO if your checkout is not at ../platform).

The spec drifts from the live API in a few places, which is why the request and endpoint commands are written against the platform's controllers instead:

  • Filter names are filter[http_codes] and filter[endpoints], not the singular forms the spec documents. The API ignores an unrecognised filter rather than rejecting it, so the documented names would return an unfiltered list that looks filtered.
  • formatted_load_time and formatted_response_size are typed as strings but arrive as {value, unit, is_good} objects.
  • The spec lists no filters on the requests collection; the controller accepts the full set the CLI exposes.

Several filters also fail silently on a value they cannot parse — a malformed --period, a search below the minimum length, an unrecognised metrics window — so the CLI validates those before sending rather than letting the API return everything as if it had filtered.

Releasing

Publishing is driven by the tag. Pushing v1.2.3 runs the tests, builds the binaries with GoReleaser, attaches them to a GitHub Release, and makes go install github.com/Treblle/cli/cmd/treblle@v1.2.3 work.

Authentication

Login goes through a LoginStrategy interface with one implementation today (paste). A browser-based loopback flow is the intended second one; the seam exists so adding it changes no commands, no config format, and no client code.

About

Treblle Command Line Tool

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages