@unerr-ai/unerr 0.2.1 → 0.2.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 +36 -45
- package/dist/cli.js +37443 -36022
- package/package.json +2 -1
- package/dist/behaviors/agent-llm-bridge.js +0 -166
- package/dist/behaviors/architecture-guard.js +0 -256
- package/dist/behaviors/auto-doc.js +0 -247
- package/dist/behaviors/cascade-guard.js +0 -289
- package/dist/behaviors/change-narrative.js +0 -270
- package/dist/behaviors/convention-drift.js +0 -290
- package/dist/behaviors/framework.js +0 -235
- package/dist/behaviors/guard-formatter.js +0 -44
- package/dist/behaviors/incomplete-work.js +0 -270
- package/dist/behaviors/loop-breaker.js +0 -300
- package/dist/behaviors/session-continuity.js +0 -208
- package/dist/commands/branches.js +0 -97
- package/dist/commands/check-commit.js +0 -225
- package/dist/commands/compress-output.js +0 -64
- package/dist/commands/config-verify.js +0 -243
- package/dist/commands/daemon.js +0 -905
- package/dist/commands/dashboard.js +0 -52
- package/dist/commands/debug.js +0 -200
- package/dist/commands/enrich.js +0 -184
- package/dist/commands/exec.js +0 -233
- package/dist/commands/gain.js +0 -156
- package/dist/commands/hook.js +0 -88
- package/dist/commands/index.js +0 -88
- package/dist/commands/init.js +0 -74
- package/dist/commands/install.js +0 -505
- package/dist/commands/learn.js +0 -116
- package/dist/commands/manifest.js +0 -193
- package/dist/commands/rewind.js +0 -103
- package/dist/commands/serve.js +0 -19
- package/dist/commands/setup-wizard.js +0 -414
- package/dist/commands/skills.js +0 -64
- package/dist/commands/stats.js +0 -20
- package/dist/commands/status.js +0 -654
- package/dist/commands/timeline.js +0 -139
- package/dist/commands/uninstall.js +0 -230
- package/dist/components/App.js +0 -109
- package/dist/components/Banner.js +0 -12
- package/dist/components/ConfirmPrompt.js +0 -25
- package/dist/components/DriftSummary.js +0 -23
- package/dist/components/GradeBadge.js +0 -15
- package/dist/components/HealthCard.js +0 -18
- package/dist/components/InkSpinner.js +0 -22
- package/dist/components/InputBox.js +0 -17
- package/dist/components/KeyValue.js +0 -13
- package/dist/components/MessageList.js +0 -14
- package/dist/components/ProgressBar.js +0 -26
- package/dist/components/Section.js +0 -16
- package/dist/components/SessionSummaryCard.js +0 -73
- package/dist/components/StartupDisplay.js +0 -24
- package/dist/components/StatusDashboard.js +0 -57
- package/dist/components/StatusLine.js +0 -8
- package/dist/components/StepLine.js +0 -22
- package/dist/components/Theme.js +0 -20
- package/dist/components/ToolProgress.js +0 -8
- package/dist/components/ViolationList.js +0 -21
- package/dist/components/render.js +0 -13
- package/dist/config/agent-registry.js +0 -237
- package/dist/config/claude-settings-hooks.js +0 -304
- package/dist/config/hook-installer.js +0 -65
- package/dist/config/instruction-writer.js +0 -388
- package/dist/config/mcp-config-writer.js +0 -266
- package/dist/config/settings.js +0 -174
- package/dist/config/tool-detector.js +0 -42
- package/dist/config/value-surfacing.js +0 -119
- package/dist/core/context-assembly.js +0 -108
- package/dist/core/conversation.js +0 -33
- package/dist/core/local-chat-provider.js +0 -475
- package/dist/core/provider-factory.js +0 -55
- package/dist/core/providers.js +0 -90
- package/dist/core/query-engine.js +0 -174
- package/dist/daemon/api.js +0 -312
- package/dist/daemon/autostart.js +0 -119
- package/dist/daemon/bootstrap.js +0 -39
- package/dist/daemon/client.js +0 -164
- package/dist/daemon/detect-ci.js +0 -81
- package/dist/daemon/platform-linux.js +0 -146
- package/dist/daemon/platform-macos.js +0 -134
- package/dist/daemon/platform-windows.js +0 -116
- package/dist/daemon/process-manager.js +0 -299
- package/dist/daemon/protocol.js +0 -23
- package/dist/daemon/registry.js +0 -270
- package/dist/daemon/settings-schema.js +0 -72
- package/dist/daemon/system-health.js +0 -134
- package/dist/daemon/version-checker.js +0 -262
- package/dist/daemon/warm-start.js +0 -223
- package/dist/entrypoints/cli.js +0 -1043
- package/dist/entrypoints/daemon.js +0 -380
- package/dist/entrypoints/repl.js +0 -147
- package/dist/hooks/adapters/claude-code.js +0 -90
- package/dist/hooks/adapters/cline.js +0 -100
- package/dist/hooks/adapters/cursor.js +0 -98
- package/dist/hooks/hook-dedup.js +0 -79
- package/dist/hooks/hook-runner.js +0 -113
- package/dist/hooks/navigation-hooks.js +0 -175
- package/dist/hooks/prompt-hooks.js +0 -63
- package/dist/hooks/shell-hooks.js +0 -47
- package/dist/ignore.js +0 -111
- package/dist/intelligence/approach-suggester.js +0 -61
- package/dist/intelligence/ast-extractor.js +0 -2615
- package/dist/intelligence/ast-worker.js +0 -34
- package/dist/intelligence/background-indexer.js +0 -121
- package/dist/intelligence/blast-radius.js +0 -200
- package/dist/intelligence/community-detection.js +0 -691
- package/dist/intelligence/community-detector.js +0 -184
- package/dist/intelligence/computation-scheduler.js +0 -75
- package/dist/intelligence/confidence-propagation.js +0 -47
- package/dist/intelligence/convention-detector.js +0 -242
- package/dist/intelligence/convention-learner.js +0 -205
- package/dist/intelligence/convention-matcher.js +0 -205
- package/dist/intelligence/cozo-schema.js +0 -376
- package/dist/intelligence/decision-point-detector.js +0 -90
- package/dist/intelligence/deep-dive-tools.js +0 -586
- package/dist/intelligence/durability-scorer.js +0 -84
- package/dist/intelligence/exploration-cost.js +0 -204
- package/dist/intelligence/exploration-pattern-tracker.js +0 -61
- package/dist/intelligence/fact-generator.js +0 -322
- package/dist/intelligence/facts-schema.js +0 -90
- package/dist/intelligence/file-intelligence.js +0 -59
- package/dist/intelligence/graph-holder.js +0 -220
- package/dist/intelligence/graph-temporal-joiner.js +0 -238
- package/dist/intelligence/health-grade.js +0 -423
- package/dist/intelligence/health-grader.js +0 -200
- package/dist/intelligence/health-map-data.js +0 -259
- package/dist/intelligence/import-symbols.js +0 -136
- package/dist/intelligence/incremental-indexer.js +0 -658
- package/dist/intelligence/indexer/centrality.js +0 -62
- package/dist/intelligence/indexer/cfg-context.js +0 -95
- package/dist/intelligence/indexer/confidence.js +0 -34
- package/dist/intelligence/indexer/cross-file-resolver.js +0 -104
- package/dist/intelligence/indexer/edge-repair.js +0 -89
- package/dist/intelligence/indexer/entity-key.js +0 -17
- package/dist/intelligence/indexer/export-map.js +0 -132
- package/dist/intelligence/indexer/git-cochange.js +0 -128
- package/dist/intelligence/indexer/graph-patch.js +0 -147
- package/dist/intelligence/indexer/incremental.js +0 -78
- package/dist/intelligence/indexer/ingest.js +0 -160
- package/dist/intelligence/indexer/language-detect.js +0 -226
- package/dist/intelligence/indexer/metadata.js +0 -63
- package/dist/intelligence/indexer/mutation-tracker.js +0 -79
- package/dist/intelligence/indexer/orchestrator.js +0 -155
- package/dist/intelligence/indexer/plugin-interface.js +0 -31
- package/dist/intelligence/indexer/plugins/csharp.js +0 -440
- package/dist/intelligence/indexer/plugins/go.js +0 -335
- package/dist/intelligence/indexer/plugins/java.js +0 -370
- package/dist/intelligence/indexer/plugins/python.js +0 -358
- package/dist/intelligence/indexer/plugins/regex-fallback.js +0 -82
- package/dist/intelligence/indexer/plugins/ruby.js +0 -290
- package/dist/intelligence/indexer/plugins/rust.js +0 -484
- package/dist/intelligence/indexer/plugins/tier2-generic.js +0 -310
- package/dist/intelligence/indexer/plugins/typescript.js +0 -456
- package/dist/intelligence/indexer/resource-monitor.js +0 -93
- package/dist/intelligence/indexer/scip/decoder.js +0 -253
- package/dist/intelligence/indexer/scip/detector.js +0 -232
- package/dist/intelligence/indexer/scip/downloader.js +0 -427
- package/dist/intelligence/indexer/scip/fallback.js +0 -34
- package/dist/intelligence/indexer/scip/merger.js +0 -109
- package/dist/intelligence/indexer/scip/orchestrator.js +0 -433
- package/dist/intelligence/indexer/scip/runner.js +0 -98
- package/dist/intelligence/indexer/snapshot.js +0 -66
- package/dist/intelligence/indexer/test-detector.js +0 -196
- package/dist/intelligence/indexer/watch-integration.js +0 -61
- package/dist/intelligence/indexer/worker.js +0 -85
- package/dist/intelligence/local-convention-detector.js +0 -437
- package/dist/intelligence/local-embeddings.js +0 -190
- package/dist/intelligence/local-graph.js +0 -1946
- package/dist/intelligence/local-indexer.js +0 -1575
- package/dist/intelligence/local-llm.js +0 -163
- package/dist/intelligence/local-rule-generator.js +0 -154
- package/dist/intelligence/local-snapshot.js +0 -213
- package/dist/intelligence/negative-knowledge.js +0 -103
- package/dist/intelligence/persistent-db.js +0 -85
- package/dist/intelligence/query-router.js +0 -2556
- package/dist/intelligence/risk-classifier.js +0 -116
- package/dist/intelligence/rule-evaluator.js +0 -380
- package/dist/intelligence/rule-generator.js +0 -49
- package/dist/intelligence/search-index.js +0 -173
- package/dist/intelligence/semantic/docstring-extractor.js +0 -67
- package/dist/intelligence/semantic/embedding-store.js +0 -52
- package/dist/intelligence/semantic/enrichment-orchestrator.js +0 -48
- package/dist/intelligence/semantic/git-message-miner.js +0 -114
- package/dist/intelligence/semantic/identifier-tokenizer.js +0 -51
- package/dist/intelligence/semantic/node2vec-embeddings.js +0 -71
- package/dist/intelligence/semantic/node2vec-walks.js +0 -103
- package/dist/intelligence/semantic/path-domain-inference.js +0 -112
- package/dist/intelligence/semantic/similarity-engine.js +0 -60
- package/dist/intelligence/semantic/tfidf-vectors.js +0 -88
- package/dist/intelligence/session-brief-builder.js +0 -159
- package/dist/intelligence/session-context.js +0 -221
- package/dist/intelligence/session-health-monitor.js +0 -211
- package/dist/intelligence/session-narrative.js +0 -197
- package/dist/intelligence/session-pattern-analyzer.js +0 -218
- package/dist/intelligence/signal-scorer.js +0 -390
- package/dist/intelligence/signal-show-store.js +0 -182
- package/dist/intelligence/smart-truncate.js +0 -158
- package/dist/intelligence/subgraph-cache.js +0 -88
- package/dist/intelligence/temporal-facts.js +0 -494
- package/dist/intelligence/token-estimator.js +0 -100
- package/dist/intelligence/tool-injector.js +0 -87
- package/dist/intelligence/tree-sitter-loader.js +0 -71
- package/dist/intelligence/worker-pool.js +0 -116
- package/dist/proxy/arg-validator.js +0 -79
- package/dist/proxy/auto-bootstrap.js +0 -167
- package/dist/proxy/bridge.js +0 -147
- package/dist/proxy/budget-enforcer.js +0 -70
- package/dist/proxy/compression-quality-monitor.js +0 -160
- package/dist/proxy/compression-stats.js +0 -51
- package/dist/proxy/context-rot-detector.js +0 -137
- package/dist/proxy/drift-detector.js +0 -139
- package/dist/proxy/efficiency-tracker.js +0 -79
- package/dist/proxy/fact-ranking.js +0 -154
- package/dist/proxy/format-encoder.js +0 -266
- package/dist/proxy/http-transport.js +0 -90
- package/dist/proxy/lifecycle-actor.js +0 -55
- package/dist/proxy/lifecycle-machine.js +0 -187
- package/dist/proxy/log-tailer.js +0 -265
- package/dist/proxy/model-pricing.js +0 -98
- package/dist/proxy/network-firewall.js +0 -141
- package/dist/proxy/nudge-state.js +0 -93
- package/dist/proxy/output-compressor.js +0 -185
- package/dist/proxy/pid-lock.js +0 -291
- package/dist/proxy/proxy-context.js +0 -11
- package/dist/proxy/proxy.js +0 -2633
- package/dist/proxy/response-enrichment.js +0 -32
- package/dist/proxy/response-envelope.js +0 -313
- package/dist/proxy/session-dedup.js +0 -82
- package/dist/proxy/session-legend.js +0 -30
- package/dist/proxy/session-persistence.js +0 -210
- package/dist/proxy/session-resume.js +0 -94
- package/dist/proxy/session-stats.js +0 -513
- package/dist/proxy/shell-classifier.js +0 -1346
- package/dist/proxy/shell-compression-log.js +0 -93
- package/dist/proxy/shell-compressor.js +0 -390
- package/dist/proxy/shell-graph-boost.js +0 -202
- package/dist/proxy/shell-monitor-map.js +0 -18
- package/dist/proxy/shell-stats.js +0 -54
- package/dist/proxy/shell-strategies/cloud.js +0 -215
- package/dist/proxy/shell-strategies/diff.js +0 -159
- package/dist/proxy/shell-strategies/error-diagnostic.js +0 -796
- package/dist/proxy/shell-strategies/filter-dsl.js +0 -358
- package/dist/proxy/shell-strategies/git-status.js +0 -177
- package/dist/proxy/shell-strategies/key-value.js +0 -193
- package/dist/proxy/shell-strategies/log-text.js +0 -154
- package/dist/proxy/shell-strategies/omni.js +0 -188
- package/dist/proxy/shell-strategies/progress.js +0 -55
- package/dist/proxy/shell-strategies/redact.js +0 -76
- package/dist/proxy/shell-strategies/structured.js +0 -241
- package/dist/proxy/shell-strategies/tabular.js +0 -243
- package/dist/proxy/shell-strategies/test-results-types.js +0 -13
- package/dist/proxy/shell-strategies/test-results.js +0 -784
- package/dist/proxy/shell-strategies/tree-paths.js +0 -144
- package/dist/proxy/shell-strategies/yaml.js +0 -182
- package/dist/proxy/shell-tee.js +0 -111
- package/dist/proxy/signal-dedup.js +0 -171
- package/dist/proxy/startup-renderer.js +0 -158
- package/dist/proxy/task-token-display.js +0 -38
- package/dist/proxy/token-counter.js +0 -61
- package/dist/proxy/tool-clusters.js +0 -273
- package/dist/proxy/tool-definitions.js +0 -525
- package/dist/proxy/transport-mux.js +0 -229
- package/dist/proxy/wire-cap.js +0 -268
- package/dist/rules/developer.mozilla.org.json +0 -9
- package/dist/rules/github.com.json +0 -21
- package/dist/schemas/api/skills.js +0 -19
- package/dist/schemas/common/errors.js +0 -7
- package/dist/schemas/common/headers.js +0 -5
- package/dist/schemas/entities/edge.js +0 -25
- package/dist/schemas/entities/entity.js +0 -22
- package/dist/schemas/entities/rule.js +0 -18
- package/dist/schemas/index.js +0 -14
- package/dist/server/event-bus.js +0 -59
- package/dist/server/http.js +0 -156
- package/dist/server/middleware.js +0 -70
- package/dist/server/routes/drift.js +0 -97
- package/dist/server/routes/intelligence.js +0 -1217
- package/dist/server/routes/reasoning-quality.js +0 -444
- package/dist/server/routes/session.js +0 -86
- package/dist/server/routes/stream.js +0 -120
- package/dist/server/routes/system.js +0 -73
- package/dist/server/routes/temporal.js +0 -170
- package/dist/server/routes/timeline.js +0 -232
- package/dist/server/routes/token-flow.js +0 -403
- package/dist/skills/effectiveness-tracker.js +0 -93
- package/dist/skills/local-pack.js +0 -380
- package/dist/skills/resolver.js +0 -495
- package/dist/state-detector.js +0 -83
- package/dist/timeline/intent-detector.js +0 -263
- package/dist/timeline/loop-miner.js +0 -140
- package/dist/timeline/open-threads.js +0 -49
- package/dist/timeline/signal-reinforcer.js +0 -62
- package/dist/timeline/timeline-bootstrap.js +0 -151
- package/dist/timeline/timeline-store.js +0 -618
- package/dist/tools/coding/bash.js +0 -49
- package/dist/tools/coding/file-edit.js +0 -72
- package/dist/tools/coding/file-outline.js +0 -227
- package/dist/tools/coding/file-read-protocol.js +0 -425
- package/dist/tools/coding/file-read.js +0 -35
- package/dist/tools/coding/file-write.js +0 -43
- package/dist/tools/coding/glob-tool.js +0 -109
- package/dist/tools/coding/grep.js +0 -162
- package/dist/tools/coding/index.js +0 -27
- package/dist/tools/intelligence/index.js +0 -269
- package/dist/tools/intelligence/record-fact.js +0 -48
- package/dist/tools/intelligence/timeline-markers.js +0 -130
- package/dist/tools/registry.js +0 -47
- package/dist/tools/types.js +0 -8
- package/dist/tracking/auto-snapshot-triggers.js +0 -246
- package/dist/tracking/branch-context.js +0 -115
- package/dist/tracking/branch-snapshot.js +0 -217
- package/dist/tracking/causal-bridge.js +0 -317
- package/dist/tracking/circuit-breaker.js +0 -147
- package/dist/tracking/commit-watcher.js +0 -114
- package/dist/tracking/context-ledger.js +0 -119
- package/dist/tracking/correction-detector.js +0 -324
- package/dist/tracking/drift-tracker.js +0 -874
- package/dist/tracking/durability-tracker.js +0 -94
- package/dist/tracking/entity-rewind.js +0 -200
- package/dist/tracking/file-hash-state.js +0 -114
- package/dist/tracking/git-attribution.js +0 -132
- package/dist/tracking/git-trailers.js +0 -171
- package/dist/tracking/intelligence-counter.js +0 -46
- package/dist/tracking/intent-correlator.js +0 -202
- package/dist/tracking/intent-encoder.js +0 -52
- package/dist/tracking/intent-token-tracker.js +0 -159
- package/dist/tracking/ledger-archiver.js +0 -94
- package/dist/tracking/ledger-chains.js +0 -245
- package/dist/tracking/metrics-store.js +0 -361
- package/dist/tracking/native-watcher.js +0 -131
- package/dist/tracking/offline-rewind.js +0 -295
- package/dist/tracking/pending-violations.js +0 -74
- package/dist/tracking/persistence-effectiveness.js +0 -167
- package/dist/tracking/prompt-durability.js +0 -202
- package/dist/tracking/quality-signals.js +0 -213
- package/dist/tracking/redactor.js +0 -73
- package/dist/tracking/rewind-engine.js +0 -161
- package/dist/tracking/session-history.js +0 -128
- package/dist/tracking/session-receipt.js +0 -88
- package/dist/tracking/session-summary-writer.js +0 -157
- package/dist/tracking/shadow-ledger.js +0 -321
- package/dist/tracking/stash-manager.js +0 -258
- package/dist/tracking/timeline-fork.js +0 -213
- package/dist/tracking/timeline.js +0 -69
- package/dist/tracking/token-flow.js +0 -276
- package/dist/tracking/turn-segmenter.js +0 -122
- package/dist/tracking/weekly-accumulator.js +0 -179
- package/dist/tracking/working-snapshots.js +0 -188
- package/dist/tracking/workspace-manifest.js +0 -176
- package/dist/transport/http.js +0 -102
- package/dist/utils/counterfactual.js +0 -65
- package/dist/utils/deep-link.js +0 -34
- package/dist/utils/detect.js +0 -193
- package/dist/utils/exec.js +0 -73
- package/dist/utils/file-logger.js +0 -87
- package/dist/utils/format-error.js +0 -29
- package/dist/utils/git.js +0 -181
- package/dist/utils/log.js +0 -57
- package/dist/utils/logger.js +0 -35
- package/dist/utils/mcp-content-json.js +0 -8
- package/dist/utils/session-logger.js +0 -154
- package/dist/utils/startup-log.js +0 -512
- package/dist/utils/ui.js +0 -56
|
@@ -1,304 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Merge unerr hooks into `.claude/settings.json`.
|
|
3
|
-
*
|
|
4
|
-
* PreToolUse hooks: Bash (rewrite), Read (nudge), Grep (nudge), Glob (nudge).
|
|
5
|
-
* PostToolUse hooks: Read (enrich), Grep (enrich), Glob (enrich).
|
|
6
|
-
* All hooks are installed on `unerr install claude-code` and removed on `unerr uninstall`.
|
|
7
|
-
*/
|
|
8
|
-
import { execSync } from "node:child_process";
|
|
9
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
|
-
import { join } from "node:path";
|
|
11
|
-
/**
|
|
12
|
-
* Resolve the absolute path to the `unerr` binary.
|
|
13
|
-
*
|
|
14
|
-
* Tries (in order):
|
|
15
|
-
* 1. `process.argv[1]` — the script currently running (works for global installs, pnpm link, npm link)
|
|
16
|
-
* 2. `which unerr` — fallback to PATH lookup at install time
|
|
17
|
-
* 3. `"unerr"` — bare name as last resort (relies on subprocess PATH)
|
|
18
|
-
*
|
|
19
|
-
* The resolved absolute path is written into settings.json so hooks work even when
|
|
20
|
-
* the subprocess PATH doesn't include the package manager's global bin directory.
|
|
21
|
-
*/
|
|
22
|
-
function resolveUnerrBinary() {
|
|
23
|
-
// process.argv[1] is the entry script — for global installs this is the real
|
|
24
|
-
// binary path (e.g. /Users/jaswanth/Library/pnpm/unerr or /usr/local/bin/unerr).
|
|
25
|
-
// Require the basename to actually look like the unerr binary so we don't
|
|
26
|
-
// bake in a path to vitest, tsx, or some other wrapper that happened to spawn
|
|
27
|
-
// the current process (which would write unrecognisable hook commands that
|
|
28
|
-
// `isAnyUnerrHook` can't match for removal).
|
|
29
|
-
const entryScript = process.argv[1];
|
|
30
|
-
if (entryScript && existsSync(entryScript)) {
|
|
31
|
-
const base = entryScript.split("/").pop() ?? "";
|
|
32
|
-
if (base === "unerr" || base.startsWith("unerr.")) {
|
|
33
|
-
return entryScript;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
// Fallback: `which unerr` at install time (captures current PATH)
|
|
37
|
-
try {
|
|
38
|
-
const resolved = execSync("which unerr", { encoding: "utf-8" }).trim();
|
|
39
|
-
if (resolved && existsSync(resolved)) {
|
|
40
|
-
return resolved;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// which not found or unerr not on PATH — fall through
|
|
45
|
-
}
|
|
46
|
-
// Last resort: bare name (original behavior — `isAnyUnerrHook` still matches
|
|
47
|
-
// `^unerr\s+hook\s+`).
|
|
48
|
-
return "unerr";
|
|
49
|
-
}
|
|
50
|
-
/** Cached resolved binary path (computed once per process). */
|
|
51
|
-
let _resolvedBinary;
|
|
52
|
-
function getUnerrBinary() {
|
|
53
|
-
if (_resolvedBinary === undefined) {
|
|
54
|
-
_resolvedBinary = resolveUnerrBinary();
|
|
55
|
-
}
|
|
56
|
-
return _resolvedBinary;
|
|
57
|
-
}
|
|
58
|
-
/** Build hook command templates using the resolved binary path. */
|
|
59
|
-
function buildMatcherHooks() {
|
|
60
|
-
const bin = getUnerrBinary();
|
|
61
|
-
return [
|
|
62
|
-
// PreToolUse — advisory nudges + Bash rewrite
|
|
63
|
-
{ event: "PreToolUse", matcher: "Bash", command: `${bin} hook pre-bash` },
|
|
64
|
-
{ event: "PreToolUse", matcher: "Read", command: `${bin} hook pre-read` },
|
|
65
|
-
{ event: "PreToolUse", matcher: "Grep", command: `${bin} hook pre-grep` },
|
|
66
|
-
{ event: "PreToolUse", matcher: "Glob", command: `${bin} hook pre-glob` },
|
|
67
|
-
// PreToolUse — blast radius + convention validation for writes
|
|
68
|
-
{ event: "PreToolUse", matcher: "Write", command: `${bin} hook pre-write` },
|
|
69
|
-
{ event: "PreToolUse", matcher: "Edit", command: `${bin} hook pre-edit` },
|
|
70
|
-
// PostToolUse — enrich tool output with graph navigation suggestions
|
|
71
|
-
{ event: "PostToolUse", matcher: "Read", command: `${bin} hook post-read` },
|
|
72
|
-
{ event: "PostToolUse", matcher: "Grep", command: `${bin} hook post-grep` },
|
|
73
|
-
{ event: "PostToolUse", matcher: "Glob", command: `${bin} hook post-glob` },
|
|
74
|
-
{
|
|
75
|
-
event: "PostToolUse",
|
|
76
|
-
matcher: "Write",
|
|
77
|
-
command: `${bin} hook post-write`,
|
|
78
|
-
},
|
|
79
|
-
{ event: "PostToolUse", matcher: "Edit", command: `${bin} hook post-edit` },
|
|
80
|
-
];
|
|
81
|
-
}
|
|
82
|
-
/** Build global hook templates using the resolved binary path. */
|
|
83
|
-
function buildGlobalHooks() {
|
|
84
|
-
const bin = getUnerrBinary();
|
|
85
|
-
return [{ event: "UserPromptSubmit", command: `${bin} hook prompt-submit` }];
|
|
86
|
-
}
|
|
87
|
-
/** Check if an entry is ANY unerr hook (for removal and dedup). */
|
|
88
|
-
function isAnyUnerrHook(entry) {
|
|
89
|
-
if (!entry || typeof entry !== "object")
|
|
90
|
-
return false;
|
|
91
|
-
const e = entry;
|
|
92
|
-
const hs = e.hooks;
|
|
93
|
-
if (!Array.isArray(hs))
|
|
94
|
-
return false;
|
|
95
|
-
// Match any hook command that contains "unerr hook" (covers both bare and absolute paths)
|
|
96
|
-
return hs.some((h) => {
|
|
97
|
-
if (!h || typeof h !== "object")
|
|
98
|
-
return false;
|
|
99
|
-
const cmd = h.command;
|
|
100
|
-
return typeof cmd === "string" && /(?:^|\/)unerr\s+hook\s+/.test(cmd);
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Merge all unerr hooks into `.claude/settings.json`.
|
|
105
|
-
* Handles PreToolUse/PostToolUse (matcher-based) and UserPromptSubmit (global).
|
|
106
|
-
* Idempotent — skips hooks that are already present.
|
|
107
|
-
*/
|
|
108
|
-
export function mergePreToolUseBashHook(cwd) {
|
|
109
|
-
const dir = join(cwd, ".claude");
|
|
110
|
-
const settingsPath = join(dir, "settings.json");
|
|
111
|
-
try {
|
|
112
|
-
if (!existsSync(dir)) {
|
|
113
|
-
mkdirSync(dir, { recursive: true });
|
|
114
|
-
}
|
|
115
|
-
let settings = {};
|
|
116
|
-
if (existsSync(settingsPath)) {
|
|
117
|
-
try {
|
|
118
|
-
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
settings = {};
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const hooks = settings.hooks ?? {};
|
|
125
|
-
let added = 0;
|
|
126
|
-
const matcherHooks = buildMatcherHooks();
|
|
127
|
-
const globalHooks = buildGlobalHooks();
|
|
128
|
-
// Remove any existing unerr hooks first (handles upgrades from bare to absolute paths)
|
|
129
|
-
for (const eventType of [
|
|
130
|
-
"PreToolUse",
|
|
131
|
-
"PostToolUse",
|
|
132
|
-
"UserPromptSubmit",
|
|
133
|
-
]) {
|
|
134
|
-
if (Array.isArray(hooks[eventType])) {
|
|
135
|
-
hooks[eventType] = hooks[eventType].filter((entry) => !isAnyUnerrHook(entry));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
// Register matcher-based hooks (PreToolUse, PostToolUse) with resolved binary path
|
|
139
|
-
for (const hookDef of matcherHooks) {
|
|
140
|
-
const eventArray = Array.isArray(hooks[hookDef.event])
|
|
141
|
-
? [...hooks[hookDef.event]]
|
|
142
|
-
: [];
|
|
143
|
-
eventArray.push({
|
|
144
|
-
matcher: hookDef.matcher,
|
|
145
|
-
hooks: [{ type: "command", command: hookDef.command }],
|
|
146
|
-
});
|
|
147
|
-
hooks[hookDef.event] = eventArray;
|
|
148
|
-
added++;
|
|
149
|
-
}
|
|
150
|
-
// Register global hooks (UserPromptSubmit — no matcher) with resolved binary path
|
|
151
|
-
for (const hookDef of globalHooks) {
|
|
152
|
-
const eventArray = Array.isArray(hooks[hookDef.event])
|
|
153
|
-
? [...hooks[hookDef.event]]
|
|
154
|
-
: [];
|
|
155
|
-
if (!eventArray.some((entry) => isAnyUnerrHook(entry))) {
|
|
156
|
-
eventArray.push({
|
|
157
|
-
hooks: [{ type: "command", command: hookDef.command }],
|
|
158
|
-
});
|
|
159
|
-
hooks[hookDef.event] = eventArray;
|
|
160
|
-
added++;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (added === 0) {
|
|
164
|
-
return { ok: true, path: settingsPath, action: "already_present" };
|
|
165
|
-
}
|
|
166
|
-
settings.hooks = hooks;
|
|
167
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf-8");
|
|
168
|
-
return { ok: true, path: settingsPath, action: "merged" };
|
|
169
|
-
}
|
|
170
|
-
catch {
|
|
171
|
-
return { ok: false, path: settingsPath, action: "failed" };
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Remove ALL unerr hook entries from `.claude/settings.json`.
|
|
176
|
-
* Handles PreToolUse, PostToolUse, and UserPromptSubmit.
|
|
177
|
-
* Returns true if any entries were removed.
|
|
178
|
-
*/
|
|
179
|
-
/**
|
|
180
|
-
* S8: Built-in tools to deny when --force-tools is active.
|
|
181
|
-
* These tools have unerr MCP equivalents (file_read, search_code, file_outline).
|
|
182
|
-
*/
|
|
183
|
-
const DISALLOWED_TOOLS = ["Grep", "Glob"];
|
|
184
|
-
/**
|
|
185
|
-
* S8: Add `permissions.deny` entries to `.claude/settings.json`.
|
|
186
|
-
* Denies Read, Grep, Glob when unerr MCP tools are confirmed available.
|
|
187
|
-
*
|
|
188
|
-
* Called by default on `unerr install claude-code`. Opt out with `--no-force-tools`.
|
|
189
|
-
* Idempotent — skips tools already denied.
|
|
190
|
-
*/
|
|
191
|
-
export function addDisallowedTools(cwd) {
|
|
192
|
-
const dir = join(cwd, ".claude");
|
|
193
|
-
const settingsPath = join(dir, "settings.json");
|
|
194
|
-
try {
|
|
195
|
-
if (!existsSync(dir)) {
|
|
196
|
-
mkdirSync(dir, { recursive: true });
|
|
197
|
-
}
|
|
198
|
-
let settings = {};
|
|
199
|
-
if (existsSync(settingsPath)) {
|
|
200
|
-
try {
|
|
201
|
-
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
202
|
-
}
|
|
203
|
-
catch {
|
|
204
|
-
settings = {};
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
const permissions = settings.permissions ?? {};
|
|
208
|
-
const deny = Array.isArray(permissions.deny)
|
|
209
|
-
? [...permissions.deny]
|
|
210
|
-
: [];
|
|
211
|
-
// Migration: remove "Read" if it was previously denied by unerr
|
|
212
|
-
// (Read is needed for the Edit workflow — deny breaks native editing across all agents)
|
|
213
|
-
const readIdx = deny.indexOf("Read");
|
|
214
|
-
if (readIdx >= 0) {
|
|
215
|
-
deny.splice(readIdx, 1);
|
|
216
|
-
}
|
|
217
|
-
let added = 0;
|
|
218
|
-
for (const tool of DISALLOWED_TOOLS) {
|
|
219
|
-
if (!deny.includes(tool)) {
|
|
220
|
-
deny.push(tool);
|
|
221
|
-
added++;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
if (added === 0) {
|
|
225
|
-
return { added: 0, path: settingsPath };
|
|
226
|
-
}
|
|
227
|
-
permissions.deny = deny;
|
|
228
|
-
settings.permissions = permissions;
|
|
229
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf-8");
|
|
230
|
-
return { added, path: settingsPath };
|
|
231
|
-
}
|
|
232
|
-
catch {
|
|
233
|
-
return { added: 0, path: settingsPath };
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* S8: Remove unerr-added `permissions.deny` entries from `.claude/settings.json`.
|
|
238
|
-
* Removes Read, Grep, Glob from deny list.
|
|
239
|
-
* Returns true if any entries were removed.
|
|
240
|
-
*/
|
|
241
|
-
export function removeDisallowedTools(cwd) {
|
|
242
|
-
const settingsPath = join(cwd, ".claude", "settings.json");
|
|
243
|
-
if (!existsSync(settingsPath))
|
|
244
|
-
return false;
|
|
245
|
-
try {
|
|
246
|
-
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
247
|
-
const permissions = settings.permissions;
|
|
248
|
-
if (!permissions || !Array.isArray(permissions.deny))
|
|
249
|
-
return false;
|
|
250
|
-
const before = permissions.deny.length;
|
|
251
|
-
permissions.deny = permissions.deny.filter((tool) => !DISALLOWED_TOOLS.includes(tool));
|
|
252
|
-
const removed = before - permissions.deny.length;
|
|
253
|
-
if (removed === 0)
|
|
254
|
-
return false;
|
|
255
|
-
// Clean up empty deny array and permissions object
|
|
256
|
-
if (permissions.deny.length === 0)
|
|
257
|
-
permissions.deny = undefined;
|
|
258
|
-
if (Object.keys(permissions).length === 0)
|
|
259
|
-
settings.permissions = undefined;
|
|
260
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf-8");
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
catch {
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
export function removePreToolUseBashHook(cwd) {
|
|
268
|
-
const settingsPath = join(cwd, ".claude", "settings.json");
|
|
269
|
-
if (!existsSync(settingsPath))
|
|
270
|
-
return false;
|
|
271
|
-
try {
|
|
272
|
-
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
273
|
-
const hooks = settings.hooks;
|
|
274
|
-
if (!hooks)
|
|
275
|
-
return false;
|
|
276
|
-
let totalRemoved = 0;
|
|
277
|
-
const eventTypes = [
|
|
278
|
-
"PreToolUse",
|
|
279
|
-
"PostToolUse",
|
|
280
|
-
"UserPromptSubmit",
|
|
281
|
-
];
|
|
282
|
-
for (const eventType of eventTypes) {
|
|
283
|
-
if (!Array.isArray(hooks[eventType]))
|
|
284
|
-
continue;
|
|
285
|
-
const before = hooks[eventType].length;
|
|
286
|
-
hooks[eventType] = hooks[eventType].filter((entry) => !isAnyUnerrHook(entry));
|
|
287
|
-
const removed = before - hooks[eventType].length;
|
|
288
|
-
totalRemoved += removed;
|
|
289
|
-
// Clean up empty arrays
|
|
290
|
-
if (hooks[eventType].length === 0)
|
|
291
|
-
delete hooks[eventType];
|
|
292
|
-
}
|
|
293
|
-
if (totalRemoved === 0)
|
|
294
|
-
return false;
|
|
295
|
-
// Clean up empty hooks object
|
|
296
|
-
if (Object.keys(hooks).length === 0)
|
|
297
|
-
settings.hooks = undefined;
|
|
298
|
-
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf-8");
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
catch {
|
|
302
|
-
return false;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook Installer — installs CLI hooks for Claude Code PostToolUse.
|
|
3
|
-
*
|
|
4
|
-
* R.4: Generates .claude/hooks/PostToolUse.sh that pipes command output
|
|
5
|
-
* through `unerr compress-output` for graph-aware compression.
|
|
6
|
-
*
|
|
7
|
-
* The hook intercepts tool output, compresses it, and returns the compressed
|
|
8
|
-
* version to the agent — reducing context window usage by 60-90%.
|
|
9
|
-
*/
|
|
10
|
-
import { chmodSync, existsSync, mkdirSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
11
|
-
import { join } from "node:path";
|
|
12
|
-
const HOOK_CONTENT = `#!/bin/bash
|
|
13
|
-
# unerr PostToolUse hook — graph-aware output compression
|
|
14
|
-
# Installed by: unerr init
|
|
15
|
-
# Removes: unerr uninstall
|
|
16
|
-
|
|
17
|
-
# Only compress large outputs (>2KB)
|
|
18
|
-
if [ \${#TOOL_OUTPUT} -gt 2048 ]; then
|
|
19
|
-
echo "$TOOL_OUTPUT" | unerr compress-output
|
|
20
|
-
else
|
|
21
|
-
echo "$TOOL_OUTPUT"
|
|
22
|
-
fi
|
|
23
|
-
`;
|
|
24
|
-
/**
|
|
25
|
-
* Install the PostToolUse hook for Claude Code.
|
|
26
|
-
*/
|
|
27
|
-
export function installClaudeHook(cwd) {
|
|
28
|
-
const hooksDir = join(cwd, ".claude", "hooks");
|
|
29
|
-
const hookPath = join(hooksDir, "PostToolUse.sh");
|
|
30
|
-
if (existsSync(hookPath)) {
|
|
31
|
-
return { path: hookPath, action: "already_exists" };
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
if (!existsSync(hooksDir)) {
|
|
35
|
-
mkdirSync(hooksDir, { recursive: true });
|
|
36
|
-
}
|
|
37
|
-
writeFileSync(hookPath, HOOK_CONTENT, "utf-8");
|
|
38
|
-
chmodSync(hookPath, 0o755);
|
|
39
|
-
return { path: hookPath, action: "installed" };
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return { path: hookPath, action: "failed" };
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Remove the PostToolUse hook.
|
|
47
|
-
*/
|
|
48
|
-
export function removeClaudeHook(cwd) {
|
|
49
|
-
const hookPath = join(cwd, ".claude", "hooks", "PostToolUse.sh");
|
|
50
|
-
if (!existsSync(hookPath))
|
|
51
|
-
return false;
|
|
52
|
-
try {
|
|
53
|
-
unlinkSync(hookPath);
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Check if the Claude hook is installed.
|
|
62
|
-
*/
|
|
63
|
-
export function isClaudeHookInstalled(cwd) {
|
|
64
|
-
return existsSync(join(cwd, ".claude", "hooks", "PostToolUse.sh"));
|
|
65
|
-
}
|