@hasna/hooks 0.0.1

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.
Files changed (110) hide show
  1. package/.npmrc.example +2 -0
  2. package/AGENTS.md +54 -0
  3. package/CLAUDE.md +70 -0
  4. package/CONTRIBUTING.md +45 -0
  5. package/README.md +232 -0
  6. package/bin/index.js +5171 -0
  7. package/hooks/hook-agentmessages/CLAUDE.md +79 -0
  8. package/hooks/hook-agentmessages/LICENSE +21 -0
  9. package/hooks/hook-agentmessages/README.md +107 -0
  10. package/hooks/hook-agentmessages/package.json +31 -0
  11. package/hooks/hook-agentmessages/src/check-messages.ts +151 -0
  12. package/hooks/hook-agentmessages/src/install.ts +126 -0
  13. package/hooks/hook-agentmessages/src/session-start.ts +255 -0
  14. package/hooks/hook-agentmessages/src/uninstall.ts +89 -0
  15. package/hooks/hook-branchprotect/CLAUDE.md +23 -0
  16. package/hooks/hook-branchprotect/README.md +25 -0
  17. package/hooks/hook-branchprotect/package.json +42 -0
  18. package/hooks/hook-branchprotect/src/cli.ts +126 -0
  19. package/hooks/hook-branchprotect/src/hook.ts +88 -0
  20. package/hooks/hook-branchprotect/tsconfig.json +25 -0
  21. package/hooks/hook-checkbugs/LICENSE +21 -0
  22. package/hooks/hook-checkbugs/README.md +140 -0
  23. package/hooks/hook-checkbugs/package.json +58 -0
  24. package/hooks/hook-checkbugs/src/cli.ts +628 -0
  25. package/hooks/hook-checkbugs/src/hook.ts +335 -0
  26. package/hooks/hook-checkbugs/tsconfig.json +15 -0
  27. package/hooks/hook-checkdocs/README.md +137 -0
  28. package/hooks/hook-checkdocs/package.json +57 -0
  29. package/hooks/hook-checkdocs/src/cli.ts +628 -0
  30. package/hooks/hook-checkdocs/src/hook.ts +310 -0
  31. package/hooks/hook-checkdocs/tsconfig.json +15 -0
  32. package/hooks/hook-checkfiles/LICENSE +21 -0
  33. package/hooks/hook-checkfiles/README.md +141 -0
  34. package/hooks/hook-checkfiles/package.json +56 -0
  35. package/hooks/hook-checkfiles/src/cli.ts +545 -0
  36. package/hooks/hook-checkfiles/src/hook.ts +321 -0
  37. package/hooks/hook-checkfiles/tsconfig.json +15 -0
  38. package/hooks/hook-checklint/LICENSE +21 -0
  39. package/hooks/hook-checklint/README.md +147 -0
  40. package/hooks/hook-checklint/package.json +57 -0
  41. package/hooks/hook-checklint/src/cli-patch.ts +32 -0
  42. package/hooks/hook-checklint/src/cli.ts +667 -0
  43. package/hooks/hook-checklint/src/hook.ts +473 -0
  44. package/hooks/hook-checklint/tsconfig.json +15 -0
  45. package/hooks/hook-checkpoint/CLAUDE.md +23 -0
  46. package/hooks/hook-checkpoint/README.md +37 -0
  47. package/hooks/hook-checkpoint/package.json +58 -0
  48. package/hooks/hook-checkpoint/src/cli.ts +191 -0
  49. package/hooks/hook-checkpoint/src/hook.ts +207 -0
  50. package/hooks/hook-checkpoint/tsconfig.json +25 -0
  51. package/hooks/hook-checksecurity/LICENSE +21 -0
  52. package/hooks/hook-checksecurity/README.md +158 -0
  53. package/hooks/hook-checksecurity/package.json +57 -0
  54. package/hooks/hook-checksecurity/src/cli.ts +601 -0
  55. package/hooks/hook-checksecurity/src/hook.ts +334 -0
  56. package/hooks/hook-checksecurity/tsconfig.json +15 -0
  57. package/hooks/hook-checktasks/README.md +144 -0
  58. package/hooks/hook-checktasks/package.json +55 -0
  59. package/hooks/hook-checktasks/src/cli.ts +578 -0
  60. package/hooks/hook-checktasks/src/hook.ts +308 -0
  61. package/hooks/hook-checktasks/tsconfig.json +20 -0
  62. package/hooks/hook-checktests/LICENSE +21 -0
  63. package/hooks/hook-checktests/README.md +137 -0
  64. package/hooks/hook-checktests/package.json +57 -0
  65. package/hooks/hook-checktests/src/cli.ts +627 -0
  66. package/hooks/hook-checktests/src/hook.ts +334 -0
  67. package/hooks/hook-checktests/tsconfig.json +15 -0
  68. package/hooks/hook-contextrefresh/CLAUDE.md +23 -0
  69. package/hooks/hook-contextrefresh/README.md +42 -0
  70. package/hooks/hook-contextrefresh/package.json +42 -0
  71. package/hooks/hook-contextrefresh/src/cli.ts +152 -0
  72. package/hooks/hook-contextrefresh/src/hook.ts +148 -0
  73. package/hooks/hook-contextrefresh/tsconfig.json +25 -0
  74. package/hooks/hook-gitguard/CLAUDE.md +22 -0
  75. package/hooks/hook-gitguard/README.md +30 -0
  76. package/hooks/hook-gitguard/package.json +57 -0
  77. package/hooks/hook-gitguard/src/cli.ts +159 -0
  78. package/hooks/hook-gitguard/src/hook.ts +129 -0
  79. package/hooks/hook-gitguard/tsconfig.json +25 -0
  80. package/hooks/hook-packageage/CLAUDE.md +23 -0
  81. package/hooks/hook-packageage/README.md +33 -0
  82. package/hooks/hook-packageage/package.json +42 -0
  83. package/hooks/hook-packageage/src/cli.ts +165 -0
  84. package/hooks/hook-packageage/src/hook.ts +177 -0
  85. package/hooks/hook-packageage/tsconfig.json +25 -0
  86. package/hooks/hook-phonenotify/CLAUDE.md +25 -0
  87. package/hooks/hook-phonenotify/README.md +44 -0
  88. package/hooks/hook-phonenotify/package.json +42 -0
  89. package/hooks/hook-phonenotify/src/cli.ts +196 -0
  90. package/hooks/hook-phonenotify/src/hook.ts +139 -0
  91. package/hooks/hook-phonenotify/tsconfig.json +25 -0
  92. package/hooks/hook-precompact/CLAUDE.md +23 -0
  93. package/hooks/hook-precompact/README.md +36 -0
  94. package/hooks/hook-precompact/package.json +42 -0
  95. package/hooks/hook-precompact/src/cli.ts +168 -0
  96. package/hooks/hook-precompact/src/hook.ts +122 -0
  97. package/hooks/hook-precompact/tsconfig.json +25 -0
  98. package/package.json +61 -0
  99. package/src/cli/components/App.tsx +191 -0
  100. package/src/cli/components/CategorySelect.tsx +37 -0
  101. package/src/cli/components/DataTable.tsx +133 -0
  102. package/src/cli/components/Header.tsx +18 -0
  103. package/src/cli/components/HookSelect.tsx +29 -0
  104. package/src/cli/components/InstallProgress.tsx +105 -0
  105. package/src/cli/components/SearchView.tsx +86 -0
  106. package/src/cli/index.tsx +218 -0
  107. package/src/index.ts +31 -0
  108. package/src/lib/installer.ts +288 -0
  109. package/src/lib/registry.ts +205 -0
  110. package/tsconfig.json +17 -0
@@ -0,0 +1,334 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * Claude Code Hook: check-security
5
+ *
6
+ * Runs security checks via Claude and Codex headless agents.
7
+ * This is a BLOCKER hook on the Stop event.
8
+ *
9
+ * Only runs for repos matching [prefix]-[name] pattern.
10
+ * Only runs once per session (state flag prevents re-runs).
11
+ *
12
+ * Configuration:
13
+ * - taskListId: task list for dispatching security tasks
14
+ * - keywords: keywords that trigger the check (default: ["dev"])
15
+ * - enabled: enable/disable the hook
16
+ */
17
+
18
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
19
+ import { join } from "path";
20
+ import { homedir } from "os";
21
+ import { spawnSync, execSync } from "child_process";
22
+
23
+ interface CheckSecurityConfig {
24
+ taskListId?: string;
25
+ keywords?: string[];
26
+ enabled?: boolean;
27
+ }
28
+
29
+ interface HookInput {
30
+ session_id: string;
31
+ transcript_path: string;
32
+ cwd: string;
33
+ }
34
+
35
+ interface SessionState {
36
+ securityChecked: boolean;
37
+ lastCheckRun: number;
38
+ }
39
+
40
+ const CONFIG_KEY = "checkSecurityConfig";
41
+ const STATE_DIR = join(homedir(), ".claude", "hook-state");
42
+
43
+ /**
44
+ * Sanitize ID to prevent path traversal and injection attacks
45
+ */
46
+ function sanitizeId(id: string): string {
47
+ if (!id || typeof id !== 'string') return 'default';
48
+ return id.replace(/[^a-zA-Z0-9_-]/g, '-').slice(0, 100) || 'default';
49
+ }
50
+
51
+ const SECURITY_PROMPT = `You are a security reviewer. Analyze the codebase in the current directory for security vulnerabilities.
52
+
53
+ For each security issue found, create a task using the service-implementation CLI:
54
+ service-implementation task dispatch "{taskListId}" -s "SECURITY: [severity] - [brief description]" -d "[detailed description with file:line reference and remediation advice]"
55
+
56
+ Severity levels: CRITICAL, HIGH, MEDIUM, LOW
57
+
58
+ Focus on:
59
+ - Injection vulnerabilities (SQL, XSS, command injection)
60
+ - Authentication/authorization issues
61
+ - Sensitive data exposure
62
+ - Insecure configurations
63
+ - Dependency vulnerabilities
64
+ - Hardcoded secrets or credentials
65
+ - Input validation issues
66
+ - CSRF vulnerabilities
67
+ - Insecure deserialization
68
+
69
+ If no security issues are found, do not create any tasks.
70
+ Only create tasks for real security concerns.
71
+ Limit to max 10 most critical security issues.`;
72
+
73
+ function isValidRepoPattern(cwd: string): boolean {
74
+ const dirName = cwd.split("/").filter(Boolean).pop() || "";
75
+ // Match: hook-checklint, skill-installhook, iapp-mail, etc.
76
+ return /^[a-z]+-[a-z0-9-]+$/i.test(dirName);
77
+ }
78
+
79
+ function readStdinJson(): HookInput | null {
80
+ try {
81
+ const stdin = readFileSync(0, "utf-8");
82
+ return JSON.parse(stdin);
83
+ } catch {
84
+ return null;
85
+ }
86
+ }
87
+
88
+ function readSettings(path: string): Record<string, unknown> {
89
+ if (!existsSync(path)) return {};
90
+ try {
91
+ return JSON.parse(readFileSync(path, "utf-8"));
92
+ } catch {
93
+ return {};
94
+ }
95
+ }
96
+
97
+ function getConfig(cwd: string): CheckSecurityConfig {
98
+ // Try project settings first
99
+ const projectSettings = readSettings(join(cwd, ".claude", "settings.json"));
100
+ if (projectSettings[CONFIG_KEY]) {
101
+ return projectSettings[CONFIG_KEY] as CheckSecurityConfig;
102
+ }
103
+
104
+ // Fall back to global settings
105
+ const globalSettings = readSettings(join(homedir(), ".claude", "settings.json"));
106
+ if (globalSettings[CONFIG_KEY]) {
107
+ return globalSettings[CONFIG_KEY] as CheckSecurityConfig;
108
+ }
109
+
110
+ // Default config
111
+ return {
112
+ keywords: ["dev"],
113
+ enabled: true,
114
+ };
115
+ }
116
+
117
+ function getStateFile(sessionId: string): string {
118
+ mkdirSync(STATE_DIR, { recursive: true });
119
+ const safeSessionId = sanitizeId(sessionId);
120
+ return join(STATE_DIR, `checksecurity-${safeSessionId}.json`);
121
+ }
122
+
123
+ function getSessionState(sessionId: string): SessionState {
124
+ const stateFile = getStateFile(sessionId);
125
+ if (existsSync(stateFile)) {
126
+ try {
127
+ return JSON.parse(readFileSync(stateFile, "utf-8"));
128
+ } catch {
129
+ // Corrupted state, reset
130
+ }
131
+ }
132
+ return { securityChecked: false, lastCheckRun: 0 };
133
+ }
134
+
135
+ function saveSessionState(sessionId: string, state: SessionState): void {
136
+ const stateFile = getStateFile(sessionId);
137
+ writeFileSync(stateFile, JSON.stringify(state, null, 2));
138
+ }
139
+
140
+ function getSessionName(transcriptPath: string): string | null {
141
+ if (!existsSync(transcriptPath)) return null;
142
+
143
+ try {
144
+ const content = readFileSync(transcriptPath, "utf-8");
145
+ let lastTitle: string | null = null;
146
+ let searchStart = 0;
147
+
148
+ while (true) {
149
+ const titleIndex = content.indexOf('"custom-title"', searchStart);
150
+ if (titleIndex === -1) break;
151
+
152
+ const lineStart = content.lastIndexOf("\n", titleIndex) + 1;
153
+ const lineEnd = content.indexOf("\n", titleIndex);
154
+ const line = content.slice(lineStart, lineEnd === -1 ? undefined : lineEnd);
155
+
156
+ try {
157
+ const entry = JSON.parse(line);
158
+ if (entry.type === "custom-title" && entry.customTitle) {
159
+ lastTitle = entry.customTitle;
160
+ }
161
+ } catch {
162
+ // Skip malformed lines
163
+ }
164
+
165
+ searchStart = titleIndex + 1;
166
+ }
167
+
168
+ return lastTitle;
169
+ } catch {
170
+ return null;
171
+ }
172
+ }
173
+
174
+ function getProjectTaskListId(cwd: string): string | null {
175
+ const dirName = cwd.split("/").filter(Boolean).pop() || "";
176
+ return `${dirName}-dev`;
177
+ }
178
+
179
+ function isClaudeAvailable(): boolean {
180
+ try {
181
+ execSync("which claude", { stdio: "pipe" });
182
+ return true;
183
+ } catch {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ function isCodexAvailable(): boolean {
189
+ try {
190
+ execSync("which codex", { stdio: "pipe" });
191
+ return true;
192
+ } catch {
193
+ return false;
194
+ }
195
+ }
196
+
197
+ function runClaudeSecurityCheck(cwd: string, taskListId: string): void {
198
+ const safeTaskListId = sanitizeId(taskListId);
199
+ const prompt = SECURITY_PROMPT.replace("{taskListId}", safeTaskListId);
200
+
201
+ console.error(`[hook-checksecurity] Running Claude security check...`);
202
+
203
+ spawnSync(
204
+ "claude",
205
+ [
206
+ "-p",
207
+ prompt,
208
+ "--permission-mode",
209
+ "acceptEdits",
210
+ "--allowedTools",
211
+ "Bash,Read,Glob,Grep",
212
+ "--no-session-persistence",
213
+ ],
214
+ {
215
+ cwd,
216
+ stdio: "inherit",
217
+ }
218
+ );
219
+ }
220
+
221
+ function runCodexSecurityCheck(cwd: string, taskListId: string): void {
222
+ const safeTaskListId = sanitizeId(taskListId);
223
+ const prompt = SECURITY_PROMPT.replace("{taskListId}", safeTaskListId);
224
+
225
+ console.error(`[hook-checksecurity] Running Codex security check...`);
226
+
227
+ spawnSync(
228
+ "codex",
229
+ [
230
+ "exec",
231
+ prompt,
232
+ ],
233
+ {
234
+ cwd,
235
+ stdio: "inherit",
236
+ }
237
+ );
238
+ }
239
+
240
+ function approve() {
241
+ console.log(JSON.stringify({ decision: "approve" }));
242
+ process.exit(0);
243
+ }
244
+
245
+ function block(reason: string) {
246
+ console.log(JSON.stringify({ decision: "block", reason }));
247
+ process.exit(0);
248
+ }
249
+
250
+ export function run() {
251
+ const hookInput = readStdinJson();
252
+ if (!hookInput) {
253
+ approve();
254
+ return;
255
+ }
256
+
257
+ const { session_id, cwd, transcript_path } = hookInput;
258
+
259
+ // Check repo pattern - only run for [prefix]-[name] folders
260
+ if (!isValidRepoPattern(cwd)) {
261
+ approve();
262
+ return;
263
+ }
264
+
265
+ const config = getConfig(cwd);
266
+
267
+ // Check if hook is disabled
268
+ if (config.enabled === false) {
269
+ approve();
270
+ return;
271
+ }
272
+
273
+ // Check keywords match
274
+ const sessionName = transcript_path ? getSessionName(transcript_path) : null;
275
+ const nameToCheck = sessionName || config.taskListId || "";
276
+ const keywords = config.keywords || ["dev"];
277
+
278
+ const matchesKeyword = keywords.some((keyword) =>
279
+ nameToCheck.toLowerCase().includes(keyword.toLowerCase())
280
+ );
281
+
282
+ // If keywords are configured and we have a session name, check for match
283
+ if (keywords.length > 0 && nameToCheck && !matchesKeyword) {
284
+ approve();
285
+ return;
286
+ }
287
+
288
+ // Check session state - only run once per session
289
+ const state = getSessionState(session_id);
290
+ if (state.securityChecked) {
291
+ // Already ran security check this session
292
+ approve();
293
+ return;
294
+ }
295
+
296
+ // Mark as checked before running (prevent re-runs)
297
+ state.securityChecked = true;
298
+ state.lastCheckRun = Date.now();
299
+ saveSessionState(session_id, state);
300
+
301
+ const taskListId = config.taskListId || getProjectTaskListId(cwd) || "default-dev";
302
+
303
+ // Run security checks
304
+ const claudeAvailable = isClaudeAvailable();
305
+ const codexAvailable = isCodexAvailable();
306
+
307
+ if (!claudeAvailable && !codexAvailable) {
308
+ console.error(`[hook-checksecurity] Neither Claude nor Codex CLI available, skipping security check`);
309
+ approve();
310
+ return;
311
+ }
312
+
313
+ console.error(`[hook-checksecurity] Running security checks for ${cwd}`);
314
+
315
+ // Run Claude security check
316
+ if (claudeAvailable) {
317
+ runClaudeSecurityCheck(cwd, taskListId);
318
+ }
319
+
320
+ // Run Codex security check
321
+ if (codexAvailable) {
322
+ runCodexSecurityCheck(cwd, taskListId);
323
+ }
324
+
325
+ console.error(`[hook-checksecurity] Security checks completed`);
326
+
327
+ // After running checks, approve (let checktasks handle blocking if tasks exist)
328
+ approve();
329
+ }
330
+
331
+ // Allow direct execution
332
+ if (import.meta.main) {
333
+ run();
334
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "./dist",
10
+ "declaration": true,
11
+ "declarationMap": true
12
+ },
13
+ "include": ["src/**/*"],
14
+ "exclude": ["node_modules", "dist"]
15
+ }
@@ -0,0 +1,144 @@
1
+ # @hasnaxyz/hook-checktasks
2
+
3
+ A Claude Code hook that prevents Claude from stopping when there are pending tasks.
4
+
5
+ ## What it does
6
+
7
+ This hook intercepts Claude's "Stop" event and:
8
+
9
+ 1. Checks configured task lists for pending/in-progress tasks
10
+ 2. If tasks remain → **blocks the stop** and prompts Claude to continue
11
+ 3. If all complete → allows stop
12
+
13
+ ## Installation
14
+
15
+ ### 1. Install the CLI globally
16
+
17
+ ```bash
18
+ bun add -g @hasnaxyz/hook-checktasks
19
+ # or
20
+ npm install -g @hasnaxyz/hook-checktasks
21
+ ```
22
+
23
+ ### 2. Install the hook
24
+
25
+ ```bash
26
+ # Auto-detect (git repo → project, else → prompt)
27
+ hook-checktasks install
28
+
29
+ # Install globally
30
+ hook-checktasks install --global
31
+
32
+ # Install to specific path
33
+ hook-checktasks install /path/to/project
34
+ ```
35
+
36
+ The installer will prompt you to configure:
37
+ - **Task list ID**: specific list or leave empty for all lists
38
+ - **Keywords**: session/list name keywords to trigger the check (default: "dev")
39
+
40
+ ## Configuration
41
+
42
+ ### Update configuration
43
+
44
+ ```bash
45
+ hook-checktasks config # Current project
46
+ hook-checktasks config --global # Global settings
47
+ ```
48
+
49
+ ### Check status
50
+
51
+ ```bash
52
+ hook-checktasks status
53
+ ```
54
+
55
+ Shows:
56
+ - Where hook is installed (global/project)
57
+ - Current configuration
58
+ - Available task lists
59
+
60
+ ### Uninstall
61
+
62
+ ```bash
63
+ hook-checktasks uninstall # Current project
64
+ hook-checktasks uninstall --global # Global
65
+ hook-checktasks uninstall /path # Specific path
66
+ ```
67
+
68
+ ## How Configuration Works
69
+
70
+ Configuration is stored in `.claude/settings.json`:
71
+
72
+ ```json
73
+ {
74
+ "hooks": {
75
+ "Stop": [{ "hooks": [{ "type": "command", "command": "bunx @hasnaxyz/hook-checktasks run" }] }]
76
+ },
77
+ "checkTasksConfig": {
78
+ "taskListId": "myproject-dev",
79
+ "keywords": ["dev"],
80
+ "enabled": true
81
+ }
82
+ }
83
+ ```
84
+
85
+ ### Config Options
86
+
87
+ | Option | Description | Default |
88
+ |--------|-------------|---------|
89
+ | `taskListId` | Specific task list to check, or `undefined` for all lists | `undefined` (all) |
90
+ | `keywords` | Keywords to match in session/list names | `["dev"]` |
91
+ | `enabled` | Enable/disable the hook | `true` |
92
+
93
+ ### Priority
94
+
95
+ 1. Project settings (`.claude/settings.json`)
96
+ 2. Global settings (`~/.claude/settings.json`)
97
+ 3. Environment variables (legacy)
98
+
99
+ ### Legacy Environment Variables
100
+
101
+ Still supported for backwards compatibility:
102
+
103
+ ```bash
104
+ CLAUDE_CODE_TASK_LIST_ID=myproject-dev claude
105
+ CHECK_TASKS_KEYWORDS=dev,sprint claude
106
+ CHECK_TASKS_DISABLED=1 claude
107
+ ```
108
+
109
+ ## CLI Commands
110
+
111
+ ```
112
+ hook-checktasks install [path] Install the hook
113
+ hook-checktasks config [path] Update configuration
114
+ hook-checktasks uninstall [path] Remove the hook
115
+ hook-checktasks status Show hook status
116
+ hook-checktasks run Execute hook (called by Claude Code)
117
+
118
+ Options:
119
+ --global, -g Apply to global settings
120
+ /path/to/repo Apply to specific project
121
+ ```
122
+
123
+ ## How it Works
124
+
125
+ ```
126
+ Claude tries to stop
127
+
128
+
129
+ Stop hook fires
130
+
131
+
132
+ Read config from settings.json
133
+
134
+
135
+ Check matching task lists
136
+
137
+ ├── Tasks remaining → BLOCK stop, prompt to continue
138
+
139
+ └── All complete → ALLOW stop
140
+ ```
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@hasnaxyz/hook-checktasks",
3
+ "version": "1.0.8",
4
+ "description": "Claude Code hook that prevents stopping when there are pending tasks",
5
+ "type": "module",
6
+ "bin": {
7
+ "hook-checktasks": "./dist/cli.js"
8
+ },
9
+ "main": "./dist/hook.js",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/hook.js",
13
+ "types": "./dist/hook.d.ts"
14
+ },
15
+ "./cli": {
16
+ "import": "./dist/cli.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "scripts": {
24
+ "build": "bun build ./src/cli.ts ./src/hook.ts --outdir ./dist --target node",
25
+ "prepublishOnly": "bun run build",
26
+ "typecheck": "tsc --noEmit"
27
+ },
28
+ "keywords": [
29
+ "claude-code",
30
+ "claude",
31
+ "hook",
32
+ "tasks",
33
+ "automation",
34
+ "cli"
35
+ ],
36
+ "author": "Hasna",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/hasnaxyz/hook-checktasks.git"
41
+ },
42
+ "publishConfig": {
43
+ "access": "restricted",
44
+ "registry": "https://registry.npmjs.org/"
45
+ },
46
+ "engines": {
47
+ "node": ">=18",
48
+ "bun": ">=1.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/bun": "^1.3.8",
52
+ "@types/node": "^20",
53
+ "typescript": "^5.0.0"
54
+ }
55
+ }