# Authenticate with qf login

Source: https://docs.qualflare.com/docs/cli/authentication · Last updated: 2026-10-28

Log the Qualflare CLI in with qf login: save a project access token under a local identifier from QF_TOKEN or a hidden prompt, on your computer and in CI.

To authenticate the Qualflare CLI, run `qf login <identifier>` once with a project access token, which starts with `qfp_`. `qf` saves it under that local identifier, and every project command then runs as `qf <identifier> <command>`. The token, not the identifier, decides which project receives your results.

## Before you begin

* `qf` installed ([Install the CLI](https://docs.qualflare.com/docs/cli/installation)).
* A project [access token](https://docs.qualflare.com/docs/api/access-tokens), which you create in the app (requires the Editor role or higher in the project).
* The token's creator must keep the Editor role or higher on the project, or uploads fail with exit code `4` ([The token lacks access](https://docs.qualflare.com/docs/cli/troubleshooting#token-lacks-access)).

## Get a token

In the [Qualflare app](https://app.qualflare.com), open **Project Settings** > **Access Tokens** > **Create Access Token**, then copy the token right away: it is shown only once. [Access Tokens](https://docs.qualflare.com/docs/api/access-tokens) covers expiry and access levels.

## Log in on your computer

```bash
qf login <identifier> [token]
```

`qf login` takes the token from the first of these that is set:

1. The `[token]` argument. Avoid it: the token ends up in your shell history and the process list.
2. The `QF_TOKEN` environment variable.
3. A hidden prompt, when you run `qf login` in a terminal.
4. Standard input, when you pipe the token in.

### Step 1: Run qf login

Run `qf login myapp` and paste the token at the hidden `API token:` prompt.

```bash
qf login myapp
```

### Step 2: Check the saved identifier

Check the success line it prints:

```text
OK Saved identifier "myapp". Use it as the first arg, e.g. `qf myapp cases`.
```

### Step 3: Upload a report

Run `qf myapp collect results.xml`.

```bash
qf myapp collect results.xml
```

`qf login` only saves the token. `collect` and the read commands use the saved token, not `QF_TOKEN`, so run `qf login` in every CI job before you upload.

## Log in in CI

In CI, store the token as a secret named `QF_TOKEN` and run `qf login ci --force` at the start of the job instead of mounting the credentials file:

```bash
# In CI: qf login reads the token from the QF_TOKEN secret
qf login ci --force
qf ci collect test-results/*.xml
```

Each CI job starts with no saved login, so run `qf login ci --force` in every job that uploads. Without a terminal, `qf` can't ask before it replaces a saved identifier, so replacing one fails unless you pass `--force`.

On GitHub Actions, expose the secret to the step that logs in and uploads:

```yaml
- name: Upload to Qualflare
  env:
    QF_TOKEN: ${{ secrets.QF_TOKEN }}
  run: |
    qf login ci --force
    qf ci collect results.xml
```

[CI/CD Integration](https://docs.qualflare.com/docs/cli/ci-cd) has the setup for GitLab CI, Jenkins and Azure DevOps.

## Check the login

Run `qf projects`: it prints each saved identifier on its own line. Then run a real request, such as `qf myapp launches list`; `--dry-run` never contacts Qualflare, so it can't test a token. The [read commands](https://docs.qualflare.com/docs/cli/read-commands#launches) list what `launches list` returns.

## Identifier rules

An identifier uses lowercase letters, digits, hyphens and underscores; 1–63 characters; must start with a letter or digit (e.g., `my-app`, `ci`, `prod`). These names are reserved: `login`, `logout`, `projects`, `version`, `list-formats`, `formats`, `lf`, `help`, `completion` and `__complete`.

The identifier is only a local name: you can save the same token under two identifiers, or tokens of different projects under different identifiers.

## Manage saved identifiers

### List identifiers with qf projects

```bash
qf projects
```

Lists all saved project identifiers, one per line. Useful for confirming what is currently configured. With none saved, it prints `No projects configured. Run 'qf login <identifier> <token>' to get started.`

### Remove one with qf logout

```bash
qf logout <identifier>
```

Removes saved credentials for `<identifier>`. The identifier subcommand will no longer be available until you `qf login` again. An identifier that isn't saved fails with ``identifier "x" not found (run `qf projects` to list)``.

## Credentials file

Tokens are stored in:

* **Linux**: `~/.config/qualflare/config.toml`, or `$XDG_CONFIG_HOME/qualflare/config.toml` when `XDG_CONFIG_HOME` is set
* **macOS**: `~/Library/Application Support/qualflare/config.toml`
* **Windows**: `%AppData%\qualflare\config.toml`

The file is created with permissions `0600`, and `qf` warns you when other users can read it. Treat it like an SSH private key: do not commit it or share it. The warning reads:

```text
warning: <path> is group/world-accessible (mode 0644); run `chmod 600 <path>` to protect your API token
```

## Migrate an old CI setup

If your CI still sets `QF_API_KEY`, `qf` ignores it, and `collect` prints `Note: QF_API_KEY is no longer read. Run 'qf login <identifier> $QF_API_KEY' to migrate.` Rename the CI secret to `QF_TOKEN` and run `qf login ci --force` instead of passing the token on the command line. {/* allow-claim: qf-api-key — migration note that names the removed variable */}

Commands without an identifier, such as `qf collect results.xml`, no longer work: `qf` reads `collect` as an identifier and answers `no identifier "collect" configured`.

## Troubleshoot

* `token cannot be empty`: `qf login` found no token in the argument, `QF_TOKEN`, the prompt or standard input. In CI, expose the secret to the job as `QF_TOKEN`.
* `identifier "ci" already exists; cannot prompt because stdin is not a terminal — use --force to overwrite`: add `--force`.
* `identifier "My-App" is invalid: …` or `identifier "login" is reserved`: choose a name that follows the [identifier rules](https://docs.qualflare.com/docs/cli/authentication#identifier-rules).
* `no identifier "myapp" configured`: run `qf login myapp` first, in the same CI job as the upload.
* `invalid or expired access token (status: 401)`, exit code `3`: create a new token and save it with `qf login <identifier> --force` ([Troubleshoot qf and CI uploads](https://docs.qualflare.com/docs/cli/troubleshooting#api-key-not-working)).

## Next steps

* [Upload results with qf collect](https://docs.qualflare.com/docs/cli/collect) · [CI/CD Integration](https://docs.qualflare.com/docs/cli/ci-cd) · [Configuration and environment variables](https://docs.qualflare.com/docs/cli/configuration) · [Access Tokens](https://docs.qualflare.com/docs/api/access-tokens) · [Glossary: project identifier](https://docs.qualflare.com/docs/reference/glossary#project-identifier)
