restish is a great API CLI tool

Mon, Sep 29, 2025 9-minute read

restish is a great API CLI tool

I really like huma. I think every API no matter how small should aim to have a OpenAPI document. It future proofs you, and with tools like Huma or goa its built in.

In the Huma docs the creator recommends a tool called restish - of which he is also the author. I played with it but to be honest didn’t really explore well enough to “get” it. Now I do.

If you have a public OpenAPI spec/doc you can add it to a restish namespace. Doing this saves the spec and lets restish “see” all of it including its request and response bodies.

Heres an example of Synadia Clouds API (it’s long):

API for Synadia Cloud

Usage:
  restish prod [flags]
  restish prod [command]

Signing Key Groups Commands:
  copy-account-sk-group                    Copy Account SK Group
  create-account-sk-group                  Create Account Signing Key Group
  delete-account-sk                        Delete Account Signing
  delete-account-sk-group                  Delete Account Signing Key Group
  get-account-sk                           Get Account Signing
  get-account-sk-group                     Get Account Signing Key Group
  list-account-sk-group                    List Account Signing Key Groups
  list-account-sk-group-keys               List Signing Keys
  rotate-account-sk                        Roate Active Signing Key
  update-account-sk                        Update Account Signing
  update-account-sk-group                  Update Account Signing Key Group

NATS Users Commands:
  assign-nats-user-team-app-user           Assign Team App User to NATS User
  copy-nats-user                           Copy nats user
  create-user                              Create NATS User
  delete-nats-user                         Delete NATS User
  download-nats-user-bearer-jwt            Get Bearer JWT
  download-nats-user-creds                 Get Creds
  download-nats-user-http-gw-token         Get HTTP Gateway Token
  get-nats-user                            Get NATS User
  list-account-sk-group-users              List NATS Users
  list-nats-user-connections               List NATs User Connections
  list-nats-user-issuances                 List nats user issuances
  list-nats-user-team-app-users            List Team App Users
  list-users                               List NATS Users
  rotate-nats-user                         Rotate nats user nkey and seed
  un-assign-nats-user-team-app-user        Unassign Team App User from NATS User
  update-nats-user                         Update NATS User

Accounts Commands:
  create-account                           Create Account
  create-or-update-nats-user-revocation    Create or Update Revocation for a NATS User NKey
  delete-account                           Delete Account
  delete-nats-user-revocation              Delete a for a NATS User NKey
  get-account                              Get Account
  get-account-export                       Export Account Seeds
  get-account-info                         Get Account Info
  get-account-metrics                      Get Account Metrics
  get-nats-user-revocation                 Get Revocation for a NATS User NKey
  list-account-connections                 List Account Connections
  list-accounts                            List Accounts
  list-accounts-overview-metrics           List Accounts overview metrics
  list-agent-tokens                        List Agent Tokens
  nats-core-websocket-viewer               Subscribe to a NATS Core subject over websockets
  unmanage-account                         Unmanage Account
  update-account                           Update Account

Alerts Commands:
  acknowledge-alert                        Acknowledge Alert
  create-alert-rule                        Create Account Alert Rule
  create-system-alert-rule                 Create System Alert Rule
  delete-alert-rule                        Delete Account Alert Rule
  delete-system-alert-rule                 Delete System Alert Rule
  get-alert                                Get Alert
  get-alert-rule                           Get Account Alert Rule
  get-system-alert-rule                    Get System Alert Rule
  list-alert-rules                         List Account Alert Rules
  list-alerts                              List Alerts
  list-system-alert-rules                  List System Alert Rules
  run-alert-rule                           Run Account Alert Rule
  run-system-alert-rule                    Run System Alert Rule
  update-alert-rule                        Update Account Alert Rule
  update-system-alert-rule                 Update System Alert Rules

App Users Commands:
  assign-account-team-app-user             Assign Team App User to Account
  assign-system-team-app-user              Assign Team App User to System
  assign-team-app-user                     Assign App User to Team
  create-app-user                          Create App User
  delete-app-user                          Delete App User
  get-app-user                             Get App User
  get-current-agent-token                  Get Current Agent Token
  list-account-team-app-users              List Account Team App Users
  list-app-user-roles                      List Roles
  list-app-users                           List App Users
  list-system-team-app-users               List System Team App Users
  list-team-app-users                      List App Users
  un-assign-account-team-app-user          Unassign Team App User from Account
  un-assign-system-team-app-user           Unassign Team App User from System
  un-assign-team-app-user                  Unassign App User from Team
  update-app-user                          Update App User
  update-team-app-user                     Update App User Team Assignment

JetStream Commands:
  delete-pull-consumer                     Delete Pull Consumer
  delete-push-consumer                     Delete Push Consumer
  get-jet-stream-placement-options         Get JetStream Placement Options
  get-pull-consumer-info                   Get Pull Consumer
  get-push-consumer-info                   Get Push Consumer
  list-jet-stream-assets                   List JetStream Assets
  update-pull-consumer                     Update Pull Consumer
  update-push-consumer                     Update Push Consumer

JetStream: KV Buckets Commands:
  create-kv-bucket                         Create KV Bucket
  create-kv-pull-consumer                  Create Pull Consumer
  create-kv-push-consumer                  Create Push Consumer
  delete-kv-bucket                         Delete KV Bucket
  get-kv-bucket                            Get KV Bucket
  list-kv-buckets                          List KV buckets
  list-kv-consumers                        List Consumers
  update-kv-bucket                         Update KV Bucket

JetStream: Mirrors Commands:
  create-mirror                            Create Mirror
  create-mirror-pull-consumer              Create Pull Consumer
  create-mirror-push-consumer              Create Push consumer
  delete-mirror                            Delete Mirror
  get-mirror                               Get Mirror
  list-mirror-consumers                    List Consumers
  list-mirrors                             List Mirrors
  update-mirror                            Update Mirror

JetStream: Object Buckets Commands:
  create-obj-pull-consumer                 Create Pull Consumer
  create-obj-push-consumer                 Create Push Consumer
  create-object-bucket                     Create Object Bucket
  delete-object-bucket                     Delete Object Bucket
  get-object-bucket                        Get Object Bucket
  list-obj-consumers                       List Consumers
  list-object-buckets                      List Object buckets
  update-object-bucket                     Update Object Bucket

JetStream: Streams Commands:
  create-pull-consumer                     Create Pull Consumer
  create-push-consumer                     Create Push Consumer
  create-stream                            Create Stream
  delete-stream                            Delete Stream
  get-stream-info                          Get Stream
  list-streams                             List Streams
  purge-kv-bucket                          Purge KV Bucket
  purge-mirror                             Purge Mirror
  purge-obj-bucket                         Purge Object Bucket
  purge-stream                             Purge Stream
  update-stream                            Update Stream

Sharing Commands:
  create-stream-export                     Create Stream Export
  create-stream-import                     Create Stream Import
  create-stream-shares                     Create Stream Shares
  create-subject-export                    Create Subject Export
  create-subject-import                    Create Subject Import
  create-subject-shares                    Create Subject Shares
  delete-stream-export                     Delete Stream Export
  delete-stream-import                     Delete Stream Import
  delete-stream-share                      Delete Stream Share
  delete-subject-export                    Delete Subject Export
  delete-subject-import                    Delete Subject Import
  delete-subject-share                     Delete Subject Share
  get-stream-export                        Get Stream Export
  get-stream-import                        Get Stream Import
  get-subject-export                       Get Subject Export
  get-subject-import                       Get Subject Import
  list-stream-exports                      List Stream Exports
  list-stream-exports-shared               List Shared Stream Exports
  list-stream-imports                      List Stream Imports
  list-stream-shares                       List Stream Shares
  list-subject-exports                     List Subject Exports
  list-subject-exports-shared              List Shared Subject Exports
  list-subject-imports                     List Subject Imports
  list-subject-shares                      List Subject Shares
  update-subject-export                    Update Subject Export
  update-subject-import                    Update Subject Import

Agent Tokens Commands:
  delete-agent-token                       Delete Agent Token

Auth Callout Commands:
  add-auth-callout-target-account          Configure Target Account
  add-auth-callout-user                    Create Auth Callout User
  delete-auth-callout                      Delete Auth Callout Config
  delete-auth-callout-target-account       Delete Target Account
  delete-auth-callout-user                 Delete Control Account User
  get-auth-callout                         Auth Callout Config
  list-auth-callout-authenticators         Get List of Available Authenticators
  list-auth-callout-target-accounts        Get Target Account List
  list-auth-callout-users                  Get Target Account List

Authorization Commands:
  check                                    Check Authz Decisions
  list-policies                            Get Policy List
  list-roles                               Get Authz roles List

Component Versions Commands:
  get-available-component-versions         Get Available Component Versions
  get-available-component-versions-by-type Get Available Component Versions By Type

Invitations Commands:
  decide-invitation                        Accept or reject team invitation
  invite-app-user                          Invite App Users
  list-invitations                         List of pending invitations

JetStream: Consumers Commands:
  list-consumers                           List Consumers

NATS User Issuances Commands:
  get-nats-user-issuance                   Get nats user issuance

Session Commands:
  accept-terms                             Accept terms
  create-app-user-access-token             Create Personal Access Token
  delete-personal-access-token             Delete Personal Access Token
  get-personal-access-token                Get Personal Access Token
  get-version                              Get Version
  leave-team                               Leave Team
  list-app-user-access-tokens              List Personal Access Tokens
  update-personal-access-token             Update Personal Access Token

Platform Components Commands:
  platform-component-connect               Connect a Platform Component

App Service Accounts Commands:
  create-app-service-account               Create App Service Account
  create-app-service-account-token         Create Acess Token for App Service Account
  delete-app-service-account               Delete App Service Account
  delete-app-service-account-token         Delete App Service Account Token
  get-app-service-account                  Get App Service Account
  get-app-service-account-token            Get App Service Account Token
  list-app-service-account-tokens          List Access Tokens for App Service Account
  list-app-service-accounts                List App Service Accounts
  update-app-service-account               Update App Service Account
  update-app-service-account-token         Update App Service Account Token

Team Service Accounts Commands:
  create-team-service-account-token        Create Acess Token for Team Service Account
  delete-team-service-account              Delete Team Service Account
  delete-team-service-account-token        Delete Team Service Account Token
  get-team-service-account                 Get Team Service Account
  get-team-service-account-token           Get Team Service Account Token
  list-team-service-account-tokens         List Access Tokens for Team Service Account
  update-team-service-account              Update Team Service Account
  update-team-service-account-token        Update Team Service Account Token

Systems Commands:
  bulk-share                               Share assets across accounts
  create-system                            Create System
  delete-system                            Delete System
  enable-auth-callout                      Enable Auth Callout For System
  get-component-token                      Get a component access token
  get-system                               Get System
  get-system-audit-job-result              Get Audit Job Result
  get-system-audit-job-status              Get Audit Job Status
  get-system-export                        Export System Seeds
  get-system-limits                        Get System Limits
  get-system-prometheus-metrics            Get Prometheus Metrics
  import-account                           Import Account
  import-user                              Import User
  list-auth-callout-configs                List Auth Callout Configs
  list-clusters                            List Clusters
  list-connections                         List Connections
  list-servers                             List Servers
  list-system-audit-jobs                   List Audit Jobs
  list-system-info-accounts                List System Accounts Info
  list-system-info-servers                 List System Servers info
  list-team-systems                        List Systems
  rotate-agent-token                       Rotate Agent Token
  run-system-audit-check                   Run System Audit Check
  system-jwt-sync                          Re-sync JWTs of all accounts in this system
  unmanage-system                          Unmanage System
  update-platform-components               Update Platform Components for System
  update-system                            Update System

Teams Commands:
  create-team                              Create Team
  create-team-service-account              Create Team Service Account
  delete-team                              Delete Team
  get-team                                 Get Team
  get-team-limits                          Get Team Limits
  import-system                            Import a System
  list-team-info-app-users                 List info of App Users in Team
  list-team-service-accounts               List Team Service Accounts
  list-teams                               List Teams
  update-team                              Update Team

Workloads Commands:
  get-workload-limits                      Get Workloads limits

Yep, that is every single endpoint from the doc.

If I want to list all consumers but don’t remember what the request body is?

Just use restish <namespace> list-consumers and it’ll print this.

List Consumers
## Argument Schema:

{
  stream-id: (string)
}


## Response 200 (application/json)

Success


{
  items*: [
    allOf{
      {
        ack_floor*: {
          consumer_seq*: (integer min:0 max:1.8446744073709552e+19)
          last_active: (string nullable:true)
          stream_seq*: (integer min:0 max:1.8446744073709552e+19)
        }
        cluster: allOf{
          {
            leader: (string)
            name: (string)
            replicas: [
              allOf{
                {
                  active*: (integer format:int64)
                  current*: (boolean)
                  lag: (integer min:0 max:1.8446744073709552e+19)
                  name*: (string)
                  offline: (boolean)
                }
              }
            ]
          }
        }
        config*: {
          ack_policy*: (string enum:none,all,explicit) enums have been changed to match UnmarshalJSON in https://github.com/nats-io/jsm.go/blob/main/api/consumers.go
          ack_wait: (integer format:int64)
          backoff: [
            (integer format:int64)
          ]
          deliver_group: (string)
          deliver_policy*: (string enum:all,last,new,by_start_sequence,by_start_time,last_per_subject)
          deliver_subject: (string)
          description: (string)
          direct: (boolean) Don't add to general clients.
          durable_name: (string)
          filter_subject: (string)
          filter_subjects: [
            (string)
          ]
          flow_control: (boolean)
          headers_only: (boolean)
          idle_heartbeat: (integer format:int64)
          inactive_threshold: (integer format:int64)
          max_ack_pending: (integer)
          max_batch: (integer)
          max_bytes: (integer)
          max_deliver: (integer)
          max_expires: (integer format:int64)
          max_waiting: (integer)
          mem_storage: (boolean)
          metadata: {
            <any>: (string)
          }
          name: (string)
          num_replicas*: (integer)
          opt_start_seq: (integer min:0 max:1.8446744073709552e+19)
          opt_start_time: (string nullable:true)
          rate_limit_bps: (integer min:0 max:1.8446744073709552e+19)
          replay_policy*: (string enum:instant,original)
          sample_freq: (string)
        }
        created*: (string format:date-time)
        delivered*: {
          consumer_seq*: (integer min:0 max:1.8446744073709552e+19)
          last_active: (string nullable:true)
          stream_seq*: (integer min:0 max:1.8446744073709552e+19)
        }
        name*: (string)
        num_ack_pending*: (integer)
        num_pending*: (integer min:0 max:1.8446744073709552e+19)
        num_redelivered*: (integer)
        num_waiting*: (integer)
        push_bound: (boolean)
        stream_name*: (string)
        ts*: (string format:date-time)
      }
    }
  ]
}


## Responses 400/401/403/404
# truncated...

To me this makes using API’s using a CLI actually possible without consulting the docs.

Walkthrough

Let’s walkthrough how to set all this up by using the restish example API.

restish api configure example
# next steps are interactive
restish api configure example https://api.rest.sh
> ? Select option Save and exit

We’ve told restish to associate https://api.rest.sh with the namespace of example. This is how we can segresgate many different API’s from one another.

Now we can auto detect what endpoints exist.

restish example

Which returns,

Usage:
  restish example [flags]
  restish example [command]

Echo Commands:
  delete-echo       
  get-echo          
  patch-echo        
  post-echo         
  put-echo          

Books Commands:
  delete-book       
  get-book          
  list-books        
  patch-book        Patch book
  put-book          

Caching Commands:
  get-cached        

Example Commands:
  get-example       

Images Commands:
  get-image         
  list-images       

Status Commands:
  get-status        

Types Commands:
  get-types-example 
  put-types-example 

I want to put-book but don’t know what I need to provide in the request body.

# restish example put-book -h
# truncating some output for brevity

## Argument Schema:

{
  book-id: (string)
}

## Option Schema:

{
  --if-match: [
    (string)
  ]
  --if-none-match: [
    (string)
  ]
  --if-modified-since: (string format:date-time-http) Succeeds if the server's
resource date is more recent than the passed date.
  --if-unmodified-since: (string format:date-time-http) Succeeds if the server's
resource date is older or the same as the passed date.
}

## Input Example

{
  "author": "string",
  "published": "2020-05-14T23:44:51-07:00",
  "rating_average": 1,
  "ratings": 1,
  "recent_ratings": [
    {
      "date": "2020-05-14T23:44:51-07:00",
      "rating": 1
    }
  ],
  "title": "string"
}

Now that we know what the request requires we can put a book into the collection

 echo '{
    "author": "Someone",
    "published": "1900-05-14T00:00:00-12:00",
    "rating_average": 4,
    "ratings": 30,
    "title": "My book is good"
    }' | restish example put-book good-book

# returns HTTP/2.0 204 No Content

And restish example list-books shows it in the collection

[
  {
    modified: 2025-09-29T03:36:11.74478507Z
    url: "/books/the-demon-haunted-world"
    version: "yWWo/Pq0gMgjMNgWw+K+Wg=="
  }
  {
    modified: 2025-09-29T03:36:11.74478507Z
    url: "/books/the-fabric-of-the-cosmos"
    version: "qhTFCaoJg92NnpRTMJzsEA=="
  }
  {
    modified: 2025-09-29T03:42:34.560280084Z
    url: "/books/good-book"
    version: "3Bvek8xG1BB3i+g4kvDzFg=="
  }
]

Of course you can also just use it like you would curl, here’s an example:

 restish api.github.com/users/rs | jq '{name, company, location, login, bio}'
> {
>   "name": "Olivier Poitrey",
>   "company": "Netflix",
>   "location": "Silicon Valley, California, USA",
>   "login": "rs",
>   "bio": "Director of Engineering at Netflix\r\nCo-Founder & ex-CTO of Dailymotion\r\nCo-Founder of NextDNS"
> }

There is a lot more to cover but thats some of the parts I really like.

restish is a tool that makes it much easier to stay in the terminal whilst interacting with a unfamiliar or complex API without needing the docs.

Tags:

#restish #api