@holdpoint/cli 0.1.0-alpha.2 → 0.1.0-alpha.21
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/dist/chunk-D7ZF5JJH.js +521 -0
- package/dist/chunk-D7ZF5JJH.js.map +1 -0
- package/dist/data/verified-mcp-registry.json +14 -0
- package/dist/index.js +1588 -603
- package/dist/index.js.map +1 -1
- package/dist/init-Y7NZBMU6.js +8 -0
- package/dist/init-Y7NZBMU6.js.map +1 -0
- package/dist/lib/scan.d.ts +20 -0
- package/dist/lib/scan.js +200 -0
- package/dist/lib/scan.js.map +1 -0
- package/dist/prompt-EQ5IFADN.js +23 -0
- package/dist/prompt-EQ5IFADN.js.map +1 -0
- package/dist/templates/HOLDPOINT_PREREQUISITES.md +10 -0
- package/dist/templates/HOLDPOINT_REFERENCE.md +372 -0
- package/dist/templates/MASTER_PROMPT.md +25 -295
- package/dist/templates/default.yaml +274 -0
- package/package.json +16 -14
- package/dist/builder-ui/assets/index-BxfWKnb5.js +0 -437
- package/dist/builder-ui/assets/index-BxfWKnb5.js.map +0 -1
- package/dist/builder-ui/assets/index-DkLHZ-in.css +0 -1
- package/dist/builder-ui/favicon.svg +0 -10
- package/dist/builder-ui/index.html +0 -14
- package/dist/templates/_base.yaml +0 -52
- package/dist/templates/fullstack.yaml +0 -93
- package/dist/templates/go.yaml +0 -60
- package/dist/templates/nextjs.yaml +0 -76
- package/dist/templates/python.yaml +0 -60
- package/dist/templates/typescript.yaml +0 -55
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/init.ts
|
|
4
|
+
import { execSync as execSync2 } from "child_process";
|
|
5
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
6
|
+
import { join as join2, dirname as dirname3 } from "path";
|
|
7
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8
|
+
import chalk2 from "chalk";
|
|
9
|
+
import ora from "ora";
|
|
10
|
+
import { buildConfigJson, buildEngine } from "@holdpoint/engine-copilot";
|
|
11
|
+
import { buildEngineJson as buildClaudeEngineJson } from "@holdpoint/engine-claude";
|
|
12
|
+
import {
|
|
13
|
+
buildCheckScript as buildCursorCheckScript,
|
|
14
|
+
buildEngine as buildCursorEngine,
|
|
15
|
+
buildHooksJson as buildCursorHooksJson
|
|
16
|
+
} from "@holdpoint/engine-cursor";
|
|
17
|
+
import {
|
|
18
|
+
buildConfigToml as buildCodexConfigToml,
|
|
19
|
+
buildHooksJson as buildCodexHooksJson,
|
|
20
|
+
buildCheckScript as buildCodexCheckScript
|
|
21
|
+
} from "@holdpoint/engine-codex";
|
|
22
|
+
import { parseHoldpointYaml } from "@holdpoint/yaml-core";
|
|
23
|
+
|
|
24
|
+
// src/detect.ts
|
|
25
|
+
import { existsSync, readFileSync } from "fs";
|
|
26
|
+
function detectPackageManager() {
|
|
27
|
+
if (existsSync("pnpm-lock.yaml")) return "pnpm";
|
|
28
|
+
if (existsSync("yarn.lock")) return "yarn";
|
|
29
|
+
return "npm";
|
|
30
|
+
}
|
|
31
|
+
function detectInstalledAgents() {
|
|
32
|
+
const agents = [];
|
|
33
|
+
if (existsSync(".github/extensions/holdpoint/extension.mjs")) agents.push("copilot");
|
|
34
|
+
if (existsSync(".claude/settings.json")) agents.push("claude");
|
|
35
|
+
if (existsSync(".cursor/hooks.json")) {
|
|
36
|
+
try {
|
|
37
|
+
if (readFileSync(".cursor/hooks.json", "utf8").includes("HOLDPOINT_MANAGED=cursor")) {
|
|
38
|
+
agents.push("cursor");
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (existsSync(".cursorrules")) {
|
|
44
|
+
try {
|
|
45
|
+
if (!agents.includes("cursor") && readFileSync(".cursorrules", "utf8").includes("Holdpoint Rules")) {
|
|
46
|
+
agents.push("cursor");
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (existsSync(".codex/holdpoint-check.mjs")) agents.push("codex");
|
|
52
|
+
return agents;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/templates.ts
|
|
56
|
+
import { copyFileSync, existsSync as existsSync2, writeFileSync } from "fs";
|
|
57
|
+
import { join, dirname } from "path";
|
|
58
|
+
import { fileURLToPath } from "url";
|
|
59
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
60
|
+
function getBundledTemplatePath(filename) {
|
|
61
|
+
const candidates = [
|
|
62
|
+
join(__dirname, "templates", filename),
|
|
63
|
+
// dist/templates/ (published package)
|
|
64
|
+
join(__dirname, "../../../templates", filename),
|
|
65
|
+
// monorepo dev fallback
|
|
66
|
+
join(process.cwd(), "templates", filename)
|
|
67
|
+
// cwd fallback
|
|
68
|
+
];
|
|
69
|
+
for (const candidate of candidates) {
|
|
70
|
+
if (existsSync2(candidate)) return candidate;
|
|
71
|
+
}
|
|
72
|
+
return "";
|
|
73
|
+
}
|
|
74
|
+
function ensureBundledFile(outputPath, templateFilename, fallbackContent) {
|
|
75
|
+
if (existsSync2(outputPath)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const templatePath = getBundledTemplatePath(templateFilename);
|
|
79
|
+
if (templatePath) {
|
|
80
|
+
copyFileSync(templatePath, outputPath);
|
|
81
|
+
} else {
|
|
82
|
+
writeFileSync(outputPath, fallbackContent, "utf8");
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/lib/preflight.ts
|
|
88
|
+
import { execSync } from "child_process";
|
|
89
|
+
import chalk from "chalk";
|
|
90
|
+
function silentExec(cmd) {
|
|
91
|
+
try {
|
|
92
|
+
const stdout = execSync(cmd, { stdio: ["ignore", "pipe", "ignore"] }).toString();
|
|
93
|
+
return { ok: true, stdout };
|
|
94
|
+
} catch {
|
|
95
|
+
return { ok: false, stdout: "" };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function checkCopilot() {
|
|
99
|
+
const gh = silentExec("gh --version");
|
|
100
|
+
if (!gh.ok) {
|
|
101
|
+
return {
|
|
102
|
+
agent: "copilot",
|
|
103
|
+
status: "action_required",
|
|
104
|
+
message: "GitHub CLI not found on PATH",
|
|
105
|
+
command: "brew install gh # or: https://cli.github.com/"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const copilot = silentExec("gh copilot --version");
|
|
109
|
+
if (!copilot.ok) {
|
|
110
|
+
return {
|
|
111
|
+
agent: "copilot",
|
|
112
|
+
status: "action_required",
|
|
113
|
+
message: "Copilot CLI extension not installed",
|
|
114
|
+
command: "gh extension install github/gh-copilot"
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
agent: "copilot",
|
|
119
|
+
status: "action_required",
|
|
120
|
+
message: "Copilot CLI detected \u2014 experimental mode required for EXTENSIONS",
|
|
121
|
+
command: "Inside Copilot CLI, run: /experimental on"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function checkClaude() {
|
|
125
|
+
const claude = silentExec("claude --version");
|
|
126
|
+
if (!claude.ok) {
|
|
127
|
+
return {
|
|
128
|
+
agent: "claude",
|
|
129
|
+
status: "unknown",
|
|
130
|
+
message: "Claude Code binary not on PATH (hooks still written for when it is)"
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
agent: "claude",
|
|
135
|
+
status: "ok",
|
|
136
|
+
message: "Claude Code detected \u2014 hooks installed at .claude/settings.json"
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function checkCursor() {
|
|
140
|
+
return {
|
|
141
|
+
agent: "cursor",
|
|
142
|
+
status: "ok",
|
|
143
|
+
message: "Cursor \u2014 .cursor/hooks.json gate + .cursor/rules breadcrumb installed",
|
|
144
|
+
docs: "https://holdpoint.dev/docs#cursor"
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function checkCodex() {
|
|
148
|
+
const codex = silentExec("codex --version");
|
|
149
|
+
if (!codex.ok) {
|
|
150
|
+
return {
|
|
151
|
+
agent: "codex",
|
|
152
|
+
status: "action_required",
|
|
153
|
+
message: "Codex CLI not found on PATH",
|
|
154
|
+
command: "Install Codex: https://github.com/openai/codex"
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
agent: "codex",
|
|
159
|
+
status: "action_required",
|
|
160
|
+
message: "Codex detected \u2014 project-level hooks require trust approval",
|
|
161
|
+
command: "In the Codex TUI: codex trust (or /hooks to review)"
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
var CHECKS = {
|
|
165
|
+
copilot: checkCopilot,
|
|
166
|
+
claude: checkClaude,
|
|
167
|
+
cursor: checkCursor,
|
|
168
|
+
codex: checkCodex
|
|
169
|
+
};
|
|
170
|
+
function runPreflight(agents) {
|
|
171
|
+
return agents.flatMap((agent) => {
|
|
172
|
+
const check = CHECKS[agent];
|
|
173
|
+
return check ? [check()] : [];
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function printPreflight(results) {
|
|
177
|
+
if (results.length === 0) return;
|
|
178
|
+
const ok = results.filter((r) => r.status === "ok");
|
|
179
|
+
const unknown = results.filter((r) => r.status === "unknown");
|
|
180
|
+
const action = results.filter((r) => r.status === "action_required");
|
|
181
|
+
console.log("");
|
|
182
|
+
console.log(chalk.bold("Agent preflight:"));
|
|
183
|
+
for (const r of ok) {
|
|
184
|
+
console.log(` ${chalk.green("\u2713")} ${r.agent.padEnd(7)} ${chalk.dim(r.message)}`);
|
|
185
|
+
}
|
|
186
|
+
for (const r of unknown) {
|
|
187
|
+
console.log(` ${chalk.dim("?")} ${r.agent.padEnd(7)} ${chalk.dim(r.message)}`);
|
|
188
|
+
}
|
|
189
|
+
for (const r of action) {
|
|
190
|
+
console.log(` ${chalk.yellow("\u2192")} ${chalk.bold(r.agent.padEnd(7))} ${r.message}`);
|
|
191
|
+
if (r.command) console.log(` ${chalk.cyan(r.command)}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/claude-settings.ts
|
|
196
|
+
var HOLDPOINT_CLAUDE_HOOK_MARKER = "HOLDPOINT_MANAGED=claude";
|
|
197
|
+
function isObject(value) {
|
|
198
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
199
|
+
}
|
|
200
|
+
function asHookArray(value) {
|
|
201
|
+
return Array.isArray(value) ? value : [];
|
|
202
|
+
}
|
|
203
|
+
function isManagedHookCommand(value) {
|
|
204
|
+
return isObject(value) && typeof value.command === "string" && value.command.includes(HOLDPOINT_CLAUDE_HOOK_MARKER);
|
|
205
|
+
}
|
|
206
|
+
function isLegacyManagedHookCommand(value) {
|
|
207
|
+
if (!isObject(value) || typeof value.command !== "string") return false;
|
|
208
|
+
return value.command === "node_modules/.bin/holdpoint event --engine claude --from-hook || true" || value.command === "node_modules/.bin/holdpoint check --staged";
|
|
209
|
+
}
|
|
210
|
+
function isManagedHookEntry(value) {
|
|
211
|
+
if (!isObject(value)) return false;
|
|
212
|
+
const hooks = asHookArray(value.hooks);
|
|
213
|
+
return hooks.length > 0 && (hooks.every(isManagedHookCommand) || hooks.every(isLegacyManagedHookCommand));
|
|
214
|
+
}
|
|
215
|
+
function mergeClaudeSettings(existing, generated) {
|
|
216
|
+
const existingHooks = isObject(existing.hooks) ? existing.hooks : {};
|
|
217
|
+
const generatedHooks = isObject(generated.hooks) ? generated.hooks : {};
|
|
218
|
+
const mergedHooks = {};
|
|
219
|
+
for (const eventName of /* @__PURE__ */ new Set([
|
|
220
|
+
...Object.keys(existingHooks),
|
|
221
|
+
...Object.keys(generatedHooks)
|
|
222
|
+
])) {
|
|
223
|
+
const preserved = asHookArray(existingHooks[eventName]).filter(
|
|
224
|
+
(entry) => !isManagedHookEntry(entry)
|
|
225
|
+
);
|
|
226
|
+
const next = asHookArray(generatedHooks[eventName]);
|
|
227
|
+
if (preserved.length > 0 || next.length > 0) {
|
|
228
|
+
mergedHooks[eventName] = [...preserved, ...next];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return { ...existing, ...generated, hooks: mergedHooks };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/cursor-hooks.ts
|
|
235
|
+
var HOLDPOINT_CURSOR_HOOK_MARKER = "HOLDPOINT_MANAGED=cursor";
|
|
236
|
+
function isObject2(value) {
|
|
237
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
238
|
+
}
|
|
239
|
+
function asHookArray2(value) {
|
|
240
|
+
return Array.isArray(value) ? value : [];
|
|
241
|
+
}
|
|
242
|
+
function isManagedCursorHook(value) {
|
|
243
|
+
return isObject2(value) && typeof value.command === "string" && (value.command.includes(HOLDPOINT_CURSOR_HOOK_MARKER) || value.command.includes(".cursor/holdpoint-hook.mjs"));
|
|
244
|
+
}
|
|
245
|
+
function mergeCursorHooks(existing, generated) {
|
|
246
|
+
const existingHooks = isObject2(existing.hooks) ? existing.hooks : {};
|
|
247
|
+
const generatedHooks = isObject2(generated.hooks) ? generated.hooks : {};
|
|
248
|
+
const mergedHooks = {};
|
|
249
|
+
for (const eventName of /* @__PURE__ */ new Set([
|
|
250
|
+
...Object.keys(existingHooks),
|
|
251
|
+
...Object.keys(generatedHooks)
|
|
252
|
+
])) {
|
|
253
|
+
const preserved = asHookArray2(existingHooks[eventName]).filter(
|
|
254
|
+
(entry) => !isManagedCursorHook(entry)
|
|
255
|
+
);
|
|
256
|
+
const next = asHookArray2(generatedHooks[eventName]);
|
|
257
|
+
if (preserved.length > 0 || next.length > 0) {
|
|
258
|
+
mergedHooks[eventName] = [...preserved, ...next];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return { ...existing, ...generated, hooks: mergedHooks };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/lib/instructions-breadcrumb.ts
|
|
265
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync } from "fs";
|
|
266
|
+
import { dirname as dirname2 } from "path";
|
|
267
|
+
var START_MARKER = "<!-- HOLDPOINT_MANAGED \u2014 content between these markers is auto-generated by holdpoint init / holdpoint update -->";
|
|
268
|
+
var END_MARKER = "<!-- /HOLDPOINT_MANAGED -->";
|
|
269
|
+
var BREADCRUMB_BODY = `## Holdpoint workflow
|
|
270
|
+
|
|
271
|
+
This repo uses [Holdpoint](https://holdpoint.dev) to gate task completion on deterministic checks.
|
|
272
|
+
|
|
273
|
+
Before marking any task done:
|
|
274
|
+
|
|
275
|
+
1. Run \`holdpoint check\` (or it will run automatically via Stop / TaskCompleted hooks).
|
|
276
|
+
2. Fix any failures. Re-run until exit 0.
|
|
277
|
+
3. Never bypass with \`--no-verify\` or by skipping the agent's stop hook.
|
|
278
|
+
|
|
279
|
+
Full workflow reference: [\`MASTER_PROMPT.md\`](./MASTER_PROMPT.md) (always injected at session start).
|
|
280
|
+
Deep reference: [\`HOLDPOINT_REFERENCE.md\`](./HOLDPOINT_REFERENCE.md) (read on demand).
|
|
281
|
+
Active checks: [\`checks.yaml\`](./checks.yaml).`;
|
|
282
|
+
function spliceBreadcrumb(filePath, body = BREADCRUMB_BODY, createIfMissing = true) {
|
|
283
|
+
const block = `${START_MARKER}
|
|
284
|
+
|
|
285
|
+
${body}
|
|
286
|
+
|
|
287
|
+
${END_MARKER}`;
|
|
288
|
+
if (!existsSync3(filePath)) {
|
|
289
|
+
if (!createIfMissing) return;
|
|
290
|
+
mkdirSync(dirname2(filePath), { recursive: true });
|
|
291
|
+
writeFileSync2(filePath, block + "\n", "utf8");
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const existing = readFileSync2(filePath, "utf8");
|
|
295
|
+
const startIdx = existing.indexOf(START_MARKER);
|
|
296
|
+
const endIdx = existing.indexOf(END_MARKER);
|
|
297
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
298
|
+
const before = existing.slice(0, startIdx);
|
|
299
|
+
const after = existing.slice(endIdx + END_MARKER.length);
|
|
300
|
+
writeFileSync2(filePath, before + block + after, "utf8");
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const sep = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
304
|
+
writeFileSync2(filePath, existing + sep + block + "\n", "utf8");
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/commands/init.ts
|
|
308
|
+
var __dirname2 = dirname3(fileURLToPath2(import.meta.url));
|
|
309
|
+
function getDefaultTemplatePath() {
|
|
310
|
+
const candidates = [
|
|
311
|
+
join2(__dirname2, "templates", "default.yaml"),
|
|
312
|
+
// dist/templates/ (published package)
|
|
313
|
+
join2(__dirname2, "../../../templates", "default.yaml"),
|
|
314
|
+
// monorepo dev fallback
|
|
315
|
+
join2(process.cwd(), "templates", "default.yaml")
|
|
316
|
+
// cwd fallback
|
|
317
|
+
];
|
|
318
|
+
for (const p of candidates) {
|
|
319
|
+
if (existsSync4(p)) return p;
|
|
320
|
+
}
|
|
321
|
+
return "";
|
|
322
|
+
}
|
|
323
|
+
var MINIMAL_CHECKS_YAML = `version: 1
|
|
324
|
+
context:
|
|
325
|
+
guides: {}
|
|
326
|
+
conditions: []
|
|
327
|
+
checks:
|
|
328
|
+
- id: karpathy-practices
|
|
329
|
+
label: "Karpathy coding practices"
|
|
330
|
+
on: session_start
|
|
331
|
+
inject:
|
|
332
|
+
text: |
|
|
333
|
+
## Coding practices (enforced by Holdpoint)
|
|
334
|
+
|
|
335
|
+
1. Read all relevant files fully before making any change.
|
|
336
|
+
2. Make the smallest change that satisfies the task. No unsolicited refactors.
|
|
337
|
+
3. Edit existing code surgically. Do not rewrite what you were not asked to rewrite.
|
|
338
|
+
4. Do not add logging, tests, types, or abstractions that were not asked for.
|
|
339
|
+
5. If a test suite exists, it must pass before you stop.
|
|
340
|
+
6. Complete exactly what was asked. Log adjacent issues as TO${"DO"}s, don't fix them.
|
|
341
|
+
|
|
342
|
+
- id: check-test-suite
|
|
343
|
+
label: "Test suite passes"
|
|
344
|
+
on: before_done
|
|
345
|
+
prompt: "If this project has a test suite (package.json test script, pytest, go test, etc.), confirm it passes. If you did not run it, run it now before finishing."
|
|
346
|
+
|
|
347
|
+
- id: check-minimal-change
|
|
348
|
+
label: "Change is minimal and scoped"
|
|
349
|
+
on: before_done
|
|
350
|
+
prompt: "Review every file you changed. Remove any addition that was not explicitly requested \u2014 unused imports, debug logs, reformatted blocks, unrequested refactors. Confirm the diff is surgical."
|
|
351
|
+
|
|
352
|
+
- id: lint
|
|
353
|
+
label: "Lint codebase"
|
|
354
|
+
cmd: "echo 'Add your lint command here'"
|
|
355
|
+
|
|
356
|
+
- id: jsdoc
|
|
357
|
+
label: "JSDoc on changed public functions"
|
|
358
|
+
prompt: "Ensure all changed public functions and exports have JSDoc comments."
|
|
359
|
+
`;
|
|
360
|
+
var MINIMAL_MASTER_PROMPT = `# Holdpoint
|
|
361
|
+
|
|
362
|
+
Run \`holdpoint check\` before marking any task complete.
|
|
363
|
+
See \`checks.yaml\` for the full list of checks.
|
|
364
|
+
`;
|
|
365
|
+
var MINIMAL_HOLDPOINT_REFERENCE = `# Holdpoint reference
|
|
366
|
+
|
|
367
|
+
Read \`MASTER_PROMPT.md\` first for the mandatory workflow, then use this file for deeper project-specific Holdpoint notes.
|
|
368
|
+
`;
|
|
369
|
+
var MINIMAL_PREREQUISITES = `# Holdpoint prerequisites
|
|
370
|
+
|
|
371
|
+
Holdpoint installed repo-local engine integrations for one or more AI coding agents. Before relying on them locally, review these setup notes:
|
|
372
|
+
|
|
373
|
+
- **GitHub Copilot CLI** \u2014 Holdpoint's \`.github/extensions/holdpoint/extension.mjs\` uses the Copilot CLI **EXTENSIONS** feature. Today that feature is gated behind experimental mode. In Copilot CLI, run \`/experimental on\` so **EXTENSIONS** appears in the enabled feature set before using Holdpoint locally.
|
|
374
|
+
- **Cursor** \u2014 project-level hooks run in trusted workspaces. After opening the repo in Cursor, confirm the workspace is trusted and review Settings \u2192 Hooks if hooks do not fire.
|
|
375
|
+
- **OpenAI Codex** \u2014 project-level hooks require trust approval. Run \`codex trust\` in the Codex TUI or review the hook with \`/hooks\`.
|
|
376
|
+
- **General** \u2014 Holdpoint expects Node.js 18+ and a git repository so \`holdpoint init\`, \`holdpoint update\`, and \`holdpoint check\` can run normally.
|
|
377
|
+
|
|
378
|
+
Docs: https://holdpoint.dev/docs
|
|
379
|
+
`;
|
|
380
|
+
async function initCommand(options) {
|
|
381
|
+
const spinner = ora("Initialising Holdpoint\u2026").start();
|
|
382
|
+
const agentOpt = options.agent;
|
|
383
|
+
const agents = !agentOpt || agentOpt === "all" ? ["copilot", "claude", "cursor", "codex"] : [agentOpt];
|
|
384
|
+
spinner.text = `Installing for: ${chalk2.cyan(agents.join(", "))}`;
|
|
385
|
+
const pm = detectPackageManager();
|
|
386
|
+
let yamlContent = MINIMAL_CHECKS_YAML;
|
|
387
|
+
if (!existsSync4("checks.yaml")) {
|
|
388
|
+
const templatePath = getDefaultTemplatePath();
|
|
389
|
+
if (templatePath) {
|
|
390
|
+
yamlContent = readFileSync3(templatePath, "utf8");
|
|
391
|
+
}
|
|
392
|
+
if (pm !== "pnpm") {
|
|
393
|
+
yamlContent = yamlContent.replace(/\bpnpm\b/g, pm);
|
|
394
|
+
}
|
|
395
|
+
writeFileSync3("checks.yaml", yamlContent, "utf8");
|
|
396
|
+
} else {
|
|
397
|
+
yamlContent = readFileSync3("checks.yaml", "utf8");
|
|
398
|
+
}
|
|
399
|
+
const config = parseHoldpointYaml(yamlContent);
|
|
400
|
+
const generatedDir = ".github/holdpoint/generated";
|
|
401
|
+
mkdirSync2(generatedDir, { recursive: true });
|
|
402
|
+
writeFileSync3(`${generatedDir}/checks.immutable.json`, buildConfigJson(config), "utf8");
|
|
403
|
+
if (agents.includes("copilot")) {
|
|
404
|
+
const extDir = ".github/extensions/holdpoint";
|
|
405
|
+
mkdirSync2(extDir, { recursive: true });
|
|
406
|
+
writeFileSync3(join2(extDir, "extension.mjs"), buildEngine(config), "utf8");
|
|
407
|
+
spliceBreadcrumb(".github/copilot-instructions.md");
|
|
408
|
+
}
|
|
409
|
+
if (agents.includes("claude")) {
|
|
410
|
+
mkdirSync2(".claude", { recursive: true });
|
|
411
|
+
const settingsPath = ".claude/settings.json";
|
|
412
|
+
let existing = {};
|
|
413
|
+
if (existsSync4(settingsPath)) {
|
|
414
|
+
try {
|
|
415
|
+
existing = JSON.parse(readFileSync3(settingsPath, "utf8"));
|
|
416
|
+
} catch {
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const holdpointHooks = JSON.parse(buildClaudeEngineJson(config));
|
|
420
|
+
writeFileSync3(
|
|
421
|
+
settingsPath,
|
|
422
|
+
JSON.stringify(mergeClaudeSettings(existing, holdpointHooks), null, 2),
|
|
423
|
+
"utf8"
|
|
424
|
+
);
|
|
425
|
+
spliceBreadcrumb("CLAUDE.md");
|
|
426
|
+
}
|
|
427
|
+
if (agents.includes("cursor")) {
|
|
428
|
+
mkdirSync2(".cursor", { recursive: true });
|
|
429
|
+
const cursorHooksPath = ".cursor/hooks.json";
|
|
430
|
+
let existingHooks = {};
|
|
431
|
+
if (existsSync4(cursorHooksPath)) {
|
|
432
|
+
try {
|
|
433
|
+
existingHooks = JSON.parse(readFileSync3(cursorHooksPath, "utf8"));
|
|
434
|
+
} catch {
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
const cursorHooks = JSON.parse(buildCursorHooksJson(config));
|
|
438
|
+
writeFileSync3(
|
|
439
|
+
cursorHooksPath,
|
|
440
|
+
JSON.stringify(mergeCursorHooks(existingHooks, cursorHooks), null, 2) + "\n",
|
|
441
|
+
"utf8"
|
|
442
|
+
);
|
|
443
|
+
writeFileSync3(".cursor/holdpoint-hook.mjs", buildCursorCheckScript(), "utf8");
|
|
444
|
+
const cursorRules = buildCursorEngine(config);
|
|
445
|
+
const cursorPath = ".cursorrules";
|
|
446
|
+
if (existsSync4(cursorPath)) {
|
|
447
|
+
const existing = readFileSync3(cursorPath, "utf8");
|
|
448
|
+
if (!existing.includes("Holdpoint Rules")) {
|
|
449
|
+
writeFileSync3(cursorPath, `${existing.trimEnd()}
|
|
450
|
+
|
|
451
|
+
${cursorRules}`, "utf8");
|
|
452
|
+
}
|
|
453
|
+
} else {
|
|
454
|
+
writeFileSync3(cursorPath, cursorRules, "utf8");
|
|
455
|
+
}
|
|
456
|
+
spliceBreadcrumb(".cursor/rules/holdpoint.md");
|
|
457
|
+
}
|
|
458
|
+
if (agents.includes("codex")) {
|
|
459
|
+
mkdirSync2(".codex", { recursive: true });
|
|
460
|
+
writeFileSync3(".codex/hooks.json", buildCodexHooksJson(config), "utf8");
|
|
461
|
+
writeFileSync3(".codex/holdpoint-check.mjs", buildCodexCheckScript(config), "utf8");
|
|
462
|
+
writeFileSync3(".codex/config.toml", buildCodexConfigToml(), "utf8");
|
|
463
|
+
spliceBreadcrumb("AGENTS.md");
|
|
464
|
+
}
|
|
465
|
+
ensureBundledFile("MASTER_PROMPT.md", "MASTER_PROMPT.md", MINIMAL_MASTER_PROMPT);
|
|
466
|
+
ensureBundledFile(
|
|
467
|
+
"HOLDPOINT_REFERENCE.md",
|
|
468
|
+
"HOLDPOINT_REFERENCE.md",
|
|
469
|
+
MINIMAL_HOLDPOINT_REFERENCE
|
|
470
|
+
);
|
|
471
|
+
ensureBundledFile(
|
|
472
|
+
"HOLDPOINT_PREREQUISITES.md",
|
|
473
|
+
"HOLDPOINT_PREREQUISITES.md",
|
|
474
|
+
MINIMAL_PREREQUISITES
|
|
475
|
+
);
|
|
476
|
+
spinner.text = "Installing holdpoint as a devDependency\u2026";
|
|
477
|
+
const installCmds = {
|
|
478
|
+
pnpm: "pnpm add -D holdpoint",
|
|
479
|
+
yarn: "yarn add --dev holdpoint",
|
|
480
|
+
npm: "npm install --save-dev holdpoint"
|
|
481
|
+
};
|
|
482
|
+
const installCmd = installCmds[pm];
|
|
483
|
+
try {
|
|
484
|
+
execSync2(installCmd, { stdio: "pipe" });
|
|
485
|
+
spinner.succeed(chalk2.bold.green("Holdpoint initialised!"));
|
|
486
|
+
} catch {
|
|
487
|
+
spinner.warn(
|
|
488
|
+
chalk2.yellow(`Holdpoint initialised, but could not install the package automatically.`) + `
|
|
489
|
+
Run manually: ${chalk2.yellow(installCmd)}`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
const preflight = runPreflight(agents);
|
|
493
|
+
printPreflight(preflight);
|
|
494
|
+
let holdpointInvocation = "npx holdpoint";
|
|
495
|
+
try {
|
|
496
|
+
execSync2("command -v holdpoint", { stdio: "pipe" });
|
|
497
|
+
holdpointInvocation = "holdpoint";
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
console.log(`
|
|
501
|
+
${chalk2.cyan("Next steps:")}
|
|
502
|
+
Karpathy coding practices are active via ${chalk2.yellow("checks.yaml")}
|
|
503
|
+
1. Edit ${chalk2.yellow("checks.yaml")} to customise your eval checkpoints
|
|
504
|
+
2. Address any ${chalk2.yellow("\u2192")} items above (full notes in ${chalk2.yellow("HOLDPOINT_PREREQUISITES.md")})
|
|
505
|
+
3. Commit ${chalk2.yellow("checks.yaml")}, ${chalk2.yellow("HOLDPOINT_PREREQUISITES.md")}, and the generated engine files
|
|
506
|
+
4. Run ${chalk2.yellow(holdpointInvocation)} ${chalk2.yellow("check")} at any time to validate
|
|
507
|
+
|
|
508
|
+
Visual builder: ${chalk2.yellow(holdpointInvocation + " builder")} (opens the daemon at /builder)
|
|
509
|
+
Agents: ${chalk2.cyan(agents.join(", "))}
|
|
510
|
+
`);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export {
|
|
514
|
+
detectInstalledAgents,
|
|
515
|
+
ensureBundledFile,
|
|
516
|
+
mergeClaudeSettings,
|
|
517
|
+
mergeCursorHooks,
|
|
518
|
+
spliceBreadcrumb,
|
|
519
|
+
initCommand
|
|
520
|
+
};
|
|
521
|
+
//# sourceMappingURL=chunk-D7ZF5JJH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/init.ts","../src/detect.ts","../src/templates.ts","../src/lib/preflight.ts","../src/claude-settings.ts","../src/cursor-hooks.ts","../src/lib/instructions-breadcrumb.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { buildConfigJson, buildEngine } from \"@holdpoint/engine-copilot\";\nimport { buildEngineJson as buildClaudeEngineJson } from \"@holdpoint/engine-claude\";\nimport {\n buildCheckScript as buildCursorCheckScript,\n buildEngine as buildCursorEngine,\n buildHooksJson as buildCursorHooksJson,\n} from \"@holdpoint/engine-cursor\";\nimport {\n buildConfigToml as buildCodexConfigToml,\n buildHooksJson as buildCodexHooksJson,\n buildCheckScript as buildCodexCheckScript,\n} from \"@holdpoint/engine-codex\";\nimport { parseHoldpointYaml } from \"@holdpoint/yaml-core\";\nimport type { AgentType } from \"@holdpoint/types\";\nimport { detectPackageManager, type PackageManager } from \"../detect.js\";\nimport { ensureBundledFile } from \"../templates.js\";\nimport { runPreflight, printPreflight } from \"../lib/preflight.js\";\nimport { mergeClaudeSettings } from \"../claude-settings.js\";\nimport { mergeCursorHooks } from \"../cursor-hooks.js\";\nimport { spliceBreadcrumb } from \"../lib/instructions-breadcrumb.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction getDefaultTemplatePath(): string {\n const candidates = [\n join(__dirname, \"templates\", \"default.yaml\"), // dist/templates/ (published package)\n join(__dirname, \"../../../templates\", \"default.yaml\"), // monorepo dev fallback\n join(process.cwd(), \"templates\", \"default.yaml\"), // cwd fallback\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return \"\";\n}\n\nconst MINIMAL_CHECKS_YAML = `version: 1\ncontext:\n guides: {}\nconditions: []\nchecks:\n - id: karpathy-practices\n label: \"Karpathy coding practices\"\n on: session_start\n inject:\n text: |\n ## Coding practices (enforced by Holdpoint)\n\n 1. Read all relevant files fully before making any change.\n 2. Make the smallest change that satisfies the task. No unsolicited refactors.\n 3. Edit existing code surgically. Do not rewrite what you were not asked to rewrite.\n 4. Do not add logging, tests, types, or abstractions that were not asked for.\n 5. If a test suite exists, it must pass before you stop.\n 6. Complete exactly what was asked. Log adjacent issues as TO${\"DO\"}s, don't fix them.\n\n - id: check-test-suite\n label: \"Test suite passes\"\n on: before_done\n prompt: \"If this project has a test suite (package.json test script, pytest, go test, etc.), confirm it passes. If you did not run it, run it now before finishing.\"\n\n - id: check-minimal-change\n label: \"Change is minimal and scoped\"\n on: before_done\n prompt: \"Review every file you changed. Remove any addition that was not explicitly requested — unused imports, debug logs, reformatted blocks, unrequested refactors. Confirm the diff is surgical.\"\n\n - id: lint\n label: \"Lint codebase\"\n cmd: \"echo 'Add your lint command here'\"\n\n - id: jsdoc\n label: \"JSDoc on changed public functions\"\n prompt: \"Ensure all changed public functions and exports have JSDoc comments.\"\n`;\n\nconst MINIMAL_MASTER_PROMPT = `# Holdpoint\n\nRun \\`holdpoint check\\` before marking any task complete.\nSee \\`checks.yaml\\` for the full list of checks.\n`;\n\nconst MINIMAL_HOLDPOINT_REFERENCE = `# Holdpoint reference\n\nRead \\`MASTER_PROMPT.md\\` first for the mandatory workflow, then use this file for deeper project-specific Holdpoint notes.\n`;\n\nconst MINIMAL_PREREQUISITES = `# Holdpoint prerequisites\n\nHoldpoint installed repo-local engine integrations for one or more AI coding agents. Before relying on them locally, review these setup notes:\n\n- **GitHub Copilot CLI** — Holdpoint's \\`.github/extensions/holdpoint/extension.mjs\\` uses the Copilot CLI **EXTENSIONS** feature. Today that feature is gated behind experimental mode. In Copilot CLI, run \\`/experimental on\\` so **EXTENSIONS** appears in the enabled feature set before using Holdpoint locally.\n- **Cursor** — project-level hooks run in trusted workspaces. After opening the repo in Cursor, confirm the workspace is trusted and review Settings → Hooks if hooks do not fire.\n- **OpenAI Codex** — project-level hooks require trust approval. Run \\`codex trust\\` in the Codex TUI or review the hook with \\`/hooks\\`.\n- **General** — Holdpoint expects Node.js 18+ and a git repository so \\`holdpoint init\\`, \\`holdpoint update\\`, and \\`holdpoint check\\` can run normally.\n\nDocs: https://holdpoint.dev/docs\n`;\n\n/**\n * Initialise Holdpoint in the current project.\n *\n * Writes `checks.yaml` (from the unified default template), `checks.immutable.json`,\n * engine files for each target agent (Copilot, Claude, Cursor, Codex),\n * and repo-local handoff docs such as `HOLDPOINT_PREREQUISITES.md`.\n * Defaults to installing all four agents; pass `--agent` to restrict to one.\n */\nexport async function initCommand(options: { agent?: string }): Promise<void> {\n const spinner = ora(\"Initialising Holdpoint…\").start();\n\n // Default: install for all agents. Pass --agent=copilot|claude|cursor to restrict.\n const agentOpt = options.agent;\n const agents: AgentType[] =\n !agentOpt || agentOpt === \"all\"\n ? [\"copilot\", \"claude\", \"cursor\", \"codex\"]\n : [agentOpt as AgentType];\n\n spinner.text = `Installing for: ${chalk.cyan(agents.join(\", \"))}`;\n\n // Detect package manager once — used both for template substitution and devDep install.\n const pm = detectPackageManager();\n\n // 1. Read or create checks.yaml\n let yamlContent = MINIMAL_CHECKS_YAML;\n if (!existsSync(\"checks.yaml\")) {\n const templatePath = getDefaultTemplatePath();\n if (templatePath) {\n yamlContent = readFileSync(templatePath, \"utf8\");\n }\n // Substitute the package manager so checks use the right runner (npm/yarn/pnpm).\n if (pm !== \"pnpm\") {\n yamlContent = yamlContent.replace(/\\bpnpm\\b/g, pm);\n }\n writeFileSync(\"checks.yaml\", yamlContent, \"utf8\");\n } else {\n yamlContent = readFileSync(\"checks.yaml\", \"utf8\");\n }\n\n const config = parseHoldpointYaml(yamlContent);\n\n // 2. Write checks.immutable.json — read by holdpoint-check.mjs at runtime\n const generatedDir = \".github/holdpoint/generated\";\n mkdirSync(generatedDir, { recursive: true });\n writeFileSync(`${generatedDir}/checks.immutable.json`, buildConfigJson(config), \"utf8\");\n\n // 3. Install engine files for each target agent\n if (agents.includes(\"copilot\")) {\n // extension.mjs handles both session context injection (onSessionStart) and\n // check enforcement (onPreToolUse → task_complete). No separate hooks files needed.\n const extDir = \".github/extensions/holdpoint\";\n mkdirSync(extDir, { recursive: true });\n writeFileSync(join(extDir, \"extension.mjs\"), buildEngine(config), \"utf8\");\n spliceBreadcrumb(\".github/copilot-instructions.md\");\n }\n\n if (agents.includes(\"claude\")) {\n mkdirSync(\".claude\", { recursive: true });\n const settingsPath = \".claude/settings.json\";\n let existing: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<string, unknown>;\n } catch {\n /* ignore */\n }\n }\n const holdpointHooks = JSON.parse(buildClaudeEngineJson(config)) as Record<string, unknown>;\n writeFileSync(\n settingsPath,\n JSON.stringify(mergeClaudeSettings(existing, holdpointHooks), null, 2),\n \"utf8\",\n );\n spliceBreadcrumb(\"CLAUDE.md\");\n }\n\n if (agents.includes(\"cursor\")) {\n mkdirSync(\".cursor\", { recursive: true });\n const cursorHooksPath = \".cursor/hooks.json\";\n let existingHooks: Record<string, unknown> = {};\n if (existsSync(cursorHooksPath)) {\n try {\n existingHooks = JSON.parse(readFileSync(cursorHooksPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n /* ignore */\n }\n }\n const cursorHooks = JSON.parse(buildCursorHooksJson(config)) as Record<string, unknown>;\n writeFileSync(\n cursorHooksPath,\n JSON.stringify(mergeCursorHooks(existingHooks, cursorHooks), null, 2) + \"\\n\",\n \"utf8\",\n );\n writeFileSync(\".cursor/holdpoint-hook.mjs\", buildCursorCheckScript(), \"utf8\");\n\n const cursorRules = buildCursorEngine(config);\n const cursorPath = \".cursorrules\";\n if (existsSync(cursorPath)) {\n const existing = readFileSync(cursorPath, \"utf8\");\n if (!existing.includes(\"Holdpoint Rules\")) {\n writeFileSync(cursorPath, `${existing.trimEnd()}\\n\\n${cursorRules}`, \"utf8\");\n }\n } else {\n writeFileSync(cursorPath, cursorRules, \"utf8\");\n }\n spliceBreadcrumb(\".cursor/rules/holdpoint.md\");\n }\n\n if (agents.includes(\"codex\")) {\n mkdirSync(\".codex\", { recursive: true });\n writeFileSync(\".codex/hooks.json\", buildCodexHooksJson(config), \"utf8\");\n writeFileSync(\".codex/holdpoint-check.mjs\", buildCodexCheckScript(config), \"utf8\");\n writeFileSync(\".codex/config.toml\", buildCodexConfigToml(), \"utf8\");\n spliceBreadcrumb(\"AGENTS.md\");\n }\n\n // 4. Create repo-local guidance files if not present\n ensureBundledFile(\"MASTER_PROMPT.md\", \"MASTER_PROMPT.md\", MINIMAL_MASTER_PROMPT);\n ensureBundledFile(\n \"HOLDPOINT_REFERENCE.md\",\n \"HOLDPOINT_REFERENCE.md\",\n MINIMAL_HOLDPOINT_REFERENCE,\n );\n ensureBundledFile(\n \"HOLDPOINT_PREREQUISITES.md\",\n \"HOLDPOINT_PREREQUISITES.md\",\n MINIMAL_PREREQUISITES,\n );\n\n // Install holdpoint as a devDependency so hooks resolve via node_modules/.bin\n // rather than downloading on every hook fire via npx.\n spinner.text = \"Installing holdpoint as a devDependency…\";\n const installCmds: Record<PackageManager, string> = {\n pnpm: \"pnpm add -D holdpoint\",\n yarn: \"yarn add --dev holdpoint\",\n npm: \"npm install --save-dev holdpoint\",\n };\n const installCmd = installCmds[pm];\n try {\n execSync(installCmd, { stdio: \"pipe\" });\n spinner.succeed(chalk.bold.green(\"Holdpoint initialised!\"));\n } catch {\n spinner.warn(\n chalk.yellow(`Holdpoint initialised, but could not install the package automatically.`) +\n `\\n Run manually: ${chalk.yellow(installCmd)}`,\n );\n }\n\n // Per-agent preflight: surface the Copilot `/experimental on` step and Codex\n // `codex trust` step at install time.\n // instead of burying them in HOLDPOINT_PREREQUISITES.md where users\n // routinely miss them.\n const preflight = runPreflight(agents);\n printPreflight(preflight);\n\n // If `holdpoint` is already on PATH (typically because the user has the\n // global install), use the bare command. Otherwise fall back to `npx\n // holdpoint` so the suggested commands actually work for users who only\n // have the local devDep.\n let holdpointInvocation = \"npx holdpoint\";\n try {\n execSync(\"command -v holdpoint\", { stdio: \"pipe\" });\n holdpointInvocation = \"holdpoint\";\n } catch {\n // not on PATH — keep the npx fallback\n }\n\n console.log(`\n${chalk.cyan(\"Next steps:\")}\n Karpathy coding practices are active via ${chalk.yellow(\"checks.yaml\")}\n 1. Edit ${chalk.yellow(\"checks.yaml\")} to customise your eval checkpoints\n 2. Address any ${chalk.yellow(\"→\")} items above (full notes in ${chalk.yellow(\"HOLDPOINT_PREREQUISITES.md\")})\n 3. Commit ${chalk.yellow(\"checks.yaml\")}, ${chalk.yellow(\"HOLDPOINT_PREREQUISITES.md\")}, and the generated engine files\n 4. Run ${chalk.yellow(holdpointInvocation)} ${chalk.yellow(\"check\")} at any time to validate\n\n Visual builder: ${chalk.yellow(holdpointInvocation + \" builder\")} (opens the daemon at /builder)\n Agents: ${chalk.cyan(agents.join(\", \"))}\n`);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AgentType } from \"@holdpoint/types\";\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"npm\";\n\n/** Detect which package manager owns the current project by checking lock files. */\nexport function detectPackageManager(): PackageManager {\n if (existsSync(\"pnpm-lock.yaml\")) return \"pnpm\";\n if (existsSync(\"yarn.lock\")) return \"yarn\";\n return \"npm\";\n}\n\n/** @deprecated Use detectInstalledAgents() — single-agent detection is no longer the default. */\nexport function detectAgent(): AgentType {\n if (existsSync(\".github/extensions\")) return \"copilot\";\n if (existsSync(\".claude\")) return \"claude\";\n if (existsSync(\".cursor/hooks.json\")) return \"cursor\";\n if (existsSync(\".cursorrules\")) return \"cursor\";\n if (existsSync(\".codex\")) return \"codex\";\n return \"unknown\";\n}\n\n/**\n * Returns every agent whose Holdpoint engine files are already present in the\n * current working directory. Used by `holdpoint update` so it regenerates only\n * the engines that were previously installed.\n */\nexport function detectInstalledAgents(): AgentType[] {\n const agents: AgentType[] = [];\n if (existsSync(\".github/extensions/holdpoint/extension.mjs\")) agents.push(\"copilot\");\n if (existsSync(\".claude/settings.json\")) agents.push(\"claude\");\n if (existsSync(\".cursor/hooks.json\")) {\n try {\n if (readFileSync(\".cursor/hooks.json\", \"utf8\").includes(\"HOLDPOINT_MANAGED=cursor\")) {\n agents.push(\"cursor\");\n }\n } catch {\n /* ignore unreadable file */\n }\n }\n if (existsSync(\".cursorrules\")) {\n try {\n if (\n !agents.includes(\"cursor\") &&\n readFileSync(\".cursorrules\", \"utf8\").includes(\"Holdpoint Rules\")\n ) {\n agents.push(\"cursor\");\n }\n } catch {\n /* ignore unreadable file */\n }\n }\n // Detect Codex by the generated check script (more specific than .codex/ existence)\n if (existsSync(\".codex/holdpoint-check.mjs\")) agents.push(\"codex\");\n return agents;\n}\n","import { copyFileSync, existsSync, writeFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport function getBundledTemplatePath(filename: string): string {\n const candidates = [\n join(__dirname, \"templates\", filename), // dist/templates/ (published package)\n join(__dirname, \"../../../templates\", filename), // monorepo dev fallback\n join(process.cwd(), \"templates\", filename), // cwd fallback\n ];\n for (const candidate of candidates) {\n if (existsSync(candidate)) return candidate;\n }\n return \"\";\n}\n\nexport function ensureBundledFile(\n outputPath: string,\n templateFilename: string,\n fallbackContent: string,\n): boolean {\n if (existsSync(outputPath)) {\n return false;\n }\n\n const templatePath = getBundledTemplatePath(templateFilename);\n if (templatePath) {\n copyFileSync(templatePath, outputPath);\n } else {\n writeFileSync(outputPath, fallbackContent, \"utf8\");\n }\n\n return true;\n}\n","import { execSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport type { AgentType } from \"@holdpoint/types\";\n\n/**\n * Result of a single preflight check for one agent.\n *\n * - `ok`: the agent's toolchain is detected and ready to use.\n * - `action_required`: we can be specific about something the user must do\n * (install a tool, enable a feature, approve a hook) — `command` is set.\n * - `unknown`: detection failed but we can't be sure what the user needs.\n */\nexport type PreflightStatus = \"ok\" | \"action_required\" | \"unknown\";\n\nexport interface PreflightResult {\n agent: AgentType;\n status: PreflightStatus;\n /** One-line human-readable summary, no trailing newline. */\n message: string;\n /** When `action_required`, the exact command the user should run next. */\n command?: string;\n /** When set, points at HOLDPOINT_PREREQUISITES.md or external docs. */\n docs?: string;\n}\n\n/**\n * Run silently — used for tool detection where we expect failure to be common\n * and don't want stderr bleeding into the init spinner output.\n */\nfunction silentExec(cmd: string): { ok: boolean; stdout: string } {\n try {\n const stdout = execSync(cmd, { stdio: [\"ignore\", \"pipe\", \"ignore\"] }).toString();\n return { ok: true, stdout };\n } catch {\n return { ok: false, stdout: \"\" };\n }\n}\n\n/**\n * Copilot CLI preflight.\n *\n * We can detect `gh` and the `gh-copilot` extension reliably, but the\n * `/experimental on` requirement is runtime state inside the Copilot CLI\n * session itself — there's no clean filesystem signal. So we always remind\n * users to enable it, even when everything else looks healthy.\n */\nfunction checkCopilot(): PreflightResult {\n const gh = silentExec(\"gh --version\");\n if (!gh.ok) {\n return {\n agent: \"copilot\",\n status: \"action_required\",\n message: \"GitHub CLI not found on PATH\",\n command: \"brew install gh # or: https://cli.github.com/\",\n };\n }\n\n // `gh copilot --version` exits non-zero if the extension isn't installed.\n const copilot = silentExec(\"gh copilot --version\");\n if (!copilot.ok) {\n return {\n agent: \"copilot\",\n status: \"action_required\",\n message: \"Copilot CLI extension not installed\",\n command: \"gh extension install github/gh-copilot\",\n };\n }\n\n return {\n agent: \"copilot\",\n status: \"action_required\",\n message: \"Copilot CLI detected — experimental mode required for EXTENSIONS\",\n command: \"Inside Copilot CLI, run: /experimental on\",\n };\n}\n\n/**\n * Claude Code preflight. Settings live at `.claude/settings.json`, which we\n * write ourselves during init, so the only failure mode is the binary\n * missing from PATH (in which case the user still wants the settings file\n * written — they may be invoking Claude Code from a different machine).\n */\nfunction checkClaude(): PreflightResult {\n const claude = silentExec(\"claude --version\");\n if (!claude.ok) {\n return {\n agent: \"claude\",\n status: \"unknown\",\n message: \"Claude Code binary not on PATH (hooks still written for when it is)\",\n };\n }\n return {\n agent: \"claude\",\n status: \"ok\",\n message: \"Claude Code detected — hooks installed at .claude/settings.json\",\n };\n}\n\n/**\n * Cursor preflight. Project `.cursor/hooks.json` hooks run only in trusted\n * workspaces, which is runtime state inside Cursor and not reliably readable\n * from disk, so init prints the trust/debugging reminder every time.\n */\nfunction checkCursor(): PreflightResult {\n return {\n agent: \"cursor\",\n status: \"ok\",\n message: \"Cursor — .cursor/hooks.json gate + .cursor/rules breadcrumb installed\",\n docs: \"https://holdpoint.dev/docs#cursor\",\n };\n}\n\n/**\n * Codex preflight. Project-level hooks require trust approval inside the\n * Codex TUI, which is runtime state we can't read from disk reliably across\n * Codex versions — so this mirrors the Copilot pattern: detect the binary,\n * always remind the user about `codex trust`.\n */\nfunction checkCodex(): PreflightResult {\n const codex = silentExec(\"codex --version\");\n if (!codex.ok) {\n return {\n agent: \"codex\",\n status: \"action_required\",\n message: \"Codex CLI not found on PATH\",\n command: \"Install Codex: https://github.com/openai/codex\",\n };\n }\n return {\n agent: \"codex\",\n status: \"action_required\",\n message: \"Codex detected — project-level hooks require trust approval\",\n command: \"In the Codex TUI: codex trust (or /hooks to review)\",\n };\n}\n\n// `AgentType` includes \"unknown\" for the stack-detection fallback path, but\n// only the four real agents have a preflight to run. `Partial` keeps this\n// honest instead of forcing a no-op stub.\nconst CHECKS: Partial<Record<AgentType, () => PreflightResult>> = {\n copilot: checkCopilot,\n claude: checkClaude,\n cursor: checkCursor,\n codex: checkCodex,\n};\n\n/**\n * Run preflight for the given agents and return results in input order.\n * Agents without a registered check are silently skipped — the caller's\n * agent list is the source of truth.\n *\n * Intentionally pure apart from `execSync` so callers can decide whether\n * to print, summarise, or fail-fast on the results.\n */\nexport function runPreflight(agents: readonly AgentType[]): PreflightResult[] {\n return agents.flatMap((agent) => {\n const check = CHECKS[agent];\n return check ? [check()] : [];\n });\n}\n\n/**\n * Pretty-print preflight results to stdout in the style used by `holdpoint init`.\n * Always groups by status so action items don't get lost between OKs.\n */\nexport function printPreflight(results: readonly PreflightResult[]): void {\n if (results.length === 0) return;\n\n const ok = results.filter((r) => r.status === \"ok\");\n const unknown = results.filter((r) => r.status === \"unknown\");\n const action = results.filter((r) => r.status === \"action_required\");\n\n console.log(\"\");\n console.log(chalk.bold(\"Agent preflight:\"));\n\n for (const r of ok) {\n console.log(` ${chalk.green(\"✓\")} ${r.agent.padEnd(7)} ${chalk.dim(r.message)}`);\n }\n for (const r of unknown) {\n console.log(` ${chalk.dim(\"?\")} ${r.agent.padEnd(7)} ${chalk.dim(r.message)}`);\n }\n for (const r of action) {\n console.log(` ${chalk.yellow(\"→\")} ${chalk.bold(r.agent.padEnd(7))} ${r.message}`);\n if (r.command) console.log(` ${chalk.cyan(r.command)}`);\n }\n}\n","type JsonObject = Record<string, unknown>;\n\nconst HOLDPOINT_CLAUDE_HOOK_MARKER = \"HOLDPOINT_MANAGED=claude\";\n\nfunction isObject(value: unknown): value is JsonObject {\n return value != null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asHookArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction isManagedHookCommand(value: unknown): boolean {\n return (\n isObject(value) &&\n typeof value.command === \"string\" &&\n value.command.includes(HOLDPOINT_CLAUDE_HOOK_MARKER)\n );\n}\n\nfunction isLegacyManagedHookCommand(value: unknown): boolean {\n if (!isObject(value) || typeof value.command !== \"string\") return false;\n return (\n value.command === \"node_modules/.bin/holdpoint event --engine claude --from-hook || true\" ||\n value.command === \"node_modules/.bin/holdpoint check --staged\"\n );\n}\n\nfunction isManagedHookEntry(value: unknown): boolean {\n if (!isObject(value)) return false;\n const hooks = asHookArray(value.hooks);\n return (\n hooks.length > 0 &&\n (hooks.every(isManagedHookCommand) || hooks.every(isLegacyManagedHookCommand))\n );\n}\n\n/**\n * Merge generated Holdpoint hooks into .claude/settings.json without clobbering\n * user-owned hooks. Re-runs remove only entries carrying Holdpoint's marker.\n */\nexport function mergeClaudeSettings(existing: JsonObject, generated: JsonObject): JsonObject {\n const existingHooks = isObject(existing.hooks) ? existing.hooks : {};\n const generatedHooks = isObject(generated.hooks) ? generated.hooks : {};\n const mergedHooks: JsonObject = {};\n\n for (const eventName of new Set([\n ...Object.keys(existingHooks),\n ...Object.keys(generatedHooks),\n ])) {\n const preserved = asHookArray(existingHooks[eventName]).filter(\n (entry) => !isManagedHookEntry(entry),\n );\n const next = asHookArray(generatedHooks[eventName]);\n if (preserved.length > 0 || next.length > 0) {\n mergedHooks[eventName] = [...preserved, ...next];\n }\n }\n\n return { ...existing, ...generated, hooks: mergedHooks };\n}\n","type JsonObject = Record<string, unknown>;\n\nconst HOLDPOINT_CURSOR_HOOK_MARKER = \"HOLDPOINT_MANAGED=cursor\";\n\nfunction isObject(value: unknown): value is JsonObject {\n return value != null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asHookArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction isManagedCursorHook(value: unknown): boolean {\n return (\n isObject(value) &&\n typeof value.command === \"string\" &&\n (value.command.includes(HOLDPOINT_CURSOR_HOOK_MARKER) ||\n value.command.includes(\".cursor/holdpoint-hook.mjs\"))\n );\n}\n\n/**\n * Merge generated Holdpoint Cursor hooks into `.cursor/hooks.json` without\n * clobbering user/partner hooks. Re-runs remove only entries carrying\n * Holdpoint's marker or the generated hook script path.\n */\nexport function mergeCursorHooks(existing: JsonObject, generated: JsonObject): JsonObject {\n const existingHooks = isObject(existing.hooks) ? existing.hooks : {};\n const generatedHooks = isObject(generated.hooks) ? generated.hooks : {};\n const mergedHooks: JsonObject = {};\n\n for (const eventName of new Set([\n ...Object.keys(existingHooks),\n ...Object.keys(generatedHooks),\n ])) {\n const preserved = asHookArray(existingHooks[eventName]).filter(\n (entry) => !isManagedCursorHook(entry),\n );\n const next = asHookArray(generatedHooks[eventName]);\n if (preserved.length > 0 || next.length > 0) {\n mergedHooks[eventName] = [...preserved, ...next];\n }\n }\n\n return { ...existing, ...generated, hooks: mergedHooks };\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nconst START_MARKER =\n \"<!-- HOLDPOINT_MANAGED — content between these markers is auto-generated by holdpoint init / holdpoint update -->\";\nconst END_MARKER = \"<!-- /HOLDPOINT_MANAGED -->\";\n\n/** Canonical breadcrumb content. Same wording for every agent on purpose. */\nexport const BREADCRUMB_BODY = `## Holdpoint workflow\n\nThis repo uses [Holdpoint](https://holdpoint.dev) to gate task completion on deterministic checks.\n\nBefore marking any task done:\n\n1. Run \\`holdpoint check\\` (or it will run automatically via Stop / TaskCompleted hooks).\n2. Fix any failures. Re-run until exit 0.\n3. Never bypass with \\`--no-verify\\` or by skipping the agent's stop hook.\n\nFull workflow reference: [\\`MASTER_PROMPT.md\\`](./MASTER_PROMPT.md) (always injected at session start).\nDeep reference: [\\`HOLDPOINT_REFERENCE.md\\`](./HOLDPOINT_REFERENCE.md) (read on demand).\nActive checks: [\\`checks.yaml\\`](./checks.yaml).`;\n\n/**\n * Idempotently splice the Holdpoint breadcrumb into a markdown instructions file.\n * - If the file is missing and createIfMissing: write a new file containing only the breadcrumb block.\n * - If the file has the markers: replace content between them.\n * - If the file exists but has no markers: append the breadcrumb block separated by a blank line.\n * Content outside the markers is never touched.\n */\nexport function spliceBreadcrumb(\n filePath: string,\n body: string = BREADCRUMB_BODY,\n createIfMissing = true,\n): void {\n const block = `${START_MARKER}\\n\\n${body}\\n\\n${END_MARKER}`;\n if (!existsSync(filePath)) {\n if (!createIfMissing) return;\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, block + \"\\n\", \"utf8\");\n return;\n }\n const existing = readFileSync(filePath, \"utf8\");\n const startIdx = existing.indexOf(START_MARKER);\n const endIdx = existing.indexOf(END_MARKER);\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n const before = existing.slice(0, startIdx);\n const after = existing.slice(endIdx + END_MARKER.length);\n writeFileSync(filePath, before + block + after, \"utf8\");\n return;\n }\n const sep = existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n writeFileSync(filePath, existing + sep + block + \"\\n\", \"utf8\");\n}\n"],"mappings":"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","names":["execSync","existsSync","readFileSync","writeFileSync","mkdirSync","join","dirname","fileURLToPath","chalk","existsSync","isObject","asHookArray","existsSync","readFileSync","writeFileSync","dirname","__dirname","dirname","fileURLToPath","join","existsSync","chalk","readFileSync","writeFileSync","mkdirSync","execSync"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[
|
|
2
|
+
"@anthropic-ai/mcp-server-brave-search",
|
|
3
|
+
"@anthropic-ai/mcp-server-fetch",
|
|
4
|
+
"@modelcontextprotocol/server-filesystem",
|
|
5
|
+
"@modelcontextprotocol/server-github",
|
|
6
|
+
"@modelcontextprotocol/server-gitlab",
|
|
7
|
+
"@modelcontextprotocol/server-google-maps",
|
|
8
|
+
"@modelcontextprotocol/server-postgres",
|
|
9
|
+
"@modelcontextprotocol/server-slack",
|
|
10
|
+
"@modelcontextprotocol/server-memory",
|
|
11
|
+
"@modelcontextprotocol/server-puppeteer",
|
|
12
|
+
"@modelcontextprotocol/server-sequential-thinking",
|
|
13
|
+
"@modelcontextprotocol/server-everything"
|
|
14
|
+
]
|