greprag 5.72.4 → 5.73.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.
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ /** greprag doc — mirror/search/read project Markdown through the CLI.
3
+ *
4
+ * This is the state-doc sibling of `greprag load`: skills/doctrine load from
5
+ * GrepRAG, while project docs can be mirrored there and read back by path.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.runDoc = runDoc;
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const proc_1 = require("../proc");
45
+ const project_anchor_1 = require("../project-anchor");
46
+ const docptr_refs_1 = require("../docptr-refs");
47
+ const API_URL_DEFAULT = 'https://api.greprag.com';
48
+ const MAX_DOC_CHARS = 600_000;
49
+ const HELP = `greprag doc — mirrored project Markdown docs
50
+
51
+ USAGE
52
+ greprag doc mirror sync Mirror tracked eligible .md files for this repo
53
+ greprag doc list [--json] List mirrored docs for this project
54
+ greprag doc search "<query>" Search mirrored docs
55
+ [--limit N=5] [--json]
56
+ greprag doc read <path> Print one mirrored doc exactly
57
+ [--out <file>]`;
58
+ function getConfig() {
59
+ return {
60
+ apiUrl: process.env.GREPRAG_API_URL || API_URL_DEFAULT,
61
+ apiKey: process.env.GREPRAG_API_KEY || '',
62
+ };
63
+ }
64
+ function normalizeRel(input) {
65
+ return (input || '').replace(/\\/g, '/').replace(/^\.\//, '').replace(/^\/+/, '').trim();
66
+ }
67
+ /** Mirror of docptr's pre-filter: .md only, no dot/build/vendor dirs, no harness
68
+ * instruction followers. */
69
+ function isDocPathEligible(relPath) {
70
+ const p = normalizeRel(relPath);
71
+ if (!p.toLowerCase().endsWith('.md'))
72
+ return false;
73
+ const segments = p.split('/');
74
+ const base = segments[segments.length - 1];
75
+ if (base === 'CLAUDE.md' || base === 'MEMORY.md')
76
+ return false;
77
+ for (const seg of segments.slice(0, -1)) {
78
+ if (seg.startsWith('.'))
79
+ return false;
80
+ if (seg === 'node_modules' || seg === 'dist' || seg === 'build' || seg === 'vendor')
81
+ return false;
82
+ }
83
+ return true;
84
+ }
85
+ function titleFromMarkdown(markdown, relPath) {
86
+ const heading = (markdown || '').split(/\r?\n/).find((line) => /^#{1,3}\s+\S/.test(line));
87
+ if (heading)
88
+ return heading.replace(/^#{1,3}\s+/, '').trim().slice(0, 140);
89
+ const base = normalizeRel(relPath).split('/').pop() || relPath;
90
+ return base.replace(/\.md$/i, '').replace(/[-_]+/g, ' ').trim() || relPath;
91
+ }
92
+ function tagsFromPath(relPath) {
93
+ const stop = new Set(['docs', 'doc', 'adr', 'readme', 'index']);
94
+ const tokens = normalizeRel(relPath)
95
+ .replace(/\.md$/i, '')
96
+ .split(/[\/._\s-]+/)
97
+ .map((t) => t.toLowerCase().trim())
98
+ .filter((t) => t.length >= 3 && !stop.has(t));
99
+ return Array.from(new Set(tokens)).slice(0, 12);
100
+ }
101
+ function getFlag(args, name) {
102
+ const i = args.indexOf(name);
103
+ return i >= 0 ? args[i + 1] : undefined;
104
+ }
105
+ async function apiPost(url, apiKey, body) {
106
+ const res = await fetch(url, {
107
+ method: 'POST',
108
+ headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
109
+ body: JSON.stringify(body),
110
+ });
111
+ if (!res.ok)
112
+ throw new Error(`API ${res.status}: ${await res.text()}`);
113
+ return await res.json();
114
+ }
115
+ async function apiGet(url, apiKey) {
116
+ const res = await fetch(url, { headers: { 'Authorization': `Bearer ${apiKey}` } });
117
+ if (!res.ok)
118
+ throw new Error(`API ${res.status}: ${await res.text()}`);
119
+ return await res.json();
120
+ }
121
+ function trackedFiles(cwd, pattern) {
122
+ const args = pattern ? ['ls-files', '--', pattern] : ['ls-files'];
123
+ const out = (0, proc_1.safeExecFileSync)('git', args, { cwd, encoding: 'utf-8' });
124
+ return out.split('\n').map((s) => normalizeRel(s)).filter(Boolean);
125
+ }
126
+ async function mirrorSync(args) {
127
+ const cfg = getConfig();
128
+ if (!cfg.apiKey) {
129
+ console.error('GREPRAG_API_KEY not set — run `greprag init` first.');
130
+ process.exit(1);
131
+ }
132
+ const json = args.includes('--json');
133
+ const cwd = process.cwd();
134
+ const anchor = (0, project_anchor_1.readAnchor)(cwd);
135
+ let tracked;
136
+ let present;
137
+ try {
138
+ tracked = trackedFiles(cwd, '*.md').filter(isDocPathEligible);
139
+ present = new Set(trackedFiles(cwd));
140
+ }
141
+ catch {
142
+ console.error('Not a git repo (or git unavailable) — doc mirror needs `git ls-files`.');
143
+ process.exit(1);
144
+ return;
145
+ }
146
+ const presentDocs = new Set(tracked);
147
+ const docs = [];
148
+ const skipped = [];
149
+ for (const rel of tracked) {
150
+ try {
151
+ const content = fs.readFileSync(path.join(cwd, rel), 'utf-8');
152
+ if (!content.trim()) {
153
+ skipped.push({ path: rel, reason: 'empty' });
154
+ continue;
155
+ }
156
+ if (content.length > MAX_DOC_CHARS) {
157
+ skipped.push({ path: rel, reason: 'too large' });
158
+ continue;
159
+ }
160
+ docs.push({
161
+ path: rel,
162
+ content,
163
+ title: titleFromMarkdown(content, rel),
164
+ tags: tagsFromPath(rel),
165
+ refs: (0, docptr_refs_1.extractDocRefs)(content.slice(0, 4_000), rel, cwd, present),
166
+ });
167
+ }
168
+ catch {
169
+ skipped.push({ path: rel, reason: 'unreadable' });
170
+ }
171
+ }
172
+ const result = await apiPost(`${cfg.apiUrl}/v1/doc/${anchor.projectId}/mirror`, cfg.apiKey, {
173
+ projectName: anchor.projectName,
174
+ docs,
175
+ presentPaths: Array.from(presentDocs),
176
+ });
177
+ if (json) {
178
+ console.log(JSON.stringify({ ...result, skipped }, null, 2));
179
+ return;
180
+ }
181
+ const skipText = skipped.length ? ` (${skipped.length} skipped)` : '';
182
+ console.log(`Mirrored ${result.mirrored} doc(s) for ${anchor.projectName}${skipText}. Pruned ${result.pruned}.`);
183
+ }
184
+ async function listDocs(args) {
185
+ const cfg = getConfig();
186
+ if (!cfg.apiKey) {
187
+ console.error('GREPRAG_API_KEY not set — run `greprag init` first.');
188
+ process.exit(1);
189
+ }
190
+ const anchor = (0, project_anchor_1.readAnchor)(process.cwd());
191
+ const data = await apiGet(`${cfg.apiUrl}/v1/doc/${anchor.projectId}/list`, cfg.apiKey);
192
+ if (args.includes('--json')) {
193
+ console.log(JSON.stringify(data.docs || [], null, 2));
194
+ return;
195
+ }
196
+ const docs = data.docs || [];
197
+ if (docs.length === 0) {
198
+ console.log('No mirrored docs yet. Run: greprag doc mirror sync');
199
+ return;
200
+ }
201
+ for (const doc of docs) {
202
+ const title = doc.title && doc.title !== doc.path ? ` — ${doc.title}` : '';
203
+ const words = Number.isFinite(doc.wordCount) ? ` (${doc.wordCount}w)` : '';
204
+ console.log(`${doc.path}${title}${words}`);
205
+ }
206
+ }
207
+ async function searchDocs(args) {
208
+ const cfg = getConfig();
209
+ if (!cfg.apiKey) {
210
+ console.error('GREPRAG_API_KEY not set — run `greprag init` first.');
211
+ process.exit(1);
212
+ }
213
+ const query = args.find((a) => !a.startsWith('--'));
214
+ if (!query) {
215
+ console.log(HELP);
216
+ return;
217
+ }
218
+ const limitRaw = parseInt(getFlag(args, '--limit') || '5', 10);
219
+ const limit = Number.isFinite(limitRaw) ? limitRaw : 5;
220
+ const anchor = (0, project_anchor_1.readAnchor)(process.cwd());
221
+ const data = await apiPost(`${cfg.apiUrl}/v1/doc/${anchor.projectId}/search`, cfg.apiKey, { query, limit });
222
+ if (args.includes('--json')) {
223
+ console.log(JSON.stringify(data.docs || [], null, 2));
224
+ return;
225
+ }
226
+ if (data.storeMissing) {
227
+ console.log('No mirrored docs yet. Run: greprag doc mirror sync');
228
+ return;
229
+ }
230
+ const docs = data.docs || [];
231
+ if (docs.length === 0) {
232
+ console.log('No matching mirrored docs.');
233
+ return;
234
+ }
235
+ for (const doc of docs) {
236
+ const title = doc.title && doc.title !== doc.path ? ` — ${doc.title}` : '';
237
+ const score = Number.isFinite(doc.score) ? ` [${doc.score.toFixed(3)}]` : '';
238
+ console.log(`${doc.path}${title}${score}`);
239
+ if (doc.preview)
240
+ console.log(` ${doc.preview}`);
241
+ console.log(` greprag doc read ${doc.path}`);
242
+ }
243
+ }
244
+ async function readDoc(args) {
245
+ const cfg = getConfig();
246
+ if (!cfg.apiKey) {
247
+ console.error('GREPRAG_API_KEY not set — run `greprag init` first.');
248
+ process.exit(1);
249
+ }
250
+ const key = args.find((a, i) => !a.startsWith('--') && args[i - 1] !== '--out');
251
+ if (!key) {
252
+ console.log(HELP);
253
+ return;
254
+ }
255
+ const anchor = (0, project_anchor_1.readAnchor)(process.cwd());
256
+ const params = new URLSearchParams({ key });
257
+ const data = await apiGet(`${cfg.apiUrl}/v1/doc/${anchor.projectId}/read?${params.toString()}`, cfg.apiKey);
258
+ const out = getFlag(args, '--out');
259
+ const content = data.doc.content.endsWith('\n') ? data.doc.content : data.doc.content + '\n';
260
+ if (out) {
261
+ fs.writeFileSync(path.resolve(process.cwd(), out), content, 'utf-8');
262
+ console.log(`Wrote ${out}`);
263
+ return;
264
+ }
265
+ process.stdout.write(content);
266
+ }
267
+ async function runDoc(args) {
268
+ const sub = args[0];
269
+ if (!sub || sub === '--help' || sub === '-h' || sub === 'help') {
270
+ console.log(HELP);
271
+ return;
272
+ }
273
+ if (sub === 'mirror' && args[1] === 'sync')
274
+ return mirrorSync(args.slice(2));
275
+ if (sub === 'sync')
276
+ return mirrorSync(args.slice(1));
277
+ if (sub === 'list')
278
+ return listDocs(args.slice(1));
279
+ if (sub === 'search')
280
+ return searchDocs(args.slice(1));
281
+ if (sub === 'read')
282
+ return readDoc(args.slice(1));
283
+ console.error(`Unknown "doc ${sub}". Run \`greprag doc --help\`.`);
284
+ process.exit(1);
285
+ }
286
+ //# sourceMappingURL=doc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc.js","sourceRoot":"","sources":["../../src/commands/doc.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyOH,wBAUC;AAjPD,4CAA8B;AAC9B,gDAAkC;AAClC,kCAA2C;AAC3C,sDAA+C;AAC/C,gDAAgD;AAEhD,MAAM,eAAe,GAAG,yBAAyB,CAAC;AAClD,MAAM,aAAa,GAAG,OAAO,CAAC;AAE9B,MAAM,IAAI,GAAG;;;;;;;;mBAQM,CAAC;AAoBpB,SAAS,SAAS;IAChB,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,eAAe;QACtD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;KAC1C,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3F,CAAC;AAED;6BAC6B;AAC7B,SAAS,iBAAiB,CAAC,OAAe;IACxC,MAAM,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAC/D,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACtC,IAAI,GAAG,KAAK,cAAc,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;IACpG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB,EAAE,OAAe;IAC1D,MAAM,OAAO,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1F,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,OAAO,CAAC;IAC/D,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC;AAC7E,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC;SACjC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,KAAK,CAAC,YAAY,CAAC;SACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,OAAO,CAAC,IAAc,EAAE,IAAY;IAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC;AAED,KAAK,UAAU,OAAO,CAAI,GAAW,EAAE,MAAc,EAAE,IAA6B;IAClF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QACpF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,MAAM,GAAG,CAAC,IAAI,EAAO,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,MAAM,CAAI,GAAW,EAAE,MAAc;IAClD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IACnF,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,MAAM,GAAG,CAAC,IAAI,EAAO,CAAC;AAC/B,CAAC;AAED,SAAS,YAAY,CAAC,GAAW,EAAE,OAAgB;IACjD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,IAAA,uBAAgB,EAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACtE,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACrE,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAc;IACtC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC3G,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,IAAA,2BAAU,EAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,OAAiB,CAAC;IACtB,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC9D,OAAO,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;QACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,MAAM,OAAO,GAA4C,EAAE,CAAC;IAE5D,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YAC9D,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;gBAAC,SAAS;YAAC,CAAC;YAChF,IAAI,OAAO,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;gBAAC,SAAS;YAAC,CAAC;YACnG,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI,EAAE,GAAG;gBACT,OAAO;gBACP,KAAK,EAAE,iBAAiB,CAAC,OAAO,EAAE,GAAG,CAAC;gBACtC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC;gBACvB,IAAI,EAAE,IAAA,4BAAc,EAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC;aACjE,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAEzB,GAAG,GAAG,CAAC,MAAM,WAAW,MAAM,CAAC,SAAS,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;QAChE,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,IAAI;QACJ,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;KACtC,CAAC,CAAC;IACH,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,QAAQ,eAAe,MAAM,CAAC,WAAW,GAAG,QAAQ,YAAY,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;AACnH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAc;IACpC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC3G,MAAM,MAAM,GAAG,IAAA,2BAAU,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,MAAM,CACvB,GAAG,GAAG,CAAC,MAAM,WAAW,MAAM,CAAC,SAAS,OAAO,EAC/C,GAAG,CAAC,MAAM,CACX,CAAC;IACF,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC/F,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAc;IACtC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC3G,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,IAAA,2BAAU,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,OAAO,CACxB,GAAG,GAAG,CAAC,MAAM,WAAW,MAAM,CAAC,SAAS,SAAS,EACjD,GAAG,CAAC,MAAM,EACV,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACF,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC/F,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC7E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC;QAC3C,IAAI,GAAG,CAAC,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,IAAc;IACnC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC3G,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAChF,IAAI,CAAC,GAAG,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAA,2BAAU,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,MAAM,CACvB,GAAG,GAAG,CAAC,MAAM,WAAW,MAAM,CAAC,SAAS,SAAS,MAAM,CAAC,QAAQ,EAAE,EAAE,EACpE,GAAG,CAAC,MAAM,CACX,CAAC;IACF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;IAC7F,IAAI,GAAG,EAAE,CAAC;QACR,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC9F,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,gCAAgC,CAAC,CAAC;IACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -45,7 +45,7 @@ function buildInboxPrimer(env) {
45
45
  ? '[OPENCODE INBOX — greprag is your agent-to-agent mesh. Inbound delivery is AUTOMATIC here: the greprag plugin arms a relay for this session (nothing to arm or re-arm) and inbound peer messages arrive as injected turns.]'
46
46
  : '[⚠ ARM YOUR INBOX WATCHER NOW — you are UNREACHABLE until you do. Peers are live in your mesh trying to coordinate with this session, and the operator can DM you — but they reach you ONLY while armed. Unarmed, you are invisible and their messages silently pile up. The watcher can DROP ANYTIME (crash / reload / OOM) — EVERY turn you are flagged unarmed you MUST re-arm, or coordination breaks.]',
47
47
  codex
48
- ? 'CODEX: Native Codex tools are the source of truth: `codex_app.list_threads` discovers tasks plus their repo/workspace, and `codex_app.send_message_to_thread` handles Codex-to-Codex coordination. GrepRAG inbox rows for Codex surface through turn hooks only: SessionStart `drain`, UserPromptSubmit `codex-notify`, and PostToolUse `codex-inbox`. There is no Codex startup watcher to install. If hooks do not fire, open Codex Desktop Settings -> Settings -> Hooks, trust the GrepRAG commands, start a fresh Codex session, then drain what is waiting: `greprag inbox`.'
48
+ ? 'CODEX: Native Codex tools are the source of truth: `codex_app.list_threads` discovers tasks plus their repo/workspace, and `codex_app.send_message_to_thread` handles Codex-to-Codex coordination. GrepRAG inbox rows for Codex surface through turn hooks only: SessionStart `drain` and UserPromptSubmit `codex-notify`. There is no Codex startup watcher to install. If hooks do not fire, open Codex Desktop Settings -> Settings -> Hooks, trust the GrepRAG commands, start a fresh Codex session, then drain what is waiting: `greprag inbox`.'
49
49
  : opencode
50
50
  ? 'DELIVERY: the relay arms itself on this session\'s first turn and injects inbound messages as they land — treat an injected `Message from <handle> (session <8hex>):` turn as async peer mail, not the operator typing. Drain anything already waiting: `greprag inbox`.'
51
51
  : `ARM: Monitor is a deferred tool — \`ToolSearch select:Monitor\`, then call Monitor with persistent:true, timeout_ms:3600000, description:"greprag inbox ${env.short}", command: \`${arm}\`. The \`--session ${env.short}\` is REQUIRED — a bare \`greprag inbox watch\` writes no pidfile, so the arm-check reads you unarmed forever. NEVER run it bare also because it is a foreground stream and hangs the turn. Then drain what is waiting: \`greprag inbox\`.`,
@@ -1 +1 @@
1
- {"version":3,"file":"inbox-primer-reminder.js","sourceRoot":"","sources":["../../src/commands/inbox-primer-reminder.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;8DAe8D;;;AAa9D,4CAwCC;AAlDD,8CAAkD;AAElD;;;;;;;uDAOuD;AACvD,SAAgB,gBAAgB,CAAC,GAAoF;IACnH,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC;IACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,KAAK,UAAU,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAA,8BAAiB,EAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpF,OAAO;QACL,qFAAqF;QACrF,qFAAqF;QACrF,uFAAuF;QACvF,6EAA6E;QAC7E,kFAAkF;QAClF,iFAAiF;QACjF,gFAAgF;QAChF,KAAK;YACH,CAAC,CAAC,0WAA0W;YAC5W,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,6NAA6N;gBAC/N,CAAC,CAAC,6YAA6Y;QACjZ,KAAK;YACH,CAAC,CAAC,ojBAAojB;YACtjB,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,0QAA0Q;gBAC5Q,CAAC,CAAC,2JAA2J,GAAG,CAAC,KAAK,iBAAiB,GAAG,uBAAuB,GAAG,CAAC,KAAK,4OAA4O;QACxc,EAAE;QACF,oFAAoF;QACpF,wFAAwF;QACxF,iFAAiF;QACjF,8CAA8C;QAC9C,+UAA+U;QAC/U,KAAK;YACH,CAAC,CAAC,kGAAkG,GAAG,CAAC,KAAK,uRAAuR;YACpY,CAAC,CAAC,0FAA0F,GAAG,CAAC,KAAK,6MAA6M;QACpT,6RAA6R;QAC7R,KAAK;YACH,CAAC,CAAC,+OAA+O;YACjP,CAAC,CAAC,gQAAgQ;QACpQ,kYAAkY;QAClY,uOAAuO;QACvO,2LAA2L;QAC3L,uGAAuG;KACxG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAEY,QAAA,iBAAiB,GAAmB;IAC/C,EAAE,EAAE,cAAc;IAClB,MAAM,EAAE,CAAC,IAAiB,EAAa,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,uBAAuB;IACvF,QAAQ,EAAE,CAAC,GAAgB,EAAiB,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC;IACpE,QAAQ,EAAE,GAAkB,EAAE,CAAC,IAAI;CACpC,CAAC"}
1
+ {"version":3,"file":"inbox-primer-reminder.js","sourceRoot":"","sources":["../../src/commands/inbox-primer-reminder.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;8DAe8D;;;AAa9D,4CAwCC;AAlDD,8CAAkD;AAElD;;;;;;;uDAOuD;AACvD,SAAgB,gBAAgB,CAAC,GAAoF;IACnH,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC;IACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,KAAK,UAAU,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAA,8BAAiB,EAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpF,OAAO;QACL,qFAAqF;QACrF,qFAAqF;QACrF,uFAAuF;QACvF,6EAA6E;QAC7E,kFAAkF;QAClF,iFAAiF;QACjF,gFAAgF;QAChF,KAAK;YACH,CAAC,CAAC,0WAA0W;YAC5W,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,6NAA6N;gBAC/N,CAAC,CAAC,6YAA6Y;QACjZ,KAAK;YACH,CAAC,CAAC,whBAAwhB;YAC1hB,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,0QAA0Q;gBAC5Q,CAAC,CAAC,2JAA2J,GAAG,CAAC,KAAK,iBAAiB,GAAG,uBAAuB,GAAG,CAAC,KAAK,4OAA4O;QACxc,EAAE;QACF,oFAAoF;QACpF,wFAAwF;QACxF,iFAAiF;QACjF,8CAA8C;QAC9C,+UAA+U;QAC/U,KAAK;YACH,CAAC,CAAC,kGAAkG,GAAG,CAAC,KAAK,uRAAuR;YACpY,CAAC,CAAC,0FAA0F,GAAG,CAAC,KAAK,6MAA6M;QACpT,6RAA6R;QAC7R,KAAK;YACH,CAAC,CAAC,+OAA+O;YACjP,CAAC,CAAC,gQAAgQ;QACpQ,kYAAkY;QAClY,uOAAuO;QACvO,2LAA2L;QAC3L,uGAAuG;KACxG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAEY,QAAA,iBAAiB,GAAmB;IAC/C,EAAE,EAAE,cAAc;IAClB,MAAM,EAAE,CAAC,IAAiB,EAAa,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,uBAAuB;IACvF,QAAQ,EAAE,CAAC,GAAgB,EAAiB,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC;IACpE,QAAQ,EAAE,GAAkB,EAAE,CAAC,IAAI;CACpC,CAAC"}
@@ -563,7 +563,7 @@ async function runCodexInit(opts) {
563
563
  console.log('\n greprag init — Setting up agent memory for Codex\n');
564
564
  if (opts.installWatcher) {
565
565
  console.error(' Error: Codex startup watcher install is retired. Run: greprag init --codex --tenant-id <handle>');
566
- console.error(' Codex inbox rows surface through SessionStart drain, UserPromptSubmit codex-notify, and PostToolUse codex-inbox.');
566
+ console.error(' Codex inbox rows surface through SessionStart drain and UserPromptSubmit codex-notify.');
567
567
  process.exit(1);
568
568
  }
569
569
  let apiKey = opts.apiKey || readSharedApiKey();
@@ -629,15 +629,15 @@ async function runCodexInit(opts) {
629
629
  const hookChanges = applyCodexHooks(hooks);
630
630
  writeCodexHooks(hooksPath, hooks);
631
631
  changes.push(...hookChanges);
632
- changes.push('Codex inbox delivery: turn hooks only (SessionStart drain, UserPromptSubmit codex-notify, PostToolUse codex-inbox)');
632
+ changes.push('Codex inbox delivery: turn hooks only (SessionStart drain, UserPromptSubmit codex-notify)');
633
633
  console.log('\n Setup complete!\n');
634
634
  for (const change of changes) {
635
635
  console.log(` - ${change}`);
636
636
  }
637
637
  console.log(`\n Codex hooks file: ${hooksPath}`);
638
638
  console.log(` Project anchor: ${anchor.anchorPath}`);
639
- console.log(' Start a fresh Codex session, then open Settings -> Settings -> Hooks and trust the 8 GrepRAG hook definitions.');
640
- console.log(' Inbox messages for Codex surface on SessionStart, UserPromptSubmit, and PostToolUse hook boundaries.');
639
+ console.log(' Start a fresh Codex session, then open Settings -> Settings -> Hooks and trust the GrepRAG hook definitions.');
640
+ console.log(' Inbox messages for Codex surface on SessionStart and UserPromptSubmit hook boundaries.');
641
641
  console.log(' Memory hooks will activate on your next Codex session.\n');
642
642
  }
643
643
  /** greprag init --global
@@ -1009,6 +1009,36 @@ function writeCodexHooks(hooksPath, hooks) {
1009
1009
  fs.mkdirSync(dir, { recursive: true });
1010
1010
  fs.writeFileSync(hooksPath, JSON.stringify(hooks, null, 2) + '\n');
1011
1011
  }
1012
+ function commandOnPath(command) {
1013
+ const paths = (process.env.PATH || '').split(path.delimiter).filter(Boolean);
1014
+ const hasExt = !!path.extname(command);
1015
+ const exts = process.platform === 'win32' && !hasExt
1016
+ ? (process.env.PATHEXT || '.COM;.EXE;.BAT;.CMD').split(';').filter(Boolean)
1017
+ : [''];
1018
+ for (const dir of paths) {
1019
+ for (const ext of exts) {
1020
+ if (fs.existsSync(path.join(dir, `${command}${ext}`)))
1021
+ return true;
1022
+ }
1023
+ }
1024
+ return false;
1025
+ }
1026
+ function shellQuote(value) {
1027
+ return `"${value.replace(/"/g, '\\"')}"`;
1028
+ }
1029
+ function codexFastHookWindowsCommand(subcommand) {
1030
+ if (commandOnPath('greprag-codex-hook'))
1031
+ return `greprag-codex-hook.cmd ${subcommand}`;
1032
+ const script = path.resolve(__dirname, '..', 'codex-fast-hook.js');
1033
+ if (fs.existsSync(script))
1034
+ return `node ${shellQuote(script)} ${subcommand}`;
1035
+ return `greprag-codex-hook.cmd ${subcommand}`;
1036
+ }
1037
+ function windowsCommandForRunner(runner, subcommand) {
1038
+ if (runner === 'greprag-codex-hook')
1039
+ return codexFastHookWindowsCommand(subcommand);
1040
+ return `${runner}.cmd ${subcommand}`;
1041
+ }
1012
1042
  function applyCodexHooks(config) {
1013
1043
  const changes = [];
1014
1044
  if (!config.hooks)
@@ -1019,15 +1049,15 @@ function applyCodexHooks(config) {
1019
1049
  const deduped = dedupeCodexHooks(config.hooks);
1020
1050
  if (deduped > 0)
1021
1051
  changes.push(`Removed ${deduped} duplicate Codex hook registration(s)`);
1022
- const commandHook = (subcommand, timeout, statusMessage) => {
1052
+ const commandHook = (subcommand, timeout, statusMessage, runner = 'greprag-hook') => {
1023
1053
  const hook = {
1024
1054
  type: 'command',
1025
- command: `greprag-hook ${subcommand}`,
1055
+ command: `${runner} ${subcommand}`,
1026
1056
  timeout,
1027
1057
  statusMessage,
1028
1058
  };
1029
1059
  if (process.platform === 'win32')
1030
- hook.commandWindows = `greprag-hook.cmd ${subcommand}`;
1060
+ hook.commandWindows = windowsCommandForRunner(runner, subcommand);
1031
1061
  return hook;
1032
1062
  };
1033
1063
  const recapHook = {
@@ -1085,18 +1115,9 @@ function applyCodexHooks(config) {
1085
1115
  else {
1086
1116
  changes.push('Codex UserPromptSubmit hook already configured (skipped)');
1087
1117
  }
1088
- const inboxHook = {
1089
- matcher: '',
1090
- hooks: [commandHook('codex-inbox', 5, 'Checking GrepRAG inbox')],
1091
- };
1092
- if (!hasGrepragHook(config.hooks.PostToolUse, 'codex-inbox')) {
1093
- if (!config.hooks.PostToolUse)
1094
- config.hooks.PostToolUse = [];
1095
- config.hooks.PostToolUse.push(inboxHook);
1096
- changes.push('Added Codex PostToolUse hook (inbox steering)');
1097
- }
1098
- else {
1099
- changes.push('Codex PostToolUse inbox hook already configured (skipped)');
1118
+ const removedPostToolInbox = removeGrepragHook(config.hooks, 'PostToolUse', 'codex-inbox');
1119
+ if (removedPostToolInbox) {
1120
+ changes.push(`Removed ${removedPostToolInbox} Codex PostToolUse inbox hook(s); UserPromptSubmit now owns inbox steering`);
1100
1121
  }
1101
1122
  const permissionHook = {
1102
1123
  matcher: '',
@@ -1149,11 +1170,35 @@ function applyCodexHooks(config) {
1149
1170
  }
1150
1171
  const chipHooks = [
1151
1172
  { event: 'SessionStart', matcher: 'startup|resume|clear|compact', label: 'chip context' },
1152
- { event: 'PreToolUse', matcher: '', label: 'chip boundary guard' },
1153
1173
  { event: 'SubagentStart', matcher: '', label: 'nested-agent chip context' },
1154
1174
  { event: 'SubagentStop', matcher: '', label: 'nested-agent completion context' },
1155
- { event: 'Stop', matcher: '', label: 'chip completion gate' },
1156
1175
  ];
1176
+ // adr: adr/codex-hook-latency.md
1177
+ // Collapse the hot PreToolUse safety pair into one fast command process. It
1178
+ // runs the chip/apply_patch guard first, then lazy-loads coordination only for
1179
+ // Bash calls.
1180
+ const removedPreToolChip = removeGrepragHook(config.hooks, 'PreToolUse', 'codex-chip-hook');
1181
+ const removedPreToolCoord = removeGrepragHook(config.hooks, 'PreToolUse', 'codex-coordinate-gate');
1182
+ if (removedPreToolChip || removedPreToolCoord) {
1183
+ changes.push(`Removed ${removedPreToolChip + removedPreToolCoord} split Codex PreToolUse hook(s); codex-pretooluse now multiplexes safety`);
1184
+ }
1185
+ const preToolUseHook = {
1186
+ matcher: '',
1187
+ hooks: [commandHook('codex-pretooluse', 10, 'Checking GrepRAG Codex safety', 'greprag-codex-hook')],
1188
+ };
1189
+ if (!hasGrepragHookWithMatcher(config.hooks.PreToolUse, 'codex-pretooluse', preToolUseHook.matcher)) {
1190
+ if (!config.hooks.PreToolUse)
1191
+ config.hooks.PreToolUse = [];
1192
+ config.hooks.PreToolUse.push(preToolUseHook);
1193
+ changes.push('Added Codex PreToolUse hook (multiplexed chip + coordination safety)');
1194
+ }
1195
+ else {
1196
+ changes.push('Codex PreToolUse multiplexed safety hook already configured (skipped)');
1197
+ }
1198
+ const removedStopChip = removeGrepragHook(config.hooks, 'Stop', 'codex-chip-hook');
1199
+ if (removedStopChip) {
1200
+ changes.push(`Removed ${removedStopChip} Codex Stop chip hook(s); Stop chip hook was a no-op`);
1201
+ }
1157
1202
  for (const spec of chipHooks) {
1158
1203
  const eventHooks = config.hooks[spec.event];
1159
1204
  if (hasGrepragHookWithMatcher(eventHooks, 'codex-chip-hook', spec.matcher)) {
@@ -1162,30 +1207,13 @@ function applyCodexHooks(config) {
1162
1207
  }
1163
1208
  const entry = {
1164
1209
  matcher: spec.matcher,
1165
- hooks: [commandHook('codex-chip-hook', 3, 'Enforcing Codex chip contract')],
1210
+ hooks: [commandHook('codex-chip-hook', 3, 'Enforcing Codex chip contract', 'greprag-codex-hook')],
1166
1211
  };
1167
1212
  if (!config.hooks[spec.event])
1168
1213
  config.hooks[spec.event] = [];
1169
1214
  config.hooks[spec.event].push(entry);
1170
1215
  changes.push(`Added Codex ${spec.event} hook (${spec.label})`);
1171
1216
  }
1172
- // Codex shipping coordination — risky Bash actions are denied until the
1173
- // current committed artifact has fresh native-task + cross-harness conferral
1174
- // evidence. This is separate from codex-chip-hook because it applies to every
1175
- // Codex task, not only managed chips. adr: adr/codex-coordinate-gate.md
1176
- const coordinateGateHook = {
1177
- matcher: 'Bash',
1178
- hooks: [commandHook('codex-coordinate-gate', 10, 'Checking peer coordination')],
1179
- };
1180
- if (!hasGrepragHookWithMatcher(config.hooks.PreToolUse, 'codex-coordinate-gate', coordinateGateHook.matcher)) {
1181
- if (!config.hooks.PreToolUse)
1182
- config.hooks.PreToolUse = [];
1183
- config.hooks.PreToolUse.push(coordinateGateHook);
1184
- changes.push('Added Codex PreToolUse hook (shipping coordination gate)');
1185
- }
1186
- else {
1187
- changes.push('Codex PreToolUse shipping coordination hook already configured (skipped)');
1188
- }
1189
1217
  const storeHook = {
1190
1218
  matcher: '',
1191
1219
  hooks: [commandHook('codex-store', 10, 'Storing GrepRAG turn')],
@@ -1226,10 +1254,10 @@ function normalizeCodexHookCommands(hooks) {
1226
1254
  'session-id': { timeout: 3, statusMessage: 'Loading GrepRAG session id' },
1227
1255
  drain: { timeout: 5, statusMessage: 'Draining GrepRAG inbox' },
1228
1256
  'codex-notify': { timeout: 300, statusMessage: 'Checking GrepRAG inbox' },
1229
- 'codex-inbox': { timeout: 5, statusMessage: 'Checking GrepRAG inbox' },
1230
1257
  'codex-permission-context': { timeout: 3, statusMessage: 'Loading GrepRAG approval context' },
1231
1258
  'codex-subagent-start': { timeout: 3, statusMessage: 'Recording GrepRAG subagent metadata' },
1232
- 'codex-chip-hook': { timeout: 3, statusMessage: 'Enforcing Codex chip contract' },
1259
+ 'codex-chip-hook': { timeout: 3, statusMessage: 'Enforcing Codex chip contract', runner: 'greprag-codex-hook' },
1260
+ 'codex-pretooluse': { timeout: 10, statusMessage: 'Checking GrepRAG Codex safety', runner: 'greprag-codex-hook' },
1233
1261
  'codex-coordinate-gate': { timeout: 10, statusMessage: 'Checking peer coordination' },
1234
1262
  'codex-store': { timeout: 10, statusMessage: 'Storing GrepRAG turn' },
1235
1263
  };
@@ -1239,7 +1267,7 @@ function normalizeCodexHookCommands(hooks) {
1239
1267
  for (const hook of entry.hooks || []) {
1240
1268
  if (!hook.command)
1241
1269
  continue;
1242
- const match = hook.command.match(/^greprag-hook(?:\.cmd)*\s+([a-z-]+)/);
1270
+ const match = hook.command.match(/^greprag(?:-codex)?-hook(?:\.cmd)*\s+([a-z-]+)/);
1243
1271
  if (!match)
1244
1272
  continue;
1245
1273
  const baseSpec = desired[match[1]];
@@ -1250,13 +1278,14 @@ function normalizeCodexHookCommands(hooks) {
1250
1278
  spec.statusMessage = 'Restoring GrepRAG session id';
1251
1279
  }
1252
1280
  const subcommand = match[1] === 'recap' ? 'codex-recap' : match[1];
1253
- const next = `greprag-hook ${subcommand}`;
1281
+ const runner = spec.runner || 'greprag-hook';
1282
+ const next = `${runner} ${subcommand}`;
1254
1283
  if (next !== hook.command) {
1255
1284
  hook.command = next;
1256
1285
  count++;
1257
1286
  }
1258
1287
  if (process.platform === 'win32') {
1259
- const windows = `greprag-hook.cmd ${subcommand}`;
1288
+ const windows = windowsCommandForRunner(runner, subcommand);
1260
1289
  if (hook.commandWindows !== windows) {
1261
1290
  hook.commandWindows = windows;
1262
1291
  count++;
@@ -1620,9 +1649,15 @@ function applySettings(settings, apiKey) {
1620
1649
  * `hasCodexHook`. adr: adr/codex-hook-idempotency.md */
1621
1650
  function commandInvokesSub(h, subcommand) {
1622
1651
  const hay = `${h.command || ''}\n${h.commandWindows || ''}`;
1652
+ const escaped = subcommand.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1653
+ const directNodeHook = new RegExp(`(?:hook|codex-fast-hook)\\.js"?\\s+${escaped}`);
1623
1654
  return hay.includes(`greprag-hook ${subcommand}`)
1624
1655
  || hay.includes(`greprag-hook.cmd ${subcommand}`)
1625
- || hay.includes(`hook.js ${subcommand}`);
1656
+ || hay.includes(`greprag-codex-hook ${subcommand}`)
1657
+ || hay.includes(`greprag-codex-hook.cmd ${subcommand}`)
1658
+ || hay.includes(`hook.js ${subcommand}`)
1659
+ || hay.includes(`codex-fast-hook.js ${subcommand}`)
1660
+ || directNodeHook.test(hay);
1626
1661
  }
1627
1662
  function hasGrepragHook(hookConfigs, subcommand) {
1628
1663
  if (!hookConfigs)
@@ -1644,12 +1679,33 @@ function hasGrepragHookWithMatcher(hookConfigs, subcommand, matcher) {
1644
1679
  function grepragSubOf(cfg) {
1645
1680
  for (const h of cfg.hooks || []) {
1646
1681
  const m = `${h.command || ''}\n${h.commandWindows || ''}`
1647
- .match(/greprag-hook(?:\.cmd)?\s+([a-z-]+)/);
1682
+ .match(/greprag(?:-codex)?-hook(?:\.cmd)?\s+([a-z-]+)/);
1648
1683
  if (m)
1649
1684
  return m[1];
1650
1685
  }
1651
1686
  return null;
1652
1687
  }
1688
+ function removeGrepragHook(hooks, eventName, subcommand) {
1689
+ const entries = hooks?.[eventName];
1690
+ if (!Array.isArray(entries))
1691
+ return 0;
1692
+ let removed = 0;
1693
+ const keptEntries = [];
1694
+ for (const entry of entries) {
1695
+ const keptHooks = (entry.hooks || []).filter(hook => {
1696
+ if (commandInvokesSub(hook, subcommand)) {
1697
+ removed++;
1698
+ return false;
1699
+ }
1700
+ return true;
1701
+ });
1702
+ if (keptHooks.length)
1703
+ keptEntries.push({ ...entry, hooks: keptHooks });
1704
+ }
1705
+ entries.length = 0;
1706
+ entries.push(...keptEntries);
1707
+ return removed;
1708
+ }
1653
1709
  /** Collapse duplicate greprag hook registrations so a repeated `init` converges
1654
1710
  * to exactly ONE set instead of stacking copies. The Windows `.cmd`-detection
1655
1711
  * bug let re-init append dupes; this also SELF-HEALS files already broken that