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

# project

> Create, inspect, update, and remove Projects. A Project owns one repository, a type, and the source defaults that Instances inherit.

A Project records one Git repository and the defaults for running it. [Projects](/docs/reference/projects) owns the fields, types, update lifecycle, and error codes. [Applications](/docs/domains/applications) shows how a Project becomes an Instance.

## Commands

| Command | Result |
| - | - |
| [`project:create`](#orbit-projectcreate) | Create a Project from a slug, a type, and a repository URL. |
| [`project:list`](#orbit-projectlist) | List Projects. |
| [`project:show`](#orbit-projectshow) | Show one Project. |
| [`project:update`](#orbit-projectupdate) | Change a Project and reconcile its Instances. |
| [`project:destroy`](#orbit-projectdestroy) | Remove a Project. |
| [`project:dev-deploy-step:list`](#orbit-projectdev-deploy-steplist) | List development deploy steps. |
| [`project:dev-deploy-step:create`](#orbit-projectdev-deploy-stepcreate) | Record a development deploy step. |
| [`project:dev-deploy-step:update`](#orbit-projectdev-deploy-stepupdate) | Change a development deploy step. |
| [`project:dev-deploy-step:destroy`](#orbit-projectdev-deploy-stepdestroy) | Remove a development deploy step. |
| [`project:excluded-node:add`](#orbit-projectexcluded-nodeadd) | Keep a Project off an `app-dev` Node. |
| [`project:excluded-node:list`](#orbit-projectexcluded-nodelist) | List the Nodes a Project cannot use. |
| [`project:excluded-node:remove`](#orbit-projectexcluded-noderemove) | Let a Project use an `app-dev` Node again. |
| [`project:document:list`](#orbit-projectdocumentlist) | List the entries in a Project Documents folder. |
| [`project:document:search`](#orbit-projectdocumentsearch) | Find Project Document entries by name or path. |
| [`project:document:show`](#orbit-projectdocumentshow) | Show the metadata of one entry. |
| [`project:document:create`](#orbit-projectdocumentcreate) | Create a folder or a file. |
| [`project:document:update`](#orbit-projectdocumentupdate) | Rename or move an entry. |
| [`project:document:read`](#orbit-projectdocumentread) | Print a file's text. |
| [`project:document:upload`](#orbit-projectdocumentupload) | Write local bytes as a new file version. |
| [`project:document:write`](#orbit-projectdocumentwrite) | Write text as a new file version. |
| [`project:document:download`](#orbit-projectdocumentdownload) | Save a file version to a new local file. |
| [`project:document:versions`](#orbit-projectdocumentversions) | List a file's versions. |
| [`project:document:restore-version`](#orbit-projectdocumentrestore-version) | Make an earlier version the newest one. |
| [`project:document:archive`](#orbit-projectdocumentarchive) | Archive an entry. |
| [`project:document:restore`](#orbit-projectdocumentrestore) | Restore an archived entry. |
| [`project:document:remove`](#orbit-projectdocumentremove) | Permanently remove an entry. |
| [`project:document-storage:show`](#orbit-projectdocument-storageshow) | Show the private document storage and its status. |
| [`project:document-storage:update`](#orbit-projectdocument-storageupdate) | Configure the private document storage. |

Every command accepts `--json`.

## Project Documents

The `project:document` commands browse, change, and version the documents of a Project. The `project:document-storage` commands configure the Gateway's private storage for them. Each command has its own section below, and [Project Documents](/docs/reference/project-documents#cli-contract) owns the full contract.

Mutations require an observed `--expected-revision`; permanent removal also requires `--yes` without a terminal. JSON mode preserves the API envelope. Local validation uses `input.invalid` and exit 2. Local download integrity or filesystem failures use `project_documents.local_io_failed` and exit 1. On `project_documents.revision_conflict`, preserve the draft and reread metadata rather than retrying automatically.

## orbit project:create

```bash theme={"dark"}
orbit project:create <slug> <type> <repository> [options]
```

| Argument | Meaning |
| - | - |
| `slug` | Unique Project slug. |
| `type` | `monorepo`, `laravel-app`, `symfony-app`, `laravel-package`, or `node-package`. |
| `repository` | HTTPS or SSH Git URL. |

| Option | Default | Meaning |
| - | - | - |
| `--name=NAME` | the slug | Display name. |
| `--source-access=VALUE` | `github_app` | `github_app` or `gh_cli`. How Orbit reads a private `github.com` repository. See [Source access](/docs/reference/projects#source-access). |
| `--default-branch=BRANCH` | the remote default | Stored default branch. The Gateway verifies that an explicit branch exists. |
| `--root=PATH` | `.` for `laravel-package` and `node-package`; `public` otherwise | Normalized repository-relative root that Instances inherit. `.` means the repository root. |
| `--task-check=COMMAND` | none | Command that task baselines and handoffs run in the workspace. See [Project check](/docs/reference/tasks#project-check). |
| `--task-workspace-routed=true\|false` | true | Whether new task workspaces get a Route. See [Task workspace routing](/docs/reference/projects#task-workspace-routing). |

```bash theme={"dark"}
orbit project:create acme laravel-app git@github.com:acme/site.git
orbit project:create support laravel-package git@github.com:acme/support.git
orbit project:create node-kit node-package git@github.com:acme/node-kit.git --task-check="vp run check"
orbit project:create leden laravel-app git@github.com:acme/leden.git --source-access=gh_cli
```

A retry with the same values returns the existing Project.

## orbit project:list

List every Project with its slug, type, repository, default branch, and root. JSON output also includes the source access.

```bash theme={"dark"}
orbit project:list [--json]
```

## orbit project:show

Show one Project with its source access, source defaults, task check, task workspace routing, and excluded Nodes. Human detail output labels the boolean `Task workspace routed`; JSON uses `task_workspace_routed`. Null `default_branch` or root values mean the source defaults are incomplete, and new Instance creation fails with `project.source_defaults_incomplete` until they exist. A null task check means tasks run no check command. Human output also lists the Project's Instances with ID, name, environment, Node, domain, and status. In a terminal, selecting an Instance opens `instance:show`.

```bash theme={"dark"}
orbit project:show <project> [--json]
```

## orbit project:update

Change a Project's display name, type, source access, source defaults, task check, task workspace routing, or review and merge. Omitted fields stay unchanged. The Gateway reconciles affected development sources, checkouts, Routes, inherited web roots, and runtimes before publishing the change. It does not start a production deployment. See [Update a Project](/docs/reference/projects#update-a-project) for validation, rollback, and retry behavior.

```bash theme={"dark"}
orbit project:update <project> [--name=NAME] [--type=TYPE] [--slug=SLUG] [--repository=URL] [--source-access=VALUE] [--default-branch=BRANCH] [--root=PATH] [--task-check=COMMAND] [--clear-task-check] [--task-workspace-routed=true|false] [--review-and-merge=true|false] [--merge-check=NAME] [--clear-merge-check]
```

| Option | Meaning |
| - | - |
| `--name=NAME` | New display name, at most 255 characters. Applies at once; the slug, domains, and code stay. |
| `--type=TYPE` | New Project type. A change to `laravel-app` or `symfony-app` is refused while an active Instance has no Route. |
| `--slug=SLUG` | New Project slug. Generated development domains follow it; recorded paths stay unchanged. |
| `--repository=URL` | New Git access URL. The Gateway validates ownership before updating checkout origins and re-binding production homes. The current URL repairs a home left on an older URL. See [Production Instances](/docs/reference/projects#production-instances). |
| `--default-branch=BRANCH` | New default branch for development sources that inherit it. |
| `--source-access=VALUE` | `github_app` or `gh_cli`. Applies at once after the Gateway reads the remote with the new value. |
| `--root=PATH` | New normalized repository-relative root for Instances without an override. Package types may use `.`. |
| `--task-check=COMMAND` | New command that task baselines and handoffs run. A type change does not change it. |
| `--clear-task-check` | Remove the task check so tasks run no check command. Combining it with `--task-check` fails with `project.task_check_conflict`. |
| `--task-workspace-routed=true\|false` | Change routing for future task workspaces. Invalid values return `project.task_workspace_routed_invalid` before a request. Existing workspaces keep their mode. |
| `--review-and-merge=true\|false` | Switch the [review-and-merge flow](/docs/reference/tasks#review-and-merge). Invalid values return `project.review_and_merge_invalid` before a request. |
| `--merge-check=NAME` | The check that must pass on a head before Orbit merges it, such as `Required checks`. |
| `--clear-merge-check` | Remove the merge check. Combining it with `--merge-check` fails with `project.merge_check_conflict`. The Gateway refuses it while the flow is on. |

## orbit project:destroy

Remove a Project that has no Instances and no Routes. Its definitions, setup steps, Node exclusions, and update records go with it. A Project with tasks cannot be removed: the request fails with HTTP 409 and `project.has_task_groups`. See [Remove a Project](/docs/reference/projects#remove-a-project).

```bash theme={"dark"}
orbit project:destroy <project> [--yes] [--json]
```

The CLI shows the Project and asks for confirmation, with No selected. `--yes` confirms without a prompt and is required for JSON and noninteractive calls.

## orbit project:dev-deploy-step:list

List the Project's development deploy steps in stored order. Each entry shows its name, command, timeout, and whether it is required. JSON returns `steps` and `request_id`.

```bash theme={"dark"}
orbit project:dev-deploy-step:list --project=4 [--json]
```

## orbit project:dev-deploy-step:create

Record a named step without starting a deployment. Human step results show control characters as visible escapes and preserve literal text such as `<error>` tags; JSON preserves the stored command unchanged. [Development deploy steps](/docs/reference/deployments#development-deploy-steps) owns the limits, placement rules, and required-versus-best-effort behavior.

```bash theme={"dark"}
orbit project:dev-deploy-step:create <name> --project=ID --command=COMMAND [--timeout=300] [--required=true|false] [--before=NAME | --after=NAME] [--json]
orbit project:dev-deploy-step:create install --project=4 --command="composer install --no-interaction"
```

`name` is the step name, unique within the Project.

| Option | Meaning |
| - | - |
| `--project=ID` | Required numeric Project ID. |
| `--command=COMMAND` | Required shell command for create; replacement command for update. |
| `--timeout=SECONDS` | Step timeout, default 300 on create. |
| `--required=true\|false` | Whether failure prevents activation. Defaults to true on create. |
| `--before=NAME` | Place before another step in this list. |
| `--after=NAME` | Place after another step in this list. Cannot be combined with `--before`. |

## orbit project:dev-deploy-step:update

Change a named step. Omitted fields keep their stored values. A required-only update is supported. JSON for create, update, and remove returns `name`, `command`, `timeout_seconds`, `required`, and `request_id`.

```bash theme={"dark"}
orbit project:dev-deploy-step:update cache --project=4 --required=false [--command=COMMAND] [--timeout=SECONDS] [--before=NAME | --after=NAME] [--json]
```

## orbit project:dev-deploy-step:destroy

Remove a named step. The remaining steps keep their order. `--yes` confirms without prompting and is required for JSON and noninteractive calls.

```bash theme={"dark"}
orbit project:dev-deploy-step:destroy <name> --project=ID [--yes] [--json]
orbit project:dev-deploy-step:destroy cache --project=4
```

## orbit project:excluded-node:add

Keep a Project off an `app-dev` Node for development placement. The Node must have an active `app-dev` role. A second `add` of the same pair returns the stored exclusion. [Development node exclusions](/docs/reference/development-node-exclusions) owns the rules.

```bash theme={"dark"}
orbit project:excluded-node:add <node> --project=ID [--json]
orbit project:excluded-node:add sabre --project=4
```

| Argument or option | Meaning |
| - | - |
| `node` | Node ID or name. |
| `--project=ID` | Numeric Project ID. |

In a terminal, an omitted Project or Node opens a searchable selector. JSON and noninteractive calls must name both.

## orbit project:excluded-node:list

List the `app-dev` Nodes the Project cannot use. Each entry shows the Node and the number of development Instances of the Project already on it.

```bash theme={"dark"}
orbit project:excluded-node:list --project=ID [--json]
```

## orbit project:excluded-node:remove

Let the Project use the Node again. It asks for no confirmation, because it moves and stops nothing.

```bash theme={"dark"}
orbit project:excluded-node:remove <node> --project=ID [--json]
```

## orbit project:document:list

List the direct children of a folder, or of the root. Columns are ID, KIND, NAME, REVISION, SIZE, and ARCHIVED. [Project Documents](/docs/reference/project-documents#cli-contract) owns the full command contract.

```bash theme={"dark"}
orbit project:document:list <project> [--parent=ID] [--state=active|archived|all] [--kind=folder|file] [--cursor=CURSOR] [--limit=50] [--json]
```

| Argument or option | Meaning |
| - | - |
| `project` | Project ID or slug. Every `project:document` command takes it first. |
| `--parent=ID` | Folder to list. The root by default. |
| `--state=active\|archived\|all` | Archive state. Default `active`. |
| `--kind=folder\|file` | Show only one kind. |
| `--cursor=CURSOR` | Page cursor from the previous page. |
| `--limit=N` | Page size. Default 50. |

## orbit project:document:search

Find entries whose name or path contains the query. Columns are ID, KIND, PATH, REVISION, SIZE, and ARCHIVED.

```bash theme={"dark"}
orbit project:document:search <project> <query> [--state=active|archived|all] [--kind=folder|file] [--cursor=CURSOR] [--limit=50] [--json]
```

`query` is a name or path substring. The options work as for `project:document:list`.

## orbit project:document:show

Show the metadata of one entry. It never prints the body.

```bash theme={"dark"}
orbit project:document:show <project> <entry> [--json]
```

`entry` is a numeric entry ID, never a path. Every command that acts on one entry takes it second.

## orbit project:document:create

Create a folder or a file.

```bash theme={"dark"}
orbit project:document:create <project> <name> --kind=folder|file [--parent=ID] [--from=PATH|-] [--content=TEXT] [--media-type=TYPE] [--json]
orbit project:document:create acme notes --kind=folder
```

| Argument or option | Meaning |
| - | - |
| `name` | Name of the new entry. |
| `--kind=folder\|file` | Required. |
| `--parent=ID` | Folder to create it in. The root by default. |
| `--from=PATH` | File body from a local file. `-` reads stdin. |
| `--content=TEXT` | File body as exact inline text. Do not combine it with `--from`. |
| `--media-type=TYPE` | Media type of the file body. |

## orbit project:document:update

Rename or move an entry.

```bash theme={"dark"}
orbit project:document:update <project> <entry> [--name=NAME] [--parent=ID|root] --expected-revision=N [--json]
```

| Option | Meaning |
| - | - |
| `--name=NAME` | New name. |
| `--parent=ID\|root` | Destination folder, or `root`. |
| `--expected-revision=N` | Revision you observed. Every mutation needs it. On `project_documents.revision_conflict`, read the metadata again rather than retrying. |

## orbit project:document:read

Print a file's exact text on stdout with no added newline. Diagnostics go to stderr. `--json` returns the API envelope.

```bash theme={"dark"}
orbit project:document:read <project> <entry> [--version=ID] [--json]
```

`--version=ID` reads an earlier version. The newest version by default.

## orbit project:document:upload

Write local bytes as a new version of a file.

```bash theme={"dark"}
orbit project:document:upload <project> <entry> --from=PATH|- [--media-type=TYPE] --expected-revision=N [--json]
orbit project:document:upload acme 12 --from=spec.pdf --expected-revision=3
```

`--from=-` reads stdin. The CLI checks the local size before sending, and the server checks it again.

## orbit project:document:write

Write UTF-8 text as a new version of a file.

```bash theme={"dark"}
orbit project:document:write <project> <entry> --content=TEXT|--from=PATH [--media-type=TYPE] --expected-revision=N [--json]
```

Give the text with `--content` or read it with `--from`. `--from=-` reads stdin.

## orbit project:document:download

Save a file version to a new local file, or print it to stdout.

```bash theme={"dark"}
orbit project:document:download <project> <entry> --output=PATH|- [--version=ID] [--json]
orbit project:document:download acme 12 --output=downloaded-spec.pdf
```

| Option | Meaning |
| - | - |
| `--output=PATH` | New local file. Download never overwrites an existing file. `-` writes raw bytes to stdout, which must not be a terminal. |
| `--version=ID` | Version to download. The newest version by default. |

The CLI verifies the size and digest before it publishes the file. `--json` returns the body as base64 instead, and refuses `--output`. A local failure returns `project_documents.local_io_failed` and exit 1.

## orbit project:document:versions

List a file's versions. Columns are NUMBER, ID, TYPE, SIZE, SHA256, and CREATED.

```bash theme={"dark"}
orbit project:document:versions <project> <entry> [--cursor=CURSOR] [--limit=50] [--json]
```

## orbit project:document:restore-version

Create a new version from an earlier one. It asks for no confirmation, because the history keeps every version.

```bash theme={"dark"}
orbit project:document:restore-version <project> <entry> --version=ID --expected-revision=N [--json]
```

## orbit project:document:archive

Archive an entry. Archiving is not removal: `project:document:restore` brings it back.

```bash theme={"dark"}
orbit project:document:archive <project> <entry> --expected-revision=N [--json]
```

## orbit project:document:restore

Restore an archived entry.

```bash theme={"dark"}
orbit project:document:restore <project> <entry> --expected-revision=N [--json]
```

## orbit project:document:remove

Permanently remove an entry. The confirmation names the Project, the entry, and whether the removal is recursive.

```bash theme={"dark"}
orbit project:document:remove <project> <entry> --expected-revision=N [--recursive] [--yes] [--json]
```

| Option | Meaning |
| - | - |
| `--recursive` | Also remove the descendants of a folder. |
| `--yes` | Confirm without a prompt. Required for JSON and noninteractive calls. |

## orbit project:document-storage:show

Show the private object storage that holds document bodies, and its status. Credentials are always redacted. It takes no Project selector.

```bash theme={"dark"}
orbit project:document-storage:show [--json]
```

## orbit project:document-storage:update

Configure the private object storage. Omitted settings stay unchanged. In a terminal, credentials use masked prompts. Secret values are never command-line arguments.

```bash theme={"dark"}
orbit project:document-storage:update [--endpoint=URL] [--region=REGION] [--bucket=BUCKET] [--access-key-id-file=PATH --secret-access-key-file=PATH] [--json]
```

| Option | Meaning |
| - | - |
| `--endpoint=URL` | HTTPS storage origin. |
| `--region=REGION` | Signing region. |
| `--bucket=BUCKET` | Bucket name. |
| `--access-key-id-file=PATH` | File that holds the access key ID. |
| `--secret-access-key-file=PATH` | File that holds the secret access key. Give both credential files together in noninteractive mode. |

A credential file is UTF-8. One final newline is stripped.

## Related

* [`instance`](/docs/cli/instance) creates and manages the Instances of a Project.
* [`process`](/docs/cli/process) and [`schedule`](/docs/cli/schedule) record Project definitions with `--project`.
* [`route`](/docs/cli/route) creates explicit domains for a Project.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.