> For the complete documentation index, see [llms.txt](https://developer.celigo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.celigo.com/cli/local-tree.md).

# The local tree

`celigo pull` downloads your account — or one integration and everything it references — as a folder tree of JSON documents. Edit the files with any editor, review them in git, and write them back with `celigo push`. The tree is the unit of work for a team: pull requests review the diff, CI gates the plan, and a deploy job pushes the merge.

Seven top-level commands work on the tree. None of them is a resource group; they are bare verbs, like git's.

| Command                                                                | What it does                                                                                      | Mode                |
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------- |
| [`celigo pull`](/cli/local-tree/pull.md)                               | Download the account, or one integration, as a file tree. Incremental.                            | read                |
| [`celigo status`](/cli/local-tree/status-and-diff.md#celigo-status)    | List local changes since the last pull. Offline.                                                  | —                   |
| [`celigo diff`](/cli/local-tree/status-and-diff.md#celigo-diff)        | Compare the tree with the live account, field by field.                                           | read                |
| [`celigo push`](/cli/local-tree/push.md)                               | Write local changes back: update, create, and (with `--prune`) delete. Plan first.                | full                |
| [`celigo lint`](/cli/local-tree/lint-and-resolve.md#celigo-lint)       | Validate the documents against the platform's published API schemas and six logic rules. Offline. | —                   |
| [`celigo resolve`](/cli/local-tree/lint-and-resolve.md#celigo-resolve) | Turn a link, path, `type:id`, or id into the document's path. Offline.                            | —                   |
| [`celigo promote`](/cli/local-tree/promote.md)                         | Write the tree into another account or environment.                                               | full, on the target |

`celigo flows graph`, `apis graph`, and `tools graph` also read the tree: they render a flow's, an API's, or a tool's Flow Builder graph offline. See [flows](/cli/commands/flows.md#celigo-flows-graph). The [Celigo VS Code extension](/cli/vscode-extension.md) opens the same graph as an interactive canvas from a pulled `flow.json`, `tool.json`, or `api.json`.

## Quick start

```bash
# Pull one integration and everything it references into ./acme
celigo pull --integration 5f83a9b2c7d3e8f1a2b3c4d5 --dir ./acme --no-symlinks
cd acme

# Edit a flow, then see what changed
celigo status
celigo diff

# Validate offline, plan the push, push
celigo lint
celigo push --dry-run
celigo push
```

`--no-symlinks` writes pointer files instead of symlinks; use it for any tree you commit to git (see [Everything else is a link](#everything-else-is-a-link)). A tree pulled without `--integration` holds the whole account.

The output samples in these pages are the `--format table` rendering. The default format is JSON, which carries the same report; set `CELIGO_FORMAT=table` or `celigo config set default_format table` to read the text form (see [Output formats](/cli/using-the-cli/output-formats.md)). Notes and warnings print on stderr in either format.

## Layout

Three rules generate the whole shape.

### Every resource is a folder

The folder is named after the resource, and a fixed file name inside says what it is: `exports/Get Orders/export.json`, `connections/Shopify/connection.json`. Payloads you author sit beside the document as editable companions:

| Resource     | Document                                    | Companion                                                                          |
| ------------ | ------------------------------------------- | ---------------------------------------------------------------------------------- |
| script       | `scripts/<Name>/script.json`                | `script.js` — the source                                                           |
| lookup cache | `lookup-caches/<Name>/lookup-cache.json`    | `data.json` — the key-value entries, in the shape `lookup-caches put-data` accepts |
| AI agent     | `ai-agents/<Name>/ai-agent.json`            | `instructions.md` — the system prompt, byte for byte                               |
| guardrail    | `guardrails/<Name>/guardrail.json`          | `instructions.md`, for an `ai_agent` check only                                    |
| sync         | `integrations/<Int>/syncs/<Name>/sync.json` | `datasets/<Dataset>.json` — one document per dataset selection                     |

A companion is part of the resource. Deleting `instructions.md` is not read as "the prompt was cleared": a `PUT` that omits the prompt would clear it on the server, so `push` refuses the resource and names the missing file. `celigo pull` restores it.

AI agents and guardrails are `/v1/imports` rows split by `adaptorType`, and the tree gives them their own directories — `imports/` holds plain imports only. A step that names one through `_importId` links into the directory that holds it.

### Placement follows ownership

A resource of an ownable type that carries an `_integrationId` lives inside its integration's folder, mirroring the integration's tabs in integrator.io. Everything else pools at the top level.

| Type                                                                                                                                                                    | Where it lives                                                                                                                                                                                                                                           |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| flow                                                                                                                                                                    | `integrations/<Int>/flows/[<Flow group>/]<Flow>/flow.json`; instance flows in the parent's `instances/` folder                                                                                                                                           |
| sync                                                                                                                                                                    | `integrations/<Int>/syncs/<Sync>/sync.json`                                                                                                                                                                                                              |
| tool                                                                                                                                                                    | `integrations/<Int>/tools/<Tool>/tool.json`                                                                                                                                                                                                              |
| API                                                                                                                                                                     | `integrations/<Int>/apis/[<API group>/]<Api>/api.json` when owned; `apis/<Api>/api.json` when global. A script-mode API is always global.                                                                                                                |
| MCP server                                                                                                                                                              | `integrations/<Int>/mcp-servers/<Server>/` when owned, else `mcp-servers/<Server>/`                                                                                                                                                                      |
| Celigo Storage                                                                                                                                                          | `integrations/<Int>/storage/<Folder>/…` for a root folder whose metadata names the integration; else `storage/…`                                                                                                                                         |
| export, import, AI agent, guardrail, script, connection, iClient, stack, lookup cache, on-premise agent, EDI profile, file definition, async helper, MCP OAuth provider | pooled at the top level: `exports/`, `imports/`, `ai-agents/`, `guardrails/`, `scripts/`, `connections/`, `iclients/`, `stacks/`, `lookup-caches/`, `on-premise-agents/`, `edi-profiles/`, `file-definitions/`, `async-helpers/`, `mcp-oauth-providers/` |
| Event Streams topic                                                                                                                                                     | always pooled: `topics/<Topic>/topic.json` (see [Event Streams topics](#event-streams-topics))                                                                                                                                                           |

Pooling is what the platform enforces, not a preference: the API drops `_integrationId` from an export, import, lookup cache, or MCP server on write. Connections, lookup caches, and topics are *registered* to integrations (`_registeredConnectionIds`, `_registeredLookupCacheIds`, `_registeredTopicIds`), never owned.

### Everything else is a link

Every document exists exactly once. A reference from one resource to another is a link named after its target, in a typed subfolder of the resource that holds the reference:

* **Inside the resource that uses something.** A flow folder links its `exports/` and `imports/`; an export links its `connections/` and `scripts/`; an Event Streams listener or publisher links the topic it binds in `topics/`. A referenced script is linked by both faces: `<Name>.js` → its source and `<Name>.json` → its document.
* **Inside an integration, for what it registers** — its connections, lookup caches, and topics.
* **Inside an integration, for a tool or API it consumes** but another integration owns. The owner never links its own.

References the API keeps inside URI strings (`/v1/connections/<id>/proxy`, `/v1/lookupcaches/<id>/getData`, `/v1/apis/<id>/request`, `/v1/topics/<id>/messages`) are linked too, from exports, imports, AI agents, guardrails, and script source. A reference to a resource that does not exist produces no link, and `pull` warns about it.

A link is a real symlink by default. `celigo pull --no-symlinks` writes a `.link.json` pointer file instead — a small JSON record holding `{ _id, type, name, target }`. Use pointer files for trees shared through git across platforms; a Windows checkout of a symlink is a text file. Where symlink creation is refused (Windows without Developer Mode), `pull` warns once and falls back to pointer files. The link style is sticky: the first pull records it in the manifest, later pulls without a flag keep it, and switching an existing tree takes the other flag plus `--force`.

### Event Streams topics

> Added in celigo-cli 2026.10.1.

`celigo pull` writes every Event Streams topic to `topics/<Name>/topic.json`. The file holds the topic's configuration — `name`, `description`, `retentionMs`, `externalId` — and never its traffic: messages, read positions, and publishing stay on the platform, behind [`celigo topics`](/cli/commands/topics.md) `messages`, `offsets`, and `publish`.

A topic pools like a lookup cache. An integration *registers* a topic (`_registeredTopicIds`) and never owns it, so the integration's folder links each topic it registers. A step binds a topic through `topic._topicId`: a listener — an export with `adaptorType: TopicExport` and `type: "stream"` — reads it, and a publisher — an import with `adaptorType: TopicImport` — appends to it. Each links its topic in its own `topics/` folder. A topic an Integration App installed names that installation in a read-only `_integrationId` and still pools at `topics/`. In a [neutral tree](/cli/local-tree/neutral-trees.md) a step names its topic by tree path: `"_topicId": "topics/orders.created/topic.json"`.

A tree that holds a topic is written in manifest layout 6, which CLI 2026.9.6 cannot read; see [The `.celigo/` directory](#the-celigo-directory). [Pull a tree](/cli/local-tree/pull.md#pull-one-integration) says which topics a scoped pull brings, and [Push changes](/cli/local-tree/push.md#event-streams-topics) says how push creates and deletes them.

## What a tree looks like

An abridged tree, pulled with symlinks. `⇒` marks a link and its relative target; everything else is a real document.

```
├── ai-agents/
│   └── Classify Email/
│       ├── connections/
│       │   └── OpenAI.json  ⇒ ../../../connections/OpenAI/connection.json
│       ├── ai-agent.json
│       └── instructions.md
├── connections/
│   └── Shopify/
│       ├── iclients/
│       │   └── Shopify App.json  ⇒ ../../../iclients/Shopify App/iclient.json
│       └── connection.json
├── exports/
│   ├── Get Orders/
│   │   ├── connections/
│   │   │   └── Shopify.json  ⇒ ../../../connections/Shopify/connection.json
│   │   ├── scripts/
│   │   │   ├── Enrich.js  ⇒ ../../../scripts/Enrich/script.js
│   │   │   └── Enrich.json  ⇒ ../../../scripts/Enrich/script.json
│   │   └── export.json
│   └── Order Events Listener/                    ← an Event Streams listener
│       ├── topics/
│       │   └── orders.created.json  ⇒ ../../../topics/orders.created/topic.json
│       └── export.json
├── imports/
│   └── Post Orders/
│       ├── connections/
│       │   └── Shopify.json  ⇒ ../../../connections/Shopify/connection.json
│       └── import.json
├── integrations/
│   └── Order to Cash/
│       ├── connections/
│       │   └── Shopify.json  ⇒ ../../../connections/Shopify/connection.json
│       ├── flows/
│       │   └── Fulfillment/                      ← flow group
│       │       └── Order Sync/
│       │           ├── exports/
│       │           │   └── Get Orders.json  ⇒ ../../../../../../exports/Get Orders/export.json
│       │           ├── imports/
│       │           │   └── Post Orders.json  ⇒ ../../../../../../imports/Post Orders/import.json
│       │           ├── instances/                ← instance flows
│       │           │   └── Acme Instance/
│       │           │       └── flow.json
│       │           └── flow.json
│       ├── tools/
│       │   └── Ranking Tool/
│       │       └── tool.json
│       ├── topics/                               ← topics it registers
│       │   └── orders.created.json  ⇒ ../../../topics/orders.created/topic.json
│       └── integration.json
├── lookup-caches/
│   └── SKU Map/
│       ├── data.json
│       └── lookup-cache.json
├── scripts/
│   └── Enrich/
│       ├── script.js
│       └── script.json
├── storage/
│   └── readme.txt.json                           ← metadata stub; --storage-files fetches the bytes
└── topics/
    └── orders.created/
        └── topic.json                            ← configuration only; messages never enter the tree
```

### Folder names

Folder names are display names, sanitized for Windows and capped at 60 characters. Two resources whose names collide within one directory get a short id suffix (`Get Orders__bda178`); names are compared case-insensitively and after Unicode normalization, the way macOS and Windows compare them. A resource with an empty name becomes `unnamed__<shortid>`. Ids appear nowhere else: `.celigo/manifest.json` keeps the id ↔ path ↔ hash map, so identity is the id and a resource can move without losing its tracking.

Renaming a folder changes nothing on the platform. The folder name is derived from the resource's `name` field; to rename a resource, edit `name` in its document and push — the next pull moves the folder. A moved folder is one `moved` event in `celigo status`, never a delete plus a create, so `push --prune` cannot delete a resource over a rename. Since celigo-cli 2026.10.1 that holds for a renamed script folder too, and in a [neutral tree](/cli/local-tree/neutral-trees.md), whose documents carry no `_id`, for a folder moved without edits: it is recognized by its content.

## The `.celigo/` directory

| Path                          | Holds                                                                                                                                                                                                                                                                                                         | Commit it?                            |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `.celigo/manifest.json`       | The tracked resources: `type:id` → file paths and hashes, the `lastModified` lock tokens, the tree's scope, its link style, the account it is bound to (`baseUrl`, `accountUserId`), and the intent markers of an interrupted push. Deterministic — no timestamps, sorted keys — and validated on every load. | Standard tree: yes. Neutral tree: no. |
| `.celigo/.gitignore`          | Written by pull, before its first request: `local/`, `tmp/`, `bindings.json`, `*.tmp` (a neutral tree's is `*`).                                                                                                                                                                                              | Written for you.                      |
| `.celigo/local/`              | Per-machine state: when this machine last pulled, `lint`'s feedback ledger, the tree lock, the journal of an interrupted pull or push (`pull-journal.json`), and the record of a lookup cache data sync a push has not finished (`data-sync/`).                                                               | Never.                                |
| `.celigo/storage/<id>.json`   | Celigo Storage item metadata (nothing authored lives in it).                                                                                                                                                                                                                                                  | Yes, or ignore storage.               |
| `.celigo/bindings.json`       | A [neutral tree's](/cli/local-tree/neutral-trees.md) binding keys → this environment's ids.                                                                                                                                                                                                                   | Never.                                |
| `.celigo/targets/<name>.json` | A [promote](/cli/local-tree/promote.md) target's id map and lock tokens.                                                                                                                                                                                                                                      | Yes.                                  |
| `.gitattributes` (tree root)  | Written once by pull: `*.json`, `*.js`, `*.md` as LF text; the manifest as `merge=binary`, so git stops on a manifest conflict instead of interleaving two JSON documents.                                                                                                                                    | Yes.                                  |

A manifest that fails validation — an unknown key, a path outside the tree, git conflict markers — is refused with one message: `.celigo/manifest.json is corrupt (<reason>) — re-pull into a fresh directory, or restore the file from git.` Nothing is repaired in place. (A symlinked content directory or document is refused on the same load with its own message; see [Pull a tree](/cli/local-tree/pull.md#gotchas).)

**Layout version.** The 2026.9.1 release writes layout v5. Since celigo-cli 2026.10.1, a tree that holds an Event Streams topic is written in layout v6; every other tree stays at v5, and a tree never goes back down a layout — one whose topics were deleted from the account stays at v6. This release reads both. CLI 2026.9.6 cannot read a layout-6 tree: it refuses it as pulled with a newer CLI and asks you to upgrade, so upgrade every machine and CI job that works on a tree before it holds a topic. A tree pulled with an older layout is refused: `This tree was pulled with an older CLI (local-tree layout v4; this CLI writes layout v5, or v6 for a tree that holds topics). Re-pull with this CLI version into a fresh directory, or delete the old tree (including .celigo/) and pull again.`

## How files are written and compared

**Owner-only, atomic writes.** Since celigo-cli 2026.10.1, `pull` and `push` write each document, its companion files, and the manifest through a temporary file beside it that is renamed into place, created readable and writable by your user only (`0600`). A pulled script can hold a hardcoded secret, so no instant of the file is readable by other users, and a full disk never leaves half a document that `status` would report as modified.

**A document is compared by what push would send.** Since celigo-cli 2026.10.1, a `.json` document is compared as push would send it — parsed and rendered canonically — not byte for byte. A file an editor's formatter rewrote (re-indented, keys reordered, the trailing newline dropped) is clean for `status`, `diff`, `push`, `pull`, and `lint`. A changed value, key, or array order is always an edit. A script's or a prompt's text is sent as written, so it is compared as text.

**Line endings.** A `.json`, `.js`, or `.md` file that differs from what was pulled only by CRLF line endings or a leading byte-order mark is not an edit, with or without the tree's `.gitattributes` (a clone made before it existed, `core.autocrlf=true`, an editor that adds a BOM). A script or prompt whose server text mixes CRLF and LF line endings stays clean after a checkout makes them uniform: since celigo-cli 2026.10.1 its manifest hash also records which lines end in CRLF, so `status` and `diff` agree and a push sends the server's text back. A tree an earlier release pulled gains that record on its next `pull`; an earlier CLI does not read the record and reports such a file as modified. A downloaded storage file is compared byte for byte, because `\r\n` in it is data. An edit made in a CRLF checkout is still pushed as written: a JSON document is re-parsed, but a `script.js` is sent verbatim, `\r\n` included. Keep the `.gitattributes`, or `core.autocrlf=input`, wherever scripts are edited on Windows.

## Interrupted pulls and pushes

> Added in celigo-cli 2026.10.1.

A pull holds Ctrl-C, `SIGTERM`, and a closed terminal (`SIGHUP`) until its writes and the manifest save are done. A kill nothing can hold — `SIGKILL`, the out-of-memory killer, a power loss — can still land between the two. So before a pull removes or moves the files of a resource the server still has (a server-side rename, an orphan `--untrack-orphans` lets go), or writes the files of a resource new to the tree, it records them in `.celigo/local/pull-journal.json`. A push does the same before a `name` edit moves a folder, or before a new resource's draft moves to its canonical folder. The journal is per machine and is never committed.

A run killed in between leaves the resource **unfinished**, never a deletion or a new file to create:

```
$ celigo status
unfinished: exports/Get Orders/export.json → exports/Orders/export.json (an interrupted `celigo pull` was renaming it — run `celigo pull` to finish)
```

* `celigo push` neither updates, prunes, nor creates it, and says so on stderr: `unfinished pull: … — <key> is not pushed, and not deleted under --prune`.
* `celigo diff` lists it as `unfinished (not compared)`, `celigo lint` reports it as one `unfinished` error and lints none of its files, and `celigo resolve` refuses it, naming both paths.
* `celigo pull` finishes it. A file that holds exactly what the journal recorded is the interrupted run's own, not a local edit; a file you changed since is kept, as any local edit is.

One case is finished by a push instead. When a push's write-back failed after writing a new resource's document (a full disk), the draft it was created from is reported `unfinished`, and the next push adopts the resource instead of creating it again. A journal that cannot be read stops `status`, `diff`, `push`, `pull`, `lint`, and `resolve`, naming the file; delete it, run `celigo pull`, and check `celigo status` before any `celigo push --prune`.

## What the tree strips and what it never carries

**Volatile fields never reach a file.** `lastModified`, debug timers, cache and storage sizes, a connection's live `queues` are stripped on pull, so diffs stay meaningful and `push` never sends them from the file. Cross-references stay as raw `_id` values, exactly as the API returns them — unless the tree was pulled with `--neutral` (see [Neutral trees](/cli/local-tree/neutral-trees.md)).

**Credentials never travel.** The API masks encrypted fields as `"******"` on `GET`, and a `PUT` replaces the whole document. A mask sent back keeps the stored secret, but `push` never sends one: it refuses any `connections`, `iclients`, or `mcp-oauth-providers` document still holding `"******"` (send such a document with `<group> update --force` instead). Since celigo-cli 2026.10.1 it also refuses, at plan time and with no override, a create whose document carries the mask (four or more asterisks and nothing else) anywhere, on every type — a new resource has no secret behind the mask — and a value that is not a string in a field the platform encrypts. To set a secret through the tree, type the real value in place of the mask, push, and let the write-back mask it again — the file becomes the server's copy immediately. A secret typed over the mask is always sent, never taken for the server's own copy. Do not commit between the edit and the push. `celigo diff` never prints such a value: it renders as `****** → (set)`, in JSON output too, and since celigo-cli 2026.10.1 `diff` hides the value of every field the platform encrypts, on every type.

**Celigo Storage is pull-only.** `storage/` mirrors the service's hierarchy: a folder is a directory, a file is either its downloaded bytes (with `pull --storage-files`) or a `<name>.json` metadata stub — never both. `push` never writes storage; the [`celigo storage`](/cli/commands/storage.md) commands are the write path.

**Integration App documents are pull-only.** A document carrying `_connectorId` belongs to an Integration App whose connector code owns it. It pulls like everything else, so a custom flow's reference to an app's connection resolves, but `push` withholds edits to it, never deletes it under `--prune`, and never `PUT`s the app's `integration.json`. `push --allow-connector-resources` pushes edited app flows, exports, and imports; since celigo-cli 2026.10.1 a field the app locks fails the item, and your edit stays in the file. The app's settings are saved through its connector code: [`celigo integrations persist-settings`](/cli/commands/integrations.md#celigo-integrations-persist-settings) one field at a time, or — since celigo-cli 2026.10.1 — `push --allow-connector-settings` for the values you edited in its `integration.json` (see [Integration App settings](/cli/local-tree/push.md#integration-app-settings)).

**Notifications are not in the tree.** They are per-user subscription records, managed with [`celigo notifications`](/cli/commands/notifications.md).

## `.celigoignore`

`.gitignore` governs what you commit; it cannot stop `pull` from writing a file or `push` from sending one. A `.celigoignore` in the tree root does, in gitignore syntax:

```
# a whole integration
integrations/Sandbox/

# every lookup cache — except the one that matters
lookup-caches/
!lookup-caches/customers/

# a name at any depth
*.tmp.json
```

A pattern containing a slash is anchored to the tree root; one without matches that name at any depth. A trailing `/` covers the directory and everything under it. `!` re-includes, and later patterns win. Unlike git, a re-include works beneath an excluded folder: `integrations/**` followed by `!integrations/Prod/**` keeps only Prod in reach. Since celigo-cli 2026.10.1 such a folder is walked and each file under it judged on its own, so a new file under `integrations/Prod/` is a create candidate.

The contract is "don't touch", in both directions. An ignored resource is not written, not tracked, not pruned, not pushed, and not deleted, so adding a pattern is never destructive. `pull` counts ignored resources under `ignored`, their links disappear, `status` and `diff` say nothing about them, and naming one on `push` reports it as `ignored`, never as "up to date".

The contract holds only while the rules can be read. Since celigo-cli 2026.10.1, a `.celigoignore` that exists but cannot be read — no read permission, a directory by that name — stops `pull`, `status`, `diff`, `push`, `promote`, `lint`, and `resolve` before they read the account or plan anything:

```
.celigoignore cannot be read (<error>) — its rules decide what pull writes, push sends and --prune deletes, so nothing runs without them. Make it a readable file, or delete it if the tree should have no rules.
```

A tree without the file has no rules.

**Parking a tracked resource.** Since celigo-cli 2026.10.1, a tracked resource folder you move into an ignored folder is *parked*, not read as deleted:

```
$ mv "exports/Get Orders" "integrations/Sandbox/exports/Get Orders"
$ celigo status
parked:    exports/Get Orders/export.json → integrations/Sandbox/exports/Get Orders/export.json  (in an ignored folder - not pushed, not deleted)
```

`push` never writes a parked resource, even when its file is edited there, and `push --prune` never deletes it. `celigo pull` leaves it where you moved it (`left parked: …`) and recreates nothing at the old path, `celigo diff` lists it as parked instead of comparing it, and `celigo resolve` points at its document in the ignored folder. Move the folder back out of the ignored path and it is an ordinary move again. The same holds for a folder moved under a pattern that ignores only a folder's contents (`exports/_archive/*`), and for an ignored folder beside the resource folders (`_archive/`).

## The tree is bound to an account

The manifest records the API host the tree was pulled from and the token owner's user id (`GET /v1/tokenInfo`). `pull`, `diff`, and `push` refuse a profile that targets another host or whose token belongs to another user — however the profile was selected, `--profile` and `CELIGO_PROFILE` included. The profile *name* is only a label: a different name on the same account is a stderr note, and an env-only CI job (`CELIGO_API_TOKEN` plus `CELIGO_BASE_URL`, no config file) can push. `--allow-account-mismatch` on `pull` and `push` is the only override. Since celigo-cli 2026.10.1, a `tokenInfo` answer that names no account — no `ownerUser`, as for an OAuth sign-in whose account grant the platform cannot confirm — counts as a failed probe: a warning, the host match, and nothing bound. The full rules, including what happens when the identity probe fails, are in [Teams, git, and CI](/cli/local-tree/workflow.md#the-account-binding).

## What's next

* [Pull a tree](/cli/local-tree/pull.md) — scoped pulls, `--force`, `--prune`, link styles, storage, interrupted pulls.
* [Status and diff](/cli/local-tree/status-and-diff.md) — local changes, live comparison, CI exit codes.
* [Push changes](/cli/local-tree/push.md) — the plan, the refusals, the logic lint gate, topics, Integration App settings, the optimistic lock, interrupt safety.
* [Lint and resolve](/cli/local-tree/lint-and-resolve.md) — offline schema and logic validation, and ref lookup.
* [Neutral trees](/cli/local-tree/neutral-trees.md) — one git branch per environment.
* [Promote to another account](/cli/local-tree/promote.md) — write the tree into a sandbox or another account.
* [Teams, git, and CI](/cli/local-tree/workflow.md) — what to commit, branches, the PR check and deploy jobs.
