> From the [Strife developer docs](https://strife.app/docs/reference/cli/authentication-and-linking). Every page is listed in [llms.txt](https://strife.app/docs/llms.txt).

# Authentication & Linking

How strife login authenticates, where credentials are stored, and how a local project gets linked to a workspace and team.

## Signing in

`strife login` uses an OAuth 2.0 Device Authorization Grant: the CLI requests a device code, prints a URL and a short code, and polls in the background while you open that URL and approve the sign-in in your browser. The CLI itself never opens a browser for you or handles a password.

A signed-in session consists of:

* A short-lived access token (roughly 30 minutes), used to authenticate API requests.
* A longer-lived refresh token (roughly 30 days), used to silently obtain a new access token as needed. It's rotated on every use.

Both are stored locally — not per-project — so signing in once covers every project on that machine until the session expires or you `strife logout`. Credentials live outside your project directories entirely, in your OS's standard per-user config location, and are never committed to a repository.

## One workspace per session

**Which workspace you're signed into is fixed for the lifetime of a session** — chosen when you approve the sign-in in your browser, not something the CLI lets you switch afterward. If you work across multiple workspaces (for example, your own team's workspace and a client's), use `strife login --force` to start a fresh sign-in and choose the other workspace when approving it. `strife whoami` shows which workspace and team the current session and linked directory resolve to.

## Linking a project

A workspace can contain multiple teams; a local project links to exactly one team via `strife link`, which writes `.strife/project.json` in the current directory. This file:

* Is looked for in the **exact directory** you run commands from — there's no upward directory search the way `git` or `npm` walk up to find a config file. Running a command from a subdirectory of a linked project reports "not linked."
* Contains only non-secret identifiers (workspace ID, team ID, names) — safe to commit, though it's added to `.gitignore` automatically since it's still local, machine-specific state in most workflows.
* Is unaffected by `strife logout` — logging out clears your session, not any directory's link. A previously linked directory still reports as linked; it just can't authenticate again until you sign in.

Creating a _new_ team (as opposed to linking to an existing one) isn't available as its own command — it happens as part of the interactive flow when you run bare `strife` / `strife .` in an unlinked directory and choose not to link to an existing team. See [bootstrapping a new project](https://strife.app/docs/reference/cli.md#bootstrapping-a-brand-new-project).

## Non-interactive use

Pass `--non-interactive` to suppress prompts. Commands that would otherwise prompt fail with an explicit error instead:

* `strife link --non-interactive` requires `--team` if the workspace has more than one team.
* `strife push --non-interactive` requires `-y`/`--yes`.
* Anything that would need to create a new team or link for the first time requires a directory that's already linked — there's nothing to prompt for the first-time setup otherwise.

Non-interactive is not unattended: every command that talks to Strife, `push` among them, needs a `strife login` session, and a CI runner cannot get one today — login happens in a browser, and every refresh replaces the session's refresh token and retires the old one, so a session copied to a runner stops working at its first refresh. Run those commands from your machine. `typegen generate` and `typegen validate` never prompt or need `--non-interactive` — they're fully offline regardless of the terminal, so they run in CI too.
