pmpt-cli 1.0.0 → 1.1.1

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/README.md CHANGED
@@ -1,57 +1,66 @@
1
- # promptwiki-cli
1
+ # pmpt-cli
2
2
 
3
- CLI tool for contributing to [PromptWiki](https://pmptwiki.com) a community-driven guide to working with AI.
3
+ CLI tool for recording and sharing your AI-driven product development journey.
4
+
5
+ **Website**: [pmptwiki.com](https://pmptwiki.com)
4
6
 
5
7
  ## Install
6
8
 
7
9
  ```bash
8
- npm install -g promptwiki-cli
10
+ npm install -g pmpt-cli
9
11
  ```
10
12
 
11
- ## Usage
12
-
13
- ### Create a new document
13
+ ## Quick Start
14
14
 
15
15
  ```bash
16
- promptwiki new
17
- ```
16
+ # Initialize project
17
+ pmpt init
18
18
 
19
- Interactive prompts will guide you through creating a properly structured markdown file.
19
+ # Start product planning (6 questions AI prompt)
20
+ pmpt plan
20
21
 
21
- ### Validate a document
22
+ # Save snapshot manually
23
+ pmpt save
22
24
 
23
- ```bash
24
- promptwiki validate ko/guide/beginner/my-guide.md
25
- ```
26
-
27
- Checks frontmatter schema, required fields, and minimum content length before submission.
25
+ # Or auto-detect file changes
26
+ pmpt watch
28
27
 
29
- ### Submit via Pull Request
28
+ # View version history
29
+ pmpt history
30
+ pmpt history --compact # Hide minor changes
30
31
 
31
- ```bash
32
- promptwiki submit ko/guide/beginner/my-guide.md
32
+ # Squash versions
33
+ pmpt squash v2 v5 # Merge v2-v5 into v2
33
34
  ```
34
35
 
35
- Automatically forks `promptwiki/content`, creates a branch, and opens a Pull Request. Requires a GitHub Personal Access Token with `repo` scope (you'll be prompted on first use).
36
+ ## Folder Structure
36
37
 
37
- ### Logout
38
-
39
- ```bash
40
- promptwiki logout
41
38
  ```
42
-
43
- Removes stored GitHub credentials from `~/.config/promptwiki/auth.json`.
39
+ .promptwiki/
40
+ ├── config.json # Config file
41
+ ├── pmpt/ # Working folder (MD files)
42
+ └── .history/ # Version history
43
+ ```
44
44
 
45
45
  ## Workflow
46
46
 
47
- ```
48
- promptwiki new # create file interactively
49
- # edit the file in your editor
50
- promptwiki validate # check before submitting
51
- promptwiki submit # fork branch PR
52
- ```
53
-
54
- Once your PR is merged into `promptwiki/content`, the site at pmptwiki.com updates automatically.
47
+ 1. `pmpt init` → Initialize project
48
+ 2. `pmpt plan` Answer 6 questions → `pmpt.md` generated
49
+ 3. Copy `pmpt.md` to AI Build with AI conversation
50
+ 4. `pmpt save` or `pmpt watch` → Save progress
51
+ 5. `pmpt submit`Share to archive (coming soon)
52
+
53
+ ## Commands
54
+
55
+ | Command | Description |
56
+ |---------|-------------|
57
+ | `pmpt init` | Initialize project folder |
58
+ | `pmpt plan` | Quick product planning with 6 questions |
59
+ | `pmpt save` | Save current state as snapshot |
60
+ | `pmpt watch` | Auto-detect file changes |
61
+ | `pmpt status` | Check project status |
62
+ | `pmpt history` | View version history |
63
+ | `pmpt squash` | Merge multiple versions |
55
64
 
56
65
  ## License
57
66
 
@@ -37,7 +37,7 @@ export function cmdHistory(path, options) {
37
37
  }
38
38
  const snapshots = getAllSnapshots(projectPath);
39
39
  if (snapshots.length === 0) {
40
- p.intro('PromptWiki — Version History');
40
+ p.intro('pmpt history');
41
41
  p.log.warn('No snapshots saved yet.');
42
42
  p.log.info('Save snapshots with pmpt save or pmpt watch.');
43
43
  p.outro('');
@@ -60,8 +60,8 @@ export function cmdHistory(path, options) {
60
60
  }
61
61
  }
62
62
  const title = options?.compact
63
- ? `PromptWiki Version History (${displaySnapshots.length} shown, ${hiddenVersions.length} hidden)`
64
- : `PromptWiki Version History (${snapshots.length} total)`;
63
+ ? `pmpt history (${displaySnapshots.length} shown, ${hiddenVersions.length} hidden)`
64
+ : `pmpt history (${snapshots.length} total)`;
65
65
  p.intro(title);
66
66
  for (const snapshot of displaySnapshots) {
67
67
  const dateStr = new Date(snapshot.timestamp).toLocaleString(undefined, {
@@ -5,7 +5,7 @@ import { initializeProject, isInitialized } from '../lib/config.js';
5
5
  import { isGitRepo, getGitInfo, formatGitInfo } from '../lib/git.js';
6
6
  import { cmdPlan } from './plan.js';
7
7
  export async function cmdInit(path, options) {
8
- p.intro('PromptWiki — Project Initialization');
8
+ p.intro('pmpt init');
9
9
  const projectPath = path ? resolve(path) : process.cwd();
10
10
  if (!existsSync(projectPath)) {
11
11
  p.outro(`Path does not exist: ${projectPath}`);
@@ -27,14 +27,12 @@ export async function cmdInit(path, options) {
27
27
  }
28
28
  // Build confirmation message
29
29
  const confirmMessage = [
30
- `Track AI conversation history in this folder?`,
30
+ `Initialize pmpt in this folder?`,
31
31
  ` Path: ${projectPath}`,
32
+ ` Docs: .pmpt/docs/`,
32
33
  ];
33
34
  if (isGit && gitInfo) {
34
35
  confirmMessage.push(` Git: ${formatGitInfo(gitInfo)}`);
35
- if (repoUrl) {
36
- confirmMessage.push(` Repository: ${repoUrl}`);
37
- }
38
36
  }
39
37
  const confirm = await p.confirm({
40
38
  message: confirmMessage.join('\n'),
@@ -46,17 +44,11 @@ export async function cmdInit(path, options) {
46
44
  }
47
45
  // If Git repo but no repoUrl, suggest connecting
48
46
  if (isGit && !repoUrl) {
49
- p.log.info(`Tip: Connect a GitHub repo with --repo for more features!`);
50
- p.log.message(` • Auto-record commit hash for each version`);
51
- p.log.message(` • Create PRs directly with pmpt submit`);
52
- p.log.message(` • Others can reproduce exact code states`);
53
- p.log.message('');
54
47
  const repoChoice = await p.select({
55
- message: 'Connect GitHub repository?',
48
+ message: 'Connect GitHub repository? (optional)',
56
49
  options: [
50
+ { value: 'skip', label: 'Skip for now', hint: 'Recommended' },
57
51
  { value: 'now', label: 'Connect now', hint: 'Enter repository URL' },
58
- { value: 'later', label: 'Connect later', hint: 'Re-run with pmpt init --repo <url>' },
59
- { value: 'skip', label: 'Skip', hint: 'Use Git tracking only' },
60
52
  ],
61
53
  });
62
54
  if (p.isCancel(repoChoice)) {
@@ -88,30 +80,31 @@ export async function cmdInit(path, options) {
88
80
  trackGit: isGit,
89
81
  });
90
82
  s.stop('Initialized');
83
+ // Build folder structure display
91
84
  const notes = [
92
85
  `Path: ${config.projectPath}`,
93
86
  '',
94
87
  'Folder structure:',
95
- ' .promptwiki/',
96
- ' ├── config.json Config file',
97
- ' ├── pmpt/ Working folder (MD files)',
98
- ' └── .history/ Version history',
88
+ ` .pmpt/`,
89
+ ` ├── config.json Config`,
90
+ ` ├── docs/ Your docs`,
91
+ ` └── .history/ Snapshots`,
99
92
  ];
100
93
  if (config.repo) {
101
- notes.push('', `Git repository: ${config.repo}`);
94
+ notes.push('', `Repository: ${config.repo}`);
102
95
  }
103
96
  if (config.trackGit) {
104
97
  notes.push(`Git tracking: Enabled`);
105
98
  }
106
- notes.push('', 'Get started with:');
107
- notes.push(' pmpt plan # Start product planning');
108
- notes.push(' pmpt save # Save current state snapshot');
109
- notes.push(' pmpt watch # Auto-detect file changes');
110
- notes.push(' pmpt history # View version history');
99
+ notes.push('', 'Commands:');
100
+ notes.push(' pmpt plan # Generate AI prompt');
101
+ notes.push(' pmpt save # Save snapshot');
102
+ notes.push(' pmpt watch # Auto-save on changes');
103
+ notes.push(' pmpt history # View versions');
111
104
  p.note(notes.join('\n'), 'Project Info');
112
105
  // Ask to start plan mode
113
106
  const startPlan = await p.confirm({
114
- message: 'Start plan mode? (Recommended for first-timers!)',
107
+ message: 'Start planning? (Generate AI prompt with 5 quick questions)',
115
108
  initialValue: true,
116
109
  });
117
110
  if (!p.isCancel(startPlan) && startPlan) {
@@ -119,7 +112,7 @@ export async function cmdInit(path, options) {
119
112
  await cmdPlan(projectPath);
120
113
  }
121
114
  else {
122
- p.outro('PromptWiki project initialized');
115
+ p.outro('Ready! Run `pmpt plan` when you want to start.');
123
116
  }
124
117
  }
125
118
  catch (error) {
@@ -1,14 +1,40 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import { resolve } from 'path';
3
3
  import { readFileSync } from 'fs';
4
+ import { execSync } from 'child_process';
4
5
  import { isInitialized } from '../lib/config.js';
5
6
  import { cmdWatch } from './watch.js';
6
7
  import { PLAN_QUESTIONS, getPlanProgress, initPlanProgress, savePlanProgress, savePlanDocuments, } from '../lib/plan.js';
8
+ // Cross-platform clipboard copy
9
+ function copyToClipboard(text) {
10
+ try {
11
+ const platform = process.platform;
12
+ if (platform === 'darwin') {
13
+ execSync('pbcopy', { input: text });
14
+ }
15
+ else if (platform === 'win32') {
16
+ execSync('clip', { input: text });
17
+ }
18
+ else {
19
+ // Linux - try xclip or xsel
20
+ try {
21
+ execSync('xclip -selection clipboard', { input: text });
22
+ }
23
+ catch {
24
+ execSync('xsel --clipboard --input', { input: text });
25
+ }
26
+ }
27
+ return true;
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
7
33
  export async function cmdPlan(path, options) {
8
34
  const projectPath = path ? resolve(path) : process.cwd();
9
35
  // Check initialization
10
36
  if (!isInitialized(projectPath)) {
11
- p.intro('PromptWiki Plan');
37
+ p.intro('pmpt plan');
12
38
  p.log.error('Project not initialized.');
13
39
  p.log.info('Run `pmpt init` first to initialize the project.');
14
40
  p.outro('');
@@ -30,12 +56,13 @@ export async function cmdPlan(path, options) {
30
56
  let progress = getPlanProgress(projectPath);
31
57
  // If already completed
32
58
  if (progress?.completed) {
33
- p.intro('PromptWiki Plan');
59
+ p.intro('pmpt plan');
34
60
  p.log.success('Plan already completed.');
35
61
  const action = await p.select({
36
62
  message: 'What would you like to do?',
37
63
  options: [
38
- { value: 'view', label: 'View AI prompt', hint: 'Copy and paste to AI' },
64
+ { value: 'copy', label: 'Copy AI prompt to clipboard', hint: 'Ready for Ctrl+V' },
65
+ { value: 'view', label: 'View AI prompt', hint: 'Display in terminal' },
39
66
  { value: 'restart', label: 'Restart plan', hint: 'Start fresh' },
40
67
  { value: 'watch', label: 'Start file watching', hint: 'pmpt watch' },
41
68
  { value: 'exit', label: 'Exit' },
@@ -45,8 +72,7 @@ export async function cmdPlan(path, options) {
45
72
  p.outro('See you next time!');
46
73
  process.exit(0);
47
74
  }
48
- if (action === 'view') {
49
- // Read pmpt.md from pmpt folder
75
+ if (action === 'copy' || action === 'view') {
50
76
  const { getPmptDir } = await import('../lib/config.js');
51
77
  const { existsSync } = await import('fs');
52
78
  const { join } = await import('path');
@@ -55,12 +81,44 @@ export async function cmdPlan(path, options) {
55
81
  try {
56
82
  if (existsSync(promptPath)) {
57
83
  const content = readFileSync(promptPath, 'utf-8');
84
+ if (action === 'copy') {
85
+ const copied = copyToClipboard(content);
86
+ if (copied) {
87
+ p.log.success('AI prompt copied to clipboard!');
88
+ p.log.message('');
89
+ // Eye-catching next step banner
90
+ const banner = [
91
+ '',
92
+ '┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
93
+ '┃ ┃',
94
+ '┃ 📋 NEXT STEP ┃',
95
+ '┃ ┃',
96
+ '┃ Open your AI coding tool and press: ┃',
97
+ '┃ ┃',
98
+ '┃ ⌘ + V (Mac) ┃',
99
+ '┃ Ctrl + V (Windows/Linux) ┃',
100
+ '┃ ┃',
101
+ '┃ Your product journey starts now! 🚀 ┃',
102
+ '┃ ┃',
103
+ '┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛',
104
+ '',
105
+ ];
106
+ console.log(banner.join('\n'));
107
+ }
108
+ else {
109
+ p.log.warn('Could not copy to clipboard. Showing content instead:');
110
+ p.log.message('');
111
+ console.log(content);
112
+ }
113
+ }
114
+ else {
115
+ p.log.message('');
116
+ p.log.info('=== AI Prompt ===');
117
+ p.log.message('');
118
+ console.log(content);
119
+ }
58
120
  p.log.message('');
59
- p.log.info('=== AI Prompt (copy the content below) ===');
60
- p.log.message('');
61
- console.log(content);
62
- p.log.message('');
63
- p.log.info(`File location: ${promptPath}`);
121
+ p.log.info(`File: ${promptPath}`);
64
122
  }
65
123
  else {
66
124
  p.log.error('AI prompt file not found.');
@@ -85,8 +143,8 @@ export async function cmdPlan(path, options) {
85
143
  if (!progress) {
86
144
  progress = initPlanProgress(projectPath);
87
145
  }
88
- p.intro('PromptWiki PlanQuick Product Planning');
89
- p.log.info('Answer 6 questions to generate an AI-ready prompt.');
146
+ p.intro('pmpt planYour Product Journey Starts Here!');
147
+ p.log.info(`Answer ${PLAN_QUESTIONS.length} quick questions to generate your AI prompt.`);
90
148
  p.log.message('You can answer in any language you prefer.');
91
149
  p.log.message('');
92
150
  const answers = {};
@@ -109,42 +167,67 @@ export async function cmdPlan(path, options) {
109
167
  }
110
168
  // Generate documents
111
169
  const s = p.spinner();
112
- s.start('Generating documents...');
170
+ s.start('Generating your AI prompt...');
113
171
  const { planPath, promptPath } = savePlanDocuments(projectPath, answers);
114
172
  // Update progress
115
173
  progress.completed = true;
116
174
  progress.answers = answers;
117
175
  savePlanProgress(projectPath, progress);
118
176
  s.stop('Done!');
119
- // Show results
120
- p.log.message('');
121
- p.log.success('Plan completed!');
177
+ // Show document explanation
122
178
  p.log.message('');
123
- p.log.info(`Plan document: ${planPath}`);
124
- p.log.info(`AI prompt: ${promptPath}`);
179
+ p.log.success('Two documents have been created:');
125
180
  p.log.message('');
126
- // Preview AI prompt
127
- const showPrompt = await p.confirm({
128
- message: 'View AI prompt now?',
129
- initialValue: true,
130
- });
131
- if (!p.isCancel(showPrompt) && showPrompt) {
132
- const content = readFileSync(promptPath, 'utf-8');
181
+ const docExplanation = [
182
+ `1. plan.md Your product overview`,
183
+ ` • Features checklist to track progress`,
184
+ ` • Reference for you`,
185
+ ` Location: ${planPath}`,
186
+ '',
187
+ `2. pmpt.md AI prompt (THE IMPORTANT ONE!)`,
188
+ ` • Copy this to Claude/ChatGPT/Codex`,
189
+ ` • AI will help you build step by step`,
190
+ ` • AI will update this doc as you progress`,
191
+ ` Location: ${promptPath}`,
192
+ ];
193
+ p.note(docExplanation.join('\n'), 'What are these files?');
194
+ // Copy to clipboard
195
+ const content = readFileSync(promptPath, 'utf-8');
196
+ const copied = copyToClipboard(content);
197
+ if (copied) {
198
+ p.log.message('');
199
+ p.log.success('AI prompt copied to clipboard!');
200
+ p.log.message('');
201
+ // Eye-catching next step banner
202
+ const banner = [
203
+ '',
204
+ '┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
205
+ '┃ ┃',
206
+ '┃ 📋 NEXT STEP ┃',
207
+ '┃ ┃',
208
+ '┃ Open your AI coding tool and press: ┃',
209
+ '┃ ┃',
210
+ '┃ ⌘ + V (Mac) ┃',
211
+ '┃ Ctrl + V (Windows/Linux) ┃',
212
+ '┃ ┃',
213
+ '┃ Your product journey starts now! 🚀 ┃',
214
+ '┃ ┃',
215
+ '┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛',
216
+ '',
217
+ ];
218
+ console.log(banner.join('\n'));
219
+ }
220
+ else {
221
+ // Fallback: show prompt
133
222
  p.log.message('');
134
- p.log.info('=== AI Prompt (copy the content below) ===');
223
+ p.log.info('=== AI Prompt (copy this to AI) ===');
135
224
  p.log.message('');
136
225
  console.log(content);
137
226
  p.log.message('');
138
227
  }
139
- // Next steps
140
- p.log.message('');
141
- p.log.step('Next steps:');
142
- p.log.message('1. Copy the AI prompt above and paste to Claude/ChatGPT');
143
- p.log.message('2. Build your product with AI');
144
- p.log.message('3. Save snapshots with pmpt save (or pmpt watch for auto-save)');
145
- p.log.message('');
228
+ // Ask about watch mode
146
229
  const startWatch = await p.confirm({
147
- message: 'Start file watching? (pmpt watch)',
230
+ message: 'Start file watching? (auto-save versions as you work)',
148
231
  initialValue: false,
149
232
  });
150
233
  if (!p.isCancel(startWatch) && startWatch) {
@@ -152,7 +235,11 @@ export async function cmdPlan(path, options) {
152
235
  await cmdWatch(projectPath);
153
236
  }
154
237
  else {
155
- p.log.info('Start watching later with `pmpt watch`');
156
- p.outro('Good luck!');
238
+ p.log.message('');
239
+ p.log.info('Tips:');
240
+ p.log.message(' pmpt save — Save a snapshot anytime');
241
+ p.log.message(' pmpt watch — Auto-save on file changes');
242
+ p.log.message(' pmpt history — View version history');
243
+ p.outro('Good luck with your build!');
157
244
  }
158
245
  }
@@ -1,7 +1,7 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import { resolve } from 'path';
3
3
  import { existsSync, statSync } from 'fs';
4
- import { isInitialized, getPmptDir } from '../lib/config.js';
4
+ import { isInitialized, getDocsDir } from '../lib/config.js';
5
5
  import { createFullSnapshot, getTrackedFiles } from '../lib/history.js';
6
6
  export async function cmdSave(fileOrPath) {
7
7
  const projectPath = fileOrPath && existsSync(fileOrPath) && statSync(fileOrPath).isDirectory()
@@ -11,13 +11,13 @@ export async function cmdSave(fileOrPath) {
11
11
  p.log.error('Project not initialized. Run `pmpt init` first.');
12
12
  process.exit(1);
13
13
  }
14
- p.intro('PromptWiki — Save Snapshot');
15
- const pmptDir = getPmptDir(projectPath);
14
+ p.intro('pmpt save');
15
+ const docsDir = getDocsDir(projectPath);
16
16
  const files = getTrackedFiles(projectPath);
17
17
  if (files.length === 0) {
18
18
  p.log.warn('No files to save.');
19
- p.log.info(`pmpt folder: ${pmptDir}`);
20
- p.log.info('Start with `pmpt plan` or add MD files to the pmpt folder.');
19
+ p.log.info(`Docs folder: ${docsDir}`);
20
+ p.log.info('Start with `pmpt plan` or add MD files to the docs folder.');
21
21
  p.outro('');
22
22
  return;
23
23
  }
@@ -31,7 +31,7 @@ export async function cmdSquash(from, to, path) {
31
31
  p.log.error(`Need at least 2 versions to squash. Found ${toSquash.length} in range v${fromVersion}-v${toVersion}.`);
32
32
  process.exit(1);
33
33
  }
34
- p.intro('PromptWiki — Squash Versions');
34
+ p.intro('pmpt squash');
35
35
  p.log.info(`Squashing v${fromVersion} through v${toVersion} (${toSquash.length} versions)`);
36
36
  const confirm = await p.confirm({
37
37
  message: `This will keep v${fromVersion} and delete v${fromVersion + 1} through v${toVersion}. Continue?`,
@@ -11,7 +11,7 @@ export function cmdStatus(path) {
11
11
  const config = loadConfig(projectPath);
12
12
  const tracked = getTrackedFiles(projectPath);
13
13
  const snapshots = getAllSnapshots(projectPath);
14
- p.intro('PromptWiki — Project Status');
14
+ p.intro('pmpt status');
15
15
  const notes = [
16
16
  `Path: ${projectPath}`,
17
17
  `Created: ${new Date(config.createdAt).toLocaleString()}`,
@@ -20,7 +20,7 @@ export function cmdStatus(path) {
20
20
  notes.push(`Last published: ${new Date(config.lastPublished).toLocaleString()}`);
21
21
  }
22
22
  notes.push('');
23
- notes.push(`pmpt folder: .promptwiki/pmpt/`);
23
+ notes.push(`Docs folder: ${config.docsPath}/`);
24
24
  notes.push(`Snapshots: ${snapshots.length}`);
25
25
  notes.push('');
26
26
  notes.push(`Tracked files: ${tracked.length}`);
@@ -1,6 +1,6 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import { resolve } from 'path';
3
- import { isInitialized, getPmptDir } from '../lib/config.js';
3
+ import { isInitialized, getDocsDir } from '../lib/config.js';
4
4
  import { startWatching } from '../lib/watcher.js';
5
5
  export function cmdWatch(path) {
6
6
  const projectPath = path ? resolve(path) : process.cwd();
@@ -8,9 +8,9 @@ export function cmdWatch(path) {
8
8
  p.log.error('Project not initialized. Run `pmpt init` first.');
9
9
  process.exit(1);
10
10
  }
11
- const pmptDir = getPmptDir(projectPath);
12
- p.intro('PromptWiki — File Watcher');
13
- p.log.info(`Watching: ${pmptDir}`);
11
+ const docsDir = getDocsDir(projectPath);
12
+ p.intro('pmpt watch — File Watcher');
13
+ p.log.info(`Watching: ${docsDir}`);
14
14
  p.log.info('Auto-saving snapshots on MD file changes.');
15
15
  p.log.info('Press Ctrl+C to stop.');
16
16
  p.log.message('');
@@ -27,7 +27,7 @@ export function cmdWatch(path) {
27
27
  p.log.message('');
28
28
  p.log.info('Stopping watcher...');
29
29
  watcher.close();
30
- p.outro('PromptWiki watcher stopped');
30
+ p.outro('Watcher stopped');
31
31
  process.exit(0);
32
32
  });
33
33
  }
package/dist/index.js CHANGED
@@ -19,16 +19,16 @@ program
19
19
  Examples:
20
20
  $ pmpt init Initialize project
21
21
  $ pmpt plan Start product planning (6 questions → AI prompt)
22
- $ pmpt save Save snapshot of pmpt folder
22
+ $ pmpt save Save snapshot of docs folder
23
23
  $ pmpt watch Auto-detect file changes
24
24
  $ pmpt history View version history
25
25
  $ pmpt history --compact Hide minor changes
26
26
  $ pmpt squash v2 v5 Merge versions v2-v5 into v2
27
27
 
28
28
  Folder structure:
29
- .promptwiki/
29
+ .pmpt/
30
30
  ├── config.json Config file
31
- ├── pmpt/ Working folder (MD files)
31
+ ├── docs/ Working folder (MD files)
32
32
  └── .history/ Version history
33
33
 
34
34
  Documentation: https://pmptwiki.com
@@ -45,7 +45,7 @@ program
45
45
  .action(cmdWatch);
46
46
  program
47
47
  .command('save [path]')
48
- .description('Save current state of pmpt folder as snapshot')
48
+ .description('Save current state of docs folder as snapshot')
49
49
  .action(cmdSave);
50
50
  program
51
51
  .command('status [path]')
@@ -1,15 +1,17 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
- const CONFIG_DIR = '.promptwiki';
3
+ const CONFIG_DIR = '.pmpt';
4
4
  const CONFIG_FILE = 'config.json';
5
- const PMPT_DIR = 'pmpt'; // 작업 폴더 (추적 대상)
6
- const HISTORY_DIR = '.history'; // 히스토리 (숨김)
5
+ const DEFAULT_DOCS_DIR = 'docs';
6
+ const HISTORY_DIR = '.history';
7
7
  export function getConfigDir(projectPath) {
8
8
  return join(projectPath, CONFIG_DIR);
9
9
  }
10
- export function getPmptDir(projectPath) {
11
- return join(getConfigDir(projectPath), PMPT_DIR);
10
+ export function getDocsDir(projectPath) {
11
+ return join(getConfigDir(projectPath), DEFAULT_DOCS_DIR);
12
12
  }
13
+ // Alias for backward compatibility
14
+ export const getPmptDir = getDocsDir;
13
15
  export function getHistoryDir(projectPath) {
14
16
  return join(getConfigDir(projectPath), HISTORY_DIR);
15
17
  }
@@ -18,15 +20,18 @@ export function isInitialized(projectPath) {
18
20
  }
19
21
  export function initializeProject(projectPath, options) {
20
22
  const configDir = getConfigDir(projectPath);
21
- const pmptDir = getPmptDir(projectPath);
22
23
  const historyDir = getHistoryDir(projectPath);
24
+ const docsDir = getDocsDir(projectPath);
25
+ // docsPath is always .pmpt/docs
26
+ const docsPath = join(CONFIG_DIR, DEFAULT_DOCS_DIR);
27
+ // Create directories
23
28
  mkdirSync(configDir, { recursive: true });
24
- mkdirSync(pmptDir, { recursive: true });
25
29
  mkdirSync(historyDir, { recursive: true });
30
+ mkdirSync(docsDir, { recursive: true });
26
31
  const config = {
27
32
  projectPath,
28
- watchPatterns: ['.promptwiki/pmpt/**/*.md'], // pmpt 폴더만 추적
29
- ignorePatterns: ['node_modules/**', '.promptwiki/.history/**', 'dist/**'],
33
+ docsPath,
34
+ ignorePatterns: ['node_modules/**', '.pmpt/.history/**', 'dist/**'],
30
35
  createdAt: new Date().toISOString(),
31
36
  repo: options?.repo,
32
37
  trackGit: options?.trackGit ?? true,
@@ -1,15 +1,15 @@
1
1
  import { copyFileSync, existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, statSync } from 'fs';
2
2
  import { basename, join, relative } from 'path';
3
- import { getHistoryDir, getPmptDir, loadConfig } from './config.js';
3
+ import { getHistoryDir, getDocsDir, loadConfig } from './config.js';
4
4
  import { getGitInfo, isGitRepo } from './git.js';
5
5
  import glob from 'fast-glob';
6
6
  /**
7
- * pmpt 폴더 전체를 스냅샷으로 저장
7
+ * .pmpt/docs 폴더의 MD 파일을 스냅샷으로 저장
8
8
  * .history/v{N}-{timestamp}/ 폴더에 모든 파일 복사
9
9
  */
10
10
  export function createFullSnapshot(projectPath) {
11
11
  const historyDir = getHistoryDir(projectPath);
12
- const pmptDir = getPmptDir(projectPath);
12
+ const docsDir = getDocsDir(projectPath);
13
13
  mkdirSync(historyDir, { recursive: true });
14
14
  // 다음 버전 번호 찾기
15
15
  const existing = getAllSnapshots(projectPath);
@@ -18,12 +18,12 @@ export function createFullSnapshot(projectPath) {
18
18
  const snapshotName = `v${version}-${timestamp}`;
19
19
  const snapshotDir = join(historyDir, snapshotName);
20
20
  mkdirSync(snapshotDir, { recursive: true });
21
- // pmpt 폴더의 모든 MD 파일 복사
21
+ // docs 폴더의 MD 파일 복사
22
22
  const files = [];
23
- if (existsSync(pmptDir)) {
24
- const mdFiles = glob.sync('**/*.md', { cwd: pmptDir });
23
+ if (existsSync(docsDir)) {
24
+ const mdFiles = glob.sync('**/*.md', { cwd: docsDir });
25
25
  for (const file of mdFiles) {
26
- const srcPath = join(pmptDir, file);
26
+ const srcPath = join(docsDir, file);
27
27
  const destPath = join(snapshotDir, file);
28
28
  // 하위 디렉토리가 있으면 생성
29
29
  const destDir = join(snapshotDir, file.split('/').slice(0, -1).join('/'));
@@ -71,9 +71,9 @@ export function createFullSnapshot(projectPath) {
71
71
  */
72
72
  export function createSnapshot(projectPath, filePath) {
73
73
  const historyDir = getHistoryDir(projectPath);
74
- const pmptDir = getPmptDir(projectPath);
75
- const relPath = relative(pmptDir, filePath);
76
- // 파일이 pmpt 폴더 외부에 있는 경우
74
+ const docsDir = getDocsDir(projectPath);
75
+ const relPath = relative(docsDir, filePath);
76
+ // 파일이 docs 폴더 외부에 있는 경우
77
77
  if (relPath.startsWith('..')) {
78
78
  // 프로젝트 루트 기준 상대 경로 사용
79
79
  const projectRelPath = relative(projectPath, filePath);
@@ -83,7 +83,6 @@ export function createSnapshot(projectPath, filePath) {
83
83
  }
84
84
  function createSingleFileSnapshot(projectPath, filePath, relPath) {
85
85
  const historyDir = getHistoryDir(projectPath);
86
- const fileName = basename(filePath, '.md');
87
86
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
88
87
  // 해당 파일의 기존 버전 수 확인
89
88
  const existing = getFileHistory(projectPath, relPath);
@@ -223,11 +222,11 @@ export function getAllHistory(projectPath) {
223
222
  return entries.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
224
223
  }
225
224
  /**
226
- * 추적 중인 파일 목록 (pmpt 폴더 기준)
225
+ * 추적 중인 파일 목록 (.pmpt/docs 기준)
227
226
  */
228
227
  export function getTrackedFiles(projectPath) {
229
- const pmptDir = getPmptDir(projectPath);
230
- if (!existsSync(pmptDir))
228
+ const docsDir = getDocsDir(projectPath);
229
+ if (!existsSync(docsDir))
231
230
  return [];
232
- return glob.sync('**/*.md', { cwd: pmptDir });
231
+ return glob.sync('**/*.md', { cwd: docsDir });
233
232
  }
package/dist/lib/plan.js CHANGED
@@ -3,72 +3,65 @@ import { join } from 'path';
3
3
  import { getConfigDir, getPmptDir } from './config.js';
4
4
  import { createFullSnapshot } from './history.js';
5
5
  const PLAN_FILE = 'plan-progress.json';
6
- // 6 simple questions (answer in any language you prefer)
6
+ // 5 simple questions (answer in any language you prefer)
7
+ // This is the first step of your product journey with AI!
7
8
  export const PLAN_QUESTIONS = [
8
9
  {
9
10
  key: 'projectName',
10
- question: 'Project name?',
11
+ question: 'What should we call your project?',
11
12
  placeholder: 'my-awesome-app',
12
13
  required: true,
13
14
  },
14
15
  {
15
- key: 'problem',
16
- question: 'What problem are you solving?',
17
- placeholder: 'e.g., Developers spend too much time finding API docs',
16
+ key: 'productIdea',
17
+ question: "What would you like to build with AI? (Let's start your journey!)",
18
+ placeholder: 'e.g., A Chrome extension that summarizes long articles, A budget tracking app for freelancers',
18
19
  multiline: true,
19
20
  required: true,
20
21
  },
21
22
  {
22
- key: 'solution',
23
- question: 'How will you solve it?',
24
- placeholder: 'e.g., AI analyzes code and auto-generates API docs',
23
+ key: 'additionalContext',
24
+ question: 'Any additional context AI should know? (optional)',
25
+ placeholder: 'e.g., I prefer simple UI, Must work offline, Target audience is students',
25
26
  multiline: true,
26
- required: true,
27
- },
28
- {
29
- key: 'targetUser',
30
- question: 'Who is your target user?',
31
- placeholder: 'e.g., Startup backend developers',
32
- required: true,
27
+ required: false,
33
28
  },
34
29
  {
35
30
  key: 'coreFeatures',
36
- question: 'Core features for MVP? (one per line)',
37
- placeholder: 'e.g.:\nCode upload\nAI analysis\nDoc generation',
31
+ question: 'Key features to include? (separate with commas or semicolons)',
32
+ placeholder: 'e.g., User login; Dashboard; Export to PDF; Dark mode',
38
33
  multiline: true,
39
34
  required: true,
40
35
  },
41
36
  {
42
37
  key: 'techStack',
43
- question: 'Preferred tech stack? (optional)',
44
- placeholder: 'e.g., React, Node.js, PostgreSQL',
38
+ question: 'Preferred tech stack? (optional - AI can suggest if unsure)',
39
+ placeholder: 'e.g., React, Node.js, PostgreSQL — or "up to you"',
45
40
  multiline: false,
46
41
  required: false,
47
42
  },
48
43
  ];
49
44
  // Generate AI prompt (language-agnostic template)
50
45
  export function generateAIPrompt(answers) {
46
+ // Parse features (support comma, semicolon, or newline separators)
51
47
  const features = answers.coreFeatures
52
- .split('\n')
48
+ .split(/[,;\n]/)
53
49
  .map((f) => f.trim())
54
50
  .filter((f) => f)
55
51
  .map((f) => `- ${f}`)
56
52
  .join('\n');
53
+ const contextSection = answers.additionalContext
54
+ ? `\n## Additional Context\n${answers.additionalContext}\n`
55
+ : '';
57
56
  const techSection = answers.techStack
58
57
  ? `\n## Tech Stack Preferences\n${answers.techStack}\n`
59
58
  : '';
60
59
  return `# ${answers.projectName} — Product Development Request
61
60
 
62
- ## Problem
63
- ${answers.problem}
64
-
65
- ## Proposed Solution
66
- ${answers.solution}
67
-
68
- ## Target User
69
- ${answers.targetUser}
70
-
71
- ## MVP Core Features
61
+ ## What I Want to Build
62
+ ${answers.productIdea}
63
+ ${contextSection}
64
+ ## Key Features
72
65
  ${features}
73
66
  ${techSection}
74
67
  ---
@@ -77,14 +70,14 @@ Please help me build this product based on the requirements above.
77
70
 
78
71
  1. First, review the requirements and ask if anything is unclear.
79
72
  2. Propose a technical architecture.
80
- 3. Outline the MVP implementation steps.
73
+ 3. Outline the implementation steps.
81
74
  4. Start coding from the first step.
82
75
 
83
76
  I'll confirm progress at each step before moving to the next.
84
77
 
85
78
  ## Documentation Rule
86
79
 
87
- **Important:** Update this document (located at \`.promptwiki/pmpt/pmpt.md\`) at these moments:
80
+ **Important:** Update this document (located at \`.pmpt/docs/pmpt.md\`) at these moments:
88
81
  - When architecture or tech decisions are finalized
89
82
  - When a feature is implemented (mark as done)
90
83
  - When a development phase is completed
@@ -102,31 +95,29 @@ This keeps a living record of our development journey.
102
95
  }
103
96
  // Generate plan document
104
97
  export function generatePlanDocument(answers) {
98
+ // Parse features (support comma, semicolon, or newline separators)
105
99
  const features = answers.coreFeatures
106
- .split('\n')
100
+ .split(/[,;\n]/)
107
101
  .map((f) => f.trim())
108
102
  .filter((f) => f)
109
103
  .map((f) => `- [ ] ${f}`)
110
104
  .join('\n');
105
+ const contextSection = answers.additionalContext
106
+ ? `\n## Additional Context\n${answers.additionalContext}\n`
107
+ : '';
111
108
  const techSection = answers.techStack
112
109
  ? `\n## Tech Stack\n${answers.techStack}\n`
113
110
  : '';
114
111
  return `# ${answers.projectName}
115
112
 
116
- ## Problem
117
- ${answers.problem}
118
-
119
- ## Solution
120
- ${answers.solution}
121
-
122
- ## Target User
123
- ${answers.targetUser}
124
-
125
- ## MVP Features
113
+ ## Product Idea
114
+ ${answers.productIdea}
115
+ ${contextSection}
116
+ ## Features
126
117
  ${features}
127
118
  ${techSection}
128
119
  ---
129
- *Generated by PromptWiki Plan*
120
+ *Generated by pmpt plan*
130
121
  `;
131
122
  }
132
123
  export function getPlanProgress(projectPath) {
@@ -1,16 +1,16 @@
1
1
  import chokidar from 'chokidar';
2
- import { loadConfig, getPmptDir } from './config.js';
2
+ import { loadConfig, getDocsDir } from './config.js';
3
3
  import { createFullSnapshot } from './history.js';
4
4
  import { readFileSync } from 'fs';
5
+ import { join } from 'path';
5
6
  export function startWatching(projectPath, onSnapshot) {
6
7
  const config = loadConfig(projectPath);
7
8
  if (!config) {
8
9
  throw new Error('Project not initialized. Run `pmpt init` first.');
9
10
  }
10
- const pmptDir = getPmptDir(projectPath);
11
- // Watch all MD files in pmpt folder
12
- const watcher = chokidar.watch('**/*.md', {
13
- cwd: pmptDir,
11
+ const docsDir = getDocsDir(projectPath);
12
+ // Watch all MD files in docs folder
13
+ const watcher = chokidar.watch(join(docsDir, '**/*.md'), {
14
14
  ignoreInitial: true,
15
15
  persistent: true,
16
16
  awaitWriteFinish: {
@@ -34,9 +34,8 @@ export function startWatching(projectPath, onSnapshot) {
34
34
  debounceTimer = setTimeout(saveSnapshot, 1000);
35
35
  };
36
36
  watcher.on('add', (path) => {
37
- const fullPath = `${pmptDir}/${path}`;
38
37
  try {
39
- const content = readFileSync(fullPath, 'utf-8');
38
+ const content = readFileSync(path, 'utf-8');
40
39
  fileContents.set(path, content);
41
40
  debouncedSave();
42
41
  }
@@ -45,9 +44,8 @@ export function startWatching(projectPath, onSnapshot) {
45
44
  }
46
45
  });
47
46
  watcher.on('change', (path) => {
48
- const fullPath = `${pmptDir}/${path}`;
49
47
  try {
50
- const newContent = readFileSync(fullPath, 'utf-8');
48
+ const newContent = readFileSync(path, 'utf-8');
51
49
  const oldContent = fileContents.get(path);
52
50
  // Only snapshot if content actually changed
53
51
  if (oldContent !== newContent) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmpt-cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Record and share your AI-driven product development journey",
5
5
  "type": "module",
6
6
  "bin": {