@hailer/mcp 1.1.4 → 1.1.6

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.
@@ -8,9 +8,9 @@
8
8
  * 1. PreCompact (auto) - escalating response by compaction count:
9
9
  * 1st: inform (context still good after one compaction)
10
10
  * 2nd: strongly urge handoff (summary-of-summary, quality degrades)
11
- * 3rd+: yolo=auto-handoff, interactive=block until acknowledged
11
+ * 3rd+: force handoff
12
12
  * 2. PostToolUse (Task) - count agent calls, warn at thresholds
13
- * 3. Stop - if yolo + compact fired, block stop until handoff written
13
+ * 3. Stop - if heavily compacted, block stop until handoff written
14
14
  * </purpose>
15
15
  *
16
16
  * <triggers>
@@ -72,16 +72,6 @@ function saveState(projectRoot, state) {
72
72
  } catch {}
73
73
  }
74
74
 
75
- function isYoloMode(projectRoot) {
76
- try {
77
- const statePath = path.join(projectRoot, '.claude', 'yolo-state.json');
78
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
79
- return state.mode === 'yolo';
80
- } catch {
81
- return false;
82
- }
83
- }
84
-
85
75
  function handoffRecentlyWritten(projectRoot) {
86
76
  const fp = path.join(projectRoot, 'SESSION-HANDOFF.md');
87
77
  try {
@@ -143,7 +133,6 @@ function processHook(data) {
143
133
  const projectRoot = getProjectRoot();
144
134
  const sessionId = data.session_id || '';
145
135
  const state = loadState(projectRoot, sessionId);
146
- const yolo = isYoloMode(projectRoot);
147
136
  const event = data.hook_event_name;
148
137
  _hookEvent = event; // Set for allow/block output formatting
149
138
 
@@ -156,63 +145,28 @@ function processHook(data) {
156
145
 
157
146
  // 1st compaction: inform — context is still usable
158
147
  if (state.compactCount === 1) {
159
- if (yolo) {
160
- allow(
161
- `📋 Context compacting (1st time). Still usable.\n\n` +
162
- `Save progress soon:\n` +
163
- `1. Update DEVELOPMENT.md with current progress\n` +
164
- `2. Write SESSION-HANDOFF.md\n` +
165
- `3. Run /save\n\n` +
166
- `You can continue working after this compaction.`
167
- );
168
- } else {
169
- allow(`📋 Context compacting (1st time). Context is still good — consider running /handoff soon to preserve state.`);
170
- }
148
+ allow(`📋 Context compacting (1st time). Context is still good — consider running /handoff soon to preserve state.`);
171
149
  }
172
150
 
173
151
  // 2nd compaction: strongly urge handoff — quality starts degrading
174
152
  if (state.compactCount === 2) {
175
- if (yolo) {
176
- allow(
177
- `⚠️ CONTEXT COMPACTING 2nd TIME quality will degrade.\n\n` +
178
- `You MUST save progress NOW before continuing:\n` +
179
- `1. Update DEVELOPMENT.md with current progress\n` +
180
- `2. Write SESSION-HANDOFF.md with full current state and next steps\n` +
181
- `3. Run /save "Handoff: 2nd compaction"\n` +
182
- `4. Tell user: "Context compacted twice. Recommend starting fresh with /recap."\n\n` +
183
- `Do this BEFORE any other work. After handoff, you may continue but expect degraded recall.`
184
- );
185
- } else {
186
- allow(
187
- `⚠️ Context compacting for the 2nd time. Earlier details are now a summary-of-a-summary.\n\n` +
188
- `Strongly recommended: run /handoff now and start a fresh session with /recap.\n` +
189
- `Continuing risks: forgetting decisions, re-reading files, repeating mistakes.`
190
- );
191
- }
153
+ allow(
154
+ `⚠️ Context compacting for the 2nd time. Earlier details are now a summary-of-a-summary.\n\n` +
155
+ `Strongly recommended: run /handoff now and start a fresh session with /recap.\n` +
156
+ `Continuing risks: forgetting decisions, re-reading files, repeating mistakes.`
157
+ );
192
158
  }
193
159
 
194
160
  // 3rd+ compaction: force handoff
195
161
  if (state.compactCount >= 3) {
196
- if (yolo) {
197
- allow(
198
- `🛑 CONTEXT COMPACTING ${ordinal(state.compactCount)} TIME session is degraded.\n\n` +
199
- `IMMEDIATELY write handoff and stop:\n` +
200
- `1. Update DEVELOPMENT.md with ALL current progress\n` +
201
- `2. Write SESSION-HANDOFF.md with full state, pending tasks, and next steps\n` +
202
- `3. Run /save "Auto-handoff: ${state.compactCount}x compacted"\n` +
203
- `4. Tell user: "Context compacted ${state.compactCount} times. Start new conversation with /recap to continue."\n\n` +
204
- `Do NOT continue working. Quality is too degraded.`
205
- );
206
- } else {
207
- allow(
208
- `🛑 Context compacting for the ${ordinal(state.compactCount)} time — session is significantly degraded.\n\n` +
209
- `You should run /handoff and start fresh. Continuing will lead to:\n` +
210
- `- Forgotten decisions and context\n` +
211
- `- Re-reading files already read\n` +
212
- `- Potential mistakes from lost context\n\n` +
213
- `Please run /handoff now.`
214
- );
215
- }
162
+ allow(
163
+ `🛑 Context compacting for the ${ordinal(state.compactCount)} time — session is significantly degraded.\n\n` +
164
+ `You should run /handoff and start fresh. Continuing will lead to:\n` +
165
+ `- Forgotten decisions and context\n` +
166
+ `- Re-reading files already read\n` +
167
+ `- Potential mistakes from lost context\n\n` +
168
+ `Please run /handoff now.`
169
+ );
216
170
  }
217
171
  }
218
172
 
@@ -230,30 +184,14 @@ function processHook(data) {
230
184
  if (state.toolCalls === URGENT_WARNING_CALLS && state.lastWarning !== 'urgent') {
231
185
  state.lastWarning = 'urgent';
232
186
  saveState(projectRoot, state);
233
-
234
- if (yolo) {
235
- allow(
236
- `⚠️ Context getting full: ${state.toolCalls} agent calls this session.\n\n` +
237
- `Save progress NOW before auto-compaction hits:\n` +
238
- `1. Update DEVELOPMENT.md with progress\n` +
239
- `2. Write SESSION-HANDOFF.md\n` +
240
- `3. Run /save\n` +
241
- `Then continue working (or tell user to start fresh).`
242
- );
243
- } else {
244
- allow(`📊 ${state.toolCalls} agent calls this session. Context may be getting full - consider /handoff.`);
245
- }
187
+ allow(`📊 ${state.toolCalls} agent calls this session. Context may be getting full - consider /handoff.`);
246
188
  }
247
189
 
248
190
  // Early warning
249
191
  if (state.toolCalls === EARLY_WARNING_CALLS && state.lastWarning === 'none') {
250
192
  state.lastWarning = 'early';
251
193
  saveState(projectRoot, state);
252
-
253
- if (yolo) {
254
- allow(`📊 Context check: ${state.toolCalls} agent calls. Consider saving progress with /save soon.`);
255
- }
256
- // Silent in non-yolo mode at early threshold
194
+ allow(`📊 Context check: ${state.toolCalls} agent calls. Consider /handoff soon.`);
257
195
  }
258
196
 
259
197
  allow();
@@ -29,8 +29,8 @@
29
29
  * SKIPS:
30
30
  * - When called from within a subagent (checks agent stack + env vars)
31
31
  *
32
- * NOTE: Delegation is enforced even in yolo mode. Yolo only bypasses confirmation
33
- * prompts (bulk-activity-guard, destructive-command-guard), not delegation pattern.
32
+ * NOTE: File read/write suggestions are ALWAYS soft (allow + message).
33
+ * Only MCP write tools and built-in agent types are hard-blocked.
34
34
  *
35
35
  * Hook type: PreToolUse
36
36
  */
@@ -132,33 +132,9 @@ const FILE_PATTERN_AGENTS = {
132
132
  '.claude/skills/': 'agent-ada-skill-builder',
133
133
  };
134
134
 
135
- // Check yolo mode once at startup
136
- let _isYolo = false;
137
- try {
138
- const statePath = path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), '.claude', 'yolo-state.json');
139
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
140
- _isYolo = state.mode === 'yolo';
141
- } catch {}
142
-
143
- /**
144
- * In normal mode: soft suggestion (allow + message)
145
- * In yolo mode: hard block (force delegation)
146
- *
147
- * Yolo means "autonomous via agents", not "orchestrator does everything".
148
- */
149
- function suggest(message, agentHint) {
150
- if (_isYolo) {
151
- console.log(JSON.stringify({
152
- decision: "block",
153
- reason: `🚫 YOLO DELEGATION: In autonomous mode, delegate to agents.\n\n${message}${agentHint ? `\n\nDelegate to: ${agentHint}` : ''}`,
154
- }));
155
- } else {
156
- console.log(JSON.stringify({
157
- decision: "allow",
158
- message: message,
159
- }));
160
- }
161
- }
135
+ // All file read/write suggestions always allow with a soft message.
136
+ // Only MCP write tools (create_activity, update_activity, install_workflow)
137
+ // and built-in agent types are hard-blocked.
162
138
 
163
139
  // Read stdin asynchronously for better cross-platform support
164
140
  let stdinData = '';
@@ -260,7 +236,7 @@ function processInput(input) {
260
236
  }
261
237
 
262
238
  // SOFT SUGGEST: Glob/Grep code searches - always soft (orchestrator needs these for delegation)
263
- // These are orchestration tools, not domain work - never block even in yolo
239
+ // These are orchestration tools, not domain work - never block always
264
240
  if (tool_name === 'Glob' || tool_name === 'Grep') {
265
241
  console.log(JSON.stringify({
266
242
  decision: "allow",
@@ -281,7 +257,7 @@ function processInput(input) {
281
257
  // MCP tools - block writes, suggest for reads
282
258
  if (tool_name?.startsWith('mcp__hailer__')) {
283
259
  // HARD BLOCK: install_workflow should use SDK, not MCP
284
- // Enforced even in yolo mode - delegation is about correctness, not permissions
260
+ // Enforced always mode - delegation is about correctness, not permissions
285
261
  if (tool_name === 'mcp__hailer__install_workflow') {
286
262
  console.log(JSON.stringify({
287
263
  decision: "block",
@@ -297,7 +273,7 @@ The install_workflow MCP tool is for admin/dev use only.`,
297
273
  }
298
274
 
299
275
  // HARD BLOCK: Activity writes must go through Dmitri
300
- // Enforced even in yolo mode - Dmitri validates field formats
276
+ // Enforced always mode - Dmitri validates field formats
301
277
  if (tool_name === 'mcp__hailer__create_activity' || tool_name === 'mcp__hailer__update_activity') {
302
278
  console.log(JSON.stringify({
303
279
  decision: "block",
@@ -313,7 +289,7 @@ Task(subagent_type="agent-dmitri-activity-crud", prompt='{"task":"create","workf
313
289
  return;
314
290
  }
315
291
 
316
- // MCP READ TOOLS: Always allow with soft message (never block, even in yolo)
292
+ // MCP READ TOOLS: Always allow with soft message (never block, always)
317
293
  // Subagent detection is unreliable — we can't tell if Viktor or the orchestrator
318
294
  // is calling preview_insight. Blocking would break agents using their own tools.
319
295
  const suggestedAgent = MCP_TOOL_AGENTS[tool_name];
@@ -352,15 +328,19 @@ Task(subagent_type="agent-dmitri-activity-crud", prompt='{"task":"create","workf
352
328
  if (tool_name === 'Read') {
353
329
  const filePath = tool_input?.file_path || '';
354
330
 
355
- // workspace/ reads - SOFT SUGGESTION (not blocking)
331
+ // workspace/ reads - ALWAYS ALLOW (never block, always)
356
332
  // Multiple specialist agents (Helga, Viktor, Alejandro, Ingrid) need workspace access
357
- // Subagent detection isn't reliable, so we suggest rather than block
333
+ // Subagent detection isn't reliable, so we can't distinguish orchestrator from agents
358
334
  if (filePath.includes('workspace/') || filePath.includes('/workspace/')) {
359
- suggest(`💡 WORKSPACE READ: If you're the orchestrator, consider delegating to Kenji.\n\nTask(subagent_type="agent-kenji-data-reader", prompt='{"task":"read_workspace_file","path":"${filePath}"}')\n\n(Specialist agents like Helga/Viktor need direct access - this is just a reminder.)`, 'agent-kenji-data-reader');
335
+ console.log(JSON.stringify({
336
+ decision: "allow",
337
+ message: `💡 WORKSPACE READ: If you're the orchestrator, consider delegating to Kenji.\n\nTask(subagent_type="agent-kenji-data-reader", prompt='{"task":"read_workspace_file","path":"${filePath}"}')\n\n(Specialist agents like Helga/Viktor need direct access - this is just a reminder.)`,
338
+ }));
360
339
  return;
361
340
  }
362
341
 
363
- // Other file patterns - soft suggestions
342
+ // Other file patterns - ALWAYS ALLOW reads (never block, always)
343
+ // Agents need to read files in their domain (Giuseppe reads apps/, etc.)
364
344
  for (const [pattern, agent] of Object.entries(FILE_PATTERN_AGENTS)) {
365
345
  if (filePath.includes(pattern) && !pattern.includes('workspace')) {
366
346
  const suggestions = {
@@ -370,7 +350,10 @@ Task(subagent_type="agent-dmitri-activity-crud", prompt='{"task":"create","workf
370
350
  };
371
351
  const suggestion = suggestions[pattern];
372
352
  if (suggestion) {
373
- suggest(`💡 CONSIDER DELEGATING: ${suggestion}\n\nAgent: ${agent}`, agent);
353
+ console.log(JSON.stringify({
354
+ decision: "allow",
355
+ message: `💡 CONSIDER DELEGATING: ${suggestion}\n\nAgent: ${agent}`,
356
+ }));
374
357
  return;
375
358
  }
376
359
  }
@@ -378,52 +361,47 @@ Task(subagent_type="agent-dmitri-activity-crud", prompt='{"task":"create","workf
378
361
  }
379
362
 
380
363
  // SOFT REMIND: Write/Edit on various files
364
+ // ALWAYS ALLOW writes — agents need to write in their domains
365
+ // Subagent detection is unreliable, so blocking writes breaks agents
381
366
  if (tool_name === 'Write' || tool_name === 'Edit') {
382
367
  const filePath = tool_input?.file_path || '';
383
368
 
384
- // WORKSPACE WRITES: Suggest appropriate specialist
369
+ // WORKSPACE WRITES: Suggest appropriate specialist (always allow)
385
370
  if (filePath.includes('workspace/')) {
386
- // Function field code
371
+ let message;
387
372
  if (filePath.includes('/functions/')) {
388
- suggest(`💡 FUNCTION FIELD CODE: Use agent-alejandro-function-fields.\n\nAlejandro specializes in calculated fields, functionVariables, and JavaScript formulas.`, 'agent-alejandro-function-fields');
389
- return;
390
- }
391
-
392
- // fields.ts - could involve function fields
393
- if (filePath.includes('fields.ts')) {
394
- suggest(`💡 FIELD DEFINITIONS: Use agent-helga-workflow-config for field config.\n\n💡 FOR FUNCTION FIELDS: If adding functionEnabled/functionVariables, also use agent-alejandro-function-fields for the function code.\n\nWorkflow: Helga adds field config → Alejandro writes function code`, 'agent-helga-workflow-config');
395
- return;
396
- }
397
-
398
- // Document templates
399
- if (filePath.includes('/templates/')) {
400
- suggest(`💡 DOCUMENT TEMPLATES: Use agent-ingrid-doc-templates.\n\nIngrid handles PDF/CSV templates, pdfmake structure, and field mappings.`, 'agent-ingrid-doc-templates');
401
- return;
373
+ message = `💡 FUNCTION FIELD CODE: If you're the orchestrator, use agent-alejandro-function-fields.`;
374
+ } else if (filePath.includes('fields.ts')) {
375
+ message = `💡 FIELD DEFINITIONS: If you're the orchestrator, use agent-helga-workflow-config for field config, agent-alejandro-function-fields for function code.`;
376
+ } else if (filePath.includes('/templates/')) {
377
+ message = `💡 DOCUMENT TEMPLATES: If you're the orchestrator, use agent-ingrid-doc-templates.`;
378
+ } else if (filePath.includes('insights.ts')) {
379
+ message = `💡 INSIGHTS: If you're the orchestrator, use agent-viktor-sql-insights.`;
380
+ } else {
381
+ message = `💡 WORKSPACE CONFIG: If you're the orchestrator, use agent-helga-workflow-config.`;
402
382
  }
403
-
404
- // Insights
405
- if (filePath.includes('insights.ts')) {
406
- suggest(`💡 INSIGHTS: Use agent-viktor-sql-insights.\n\nViktor creates SQL queries, data sources, and insight configurations.`, 'agent-viktor-sql-insights');
407
- return;
408
- }
409
-
410
- // General workspace config
411
- suggest(`💡 WORKSPACE CONFIG: Use agent-helga-workflow-config.\n\nHelga manages workflows, fields, phases via SDK. Knows correct field types and push/pull order.`, 'agent-helga-workflow-config');
383
+ console.log(JSON.stringify({ decision: "allow", message }));
412
384
  return;
413
385
  }
414
386
 
415
- // Suggest delegation for agent/skill modifications
387
+ // Suggest delegation for agent/skill modifications (always allow)
416
388
  if (filePath.includes('.claude/agents/')) {
417
- suggest(`💡 CONSIDER DELEGATING: Use agent-builder-agent-creator for agent modifications.\n\nIt follows agent structure patterns and validates format.`, 'agent-builder-agent-creator');
389
+ console.log(JSON.stringify({
390
+ decision: "allow",
391
+ message: `💡 CONSIDER DELEGATING: Use agent-builder-agent-creator for agent modifications.`,
392
+ }));
418
393
  return;
419
394
  }
420
395
 
421
396
  if (filePath.includes('.claude/skills/')) {
422
- suggest(`💡 CONSIDER DELEGATING: Use agent-ada-skill-builder for skill modifications.\n\nIt creates skills from patterns and failure analysis.`, 'agent-ada-skill-builder');
397
+ console.log(JSON.stringify({
398
+ decision: "allow",
399
+ message: `💡 CONSIDER DELEGATING: Use agent-ada-skill-builder for skill modifications.`,
400
+ }));
423
401
  return;
424
402
  }
425
403
 
426
- // .claude/ config files - allow in yolo (orchestrator legitimately edits config)
404
+ // .claude/ config files - always allow
427
405
  if (filePath.includes('.claude/') && (filePath.endsWith('.json') || filePath.endsWith('.cjs'))) {
428
406
  console.log(JSON.stringify({
429
407
  decision: "allow",
@@ -433,17 +411,23 @@ Task(subagent_type="agent-dmitri-activity-crud", prompt='{"task":"create","workf
433
411
  }
434
412
 
435
413
  if (filePath.includes('apps/') && (filePath.endsWith('.tsx') || filePath.endsWith('.ts'))) {
436
- suggest(`💡 CONSIDER DELEGATING: Use agent-giuseppe-app-builder for app code.\n\nGiuseppe handles SDK patterns, design system, and build verification.`, 'agent-giuseppe-app-builder');
414
+ console.log(JSON.stringify({
415
+ decision: "allow",
416
+ message: `💡 CONSIDER DELEGATING: If you're the orchestrator, use agent-giuseppe-app-builder for app code.`,
417
+ }));
437
418
  return;
438
419
  }
439
420
 
440
421
  // Integration files
441
422
  if (filePath.includes('integrations/') || filePath.includes('activity-mover')) {
442
- suggest(`💡 INTEGRATIONS: Consider the specialist:\n\n- agent-igor-activity-mover-automation: Phase cascade bots\n- agent-ivan-monolith: Webhook handlers, scheduled jobs\n- agent-zara-zapier: Zapier integrations`);
423
+ console.log(JSON.stringify({
424
+ decision: "allow",
425
+ message: `💡 INTEGRATIONS: If you're the orchestrator, consider: agent-igor (movers), agent-ivan (monolith), agent-zara (Zapier).`,
426
+ }));
443
427
  return;
444
428
  }
445
429
 
446
- // General .ts/.tsx code edits - don't block in yolo, just remind about tests
430
+ // General .ts/.tsx code edits - allow with test reminder
447
431
  if ((filePath.endsWith('.ts') || filePath.endsWith('.tsx')) &&
448
432
  !filePath.includes('workspace/') &&
449
433
  !filePath.includes('apps/') &&
@@ -467,7 +451,10 @@ Task(subagent_type="agent-dmitri-activity-crud", prompt='{"task":"create","workf
467
451
  if ((agentType.includes('general') || agentType.includes('explore')) &&
468
452
  (prompt.includes('bug') || prompt.includes('debug') || prompt.includes('error') ||
469
453
  prompt.includes('not working') || prompt.includes('broken') || prompt.includes('why'))) {
470
- suggest(`💡 FOR CODE ISSUES: Consider agent-lars-code-inspector.\n\nLars uses LSP to find:\n- Dead code and unused variables\n- Unused imports\n- Type errors\n\nTask(subagent_type="agent-lars-code-inspector", prompt='{"task":"inspect","file":"path/to/file.ts"}')`, 'agent-lars-code-inspector');
454
+ console.log(JSON.stringify({
455
+ decision: "allow",
456
+ message: `💡 FOR CODE ISSUES: Consider agent-lars-code-inspector for dead code, unused imports, and type errors.`,
457
+ }));
471
458
  return;
472
459
  }
473
460
  }
@@ -29,18 +29,6 @@
29
29
  const fs = require('fs');
30
30
  const path = require('path');
31
31
 
32
- // Skip in yolo mode
33
- try {
34
- const statePath = path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), '.claude', 'yolo-state.json');
35
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
36
- if (state.mode === 'yolo') process.exit(0);
37
- } catch (e) {
38
- // ENOENT is expected when not in yolo mode - only warn on unexpected errors
39
- if (e.code !== 'ENOENT' && !e.message.includes('Unexpected')) {
40
- console.error(`[design-system-lint] Warning: ${e.message}`);
41
- }
42
- }
43
-
44
32
  // Read hook input from stdin
45
33
  let input = '';
46
34
  process.stdin.setEncoding('utf8');
@@ -31,13 +31,6 @@ const path = require('path');
31
31
  const fs = require('fs');
32
32
  const os = require('os');
33
33
 
34
- // Skip in yolo mode
35
- try {
36
- const statePath = path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), '.claude', 'yolo-state.json');
37
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
38
- if (state.mode === 'yolo') process.exit(0);
39
- } catch {}
40
-
41
34
  const TEMP_DIR = os.tmpdir();
42
35
  const TRACKER_DIR = path.join(TEMP_DIR, '.claude-scaffolded-apps');
43
36
 
@@ -23,14 +23,6 @@ const os = require('os');
23
23
  const ALLOW = JSON.stringify({ decision: 'allow' });
24
24
  const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
25
25
 
26
- // --- Yolo mode check ---
27
- let isYolo = false;
28
- try {
29
- const statePath = path.join(projectDir, '.claude', 'yolo-state.json');
30
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
31
- isYolo = state.mode === 'yolo';
32
- } catch {}
33
-
34
26
  // Skip if stdin is TTY (no piped input)
35
27
  if (process.stdin.isTTY) {
36
28
  console.log(ALLOW);
@@ -63,12 +55,10 @@ function processHook(data) {
63
55
  console.error('[prompt-guard] checkSessionStructure crashed:', e.message);
64
56
  }
65
57
 
66
- // 2. Interactive mode (every message, skipped in yolo)
58
+ // 2. Interactive mode (every message)
67
59
  try {
68
- if (!isYolo) {
69
- const interactiveMsg = checkInteractiveMode(data.prompt);
70
- if (interactiveMsg) messages.push(interactiveMsg);
71
- }
60
+ const interactiveMsg = checkInteractiveMode(data.prompt);
61
+ if (interactiveMsg) messages.push(interactiveMsg);
72
62
  } catch (e) {
73
63
  console.error('[prompt-guard] checkInteractiveMode crashed:', e.message);
74
64
  }
@@ -78,12 +68,10 @@ function processHook(data) {
78
68
  console.error('[prompt-guard] Marketplace sync crashed:', e.message);
79
69
  }
80
70
 
81
- // 4. Git hooks check (once per session, skipped in yolo)
71
+ // 4. Git hooks check (once per session)
82
72
  try {
83
- if (!isYolo) {
84
- const gitMsg = checkGitHooks();
85
- if (gitMsg) console.error(gitMsg);
86
- }
73
+ const gitMsg = checkGitHooks();
74
+ if (gitMsg) console.error(gitMsg);
87
75
  } catch (e) {
88
76
  console.error('[prompt-guard] checkGitHooks crashed:', e.message);
89
77
  }
@@ -33,16 +33,6 @@
33
33
  * </workflow>
34
34
  */
35
35
 
36
- const fs = require('fs');
37
- const path = require('path');
38
-
39
- // Skip in yolo mode
40
- try {
41
- const statePath = path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), '.claude', 'yolo-state.json');
42
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
43
- if (state.mode === 'yolo') process.exit(0);
44
- } catch {}
45
-
46
36
  // Skip in subagent context - subagents can't use AskUserQuestion to recover
47
37
  if (process.env.CLAUDE_AGENT_ID || process.env.CLAUDE_SUBAGENT) {
48
38
  console.log(JSON.stringify({ decision: 'allow' }));
@@ -39,13 +39,6 @@ const fs = require('fs');
39
39
  const path = require('path');
40
40
  const os = require('os');
41
41
 
42
- // Skip in yolo mode
43
- try {
44
- const statePath = path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), '.claude', 'yolo-state.json');
45
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
46
- if (state.mode === 'yolo') process.exit(0);
47
- } catch {}
48
-
49
42
  // Skip in subagent context - subagents can't use AskUserQuestion or Bash to recover
50
43
  if (process.env.CLAUDE_AGENT_ID || process.env.CLAUDE_SUBAGENT) {
51
44
  console.log(JSON.stringify({ decision: 'allow' }));
@@ -14,24 +14,10 @@ const crypto = require('crypto');
14
14
 
15
15
  const ALLOW = JSON.stringify({ decision: 'allow' });
16
16
 
17
- // Skip in yolo mode
18
- try {
19
- const statePath = path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), '.claude', 'yolo-state.json');
20
- const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
21
- if (state.mode === 'yolo') { console.log(ALLOW); process.exit(0); }
22
- } catch (e) {
23
- // ENOENT is expected when not in yolo mode - only warn on unexpected errors
24
- if (e.code !== 'ENOENT' && !e.message.includes('Unexpected')) {
25
- console.error(`[sync-marketplace-agents] Warning: ${e.message}`);
26
- }
27
- }
28
-
29
17
  const PLUGINS_DIR = path.join(os.homedir(), '.claude', 'plugins', 'marketplaces');
30
18
  const INSTALLED_PLUGINS = path.join(os.homedir(), '.claude', 'plugins', 'installed_plugins.json');
31
19
  const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
32
20
  const CLAUDE_MD = path.join(PROJECT_DIR, 'CLAUDE.md');
33
- const PROJECT_SETTINGS = path.join(PROJECT_DIR, '.claude', 'settings.json');
34
- const USER_SETTINGS = path.join(os.homedir(), '.claude', 'settings.json');
35
21
 
36
22
  // Store sync state in user's home, keyed by project path hash
37
23
  const SYNC_STATE_DIR = path.join(os.homedir(), '.claude', 'sync-state');