(written with help of AI)
First off, huge appreciation to the Plane team for building “Project-as-Code” (Plane Compose / CLI). Having issue tracking, cycles, pages, and workflows version-controlled alongside code is an incredible direction for developer-centric project management.
I wanted to open a discussion and feature proposal regarding the directory structure created by the Plane CLI when cloning or initializing a project inside an existing repository.
Background & Context
About 7 months ago, I had a brief chat with one of the Plane developers and shared initial feedback regarding this directory convention. They kindly mentioned they would pass the thought along to the core team.
I’m bringing it to the community forum now simply to ensure the feedback isn’t lost, to see if other teams feel the same friction, and to offer concrete suggestions on how we could align with standard developer tooling conventions.
The Problem
When running `plane clone` or initializing a project within the root of an existing repository, the CLI currently creates a top-level directory named after the project key/identifier (for example, in our case, an `event/` folder for project key `EVENT`).
Inside this project-named folder, we get:
```text
event/
├── .gitignore
├── .plane/ (internal CLI state: state.json, state.lock)
├── plane.yaml
├── workspace.yaml
├── schema/
└── work/
While this works well if Plane is treated as an isolated standalone repository, it causes significant friction when embedding Project-as-Code into an existing application or monorepo:
- Naming Collisions with Domain/Source Code:
Project keys often match the domain or product name (e.g.,event,billing,core,api). Having a folder namedevent/at the repository root directly clashes with source code folders, microservice boundaries, or domain libraries. - Root Clutter:
It adds an un-namespaced, visible top-level folder to the repository root that looks like application code rather than tooling configuration. - Divergence from Ecosystem Conventions:
Modern developer tooling unanimously follows the dot-folder convention (.<tool>/) at the repository root to encapsulate project-level tool metadata and configurations:.github/(GitHub Actions, templates).gitlab/(GitLab CI/CD).vscode/or.idea/(IDE settings).claude/,.cursor/,.omo/(AI agent configs & rules).devcontainer/,.husky/,.terraform/
Proposed Solution
Encapsulate all Plane Project-as-Code files inside a dedicated dot-directory at the repository root: .plane/.
1. Ideal Structure (Single Project):
When cloning or initializing in the root of an existing project:
my-repo/
├── .plane/
│ ├── plane.yaml
│ ├── workspace.yaml
│ ├── schema/
│ ├── work/
│ └── cache/ (or internal state)
├── src/
├── tests/
└── README.md
2. Monorepo / Multi-Project Support:
If a repository links to multiple Plane projects:
my-repo/
└── .plane/
├── workspace.yaml
└── projects/
├── event/
│ ├── plane.yaml
│ └── ...
└── billing/
├── plane.yaml
└── ...
3. CLI Ergonomics:
At minimum, even if the default behavior is preserved for backwards compatibility, providing an explicit target path or flag would solve this immediately:
# Clone directly into .plane in current directory
plane clone <PROJECT_KEY> --path .plane
# or
plane init --dir .plane
Why this matters
Embracing the .plane/ convention makes Plane feel like a native citizen in modern codebases. Developers and teams can commit their Project-as-Code setup without interfering with existing build systems, file trees, or package layouts.