diff --git a/fern/products/cli-generator/cli-generator.yml b/fern/products/cli-generator/cli-generator.yml index d7c49b516..64d334cc6 100644 --- a/fern/products/cli-generator/cli-generator.yml +++ b/fern/products/cli-generator/cli-generator.yml @@ -7,6 +7,13 @@ navigation: - page: Features path: ./features.mdx slug: features + - page: Configuration + path: ./configuration.mdx + slug: configuration + - page: Publishing + path: ./publishing.mdx + slug: publishing + hidden: true - page: Authentication path: ./authentication.mdx slug: authentication diff --git a/fern/products/cli-generator/configuration.mdx b/fern/products/cli-generator/configuration.mdx new file mode 100644 index 000000000..3e0bbb458 --- /dev/null +++ b/fern/products/cli-generator/configuration.mdx @@ -0,0 +1,190 @@ +--- +title: Configuration +description: Configure CLI generation in generators.yml with generator-specific options, output targets, GitHub integration, and shared settings. +availability: beta +--- + + +The CLI generator is in early access. [Reach out](https://buildwithfern.com/book-demo?type=cli) to get started. + + +Configure the CLI generator in `generators.yml`. The configuration has two layers: generator-specific options under `config`, and shared options (`output`, `github`, `audiences`, `metadata`, `smart-casing`) that work the same way as for [SDK generators](/learn/sdks/reference/generators-yml). + +```yaml title="generators.yml" {6-8} +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + config: + binaryName: my-cli + customCommands: true + github: + repository: my-org/my-cli + mode: pull-request +``` + +## Generator-specific options + + +Name of the compiled binary. Determines the executable filename, the Cargo `[[bin]]` target name, and the environment-variable prefix used for [TLS, proxy, and logging settings](/learn/cli-generator/get-started/features#tls-proxies-and-ca-bundles). + +When omitted, the generator derives the name from the API definition's display name (kebab-cased). Multi-spec workspaces must set this field explicitly — there is no sensible auto-derivation when multiple specs are present. + +```yaml title="generators.yml" +config: + binaryName: contoso +``` + +The binary name `contoso` produces: +- Executable: `contoso` +- Env-var prefix: `CONTOSO` (e.g. `CONTOSO_CA_BUNDLE`, `CONTOSO_LOG`) + + + +Controls whether the generator produces the custom command infrastructure alongside the CLI binary. When enabled, the output includes: + +- A `-types` library crate (typed serde structs) +- A `-sdk` library crate (HTTP client accessible via `ctx.client()`) +- Scaffolding files for user-authored command handlers + +Set to `false` to produce a spec-only CLI with no custom command support. + +```yaml title="generators.yml" +config: + customCommands: false +``` + + +## Shared options + +The following options from the [generators.yml reference](/learn/sdks/reference/generators-yml) apply to the CLI generator identically to SDK generators. + +### `github` + +Specifies how generated CLI code is delivered to your repository. Supports the same [modes as SDKs](/learn/sdks/reference/generators-yml#github): `release`, `pull-request`, and `push`. + +```yaml title="generators.yml" +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + config: + binaryName: my-cli + github: + repository: my-org/my-cli + mode: release +``` + +| Mode | Behavior | +| --- | --- | +| `release` | Commits to the default branch and tags a new release. Triggers CI workflows that build and publish the binary. | +| `pull-request` | Opens a PR with the generated source for review before merging. | +| `push` | Pushes directly to the specified branch. Requires `branch` field. | + +### `output` + +Configures where to publish the generated CLI. The CLI generator supports `npm` and `local-file-system` output locations. + + + + +Publish the CLI as an npm package. Users install with `npm install -g @myorg/my-cli` or `npx @myorg/my-cli`. + +```yaml title="generators.yml" +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + output: + location: npm + package-name: "@myorg/my-cli" + token: "${NPM_TOKEN}" + config: + binaryName: my-cli +``` + + + +Write the generated Rust project to a local directory for manual building and distribution. + +```yaml title="generators.yml" +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + output: + location: local-file-system + path: ../my-cli + config: + binaryName: my-cli +``` + + + +### `audiences` + +Filter which API endpoints are included in the generated CLI based on audience tags. Only endpoints tagged with the specified audiences in your API spec (via [`x-fern-audiences`](/learn/api-definitions/openapi/extensions/audiences)) produce commands. Without this filter, all endpoints generate commands. + +```yaml title="generators.yml" +groups: + cli: + audiences: ["external"] + generators: + - name: fern-cli-generator + version: 0.6.1 + config: + binaryName: my-cli +``` + +### `smart-casing` + +Enables intelligent case conversion that preserves numbers and common programming patterns in generated command and flag names. + +```yaml title="generators.yml" +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + smart-casing: true + config: + binaryName: my-cli +``` + +### `metadata` + +Attach package metadata to the generated CLI for use in published artifacts. + +```yaml title="generators.yml" +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + metadata: + package-description: "CLI for the Contoso API" + author: "Contoso Inc." + reference-url: "https://docs.contoso.com/cli" + config: + binaryName: contoso +``` + +### `api` + +Override authentication settings at the generator level. This uses the same schema as the [SDK generator-level `api.auth`](/learn/sdks/reference/generators-yml#override-api-authentication-settings) to control which auth schemes the CLI uses. + +```yaml title="generators.yml" +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + api: + auth: BearerAuth + config: + binaryName: my-cli +``` diff --git a/fern/products/cli-generator/features.mdx b/fern/products/cli-generator/features.mdx index f7d770175..8eb534827 100644 --- a/fern/products/cli-generator/features.mdx +++ b/fern/products/cli-generator/features.mdx @@ -1,6 +1,6 @@ --- title: Features -description: Explore the capabilities of Fern's generated CLIs, including output formatting, pagination, dry-run mode, and TLS configuration. +description: Explore the capabilities of Fern's generated CLIs, including output formatting, retries, pagination, dry-run mode, and TLS configuration. availability: beta --- @@ -8,7 +8,7 @@ availability: beta The CLI generator is in early access. [Reach out](https://buildwithfern.com/book-demo?type=cli) to get started. -Generated CLIs ship with a common set of runtime flags and environment variables: output formatting, pagination, dry-run previewing, TLS and proxy configuration, exit codes, and structured logging. APIs with templated server URLs also expose per-variable flags and environment variables. +Generated CLIs ship with a common set of runtime flags and environment variables: output formatting, retries with exponential backoff, pagination, dry-run previewing, TLS and proxy configuration, exit codes, and structured logging. APIs with templated server URLs also expose per-variable flags and environment variables. ## Output formatting @@ -37,6 +37,28 @@ Pass `--dry-run` to validate arguments and preview the HTTP request without send contoso plants get --params '{"plantId": "abc"}' --dry-run ``` +## Retries with backoff + +Failed requests are retried automatically with exponential backoff. A request retries as long as the status code is retryable and the retry limit has not been reached. + +| Setting | Default | +| --- | --- | +| Total attempts | 4 (initial + 3 retries) | +| Base delay | 500 ms | +| Backoff factor | 2x | +| Jitter | 10% | + +Retryable status codes: `408` (Timeout), `429` (Too Many Requests), and `5xx` (server errors). The CLI also honors `Retry-After` headers. + +Only idempotent methods (GET, HEAD, OPTIONS, DELETE, PUT) retry by default. POST and PATCH requests retry only when the endpoint is marked idempotent in the spec. + +Pass `--no-retry` on any command to disable retries for that invocation. + +```bash +# Disable retries for a single request +contoso plants create --json '{"name": "Monstera"}' --no-retry +``` + ## Pagination For endpoints annotated with [`x-fern-pagination`](/learn/api-definitions/openapi/extensions/pagination), the CLI auto-paginates when the `--page-all` flag is set. diff --git a/fern/products/cli-generator/publishing.mdx b/fern/products/cli-generator/publishing.mdx new file mode 100644 index 000000000..84b3c2171 --- /dev/null +++ b/fern/products/cli-generator/publishing.mdx @@ -0,0 +1,251 @@ +--- +title: Publishing +description: Publish your generated CLI to npm, Homebrew, and GitHub Releases with automated cross-platform builds. +availability: beta +--- + + +The CLI generator is in early access. [Reach out](https://buildwithfern.com/book-demo?type=cli) to get started. + + +Publish your generated CLI to npm, Homebrew, and GitHub Releases. After following the steps on this page, each tagged release builds cross-platform binaries and publishes them automatically. + + +This page assumes that you have: + +* An initialized `fern` folder with `generators.yml` configured for the CLI generator. See [Quickstart](/learn/cli-generator/get-started/quickstart). +* A GitHub repository for the generated CLI source. + + +## Distribution channels + +| Channel | Install command | Platforms | +| --- | --- | --- | +| npm | `npm install -g @myorg/my-cli` | All (via Node.js wrapper) | +| Homebrew | `brew install myorg/tap/my-cli` | macOS, Linux | +| GitHub Releases | Download binary from release assets | All | + +## Configure output location + + + + + +In the `group` for your CLI, set the output location to `npm`: + +```yaml title="generators.yml" {7-8} +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + output: + location: npm + config: + binaryName: my-cli +``` + + + + + +The package name must be unique in the npm registry. + +```yaml title="generators.yml" {9} +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + output: + location: npm + package-name: "@myorg/my-cli" + config: + binaryName: my-cli +``` + + + + + +## Configure GitHub publishing + +Fern publishes your CLI via GitHub Actions. Configure your GitHub repository and publishing mode: + +```yaml title="generators.yml" {10-12} +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + output: + location: npm + package-name: "@myorg/my-cli" + config: + binaryName: my-cli + github: + repository: my-org/my-cli + mode: release +``` + +| Mode | Behavior | +| --- | --- | +| `release` | Commits to the default branch and tags a release. The CI workflow builds binaries and publishes automatically. | +| `pull-request` | Opens a PR with generated source for review. Merge the PR and create a GitHub release to trigger publishing. | + +## Configure authentication + +Choose how to authenticate with npm when publishing. + + + + +OIDC-based publishing (trusted publishing) is the most secure option. npm trusts your GitHub repository to publish directly — no tokens to manage. + + + + + +Set `token: OIDC` in the `output` section: + +```yaml title="generators.yml" {9} +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + output: + location: npm + package-name: "@myorg/my-cli" + token: OIDC + config: + binaryName: my-cli + github: + repository: my-org/my-cli + mode: release +``` + + + + + +Generate the CLI to create the GitHub Actions workflow with OIDC configuration: + +```bash +fern generate --group cli +``` + +This creates a `.github/workflows/ci.yml` file configured for OIDC npm publishing. + + + + + +Configure trusted publishing on npmjs.com: + +1. Navigate to your package settings on npmjs.com +1. Find the **Trusted Publisher** section and click **Add trusted publisher** +1. Select **GitHub Actions** as your provider +1. Fill in: + - **Organization or user**: Your GitHub username or organization + - **Repository**: Your CLI repository name (e.g. `my-cli`) + - **Workflow filename**: `ci.yml` + - **Environment name**: Leave blank + +For details, see npm's [trusted publishing documentation](https://docs.npmjs.com/trusted-publishers). + + + + + + + + + + + + + +1. Log into [npmjs.com](https://www.npmjs.com/) +1. Click your profile picture and select **Access Tokens** +1. Click **Generate New Token** and choose **Automation** type +1. Save your token securely + + + + + +Set `token: ${NPM_TOKEN}` in the `output` section: + +```yaml title="generators.yml" {9} +groups: + cli: + generators: + - name: fern-cli-generator + version: 0.6.1 + output: + location: npm + package-name: "@myorg/my-cli" + token: ${NPM_TOKEN} + config: + binaryName: my-cli + github: + repository: my-org/my-cli + mode: release +``` + + + + + +1. Open your CLI repository on GitHub and go to **Settings** +1. Navigate to **Secrets and variables** > **Actions** +1. Click **New repository secret** +1. Name it `NPM_TOKEN` and paste your npm token +1. Click **Add secret** + + + + + + + + + +## Publish your CLI + +Your CLI publishes automatically when you create a GitHub release with a version tag: + +1. Run `fern generate --group cli` to push updated source to your CLI repository +1. Create a GitHub release with a version tag (e.g. `v1.0.0`) +1. The CI workflow builds binaries for all platforms and publishes to npm, Homebrew, and GitHub Releases + +## Build targets + +The CI workflow produces statically linked binaries for: + +| Target | OS | Architecture | +| --- | --- | --- | +| `x86_64-unknown-linux-gnu` | Linux | x86_64 | +| `aarch64-unknown-linux-gnu` | Linux | ARM64 | +| `x86_64-apple-darwin` | macOS | Intel | +| `aarch64-apple-darwin` | macOS | Apple Silicon | +| `x86_64-pc-windows-msvc` | Windows | x86_64 | + +The npm package wraps the native binary with a Node.js launcher. Platform-specific optional dependencies ensure only the correct binary downloads at install time. + +## Install instructions for users + +After publishing, direct users to install with their preferred method: + +```bash +# npm (all platforms) +npm install -g @myorg/my-cli + +# Homebrew (macOS / Linux) +brew install myorg/tap/my-cli + +# Direct download (any platform) +curl -fsSL https://github.com/my-org/my-cli/releases/latest/download/my-cli-x86_64-linux -o my-cli +chmod +x my-cli +```