pmpt-cli 1.17.0 → 1.18.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
@@ -96,6 +96,7 @@ The generated prompt is **automatically copied to your clipboard**. Just paste i
96
96
  | Command | Description |
97
97
  |---------|-------------|
98
98
  | `pmpt init` | Initialize project — sets up `.pmpt/`, selects AI tool, creates entry points |
99
+ | `pmpt harness` | Add harness to existing project — missing pmpt.md sections + index.md + tool entry points |
99
100
  | `pmpt plan` | 5 questions → AI prompt (auto-copied to clipboard) |
100
101
  | `pmpt plan --template` | Generate a fillable `answers.json` (Windows/PowerShell friendly) |
101
102
  | `pmpt plan --answers-file <f>` | Run plan non-interactively from a JSON file |
@@ -0,0 +1,59 @@
1
+ import * as p from '@clack/prompts';
2
+ import { resolve, basename } from 'path';
3
+ import { isInitialized } from '../lib/config.js';
4
+ import { addMissingSections, ensureIndexMd, ensureCursorRules, ensureAgentsMd, ensureClaudeMdRef, } from '../lib/harness.js';
5
+ export async function cmdHarness(path) {
6
+ const projectPath = path ? resolve(path) : process.cwd();
7
+ const projectName = basename(projectPath);
8
+ p.intro('pmpt harness');
9
+ if (!isInitialized(projectPath)) {
10
+ p.log.error('Project not initialized. Run `pmpt init` first.');
11
+ process.exit(1);
12
+ }
13
+ // 1. Add missing sections to pmpt.md
14
+ const added = addMissingSections(projectPath);
15
+ if (added.length > 0) {
16
+ p.log.success(`Added to pmpt.md: ${added.join(', ')}`);
17
+ }
18
+ else {
19
+ p.log.info('pmpt.md already has all harness sections.');
20
+ }
21
+ // 2. Create .pmpt/index.md
22
+ ensureIndexMd(projectPath, projectName);
23
+ p.log.success('Created: .pmpt/index.md');
24
+ // 3. Ask which AI tool
25
+ const toolChoice = await p.select({
26
+ message: 'Which AI coding tool do you use?',
27
+ options: [
28
+ { value: 'claude', label: 'Claude Code', hint: 'CLAUDE.md → .pmpt/index.md' },
29
+ { value: 'cursor', label: 'Cursor', hint: '.cursorrules → .pmpt/index.md' },
30
+ { value: 'codex', label: 'Codex', hint: 'AGENTS.md → .pmpt/index.md' },
31
+ { value: 'all', label: 'All of the above' },
32
+ { value: 'skip', label: 'Skip' },
33
+ ],
34
+ });
35
+ if (p.isCancel(toolChoice) || toolChoice === 'skip') {
36
+ p.outro('Done. .pmpt/index.md created, pmpt.md updated.');
37
+ return;
38
+ }
39
+ const tool = toolChoice;
40
+ const created = [];
41
+ if (tool === 'claude' || tool === 'all') {
42
+ ensureClaudeMdRef(projectPath);
43
+ created.push('CLAUDE.md (updated)');
44
+ }
45
+ if (tool === 'cursor' || tool === 'all') {
46
+ ensureCursorRules(projectPath);
47
+ created.push('.cursorrules');
48
+ }
49
+ if (tool === 'codex' || tool === 'all') {
50
+ ensureAgentsMd(projectPath, projectName);
51
+ created.push('AGENTS.md');
52
+ }
53
+ if (created.length > 0) {
54
+ p.log.success(`Created: ${created.join(', ')}`);
55
+ }
56
+ p.log.message('');
57
+ p.log.info('AI tools will now read .pmpt/index.md → .pmpt/docs/pmpt.md at session start.');
58
+ p.outro('Harness ready.');
59
+ }
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ import { cmdInternalSeed } from './commands/internal-seed.js';
47
47
  import { cmdMcpSetup } from './commands/mcp-setup.js';
48
48
  import { cmdDoctor } from './commands/doctor.js';
49
49
  import { cmdConstraint } from './commands/constraint.js';
50
+ import { cmdHarness } from './commands/harness.js';
50
51
  import { trackCommand } from './lib/api.js';
51
52
  import { checkForUpdates } from './lib/update-check.js';
52
53
  import { createRequire } from 'module';
@@ -154,6 +155,10 @@ program
154
155
  ...options,
155
156
  template: options.template === true ? 'answers.json' : options.template,
156
157
  }));
158
+ program
159
+ .command('harness [path]')
160
+ .description('Set up AI context harness for existing projects — adds missing pmpt.md sections and creates tool entry points')
161
+ .action(cmdHarness);
157
162
  program
158
163
  .command('constraint <action>')
159
164
  .description('Manage architecture constraints — add, list, or remove rules')
@@ -62,7 +62,12 @@ export function saveConfig(projectPath, config) {
62
62
  const configPath = join(getConfigDir(projectPath), CONFIG_FILE);
63
63
  writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
64
64
  }
65
- const PMPT_CLAUDE_SECTION = `
65
+ const PMPT_INDEX_SECTION = `
66
+ <!-- pmpt-index -->
67
+ See \`.pmpt/index.md\` for project context. Single source of truth: \`.pmpt/docs/pmpt.md\`.
68
+ <!-- /pmpt-index -->
69
+ `;
70
+ const PMPT_MCP_SECTION = `
66
71
  <!-- pmpt -->
67
72
  ## pmpt MCP Tools
68
73
 
@@ -78,6 +83,7 @@ Save after: feature completion, architecture decisions, bug fixes, or any signif
78
83
  If pmpt MCP is not available, run \`pmpt save\` in terminal instead.
79
84
  <!-- /pmpt -->
80
85
  `;
86
+ const PMPT_CLAUDE_SECTION = PMPT_INDEX_SECTION + PMPT_MCP_SECTION;
81
87
  /**
82
88
  * Add pmpt MCP instructions to CLAUDE.md in the project root.
83
89
  * Creates the file if it doesn't exist; appends the section if not already present.
@@ -26,21 +26,35 @@ export function generateIndexMd(projectName) {
26
26
  export function generateCursorRules() {
27
27
  return `# Project Rules
28
28
 
29
- See \`.pmpt/index.md\` for the project context map.
30
-
29
+ See \`.pmpt/index.md\` for the full project context map.
31
30
  The single source of truth is \`.pmpt/docs/pmpt.md\`.
32
- Always check the **## Constraints** section before making code changes.
33
- After completing milestones, run \`pmpt save\` in terminal.
31
+
32
+ ## pmpt
33
+
34
+ This project uses [pmpt](https://pmptwiki.com) to track development progress.
35
+
36
+ - Read \`.pmpt/docs/pmpt.md\` before making any code changes
37
+ - Follow every rule in the **## Constraints** section of pmpt.md
38
+ - After milestones, run \`pmpt save\` in terminal with a summary
39
+ - Run \`pmpt status\` to check project state
40
+ - Update pmpt.md when architecture, constraints, or features change
34
41
  `;
35
42
  }
36
43
  export function generateAgentsMd(projectName) {
37
44
  return `# ${projectName} — Agent Instructions
38
45
 
39
- See \`.pmpt/index.md\` for the project context map.
40
-
46
+ See \`.pmpt/index.md\` for the full project context map.
41
47
  The single source of truth is \`.pmpt/docs/pmpt.md\`.
42
- Always check the **## Constraints** section before making code changes.
43
- After completing milestones, run \`pmpt save\` in terminal.
48
+
49
+ ## pmpt
50
+
51
+ This project uses [pmpt](https://pmptwiki.com) to track development progress.
52
+
53
+ - Read \`.pmpt/docs/pmpt.md\` before making any code changes
54
+ - Follow every rule in the **## Constraints** section of pmpt.md
55
+ - After milestones, run \`pmpt save\` in terminal with a summary
56
+ - Run \`pmpt status\` to check project state
57
+ - Update pmpt.md when architecture, constraints, or features change
44
58
  `;
45
59
  }
46
60
  // ─── Setup functions ───────────────────────────────────────────────
@@ -77,22 +91,62 @@ export function setupHarnessForTools(projectPath, projectName, tools) {
77
91
  ensureClaudeMdIndexRef(projectPath);
78
92
  }
79
93
  }
94
+ export function ensureClaudeMdRef(projectPath) {
95
+ ensureClaudeMdIndexRef(projectPath);
96
+ }
80
97
  function ensureClaudeMdIndexRef(projectPath) {
81
- const claudeMdPath = join(projectPath, 'CLAUDE.md');
82
- const marker = '<!-- pmpt-index -->';
83
- const section = `${marker}\nSee \`.pmpt/index.md\` for project context. Single source of truth: \`.pmpt/docs/pmpt.md\`.\n<!-- /pmpt-index -->`;
84
- if (!existsSync(claudeMdPath))
85
- return;
86
- const content = readFileSync(claudeMdPath, 'utf-8');
87
- if (content.includes(marker))
88
- return;
89
- const pmptMarker = '<!-- pmpt -->';
90
- if (content.includes(pmptMarker)) {
91
- writeFileSync(claudeMdPath, content.replace(pmptMarker, section + '\n\n' + pmptMarker), 'utf-8');
98
+ // Delegate to ensurePmptClaudeMd which handles both creation and section injection
99
+ // (index pointer + MCP tools)
100
+ const { ensurePmptClaudeMd } = require('./config.js');
101
+ ensurePmptClaudeMd(projectPath);
102
+ }
103
+ // ─── pmpt.md section migration ────────────────────────────────────
104
+ const HARNESS_SECTIONS = [
105
+ {
106
+ heading: '## Architecture',
107
+ comment: '<!-- High-level structure. Update as it evolves. -->\n<!-- Example: "Next.js frontend → Cloudflare Workers API → D1 database" -->',
108
+ },
109
+ {
110
+ heading: '## Active Work',
111
+ comment: '<!-- What\'s currently being built. Clear when done, move to Snapshot Log. -->',
112
+ },
113
+ {
114
+ heading: '## Constraints',
115
+ comment: '<!-- Platform or library limitations discovered during development. -->\n<!-- Format: - [Platform/Tool]: what doesn\'t work → workaround used -->',
116
+ },
117
+ {
118
+ heading: '## Lessons',
119
+ comment: '<!-- Anti-patterns and "tried X, broke because Y" discoveries. -->\n<!-- Format: - [What failed] → [Root cause] → [Fix applied] -->',
120
+ },
121
+ ];
122
+ /**
123
+ * Add missing harness sections to an existing pmpt.md.
124
+ * Returns list of section headings that were added.
125
+ */
126
+ export function addMissingSections(projectPath) {
127
+ const pmptMdPath = join(getDocsDir(projectPath), 'pmpt.md');
128
+ if (!existsSync(pmptMdPath))
129
+ return [];
130
+ let content = readFileSync(pmptMdPath, 'utf-8');
131
+ const added = [];
132
+ for (const section of HARNESS_SECTIONS) {
133
+ if (content.includes(section.heading))
134
+ continue;
135
+ // Insert before ## Decisions if it exists, otherwise append
136
+ const insertBefore = '## Decisions';
137
+ const block = `${section.heading}\n${section.comment}\n`;
138
+ if (content.includes(insertBefore)) {
139
+ content = content.replace(insertBefore, block + '\n' + insertBefore);
140
+ }
141
+ else {
142
+ content = content.trimEnd() + '\n\n' + block;
143
+ }
144
+ added.push(section.heading);
92
145
  }
93
- else {
94
- writeFileSync(claudeMdPath, section + '\n\n' + content, 'utf-8');
146
+ if (added.length > 0) {
147
+ writeFileSync(pmptMdPath, content, 'utf-8');
95
148
  }
149
+ return added;
96
150
  }
97
151
  // ─── Constraint management — reads/writes pmpt.md ## Constraints ──
98
152
  export function readConstraints(projectPath) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmpt-cli",
3
- "version": "1.17.0",
3
+ "version": "1.18.1",
4
4
  "description": "Record and share your AI-driven product development journey",
5
5
  "type": "module",
6
6
  "bin": {