> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sync Your First Project

> Pull a Metabind project to disk, make an edit in your own editor, and publish it with the CLI

In this tutorial, you'll pull an existing Metabind project to disk as files, edit one in your own editor, and send the change back: first as a draft you can inspect, then as a published release. By the end, you'll have run the flat-file loop once and know which step is safe to repeat and which one goes live.

Once the loop makes sense, the [flat-file sync guide](/cli/flat-file-sync) covers what this tutorial skips: conflicts, renames, and repairing local state.

## Prerequisites

<Note>
  Before you start, make sure you have:

  * The Metabind CLI installed and signed in. See [Install and Sign In](/cli/install). The CLI ships as a macOS binary through the Homebrew tap, with no Windows or Linux build and no `npx` form yet.
  * A project you can edit, saved as your active context with `metabind use`. Run `metabind status` to confirm which project you're pointed at.
  * Any text editor. This tutorial edits a Markdown file, so you don't need to know BindJS to finish it.
</Note>

## What You'll Build

You'll edit your project's MCP instructions (the text Metabind surfaces to MCP clients), then publish that edit. Nothing here touches a component, so there's no compile step and no way to break a running tool. The focus is the loop itself:

**Pull → edit → preview → push → publish.** `pull` and the preview write nothing you can't discard. `push` writes a draft. `publish` is the only step that changes what your live MCP app serves.

## Pull Before You Push

`push` reads a baseline that `pull` records in `.metabind/state.json` to tell your edits apart from server-side changes. **You have to `pull` a project before you can `push` it.** Run `push` in a directory you never pulled, and it stops before doing anything:

```text theme={null}
No .metabind/state.json under <dir>. Run metabind pull first
```

The loop always starts with a pull.

<Steps>
  <Step title="Pull the Project Into a Folder">
    Write the project to a new directory. `pull` is read-only: it fetches the files and records the baseline `push` needs later.

    ```bash theme={null}
    metabind pull --out ./my-project
    ```

    You now have a folder of files: `metabind.jsonc` for project settings, `mcp-instructions.md`, `components/` for BindJS source, `tools/` for tool definitions, `content/`, and a CLI-owned `.metabind/` directory holding the baseline. Secret *values* are never written, only their names. For the full layout, see the [flat-file sync guide](/cli/flat-file-sync#project-layout).
  </Step>

  <Step title="Change One File">
    Open `mcp-instructions.md` in the folder you pulled and add a line:

    ```markdown theme={null}
    Prefer concise answers. Link to the pricing page when a plan is mentioned.
    ```

    Save the file. This is an ordinary edit, detected by content rather than timestamp, so a file you didn't touch never registers as changed.
  </Step>

  <Step title="Preview What Would Change">
    Before writing anything back, preview the change. `push --plan` reports the changelist and exits without touching the server.

    ```bash theme={null}
    metabind push --plan --out ./my-project
    ```

    You should see your project settings marked as updated and everything else unchanged. `--plan` never writes, so you can rerun it as often as needed.
  </Step>

  <Step title="Push the Change as a Draft">
    Apply the edit. `push` writes to the server, but only ever as a draft, so nothing your published MCP app serves changes yet.

    ```bash theme={null}
    metabind push --out ./my-project
    ```

    If someone edited the same entity in Studio since you pulled, `push` refuses the whole batch rather than merging, so follow [Resolving Conflicts](/cli/flat-file-sync#resolving-conflicts) to reconcile it. It also stops before sending anything if an edit looks like it holds a secret value, so keep secrets in project secret bindings and reference them by name instead.
  </Step>

  <Step title="Publish the Release">
    Promote the draft to published. This is the step that changes what your live app serves: the same release action as publishing from Studio.

    ```bash theme={null}
    metabind publish
    ```

    If you only wanted to try the loop, stop before this step. A draft stays untouched until you publish it or replace it with a fresh pull.
  </Step>
</Steps>

## Verify It Works

Run the preview again from the same folder:

```bash theme={null}
metabind push --plan --out ./my-project
```

With your edit pushed and nothing else changed, it should report no changes to make. You can also open the project to see the published instructions:

```bash theme={null}
metabind open
```

## What You've Built

You've run the full flat-file loop once: you pulled a project to disk, edited it in your own editor, previewed the change, pushed it as a draft, and published it. Two rules keep the loop safe: `pull` establishes the baseline `push` depends on, and `push` only ever writes drafts, so `publish` is the single deliberate step that goes live.

## Next Steps

<CardGroup cols={2}>
  <Card title="Flat-File Sync" icon="folder-tree" href="/cli/flat-file-sync">
    The full workflow: project layout, conflicts, renames, and repairing local state.
  </Card>

  <Card title="CI Publish Lane" icon="github" href="/cli/ci-publish">
    Run this same loop from GitHub Actions, without storing a credential.
  </Card>

  <Card title="Workflow Map" icon="list-tree" href="/cli/verbs">
    Every CLI command family, grouped by the job it does.
  </Card>
</CardGroup>
