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 +1 -0
- package/dist/commands/harness.js +59 -0
- package/dist/index.js +5 -0
- package/dist/lib/config.js +7 -1
- package/dist/lib/harness.js +75 -21
- package/package.json +1 -1
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')
|
package/dist/lib/config.js
CHANGED
|
@@ -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
|
|
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.
|
package/dist/lib/harness.js
CHANGED
|
@@ -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
|
-
|
|
33
|
-
|
|
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
|
-
|
|
43
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
94
|
-
writeFileSync(
|
|
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) {
|