@hailer/mcp 1.1.12 â 1.1.14
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/CHANGELOG.md +0 -7
- package/{.claude â dist}/CLAUDE.md +2 -2
- package/dist/app.js +18 -5
- package/dist/bot/bot-config.d.ts +10 -1
- package/dist/bot/bot-config.js +64 -3
- package/dist/bot/bot-manager.d.ts +2 -0
- package/dist/bot/bot-manager.js +9 -2
- package/dist/bot/bot.d.ts +33 -0
- package/dist/bot/bot.js +461 -160
- package/dist/bot/services/message-classifier.js +17 -0
- package/dist/bot/services/permission-guard.d.ts +52 -0
- package/dist/bot/services/permission-guard.js +149 -0
- package/dist/bot/services/types.d.ts +5 -0
- package/dist/bot/services/typing-indicator.d.ts +6 -1
- package/dist/bot/services/typing-indicator.js +19 -3
- package/dist/cli.js +0 -0
- package/dist/config.d.ts +6 -1
- package/dist/config.js +43 -0
- package/dist/core.js +3 -6
- package/dist/lib/discussion-lock.d.ts +42 -0
- package/dist/lib/discussion-lock.js +110 -0
- package/dist/mcp/UserContextCache.d.ts +5 -0
- package/dist/mcp/UserContextCache.js +51 -19
- package/dist/mcp/hailer-clients.d.ts +19 -1
- package/dist/mcp/hailer-clients.js +158 -24
- package/dist/mcp/session-store.d.ts +68 -0
- package/dist/mcp/session-store.js +169 -0
- package/dist/mcp/signal-handler.js +2 -0
- package/dist/mcp/tool-registry.d.ts +17 -4
- package/dist/mcp/tool-registry.js +37 -7
- package/dist/mcp/tools/activity.js +99 -7
- package/dist/mcp/tools/app-scaffold.js +304 -336
- package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
- package/dist/mcp/tools/bot-config/constants.js +94 -0
- package/dist/mcp/tools/bot-config/core.d.ts +253 -0
- package/dist/mcp/tools/bot-config/core.js +2456 -0
- package/dist/mcp/tools/bot-config/index.d.ts +10 -0
- package/dist/mcp/tools/bot-config/index.js +59 -0
- package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
- package/dist/mcp/tools/bot-config/tools.js +15 -0
- package/dist/mcp/tools/bot-config/types.d.ts +50 -0
- package/dist/mcp/tools/bot-config/types.js +6 -0
- package/dist/mcp/tools/bug-fixer-tools.d.ts +45 -0
- package/dist/mcp/tools/bug-fixer-tools.js +1096 -0
- package/dist/mcp/tools/company.d.ts +9 -0
- package/dist/mcp/tools/company.js +88 -0
- package/dist/mcp/tools/discussion.js +68 -0
- package/dist/mcp/tools/document.d.ts +11 -0
- package/dist/mcp/tools/document.js +741 -0
- package/dist/mcp/tools/investigate.d.ts +9 -0
- package/dist/mcp/tools/investigate.js +254 -0
- package/dist/mcp/tools/workflow-permissions.d.ts +15 -0
- package/dist/mcp/tools/workflow-permissions.js +204 -0
- package/dist/mcp/tools/workflow.js +57 -18
- package/dist/mcp/utils/index.d.ts +2 -0
- package/dist/mcp/utils/index.js +12 -1
- package/dist/mcp/utils/role-utils.d.ts +74 -0
- package/dist/mcp/utils/role-utils.js +151 -0
- package/dist/mcp/utils/types.d.ts +43 -1
- package/dist/mcp/utils/types.js +14 -0
- package/dist/mcp/webhook-handler.d.ts +4 -0
- package/dist/mcp/webhook-handler.js +8 -0
- package/dist/mcp-server.d.ts +23 -2
- package/dist/mcp-server.js +639 -127
- package/dist/plugins/vipunen/client.d.ts +150 -0
- package/dist/plugins/vipunen/client.js +535 -0
- package/dist/plugins/vipunen/config/schema-config.json +19 -0
- package/dist/plugins/vipunen/config/schema-doc.json +22 -0
- package/dist/plugins/vipunen/index.d.ts +41 -0
- package/dist/plugins/vipunen/index.js +88 -0
- package/dist/plugins/vipunen/tools.d.ts +26 -0
- package/dist/plugins/vipunen/tools.js +501 -0
- package/dist/stdio-server.d.ts +14 -0
- package/dist/stdio-server.js +101 -0
- package/package.json +2 -1
- package/.claude/agents/agent-ada-skill-builder.md +0 -94
- package/.claude/agents/agent-alejandro-function-fields.md +0 -342
- package/.claude/agents/agent-bjorn-config-audit.md +0 -103
- package/.claude/agents/agent-builder-agent-creator.md +0 -130
- package/.claude/agents/agent-code-simplifier.md +0 -53
- package/.claude/agents/agent-dmitri-activity-crud.md +0 -159
- package/.claude/agents/agent-giuseppe-app-builder.md +0 -247
- package/.claude/agents/agent-gunther-mcp-tools.md +0 -39
- package/.claude/agents/agent-helga-workflow-config.md +0 -204
- package/.claude/agents/agent-igor-activity-mover-automation.md +0 -125
- package/.claude/agents/agent-ingrid-doc-templates.md +0 -261
- package/.claude/agents/agent-ivan-monolith.md +0 -154
- package/.claude/agents/agent-kenji-data-reader.md +0 -86
- package/.claude/agents/agent-lars-code-inspector.md +0 -102
- package/.claude/agents/agent-marco-mockup-builder.md +0 -110
- package/.claude/agents/agent-marcus-api-documenter.md +0 -323
- package/.claude/agents/agent-marketplace-publisher.md +0 -280
- package/.claude/agents/agent-marketplace-reviewer.md +0 -309
- package/.claude/agents/agent-permissions-handler.md +0 -208
- package/.claude/agents/agent-simple-writer.md +0 -48
- package/.claude/agents/agent-svetlana-code-review.md +0 -171
- package/.claude/agents/agent-tanya-test-runner.md +0 -333
- package/.claude/agents/agent-ui-designer.md +0 -100
- package/.claude/agents/agent-viktor-sql-insights.md +0 -212
- package/.claude/agents/agent-web-search.md +0 -55
- package/.claude/agents/agent-yevgeni-discussions.md +0 -45
- package/.claude/agents/agent-zara-zapier.md +0 -159
- package/.claude/commands/app-squad.md +0 -135
- package/.claude/commands/audit-squad.md +0 -158
- package/.claude/commands/autoplan.md +0 -563
- package/.claude/commands/cleanup-squad.md +0 -98
- package/.claude/commands/config-squad.md +0 -106
- package/.claude/commands/crud-squad.md +0 -87
- package/.claude/commands/data-squad.md +0 -97
- package/.claude/commands/debug-squad.md +0 -303
- package/.claude/commands/doc-squad.md +0 -65
- package/.claude/commands/handoff.md +0 -137
- package/.claude/commands/health.md +0 -49
- package/.claude/commands/help.md +0 -29
- package/.claude/commands/help:agents.md +0 -151
- package/.claude/commands/help:commands.md +0 -78
- package/.claude/commands/help:faq.md +0 -79
- package/.claude/commands/help:plugins.md +0 -50
- package/.claude/commands/help:skills.md +0 -93
- package/.claude/commands/help:tools.md +0 -75
- package/.claude/commands/hotfix-squad.md +0 -112
- package/.claude/commands/integration-squad.md +0 -82
- package/.claude/commands/janitor-squad.md +0 -167
- package/.claude/commands/learn-auto.md +0 -120
- package/.claude/commands/learn.md +0 -120
- package/.claude/commands/mcp-list.md +0 -27
- package/.claude/commands/onboard-squad.md +0 -140
- package/.claude/commands/plan-workspace.md +0 -732
- package/.claude/commands/prd.md +0 -130
- package/.claude/commands/project-status.md +0 -82
- package/.claude/commands/publish.md +0 -138
- package/.claude/commands/recap.md +0 -69
- package/.claude/commands/restore.md +0 -64
- package/.claude/commands/review-squad.md +0 -152
- package/.claude/commands/save.md +0 -24
- package/.claude/commands/stats.md +0 -19
- package/.claude/commands/swarm.md +0 -210
- package/.claude/commands/tool-builder.md +0 -39
- package/.claude/commands/ws-pull.md +0 -44
- package/.claude/hooks/_shared-memory.cjs +0 -305
- package/.claude/hooks/_utils.cjs +0 -108
- package/.claude/hooks/agent-failure-detector.cjs +0 -383
- package/.claude/hooks/agent-usage-logger.cjs +0 -204
- package/.claude/hooks/app-edit-guard.cjs +0 -494
- package/.claude/hooks/auto-learn.cjs +0 -304
- package/.claude/hooks/bash-guard.cjs +0 -272
- package/.claude/hooks/builder-mode-manager.cjs +0 -354
- package/.claude/hooks/bulk-activity-guard.cjs +0 -271
- package/.claude/hooks/context-watchdog.cjs +0 -230
- package/.claude/hooks/delegation-reminder.cjs +0 -465
- package/.claude/hooks/design-system-lint.cjs +0 -271
- package/.claude/hooks/post-scaffold-hook.cjs +0 -181
- package/.claude/hooks/prompt-guard.cjs +0 -354
- package/.claude/hooks/publish-template-guard.cjs +0 -147
- package/.claude/hooks/session-start.cjs +0 -35
- package/.claude/hooks/shared-memory-writer.cjs +0 -147
- package/.claude/hooks/skill-injector.cjs +0 -140
- package/.claude/hooks/skill-usage-logger.cjs +0 -258
- package/.claude/hooks/src-edit-guard.cjs +0 -240
- package/.claude/hooks/sync-marketplace-agents.cjs +0 -346
- package/.claude/settings.json +0 -257
- package/.claude/skills/SDK-activity-patterns/SKILL.md +0 -428
- package/.claude/skills/SDK-document-templates/SKILL.md +0 -1033
- package/.claude/skills/SDK-function-fields/SKILL.md +0 -542
- package/.claude/skills/SDK-generate-skill/SKILL.md +0 -92
- package/.claude/skills/SDK-init-skill/SKILL.md +0 -127
- package/.claude/skills/SDK-insight-queries/SKILL.md +0 -787
- package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -1139
- package/.claude/skills/agent-structure/SKILL.md +0 -98
- package/.claude/skills/api-documentation-patterns/SKILL.md +0 -474
- package/.claude/skills/chrome-mcp-reference/SKILL.md +0 -370
- package/.claude/skills/delegation-routing/SKILL.md +0 -202
- package/.claude/skills/frontend-design/SKILL.md +0 -254
- package/.claude/skills/hailer-activity-mover/SKILL.md +0 -213
- package/.claude/skills/hailer-api-client/SKILL.md +0 -518
- package/.claude/skills/hailer-app-builder/SKILL.md +0 -1434
- package/.claude/skills/hailer-apps-pictures/SKILL.md +0 -269
- package/.claude/skills/hailer-design-system/SKILL.md +0 -235
- package/.claude/skills/hailer-monolith-automations/SKILL.md +0 -686
- package/.claude/skills/hailer-permissions-system/SKILL.md +0 -121
- package/.claude/skills/hailer-project-protocol/SKILL.md +0 -488
- package/.claude/skills/hailer-rest-api/SKILL.md +0 -61
- package/.claude/skills/hailer-rest-api/hailer-activities.md +0 -184
- package/.claude/skills/hailer-rest-api/hailer-admin.md +0 -473
- package/.claude/skills/hailer-rest-api/hailer-calendar.md +0 -256
- package/.claude/skills/hailer-rest-api/hailer-feed.md +0 -249
- package/.claude/skills/hailer-rest-api/hailer-insights.md +0 -195
- package/.claude/skills/hailer-rest-api/hailer-messaging.md +0 -276
- package/.claude/skills/hailer-rest-api/hailer-workflows.md +0 -283
- package/.claude/skills/insight-join-patterns/SKILL.md +0 -174
- package/.claude/skills/integration-patterns/SKILL.md +0 -421
- package/.claude/skills/json-only-output/SKILL.md +0 -72
- package/.claude/skills/lsp-setup/SKILL.md +0 -160
- package/.claude/skills/mcp-direct-tools/SKILL.md +0 -153
- package/.claude/skills/optional-parameters/SKILL.md +0 -72
- package/.claude/skills/publish-hailer-app/SKILL.md +0 -244
- package/.claude/skills/testing-patterns/SKILL.md +0 -630
- package/.claude/skills/tool-builder/SKILL.md +0 -250
- package/.claude/skills/tool-parameter-usage/SKILL.md +0 -126
- package/.claude/skills/tool-response-verification/SKILL.md +0 -92
- package/.claude/skills/zapier-hailer-patterns/SKILL.md +0 -581
- package/.mcp.json +0 -13
- package/.opencode/agent/agent-ada-skill-builder.md +0 -35
- package/.opencode/agent/agent-alejandro-function-fields.md +0 -39
- package/.opencode/agent/agent-bjorn-config-audit.md +0 -36
- package/.opencode/agent/agent-builder-agent-creator.md +0 -39
- package/.opencode/agent/agent-code-simplifier.md +0 -31
- package/.opencode/agent/agent-dmitri-activity-crud.md +0 -40
- package/.opencode/agent/agent-giuseppe-app-builder.md +0 -37
- package/.opencode/agent/agent-gunther-mcp-tools.md +0 -39
- package/.opencode/agent/agent-helga-workflow-config.md +0 -203
- package/.opencode/agent/agent-igor-activity-mover-automation.md +0 -46
- package/.opencode/agent/agent-ingrid-doc-templates.md +0 -39
- package/.opencode/agent/agent-ivan-monolith.md +0 -46
- package/.opencode/agent/agent-kenji-data-reader.md +0 -53
- package/.opencode/agent/agent-lars-code-inspector.md +0 -28
- package/.opencode/agent/agent-marco-mockup-builder.md +0 -42
- package/.opencode/agent/agent-marcus-api-documenter.md +0 -53
- package/.opencode/agent/agent-marketplace-publisher.md +0 -44
- package/.opencode/agent/agent-marketplace-reviewer.md +0 -42
- package/.opencode/agent/agent-permissions-handler.md +0 -50
- package/.opencode/agent/agent-simple-writer.md +0 -45
- package/.opencode/agent/agent-svetlana-code-review.md +0 -39
- package/.opencode/agent/agent-tanya-test-runner.md +0 -57
- package/.opencode/agent/agent-ui-designer.md +0 -56
- package/.opencode/agent/agent-viktor-sql-insights.md +0 -34
- package/.opencode/agent/agent-web-search.md +0 -42
- package/.opencode/agent/agent-yevgeni-discussions.md +0 -37
- package/.opencode/agent/agent-zara-zapier.md +0 -53
- package/.opencode/commands/app-squad.md +0 -135
- package/.opencode/commands/audit-squad.md +0 -158
- package/.opencode/commands/autoplan.md +0 -563
- package/.opencode/commands/cleanup-squad.md +0 -98
- package/.opencode/commands/config-squad.md +0 -106
- package/.opencode/commands/crud-squad.md +0 -87
- package/.opencode/commands/data-squad.md +0 -97
- package/.opencode/commands/debug-squad.md +0 -303
- package/.opencode/commands/doc-squad.md +0 -65
- package/.opencode/commands/handoff.md +0 -137
- package/.opencode/commands/health.md +0 -49
- package/.opencode/commands/help-agents.md +0 -151
- package/.opencode/commands/help-commands.md +0 -32
- package/.opencode/commands/help-faq.md +0 -29
- package/.opencode/commands/help-plugins.md +0 -28
- package/.opencode/commands/help-skills.md +0 -7
- package/.opencode/commands/help-tools.md +0 -40
- package/.opencode/commands/help.md +0 -28
- package/.opencode/commands/hotfix-squad.md +0 -112
- package/.opencode/commands/integration-squad.md +0 -82
- package/.opencode/commands/janitor-squad.md +0 -167
- package/.opencode/commands/learn-auto.md +0 -120
- package/.opencode/commands/learn.md +0 -120
- package/.opencode/commands/mcp-list.md +0 -27
- package/.opencode/commands/onboard-squad.md +0 -140
- package/.opencode/commands/plan-workspace.md +0 -732
- package/.opencode/commands/prd.md +0 -131
- package/.opencode/commands/project-status.md +0 -82
- package/.opencode/commands/publish.md +0 -138
- package/.opencode/commands/recap.md +0 -69
- package/.opencode/commands/restore.md +0 -64
- package/.opencode/commands/review-squad.md +0 -152
- package/.opencode/commands/save.md +0 -24
- package/.opencode/commands/stats.md +0 -19
- package/.opencode/commands/swarm.md +0 -210
- package/.opencode/commands/tool-builder.md +0 -39
- package/.opencode/commands/ws-pull.md +0 -44
- package/.opencode/opencode.json +0 -28
- package/SESSION-HANDOFF.md +0 -68
- package/inbox/2026-03-04-bot-config-patterns.md +0 -24
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* <hook-name>skill-injector</hook-name>
|
|
4
|
-
* <purpose>Auto-injects skill content into subagent context via SubagentStart</purpose>
|
|
5
|
-
* <triggers>SubagentStart</triggers>
|
|
6
|
-
*
|
|
7
|
-
* Problem: Agents have skills listed in frontmatter but never actually call
|
|
8
|
-
* the Skill tool. This hook reads the agent's frontmatter `skills:` list
|
|
9
|
-
* and injects skill content via additionalContext when the subagent starts.
|
|
10
|
-
*
|
|
11
|
-
* Uses SubagentStart hook event with additionalContext (not PreToolUse updatedInput).
|
|
12
|
-
*
|
|
13
|
-
* Hook type: SubagentStart
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const fs = require('fs');
|
|
17
|
-
const path = require('path');
|
|
18
|
-
|
|
19
|
-
const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
20
|
-
const AGENTS_DIR = path.join(PROJECT_DIR, '.claude', 'agents');
|
|
21
|
-
const SKILLS_DIR = path.join(PROJECT_DIR, '.claude', 'skills');
|
|
22
|
-
|
|
23
|
-
// Skip if stdin is TTY
|
|
24
|
-
if (process.stdin.isTTY) {
|
|
25
|
-
console.log(JSON.stringify({}));
|
|
26
|
-
process.exit(0);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
let input = '';
|
|
30
|
-
process.stdin.setEncoding('utf8');
|
|
31
|
-
process.stdin.on('data', chunk => input += chunk);
|
|
32
|
-
process.stdin.on('end', () => {
|
|
33
|
-
try {
|
|
34
|
-
const data = JSON.parse(input);
|
|
35
|
-
processHook(data);
|
|
36
|
-
} catch (e) {
|
|
37
|
-
console.error(`[skill-injector] Parse error: ${e.message}`);
|
|
38
|
-
console.log(JSON.stringify({}));
|
|
39
|
-
process.exit(0);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Parse skills: list from agent frontmatter
|
|
45
|
-
*/
|
|
46
|
-
function getAgentSkills(agentType) {
|
|
47
|
-
const agentFile = path.join(AGENTS_DIR, `${agentType}.md`);
|
|
48
|
-
if (!fs.existsSync(agentFile)) {
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
const content = fs.readFileSync(agentFile, 'utf8');
|
|
54
|
-
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
55
|
-
if (!fmMatch) return [];
|
|
56
|
-
|
|
57
|
-
const frontmatter = fmMatch[1];
|
|
58
|
-
const skills = [];
|
|
59
|
-
let inSkills = false;
|
|
60
|
-
|
|
61
|
-
for (const line of frontmatter.split('\n')) {
|
|
62
|
-
if (line.match(/^skills:\s*$/)) {
|
|
63
|
-
inSkills = true;
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
if (inSkills) {
|
|
67
|
-
const skillMatch = line.match(/^\s+-\s+(.+)$/);
|
|
68
|
-
if (skillMatch) {
|
|
69
|
-
skills.push(skillMatch[1].trim());
|
|
70
|
-
} else {
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return skills;
|
|
77
|
-
} catch (e) {
|
|
78
|
-
console.error(`[skill-injector] Error reading ${agentFile}: ${e.message}`);
|
|
79
|
-
return [];
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Read skill content from SKILL.md
|
|
85
|
-
*/
|
|
86
|
-
function readSkillContent(skillName) {
|
|
87
|
-
const skillFile = path.join(SKILLS_DIR, skillName, 'SKILL.md');
|
|
88
|
-
if (!fs.existsSync(skillFile)) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
const content = fs.readFileSync(skillFile, 'utf8');
|
|
94
|
-
// Limit to 20KB per skill to avoid bloating context
|
|
95
|
-
if (content.length > 20000) {
|
|
96
|
-
return content.substring(0, 20000) + '\n\n[... truncated at 20KB ...]';
|
|
97
|
-
}
|
|
98
|
-
return content;
|
|
99
|
-
} catch (e) {
|
|
100
|
-
console.error(`[skill-injector] Error reading skill ${skillName}: ${e.message}`);
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function processHook(data) {
|
|
106
|
-
const agentType = data.agent_type || '';
|
|
107
|
-
|
|
108
|
-
// Get skills for this agent type
|
|
109
|
-
const skills = getAgentSkills(agentType);
|
|
110
|
-
if (skills.length === 0) {
|
|
111
|
-
console.log(JSON.stringify({}));
|
|
112
|
-
process.exit(0);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Load skill contents
|
|
116
|
-
const skillBlocks = [];
|
|
117
|
-
for (const skillName of skills) {
|
|
118
|
-
const content = readSkillContent(skillName);
|
|
119
|
-
if (content) {
|
|
120
|
-
skillBlocks.push(`<skill name="${skillName}">\n${content}\n</skill>`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (skillBlocks.length === 0) {
|
|
125
|
-
console.log(JSON.stringify({}));
|
|
126
|
-
process.exit(0);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const skillSection = `<injected-skills>\nThe following skills have been auto-loaded based on your agent configuration. Use this knowledge for your task.\n\n${skillBlocks.join('\n\n')}\n</injected-skills>`;
|
|
130
|
-
|
|
131
|
-
console.error(`[skill-injector] Injected ${skillBlocks.length} skill(s) into ${agentType}: ${skills.join(', ')}`);
|
|
132
|
-
|
|
133
|
-
console.log(JSON.stringify({
|
|
134
|
-
hookSpecificOutput: {
|
|
135
|
-
hookEventName: 'SubagentStart',
|
|
136
|
-
additionalContext: skillSection
|
|
137
|
-
}
|
|
138
|
-
}));
|
|
139
|
-
process.exit(0);
|
|
140
|
-
}
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* <hook-name>skill-usage-logger</hook-name>
|
|
4
|
-
*
|
|
5
|
-
* <purpose>
|
|
6
|
-
* Logs every skill load for analytics - which skills are used, by which agents, in which projects.
|
|
7
|
-
* </purpose>
|
|
8
|
-
*
|
|
9
|
-
* <triggers>
|
|
10
|
-
* - PostToolUse on Skill
|
|
11
|
-
* </triggers>
|
|
12
|
-
*
|
|
13
|
-
* <log-file>$CLAUDE_PROJECT_DIR/inbox/skill-usage.jsonl</log-file>
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const fs = require('fs');
|
|
17
|
-
const path = require('path');
|
|
18
|
-
const os = require('os');
|
|
19
|
-
|
|
20
|
-
const LOG_FILE = path.join(
|
|
21
|
-
process.env.HAILER_INBOX_DIR || path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), 'inbox'),
|
|
22
|
-
'skill-usage.jsonl'
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
// Read hook input from stdin
|
|
26
|
-
let input = '';
|
|
27
|
-
process.stdin.setEncoding('utf8');
|
|
28
|
-
process.stdin.on('data', chunk => input += chunk);
|
|
29
|
-
process.stdin.on('end', () => {
|
|
30
|
-
try {
|
|
31
|
-
const data = JSON.parse(input);
|
|
32
|
-
processHook(data);
|
|
33
|
-
} catch (e) {
|
|
34
|
-
console.error(`[skill-usage-logger] Failed to parse input: ${e.message}`);
|
|
35
|
-
process.exit(0);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Detect if running in subagent context from transcript_path
|
|
41
|
-
* Subagent paths contain /subagents/
|
|
42
|
-
* Returns: { isSubagent: boolean, agentName: string | null }
|
|
43
|
-
*/
|
|
44
|
-
function detectSubagentContext(transcriptPath) {
|
|
45
|
-
if (!transcriptPath) {
|
|
46
|
-
return { isSubagent: false, agentName: null };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Subagent paths look like: .../{session_id}/subagents/agent-{agent_id}.jsonl
|
|
50
|
-
if (transcriptPath.includes('/subagents/')) {
|
|
51
|
-
// Extract agent name from path
|
|
52
|
-
const match = transcriptPath.match(/subagents\/([^/]+)\.jsonl$/);
|
|
53
|
-
if (match) {
|
|
54
|
-
// Clean up agent ID - might be like "agent-a7004fa" or full name
|
|
55
|
-
return { isSubagent: true, agentName: match[1] };
|
|
56
|
-
}
|
|
57
|
-
return { isSubagent: true, agentName: 'unknown' };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return { isSubagent: false, agentName: null };
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function processHook(data) {
|
|
64
|
-
const { tool_name, tool_input, tool_response, transcript_path } = data;
|
|
65
|
-
|
|
66
|
-
// Only process Skill tool
|
|
67
|
-
if (tool_name !== 'Skill') {
|
|
68
|
-
process.exit(0);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Extract skill name from tool_input
|
|
72
|
-
const skillName = tool_input?.skill || tool_input?.command || 'unknown';
|
|
73
|
-
const skillArgs = tool_input?.args || null;
|
|
74
|
-
|
|
75
|
-
// Detect subagent context
|
|
76
|
-
const { isSubagent, agentName } = detectSubagentContext(transcript_path);
|
|
77
|
-
|
|
78
|
-
// Get project from env or cwd
|
|
79
|
-
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
80
|
-
const project = path.basename(projectDir);
|
|
81
|
-
|
|
82
|
-
const entry = {
|
|
83
|
-
ts: new Date().toISOString(),
|
|
84
|
-
skill: skillName,
|
|
85
|
-
agent: isSubagent ? agentName : 'orchestrator',
|
|
86
|
-
isSubagent,
|
|
87
|
-
project,
|
|
88
|
-
args: skillArgs
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
// Ensure directory exists
|
|
93
|
-
const logDir = path.dirname(LOG_FILE);
|
|
94
|
-
if (!fs.existsSync(logDir)) {
|
|
95
|
-
fs.mkdirSync(logDir, { recursive: true });
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
fs.appendFileSync(LOG_FILE, JSON.stringify(entry) + '\n');
|
|
99
|
-
} catch (err) {
|
|
100
|
-
console.error(`[skill-usage-logger] Could not write: ${err.message}`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
process.exit(0);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// CLI: Show recent skill loads
|
|
107
|
-
if (process.argv[2] === '--recent' || process.argv[2] === '-r') {
|
|
108
|
-
const limit = parseInt(process.argv[3]) || 20;
|
|
109
|
-
|
|
110
|
-
if (!fs.existsSync(LOG_FILE)) {
|
|
111
|
-
console.log('No skill usage data yet');
|
|
112
|
-
process.exit(0);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const lines = fs.readFileSync(LOG_FILE, 'utf8').trim().split('\n');
|
|
116
|
-
const recent = lines.slice(-limit);
|
|
117
|
-
|
|
118
|
-
console.log(`Last ${recent.length} skill loads:\n`);
|
|
119
|
-
console.log('Time'.padEnd(10) + 'Skill'.padEnd(30) + 'Agent'.padEnd(20) + 'Project');
|
|
120
|
-
console.log('-'.repeat(75));
|
|
121
|
-
|
|
122
|
-
for (const line of recent) {
|
|
123
|
-
try {
|
|
124
|
-
const entry = JSON.parse(line);
|
|
125
|
-
const time = entry.ts.split('T')[1].split('.')[0];
|
|
126
|
-
const agent = entry.isSubagent ? entry.agent : 'orchestrator';
|
|
127
|
-
console.log(`${time.padEnd(10)}${entry.skill.padEnd(30)}${agent.padEnd(20)}${entry.project}`);
|
|
128
|
-
} catch {}
|
|
129
|
-
}
|
|
130
|
-
process.exit(0);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// CLI: Show stats by skill
|
|
134
|
-
if (process.argv[2] === '--stats' || process.argv[2] === '-s') {
|
|
135
|
-
if (!fs.existsSync(LOG_FILE)) {
|
|
136
|
-
console.log('No skill usage data yet');
|
|
137
|
-
process.exit(0);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const lines = fs.readFileSync(LOG_FILE, 'utf8').trim().split('\n');
|
|
141
|
-
const skillStats = {};
|
|
142
|
-
const agentSkills = {};
|
|
143
|
-
|
|
144
|
-
for (const line of lines) {
|
|
145
|
-
try {
|
|
146
|
-
const entry = JSON.parse(line);
|
|
147
|
-
|
|
148
|
-
// Count by skill
|
|
149
|
-
if (!skillStats[entry.skill]) {
|
|
150
|
-
skillStats[entry.skill] = { total: 0, byOrchestrator: 0, bySubagent: 0 };
|
|
151
|
-
}
|
|
152
|
-
skillStats[entry.skill].total++;
|
|
153
|
-
if (entry.isSubagent) {
|
|
154
|
-
skillStats[entry.skill].bySubagent++;
|
|
155
|
-
} else {
|
|
156
|
-
skillStats[entry.skill].byOrchestrator++;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Track which agents use which skills
|
|
160
|
-
if (entry.isSubagent && entry.agent) {
|
|
161
|
-
if (!agentSkills[entry.agent]) {
|
|
162
|
-
agentSkills[entry.agent] = new Set();
|
|
163
|
-
}
|
|
164
|
-
agentSkills[entry.agent].add(entry.skill);
|
|
165
|
-
}
|
|
166
|
-
} catch {}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
console.log('Skill Usage Stats:\n');
|
|
170
|
-
console.log('Skill'.padEnd(35) + 'Total'.padEnd(8) + 'Orch'.padEnd(8) + 'Subagent');
|
|
171
|
-
console.log('-'.repeat(60));
|
|
172
|
-
|
|
173
|
-
const sorted = Object.entries(skillStats).sort((a, b) => b[1].total - a[1].total);
|
|
174
|
-
for (const [skill, s] of sorted) {
|
|
175
|
-
console.log(`${skill.padEnd(35)}${String(s.total).padEnd(8)}${String(s.byOrchestrator).padEnd(8)}${s.bySubagent}`);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
console.log('-'.repeat(60));
|
|
179
|
-
console.log(`Total: ${lines.length} skill loads\n`);
|
|
180
|
-
|
|
181
|
-
// Show agent -> skill mapping
|
|
182
|
-
if (Object.keys(agentSkills).length > 0) {
|
|
183
|
-
console.log('Skills by Agent:\n');
|
|
184
|
-
for (const [agent, skills] of Object.entries(agentSkills)) {
|
|
185
|
-
console.log(` ${agent}: ${[...skills].join(', ')}`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
process.exit(0);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// CLI: Show unused skills (skills in .claude/skills/ not in log)
|
|
193
|
-
if (process.argv[2] === '--unused' || process.argv[2] === '-u') {
|
|
194
|
-
const skillsDir = path.join(process.cwd(), '.claude', 'skills');
|
|
195
|
-
|
|
196
|
-
if (!fs.existsSync(skillsDir)) {
|
|
197
|
-
console.log('No .claude/skills/ directory found');
|
|
198
|
-
process.exit(0);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Get all skill directories
|
|
202
|
-
const allSkills = fs.readdirSync(skillsDir, { withFileTypes: true })
|
|
203
|
-
.filter(d => d.isDirectory())
|
|
204
|
-
.map(d => d.name);
|
|
205
|
-
|
|
206
|
-
// Get used skills from log
|
|
207
|
-
const usedSkills = new Set();
|
|
208
|
-
if (fs.existsSync(LOG_FILE)) {
|
|
209
|
-
const lines = fs.readFileSync(LOG_FILE, 'utf8').trim().split('\n');
|
|
210
|
-
for (const line of lines) {
|
|
211
|
-
try {
|
|
212
|
-
const entry = JSON.parse(line);
|
|
213
|
-
usedSkills.add(entry.skill);
|
|
214
|
-
} catch {}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const unused = allSkills.filter(s => !usedSkills.has(s));
|
|
219
|
-
|
|
220
|
-
if (unused.length === 0) {
|
|
221
|
-
console.log('All skills have been used at least once!');
|
|
222
|
-
} else {
|
|
223
|
-
console.log(`Unused skills (${unused.length}):\n`);
|
|
224
|
-
for (const skill of unused.sort()) {
|
|
225
|
-
console.log(` - ${skill}`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
process.exit(0);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// CLI: Clear log
|
|
233
|
-
if (process.argv[2] === '--clear') {
|
|
234
|
-
if (fs.existsSync(LOG_FILE)) {
|
|
235
|
-
fs.unlinkSync(LOG_FILE);
|
|
236
|
-
console.log('â Skill usage log cleared');
|
|
237
|
-
} else {
|
|
238
|
-
console.log('No log file to clear');
|
|
239
|
-
}
|
|
240
|
-
process.exit(0);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// CLI: Help
|
|
244
|
-
if (process.argv[2] === '--help' || process.argv[2] === '-h') {
|
|
245
|
-
console.log(`
|
|
246
|
-
Skill Usage Logger - Track skill loads by agents
|
|
247
|
-
|
|
248
|
-
Usage:
|
|
249
|
-
node skill-usage-logger.cjs --recent [N] Show last N skill loads (default 20)
|
|
250
|
-
node skill-usage-logger.cjs --stats Show usage statistics
|
|
251
|
-
node skill-usage-logger.cjs --unused Show skills never loaded
|
|
252
|
-
node skill-usage-logger.cjs --clear Clear the log
|
|
253
|
-
node skill-usage-logger.cjs --help Show this help
|
|
254
|
-
|
|
255
|
-
Log file: ${LOG_FILE}
|
|
256
|
-
`);
|
|
257
|
-
process.exit(0);
|
|
258
|
-
}
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* <hook-name>src-edit-guard</hook-name>
|
|
4
|
-
*
|
|
5
|
-
* <purpose>
|
|
6
|
-
* Blocks direct edits to src/ directory.
|
|
7
|
-
* Forces main agent to spawn subagents for MCP server code changes.
|
|
8
|
-
* Preserves orchestrator context by delegating implementation work.
|
|
9
|
-
* </purpose>
|
|
10
|
-
*
|
|
11
|
-
* <triggers>
|
|
12
|
-
* - PreToolUse on Write and Edit tools
|
|
13
|
-
* - Only when file path starts with src/
|
|
14
|
-
* </triggers>
|
|
15
|
-
*
|
|
16
|
-
* <allowed-when>
|
|
17
|
-
* - Builder mode is active (/tmp/.claude-builder-agent-active exists)
|
|
18
|
-
* - File is outside src/ directory
|
|
19
|
-
* </allowed-when>
|
|
20
|
-
*
|
|
21
|
-
* <behavior>
|
|
22
|
-
* 1. Checks if file is in src/ directory
|
|
23
|
-
* 2. Checks builder mode status
|
|
24
|
-
* 3. Blocks with instructions to spawn general-purpose agent
|
|
25
|
-
* </behavior>
|
|
26
|
-
*
|
|
27
|
-
* <shared-files>
|
|
28
|
-
* /tmp/.claude-builder-agent-active (shared with app-edit-guard, builder-mode-manager)
|
|
29
|
-
* </shared-files>
|
|
30
|
-
*
|
|
31
|
-
* <cli-commands>
|
|
32
|
-
* --on: Enable builder mode (allow src/ edits)
|
|
33
|
-
* --off: Disable builder mode (block src/ edits)
|
|
34
|
-
* --status: Check current mode
|
|
35
|
-
* </cli-commands>
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
const fs = require('fs');
|
|
39
|
-
const path = require('path');
|
|
40
|
-
const os = require('os');
|
|
41
|
-
|
|
42
|
-
// Skip in subagent context - subagents can't use AskUserQuestion or Bash to recover
|
|
43
|
-
if (process.env.CLAUDE_AGENT_ID || process.env.CLAUDE_SUBAGENT) {
|
|
44
|
-
console.log(JSON.stringify({ decision: 'allow' }));
|
|
45
|
-
process.exit(0);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// UNIFIED: Use same builder mode file as app-edit-guard.cjs
|
|
49
|
-
const TEMP_DIR = os.tmpdir();
|
|
50
|
-
const BUILDER_MODE_FILE = path.join(TEMP_DIR, '.claude-builder-agent-active');
|
|
51
|
-
|
|
52
|
-
// Read hook input from stdin
|
|
53
|
-
let input = '';
|
|
54
|
-
process.stdin.setEncoding('utf8');
|
|
55
|
-
process.stdin.on('data', chunk => input += chunk);
|
|
56
|
-
process.stdin.on('end', () => {
|
|
57
|
-
try {
|
|
58
|
-
const data = JSON.parse(input);
|
|
59
|
-
processHook(data);
|
|
60
|
-
} catch (e) {
|
|
61
|
-
// Invalid JSON - allow to avoid blocking legitimate operations
|
|
62
|
-
outputAllow();
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
function outputAllow() {
|
|
67
|
-
console.log(JSON.stringify({ decision: 'allow' }));
|
|
68
|
-
process.exit(0);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function outputBlock(message) {
|
|
72
|
-
console.log(JSON.stringify({
|
|
73
|
-
decision: 'block',
|
|
74
|
-
reason: message
|
|
75
|
-
}));
|
|
76
|
-
process.exit(0);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Check if builder mode is active (subagent editing)
|
|
81
|
-
*/
|
|
82
|
-
function isBuilderModeActive() {
|
|
83
|
-
try {
|
|
84
|
-
return fs.existsSync(BUILDER_MODE_FILE);
|
|
85
|
-
} catch {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Enable builder mode
|
|
92
|
-
*/
|
|
93
|
-
function enableBuilderMode() {
|
|
94
|
-
fs.writeFileSync(BUILDER_MODE_FILE, JSON.stringify({
|
|
95
|
-
enabledAt: new Date().toISOString(),
|
|
96
|
-
pid: process.pid
|
|
97
|
-
}));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Disable builder mode
|
|
102
|
-
*/
|
|
103
|
-
function disableBuilderMode() {
|
|
104
|
-
if (fs.existsSync(BUILDER_MODE_FILE)) {
|
|
105
|
-
fs.unlinkSync(BUILDER_MODE_FILE);
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function processHook(data) {
|
|
112
|
-
const { tool_name, tool_input } = data;
|
|
113
|
-
|
|
114
|
-
// Only guard Write and Edit tools
|
|
115
|
-
if (tool_name !== 'Write' && tool_name !== 'Edit') {
|
|
116
|
-
outputAllow();
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const filePath = tool_input?.file_path;
|
|
121
|
-
if (!filePath) {
|
|
122
|
-
outputAllow();
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Normalize and get relative path
|
|
127
|
-
const normalizedPath = path.resolve(filePath);
|
|
128
|
-
const projectRoot = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
129
|
-
const relativePath = path.relative(projectRoot, normalizedPath);
|
|
130
|
-
|
|
131
|
-
// Check if file is in src/ directory
|
|
132
|
-
const isInSrc = relativePath.startsWith('src/') || relativePath.startsWith('src\\');
|
|
133
|
-
|
|
134
|
-
if (!isInSrc) {
|
|
135
|
-
// Not in src/ directory - allow
|
|
136
|
-
outputAllow();
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Check if builder mode is active - ALLOW
|
|
141
|
-
if (isBuilderModeActive()) {
|
|
142
|
-
outputAllow();
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// BLOCK with helpful message
|
|
147
|
-
outputBlock(`
|
|
148
|
-
đĢ BLOCKED: Direct edit to source file
|
|
149
|
-
|
|
150
|
-
File: ${relativePath}
|
|
151
|
-
|
|
152
|
-
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
153
|
-
WHY: Use a subagent to save your context for orchestration
|
|
154
|
-
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
155
|
-
|
|
156
|
-
TO PROCEED: Spawn a general-purpose agent with detailed instructions:
|
|
157
|
-
|
|
158
|
-
Task({
|
|
159
|
-
subagent_type: "general-purpose",
|
|
160
|
-
description: "Fix issue #XX",
|
|
161
|
-
prompt: \`
|
|
162
|
-
[Detailed instructions for the change]
|
|
163
|
-
|
|
164
|
-
File to modify: ${relativePath}
|
|
165
|
-
|
|
166
|
-
[Explain what to change and why]
|
|
167
|
-
\`
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
The agent will:
|
|
171
|
-
1. Make the code changes
|
|
172
|
-
2. Verify the build passes
|
|
173
|
-
3. Report back results
|
|
174
|
-
|
|
175
|
-
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
176
|
-
OR: Enable builder mode temporarily (if you need to edit directly)
|
|
177
|
-
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
178
|
-
|
|
179
|
-
Bash: node .claude/hooks/src-edit-guard.cjs --on
|
|
180
|
-
[Make your edits]
|
|
181
|
-
Bash: node .claude/hooks/src-edit-guard.cjs --off
|
|
182
|
-
`);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// CLI: Enable builder mode
|
|
186
|
-
if (process.argv[2] === '--on') {
|
|
187
|
-
enableBuilderMode();
|
|
188
|
-
console.log('đ§ Builder mode ENABLED - src/ edits now allowed');
|
|
189
|
-
process.exit(0);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// CLI: Disable builder mode
|
|
193
|
-
if (process.argv[2] === '--off') {
|
|
194
|
-
if (disableBuilderMode()) {
|
|
195
|
-
console.log('đ Builder mode DISABLED - src/ edits blocked again');
|
|
196
|
-
} else {
|
|
197
|
-
console.log('âšī¸ Builder mode was not active');
|
|
198
|
-
}
|
|
199
|
-
process.exit(0);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// CLI: Check status
|
|
203
|
-
if (process.argv[2] === '--status') {
|
|
204
|
-
if (isBuilderModeActive()) {
|
|
205
|
-
const data = JSON.parse(fs.readFileSync(BUILDER_MODE_FILE, 'utf8'));
|
|
206
|
-
console.log(`đ§ Builder mode is ACTIVE (enabled at ${data.enabledAt})`);
|
|
207
|
-
} else {
|
|
208
|
-
console.log('đ Builder mode is OFF - src/ edits are blocked');
|
|
209
|
-
}
|
|
210
|
-
process.exit(0);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// CLI: Help
|
|
214
|
-
if (process.argv[2] === '--help' || process.argv[2] === '-h') {
|
|
215
|
-
console.log(`
|
|
216
|
-
Source Code Edit Guard - Blocks direct edits to src/ directory
|
|
217
|
-
|
|
218
|
-
Usage:
|
|
219
|
-
node src-edit-guard.cjs --on Enable builder mode (allow edits)
|
|
220
|
-
node src-edit-guard.cjs --off Disable builder mode (block edits)
|
|
221
|
-
node src-edit-guard.cjs --status Check current mode
|
|
222
|
-
node src-edit-guard.cjs --help Show this help
|
|
223
|
-
|
|
224
|
-
UNIFIED SYSTEM: This hook uses the same builder mode file as app-edit-guard.cjs.
|
|
225
|
-
Enabling builder mode here also enables it for Hailer app edits, and vice versa.
|
|
226
|
-
|
|
227
|
-
Preferred commands (via app-edit-guard.cjs):
|
|
228
|
-
node app-edit-guard.cjs --agent-on Enable global builder mode
|
|
229
|
-
node app-edit-guard.cjs --agent-off Disable global builder mode
|
|
230
|
-
|
|
231
|
-
As a hook:
|
|
232
|
-
Reads JSON from stdin with tool_name and tool_input
|
|
233
|
-
Outputs JSON with decision: "allow" or "block"
|
|
234
|
-
|
|
235
|
-
Purpose:
|
|
236
|
-
Forces the main Claude agent to spawn subagents for code changes.
|
|
237
|
-
This saves context in the main agent for orchestration tasks.
|
|
238
|
-
`);
|
|
239
|
-
process.exit(0);
|
|
240
|
-
}
|