# faas-cli: the command line that turns a handler file into a deployed function

> faas-cli is the official OpenFaaS command line tool, and its job is to remove the boilerplate between a handler file and a running function: it builds a Docker image from a language template, pushes it to a registry, deploys it to a gateway, and keeps the gateway address and credentials in one place. It is opinionated around OpenFaaS and Docker, and a few of its commands are restricted to paid tiers.

**openfaas/faas-cli** — Official CLI for OpenFaaS

- Repository: https://github.com/openfaas/faas-cli
- Website: https://www.openfaas.com/
- Stars: 814 · Forks: 230
- Language: Go
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/openfaas-faas-cli

## The gap between a handler file and a running function

Serverless development has a repetitive middle section. You write a handler, and then you need a container image, a registry push, a function definition with an image reference, a way to tell the gateway about it, and a way to call it. Each of those steps is small on its own and tedious in aggregate, and each one is different on every platform.

faas-cli is the official CLI for OpenFaaS and exists to compress that middle section. The project states that you can build OpenFaaS functions from a set of supported language templates such as Node.js, Python, CSharp and Ruby, which means you write a handler file such as handler.py or handler.js and the CLI does the rest to create a Docker image.

That word templates is doing real work. A template supplies the Dockerfile, the language runtime and the boilerplate around your handler, so the only file you author is the function itself. The repository ships sample directories for the same idea, including sample/csharp-hello, sample/nodejs-echo, sample/ruby-echo, sample/url-ping and sample/get_captains, alongside hmac.yml and other configuration samples.

The audience is engineers already on OpenFaaS, plus newcomers who want a working function on their laptop before reading the platform documentation. The primary language of the implementation is Go, and the project is MIT licensed with a homepage at openfaas.com.

One design decision shapes the whole tool. The gateway is the API you deploy to, and the CLI treats its address as configurable state rather than a constant, which is what lets the same command work against a local development gateway and a production cluster.

## The command surface follows the deployment pipeline

The commands map onto the stages of shipping a function, which makes the tool easy to reason about.

faas-cli new creates a new function from a template in the current directory. faas-cli build builds a Docker image from the supported language types. faas-cli push pushes that image into a registry, and faas-cli deploy deploys the functions into a local or remote OpenFaaS gateway. faas-cli up is described as a combination of build, push and deploy, which is the command most pipelines actually use.

After deployment, faas-cli invoke calls a function and reads the request body from STDIN, which is what makes it usable in a shell pipeline. faas-cli remove takes functions back off the gateway, and faas-cli store lets you browse and deploy functions from the OpenFaaS store.

Two commands deal with credentials rather than code. faas-cli login stores basic auth credentials for the gateway and supports multiple gateways, with faas-cli logout removing them for a given gateway. faas-cli secret manages secrets for your functions. faas-cli registry-login generates a registry auth file in the correct format by giving a username and password for Docker, ECR or a self hosted registry, which avoids hand-writing that file.

One command stands apart. faas-cli publish builds and pushes multi-arch images for CI and release artifacts, which is a different job from deploying a function to a gateway, and faas-cli template pull brings templates in from a remote git repository, with detailed documentation in guide/TEMPLATE.md.

The implementation uses cobra and pflag for the command tree, and the go.mod lists the OpenFaaS provider and gateway client libraries alongside the Docker client, so the CLI talks to the gateway over its HTTP API rather than shelling out to something else.

## Installing the CLI and running your first command

There are several install routes and they differ in how current they are. The fastest on Linux and macOS is the utility script, run with root privileges so it can place the binary where your PATH will find it:

```bash
$ curl -sSL https://cli.openfaas.com | sudo sh
```

If you would rather not use sudo, the same script runs as your own user, and the documentation notes that further actions are required as advised after downloading:

```bash
$ curl -sSL https://cli.openfaas.com | sh
```

On macOS, Homebrew is the usual path:

```bash
$ brew install faas-cli
```

The caveat on that one is stated plainly: the brew release may not run the latest minor release, though it is updated regularly. If you need the newest version, the releases page is the source of truth. An npm installation route is listed as coming soon, with the command given as `npm install --global @openfaas/faas-cli` and separate npm instructions in the npm README.

On Windows, the documentation points you at the releases page for faas-cli.exe, and also gives a PowerShell snippet that reads the latest tag from the GitHub API and downloads the binary:

```powershell
$version = (Invoke-WebRequest "https://api.github.com/repos/openfaas/faas-cli/releases/latest" | ConvertFrom-Json)[0].tag_name
(New-Object System.Net.WebClient).DownloadFile("https://github.com/openfaas/faas-cli/releases/download/$version/faas-cli.exe", "faas-cli.exe")
```

Once installed you get both the faas-cli command and a shorter faas alias. Running faas-cli --help lists everything, and faas-cli help or faas-cli [command] --help covers individual commands. Building from source is documented in CONTRIBUTING.md, which also covers setting up a Golang development environment.

## How the CLI decides which gateway to talk to

The default gateway URL is 127.0.0.1:8080, and it can be overridden in three places, which are listed in a strict priority order.

First priority is the --gateway flag. Second priority is the --yaml or -f flag, or a stack.yaml file if one exists in the current directory. Third priority is the OPENFAAS_URL environment variable. Because the flag wins over the file and the file wins over the environment, a script can point at one gateway with a variable and still override it for a single command without editing the file.

For Kubernetes users the documentation suggests setting this in your .bash_rc file, with the NodePort address of the gateway:

```bash
export OPENFAAS_URL=http://127.0.0.1:31112
```

Templates follow the same pattern. The default template URL is https://github.com/openfaas/templates.git, and it can be overridden in two places, first by CLI input and second by the OPENFAAS_TEMPLATE_URL environment variable. The template pull command is how a remote template repository enters the picture, which is what lets a team keep its own house style of Dockerfile and handler scaffolding rather than always using the upstream set.

There is also a debug switch worth knowing about. Setting FAAS_DEBUG=1 makes the CLI print out the HTTP request it is making to the OpenFaaS gateway, which turns an opaque failure into something you can read when a deploy does not do what you expected.

## envsubst templates and the stack.yaml file

The CLI supports envsubst-style templates, which means one stack file can hold several configurations for different accounts, versions or environments.

The example given is a deployment pipeline with two Docker Hub identities. In production, images go to the exampleco account; in development you want your own account, alexellis2. Instead of maintaining two stack files, the image reference carries a substitution with a default:

```yaml
functions:
  url-ping:
    lang: python
    handler: ./sample/url-ping
    image: ${DOCKER_USER:-exampleco}/faas-url-ping:0.2
```

The default value after the colon is what you get when the variable is unset or empty:

```bash
$ faas-cli build
$ DOCKER_USER="" faas-cli build
```

Setting it overrides the default:

```bash
$ DOCKER_USER="alexellis2" faas-cli build
```

That pattern is more than a convenience for image names. Because the same substitution works over the whole stack file, one file can carry a different gateway, a different image prefix and a different environment for each deployment target, which keeps the configuration in one place instead of scattering it across CI variables and per-developer copies.

The repository carries a t1.yml at the top level and a t1 directory, along with sample configuration, and the Go dependencies include the drone envsubst package, which is the implementation behind the substitution.

## OAuth2 tokens and the Pro-only auth command

Beyond basic auth, the CLI can obtain a JWT to use as a Bearer token through faas-cli pro auth, and the documentation is explicit that this command is licensed for OpenFaaS Pro customers.

Two OAuth2 grants are supported. The code grant is the default and is meant for interactive use from a workstation. It uses the PKCE extension, and the example shows the parameters an identity provider expects:

```sh
faas-cli pro auth \
  --auth-url https://tenant0.eu.auth0.com/authorize \
  --token-url https://tenant0.eu.auth0.com/oauth/token \
  --audience http://gw.example.com \
  --client-id "${OAUTH_CLIENT_ID}"
```

The client_credentials grant is described as the one for machine to machine communication, such as deploying a function to a gateway that uses OAuth2 or OIDC:

```sh
faas-cli pro auth \
  --grant client_credentials \
  --auth-url https://tenant0.eu.auth0.com/oauth/token \
  --client-id "${OAUTH_CLIENT_ID}" \
  --client-secret "${OAUTH_CLIENT_SECRET}"\
  --audience http://gw.example.com
```

One limitation is called out and it matters for scripted use. At this time the token cannot be saved or retained in your OpenFaaS config file, so you pass it with the --token=$TOKEN flag instead. That means a CI job has to obtain a token and thread it through every subsequent command, and there is no built in refresh for a long running pipeline.

For everyone else, login and logout still store basic auth credentials in the config, and login supports multiple gateways so one workstation can talk to more than one cluster.

## Where the CLI ends and the platform begins

The boundaries are worth stating, because a CLI that looks generic is often platform specific in ways that only appear later.

The build path is a Docker path. faas-cli build produces a Docker image from a language template, so a machine without a usable Docker daemon cannot build even though the CLI itself is a single static binary. The choice of template is also a real constraint: you either use one of the supported language templates and write only a handler, or you bring your own Dockerfile and lose the templating convenience entirely.

Template selection has its own coupling. Templates come from a git repository, defaulting to the upstream templates repository, and a template pull is a git operation that has to reach that repository. Air-gapped or restricted networks need either a mirror or OPENFAAS_TEMPLATE_URL pointed somewhere local.

Then there is the licensing boundary. The auth command is a Pro feature, so an OpenFaaS Cloud or Pro user gets an OAuth2 path that a community edition user does not, even though the binary is the same.

On maintenance, the repository is not archived and the last push was on 2026-10-06, with releases 0.18.16 and 0.18.15 published that same day and 0.18.14 on 2026-09-29. The go.mod requires Go 1.24.0, the build uses a vendored dependency tree with GOFLAGS=-mod=vendor, and the Dockerfile compiles with a Go 1.26 image. The build also runs a license-check stage that fails unless source files carry the expected copyright headers, naming Alex Ellis, OpenFaaS Author(s) and OpenFaaS Ltd, and a gofmt check that rejects unformatted code before the tests run. That is the upgrade cost: a contributor must match the project's formatting and header conventions or the build stops.

## Conclusion

Adopt faas-cli if you deploy to OpenFaaS and want one binary that handles templating, image build, registry push, gateway deploy and invocation from the same shell. Do not adopt it as a general Docker or cloud CLI, since the build path assumes a language template and a Docker image, and the OAuth2 auth command is licensed for OpenFaaS Pro customers only. Before your first deploy, set the gateway address with the OPENFAAS_URL environment variable or a stack.yaml, because the default is 127.0.0.1:8080, and check the copyright headers the build expects, since the license-check stage in the Dockerfile fails the build unless they are present.

## FAQ

### How do I install faas-cli on Linux or macOS?

Use the utility script, either with sudo for a system-wide install or without it for a user install that needs the further actions described in the documentation. Homebrew is also supported with brew install faas-cli, but the documentation notes the brew release may not run the latest minor release.

### How do I point faas-cli at a different OpenFaaS gateway?

The default is 127.0.0.1:8080, and the override priority is the --gateway flag first, then the --yaml or -f flag or a stack.yaml in the current directory, then the OPENFAAS_URL environment variable. Setting FAAS_DEBUG=1 makes the CLI print the HTTP request it sends to the gateway.

### Can faas-cli deploy functions with OAuth2 instead of basic auth?

Yes, through faas-cli pro auth, which supports a code grant using PKCE for interactive use and a client_credentials grant for machine to machine use. That command is licensed for OpenFaaS Pro customers, and the token cannot be saved in the config file, so it is passed with --token=$TOKEN.

### How does faas-cli support different Docker accounts for CI and development?

The CLI supports envsubst-style templates, so a stack.yaml can carry an image reference such as ${DOCKER_USER:-exampleco}/faas-url-ping:0.2. Leaving DOCKER_USER unset or empty uses the default account, and setting DOCKER_USER="alexellis2" overrides it for that build.

### What does faas-cli publish do differently from faas-cli up?

faas-cli up is a combination of build, push and deploy to a gateway, while faas-cli publish builds and pushes multi-arch images intended for CI and release artifacts rather than for a function deployment.

## Sources

- [License: MIT](https://github.com/openfaas/faas-cli/blob/master/LICENSE)
- [openfaas/faas-cli on GitHub](https://github.com/openfaas/faas-cli)
- [Project website](https://www.openfaas.com/)
- [README](https://github.com/openfaas/faas-cli/blob/master/README.md)
- [Releases](https://github.com/openfaas/faas-cli/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/openfaas-faas-cli
