claude-brain 0.30.2 → 0.30.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +241 -191
- package/VERSION +1 -1
- package/assets/CLAUDE-unified.md +11 -11
- package/assets/CLAUDE.md +29 -29
- package/package.json +7 -3
- package/packs/backend/node.json +173 -173
- package/packs/core/javascript.json +176 -176
- package/packs/core/typescript.json +222 -222
- package/packs/frontend/react.json +254 -254
- package/packs/meta/testing.json +172 -172
- package/scripts/postinstall.mjs +531 -531
- package/src/automation/decision-detector.ts +452 -452
- package/src/automation/phase12-manager.ts +456 -456
- package/src/automation/proactive-recall.ts +373 -373
- package/src/automation/project-detector.ts +310 -310
- package/src/automation/repo-scanner.ts +210 -205
- package/src/cli/auto-setup.ts +75 -75
- package/src/cli/auto-start.ts +266 -266
- package/src/cli/bin.ts +264 -264
- package/src/cli/commands/autostart.ts +90 -90
- package/src/cli/commands/chroma.ts +578 -577
- package/src/cli/commands/export-training.ts +70 -70
- package/src/cli/commands/export.ts +130 -130
- package/src/cli/commands/git-hook.ts +183 -183
- package/src/cli/commands/hooks.ts +217 -217
- package/src/cli/commands/init.ts +123 -123
- package/src/cli/commands/install-mcp.ts +122 -111
- package/src/cli/commands/models.ts +979 -979
- package/src/cli/commands/pack.ts +200 -200
- package/src/cli/commands/refresh.ts +344 -339
- package/src/cli/commands/reindex.ts +120 -120
- package/src/cli/commands/serve.ts +466 -463
- package/src/cli/commands/start.ts +44 -44
- package/src/cli/commands/status.ts +220 -203
- package/src/cli/commands/uninstall-mcp.ts +45 -41
- package/src/cli/commands/update.ts +130 -124
- package/src/cli/migrate-chroma.ts +106 -106
- package/src/cli/ui/animations.ts +80 -80
- package/src/cli/ui/components.ts +82 -82
- package/src/cli/ui/index.ts +4 -4
- package/src/cli/ui/logo.ts +36 -36
- package/src/cli/ui/theme.ts +55 -55
- package/src/code-intelligence/indexer.ts +352 -352
- package/src/code-intelligence/linker.ts +178 -178
- package/src/code-intelligence/parser.ts +484 -484
- package/src/code-intelligence/query.ts +291 -291
- package/src/code-intelligence/schema.ts +83 -83
- package/src/code-intelligence/types.ts +95 -95
- package/src/config/defaults.ts +52 -52
- package/src/config/home.ts +56 -56
- package/src/config/index.ts +5 -5
- package/src/config/loader.ts +192 -192
- package/src/config/schema.ts +446 -415
- package/src/config/validator.ts +182 -182
- package/src/context/assembler.ts +407 -400
- package/src/context/index.ts +79 -79
- package/src/context/progress-tracker.ts +174 -174
- package/src/context/standards-manager.ts +287 -287
- package/src/context/validator.ts +58 -58
- package/src/diagnostics/index.ts +122 -121
- package/src/health/index.ts +233 -232
- package/src/hooks/brain-hook.ts +134 -131
- package/src/hooks/capture.ts +168 -168
- package/src/hooks/claude-code-mastery.md +112 -112
- package/src/hooks/context-hook.ts +260 -245
- package/src/hooks/deduplicator.ts +72 -72
- package/src/hooks/git-capture.ts +109 -109
- package/src/hooks/git-hook-installer.ts +211 -207
- package/src/hooks/index.ts +20 -20
- package/src/hooks/installer.ts +306 -288
- package/src/hooks/interceptor-hook.ts +204 -201
- package/src/hooks/passive-classifier.ts +397 -397
- package/src/hooks/queue.ts +160 -129
- package/src/hooks/session-tracker.ts +312 -312
- package/src/hooks/types.ts +52 -52
- package/src/index.ts +7 -7
- package/src/intelligence/cross-project/generalizer.ts +283 -283
- package/src/intelligence/cross-project/index.ts +7 -7
- package/src/intelligence/hf-downloader.ts +222 -222
- package/src/intelligence/hf-manifest.json +78 -78
- package/src/intelligence/index.ts +24 -24
- package/src/intelligence/inference-router.ts +762 -762
- package/src/intelligence/model-manager.ts +263 -245
- package/src/intelligence/optimization/index.ts +10 -10
- package/src/intelligence/optimization/precompute.ts +202 -202
- package/src/intelligence/optimization/semantic-cache.ts +213 -207
- package/src/intelligence/prediction/index.ts +7 -7
- package/src/intelligence/prediction/recommender.ts +276 -268
- package/src/intelligence/reasoning/chain-retrieval.ts +243 -247
- package/src/intelligence/reasoning/index.ts +7 -7
- package/src/intelligence/temporal/evolution.ts +193 -197
- package/src/intelligence/temporal/index.ts +16 -16
- package/src/intelligence/temporal/query-processor.ts +190 -190
- package/src/intelligence/temporal/timeline.ts +272 -259
- package/src/intelligence/temporal/trends.ts +263 -263
- package/src/intelligence/tokenizer.ts +118 -118
- package/src/knowledge/entity-extractor.ts +447 -443
- package/src/knowledge/graph/builder.ts +185 -185
- package/src/knowledge/graph/linker.ts +201 -201
- package/src/knowledge/graph/memory-graph.ts +359 -359
- package/src/knowledge/graph/schema.ts +99 -99
- package/src/knowledge/graph/search.ts +166 -166
- package/src/knowledge/relationship-extractor.ts +108 -108
- package/src/memory/chroma/client.ts +211 -192
- package/src/memory/chroma/collection-manager.ts +92 -92
- package/src/memory/chroma/config.ts +57 -57
- package/src/memory/chroma/embeddings.ts +177 -175
- package/src/memory/chroma/index.ts +82 -82
- package/src/memory/chroma/migration.ts +270 -270
- package/src/memory/chroma/schemas.ts +69 -69
- package/src/memory/chroma/search.ts +319 -315
- package/src/memory/chroma/store.ts +755 -747
- package/src/memory/compression.ts +121 -121
- package/src/memory/consolidation/archiver.ts +162 -165
- package/src/memory/consolidation/merger.ts +182 -186
- package/src/memory/consolidation/scorer.ts +136 -136
- package/src/memory/database.ts +9 -0
- package/src/memory/dual-write.ts +145 -0
- package/src/memory/embeddings.ts +226 -226
- package/src/memory/episodic/detector.ts +108 -108
- package/src/memory/episodic/manager.ts +347 -351
- package/src/memory/episodic/summarizer.ts +179 -179
- package/src/memory/episodic/types.ts +52 -52
- package/src/memory/fts5-search.ts +692 -633
- package/src/memory/index.ts +943 -1060
- package/src/memory/migrations/add-fts5.ts +118 -108
- package/src/memory/patterns.ts +438 -438
- package/src/memory/pruning.ts +60 -60
- package/src/memory/schema.ts +88 -88
- package/src/memory/store.ts +911 -787
- package/src/orchestrator/handlers/decision-handler.ts +204 -204
- package/src/packs/index.ts +9 -9
- package/src/packs/loader.ts +134 -134
- package/src/packs/manager.ts +204 -204
- package/src/packs/ranker.ts +78 -78
- package/src/packs/types.ts +81 -81
- package/src/phase12/index.ts +5 -5
- package/src/retrieval/bm25/index.ts +300 -297
- package/src/retrieval/bm25/tokenizer.ts +184 -184
- package/src/retrieval/feedback/adaptive.ts +221 -221
- package/src/retrieval/feedback/index.ts +16 -16
- package/src/retrieval/feedback/metrics.ts +221 -221
- package/src/retrieval/feedback/store.ts +283 -283
- package/src/retrieval/fusion/index.ts +194 -194
- package/src/retrieval/fusion/rrf.ts +165 -165
- package/src/retrieval/index.ts +12 -12
- package/src/retrieval/pipeline.ts +375 -375
- package/src/retrieval/query/expander.ts +203 -203
- package/src/retrieval/query/index.ts +27 -27
- package/src/retrieval/query/intent-classifier.ts +252 -252
- package/src/retrieval/query/temporal-parser.ts +295 -295
- package/src/retrieval/reranker/index.ts +189 -188
- package/src/retrieval/reranker/model.ts +99 -95
- package/src/retrieval/service.ts +125 -125
- package/src/retrieval/types.ts +162 -162
- package/src/routing/entity-extractor.ts +454 -454
- package/src/routing/handlers/exploration-handler.ts +369 -0
- package/src/routing/handlers/index.ts +19 -0
- package/src/routing/handlers/memory-handler.ts +273 -0
- package/src/routing/handlers/mutation-handler.ts +241 -0
- package/src/routing/handlers/recall-handler.ts +642 -0
- package/src/routing/handlers/shared.ts +515 -0
- package/src/routing/handlers/types.ts +48 -0
- package/src/routing/intent-classifier.ts +552 -552
- package/src/routing/response-filter.ts +399 -391
- package/src/routing/router.ts +245 -2193
- package/src/routing/search-engine.ts +521 -514
- package/src/routing/types.ts +104 -94
- package/src/scripts/health-check.ts +118 -118
- package/src/scripts/setup.ts +122 -122
- package/src/server/auto-updater.ts +283 -276
- package/src/server/handlers/call-tool.ts +159 -159
- package/src/server/handlers/list-tools.ts +35 -35
- package/src/server/handlers/tools/auto-remember.ts +165 -165
- package/src/server/handlers/tools/brain.ts +86 -86
- package/src/server/handlers/tools/create-project.ts +135 -135
- package/src/server/handlers/tools/get-code-standards.ts +123 -123
- package/src/server/handlers/tools/get-corrections.ts +152 -152
- package/src/server/handlers/tools/get-patterns.ts +156 -156
- package/src/server/handlers/tools/get-project-context.ts +75 -75
- package/src/server/handlers/tools/index.ts +30 -30
- package/src/server/handlers/tools/init-project.ts +756 -756
- package/src/server/handlers/tools/list-projects.ts +126 -126
- package/src/server/handlers/tools/recall-similar.ts +87 -87
- package/src/server/handlers/tools/recognize-pattern.ts +132 -132
- package/src/server/handlers/tools/record-correction.ts +131 -131
- package/src/server/handlers/tools/remember-decision.ts +168 -168
- package/src/server/handlers/tools/schemas.ts +179 -179
- package/src/server/handlers/tools/search-code.ts +122 -122
- package/src/server/handlers/tools/smart-context.ts +146 -146
- package/src/server/handlers/tools/update-progress.ts +131 -131
- package/src/server/http-api.ts +215 -1229
- package/src/server/mcp-proxy.ts +85 -84
- package/src/server/mcp-server.ts +285 -284
- package/src/server/middleware/auth.ts +39 -0
- package/src/server/middleware/error-handler.ts +37 -0
- package/src/server/middleware/rate-limit.ts +53 -0
- package/src/server/middleware/validate.ts +42 -0
- package/src/server/pid-manager.ts +137 -136
- package/src/server/providers/resources.ts +581 -581
- package/src/server/routes/code.ts +228 -0
- package/src/server/routes/context.ts +26 -0
- package/src/server/routes/health.ts +19 -0
- package/src/server/routes/helpers.ts +100 -0
- package/src/server/routes/hooks.ts +197 -0
- package/src/server/routes/mcp.ts +47 -0
- package/src/server/routes/memory.ts +397 -0
- package/src/server/routes/models.ts +96 -0
- package/src/server/routes/projects.ts +89 -0
- package/src/server/routes/types.ts +21 -0
- package/src/server/schemas/api-schemas.ts +202 -0
- package/src/server/services.ts +720 -720
- package/src/server/utils/memory-indicator.ts +84 -84
- package/src/server/utils/response-formatter.ts +129 -129
- package/src/server/web-viewer.ts +1145 -1115
- package/src/setup/index.ts +38 -38
- package/src/tools/registry.ts +115 -115
- package/src/tools/schemas.ts +666 -666
- package/src/tools/types.ts +412 -412
- package/src/training/data-store.ts +320 -298
- package/src/training/retrain-pipeline.ts +399 -394
- package/src/utils/error-handler.ts +136 -136
- package/src/utils/index.ts +58 -58
- package/src/utils/kill-port.ts +55 -53
- package/src/utils/phase12-helper.ts +56 -56
- package/src/utils/safe-path.ts +43 -0
- package/src/utils/timing.ts +47 -47
- package/src/utils/transaction.ts +63 -63
- package/src/vault/index.ts +4 -3
- package/src/vault/paths.ts +106 -106
- package/src/vault/query.ts +4 -1
- package/src/vault/reader.ts +44 -1
- package/src/vault/watcher.ts +24 -1
- package/src/vault/writer.ts +487 -413
- package/skills/persistent-memory/SKILL.md +0 -148
- package/skills/persistent-memory/references/tool-reference.md +0 -90
|
@@ -1,217 +1,217 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 17: CLI Hooks Command
|
|
3
|
-
* Manages passive learning hooks (install/uninstall/status/enable/disable)
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { parseArgs } from 'citty'
|
|
7
|
-
import {
|
|
8
|
-
renderLogo, theme, heading, successText, warningText, errorText, dimText,
|
|
9
|
-
box, summaryPanel, withSpinner,
|
|
10
|
-
} from '@/cli/ui/index.js'
|
|
11
|
-
import { installHooks, uninstallHooks, isHooksInstalled, getHookScriptPath } from '@/hooks/installer'
|
|
12
|
-
import { readQueue } from '@/hooks/queue'
|
|
13
|
-
|
|
14
|
-
export async function runHooks() {
|
|
15
|
-
const args = parseArgs(process.argv.slice(3), {
|
|
16
|
-
subcommand: { type: 'positional', required: false, description: 'install|uninstall|status|enable|disable' },
|
|
17
|
-
})
|
|
18
|
-
const subcommand: string = args.subcommand ?? 'status'
|
|
19
|
-
|
|
20
|
-
switch (subcommand) {
|
|
21
|
-
case 'install':
|
|
22
|
-
await handleInstall()
|
|
23
|
-
break
|
|
24
|
-
case 'uninstall':
|
|
25
|
-
await handleUninstall()
|
|
26
|
-
break
|
|
27
|
-
case 'status':
|
|
28
|
-
await handleStatus()
|
|
29
|
-
break
|
|
30
|
-
case 'enable':
|
|
31
|
-
await handleToggle(true)
|
|
32
|
-
break
|
|
33
|
-
case 'disable':
|
|
34
|
-
await handleToggle(false)
|
|
35
|
-
break
|
|
36
|
-
default:
|
|
37
|
-
console.log()
|
|
38
|
-
console.log(errorText(`Unknown hooks subcommand: ${subcommand}`))
|
|
39
|
-
printHooksHelp()
|
|
40
|
-
process.exit(1)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function handleInstall() {
|
|
45
|
-
console.log()
|
|
46
|
-
console.log(renderLogo())
|
|
47
|
-
console.log()
|
|
48
|
-
console.log(heading('Install Passive Learning Hooks'))
|
|
49
|
-
console.log()
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
let result: { installed: boolean; message: string } | undefined
|
|
53
|
-
await withSpinner('Installing hooks into Claude Code', async () => {
|
|
54
|
-
result = installHooks()
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
console.log()
|
|
58
|
-
if (result?.installed) {
|
|
59
|
-
console.log(box([
|
|
60
|
-
successText(result.message),
|
|
61
|
-
'',
|
|
62
|
-
dimText('Hooks will fire on every tool call in Claude Code.'),
|
|
63
|
-
dimText('Knowledge is captured and sent to the brain server.'),
|
|
64
|
-
dimText('Session summaries are auto-stored when conversations end.'),
|
|
65
|
-
'',
|
|
66
|
-
`${theme.dim('Hook script:')} ${getHookScriptPath()}`,
|
|
67
|
-
`${theme.dim('Settings:')} ~/.claude/settings.json`,
|
|
68
|
-
'',
|
|
69
|
-
dimText('Hooks are enabled by default. To disable:'),
|
|
70
|
-
` ${theme.bold('export CLAUDE_BRAIN_HOOKS_ENABLED=false')}`,
|
|
71
|
-
].join('\n'), 'Hooks Installed'))
|
|
72
|
-
}
|
|
73
|
-
} catch (err) {
|
|
74
|
-
console.log()
|
|
75
|
-
console.log(box(
|
|
76
|
-
errorText(`Failed to install hooks: ${err instanceof Error ? err.message : String(err)}`),
|
|
77
|
-
'Error'
|
|
78
|
-
))
|
|
79
|
-
process.exit(1)
|
|
80
|
-
}
|
|
81
|
-
console.log()
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function handleUninstall() {
|
|
85
|
-
console.log()
|
|
86
|
-
console.log(renderLogo())
|
|
87
|
-
console.log()
|
|
88
|
-
console.log(heading('Uninstall Passive Learning Hooks'))
|
|
89
|
-
console.log()
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
let result: { uninstalled: boolean; message: string } | undefined
|
|
93
|
-
await withSpinner('Removing hooks from Claude Code', async () => {
|
|
94
|
-
result = uninstallHooks()
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
console.log()
|
|
98
|
-
if (result?.uninstalled) {
|
|
99
|
-
console.log(box(
|
|
100
|
-
successText(result.message),
|
|
101
|
-
'Hooks Removed'
|
|
102
|
-
))
|
|
103
|
-
}
|
|
104
|
-
} catch (err) {
|
|
105
|
-
console.log()
|
|
106
|
-
console.log(box(
|
|
107
|
-
errorText(`Failed to uninstall hooks: ${err instanceof Error ? err.message : String(err)}`),
|
|
108
|
-
'Error'
|
|
109
|
-
))
|
|
110
|
-
process.exit(1)
|
|
111
|
-
}
|
|
112
|
-
console.log()
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async function handleStatus() {
|
|
116
|
-
console.log()
|
|
117
|
-
console.log(renderLogo())
|
|
118
|
-
console.log()
|
|
119
|
-
console.log(heading('Hook Status'))
|
|
120
|
-
console.log()
|
|
121
|
-
|
|
122
|
-
const installed = isHooksInstalled()
|
|
123
|
-
const queueItems = readQueue()
|
|
124
|
-
const envEnabled = process.env.CLAUDE_BRAIN_HOOKS_ENABLED !== 'false'
|
|
125
|
-
|
|
126
|
-
const items = [
|
|
127
|
-
{ label: 'Installed', value: installed ? 'Yes' : 'No', status: installed ? 'success' as const : 'warning' as const },
|
|
128
|
-
{ label: 'Env enabled', value: envEnabled ? 'Yes' : 'No', status: envEnabled ? 'success' as const : 'info' as const },
|
|
129
|
-
{ label: 'Queue items', value: String(queueItems.length), status: queueItems.length > 0 ? 'warning' as const : 'info' as const },
|
|
130
|
-
{ label: 'Hook script', value: getHookScriptPath(), status: 'info' as const },
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
console.log(summaryPanel('Passive Learning Hooks', items))
|
|
134
|
-
|
|
135
|
-
// Try to fetch live stats from the server
|
|
136
|
-
try {
|
|
137
|
-
const port = parseInt(process.env.CLAUDE_BRAIN_PORT || '3000', 10)
|
|
138
|
-
const res = await fetch(`http://localhost:${port}/api/hooks/status`, {
|
|
139
|
-
signal: AbortSignal.timeout(2000),
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
if (res.ok) {
|
|
143
|
-
const data = await res.json() as any
|
|
144
|
-
if (data.success && data.data) {
|
|
145
|
-
console.log()
|
|
146
|
-
const serverItems = [
|
|
147
|
-
{ label: 'Total captured', value: String(data.data.totalCaptured || 0), status: 'info' as const },
|
|
148
|
-
{ label: 'Total skipped', value: String(data.data.totalSkipped || 0), status: 'info' as const },
|
|
149
|
-
{ label: 'Total merged', value: String(data.data.totalMerged || 0), status: 'info' as const },
|
|
150
|
-
{ label: 'Active sessions', value: String(data.data.activeSessions || 0), status: 'info' as const },
|
|
151
|
-
{ label: 'Last capture', value: data.data.lastCaptureAt || 'Never', status: 'info' as const },
|
|
152
|
-
]
|
|
153
|
-
console.log(summaryPanel('Server Stats', serverItems))
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
} catch {
|
|
157
|
-
console.log()
|
|
158
|
-
console.log(dimText(' (Server not running — no live stats available)'))
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
console.log()
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async function handleToggle(enable: boolean) {
|
|
165
|
-
console.log()
|
|
166
|
-
console.log(renderLogo())
|
|
167
|
-
console.log()
|
|
168
|
-
|
|
169
|
-
const action = enable ? 'Enabling' : 'Disabling'
|
|
170
|
-
console.log(heading(`${action} Passive Learning`))
|
|
171
|
-
console.log()
|
|
172
|
-
|
|
173
|
-
// Toggle via env hint (actual config toggle would need config file editing)
|
|
174
|
-
if (enable) {
|
|
175
|
-
console.log(box([
|
|
176
|
-
successText('Hooks are enabled by default since v0.10.0.'),
|
|
177
|
-
'',
|
|
178
|
-
dimText('If previously disabled, remove the env variable:'),
|
|
179
|
-
` ${theme.bold('unset CLAUDE_BRAIN_HOOKS_ENABLED')}`,
|
|
180
|
-
'',
|
|
181
|
-
dimText('Hooks capture Edit/Write/Bash events automatically.'),
|
|
182
|
-
dimText('Session summaries are stored when conversations end.'),
|
|
183
|
-
].join('\n'), 'Enable Hooks'))
|
|
184
|
-
} else {
|
|
185
|
-
console.log(box([
|
|
186
|
-
warningText('To disable hooks, set the environment variable:'),
|
|
187
|
-
'',
|
|
188
|
-
` ${theme.bold('export CLAUDE_BRAIN_HOOKS_ENABLED=false')}`,
|
|
189
|
-
'',
|
|
190
|
-
dimText('This stops hook processing without uninstalling.'),
|
|
191
|
-
].join('\n'), 'Disable Hooks'))
|
|
192
|
-
}
|
|
193
|
-
console.log()
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function printHooksHelp() {
|
|
197
|
-
console.log()
|
|
198
|
-
const commands = [
|
|
199
|
-
['install', 'Install hooks into Claude Code settings'],
|
|
200
|
-
['uninstall', 'Remove hooks from Claude Code settings'],
|
|
201
|
-
['status', 'Show hook installation and capture stats'],
|
|
202
|
-
['enable', 'Enable passive learning (show instructions)'],
|
|
203
|
-
['disable', 'Disable passive learning (show instructions)'],
|
|
204
|
-
]
|
|
205
|
-
|
|
206
|
-
const cmdLines = commands
|
|
207
|
-
.map(([cmd, desc]) => ` ${theme.primary(cmd!.padEnd(14))} ${dimText(desc!)}`)
|
|
208
|
-
.join('\n')
|
|
209
|
-
|
|
210
|
-
console.log(box([
|
|
211
|
-
theme.bold('Usage:') + ' ' + dimText('claude-brain hooks [subcommand]'),
|
|
212
|
-
'',
|
|
213
|
-
theme.bold('Subcommands:'),
|
|
214
|
-
cmdLines,
|
|
215
|
-
].join('\n'), 'Hooks Help'))
|
|
216
|
-
console.log()
|
|
217
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Phase 17: CLI Hooks Command
|
|
3
|
+
* Manages passive learning hooks (install/uninstall/status/enable/disable)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { parseArgs } from 'citty'
|
|
7
|
+
import {
|
|
8
|
+
renderLogo, theme, heading, successText, warningText, errorText, dimText,
|
|
9
|
+
box, summaryPanel, withSpinner,
|
|
10
|
+
} from '@/cli/ui/index.js'
|
|
11
|
+
import { installHooks, uninstallHooks, isHooksInstalled, getHookScriptPath } from '@/hooks/installer'
|
|
12
|
+
import { readQueue } from '@/hooks/queue'
|
|
13
|
+
|
|
14
|
+
export async function runHooks() {
|
|
15
|
+
const args = parseArgs(process.argv.slice(3), {
|
|
16
|
+
subcommand: { type: 'positional', required: false, description: 'install|uninstall|status|enable|disable' },
|
|
17
|
+
})
|
|
18
|
+
const subcommand: string = args.subcommand ?? 'status'
|
|
19
|
+
|
|
20
|
+
switch (subcommand) {
|
|
21
|
+
case 'install':
|
|
22
|
+
await handleInstall()
|
|
23
|
+
break
|
|
24
|
+
case 'uninstall':
|
|
25
|
+
await handleUninstall()
|
|
26
|
+
break
|
|
27
|
+
case 'status':
|
|
28
|
+
await handleStatus()
|
|
29
|
+
break
|
|
30
|
+
case 'enable':
|
|
31
|
+
await handleToggle(true)
|
|
32
|
+
break
|
|
33
|
+
case 'disable':
|
|
34
|
+
await handleToggle(false)
|
|
35
|
+
break
|
|
36
|
+
default:
|
|
37
|
+
console.log()
|
|
38
|
+
console.log(errorText(`Unknown hooks subcommand: ${subcommand}`))
|
|
39
|
+
printHooksHelp()
|
|
40
|
+
process.exit(1)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function handleInstall() {
|
|
45
|
+
console.log()
|
|
46
|
+
console.log(renderLogo())
|
|
47
|
+
console.log()
|
|
48
|
+
console.log(heading('Install Passive Learning Hooks'))
|
|
49
|
+
console.log()
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
let result: { installed: boolean; message: string } | undefined
|
|
53
|
+
await withSpinner('Installing hooks into Claude Code', async () => {
|
|
54
|
+
result = installHooks()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
console.log()
|
|
58
|
+
if (result?.installed) {
|
|
59
|
+
console.log(box([
|
|
60
|
+
successText(result.message),
|
|
61
|
+
'',
|
|
62
|
+
dimText('Hooks will fire on every tool call in Claude Code.'),
|
|
63
|
+
dimText('Knowledge is captured and sent to the brain server.'),
|
|
64
|
+
dimText('Session summaries are auto-stored when conversations end.'),
|
|
65
|
+
'',
|
|
66
|
+
`${theme.dim('Hook script:')} ${getHookScriptPath()}`,
|
|
67
|
+
`${theme.dim('Settings:')} ~/.claude/settings.json`,
|
|
68
|
+
'',
|
|
69
|
+
dimText('Hooks are enabled by default. To disable:'),
|
|
70
|
+
` ${theme.bold('export CLAUDE_BRAIN_HOOKS_ENABLED=false')}`,
|
|
71
|
+
].join('\n'), 'Hooks Installed'))
|
|
72
|
+
}
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.log()
|
|
75
|
+
console.log(box(
|
|
76
|
+
errorText(`Failed to install hooks: ${err instanceof Error ? err.message : String(err)}`),
|
|
77
|
+
'Error'
|
|
78
|
+
))
|
|
79
|
+
process.exit(1)
|
|
80
|
+
}
|
|
81
|
+
console.log()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function handleUninstall() {
|
|
85
|
+
console.log()
|
|
86
|
+
console.log(renderLogo())
|
|
87
|
+
console.log()
|
|
88
|
+
console.log(heading('Uninstall Passive Learning Hooks'))
|
|
89
|
+
console.log()
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
let result: { uninstalled: boolean; message: string } | undefined
|
|
93
|
+
await withSpinner('Removing hooks from Claude Code', async () => {
|
|
94
|
+
result = uninstallHooks()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
console.log()
|
|
98
|
+
if (result?.uninstalled) {
|
|
99
|
+
console.log(box(
|
|
100
|
+
successText(result.message),
|
|
101
|
+
'Hooks Removed'
|
|
102
|
+
))
|
|
103
|
+
}
|
|
104
|
+
} catch (err) {
|
|
105
|
+
console.log()
|
|
106
|
+
console.log(box(
|
|
107
|
+
errorText(`Failed to uninstall hooks: ${err instanceof Error ? err.message : String(err)}`),
|
|
108
|
+
'Error'
|
|
109
|
+
))
|
|
110
|
+
process.exit(1)
|
|
111
|
+
}
|
|
112
|
+
console.log()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function handleStatus() {
|
|
116
|
+
console.log()
|
|
117
|
+
console.log(renderLogo())
|
|
118
|
+
console.log()
|
|
119
|
+
console.log(heading('Hook Status'))
|
|
120
|
+
console.log()
|
|
121
|
+
|
|
122
|
+
const installed = isHooksInstalled()
|
|
123
|
+
const queueItems = readQueue()
|
|
124
|
+
const envEnabled = process.env.CLAUDE_BRAIN_HOOKS_ENABLED !== 'false'
|
|
125
|
+
|
|
126
|
+
const items = [
|
|
127
|
+
{ label: 'Installed', value: installed ? 'Yes' : 'No', status: installed ? 'success' as const : 'warning' as const },
|
|
128
|
+
{ label: 'Env enabled', value: envEnabled ? 'Yes' : 'No', status: envEnabled ? 'success' as const : 'info' as const },
|
|
129
|
+
{ label: 'Queue items', value: String(queueItems.length), status: queueItems.length > 0 ? 'warning' as const : 'info' as const },
|
|
130
|
+
{ label: 'Hook script', value: getHookScriptPath(), status: 'info' as const },
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
console.log(summaryPanel('Passive Learning Hooks', items))
|
|
134
|
+
|
|
135
|
+
// Try to fetch live stats from the server
|
|
136
|
+
try {
|
|
137
|
+
const port = parseInt(process.env.CLAUDE_BRAIN_PORT || '3000', 10)
|
|
138
|
+
const res = await fetch(`http://localhost:${port}/api/hooks/status`, {
|
|
139
|
+
signal: AbortSignal.timeout(2000),
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
if (res.ok) {
|
|
143
|
+
const data = await res.json() as any
|
|
144
|
+
if (data.success && data.data) {
|
|
145
|
+
console.log()
|
|
146
|
+
const serverItems = [
|
|
147
|
+
{ label: 'Total captured', value: String(data.data.totalCaptured || 0), status: 'info' as const },
|
|
148
|
+
{ label: 'Total skipped', value: String(data.data.totalSkipped || 0), status: 'info' as const },
|
|
149
|
+
{ label: 'Total merged', value: String(data.data.totalMerged || 0), status: 'info' as const },
|
|
150
|
+
{ label: 'Active sessions', value: String(data.data.activeSessions || 0), status: 'info' as const },
|
|
151
|
+
{ label: 'Last capture', value: data.data.lastCaptureAt || 'Never', status: 'info' as const },
|
|
152
|
+
]
|
|
153
|
+
console.log(summaryPanel('Server Stats', serverItems))
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
} catch {
|
|
157
|
+
console.log()
|
|
158
|
+
console.log(dimText(' (Server not running — no live stats available)'))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function handleToggle(enable: boolean) {
|
|
165
|
+
console.log()
|
|
166
|
+
console.log(renderLogo())
|
|
167
|
+
console.log()
|
|
168
|
+
|
|
169
|
+
const action = enable ? 'Enabling' : 'Disabling'
|
|
170
|
+
console.log(heading(`${action} Passive Learning`))
|
|
171
|
+
console.log()
|
|
172
|
+
|
|
173
|
+
// Toggle via env hint (actual config toggle would need config file editing)
|
|
174
|
+
if (enable) {
|
|
175
|
+
console.log(box([
|
|
176
|
+
successText('Hooks are enabled by default since v0.10.0.'),
|
|
177
|
+
'',
|
|
178
|
+
dimText('If previously disabled, remove the env variable:'),
|
|
179
|
+
` ${theme.bold('unset CLAUDE_BRAIN_HOOKS_ENABLED')}`,
|
|
180
|
+
'',
|
|
181
|
+
dimText('Hooks capture Edit/Write/Bash events automatically.'),
|
|
182
|
+
dimText('Session summaries are stored when conversations end.'),
|
|
183
|
+
].join('\n'), 'Enable Hooks'))
|
|
184
|
+
} else {
|
|
185
|
+
console.log(box([
|
|
186
|
+
warningText('To disable hooks, set the environment variable:'),
|
|
187
|
+
'',
|
|
188
|
+
` ${theme.bold('export CLAUDE_BRAIN_HOOKS_ENABLED=false')}`,
|
|
189
|
+
'',
|
|
190
|
+
dimText('This stops hook processing without uninstalling.'),
|
|
191
|
+
].join('\n'), 'Disable Hooks'))
|
|
192
|
+
}
|
|
193
|
+
console.log()
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function printHooksHelp() {
|
|
197
|
+
console.log()
|
|
198
|
+
const commands = [
|
|
199
|
+
['install', 'Install hooks into Claude Code settings'],
|
|
200
|
+
['uninstall', 'Remove hooks from Claude Code settings'],
|
|
201
|
+
['status', 'Show hook installation and capture stats'],
|
|
202
|
+
['enable', 'Enable passive learning (show instructions)'],
|
|
203
|
+
['disable', 'Disable passive learning (show instructions)'],
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
const cmdLines = commands
|
|
207
|
+
.map(([cmd, desc]) => ` ${theme.primary(cmd!.padEnd(14))} ${dimText(desc!)}`)
|
|
208
|
+
.join('\n')
|
|
209
|
+
|
|
210
|
+
console.log(box([
|
|
211
|
+
theme.bold('Usage:') + ' ' + dimText('claude-brain hooks [subcommand]'),
|
|
212
|
+
'',
|
|
213
|
+
theme.bold('Subcommands:'),
|
|
214
|
+
cmdLines,
|
|
215
|
+
].join('\n'), 'Hooks Help'))
|
|
216
|
+
console.log()
|
|
217
|
+
}
|