---
title: "Use the FGA CLI"
description: "Use the FGA CLI"
canonical: "https://openfga.dev/docs/getting-started/cli"
content_type: "documentation"
last_updated: "2026-08-24T10:26:12.000Z"
---

# Use the FGA CLI

The OpenFGA Command Line Interface (CLI) enables you to interact with an FGA store, where you can manage tasks, create stores, and update FGA models, among other actions. For more information on FGA stores, see [What Is A Store](https://openfga.dev/docs/concepts.md#what-is-a-store).

For instructions on installing it, visit the [OpenFGA CLI Github repository](https://github.com/openfga/cli).

## Configuration

The CLI is configured to use a specific FGA server in one of three ways:

- Using CLI flags.

- Using environment variables.

- Using a `.fga.yaml` configuration file, searched in the following order (highest to lowest priority):

  1. **Current working directory**

  2. **User-specific config directory**

     - Unix: `$XDG_CONFIG_HOME` (if set), otherwise `$HOME/.config`
     - Windows: `%AppData%`

  3. **`fga` subdirectory under the user config directory**

  4. **User's home directory**

     - Unix: `$HOME`
     - Windows: `%USERPROFILE%`

The API Url setting needs to point to the OpenFGA server:

| Name    | Flag      | Environment   | \~/.fga.yaml | Default Value           |
| ------- | --------- | ------------- | ------------ | ----------------------- |
| API Url | --api-url | FGA\_API\_URL | api-url      | `http://localhost:8080` |

If you use [pre-shared key authentication](https://openfga.dev/docs/getting-started/setup-openfga/configure-openfga.md#pre-shared-key-authentication), provide the following parameters which appends the pre-shared key in the HTTP request header:

| Name      | Flag        | Environment     | \~/.fga.yaml |
| --------- | ----------- | --------------- | ------------ |
| API Token | --api-token | FGA\_API\_TOKEN | api-token    |

If you use [OIDC authentication](https://openfga.dev/docs/getting-started/setup-openfga/configure-openfga.md#oidc), configure the following parameters based on the OIDC server that’s used to issue tokens:

| Name           | Flag               | Environment             | \~/.fga.yaml     |
| -------------- | ------------------ | ----------------------- | ---------------- |
| Client ID      | --client-id        | FGA\_CLIENT\_ID         | client-id        |
| Client Secret  | --client-secret    | FGA\_CLIENT\_SECRET     | client-secret    |
| Scopes         | --api-scopes       | FGA\_API\_SCOPES        | api-scopes       |
| Token Issuer   | --api-token-issuer | FGA\_API\_TOKEN\_ISSUER | api-token-issuer |
| Token Audience | --api-audience     | FGA\_API\_AUDIENCE      | api-audience     |

A default store Id and authorization model Id can also be configured:

| Name                   | Flag       | Environment    | \~/.fga.yaml |
| ---------------------- | ---------- | -------------- | ------------ |
| Store ID               | --store-id | FGA\_STORE\_ID | store-id     |
| Authorization Model ID | --model-id | FGA\_MODEL\_ID | model-id     |

All of the examples in this document assume the CLI is properly configured and that the Store ID is set either in an environment variable or the `~/.fga.yaml` file.

## Basic operations

The CLI commands below show you how to create a store and run your application’s most common operations, including how to write a model and write/delete/read tuples, and run queries.

```


# Create a store with a model

$ fga store create --model docs.fga

{

  "store": {

    "created_at":"2024-02-09T23:20:28.637533296Z",

    "id":"01HP82R96XEJX1Q9YWA9XRQ4PM",

    "name":"docs",

    "updated_at":"2024-02-09T23:20:28.637533296Z"

  },

  "model": {

    "authorization_model_id":"01HP82R97B448K89R45PW7NXD8"

  }

}



# Keep the returned store id in an environment variable

$ export FGA_STORE_ID=01HP82R96XEJX1Q9YWA9XRQ4PM



# Get the latest model

$ fga model get

model

  schema 1.1



type user



type organization

  relations

    define admin: [user with non_expired_grant]

    define member: [user]



type document

  relations

    define editor: admin from organization

    define organization: [organization]

    define viewer: editor or member from organization



condition non_expired_grant(current_time: timestamp, grant_duration: duration, grant_time: timestamp) {

  current_time < grant_time + grant_duration



}



# Write a tuple

$ fga tuple write user:anne member organization:acme

{

  "successful": [

    {

      "object":"organization:acme",

      "relation":"member",

      "user":"user:anne"

    }

  ]

}



# Read all tuples. It returns the one added above

$ fga tuple read

{

  "continuation_token":"",

  "tuples": [

    {

      "key": {

        "object":"organization:acme",

        "relation":"member",

        "user":"user:anne"

      },

      "timestamp":"2024-02-09T23:05:43.586Z"

    }

  ]

}



# Write another tuple, adding a document for the acme organization

$ fga tuple write organization:acme organization document:readme

{

  "successful": [

    {

      "object":"document:readme",

      "relation":"organization",

      "user":"organization:acme"

    }

  ]

}



# Check if anne can view the document.

# Anne can view it as she's a member of organization:acme, which is the organization that owns the document

$ fga query check user:anne viewer document:readme

{

  "allowed":true,

  "resolution":""

}



# List all the documents user:anne can view

$ fga query list-objects user:anne viewer document

{

  "objects": [

    "document:readme"

  ]

}



# List all the relations that user:anne has with document:readme

$ fga query list-relations user:anne document:readme

{

  "relations": [

    "viewer"

  ]

}



# Delete user:anne as a member of organization:acme

$ fga tuple delete user:anne member organization:acme

{}



# Verify that user:anne is no longer a viewer of document:readme

$ fga query check user:anne viewer document:readme

{

  "allowed":false,

  "resolution":""

}
```

## Work with authorization model versions

OpenFGA models are [immutable](https://openfga.dev/docs/getting-started/immutable-models.md); each time a model is written to a store, a new version of the model is created.

All OpenFGA API endpoints receive an optional authorization model ID that points to a specific version of the model and defaults to the latest model version. Always use a specific model ID and update it each time a new model version is used in production.

The following CLI commands lists the model Ids and find the latest one:

```
# List all the authorization models

$ fga model list

{

  "authorization_models": [

    {

      "id":"01HPJ8JZV091THNTDFE2SFYNNJ",

      "created_at":"2024-02-13T22:14:50Z"

    },

    {

      "id":"01HPJ808Q8J56QMK4WNT7MG7P7",

      "created_at":"2024-02-13T22:04:37Z"

    },

    {

      "id":"01HPJ7YKNV0QT0S6CFRJMK231P",

      "created_at":"2024-02-13T22:03:43Z"

    }

  ]

}



# List the last model, displaying just the model ID

$ fga model get --field id

# Model ID: 01HPJ8JZV091THNTDFE2SFYNNJ



# List the last model, displaying just the model ID, in JSON format, to make it simpler to parse

$ fga model get --field id --format json

{

  "id":"01HPJ8JZV091THNTDFE2SFYNNJ"

}
```

When using the CLI, the model ID can be specified as a `--model-id` parameter or as part of the configuration.

## Import tuples

To import tuples, use the`fga tuple write` command. It has the following parameters:

| Parameter                                            | Description                                                                                                          |
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| --file                                               | Specifies the file name json, yaml and csv files are supported                                                       |
| --max-tuples-per-write (optional, default=1, max=40) | Maximum number of tuples to send in a single write                                                                   |
| --max-parallel-requests (optional, default=4)        | Maximum number of requests to send in parallel. Make it larger if you want to import a large number of tuples faster |
| --hide-imported-tuples (optional, default=false)     | Hide successful imports from output, useful when importing large datasets                                            |

The CLI returns a detailed JSON response that includes:

- `successful`: List of successfully written tuples (hidden when using `--hide-imported-tuples`)
- `failed`: List of tuples that failed to write, including the error reason
- `total_count`: Total number of tuples processed in this operation
- `successful_count`: Number of tuples successfully written
- `failed_count`: Number of tuples that failed to write

When using `--hide-imported-tuples`, the successful tuples are not included in the output, making it more practical when importing large datasets. Failed tuples are always shown to help identify and fix any issues. If you specify `--max-tuples-per-write` greater than one, an error in one of the tuples implies none of the tuples get written.

```
$ fga tuple write --file tuples.yaml



{

  "successful": [

    {

      "object":"organization:acme",

      "relation":"member",

      "user":"user:anne"

    }

  ],

  "failed":null,

  "total_count": 1,

  "successful_count": 1,

  "failed_count": 0

}



$ fga tuple write --file tuples.yaml

{

  "successful":null,

  "failed": [

      {

        "tuple_key": {

          "object":"organization:acme",

          "relation":"member",

          "user":"user:anne"

        },

      "reason":"Write validation error for POST Write with body {\"code\":\"write_failed_due_to_invalid_input\",\"message\":\"cannot write a tuple which already exists: user: 'user:anne', relation: 'member', object: 'organization:acme': invalid write input\"}\n with error code write_failed_due_to_invalid_input error message: cannot write a tuple which already exists: user: 'user:anne', relation: 'member', object: 'organization:acme': invalid write input"

    }

  ],

  "total_count": 1,

  "successful_count": 0,

  "failed_count": 1

}
```

Below are examples of the different file formats the CLI accepts when writing tuples:

### yaml

```
- user: user:peter

  relation: admin

  object: organization:acme

  condition:

    name: non_expired_grant

    context:

      grant_time: '2024-02-01T00:00:00Z'

      grant_duration: 1h

- user: user:anne

  relation: member

  object: organization:acme
```

### JSON

```
[

    {

        "user": "user:peter",

        "relation": "admin",

        "object": "organization:acme",

        "condition": {

            "context": {

                "grant_duration": "1h",

                "grant_time": "2024-02-01T00:00:00Z"

            },

            "name": "non_expired_grant"

        }

    },

    {

        "user": "user:anne",

        "relation": "member",

        "object": "organization:acme"

    }

]
```

### CSV

```
user_type,user_id,user_relation,relation,object_type,object_id,condition_name,condition_context

user,anne,member,,organization,acme,,

user,peter1,admin,,organization,acme,non_expired_grant,"{""grant_duration"": ""1h"", ""grant_time"": ""2024-02-01T00:00:00Z""}"
```

When using the CSV format, you can omit certain headers, and you don’t need to specify the value for those fields.

## Delete Tuples

To delete a tuple, specify the user/relation/object you want to delete. To delete a group of tuples, specify a file that contains those tuples. Supported file formats are `json`, `yaml` and `csv`.

```
$ fga tuple delete --file tuples.yaml

{

  "successful": [

    {

      "object":"organization:acme",

      "relation":"admin",

      "user":"user:peter"

    },

    {

      "object":"organization:acme",

      "relation":"member",

      "user":"user:anne"

    }

  ],

  "failed":null

}
```

Delete all tuples from a store by reading all the tuples first and then deleting them:

```
# Reads all the tuples and outputs them in a json format that can be used by 'fga tuple delete' and 'fga tuple write'.



$ fga tuple read --output-format=simple-json --max-pages 0    > tuples.json

$ fga tuple delete --file  tuples.json
```

## Import stores

The CLI can import an [FGA Test file](https://openfga.dev/docs/modeling/testing.md) in a store. It writes the model included and imports the tuples in the fga test file.

Given the following `.fga.yaml` file:

```
model: |

  model

    schema 1.1



  type user

  type organization

   relations

     define member : [user]

  }



tuples:

  # Anne is a member of the Acme organization

  - user: user:anne

    relation: member

    object: organization:acme
```

The following command is used to import the file contents in a store:

```
$ fga store import --file <filename>.fga.yaml
```

Use the `fga model get` command is used to verify that the model was correctly written, and the `fga tuple read` command is used to verify that the tuples were properly imported.

## Related Sections

Check the following sections for more on how to learn how to write tests.

**Testing Models**

Learn how to test FGA models using the FGA CLI.

- [More](https://openfga.dev/docs/modeling/testing.md)
