pmpt-cli 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 pmptwiki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,10 +1,49 @@
1
+ <div align="center">
2
+
1
3
  # pmpt
2
4
 
3
- **Record and share your AI-driven product development journey.**
5
+ **Answer 5 questions. Start building with AI.**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/pmpt-cli.svg?style=flat-square&color=cb3837)](https://www.npmjs.com/package/pmpt-cli)
8
+ [![license](https://img.shields.io/github/license/pmptwiki/pmpt-cli?style=flat-square&v=2)](https://github.com/pmptwiki/pmpt-cli/blob/main/LICENSE)
9
+ [![node](https://img.shields.io/badge/node-%3E%3D18-brightgreen?style=flat-square)](https://github.com/pmptwiki/pmpt-cli)
10
+
11
+ The CLI that turns your idea into an AI-ready prompt in 30 seconds.
4
12
 
5
- [![npm version](https://img.shields.io/npm/v/pmpt-cli.svg)](https://www.npmjs.com/package/pmpt-cli)
13
+ No coding required. No complex setup. Just answer 5 questions.
6
14
 
7
- **Website**: [pmptwiki.com](https://pmptwiki.com)
15
+ [Quick Start](#quick-start) · [Commands](#commands) · [How It Works](#how-it-works) · [Explore Projects](#explore-projects)
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ ## Demo
22
+
23
+ ```
24
+ $ pmpt plan
25
+
26
+ ┌ pmpt — Let's plan your product!
27
+
28
+ ◆ What should we call your project?
29
+ │ my-budget-app
30
+
31
+ ◆ What would you like to build with AI?
32
+ │ A personal budget tracking app for freelancers
33
+
34
+ ◆ Any additional context AI should know? (optional)
35
+ │ Simple UI, mobile-friendly, works offline
36
+
37
+ ◆ Key features to include?
38
+ │ Expense tracking; Income categories; Monthly reports; Export to CSV
39
+
40
+ ◆ Preferred tech stack? (optional)
41
+ │ React, Node.js
42
+
43
+ └ Done! AI prompt copied to clipboard.
44
+
45
+ → Open Claude / ChatGPT / Cursor → Ctrl+V → Start building!
46
+ ```
8
47
 
9
48
  ---
10
49
 
@@ -14,35 +53,59 @@
14
53
  npm install -g pmpt-cli
15
54
  ```
16
55
 
56
+ > Requires Node.js 18+
57
+
17
58
  ---
18
59
 
19
60
  ## Quick Start
20
61
 
21
62
  ```bash
22
- # 1. Initialize project
63
+ # 1. Install
64
+ npm i -g pmpt-cli
65
+
66
+ # 2. Initialize your project
23
67
  pmpt init
24
68
 
25
- # 2. Answer 5 questions → AI prompt generated
69
+ # 3. Answer 5 questions → AI prompt auto-generated & copied
26
70
  pmpt plan
27
71
 
28
- # 3. Copy the prompt to Claude/ChatGPT/Cursor and build!
72
+ # 4. Paste into Claude / ChatGPT / Cursor Build your product!
29
73
 
30
- # 4. Save your progress
74
+ # 5. Save your progress anytime
31
75
  pmpt save
32
76
 
33
- # 5. Publish to pmptwiki
34
- pmpt login
35
- pmpt publish
77
+ # 6. Share with the community
78
+ pmpt login && pmpt publish
79
+
80
+ # Bonus: Explore what others are building
81
+ pmpt browse
36
82
  ```
37
83
 
38
84
  ---
39
85
 
40
86
  ## Why pmpt?
41
87
 
42
- - **5 questions** Quick product planning with AI-ready prompts
43
- - **Version history** — Track every step of your AI-assisted development
44
- - **Share & reproduce** Publish projects for others to learn from and clone
45
- - **Project hub** Browse and clone projects at [pmptwiki.com](https://pmptwiki.com/explore)
88
+ | | Without pmpt | With pmpt |
89
+ |---|---|---|
90
+ | **Planning** | Stare at blank screen, write vague prompts | Answer 5 guided questions, get structured AI prompt |
91
+ | **Tracking** | Lose track of what you built and how | Every version auto-saved with full history |
92
+ | **Sharing** | Share finished code only | Share the entire journey — others can reproduce it |
93
+
94
+ ---
95
+
96
+ ## The 5 Questions
97
+
98
+ `pmpt plan` asks just 5 questions to generate a complete AI prompt:
99
+
100
+ | # | Question | Example |
101
+ |---|----------|---------|
102
+ | 1 | **Project name** | `my-budget-app` |
103
+ | 2 | **What to build** | `A budget tracking app for freelancers` |
104
+ | 3 | **Additional context** *(optional)* | `Simple UI, mobile-friendly` |
105
+ | 4 | **Key features** | `Expense tracking; Monthly reports; CSV export` |
106
+ | 5 | **Tech stack** *(optional)* | `React, Node.js` — or let AI decide |
107
+
108
+ The generated prompt is **automatically copied to your clipboard**. Just paste it into your favorite AI tool.
46
109
 
47
110
  ---
48
111
 
@@ -52,72 +115,95 @@ pmpt publish
52
115
 
53
116
  | Command | Description |
54
117
  |---------|-------------|
55
- | `pmpt init` | Initialize project |
56
- | `pmpt plan` | 5 questions → AI prompt (copied to clipboard) |
57
- | `pmpt save` | Save current state as snapshot |
58
- | `pmpt watch` | Auto-detect file changes |
118
+ | `pmpt init` | Initialize project and start tracking |
119
+ | `pmpt plan` | 5 questions → AI prompt (auto-copied to clipboard) |
120
+ | `pmpt save` | Save current state as a snapshot |
121
+ | `pmpt watch` | Auto-detect file changes and save versions |
122
+ | `pmpt status` | Check project status and tracked files |
59
123
  | `pmpt history` | View version history |
60
- | `pmpt history --compact` | Hide minor changes |
61
- | `pmpt squash v2 v5` | Merge versions v2-v5 into v2 |
62
- | `pmpt export` | Export as `.pmpt` file (single JSON) |
124
+ | `pmpt squash v2 v5` | Merge versions v2–v5 into one |
125
+ | `pmpt export` | Export project as `.pmpt` file |
63
126
  | `pmpt import <file>` | Import from `.pmpt` file |
64
- | `pmpt status` | Check project status |
65
127
 
66
128
  ### Platform
67
129
 
68
130
  | Command | Description |
69
131
  |---------|-------------|
70
- | `pmpt login` | Authenticate with GitHub (one-time setup) |
71
- | `pmpt publish` | Publish project to pmptwiki |
72
- | `pmpt clone <slug>` | Clone a published project |
73
- | `pmpt browse` | Browse and discover projects |
132
+ | `pmpt login` | Authenticate via GitHub (one-time) |
133
+ | `pmpt publish` | Publish your project for others to discover |
134
+ | `pmpt edit` | Edit published project metadata (description, tags, category) |
135
+ | `pmpt unpublish` | Remove a published project from pmptwiki |
136
+ | `pmpt clone <slug>` | Clone and reproduce someone's project |
137
+ | `pmpt browse` | Browse and search published projects |
138
+
139
+ > See the full documentation at [pmptwiki.com/docs](https://pmptwiki.com/docs)
74
140
 
75
141
  ---
76
142
 
77
- ## Workflow
143
+ ## How It Works
78
144
 
79
145
  ```
80
- [You]
81
-
82
- ├─ pmpt plan ─────→ 5 questions → AI prompt (clipboard)
83
-
84
- ├─ Build with AI ──→ Create files, iterate
85
-
86
- ├─ pmpt save ─────→ Save to .pmpt/.history
87
-
88
- ├─ pmpt publish ──→ Share on pmptwiki.com
89
-
90
- └─ pmpt clone ────→ Reproduce someone's project
146
+ You pmpt AI Tool
147
+ │ │
148
+ ├── pmpt init ──────────────→│ │
149
+ │ │ Creates .pmpt/ project
150
+ │ │ │
151
+ ├── pmpt plan ──────────────→│
152
+ │ (answer 5 questions) │ Generates AI prompt │
153
+ │ │ → Copied to clipboard
154
+ │ │ │
155
+ ├── Ctrl+V ─────────────────────────────────────────────────→│
156
+ │ │ Builds your product
157
+ │ │ │
158
+ ├── pmpt save ──────────────→│ │
159
+ │ │ Snapshots version history │
160
+ │ │ │
161
+ ├── pmpt publish ───────────→│ │
162
+ │ │ Shares with community │
163
+ │ │ │
164
+ └── Others: pmpt clone ─────→│ Reproduces your journey │
91
165
  ```
92
166
 
93
167
  ---
94
168
 
95
- ## Folder Structure
169
+ ## Project Structure
96
170
 
97
171
  ```
98
- .pmpt/
99
- ├── config.json # Config file
100
- ├── docs/ # Working folder (MD files)
101
- ├── plan.md # Product plan
102
- └── pmpt.md # AI prompt
103
- └── .history/ # Version history
104
- ├── v1-2024-02-20/
105
- ├── v2-2024-02-21/
106
- └── ...
172
+ your-project/
173
+ └── .pmpt/
174
+ ├── config.json # Project configuration
175
+ ├── docs/ # Generated documents
176
+ ├── plan.md # Product plan (features checklist)
177
+ └── pmpt.md # AI-ready prompt
178
+ └── .history/ # Auto-saved version history
179
+ ├── v1-2024-02-20/
180
+ ├── v2-2024-02-21/
181
+ └── ...
107
182
  ```
108
183
 
109
184
  ---
110
185
 
111
186
  ## .pmpt File Format
112
187
 
113
- Single JSON file containing your entire development journey:
188
+ A single portable file containing your entire development journey:
114
189
 
115
190
  ```json
116
191
  {
117
192
  "schemaVersion": "1.0",
118
- "meta": { "projectName": "", "description": "", "createdAt": "" },
119
- "plan": { "productIdea": "", "coreFeatures": "", "techStack": "" },
120
- "docs": { "plan.md": "...", "pmpt.md": "..." },
193
+ "meta": {
194
+ "projectName": "my-budget-app",
195
+ "description": "Budget tracking app for freelancers",
196
+ "createdAt": "2024-02-20T10:00:00Z"
197
+ },
198
+ "plan": {
199
+ "productIdea": "A budget tracking app...",
200
+ "coreFeatures": "Expense tracking; Monthly reports",
201
+ "techStack": "React, Node.js"
202
+ },
203
+ "docs": {
204
+ "plan.md": "...",
205
+ "pmpt.md": "..."
206
+ },
121
207
  "history": [
122
208
  { "version": 1, "timestamp": "...", "files": {} },
123
209
  { "version": 2, "timestamp": "...", "files": {} }
@@ -125,26 +211,63 @@ Single JSON file containing your entire development journey:
125
211
  }
126
212
  ```
127
213
 
214
+ Share it. Clone it. Reproduce it.
215
+
128
216
  ---
129
217
 
130
218
  ## Use Cases
131
219
 
132
- - **Side project builders**Track your AI-assisted development
133
- - **Startup founders** — Document MVP creation process
134
- - **Content creators** — Share your coding journey
135
- - **Learners** — Browse and clone projects to study how others build with AI
220
+ - **Have an idea but no coding skills?** Answer 5 questions, paste the prompt into AI, and start building
221
+ - **Startup founders** — Document your MVP creation process from day one
222
+ - **Content creators** — Share your AI-assisted building journey as reproducible content
223
+ - **Learners** — Clone published projects to study how others build with AI
224
+
225
+ ---
226
+
227
+ ## Explore Projects
228
+
229
+ Don't know what to build? Browse what others have created with AI.
230
+
231
+ ```bash
232
+ # Discover projects from the community
233
+ pmpt browse
234
+
235
+ # Found something interesting? Clone it and make it yours
236
+ pmpt clone budget-tracker-app
237
+ ```
238
+
239
+ **[Explore Projects on pmptwiki.com →](https://pmptwiki.com/explore)**
240
+
241
+ See how others planned their products, what prompts they used, and how their projects evolved step by step. Clone any project and use it as a starting point for your own.
242
+
243
+ ---
244
+
245
+ ## Contributing
246
+
247
+ Contributions are welcome! Feel free to open an [issue](https://github.com/pmptwiki/pmpt-cli/issues) or submit a [pull request](https://github.com/pmptwiki/pmpt-cli/pulls).
136
248
 
137
249
  ---
138
250
 
139
251
  ## Links
140
252
 
141
- - [Website](https://pmptwiki.com)
142
- - [Explore Projects](https://pmptwiki.com/explore)
143
253
  - [GitHub](https://github.com/pmptwiki/pmpt-cli)
144
254
  - [npm](https://www.npmjs.com/package/pmpt-cli)
255
+ - [Documentation](https://pmptwiki.com/docs)
145
256
 
146
257
  ---
147
258
 
148
259
  ## License
149
260
 
150
- MIT
261
+ [MIT](https://github.com/pmptwiki/pmpt-cli/blob/main/LICENSE)
262
+
263
+ ---
264
+
265
+ <div align="center">
266
+
267
+ **If pmpt helps you build something, give it a ⭐**
268
+
269
+ [Explore what others are building →](https://pmptwiki.com/explore)
270
+
271
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-support-yellow?style=flat-square&logo=buy-me-a-coffee)](https://buymeacoffee.com/pmpt_cafe)
272
+
273
+ </div>
@@ -0,0 +1,99 @@
1
+ import * as p from '@clack/prompts';
2
+ import { loadAuth } from '../lib/auth.js';
3
+ import { fetchProjects, editProject } from '../lib/api.js';
4
+ export async function cmdEdit() {
5
+ const auth = loadAuth();
6
+ if (!auth?.token || !auth?.username) {
7
+ p.log.error('Login required. Run `pmpt login` first.');
8
+ process.exit(1);
9
+ }
10
+ p.intro('pmpt edit');
11
+ const s = p.spinner();
12
+ s.start('Loading your projects...');
13
+ let myProjects;
14
+ try {
15
+ const index = await fetchProjects();
16
+ myProjects = index.projects.filter((proj) => proj.author === auth.username);
17
+ }
18
+ catch (err) {
19
+ s.stop('Failed to load projects');
20
+ p.log.error(err instanceof Error ? err.message : 'Failed to fetch projects.');
21
+ process.exit(1);
22
+ }
23
+ s.stop('Projects loaded');
24
+ if (myProjects.length === 0) {
25
+ p.log.warn('No published projects found. Run `pmpt publish` first.');
26
+ p.outro('');
27
+ return;
28
+ }
29
+ const slug = await p.select({
30
+ message: 'Select a project to edit:',
31
+ options: myProjects.map((proj) => ({
32
+ value: proj.slug,
33
+ label: proj.slug,
34
+ hint: proj.description?.slice(0, 50) || '',
35
+ })),
36
+ });
37
+ if (p.isCancel(slug)) {
38
+ p.cancel('Cancelled');
39
+ process.exit(0);
40
+ }
41
+ const project = myProjects.find((proj) => proj.slug === slug);
42
+ const description = await p.text({
43
+ message: 'Description:',
44
+ defaultValue: project.description,
45
+ placeholder: project.description,
46
+ });
47
+ if (p.isCancel(description)) {
48
+ p.cancel('Cancelled');
49
+ process.exit(0);
50
+ }
51
+ const tagsInput = await p.text({
52
+ message: 'Tags (comma-separated):',
53
+ defaultValue: project.tags.join(', '),
54
+ placeholder: project.tags.join(', '),
55
+ });
56
+ if (p.isCancel(tagsInput)) {
57
+ p.cancel('Cancelled');
58
+ process.exit(0);
59
+ }
60
+ const tags = tagsInput
61
+ .split(',')
62
+ .map((t) => t.trim().toLowerCase())
63
+ .filter(Boolean);
64
+ const category = await p.select({
65
+ message: 'Category:',
66
+ initialValue: project.category || 'other',
67
+ options: [
68
+ { value: 'web-app', label: 'Web App' },
69
+ { value: 'mobile-app', label: 'Mobile App' },
70
+ { value: 'cli-tool', label: 'CLI Tool' },
71
+ { value: 'api-backend', label: 'API/Backend' },
72
+ { value: 'ai-ml', label: 'AI/ML' },
73
+ { value: 'game', label: 'Game' },
74
+ { value: 'library', label: 'Library' },
75
+ { value: 'other', label: 'Other' },
76
+ ],
77
+ });
78
+ if (p.isCancel(category)) {
79
+ p.cancel('Cancelled');
80
+ process.exit(0);
81
+ }
82
+ const s2 = p.spinner();
83
+ s2.start('Updating...');
84
+ try {
85
+ await editProject(auth.token, slug, {
86
+ description: description,
87
+ tags,
88
+ category: category,
89
+ });
90
+ s2.stop('Updated!');
91
+ p.log.success(`Project "${slug}" has been updated.`);
92
+ }
93
+ catch (err) {
94
+ s2.stop('Update failed');
95
+ p.log.error(err instanceof Error ? err.message : 'Failed to update project.');
96
+ process.exit(1);
97
+ }
98
+ p.outro('');
99
+ }
@@ -6,7 +6,7 @@ import { getAllSnapshots, resolveFullSnapshot } from '../lib/history.js';
6
6
  import { getPlanProgress } from '../lib/plan.js';
7
7
  import { createPmptFile } from '../lib/pmptFile.js';
8
8
  import { loadAuth } from '../lib/auth.js';
9
- import { publishProject } from '../lib/api.js';
9
+ import { publishProject, fetchProjects } from '../lib/api.js';
10
10
  import glob from 'fast-glob';
11
11
  import { join } from 'path';
12
12
  function readDocsFolder(docsDir) {
@@ -43,10 +43,23 @@ export async function cmdPublish(path) {
43
43
  return;
44
44
  }
45
45
  const projectName = planProgress?.answers?.projectName || basename(projectPath);
46
+ // Try to load existing published data for prefill
47
+ let existing;
48
+ const savedSlug = config?.lastPublishedSlug;
49
+ try {
50
+ const index = await fetchProjects();
51
+ if (savedSlug) {
52
+ existing = index.projects.find((p) => p.slug === savedSlug && p.author === auth.username);
53
+ }
54
+ }
55
+ catch { /* ignore — first publish or offline */ }
56
+ const defaultSlug = savedSlug
57
+ || projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
46
58
  // Collect publish info
47
59
  const slug = await p.text({
48
60
  message: 'Project slug (used in URL):',
49
- placeholder: projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-'),
61
+ placeholder: defaultSlug,
62
+ defaultValue: savedSlug || '',
50
63
  validate: (v) => {
51
64
  if (!/^[a-z0-9][a-z0-9-]{1,48}[a-z0-9]$/.test(v)) {
52
65
  return '3-50 chars, lowercase letters, numbers, and hyphens only.';
@@ -59,8 +72,8 @@ export async function cmdPublish(path) {
59
72
  }
60
73
  const description = await p.text({
61
74
  message: 'Project description (brief):',
62
- placeholder: planProgress?.answers?.productIdea?.slice(0, 100) || '',
63
- defaultValue: planProgress?.answers?.productIdea?.slice(0, 200) || '',
75
+ placeholder: existing?.description || planProgress?.answers?.productIdea?.slice(0, 100) || '',
76
+ defaultValue: existing?.description || planProgress?.answers?.productIdea?.slice(0, 200) || '',
64
77
  });
65
78
  if (p.isCancel(description)) {
66
79
  p.cancel('Cancelled');
@@ -69,7 +82,7 @@ export async function cmdPublish(path) {
69
82
  const tagsInput = await p.text({
70
83
  message: 'Tags (comma-separated):',
71
84
  placeholder: 'react, saas, mvp',
72
- defaultValue: '',
85
+ defaultValue: existing?.tags?.join(', ') || '',
73
86
  });
74
87
  if (p.isCancel(tagsInput)) {
75
88
  p.cancel('Cancelled');
@@ -81,6 +94,7 @@ export async function cmdPublish(path) {
81
94
  .filter(Boolean);
82
95
  const category = await p.select({
83
96
  message: 'Project category:',
97
+ initialValue: existing?.category || 'other',
84
98
  options: [
85
99
  { value: 'web-app', label: 'Web App' },
86
100
  { value: 'mobile-app', label: 'Mobile App' },
@@ -155,6 +169,7 @@ export async function cmdPublish(path) {
155
169
  // Update config
156
170
  if (config) {
157
171
  config.lastPublished = new Date().toISOString();
172
+ config.lastPublishedSlug = slug;
158
173
  saveConfig(projectPath, config);
159
174
  }
160
175
  p.note([
@@ -0,0 +1,62 @@
1
+ import * as p from '@clack/prompts';
2
+ import { loadAuth } from '../lib/auth.js';
3
+ import { fetchProjects, unpublishProject } from '../lib/api.js';
4
+ export async function cmdUnpublish() {
5
+ const auth = loadAuth();
6
+ if (!auth?.token || !auth?.username) {
7
+ p.log.error('Login required. Run `pmpt login` first.');
8
+ process.exit(1);
9
+ }
10
+ p.intro('pmpt unpublish');
11
+ const s = p.spinner();
12
+ s.start('Loading your projects...');
13
+ let myProjects;
14
+ try {
15
+ const index = await fetchProjects();
16
+ myProjects = index.projects.filter((proj) => proj.author === auth.username);
17
+ }
18
+ catch (err) {
19
+ s.stop('Failed to load projects');
20
+ p.log.error(err instanceof Error ? err.message : 'Failed to fetch projects.');
21
+ process.exit(1);
22
+ }
23
+ s.stop('Projects loaded');
24
+ if (myProjects.length === 0) {
25
+ p.log.warn('No published projects found.');
26
+ p.outro('');
27
+ return;
28
+ }
29
+ const slug = await p.select({
30
+ message: 'Select a project to remove:',
31
+ options: myProjects.map((proj) => ({
32
+ value: proj.slug,
33
+ label: proj.slug,
34
+ hint: proj.description?.slice(0, 50) || '',
35
+ })),
36
+ });
37
+ if (p.isCancel(slug)) {
38
+ p.cancel('Cancelled');
39
+ process.exit(0);
40
+ }
41
+ const confirm = await p.confirm({
42
+ message: `Delete "${slug}" from pmptwiki? This cannot be undone.`,
43
+ initialValue: false,
44
+ });
45
+ if (p.isCancel(confirm) || !confirm) {
46
+ p.cancel('Cancelled');
47
+ process.exit(0);
48
+ }
49
+ const s2 = p.spinner();
50
+ s2.start('Removing...');
51
+ try {
52
+ await unpublishProject(auth.token, slug);
53
+ s2.stop('Removed!');
54
+ p.log.success(`Project "${slug}" has been removed from pmptwiki.`);
55
+ }
56
+ catch (err) {
57
+ s2.stop('Remove failed');
58
+ p.log.error(err instanceof Error ? err.message : 'Failed to remove project.');
59
+ process.exit(1);
60
+ }
61
+ p.outro('');
62
+ }
package/dist/index.js CHANGED
@@ -11,6 +11,8 @@ import { cmdExport } from './commands/export.js';
11
11
  import { cmdImport } from './commands/import.js';
12
12
  import { cmdLogin } from './commands/login.js';
13
13
  import { cmdPublish } from './commands/publish.js';
14
+ import { cmdEdit } from './commands/edit.js';
15
+ import { cmdUnpublish } from './commands/unpublish.js';
14
16
  import { cmdClone } from './commands/clone.js';
15
17
  import { cmdBrowse } from './commands/browse.js';
16
18
  const program = new Command();
@@ -94,6 +96,14 @@ program
94
96
  .command('publish [path]')
95
97
  .description('Publish project to pmptwiki platform')
96
98
  .action(cmdPublish);
99
+ program
100
+ .command('edit')
101
+ .description('Edit published project metadata (description, tags, category)')
102
+ .action(cmdEdit);
103
+ program
104
+ .command('unpublish')
105
+ .description('Remove a published project from pmptwiki')
106
+ .action(cmdUnpublish);
97
107
  program
98
108
  .command('clone <slug>')
99
109
  .description('Clone a project from pmptwiki platform')
package/dist/lib/api.js CHANGED
@@ -48,6 +48,32 @@ export async function fetchProjects() {
48
48
  }
49
49
  return res.json();
50
50
  }
51
+ export async function editProject(token, slug, data) {
52
+ const res = await fetch(`${API_BASE}/publish/${slug}`, {
53
+ method: 'PATCH',
54
+ headers: {
55
+ Authorization: `Bearer ${token}`,
56
+ 'Content-Type': 'application/json',
57
+ },
58
+ body: JSON.stringify(data),
59
+ });
60
+ if (!res.ok) {
61
+ const err = await res.json().catch(() => ({ error: 'Edit failed' }));
62
+ throw new Error(err.error);
63
+ }
64
+ }
65
+ export async function unpublishProject(token, slug) {
66
+ const res = await fetch(`${API_BASE}/publish/${slug}`, {
67
+ method: 'DELETE',
68
+ headers: {
69
+ Authorization: `Bearer ${token}`,
70
+ },
71
+ });
72
+ if (!res.ok) {
73
+ const err = await res.json().catch(() => ({ error: 'Unpublish failed' }));
74
+ throw new Error(err.error);
75
+ }
76
+ }
51
77
  export async function fetchPmptFile(slug) {
52
78
  const res = await fetch(`${R2_PUBLIC_URL}/projects/${slug}.pmpt`);
53
79
  if (!res.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmpt-cli",
3
- "version": "1.5.2",
3
+ "version": "1.6.0",
4
4
  "description": "Record and share your AI-driven product development journey",
5
5
  "type": "module",
6
6
  "bin": {