# Build with AI Agents

> This page is about FlutterFlow Studio (the visual builder), not FlutterFlow (the app builder you use by describing your app).

URL: https://docs.flutterflow.io/flutterflow-cli/build

Create and edit FlutterFlow Studio projects from your terminal using your preferred AI coding agent.

The [FlutterFlow CLI](https://pub.dev/packages/flutterflow_cli) lets you create and edit FlutterFlow Studio apps from the terminal using your own AI coding agent, such as Claude Code, Gemini CLI, Codex, or any MCP-compatible client. You describe what you want in plain English, the agent plans and applies the changes, and the result lands as a real FlutterFlow Studio project you can open in the visual builder.

A FlutterFlow Studio project is the source of truth. The CLI is how you create or edit it from your local workspace.

If you use Codex, see [Build with Codex](https://docs.flutterflow.io/flutterflow-cli/codex) for the
FlutterFlow Studio plugin installation, secure authentication flow, and Codex-specific
troubleshooting.

![flutterflow-cli-ff-builder-using-same-ff-app](https://docs.flutterflow.io/assets/images/flutterflow-ff-builder-using-same-ff-app-ec46b7dc9dab6a03f2766eca594ffa83.avif)

## Architecture

`flutterflow ai init` creates a local **workspace** - a folder pre-configured with an MCP config file pointing at the FlutterFlow MCP server. When you launch your AI agent inside that folder, it discovers the MCP server and gains a set of tools that talk to FlutterFlow Studio's cloud:

1. You prompt the agent.
2. The agent plans changes and calls the MCP server's tools.
3. The MCP server applies those changes to your FlutterFlow Studio project.
4. You verify the result in the FlutterFlow Studio visual builder.

The workspace is just a folder on your disk. The actual project lives in FlutterFlow Studio server.

:::tip[What is MCP?]
The [**Model Context Protocol**](https://modelcontextprotocol.io) is an open standard that lets AI agents call external tools. The FlutterFlow AI MCP server exposes FlutterFlow Studio's project APIs to your agent so it can read and modify your project on your behalf.
:::

:::note[Remember]
- **FlutterFlow CLI is not a replacement for the visual builder.** FlutterFlow Studio is still faster for most visual work. FlutterFlow CLI is for precision, repeatability, and automation.
- **FlutterFlow CLI doesn't execute your app.** It produces a FlutterFlow Studio project, which you can test and run inside the FlutterFlow Studio visual builder.
:::

:::note[Prerequisites]

Before you start, make sure you have:

- **FlutterFlow CLI installed.** See [**Installation**](https://docs.flutterflow.io/flutterflow-cli).
- **A FlutterFlow Studio API key.** See [**generating an API token**](https://docs.flutterflow.io/accounts-billing/account-management#how-do-i-generate-an-api-token).
- **An MCP-compatible AI agent installed locally**, such as [**Claude Code**](https://www.claude.com/product/claude-code), [**Gemini CLI**](https://github.com/google-gemini/gemini-cli), or [**Codex**](https://github.com/openai/codex).
- **A FlutterFlow Studio project ID** (only if you're editing an existing project).
::: 

:::tip[Using Claude Code?]
The [**FlutterFlow Studio plugin for Claude Code**](https://docs.flutterflow.io/flutterflow-cli/claude-code) can handle the CLI install and API key setup for you, as an alternative to the manual setup below.
:::

## Setup Workspace

Open your terminal in the folder where you want the workspace to live, then run:

```bash
flutterflow ai init
```

By default, `flutterflow ai init` targets the production FlutterFlow Studio environment. To initialize a workspace against a non-production environment, pass the environment explicitly:

```bash
flutterflow ai init --env beta
flutterflow ai init --env enterprise-india
```

This launches an interactive setup wizard. Walk through the prompts:

1. **Workspace name.** A short, lowercase name with no spaces. This becomes the folder name for your project.
   ```
   Workspace name
     Directory to scaffold the FlutterFlow AI workspace in.
   > mindfly
   ```
2. **Existing project ID.** Press **Enter** with no input to create a new app, or paste an existing project ID to bind the workspace to it.
   ```
   Existing project ID to edit (press Enter to create a new app)
   >
   ```
3. **FlutterFlow Studio API key.** Paste your API key and press **Enter**. Input is masked.
4. **Register MCP server with detected coding CLIs.** The wizard scans your `PATH` and offers to register the FlutterFlow AI MCP server with each agent it finds (Claude Code, Gemini CLI, Codex, OpenCode). Answer `Y` (default) for each one you plan to use.
   ```
   Register FlutterFlow AI MCP server with coding CLIs
     Detected: claude, gemini, codex
     Register with claude? [Y/n]
   ```
5. **Confirm.** The wizard prints a summary. Review it and press **Enter** (default `Y`) to proceed.
   ```
   Ready to create:
     Workspace:  mindfly
     Project ID: (none, unlinked)
     API key:    set (***abcd)
     Base URL:   https://api.flutterflow.io  (built-in for prod)
     MCP CLIs:   claude, gemini, codex

   Proceed? [Y/n]
   ```

When the wizard finishes, you'll have a workspace folder ready for your agent. Depending on which CLIs you registered, the folder will contain one or more of:

- `.mcp.json` for Claude Code
- `.gemini/settings.json` for Gemini CLI
- `.codex/config.toml` for Codex
- `opencode.json` for OpenCode

Each file points the corresponding agent at the FlutterFlow AI MCP server.

<div style={{
    position: 'relative',
    paddingBottom: 'calc(56.67989417989418% + 41px)', // Keeps the aspect ratio and additional padding
    height: 0,
    width: '100%'}}>
    <iframe 
        src="https://demo.arcade.software/mBJK3OJs4yg0WY3GxSU0?embed&show_copy_link=true"
        title=""
        style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            colorScheme: 'light'
        }}
        frameborder="0"
        loading="lazy"
        webkitAllowFullScreen
        mozAllowFullScreen
        allowFullScreen
        allow="clipboard-write">
    </iframe>
</div>
<p></p>

## Launch your Agent

Move into the workspace and start your agent. The example below uses Claude Code; the same pattern applies to any agent you registered in the wizard. `cd` into the workspace and launch the agent's CLI.

Codex users who installed the FlutterFlow Studio plugin should start a new Codex task
from this workspace. See [Build with Codex](https://docs.flutterflow.io/flutterflow-cli/codex#choose-your-codex-surface).

```bash
cd mindfly
claude
```

The first time the agent opens the workspace, it detects the new MCP server and asks you to approve it. The exact prompt varies by agent. Claude Code's looks like this:

```
New MCP server found in .mcp.json: flutterflow_ai

MCP servers may execute code or access system resources.
All tool calls require approval.

> 1. Use this and all future MCP servers in this project
  2. Use this MCP server
  3. Continue without using this MCP server
```

Choose **option 1** to approve the FlutterFlow AI MCP server (and any others added to this workspace later) without being asked again.

> **Why approve?** Without the MCP server, the agent can edit local files but can't push changes to your FlutterFlow Studio project. With it approved, the agent has the same tools you'd run yourself from the CLI.

<div style={{
    position: 'relative',
    paddingBottom: 'calc(56.67989417989418% + 41px)', // Keeps the aspect ratio and additional padding
    height: 0,
    width: '100%'}}>
    <iframe 
        src="https://demo.arcade.software/wPBM094bg4iDSWblXpnG?embed&show_copy_link=true"
        title=""
        style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            colorScheme: 'light'
        }}
        frameborder="0"
        loading="lazy"
        webkitAllowFullScreen
        mozAllowFullScreen
        allowFullScreen
        allow="clipboard-write">
    </iframe>
</div>
<p></p>

## Generate a New App

With the agent connected, describe the app you want at the prompt:

```
> create a minimalist meditation app
```

Phrase it however you like: `a recipe-sharing app with a social feed`, `a habit tracker with streaks`, `a tip calculator for restaurants`. The agent plans the app, generates the changes, pushes them to FlutterFlow Studio through the MCP server, and reports back. Open FlutterFlow Studio in your browser and navigate to the project. The generated app will be reflected in the visual builder. From there you can keep refining visually or send another prompt to the agent.

Once the app exists, the workspace is bound to it. Follow-up prompts in the same session are treated as edits, not new generations, you'll see the agent acknowledge the switch with something like:

```
The project is bound, so I'll switch to edit mode.
Let me check the workspace and read the edit template.
```

From that point on, the same rules apply as when [editing an existing project](#edit-an-existing-project) - concurrency, branches, scope, and refreshing context.

<div style={{
    position: 'relative',
    paddingBottom: 'calc(56.67989417989418% + 41px)', // Keeps the aspect ratio and additional padding
    height: 0,
    width: '100%'}}>
    <iframe 
        src="https://demo.arcade.software/RnNngmhVpZflzDWqsDBA?embed&show_copy_link=true"
        title=""
        style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            colorScheme: 'light'
        }}
        frameborder="0"
        loading="lazy"
        webkitAllowFullScreen
        mozAllowFullScreen
        allowFullScreen
        allow="clipboard-write">
    </iframe>
</div>
<p></p>

## Edit an Existing Project

:::note[Prerequisite]
Have your **project ID** ready. Open the project in the FlutterFlow Studio editor. The project ID is the path segment after `/project/` in the URL.
:::

Editing an existing project follows the same flow as [creating a new one](#setup-workspace). You run `flutterflow ai init` to scaffold a workspace, then drive changes from your agent. The only difference is one step in the wizard: when it asks for an **existing project ID**, paste yours instead of pressing Enter:

```
Existing project ID to edit (press Enter to create a new app)
> mindfly-c9lbgr
```

The workspace is now bound to that project. `cd` into the workspace folder, [launch your agent](#launch-your-agent), and describe the changes you want, such as "add a profile screen", "switch the primary color to teal", or "wire up the login form to Firebase Auth". The agent reads the current project, plans the change, and pushes it through the MCP server. Open FlutterFlow Studio in your browser to verify.

:::caution[Pinned projects]
The FlutterFlow AI SDK writes project data in the format of the latest FlutterFlow Studio version, which a project pinned to an older version can't open. The SDK works on a pinned project only when the project is pinned to the latest stable FlutterFlow Studio version. For any other pin, pulls, pushes, and other SDK requests fail with an error that names the pinned version. This includes a project pinned to an older version and a project pinned to **Next stable release**. It also applies to a branch when its main project is pinned.

To use the SDK on such a project, open **Settings & Integrations > App Details**, and then set **Pinned FlutterFlow Studio Version** to the latest stable version or to **Latest Version (Unpinned)**. For more information, see [**Pinned FlutterFlow Studio Version**](https://docs.flutterflow.io/resources/projects/settings/flutterflow-version-management).

Only project members see this error. If a request fails because of a pinned project, your agent doesn't retry it or fall back to another command, because those requests are refused too. A merge that you started before the project was pinned can still be aborted.

If a project's pin changes while a request is running, the request isn't applied. Run it again.
:::

<div style={{
    position: 'relative',
    paddingBottom: 'calc(56.67989417989418% + 41px)', // Keeps the aspect ratio and additional padding
    height: 0,
    width: '100%'}}>
    <iframe 
        src="https://demo.arcade.software/VNb9xlkwjZGrdaeIpUb1?embed&show_copy_link=true"
        title=""
        style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            colorScheme: 'light'
        }}
        frameborder="0"
        loading="lazy"
        webkitAllowFullScreen
        mozAllowFullScreen
        allowFullScreen
        allow="clipboard-write">
    </iframe>
</div>
<p></p>

### Copy AI Selector

You can right-click any widget in the builder and select **Copy AI Selector** when you want the agent to update a specific widget in your app. This copies a precise location for the selected widget, which you can paste into your prompt so the agent knows exactly which widget to inspect or modify.

This is helpful when a page has repeated widgets, nested components, or similar labels. Instead of describing the widget only by its position or text, you can give the agent the copied selector value and ask for a targeted change, such as updating that widget's style, action, visibility, or data binding.

<div style={{
    position: 'relative',
    paddingBottom: 'calc(56.67989417989418% + 41px)', // Keeps the aspect ratio and additional padding
    height: 0,
    width: '100%'}}>
    <iframe 
        src="https://demo.arcade.software/Jx4zuTngeaDsJ3ZPKkNI?embed&show_copy_link=true"
        title=""
        style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            colorScheme: 'light'
        }}
        frameborder="0"
        loading="lazy"
        webkitAllowFullScreen
        mozAllowFullScreen
        allowFullScreen
        allow="clipboard-write">
    </iframe>
</div>
<p></p>

### Concurrent Edits with Builder

You can edit visually while an agent is working, but writes use **optimistic concurrency**: when the agent pushes, the server checks the project's last-modified timestamp against the agent's snapshot. If anyone else (you in the visual builder, a teammate, or another agent) modified the project in between, the push is rejected. The agent will re-read the latest state and retry. This may also mean re-planning if your change conflicts with what it was about to do.

So nothing gets silently overwritten, but expect occasional retries when you and the agent are editing the same project at once.

### Agent Edit Scope

**In scope**

- Pages, components, app state, theme, navigation, action blocks, app events
- Custom functions, actions, widgets, classes, and enums
- API endpoints, queries, custom data types and enums
- Pub and library dependencies, design tokens, GenUI catalog, Firebase Auth wiring
- [Native config files](#native-config-files), such as `AndroidManifest.xml`, `Info.plist`, and the `Podfile`. Unlocking or relocking a file always needs your approval.

**Out of scope**

- Anything outside the FlutterFlow Studio project itself, such as running the app, deploying it, creating Firebase projects, managing secrets, or handling App Store submissions.

### Refreshing Stale Context

If you've made visual edits since the agent last read the project, the agent's local snapshot is stale. Two ways to fix it:

- **Ask the agent to refresh.** Most agents call the [`refresh-context`](#mcp-tools) tool on their own when they detect drift, but you can prompt explicitly: "refresh the project context."
- **Run it from the CLI.** `flutterflow ai context-check` reports whether the local snapshot is behind, and `flutterflow ai refresh-context <project-id>` pulls the latest. 

See [MCP tools](#mcp-tools) for the full command list.

## Live Sessions

Live Sessions let your AI agent apply changes to a running FlutterFlow Studio app and display those updates directly on the connected device. This is useful when you want to iterate quickly. You can ask the agent to update screens, fix issues, inspect logs, trigger hot reloads or hot restarts, capture screenshots, and then immediately review the results on your running devices.

To use Live Sessions, run your app from the FlutterFlow Studio desktop app on a connected device or simulator, then activate your agent. Once the live session starts, confirm its status in the desktop app, ask the agent to make changes, and review those updates as they appear in the running app.

:::note
Keep the desktop app and the running app session open for as long as you want live updates to continue.
:::

<div style={{
    position: 'relative',
    paddingBottom: 'calc(56.67989417989418% + 41px)', // Keeps the aspect ratio and additional padding
    height: 0,
    width: '100%'}}>
    <iframe 
        src="https://demo.arcade.software/YFO4oGfSMWHGKqaEHRCy?embed&show_copy_link=true"
        title=""
        style={{
            position: 'absolute',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            colorScheme: 'light'
        }}
        frameborder="0"
        loading="lazy"
        webkitAllowFullScreen
        mozAllowFullScreen
        allowFullScreen
        allow="clipboard-write">
    </iframe>
</div>
<p></p>

## Native Config Files

Your agent can edit the same native [**Configuration Files**](https://docs.flutterflow.io/concepts/custom-code/configuration-files) that you edit in the **Custom Code** section of the editor: `AndroidManifest.xml`, `build.gradle`, `proguard-rules.pro`, `MainActivity.kt`, `Info.plist`, `Runner.entitlements`, `AppDelegate.swift`, and the `Podfile`.

Each file is either locked or unlocked:

- **Locked**: FlutterFlow Studio generates the file. The agent adds snippets at the places the editor offers for that file, and creates file-level variables for any `{{variableName}}` placeholders the snippets use. A variable's value is either text or one of your app constants. `MainActivity.kt` and the `Podfile` have no snippet places, so the agent can change them only after you unlock them.
- **Unlocked**: your project owns the whole file, and FlutterFlow Studio stops updating it when you add integrations later. The agent can replace the file's content, but FlutterFlow Studio doesn't apply snippets to an unlocked file.

If a snippet uses a `{{variableName}}` placeholder that the agent didn't declare as a variable, the run fails. The editor, by comparison, creates an empty variable for you.

### Approve Unlocking and Locking

The editor asks you to confirm before it unlocks or locks a file. The agent follows the same rule: a `run` never changes whether a file is locked, and the agent can't unlock a file to get around an error. If the agent needs to change an entire locked file, it prefers a snippet and otherwise asks you to unlock the file.

:::caution
Unlocking a file means you manage it yourself, and it can diverge when you add new integrations. Locking a file discards the content your project owns and goes back to the version FlutterFlow Studio generates. Snippets and variables are kept.
:::

You can approve a change in either of these ways:

- **Run the command yourself.** `flutterflow ai native-file unlock FILE` and `flutterflow ai native-file lock FILE` print what the change does and ask `Continue? [y/N]`. An unlock starts the file from the content FlutterFlow Studio generated, so the result matches unlocking it in the editor. Add `--yes` only if you run the command in a terminal that can't ask you a question. Without `--yes`, the command refuses to run there. Don't let an agent pass `--yes`.
- **Approve the agent's tool call.** The `native_file.unlock` and `native_file.lock` tools run only after you approve the call in your agent. When a file has content that a lock would discard, the agent first shows you that content. It locks the file only after you confirm and approve a second call. If a teammate saves the file in between, the agent shows you the new content and asks again.

To check the state of your files, run these read-only commands, or ask your agent to:

```
flutterflow ai native-file list
flutterflow ai native-file show Podfile
```

`list` shows whether each file is locked and how many snippets and variables it has. `show` lists a file's snippets and variables, and prints the content the way the editor shows it, with `{{variableName}}` placeholders left in place. Both commands default to the workspace project. Pass a project ID after the file name to use a different one.

:::note
Customizing a native file for the first time, whether by adding a snippet or a variable or by unlocking it, needs a paid plan, the same as in the editor. On the Free plan, the agent's push fails. Files that you already customized stay editable.
:::

## Investigate Project Activity

When a project behaves unexpectedly, ask your agent to retrieve the project's activity logs and identify changes that might explain the issue. The agent calls the read-only `activity_logs` tool with:

- `projectId`: The ID of the project.
- `startTime` and `endTime` (optional): The inclusive time range to retrieve. Each value is an ISO 8601 timestamp that ends with `Z` or includes a timezone offset, such as `2026-10-07T10:00:00+04:00`. If you omit `startTime`, there is no start-time limit. If you omit `endTime`, there is no end-time limit.

For example, replace `PROJECT_ID` with your project's ID in this prompt: "Retrieve the activity logs for project `PROJECT_ID` between 10:00 and 11:00 on October 7, 2026 (UTC+4), and explain what changed on the Home page."

The tool uses your FlutterFlow Studio API key and works with any project you have read access to, including projects where you're a read-only collaborator. It doesn't need an initialized workspace.

The result is JSON that contains:

- An activity timeline with a description of each edit, its source (editor, SDK, or hosted agent), and whether it was an undo or redo.
- Whether each recorded update was applied.
- The fields that each update changed, with their values before and after the update.
- Markers for history that isn't available.

Free-form text and binary values are redacted, so the result doesn't include text that people typed into the project.

If the result is large, the tool saves it to a JSON file in the `.flutterflow_ai/cache/activity_logs/` folder of your workspace and returns the file's path. Ask your agent to read that file.

:::note
- Activity logs record changes that reached FlutterFlow Studio. They don't include rejected requests or conversations between you and your agent.
- Older entries don't have change details, and the result marks them as not recorded. History beyond its retention period is marked as expired or missing.
- The SDK source indicates how a change was submitted, not whether a person or an AI agent decided to make it.
:::

## Branches and Rollback

The CLI can point to any branch of a FlutterFlow Studio project. Since each branch is accessed through its own URL, it has its own project ID. To work on a specific branch, open it in the FlutterFlow Studio editor, copy the project ID from the URL, and paste it when `flutterflow ai init` prompts for an existing project ID.

To roll back, use FlutterFlow Studio's project version history in the visual builder, which is the same mechanism used for visual edits. Each agent push lands as a commit there with whatever commit message the agent supplied.

## Working with Libraries

A workspace has one **primary project** and can also track the [library projects](https://docs.flutterflow.io/resources/projects/libraries) that the primary project depends on. Your agent can then edit a library and the app that uses it from the same workspace.

When you run `flutterflow ai init` with an existing project ID, the CLI downloads every library the project depends on, including libraries that other libraries depend on. Each library gets its own folder under `libraries/`, with its own `dsl/`, `generated_code/`, and `PROJECT_CONTEXT.md`. The primary project keeps the workspace root.

```
workspace/
├── dsl/                    (primary project)
├── generated_code/         (primary project)
├── PROJECT_CONTEXT.md      (primary project)
└── libraries/
    ├── auth_kit/
    │   ├── dsl/
    │   ├── generated_code/
    │   └── PROJECT_CONTEXT.md
    └── design_system/
```

To change which libraries `init` downloads, pass `--with-libraries`:

| Value | Libraries downloaded |
| --- | --- |
| `auto` or `all` (default) | All libraries, including nested ones. |
| `direct` | Only libraries the primary project depends on directly. |
| `none` | No libraries. |
| `ID_1,ID_2` | Only the libraries with these project IDs. |

### Choose Which Project a Command Changes

The `run`, `validate`, `refresh-context`, `codegen refresh`, and `status` commands accept a `--target` flag:

- `--target primary` (default) uses the primary project.
- `--target lib:NAME_OR_ID` uses the library with that local folder name or project ID.

If the library can't be found in the workspace, the command fails instead of falling back to the primary project. Pass `--all` to `refresh-context` or `codegen refresh` to refresh the primary project and every library at once.

```
flutterflow ai run libraries/design_system/dsl/edit.dart --target lib:design_system
flutterflow ai refresh-context --all
```

The `run` and `validate` tools that your agent calls through the MCP server also accept a `target` argument.

### Manage Library Dependencies

Use these commands to change which libraries the primary project depends on:

| Command | What it does |
| --- | --- |
| `add-library LIBRARY_PROJECT_ID` | Adds the library as a dependency and downloads it. Use `--name` to set the local folder name and `--version` to pin a version. |
| `remove-library NAME_OR_ID` | Removes the dependency. Use `--keep-files` to leave the `libraries/` folder on disk. |
| `update-library NAME_OR_ID --version VERSION` | Changes the pinned version and downloads it again. |
| `publish-library --version VERSION` | Publishes a new library version from the current state of the target project. Use `--target lib:NAME_OR_ID` to publish a library, `--description` to add a description, and `--and-update-primary` to also pin the primary project to the new version. |
| `library-versions` | Lists published versions, newest first, and marks the version the primary project uses. |

To create a library from the CLI, run `flutterflow ai create-project --name NAME --library`. Add `--attach` to also add the new library as a dependency of the primary project. To make the primary project of a new workspace a library, run `flutterflow ai init --as-library`.

### Frozen and Live Version Pins

A library dependency is pinned to a version in one of two ways. The pin decides whether your edits to a library reach the primary project:

- **Frozen**: a version number such as `1.3.0`. The primary project keeps using that published snapshot. Publish a new version and update the pin to pick up library changes.
- **Live**: `current` or `latest`. The primary project uses the library's latest saved state, so edits to the library appear in the primary project right away.

`flutterflow ai status` shows `(live)` or `(frozen)` next to each library. If you run `add-library` without `--version`, the dependency is pinned to the highest published version, which is frozen. To iterate on a library and an app together, switch the dependency to a live pin:

```
flutterflow ai update-library design_system --version current
```

When the library is ready, publish it and update the primary project in one step:

```
flutterflow ai publish-library --version 1.3.0 --target lib:design_system --and-update-primary
```

:::note
Publishing requires a paid plan and access to branching, the same as publishing a library from the editor. See [Libraries](https://docs.flutterflow.io/resources/projects/libraries#publishing-a-library) for the requirements.
:::

:::caution
Publishing a project marks it as a library permanently. For this reason, `publish-library` refuses to publish the primary project unless you created the workspace with `--as-library` or you pass `--allow-primary`. `--and-update-primary` works only for libraries the primary project depends on directly, not for nested ones.
:::

## Switching Projects

A workspace has one primary project, plus any libraries it tracks. To work on a different app, run `flutterflow ai init` in a **new** folder and link it to the new project ID. `init` refuses to run in a non-empty directory, so it won't re-bind an existing workspace.

## MCP tools

Run these from inside a FlutterFlow AI workspace. Your agent calls them via the MCP server; you can also run them directly in the terminal.

| Category | Command | What it does |
| --- | --- | --- |
| **Build** | `run` | Apply changes to your FlutterFlow Studio project. |
| | `validate` | Dry-run a change without pushing it. |
| **Explore** | `inspect` | Whole-project summary or a scoped view of structure. |
| | `resources` | List reusable project and library resources. |
| | `search` | Search the project for a name or identifier. |
| | `status` | Show workspace and project state. |
| **AI integration** | `mcp` | Register the FlutterFlow MCP server with Claude Code, Codex, Gemini CLI, Cursor, Copilot, and other MCP-aware clients. |
| **Native files** | `native-file` | List, show, unlock, or lock the project's [native config files](#native-config-files). |
| **Plan & audit** | `plan` | Capture intent before a run. |
| | `trace` | Replay a prior run. |
| | `history` | List prior commands and outcomes. |
| | `activity_logs` | Retrieve a project's [activity logs](#investigate-project-activity) for a time range. |
| **Diagnose** | `doctor` | Check for common workspace problems. |
| | `context-check` | Report whether the local snapshot is behind the live project. |
| | `precache` | Pre-load project context. |
| **Stay current** | `upgrade` | Update the FlutterFlow CLI tooling. |
| | `refresh-workspace` | Refresh the workspace's local config. |
| | `refresh-context` | Pull the latest project state into the local snapshot. |
| **Learn** | `docs [topic]` | Open FlutterFlow AI documentation for a topic. |

Run `flutterflow ai --help` from inside a workspace for the full command list and per-command flags. When the agent invokes a command via MCP, every call is subject to your agent's approval rules.
