Getting Started

Quickstart

Turn your OpenAPI spec into a production-ready CLI in under 5 minutes. No Go experience required — petl handles generation, building, and distribution.

01

Create a CLI

Register your CLI definition and get a telemetry token.

02

Upload your spec

Submit your OpenAPI 3.x YAML. We generate and build the binary.

03

Ship it

Download binaries for all platforms. Publish install scripts.

petl

Core Concepts

Three objects you'll work with constantly.

CLIpermanent

The top-level object that represents your CLI product. Has a stable identity (ID, telemetry token, env prefix) that persists across all versions. Think of it like a GitHub repo — the container, not the content.

idnamemodule_pathenv_prefixtelemetry_tokencurrent_version
CLIVersionimmutable

A specific release of your CLI tied to a spec hash. Once built, a version is immutable. Versions move through states: pending → building → ready → deprecated. Same spec + same config always produces the same binary (deterministic).

versionspec_hashstatusartifactspublished_at
TelemetryEventanalytics only

Every command invocation from every deployed binary emits one event. Events are attributed to your CLI via the telemetry token baked into the binary at generation time. You never interact with events directly — they flow through the Metrics API.

commandcaller_typeagent_typeduration_msexit_codeflags_used
API Reference

Authentication

All management API endpoints require your provider API key.

Authorization: Bearer petl_pk_<your-key>

Generate your key in the API Key section of your dashboard. Keys are shown once — store them securely (environment variables, a secrets manager). If lost, rotate immediately.

Error responses

401Missing or invalid API key
403Key valid but resource belongs to another provider
429Rate limit exceeded — back off and retry

CLIs

Create and manage your CLI definitions.

Versions

Submit specs, track builds, publish releases. The same spec + config always produces the same binary — duplicate submissions return the existing build instantly.

Uploads are multipart/form-data. The spec field is your OpenAPI YAML file. The optional config field is a petl.yml for command tree overrides.

Version status lifecycle

pendingbuildingreadydeprecatedorfailed

Metrics

Aggregated analytics over your CLI's telemetry events. All endpoints accept a ?period=7d|30d|90d query param (default 7d).

Telemetry

How It Works

Every generated CLI has a telemetry emitter baked in. It fires one event per command invocation — async, non-blocking, and silent on failure. Your users never feel it.

petl

Non-blocking

Events fire in a goroutine after the command exits. CLIs never wait for delivery.

At-least-once

A 3-second flush window on exit ensures events arrive even for fast commands.

Opt-out

Users set ACME_NO_TELEMETRY=1 to disable entirely. Missing data is expected — not an error.

Token attribution

The telemetry token baked into each binary maps events back to your CLI automatically.

Privacy Model

Telemetry is designed to be structurally incapable of capturing sensitive data — not just policy-prohibited.

Flag values
never

Only flag names are captured (e.g. ["output", "filter"]). Values like --output=secret are never transmitted.

Base URLs
hashed

The API base URL is SHA-256 hashed (first 16 chars) so you can distinguish prod vs staging without exposing endpoints.

Session IDs
opaque

Session IDs come from the agent's own environment (e.g. CLAUDE_CODE). Treated as opaque — never deanonymized.

IP addresses
never

The ingest endpoint never logs source IPs. No consent required because no PII is captured.

Auth commands
excluded

configure, login, and logout commands are never wrapped with telemetry. Credentials can't accidentally leak.

Event Schema

Every telemetry event has this shape. Fields are set by the runtime — you never construct them manually.

{
  // Identity
  "cli_id":      "petl_tok_...",  // maps to your CLI
  "cli_name":    "acme",
  "cli_version": "1.2.0",

  // Invocation
  "command":     "events list",         // full cobra path
  "caller_type": "agent",               // "human" | "agent" | "ci"
  "agent_type":  "claude_code",         // which AI tool
  "session_id":  "sess_abc123",         // from agent env var

  // Timing
  "timestamp":   "2026-04-19T12:00:00Z",
  "duration_ms": 312,

  // Usage
  "flags_used":     ["output", "filter"],  // names only, never values
  "output_format":  "json",
  "used_jq":        false,
  "used_schema":    false,
  "used_dry_run":   false,

  // Result
  "exit_code":   0,
  "error_code":  "",
  "http_status": 200,

  // Environment
  "base_url_hash": "a3f9c2b1d4e7f8a0"    // SHA-256 of base URL, first 16 chars
}