---
title: Sign in, device codes and sessions
description: How you and your agent sign in to invideo: in the browser, with a device code when there is no browser, and how to sign out.
---
You sign in to invideo in your browser. Your agent then works in your account, in the workspaces you chose. When the agent runs where no browser can open, it signs in with a device code: it sends you a link and a code, and you approve on your own device. There are no API keys and no passwords.

```bash
invideo auth login
INVIDEO_NO_BROWSER=1 invideo auth login
invideo auth status
```

## How you sign in to invideo

invideo has no passwords. On the sign-in page you choose one of these.

- **Join with Google**, if you signed up with Google.
- **Join with Apple**, if you signed up with Apple.
- **Your email address.** invideo emails you a short code. Enter it on the page.

If the code does not arrive, check your spam folder. If it still does not arrive, try another email address or contact support from the chat button on the invideo site.

## Sign in from an MCP client

Each MCP client starts the sign-in when it connects to `https://mcp.invideo.io/mcp`. You sign in to invideo in the browser and choose the workspaces the agent may use. Clients differ in who starts the step. Terminal agents (Claude Code, Codex, Antigravity, and Cursor with the skills) sign in through the CLI, below.

| Client | Who signs in, and how |
| --- | --- |
| Claude (claude.ai or desktop) | Add invideo in **Customize**, then **Connectors**, and click **Connect**. The client opens the sign-in and retries the call. |
| ChatGPT | Install the official invideo plugin, then sign in when ChatGPT asks. The client runs the sign-in itself. |
| Gemini app | Add invideo as a custom app in **Connected Apps** and follow the on-screen steps. Google limits who can add custom apps; see [Use invideo in Gemini](/start/gemini). |
| Gemini CLI | Run `/mcp auth invideo` when invideo asks for sign-in. With no browser, use the invideo CLI for that session instead of MCP. |
| VS Code and any other client | The client runs the OAuth sign-in when it connects. If it cannot, use the device code below. |

## Sign in from the CLI

The CLI keeps one sign-in per machine. You sign in once, then every command runs as you.

<Steps>
<Step title="Start the sign-in">
Run `invideo auth login`. It opens your browser on this machine and waits until you approve. Your agent runs it in the background, or with a long timeout, because the wait can take a few minutes. It sees the command finish when you approve.
</Step>
<Step title="Approve in the browser">
Sign in to invideo in the tab that opened, and approve. Then go back to the terminal.
</Step>
<Step title="Check who is signed in">
Run `invideo auth status`. It prints your name, email and the credits left. If it exits with code 4, the sign-in did not finish. Run `invideo auth login` again.
</Step>
</Steps>

The CLI keeps your sign-in on this machine, outside your project folders. `invideo auth logout` forgets it.

## Sign in with a device code

Use a device code when no browser can open on the machine: over ssh, in a container, on a cloud machine, or in a cloud agent. You approve on a phone or laptop you hold.

```bash
INVIDEO_NO_BROWSER=1 invideo auth login
```

It prints a link and a code. Open the link on another device and enter the code. Your agent never asks you to send the code back, and never asks for a password.

Your agent runs the command in the background, because it waits for your approval. It sends you the link and the code in one message. You choose your workspaces and approve.

This device code signs in the CLI only. It does not sign in an MCP connection, because the CLI and the MCP server use separate sign-ins. An MCP client with no browser uses the device flow over HTTP, below.

## Device flow over HTTP

An agent that calls `https://mcp.invideo.io/mcp` with no browser and no CLI signs in with this flow. It ends with an access token and a refresh token. For CI jobs and servers, see [Run invideo in CI and on servers](/how-to/ci-and-servers).

<Steps>
<Step title="Find the endpoints">
Fetch the server's protected-resource document. Its `invideo_device_authorization` field gives the `client_id` and the `device_authorization_endpoint`. The token endpoint is `/oauth/token` on that host. You see both URLs and the `client_id`.
</Step>
<Step title="Get a code">
POST the `client_id` to the device endpoint. The answer has `device_code`, `user_code`, `verification_uri`, `expires_in` and `interval`. On `unauthorized_client`, the `error_description` names the right `client_id`.
</Step>
<Step title="Tell the person once">
Send one message: open the `verification_uri` and enter the `user_code`. Say when it expires. The person chooses the workspaces there and approves.
</Step>
<Step title="Poll for the token">
POST the same `device_code` to the token endpoint every `interval` seconds. On `authorization_pending`, wait. On `slow_down`, add 5 seconds. On `access_denied`, stop and tell the person. On `expired_token`, start one new flow. You see `access_token` and `refresh_token`.
</Step>
<Step title="Call the server">
Send `authorization: Bearer <access_token>` on every request. The access token lasts for its `expires_in` seconds. Read the field; do not assume a length.
</Step>
</Steps>

```bash
MCP_URL=https://mcp.invideo.io/mcp
ORIGIN=$(echo "$MCP_URL" | cut -d/ -f1-3)
curl -s "$ORIGIN/.well-known/oauth-protected-resource${MCP_URL#"$ORIGIN"}"
curl -s -X POST "$DEVICE_ENDPOINT" -d "client_id=$CLIENT_ID"
curl -s -X POST "$TOKEN_ENDPOINT" \
  -d grant_type=urn:ietf:params:oauth:grant-type:device_code \
  -d "device_code=$DEVICE_CODE" -d "client_id=$CLIENT_ID"
```

`$DEVICE_ENDPOINT` and `$CLIENT_ID` come from the first command's answer. `$TOKEN_ENDPOINT` is `/oauth/token` on the device endpoint's host. `$DEVICE_CODE` comes from the second command's answer.

To refresh, POST `grant_type=refresh_token` with the `refresh_token` and the `client_id` to the same token endpoint. Sessions and staying signed in, below, has the rules.

## The rule for agents

Your agent never asks you for a password, an email code, or the device code back. It sends you the link and the code, once, in one message, and waits.

- Send one message per code. Do not ask for a new code while one is waiting.
- The person may be away for a while. Waiting is normal. Do not start a new code because they have not approved.
- If the person denies the request, stop and tell them.
- If the code expires, start one new sign-in with one new message. If that expires too, stop.
- Keep tokens and codes out of chat, out of files the person sees, and out of logs.

## Sessions and staying signed in

A sign-in lasts across sessions, but it can lapse. When it does, the next call returns a sign-in challenge, or the CLI exits with code 4.

- **Claude Code, Codex, Cursor and Antigravity.** These use the CLI. Run `invideo auth login` again.
- **Claude and ChatGPT.** The client asks you to sign in again.
- **Any other shell.** Run `invideo auth login` again.
- **Device flow over HTTP.** The agent keeps the refresh token in its own secret store, not in chat. When a call returns 401, it uses the refresh token to get a new access token. Each refresh returns a new refresh token, so the agent stores the new one every time. It starts a new device sign-in only when the refresh fails.

To use a workspace you did not choose at sign-in, connect again and choose it. See [Seats and workspaces](/account/seats).

## Sign out

How you sign out depends on where you signed in.

- **CLI.** Run `invideo auth logout`. It forgets this machine's sign-in.
- **MCP clients.** Remove invideo in the client. In Claude, remove the connector under **Customize**, then **Connectors**. In ChatGPT, remove the plugin. In the Gemini app, disconnect the custom app. In Gemini CLI or VS Code, remove the server.

```bash
invideo auth logout
```

## If something goes wrong

Most sign-in problems are a step that only the person can do.

| Symptom | Fix |
| --- | --- |
| The agent says it needs your account. | Finish the sign-in step for your client, then ask again. |
| Claude Code or Codex does not use invideo. | Check the plugin with `claude plugin list` or `codex plugin list`. Then ask for the video job again. |
| The CLI exits with code 4. | Run `invideo auth login`, or `INVIDEO_NO_BROWSER=1 invideo auth login` without a browser. |
| `invideo auth login` stops before you approve. | The agent's shell timed out. Run it in the background or with a longer timeout. |
| A project URL does not open for the agent. | The project is in a workspace you did not choose. Connect again and choose it. |
| The agent asks you for a code or a password. | Avoid this. Instead, the agent sends you the link and code, and you approve. |

## Related

- [invideo for AI agents](/agents)
- [Is there an invideo API?](/api)
- [Run invideo in CI and on servers](/how-to/ci-and-servers)
- [Seats and workspaces](/account/seats)
- [Environment variables](/reference/environment)
- [Exit codes](/reference/exit-codes)