---
title: invideo for AI agents
description: Connect your agent to invideo to generate video, images, voice and music with the leading models and edit them on a real timeline. Setup lines for every client, the work loop and the rules.
---
invideo puts the leading video, image, voice and music models next to a professional timeline editor, in the cloud. Your agent generates the shots, voices and music a project lacks, cuts them with your own footage, and exports the result, all in one project. Agents and people work in the same project, and you watch every edit land live in the browser.

Agents with a terminal use the invideo plugin and the CLI. The plugin installs the skills, and the agent installs the CLI, one binary with no sudo, on the first video job. In Cursor, add the skills with `npx skills add invideoio/skills`. The Cursor Marketplace plugin is the MCP route in Cursor, and it carries the MCP server only. Agents without a shell use the MCP server at `https://mcp.invideo.io/mcp`.

<CodeBlock>
<CodeTab label="Claude Code" lang="bash">

```bash
claude plugin marketplace add invideoio/skills
claude plugin install invideo@invideo
```

</CodeTab>
<CodeTab label="Codex" lang="bash">

```bash
codex plugin marketplace add invideoio/skills
codex plugin add invideo@invideo
```

</CodeTab>
<CodeTab label="Antigravity" lang="bash">

```bash
agy plugin install https://github.com/invideoio/skills
```

</CodeTab>
<CodeTab label="Cursor" lang="bash">

```bash
npx skills add invideoio/skills
```

</CodeTab>
<CodeTab label="Any agent, skills only" lang="bash">

```bash
npx skills add invideoio/skills
```

</CodeTab>
<CodeTab label="CLI, macOS and Linux" lang="bash">

```bash
curl -fsSL https://agents.invideo.io | sh
```

</CodeTab>
<CodeTab label="CLI, Windows" lang="powershell">

```powershell
irm https://raw.githubusercontent.com/invideoio/cli/main/install.ps1 | iex
```

</CodeTab>
</CodeBlock>

A chat app, or an agent with no shell, uses MCP. In ChatGPT, the person installs the official invideo plugin: **Customize**, then **Plugins**. In Claude on the web or desktop, the person adds invideo as a connector: **Customize**, then **Connectors**. In the Gemini app, the person adds invideo as a custom app with the server URL: **Settings**, then **Connected Apps**. Antigravity, Claude Code and Codex use the CLI only. Cursor uses the CLI first, and its Marketplace plugin is the MCP route. Gemini CLI and VS Code have no invideo plugin, so they take the MCP server with the lines below.

<CodeBlock>
<CodeTab label="VS Code" lang="bash">

```bash
code --add-mcp \
  '{"name":"invideo","type":"http","url":"https://mcp.invideo.io/mcp"}'
```

</CodeTab>
<CodeTab label="Gemini CLI" lang="bash">

```bash
gemini mcp add --transport http --scope user invideo \
  https://mcp.invideo.io/mcp
```

</CodeTab>
<CodeTab label="Any other MCP client" lang="json">

```json
{
  "mcpServers": {
    "invideo": { "url": "https://mcp.invideo.io/mcp" }
  }
}
```

</CodeTab>
</CodeBlock>

Each start page below has the full steps.

If you are the agent reading this, run the setup yourself. Installing the plugin, the CLI or the server changes the person's machine, so ask once ("Should I add invideo to your Claude Code?") and do it on a yes. Give the person a command to run only when nothing you can do works.

## Start pages

Each client has its own page with the setup, the sign-in, a first prompt and the known failures.

- [Set up invideo in Claude Code](/start/claude-code)
- [Set up invideo in Codex](/start/codex)
- [Set up invideo in Cursor](/start/cursor)
- [Set up invideo in Antigravity](/start/antigravity)
- [Use invideo in ChatGPT](/start/chatgpt)
- [Use invideo in Gemini](/start/gemini)
- [Make a video with invideo without a terminal](/start/no-terminal)

The plugin for Claude Code, Codex and Antigravity, and the skills command for Cursor, install the invideo skills, and the skills are CLI-first: the agent installs the CLI and signs in on the first job. The plugin carries no MCP config. ChatGPT uses the official invideo plugin. The Gemini app takes invideo as a custom app, Claude on the web as a connector, and Gemini CLI and VS Code as an MCP server. None of them gets the skills.

## CLI or MCP

Both reach the same projects, the same timelines and the same account. Pick one per session and stay on it. Mixing them in one session splits your state and your name in the project.

- **Use the CLI** in a terminal agent with the invideo plugin (Claude Code, Codex, Cursor, Antigravity), and in a script or a server. It is the only way in that the start pages give for those agents, and the way the skills teach. Each command prints the URLs and the next step. Add `--json` to get one JSON object. `--out <dir>` saves files on `invideo notebook show` and `invideo edit capture`; `invideo status` follows a job and saves nothing.
- **Use MCP** in a chat app (Claude on the web, ChatGPT, the Gemini app), in VS Code or Gemini CLI, which have no invideo plugin, or in any agent with no shell. You call tools like `read` and `edit_timeline` and pass a URL as `url`. Gemini CLI has a shell, so it can also use the CLI instead; see [Use invideo in Gemini](/start/gemini).

Check the CLI install with this command. It prints `invideo` and the version.

```bash
invideo --version
```

## Sign in

There are no API keys. Every call runs as a signed-in person, in the workspaces they chose when they signed in.

- **CLI.** Run `invideo auth login` in the background or with a long timeout. It opens the browser and waits. Tell the person in one message that a sign-in tab opened.
- **MCP in a chat app.** Claude on the web, ChatGPT and the Gemini app run the browser sign-in themselves when the server asks.
- **MCP in VS Code, Gemini CLI or another client.** The client runs the browser sign-in when the server asks, or has its own authenticate step. In Gemini CLI that step is `/mcp auth invideo`. Signing in the invideo CLI does not sign in an MCP connection. Never run a login command that needs an interactive terminal from the agent's shell.
- **No browser.** On ssh, in a container or on a cloud machine, use a device code.

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

The first command prints a link and a code at once, then waits for approval. Send the person the link and the code in one message. They open the link on their own device and approve. `invideo auth status` shows who is signed in.

The device code above signs in the CLI only. An MCP client with no browser uses its own device flow over HTTP. The steps are on [Sign in, device codes and sessions](/account/sign-in).

Never ask the person for a password, an email code, or the device code back. One sign-in at a time: while a code is pending, do not request another.

## The work loop

Every job follows the same loop. Call `get_help` once for the full guide, or `get_help` with a `topic` for one section.

<Steps>
<Step title="Read">
Find the project with `list_projects`, or make one with `new_project`. Call `read` on its URL to see pages, threads and sequences. In a project, call `register` once and pass your name as `as` on every call there. You see the project URL and its notebook.
</Step>
<Step title="Bring media in">
Add files with `add_media`. For a local file, call `start_upload`, PUT the bytes to the `upload_url`, then call `add_media` with the `upload_id`. In Claude on the web or the desktop app, the PUT goes from Claude's sandbox to the `upload_url` on m.invideo.io. If that PUT cannot reach m.invideo.io (the host does not resolve, the connection is refused, or the sandbox network blocks it), do not describe the files in text instead, and do not ask the person to send them again. Tell the person to allow m.invideo.io in Claude under **Settings**, then **Capabilities**, then **Allowed websites** (the steps are on [How do I let Claude upload my files to invideo?](/ai-agents/how-do-i-let-claude-upload-my-files-to-invideo)), and retry in a new chat once they have. Find stock with `search_library`. You see a sequence URL for each file.
</Step>
<Step title="Generate what is missing">
For a shot, an image, a voice, music or a sound that nobody has, find a model with `find_models` and the job in words, read its inputs with `get_model`, then call `generate` with `dry_run: true` to price it. Follow the cost rule below, then call `generate` again with `max_credits` and an `idempotency_key`. Media inputs are sequence URLs from this project. You see a thread URL at once and a sequence URL when the result lands; `read` it, do not call `generate` again to check.
</Step>
<Step title="Edit on a branch">
Make a timeline with `new_timeline`. Create a branch with `timeline_history` unless the person asks you to edit main. Read with `get_timeline`, look up fields with `timeline_catalog`, then send `edit_timeline` with the latest `expected_state_token`. You see a new `state_token`.
</Step>
<Step title="Check">
Look before you say done. Call `capture` at the moments that matter, `check_timeline` for structure, and `media` with `video.frames` or `audio.loudness` for a source. You see frames and findings. Fix what is wrong and look again.
</Step>
<Step title="Export">
Call `export` with the timeline URL and a `format`, and an `idempotency_key`. `video` renders a 1080p MP4. `premiere`, `davinci` and `final_cut` make a project file that Premiere Pro, DaVinci Resolve or Final Cut Pro opens. You see an export card URL. `read` it until its status is `completed`. For `premiere`, `final_cut` and `davinci`, read it again until the files list is there; `completed` can come before the media package.
</Step>
</Steps>

Tell the person what changed, with timecodes and URLs. Each URL opens exactly that thing in invideo.

The same loop on the CLI. The CLI calls a timeline an edit: `invideo edit new` makes a timeline, and the `<edit-url>` it prints is the timeline's URL.

```bash
invideo project new --title "Launch teaser"
invideo agent register <project-url> --name scout
export INVIDEO_AS=scout
invideo asset upload <project-url> ./shots/*.mp4
invideo notebook new-page <project-url> --title "Shots"
invideo gen models <project-url> --query "cinematic product shot"
invideo gen model <project-url> --model seedance_2_5.r2v
invideo gen run <page-url> --model seedance_2_5.r2v --dry-run \
  -i prompt="slow push on the bottle, studio light"
invideo gen run <page-url> --model seedance_2_5.r2v \
  --max-credits <price> --idempotency-key teaser-shot-1 \
  -i prompt="slow push on the bottle, studio light"
invideo edit new <project-url> --name "Teaser v1"
invideo edit show <edit-url> --json
invideo edit change <edit-url> --timeline T1 --token <state_token> \
  --operations @ops.json
invideo edit check <edit-url>
invideo edit capture <edit-url> --at 1,3.5 --out ./frames
invideo edit export <edit-url> --format video --quality 1080 \
  --idempotency-key teaser-export-1 --json
invideo status <card-url> --wait
invideo notebook show <card-url> --out ./out
```

Where each value comes from:

- `<project-url>` comes from `invideo project new`. `INVIDEO_AS` passes your registered name on every later command, like `--as`.
- `<page-url>` comes from `invideo notebook new-page`. A generation on a page starts a new thread there.
- `<price>` is the `estimated_credits` in the dry run's answer. Pass the same `-i` inputs on the dry run and the paid run.
- `<edit-url>` comes from `invideo edit new`. `<state_token>` comes from `invideo edit show`, and each `edit change` returns a fresh one.
- `ops.json` holds a bare JSON list of operations, `[ {...}, {...} ]`, with no `operations` wrapper.
- `<card-url>` is `.sequences[0]` in the export's answer. `invideo status` waits for the job and saves nothing. `invideo notebook show` with `--out` saves the file as `export.mp4`; rename it after.

## The cost rule

Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything.

Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost.

The agent follows these rules on every paid call.

- On MCP, call `generate` with `dry_run: true` before the first paid call. It checks the inputs and returns the price. Then call it with `max_credits` set, so nothing starts above that price.
- Paid `media` ops, like `audio.transcript` and `video.upscale`, take the same `dry_run` and `max_credits`.
- On the CLI, use `--dry-run` first, then `--max-credits`.
- Pass an `idempotency_key` on every `generate` and `export`. A retry after a timeout then finds the first job instead of paying twice.
- Models retire. A retired model is refused as not found. Run `find_models` with the job in words, use the best match, run the dry run again, and tell the person which model you used.

Prices and the balance are on [Credits and what they cost](/account/credits). For a question about plans, prices or credits, read <a href="https://invideo.io/help/billing/how-do-credits-work/" target="_blank">the credits FAQ</a> and its sibling pages, not only the pricing page.

## Check before you say done

Never tell the person a video is done without looking at it. Call `capture` on the timeline, read the frames, and call `check_timeline`. On the CLI, run `invideo edit capture` and `invideo edit check`. `check_timeline` reports structure only. It does not judge the cut, so you still look at the frames.

## Conventions

These are the places where agents guess wrong. The left column is the usual guess. The right column is what invideo does.

| You'd guess | invideo uses |
| --- | --- |
| An id or a name points to a project | A URL is the handle. Every tool takes a URL as `url` and every result gives the next URLs. |
| Calls are anonymous | `register` a name in the project, then pass it as `as` on every call. |
| Each operation lands on its own | An `edit_timeline` call lands all its operations or none. |
| After a timeout, read again and resend | Retry the identical request with the same `expected_state_token`. A conflict means it landed. |
| Decide the next call yourself | Follow `next` in every result. It names the tools and URLs to use. |
| Call `generate` again to check on it | `read` the URL or call `status`. `retry_after_s` says when to look again. |
| A model id from a page or a saved prompt is forever | Models retire. A retired model is refused as not found. Run `find_models` with the job in words, use the best match, and tell the person. |
| Edit the main timeline | Create a branch with `timeline_history`. Edit main only when asked. |
| Mix the CLI and MCP | Pick one per session. The skills teach the CLI wherever there is a shell. |
| Ask the person for the sign-in code | Send the link and the code once. Never ask for them back. |
| Say done after the last edit | `capture` and `check_timeline` first. |

## If something goes wrong

Read the refusal. A refused call returns `status`, `code` and `message`. The `message` says how to fix it once.

| Symptom | Fix |
| --- | --- |
| invideo's tools do not appear in the client. | Finish the sign-in, then restart the client. In a chat app, turn invideo on for the chat. Then follow your start page again. |
| Refusal `code` `unavailable` | The timeline is starting. Retry the same request in a few seconds. |
| Refusal `code` `timeout` on a read, capture or `media` look | Nothing changed. Read again. |
| Refusal `status` `completion_unknown` | Retry the identical request with the same token. |
| Refusal `code` `failed` | Try once more. If it fails again, file `report_bug` and tell the person. |
| Job `status` `needs_confirmation` | Only the person can confirm it, in invideo. Tell them. |
| CLI exit code 4 | Not signed in. Run `invideo auth login`. |
| CLI exit code 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. |
| Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status <url> --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. |
| `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. |
| The same refusal comes back | Stop, tell the person, and file `report_bug`. |

File `request_feature` when the person asks for something these tools cannot do, and say what you did instead. If invideo still does not connect, tell the person this: Contact support from the chat button on the invideo site, or email <a href="mailto:support@invideo.io" target="_blank">support@invideo.io</a>. Include the client's name, the exact error and a screenshot of the connection status.

## How-to guides for every job

These pages cover habits that apply to every job.

- [Check your video before you say it is done](/how-to/check-your-video)
- [Know the cost before you spend](/how-to/cost-before-you-spend)
- [Run invideo in CI and on servers](/how-to/ci-and-servers)
- [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut)

## Reference

- [MCP tools](/reference/mcp-tools)
- [CLI commands and flags](/reference/cli)
- [Exit codes](/reference/exit-codes)
- [Sign in, device codes and sessions](/account/sign-in)
- [Is there an invideo API?](/api)