Skip to content
FeedbackDashboard

Create a command line tool

Stainless can use your API specification to create a command line tool. Supports CRUD-like APIs, OpenAPI customization, and schema migrations.

This guide will show you how to generate a command line tool for your API. Your CLI can be used with shell scripts and other programs that can invoke shell commands.

The CLI generator creates a wrapper around your Go SDK with command line argument parsing. Thus, Go must be included as one of your SDK targets, and you must have a public-facing repository for your Go SDK.

Command line interfaces have some limitations that make it awkward to pass deeply nested structures as command line arguments. The command line interface generator will do its best to make the command line tool’s flags as ergonomic as possible, but you may have to provide deeply nested parameters in JSON or YAML format in some cases.

First, ensure that Go is enabled as a build target. After enabling Go, enable the CLI target, then save and build your project.

The build process will create a new repository for your CLI tool. Your CLI tool’s binary name will be taken from the targets.cli.binary_name field in your Stainless config. You can also optionally specify which Go SDK package and version you want to use.

targets:
go:
...
cli:
binary_name: your-project
options:
go_sdk_package: ...
go_sdk_version: ...

To test and debug your CLI tool before release, clone your CLI repo and run the tool with Go as documented in the repo’s README.md.

When you’re satisfied with your CLI tool, release it by following the steps to publish your SDK as you would with any other SDK target. Your published CLI tool will include man pages. When running locally, you can generate your man pages by running your-tool @manpages.

The basic structure of your command line tool follows this format:

Terminal window
your-tool [resource [sub-resource...]] method-name --method-arg value

For example, if your Stainless configuration had the following configuration:

resources:
$client:
methods:
current_status: get /status
people:
methods:
retrieve: get /person
create: post /person
list: get /people

Then your generated CLI tool could be used like this:

Terminal window
my-tool current-status
# Output: {"status": "Up and running!"}
Terminal window
my-tool people create --job "President" \
--name.full-name "Abraham Lincoln" \
--name.nickname "Abe Lincoln"
# Output: {
# "created": {
# "id": 123,
# "name": {
# "full_name": "Abraham Lincoln",
# "nickname": "Abe Lincoln"
# },
# "job": "President"
# }
# }
Terminal window
my-tool people retrieve --id 123
# Output: {
# "id": 123,
# "name": {
# "full_name": "Abraham Lincoln",
# "nickname": "Abe Lincoln"
# },
# "job": "President"
# }
Terminal window
my-tool people list
# Output: {
# "people": [
# {
# "name": {
# "full_name": "Abraham Lincoln",
# "nickname": "Abe Lincoln"
# },
# "job": "President"
# }
# ]

Note that method names like current-status and flags like --first-name use kebab-case, which is conventional for command line tools.

Full argument parsing documentation for your command line tool can be found using the --help flag:

Terminal window
# General help
my-tool --help
# Help for a specific endpoint
my-tool people create --help

In addition to specifying values via command line flags, you can also pipe JSON or YAML data to your CLI tool, which will be used as body parameters:

Terminal window
my-tool people create <<YAML
name:
full_name: Abraham Lincoln
nickname: Honest Abe
job: President
YAML
# Or:
cat person.json | my-tool people create
# Output: {
# "created": {
# "id": 123,
# "name": {
# "full_name": "Abraham Lincoln",
# "nickname": "Honest Abe"
# },
# "job": "President"
# }
# }

There are a small number of built-in top-level flags:

  • --help, -h: show a help message and exit.
  • --version, -v: print the CLI tool’s version and exit.
  • --base-url: provide a base URL for the API backend.
  • --format=...: change the output formatting (see below).
  • --debug: show debug information for HTTP requests and responses.

The default output format for CLI commands is formatted and syntax-highlighted JSON. You can select different output formats using the --format flag:

  • --format=auto: output format is automatically chosen, currently this defaults to json, but may change in the future.
  • --format=json: JSON output with autoformatting and syntax highlighting (or without syntax highlighting when used in a pipe or when the FORCE_COLOR=0 environment variable is set).
  • --format=jsonl: JSON output formatted to fit on a single line, or multiple lines for array-type responses.
  • --format=raw: the exact raw JSON response sent from the server (no formatting or coloring applied).
  • --format=yaml: the response in YAML format.
  • --format=pretty: a nice-looking human-readable format similar to YAML with a box around it.
  • --format=explore: an interactive TUI explorer that lets you browse through nested data.

For paginated endpoints, your CLI tool supports automatic pagination. Items will be lazily streamed from your API and sent to your user’s terminal pager of choice (e.g., $PAGER or less). New pages will be automatically loaded as the user scrolls down. This allows users to view as much or as little data as they want efficiently, without putting undue strain on your backend server.

If the CLI is used to pipe the response of a paginated endpoint to a tool like sed or yq, or if the tool is run from an environment that is not a terminal emulator, your CLI tool will stream its data to standard output.

The CLI tool will respect HTTP 429 (too many requests) responses from your server and slow the rate at which new pages are requested according to the policy defined in your response headers. This ensures requests for large amounts of data will automatically throttle to accommodate the rate-limiting policies of your backend server, and won’t be denied outright when rate limits are exceeded.

If you find a bug, have a question, or want to provide product feedback, let us know at support@stainless.com.