Skip to Content
Project Config

Project Config

Project configuration lives in .mdp/project.json. This file is the sole source of truth for a project at runtime — no merging, no fallbacks. It is written once at project creation from a preset, with CLI flag overrides applied on top.

Complete project.json

Below is the full project.json generated by the default software preset. Every field is shown with its real default value:

{ "name": "my-project", "description": "Optional one-line project description", "instructions": "Optional free-text guidance for LLMs and collaborators", "issues": { "prefix": "ISS", "statuses": { "triage": [], "backlog": [{ "name": "Backlog", "description": "Not yet triaged" }], "unstarted": [{ "name": "To Do", "description": "Ready to be worked on" }], "started": [{ "name": "In Progress", "description": "Actively being worked on" }], "completed": [{ "name": "Done", "description": "Work completed" }], "canceled": [] }, "priorities": [ { "name": "None", "description": "No priority assigned" }, { "name": "Low", "description": "Low priority" }, { "name": "Medium", "description": "Medium priority" }, { "name": "High", "description": "High priority" }, { "name": "Urgent", "description": "Requires immediate attention" } ], "labels": [ { "name": "bug", "description": "Bug report" }, { "name": "enhancement", "description": "Improvement to existing functionality" }, { "name": "documentation", "description": "Documentation related" }, { "name": "security", "description": "Security related" }, { "name": "frontend", "description": "Frontend related" }, { "name": "backend", "description": "Backend related" } ], "types": [ { "name": "task", "description": "General work item" }, { "name": "bug", "description": "Something broken" }, { "name": "feature", "description": "New functionality" }, { "name": "chore", "description": "Maintenance, refactoring" }, { "name": "spike", "description": "Research or investigation" } ] }, "milestones": { "prefix": "M", "statuses": { "backlog": [], "planned": [{ "name": "Planning", "description": "Defining scope and goals" }], "in_progress": [ { "name": "Active", "description": "In progress" }, { "name": "On Hold", "description": "Temporarily paused" } ], "completed": [{ "name": "Completed", "description": "All goals met" }], "canceled": [] }, "priorities": [ { "name": "None", "description": "No priority assigned" }, { "name": "Low", "description": "Low priority" }, { "name": "Medium", "description": "Medium priority" }, { "name": "High", "description": "High priority" }, { "name": "Urgent", "description": "Requires immediate attention" } ], "labels": [ { "name": "bug", "description": "Bug report" }, { "name": "enhancement", "description": "Improvement to existing functionality" }, { "name": "documentation", "description": "Documentation related" }, { "name": "security", "description": "Security related" }, { "name": "frontend", "description": "Frontend related" }, { "name": "backend", "description": "Backend related" } ] } }

Field Reference

FieldDescription
nameHuman-readable project name (required). Defaults to directory name at creation.
descriptionOptional one-line project description.
instructionsOptional free-text guidance for LLMs and collaborators.
issues.prefixID prefix for issues (e.g., "ISS" produces ISS-1, ISS-2, …)
issues.statusesStatus categories mapped to arrays of statuses. See Statuses below.
issues.prioritiesOrdered list of priorities from lowest to highest urgency.
issues.labelsAvailable labels for categorizing issues. Labels not in this list produce an error.
issues.typesAvailable issue types. Types not in this list produce an error.
milestones.prefixID prefix for milestones (e.g., "M" produces M-1, M-2, …)
milestones.statusesStatus categories mapped to arrays of statuses. Same structure as issue statuses but with milestone-specific categories.
milestones.prioritiesSame structure as issue priorities.
milestones.labelsAvailable labels for milestones. Shared with issues by default.

How Configuration Works

At project creation

When you run mdp project create, a preset (built-in or custom) is selected, CLI flag overrides are applied, and the full resolved config is written to .mdp/project.json. The project file is self-contained and portable.

The merge order at creation time is: preset → CLI flags.

Custom presets can be defined in ~/.mdp/config.json. See Global Config for details.

At runtime

Commands read .mdp/project.json directly. There is no runtime merge — what you see in the file is what you get.

Use mdp project settings to display the current project configuration.

Statuses

Statuses represent the workflow stage of an issue or milestone. They are stored in frontmatter and validated against the project configuration.

Status Categories

Every status belongs to a status category — a fixed lifecycle stage that the system uses to determine behavior (e.g., completion percentage, overdue detection). Categories are system-defined; the statuses within each category are user-customizable.

Each status has two fields:

{ "name": "In Progress", "description": "Actively being worked on" }

Issue Status Categories

CategoryMeaningDefault Statuses
triageInbox, needs review(none)
backlogAccepted, not yet plannedBacklog
unstartedPlanned, ready to startTo Do
startedWork in progressIn Progress
completedDone successfullyDone
canceledWon’t do(none)

Milestone Status Categories

CategoryMeaningDefault Statuses
backlogNot yet planned(none)
plannedScoped and plannedPlanning
in_progressActively being worked onActive, On Hold
completedAll goals metCompleted
canceledAbandoned(none)

How Categories Drive Behavior

The system uses status categories — not status names — to determine behavior:

  • Completion percentage: Issues in the completed category count as done. Custom status names like “Shipped” or “Deployed” work automatically when placed in the completed category.
  • Overdue detection: Issues not in completed or canceled with a past due date are flagged as overdue.
  • Milestone progress: Milestone completion % is based on how many assigned issues are in the completed category.

Invalid Status Example

mdp issue update --id ISS-1 --status "bogus"
{ "ok": false, "error": { "code": "INVALID_STATUS", "message": "Invalid status \"bogus\"", "details": {} } }

An issue file with a valid status looks like:

status: In Progress

Priorities

Priorities indicate urgency level. Changing a priority updates the YAML frontmatter in the issue/milestone file.

Default Priorities

PriorityDescription
NoneNo priority assigned
LowLow priority
MediumMedium priority
HighHigh priority
UrgentRequires immediate attention

Priorities are shared across issues and milestones. The same set is used for both.

Invalid Priority Example

mdp issue update --id ISS-1 --priority "Critical"
{ "ok": false, "error": { "code": "INVALID_PRIORITY", "message": "Invalid priority \"Critical\"", "details": {} } }

Types

Types categorize the fundamental nature of an issue (feature, bug, task, etc.). Types are issue-only — milestones do not have types.

Default Types (Software Preset)

TypeDescription
taskGeneral work item
bugSomething broken
featureNew functionality
choreMaintenance, refactoring
spikeResearch or investigation

Types by Preset

PresetTypes
softwaretask, bug, feature, chore, spike
marketingcampaign, content, email, social, analysis
designdesign, review, research, prototype, asset
productfeature, research, experiment, feedback, spec
social-mediapost, story, campaign, engagement, analysis
generictask, milestone-task, review

Invalid Type Example

mdp issue create -t "Fix button" --type "unknown"
{ "ok": false, "error": { "code": "INVALID_TYPE", "message": "Invalid type \"unknown\"", "details": {} } }

Labels

Labels are categorization tags stored in frontmatter. Labels exist on both issues and milestones.

Default Labels (Software Preset)

LabelDescription
bugBug report
enhancementImprovement to existing functionality
documentationDocumentation related
securitySecurity related
frontendFrontend related
backendBackend related

Labels by Preset

PresetLabels
softwarebug, enhancement, documentation, security, frontend, backend
marketingseo, paid, organic, brand, copy, design
designui, ux, branding, illustration, motion
productmvp, growth, retention, onboarding, mobile, web
social-mediainstagram, twitter, linkedin, tiktok, youtube, facebook
genericurgent, documentation, question

Invalid Label Example

mdp issue create -t "Test" -l "nonexistent"
{ "ok": false, "error": { "code": "INVALID_LABEL", "message": "Invalid label \"nonexistent\"", "details": {} } }

An issue file with labels in frontmatter:

labels: - bug - security

Templates

Templates provide reusable starting points for issues and milestones. They are read once at creation time — after creation, the template has no connection to the created item.

Template Location

Templates live in .mdp/templates/ as markdown files. The filename (minus .md extension) is the template name.

.mdp/templates/ ├── issue-template.md # Default issue template ├── milestone-template.md # Default milestone template ├── bug-report.md # Custom template (name: "bug-report") └── feature-request.md # Custom template (name: "feature-request")

Template Format

Templates are standard markdown files with YAML frontmatter. Any frontmatter field can be set in the template; command-line flags override template values.

Bug report template (.mdp/templates/bug-report.md):

--- title: type: bug status: Backlog priority: Medium labels: - bug assignee: null estimate: null spent: null blockedBy: [] parent: null relatedTo: [] checklist: - text: Bug is fixed done: false - text: Tests added done: false - text: No regressions done: false log: [] --- ## Description [Describe the bug] ## Steps to Reproduce 1. Step 1 2. Step 2 ## Expected Behavior [What should happen] ## Actual Behavior [What actually happens]

Feature request template (.mdp/templates/feature-request.md):

--- title: type: feature status: Backlog priority: null labels: [] assignee: null estimate: null spent: null blockedBy: [] parent: null relatedTo: [] checklist: [] log: [] --- ## Description [Describe the feature] ## Motivation [Why is this needed?] ## Proposed Solution [How should it work?]

Usage

# Use a template mdp issue create -t "Login fails on Safari" --template bug-report # Template fields are defaults — flags override them mdp issue create -t "Login fails" --template bug-report --priority High --labels "bug,security"

The resulting ISS-1-login-fails-on-safari.md file:

--- id: ISS-1 title: Login fails on Safari type: bug status: Backlog priority: Medium labels: - bug assignee: null milestone: null estimate: null spent: null dueDate: null blockedBy: [] parent: null relatedTo: [] checklist: - text: Bug is fixed done: false - text: Tests added done: false - text: No regressions done: false log: [] createdAt: 2025-03-01T10:00:00.000Z updatedAt: 2025-03-01T10:00:00.000Z --- ## Description [Describe the bug] ## Steps to Reproduce 1. Step 1 2. Step 2 ## Expected Behavior [What should happen] ## Actual Behavior [What actually happens]

With flag overrides (--priority High --labels "bug,security"), the frontmatter changes to:

priority: High labels: - bug - security

Template Resolution

  1. Look for {name}.md in .mdp/templates/
  2. If not found, produce an error with exit code 1
  3. Parse frontmatter and body from template
  4. Merge: command flags take precedence over template values
  5. Template body is used as the initial markdown content (unless --content is specified)

Validation

All validation is case-insensitive. "In Progress", "in progress", and "IN PROGRESS" all match the same status.

ConceptOn Invalid Value
StatusINVALID_STATUS error, command fails
PriorityINVALID_PRIORITY error, command fails
TypeINVALID_TYPE error, command fails
LabelsINVALID_LABEL error, command fails
Last updated on