Create and sync projects
Every command here takes an optional [project] folder name plus --path for its parent directory. Without them, the current directory is the project.
init
Confirm. Scaffolds a local project folder from a template. Nothing is created in Plane until you push.
| Flag / argument | What it controls |
|---|---|
[project] | Project identifier, for example MYPROJ. Upper-cased, other characters stripped, at most 10 characters. The folder is the lower-cased key. Leave it and -w out for interactive mode. |
-w, --workspace | Workspace slug. Required when you give a project. |
-c, --connection | Connection ID. Only needed when a slug is linked to more than one connection. |
--path | Parent directory for the new folder. Default: the current directory. |
-t, --template | Template source: left out for the built-in template, a local path, or a Git URL. |
plane init MYPROJ -w myteam
plane init MYPROJ -w myteam --template ./templates/custom
plane init MYPROJ -w myteam --template https://github.com/org/repo/templates/standard@v1.2.0
plane init # interactiveinit writes plane.yaml, fetches workspace features into workspace.yaml, copies the template into schema/ and work/, adds you to schema/members.yaml as admin, and creates .plane/state.json and a .gitignore. If the folder already exists, you're asked before it's overwritten. The next plane schema push or plane push creates the project in Plane.
The built-in template turns on cycles, modules, pages and views and leaves the other features off. See features.yaml.
Template sources
A Git URL must include the template's path inside the repo, for example https://github.com/org/repo/templates/name. A bare repo URL is an error. GitHub /tree/<branch>/path URLs work too.
- Append
@<ref>(a tag, release or branch) to pin a version. This works withinit -tandupgrade -t. https,httpandgit@URLs are accepted. For SSH, usegit@github.com:org/repo/templates/name, without.git.- The repo is cloned with a 60-second timeout.
- A template needs
schema/andwork/folders. Only their top-level*.yamlfiles are copied.
clone
Safe. Copies an existing Plane project into a new local folder with plane.yaml, schema/, work/ and sync state, like git clone.
| Flag / argument | What it controls |
|---|---|
PROJECT | Required. A project UUID, a project key (MYPROJ), or workspace/KEY. |
-w, --workspace | Workspace slug. Needed with a UUID or a bare key. |
-c, --connection | Connection ID, when you need to pick one. |
-d, --directory | Folder to clone into. Default: the project identifier. |
--path | Parent directory. Default: the current directory. |
--schema-only | Skip work items, cycles, modules, milestones and pages. |
--skip <section> | Skip one section. Repeatable. |
--with-properties / --no-properties | Fetch custom property values on work items. Default: on. |
plane clone myteam/MYPROJ
plane clone MYPROJ --workspace myteam
plane clone 8cee0da2-1b5b-4699-b11a-e3c8b26dd55d --workspace myteam
plane clone myteam/MYPROJ --schema-onlyProperty values are cloned by default. Pass --no-properties for a faster clone of a large project.
Use clone to start from a project you don't have locally. For a project you already have, use pull.
push
Confirm. Sends your local schema and work to Plane. Push creates and updates; it never deletes work items.
Push runs in two steps:
- Schema. The same as
plane schema push, without--prune. - Work. Cycles, modules, milestones and pages, then work items.
| Flag | What it controls |
|---|---|
-n, --dry-run | Show what would be pushed. Change nothing. |
-f, --force | Skip every confirmation, including the conflict prompt. |
--work-only | Skip the schema step. |
--schema-only | Skip work items, cycles, modules, milestones and pages. |
--skip <section> | Skip workitems, cycles, modules, milestones or pages. Repeatable. |
--no-conflict-check | Don't check Plane for changes made since your last sync. |
--exit-code | Exit 0 when there was nothing to push, 1 on error, 2 when work item changes were applied (or found, with --dry-run). Schema, cycle, module and page changes don't produce 2. |
--json | Machine-readable result on stdout: created, updated, deleted, failed, elapsed time and failed items. Implies --force. |
--resume | Retry only the items that failed in the last push. Can't be combined with --schema-only or --skip workitems. |
--all | Push every project under the current directory. See Multiple projects. |
-c, --connection | Doesn't change which credentials are used. See Which connection a command uses. |
--json, --resume and --all don't show in --help in v0.5.2, but they work. plane sync is another name for plane push.
plane push
plane push --dry-run
plane push --work-only --skip pages
plane push --exit-code
plane push --resumeA push prints a plan and asks before applying it:
Step 1: Pushing schema...
Step 2: Pushing work...
(plan table, then: Create N, Update M work items in Plane?)
Auto-assigned IDs to N work item(s) in YAMLRun it again with nothing changed and you get All work items are already synced!.
What push skips
- A section whose file is missing from
work/. - Cycles, modules or pages when that feature is
falseinfeatures.yaml. - Pages that already have an
id. Pages are create-only. - Pages, when cycles, modules and milestones are all skipped.
Conflicts
Before updating a work item, push checks whether it changed in Plane since your last sync. If it did, you're asked before it's overwritten. To take the remote changes instead, run plane diff, then plane pull --merge. --force and --no-conflict-check skip the question.
Validate before you push
Work items are validated at the start of step 2, after step 1 has already pushed the schema. An unknown type, state or label, a bad date or priority, a duplicate id, or watchers / children stops the work push with exit code 1. Run plane validate first to catch them before anything changes.
Failed items
Items that fail are recorded in .plane/resume.json. Fix the cause, then run plane push --resume to retry only those items.
pull
Confirm. Pulls the project from Plane into your files: schema into schema/, work items into work/workitems.yaml, and cycles, modules, milestones and pages.
| Flag | What it controls |
|---|---|
--merge | Merge with the items already in the file instead of replacing them. |
-f, --force | Skip the prompt shown when the project has more than 10,000 work items. |
--work-only | Pull work items only, not the schema. |
--schema-only | Skip work items, cycles, modules, milestones and pages. Much faster on large projects. |
--skip <section> | Skip workitems, cycles, modules, milestones or pages. Repeatable. |
--with-properties / --no-properties | Fetch custom property values. Default: on. |
--all, --json | Pull every project under the current directory, or print a machine-readable result. Hidden from --help. --all asks first unless --force. |
-c, --connection | Doesn't change which credentials are used. See Which connection a command uses. |
plane pull
plane pull --schema-only
plane pull --skip cycles --skip modules --skip milestones
plane pull --merge --no-propertiesPull refreshes every section that exists in Plane unless you skip it, and updates .plane/state.json with the new content hashes, so the next plane push doesn't send back what you just pulled. Dependencies and relations are written in the dependencies: / relations: form.
diff
Safe. Compares your files with Plane. It first prints schema, feature, milestone, cycle and module comparisons, then sorts work items into local changes that a push would send and items changed or missing in Plane.
| Flag | What it controls |
|---|---|
--json | Machine-readable output. Covers work items only. |
--exit-code | Exit 0 when in sync, 1 on error, 2 when there are differences. With --json, work items only. |
-v, --verbose | Show content hashes, for debugging. |
--schema-only | Skip all work data. |
--skip <section> | Skip workitems, cycles, modules, milestones or pages. Repeatable. |
plane diff
plane diff --skip workitems
plane diff --exit-code --jsondiff walks the work items your sync state already tracks. It doesn't list work items that exist only in Plane, so it isn't a preview of everything a pull would bring down. A tracked item that can't be fetched is reported as deleted remotely.
status
Safe. An offline summary: schema objects local versus synced, pending work item changes, unchanged items and the last sync time. It reads only local files and state.json, with no API call.
| Flag / argument | What it controls |
|---|---|
[path] | Project directory. Default: the current directory. |
--all | Status of every project under the current directory. |
-w, --workspace | With --all, only projects in this workspace. |
--filter <glob> | With --all, only project paths matching the glob. |
--json | Machine-readable output for a single project. |
plane status
plane status ./projects/api
plane status --all -w myteamvalidate
Safe. Checks work items before you push: that types, states and labels exist, priority values, date formats and order, duplicate IDs, parent loops, assignee format, unknown or mistyped custom properties, and the unsupported watchers and children fields. A missing id is a warning.
| Flag / argument | What it controls |
|---|---|
[path] | Project directory. Default: the current directory. |
--offline | Don't connect to Plane. Skips the type, state, label and custom property checks, and needs no credentials. |
--json | Machine-readable output with valid, items, errors, warnings and issues. |
plane validate
plane validate --offline
plane validate --jsonThe exit code is 1 when there's any error. Warnings alone exit 0. plane push runs the same checks.
If Plane returns no work item types, validate can't check type names, so a misspelled type is only caught by Plane at push time.

