@trac3er/oh-my-god 2.0.0-beta.6 → 2.0.0
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/scripts/install.sh +9 -0
- package/.claude-plugin/scripts/uninstall.sh +0 -0
- package/.claude-plugin/scripts/update.sh +0 -0
- package/OMG-setup.sh +0 -0
- package/README.md +4 -2
- package/hud/omg-hud.mjs +0 -30
- package/package.json +4 -4
- package/plugins/README.md +1 -1
- package/plugins/advanced/plugin.json +1 -1
- package/plugins/core/plugin.json +1 -1
- package/runtime/compat.ts +1 -1
- package/runtime/provider_bootstrap.ts +0 -1
- package/runtime/release_readiness.ts +143 -5
- package/scripts/check-runtime-clean.ts +5 -1
- package/scripts/settings-merge.ts +30 -1
- package/settings.json +1 -21
- package/trac3er-oh-my-god-2.0.0.tgz +0 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "OMG Bun runtime for Claude Code",
|
|
9
|
-
"version": "2.0.0
|
|
9
|
+
"version": "2.0.0",
|
|
10
10
|
"homepage": "https://github.com/trac3er00/OMG",
|
|
11
11
|
"repository": "git@github.com:trac3er00/OMG.git"
|
|
12
12
|
},
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"name": "omg",
|
|
16
16
|
"description": "OMG Bun runtime orchestration layer for Claude Code",
|
|
17
|
-
"version": "2.0.0
|
|
17
|
+
"version": "2.0.0",
|
|
18
18
|
"source": "./",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "trac3er00"
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
]
|
|
33
33
|
}
|
|
34
34
|
],
|
|
35
|
-
"version": "2.0.0
|
|
35
|
+
"version": "2.0.0"
|
|
36
36
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
PLUGIN_DIR="$(dirname "$SCRIPT_DIR")"
|
|
6
|
+
OMG_ROOT="$(dirname "$PLUGIN_DIR")"
|
|
7
|
+
|
|
8
|
+
echo "Installing OMG Bun plugin..."
|
|
9
|
+
exec bash "$OMG_ROOT/OMG-setup.sh" install --install-as-plugin --non-interactive
|
|
File without changes
|
|
File without changes
|
package/OMG-setup.sh
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OMG v2 Bun Runtime
|
|
2
2
|
|
|
3
|
-
OMG `v2.0.0
|
|
3
|
+
OMG `v2.0.0` runs on Bun + TypeScript. The public product surface stays stable:
|
|
4
4
|
|
|
5
5
|
- `omg` remains the CLI entrypoint
|
|
6
6
|
- Claude hooks still write to `.omg/`
|
|
@@ -11,7 +11,7 @@ OMG `v2.0.0-beta.6` runs on Bun + TypeScript. The public product surface stays s
|
|
|
11
11
|
|
|
12
12
|
- Bun `>= 1.3`
|
|
13
13
|
- Claude Code or a compatible `~/.claude` config
|
|
14
|
-
- optional provider CLIs for multi-provider routing: `codex`, `gemini`, `
|
|
14
|
+
- optional provider CLIs for multi-provider routing: `codex`, `gemini`, `kimi`
|
|
15
15
|
|
|
16
16
|
## Install
|
|
17
17
|
|
|
@@ -62,6 +62,8 @@ omg teams --target auto --problem "debug auth regression"
|
|
|
62
62
|
- `omg_natives/index.ts`: Bun-native helper surface
|
|
63
63
|
- `tools/*.ts`: Bun support utilities used by commands and tests
|
|
64
64
|
|
|
65
|
+
Stable `settings.json` only registers hooks that perform work at runtime: session start/end capture, the Bash circuit breaker, tool ledger, post-tool-failure, and stop dispatch.
|
|
66
|
+
|
|
65
67
|
## Verification
|
|
66
68
|
|
|
67
69
|
```bash
|
package/hud/omg-hud.mjs
CHANGED
|
@@ -219,36 +219,6 @@ const PRESET_CONFIGS = {
|
|
|
219
219
|
safeMode: true,
|
|
220
220
|
inventory: true,
|
|
221
221
|
},
|
|
222
|
-
opencode: {
|
|
223
|
-
cwd: true,
|
|
224
|
-
cwdFormat: "relative",
|
|
225
|
-
gitRepo: false,
|
|
226
|
-
gitBranch: true,
|
|
227
|
-
model: false,
|
|
228
|
-
modelFormat: "short",
|
|
229
|
-
omcLabel: true,
|
|
230
|
-
rateLimits: false,
|
|
231
|
-
activeSkills: true,
|
|
232
|
-
lastSkill: true,
|
|
233
|
-
contextBar: true,
|
|
234
|
-
promptTime: true,
|
|
235
|
-
sessionHealth: true,
|
|
236
|
-
ralph: true,
|
|
237
|
-
autopilot: true,
|
|
238
|
-
prdStory: false,
|
|
239
|
-
agents: true,
|
|
240
|
-
agentsFormat: "count",
|
|
241
|
-
backgroundTasks: false,
|
|
242
|
-
todos: true,
|
|
243
|
-
thinking: true,
|
|
244
|
-
thinkingFormat: "text",
|
|
245
|
-
permissionStatus: false,
|
|
246
|
-
useBars: false,
|
|
247
|
-
showCallCounts: false,
|
|
248
|
-
maxOutputLines: 4,
|
|
249
|
-
safeMode: true,
|
|
250
|
-
inventory: true,
|
|
251
|
-
},
|
|
252
222
|
};
|
|
253
223
|
|
|
254
224
|
function countByExt(dirPath, ext) {
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trac3er/oh-my-god",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "OMG (Oh My God) — Multi-agent orchestration, intelligent model routing, and durable session state for Claude Code",
|
|
5
5
|
"bin": {
|
|
6
6
|
"omg": "scripts/omg.ts"
|
|
7
7
|
},
|
|
8
8
|
"main": "scripts/omg.ts",
|
|
9
9
|
"scripts": {
|
|
10
|
-
"postinstall": "./OMG-setup.sh install --non-interactive",
|
|
11
|
-
"update": "./OMG-setup.sh update",
|
|
12
|
-
"uninstall": "./OMG-setup.sh uninstall",
|
|
10
|
+
"postinstall": "bash ./OMG-setup.sh install --non-interactive",
|
|
11
|
+
"update": "bash ./OMG-setup.sh update",
|
|
12
|
+
"uninstall": "bash ./OMG-setup.sh uninstall",
|
|
13
13
|
"test": "bun test",
|
|
14
14
|
"typecheck": "bunx tsc --noEmit",
|
|
15
15
|
"check:runtime-clean": "bun scripts/check-runtime-clean.ts"
|
package/plugins/README.md
CHANGED
package/plugins/core/plugin.json
CHANGED
package/runtime/compat.ts
CHANGED
|
@@ -53,7 +53,7 @@ export function getCompatSkillContract(skill: string): CompatContract | null {
|
|
|
53
53
|
export function buildContractSnapshotPayload(options: { includeGeneratedAt?: boolean } = {}) {
|
|
54
54
|
const payload: Record<string, unknown> = {
|
|
55
55
|
schema: "OmgCompatContractSnapshot",
|
|
56
|
-
contract_version: "2.0.0
|
|
56
|
+
contract_version: "2.0.0",
|
|
57
57
|
count: CONTRACTS.length,
|
|
58
58
|
contracts: listCompatSkillContracts()
|
|
59
59
|
};
|
|
@@ -1,5 +1,33 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { nowIso, readJsonFile } from "./common.ts";
|
|
1
4
|
import { collectProviderStatusWithOptions } from "./provider_bootstrap.ts";
|
|
2
5
|
|
|
6
|
+
const STABLE_METADATA_FILES = [
|
|
7
|
+
"package.json",
|
|
8
|
+
"README.md",
|
|
9
|
+
"settings.json",
|
|
10
|
+
".claude-plugin/plugin.json",
|
|
11
|
+
".claude-plugin/marketplace.json",
|
|
12
|
+
"plugins/core/plugin.json",
|
|
13
|
+
"plugins/advanced/plugin.json",
|
|
14
|
+
"runtime/compat.ts"
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const DEPRECATED_PROVIDER_FILES = [
|
|
18
|
+
"README.md",
|
|
19
|
+
"plugins/README.md",
|
|
20
|
+
"hud/omg-hud.mjs",
|
|
21
|
+
"runtime/provider_bootstrap.ts"
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const REQUIRED_INSTALL_SCRIPTS = [
|
|
25
|
+
"OMG-setup.sh",
|
|
26
|
+
".claude-plugin/scripts/install.sh",
|
|
27
|
+
".claude-plugin/scripts/update.sh",
|
|
28
|
+
".claude-plugin/scripts/uninstall.sh"
|
|
29
|
+
];
|
|
30
|
+
|
|
3
31
|
function git(projectDir: string, args: string[]): string {
|
|
4
32
|
const proc = Bun.spawnSync({
|
|
5
33
|
cmd: ["git", ...args],
|
|
@@ -10,6 +38,91 @@ function git(projectDir: string, args: string[]): string {
|
|
|
10
38
|
return proc.exitCode === 0 ? proc.stdout.toString().trim() : "";
|
|
11
39
|
}
|
|
12
40
|
|
|
41
|
+
function readTextIfPresent(projectDir: string, relativePath: string): string {
|
|
42
|
+
const path = join(projectDir, relativePath);
|
|
43
|
+
return existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isExecutable(projectDir: string, relativePath: string): boolean {
|
|
47
|
+
const path = join(projectDir, relativePath);
|
|
48
|
+
if (!existsSync(path)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return (statSync(path).mode & 0o111) !== 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function collectStableMetadataBlockers(projectDir: string): string[] {
|
|
55
|
+
const blockers: string[] = [];
|
|
56
|
+
const betaPattern = /\b2\.0\.0-beta\.\d+\b|\bv2\.0\.0-beta\.\d+\b/;
|
|
57
|
+
|
|
58
|
+
for (const relativePath of STABLE_METADATA_FILES) {
|
|
59
|
+
const content = readTextIfPresent(projectDir, relativePath);
|
|
60
|
+
if (content && betaPattern.test(content)) {
|
|
61
|
+
blockers.push(`beta marker in ${relativePath}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const pkg = readJsonFile<Record<string, unknown>>(join(projectDir, "package.json"), {});
|
|
66
|
+
if (String(pkg.version || "").includes("-beta.")) {
|
|
67
|
+
blockers.push("beta marker in package.json");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return [...new Set(blockers)];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function collectDeprecatedProviderBlockers(projectDir: string): string[] {
|
|
74
|
+
const blockers: string[] = [];
|
|
75
|
+
|
|
76
|
+
for (const relativePath of DEPRECATED_PROVIDER_FILES) {
|
|
77
|
+
const content = readTextIfPresent(projectDir, relativePath);
|
|
78
|
+
if (content && /\bopencode\b/i.test(content)) {
|
|
79
|
+
blockers.push(`deprecated provider token in ${relativePath}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return blockers;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function collectPackagingBlockers(projectDir: string): string[] {
|
|
87
|
+
const blockers: string[] = [];
|
|
88
|
+
const pkg = readJsonFile<Record<string, any>>(join(projectDir, "package.json"), {});
|
|
89
|
+
const scripts = pkg.scripts && typeof pkg.scripts === "object" ? (pkg.scripts as Record<string, string>) : {};
|
|
90
|
+
|
|
91
|
+
if (scripts.postinstall !== "bash ./OMG-setup.sh install --non-interactive") {
|
|
92
|
+
blockers.push("packaged install smoke missing: package.json postinstall must use bash ./OMG-setup.sh");
|
|
93
|
+
}
|
|
94
|
+
if (scripts.update !== "bash ./OMG-setup.sh update") {
|
|
95
|
+
blockers.push("packaged install smoke missing: package.json update must use bash ./OMG-setup.sh");
|
|
96
|
+
}
|
|
97
|
+
if (scripts.uninstall !== "bash ./OMG-setup.sh uninstall") {
|
|
98
|
+
blockers.push("packaged install smoke missing: package.json uninstall must use bash ./OMG-setup.sh");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const npmignore = readTextIfPresent(projectDir, ".npmignore");
|
|
102
|
+
if (npmignore) {
|
|
103
|
+
const ignoresInstallScript = npmignore.split(/\r?\n/).some((line) => line.trim() === "install.sh");
|
|
104
|
+
const restoresPluginInstallScript = npmignore
|
|
105
|
+
.split(/\r?\n/)
|
|
106
|
+
.some((line) => line.trim() === "!.claude-plugin/scripts/install.sh");
|
|
107
|
+
if (ignoresInstallScript && !restoresPluginInstallScript) {
|
|
108
|
+
blockers.push("packaged install smoke missing: .npmignore excludes .claude-plugin/scripts/install.sh");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (const relativePath of REQUIRED_INSTALL_SCRIPTS) {
|
|
113
|
+
const path = join(projectDir, relativePath);
|
|
114
|
+
if (!existsSync(path)) {
|
|
115
|
+
blockers.push(`packaged install smoke missing: ${relativePath}`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (!isExecutable(projectDir, relativePath)) {
|
|
119
|
+
blockers.push(`packaged install smoke missing: ${relativePath} is not executable`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return blockers;
|
|
124
|
+
}
|
|
125
|
+
|
|
13
126
|
export function collectReleaseReadiness(projectDir: string) {
|
|
14
127
|
const providerStatus = collectProviderStatusWithOptions(projectDir, {
|
|
15
128
|
includeSmoke: true,
|
|
@@ -22,16 +135,27 @@ export function collectReleaseReadiness(projectDir: string) {
|
|
|
22
135
|
const native_ready = providers
|
|
23
136
|
.filter((entry) => Boolean(entry.native_ready))
|
|
24
137
|
.map((entry) => String(entry.provider));
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
138
|
+
|
|
139
|
+
const staticBlockers = {
|
|
140
|
+
stable_metadata: collectStableMetadataBlockers(projectDir),
|
|
141
|
+
deprecated_provider_tokens: collectDeprecatedProviderBlockers(projectDir),
|
|
142
|
+
packaged_install_smoke: collectPackagingBlockers(projectDir)
|
|
143
|
+
};
|
|
144
|
+
|
|
29
145
|
const statusLines = git(projectDir, ["status", "--short"])
|
|
30
146
|
.split(/\r?\n/)
|
|
31
147
|
.filter(Boolean);
|
|
148
|
+
const blockers = [
|
|
149
|
+
...staticBlockers.stable_metadata,
|
|
150
|
+
...staticBlockers.deprecated_provider_tokens,
|
|
151
|
+
...staticBlockers.packaged_install_smoke,
|
|
152
|
+
...(statusLines.length > 0 ? ["git working tree is dirty"] : [])
|
|
153
|
+
];
|
|
154
|
+
|
|
32
155
|
return {
|
|
33
156
|
schema: "OmgReleaseReadiness",
|
|
34
157
|
status: "ok",
|
|
158
|
+
generated_at: nowIso(),
|
|
35
159
|
git: {
|
|
36
160
|
branch: git(projectDir, ["branch", "--show-current"]),
|
|
37
161
|
dirty: statusLines.length > 0,
|
|
@@ -42,7 +166,21 @@ export function collectReleaseReadiness(projectDir: string) {
|
|
|
42
166
|
native_ready,
|
|
43
167
|
matrix: providerStatus
|
|
44
168
|
},
|
|
169
|
+
static_checks: {
|
|
170
|
+
stable_metadata: {
|
|
171
|
+
status: staticBlockers.stable_metadata.length === 0 ? "ok" : "blocked",
|
|
172
|
+
blockers: staticBlockers.stable_metadata
|
|
173
|
+
},
|
|
174
|
+
deprecated_provider_tokens: {
|
|
175
|
+
status: staticBlockers.deprecated_provider_tokens.length === 0 ? "ok" : "blocked",
|
|
176
|
+
blockers: staticBlockers.deprecated_provider_tokens
|
|
177
|
+
},
|
|
178
|
+
packaged_install_smoke: {
|
|
179
|
+
status: staticBlockers.packaged_install_smoke.length === 0 ? "ok" : "blocked",
|
|
180
|
+
blockers: staticBlockers.packaged_install_smoke
|
|
181
|
+
}
|
|
182
|
+
},
|
|
45
183
|
blockers,
|
|
46
|
-
ready_for_release:
|
|
184
|
+
ready_for_release: blockers.length === 0
|
|
47
185
|
};
|
|
48
186
|
}
|
|
@@ -24,8 +24,10 @@ const CHECK_DIRS = [
|
|
|
24
24
|
"commands",
|
|
25
25
|
"control_plane",
|
|
26
26
|
"hooks",
|
|
27
|
+
"hud",
|
|
27
28
|
"lab",
|
|
28
29
|
"omg_natives",
|
|
30
|
+
"plugins",
|
|
29
31
|
"registry",
|
|
30
32
|
"runtime",
|
|
31
33
|
"scripts",
|
|
@@ -41,7 +43,9 @@ const BLOCKED_PATTERNS = [
|
|
|
41
43
|
new RegExp(`\\b${escapeRegex(PYTHON)}3?\\b`, "i"),
|
|
42
44
|
new RegExp(`\\b${escapeRegex(PYTEST)}\\b`, "i"),
|
|
43
45
|
new RegExp(escapeRegex(OMG_PY)),
|
|
44
|
-
new RegExp(escapeRegex(PY))
|
|
46
|
+
new RegExp(escapeRegex(PY)),
|
|
47
|
+
/\bopencode\b/i,
|
|
48
|
+
/\bOpenCode\b/
|
|
45
49
|
];
|
|
46
50
|
|
|
47
51
|
function walk(path: string, files: string[] = []): string[] {
|
|
@@ -13,6 +13,35 @@ function unique<T>(items: T[]): T[] {
|
|
|
13
13
|
return [...new Set(items)];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
type HookCommandEntry = {
|
|
17
|
+
command?: unknown;
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const RETIRED_HOOK_COMMANDS = new Set([
|
|
22
|
+
"\"$HOME/.claude/hooks/pre-tool-inject.ts\"",
|
|
23
|
+
"\"$HOME/.claude/hooks/test-generator-hook.ts\"",
|
|
24
|
+
"\"$HOME/.claude/hooks/post-write.ts\""
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
function pruneRetiredHooks(hooks: Record<string, any>) {
|
|
28
|
+
const pruned: Record<string, any[]> = {};
|
|
29
|
+
for (const [event, entries] of Object.entries(hooks)) {
|
|
30
|
+
const nextEntries = (Array.isArray(entries) ? entries : [])
|
|
31
|
+
.map((entry) => {
|
|
32
|
+
const nextHooks = (Array.isArray(entry?.hooks) ? entry.hooks : []).filter(
|
|
33
|
+
(hook: HookCommandEntry) => !RETIRED_HOOK_COMMANDS.has(String(hook.command || ""))
|
|
34
|
+
);
|
|
35
|
+
return nextHooks.length > 0 ? { ...entry, hooks: nextHooks } : null;
|
|
36
|
+
})
|
|
37
|
+
.filter(Boolean);
|
|
38
|
+
if (nextEntries.length > 0) {
|
|
39
|
+
pruned[event] = nextEntries as any[];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return pruned;
|
|
43
|
+
}
|
|
44
|
+
|
|
16
45
|
function mergeHooks(target: Record<string, any>, source: Record<string, any>) {
|
|
17
46
|
const merged: Record<string, any[]> = { ...target };
|
|
18
47
|
for (const [event, entries] of Object.entries(source)) {
|
|
@@ -28,7 +57,7 @@ function mergeHooks(target: Record<string, any>, source: Record<string, any>) {
|
|
|
28
57
|
}
|
|
29
58
|
merged[event] = current;
|
|
30
59
|
}
|
|
31
|
-
return merged;
|
|
60
|
+
return pruneRetiredHooks(merged);
|
|
32
61
|
}
|
|
33
62
|
|
|
34
63
|
function mergeSettings(target: Record<string, any>, source: Record<string, any>) {
|
package/settings.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
3
|
-
"_comment": "OMG v2.0.0
|
|
3
|
+
"_comment": "OMG v2.0.0 — Bun runtime hook registrations and feature flags.",
|
|
4
4
|
"permissions": {
|
|
5
5
|
"allow": [
|
|
6
6
|
"Agent",
|
|
@@ -174,16 +174,6 @@
|
|
|
174
174
|
]
|
|
175
175
|
}
|
|
176
176
|
],
|
|
177
|
-
"PreToolUse": [
|
|
178
|
-
{
|
|
179
|
-
"hooks": [
|
|
180
|
-
{
|
|
181
|
-
"type": "command",
|
|
182
|
-
"command": "\"$HOME/.claude/hooks/pre-tool-inject.ts\""
|
|
183
|
-
}
|
|
184
|
-
]
|
|
185
|
-
}
|
|
186
|
-
],
|
|
187
177
|
"PostToolUse": [
|
|
188
178
|
{
|
|
189
179
|
"matcher": "Bash",
|
|
@@ -202,16 +192,6 @@
|
|
|
202
192
|
"type": "command",
|
|
203
193
|
"command": "\"$HOME/.claude/hooks/tool-ledger.ts\"",
|
|
204
194
|
"timeout": 10
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
"type": "command",
|
|
208
|
-
"command": "\"$HOME/.claude/hooks/test-generator-hook.ts\"",
|
|
209
|
-
"timeout": 10
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
"type": "command",
|
|
213
|
-
"command": "\"$HOME/.claude/hooks/post-write.ts\"",
|
|
214
|
-
"timeout": 15
|
|
215
195
|
}
|
|
216
196
|
]
|
|
217
197
|
}
|
|
Binary file
|