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
| Field | Description |
|---|---|
name | Human-readable project name (required). Defaults to directory name at creation. |
description | Optional one-line project description. |
instructions | Optional free-text guidance for LLMs and collaborators. |
issues.prefix | ID prefix for issues (e.g., "ISS" produces ISS-1, ISS-2, …) |
issues.statuses | Status categories mapped to arrays of statuses. See Statuses below. |
issues.priorities | Ordered list of priorities from lowest to highest urgency. |
issues.labels | Available labels for categorizing issues. Labels not in this list produce an error. |
issues.types | Available issue types. Types not in this list produce an error. |
milestones.prefix | ID prefix for milestones (e.g., "M" produces M-1, M-2, …) |
milestones.statuses | Status categories mapped to arrays of statuses. Same structure as issue statuses but with milestone-specific categories. |
milestones.priorities | Same structure as issue priorities. |
milestones.labels | Available 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
| Category | Meaning | Default Statuses |
|---|---|---|
triage | Inbox, needs review | (none) |
backlog | Accepted, not yet planned | Backlog |
unstarted | Planned, ready to start | To Do |
started | Work in progress | In Progress |
completed | Done successfully | Done |
canceled | Won’t do | (none) |
Milestone Status Categories
| Category | Meaning | Default Statuses |
|---|---|---|
backlog | Not yet planned | (none) |
planned | Scoped and planned | Planning |
in_progress | Actively being worked on | Active, On Hold |
completed | All goals met | Completed |
canceled | Abandoned | (none) |
How Categories Drive Behavior
The system uses status categories — not status names — to determine behavior:
- Completion percentage: Issues in the
completedcategory count as done. Custom status names like “Shipped” or “Deployed” work automatically when placed in thecompletedcategory. - Overdue detection: Issues not in
completedorcanceledwith a past due date are flagged as overdue. - Milestone progress: Milestone completion % is based on how many assigned issues are in the
completedcategory.
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 ProgressPriorities
Priorities indicate urgency level. Changing a priority updates the YAML frontmatter in the issue/milestone file.
Default Priorities
| Priority | Description |
|---|---|
| None | No priority assigned |
| Low | Low priority |
| Medium | Medium priority |
| High | High priority |
| Urgent | Requires 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)
| Type | Description |
|---|---|
task | General work item |
bug | Something broken |
feature | New functionality |
chore | Maintenance, refactoring |
spike | Research or investigation |
Types by Preset
| Preset | Types |
|---|---|
software | task, bug, feature, chore, spike |
marketing | campaign, content, email, social, analysis |
design | design, review, research, prototype, asset |
product | feature, research, experiment, feedback, spec |
social-media | post, story, campaign, engagement, analysis |
generic | task, 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)
| Label | Description |
|---|---|
bug | Bug report |
enhancement | Improvement to existing functionality |
documentation | Documentation related |
security | Security related |
frontend | Frontend related |
backend | Backend related |
Labels by Preset
| Preset | Labels |
|---|---|
software | bug, enhancement, documentation, security, frontend, backend |
marketing | seo, paid, organic, brand, copy, design |
design | ui, ux, branding, illustration, motion |
product | mvp, growth, retention, onboarding, mobile, web |
social-media | instagram, twitter, linkedin, tiktok, youtube, facebook |
generic | urgent, 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
- securityTemplates
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
- securityTemplate Resolution
- Look for
{name}.mdin.mdp/templates/ - If not found, produce an error with exit code 1
- Parse frontmatter and body from template
- Merge: command flags take precedence over template values
- Template body is used as the initial markdown content (unless
--contentis specified)
Validation
All validation is case-insensitive. "In Progress", "in progress", and "IN PROGRESS" all match the same status.
| Concept | On Invalid Value |
|---|---|
| Status | INVALID_STATUS error, command fails |
| Priority | INVALID_PRIORITY error, command fails |
| Type | INVALID_TYPE error, command fails |
| Labels | INVALID_LABEL error, command fails |