vibe-checking 1.0.3 → 1.2.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.
package/README.md CHANGED
@@ -1,41 +1,57 @@
1
1
  # vibecheck
2
2
 
3
- Security audit for AI-generated codebases. Finds vulnerabilities, then traces them back to the prompt that caused them.
3
+ Security audit for AI-generated codebases.
4
+
5
+ vibecheck finds security vulnerabilities in your code and traces each one back to the AI prompt that introduced it.
6
+
7
+ Run it before you deploy, or whenever you want to check what your AI sessions left behind.
4
8
 
5
9
  No account. No API key. Nothing leaves your machine.
6
10
 
7
11
  ## Quick start
8
12
 
9
13
  ```bash
10
- npx vibe-checking --with-cursor-history
14
+ npx vibe-checking --with-cursor-history --with-claude-history
11
15
  ```
12
16
 
13
- Run this from your project directory. The tool scans your code, reads your Cursor session history, and shows which prompts introduced each vulnerability.
17
+ Run this from your project directory. To scan automatically on every push:
18
+
19
+ ```bash
20
+ npx vibe-checking hook install
21
+ ```
14
22
 
15
23
  ## What it checks
16
24
 
17
25
  - **Secrets** — leaked API keys, tokens, credentials in git history (via gitleaks)
18
- - **Code vulnerabilities** — injection, XSS, auth gaps, unverified webhooks (via semgrep)
26
+ - **Code vulnerabilities** — injection, XSS, crypto issues, auth gaps (via semgrep)
19
27
  - **Supabase RLS** — tables missing Row Level Security in your migrations
20
28
  - **Dependencies** — known CVEs in your packages (via npm audit)
21
29
 
22
- gitleaks and semgrep are auto-installed if missing. If installation fails, the tool skips that check and continues.
30
+ gitleaks and semgrep are auto-installed if missing.
23
31
 
24
- ## Prompt tracing
32
+ ## Vibe coding analysis
25
33
 
26
- This is what makes vibecheck different from a regular scanner.
34
+ When you add `--with-cursor-history` or `--with-claude-history`, vibecheck reads the session files that Cursor and Claude Code store locally on your machine. It performs two analyses:
27
35
 
28
- When you add `--with-cursor-history` or `--with-claude-history`, the tool reads the session files that Cursor and Claude Code store locally on your machine. It matches each finding to the prompt that generated the vulnerable code, and shows how the prompt should have been written.
36
+ **Prompt tracing** matches each security finding to the AI prompt that generated the vulnerable code. Shows what the prompt asked for, what file was generated, and what security constraints were missing.
29
37
 
30
- Without these flags, you still get the full security scan just without the prompt correlation.
38
+ **Behavior analysis** looks at how you interacted with the AI across all sessions:
39
+ - **Blind approval chains** — sequences of 3+ "ok/continue/oui" where code was accepted without review
40
+ - **High-delegation prompts** — short prompts that generated large amounts of code
41
+ - **Files without review** — generated files never mentioned again in the conversation
42
+ - **Security-blind sessions** — sessions where security was never mentioned in any prompt
43
+
44
+ Without these flags, you still get the full security scan — just without the prompt tracing and behavior analysis.
31
45
 
32
46
  ## Usage
33
47
 
34
48
  ```bash
35
49
  npx vibe-checking # security scan only
36
- npx vibe-checking --with-cursor-history # scan + trace Cursor prompts
37
- npx vibe-checking --with-claude-history # scan + trace Claude Code prompts
38
- npx vibe-checking --with-cursor-history --with-claude-history # scan + trace both
50
+ npx vibe-checking --with-cursor-history # scan + vibe analysis (Cursor)
51
+ npx vibe-checking --with-claude-history # scan + vibe analysis (Claude)
52
+ npx vibe-checking --with-cursor-history --with-claude-history # scan + vibe analysis (both)
53
+ npx vibe-checking hook install # add pre-push hook
54
+ npx vibe-checking hook remove # remove pre-push hook
39
55
  ```
40
56
 
41
57
  ## Interactive commands
@@ -44,16 +60,47 @@ Once the scan completes, you get an interactive prompt:
44
60
 
45
61
  | Command | Action |
46
62
  |---------|--------|
47
- | `1`, `2`, `3`... | Inspect a finding |
48
- | `fix` | Show the rewritten secure prompt |
63
+ | `1`, `2`, `3`... | Inspect a finding (shows prompt trace + missing constraints) |
64
+ | `solved` | Mark finding as fixed in code |
49
65
  | `ignore` | Dismiss the current finding |
50
66
  | `next` | Jump to the next open finding |
51
67
  | `list` | Reprint the list with updated score |
52
- | `q` | Save an HTML report and exit |
68
+ | `vibe` | Show vibe coding behavior analysis |
69
+ | `q` | Save statuses and write report |
70
+
71
+ ## Persistent statuses
72
+
73
+ Findings you mark as `solved` or `ignore` are saved in a `.vibecheck` file at the root of your repo. On the next scan, vibecheck loads these statuses:
74
+
75
+ - **ignored** findings stay dismissed
76
+ - **solved** findings are re-checked — if the vulnerability is still there, it goes back to open
77
+
78
+ Commit `.vibecheck` to share decisions with your team. If all findings are handled, the scan passes silently.
79
+
80
+ ## Git hook
81
+
82
+ `npx vibe-checking hook install` adds a pre-push hook to your repo. Every time you `git push`, vibecheck runs a full scan. If there are open findings, the REPL opens and you need to handle them before the push goes through. If everything is already solved or ignored, the push passes immediately.
83
+
84
+ If you installed the hook before v1.2.1, remove and reinstall so vibecheck runs before any existing `exit 0` in your hook:
85
+
86
+ ```bash
87
+ npx vibe-checking hook remove
88
+ npx vibe-checking hook install
89
+ ```
90
+
91
+ To skip the hook once: `git push --no-verify`.
92
+
93
+ ## How it works
53
94
 
54
- ## Privacy
95
+ Everything runs locally:
96
+ - **gitleaks** and **semgrep** are local binaries that scan your code and git history
97
+ - **RLS analysis** parses your SQL migration files directly
98
+ - **npm audit** checks your lock file against the npm vulnerability database
99
+ - **Prompt history** is read from local files (`~/.claude/projects/` and `~/.cursor/projects/`)
100
+ - **Behavior analysis** is pattern matching on your prompt text and session structure
101
+ - **Statuses** are saved in `.vibecheck` at the root of your repo
55
102
 
56
- Everything runs locally. The scanners are local binaries. The session history is read from local files. The HTML report is saved to your project directory. Nothing is uploaded, no telemetry, no account required.
103
+ No API keys needed. No code uploaded.
57
104
 
58
105
  ---
59
106
 
@@ -0,0 +1,11 @@
1
+ import type { ClaudeSession, Finding } from "../types.js";
2
+ export interface VibeAnalysis {
3
+ blindChains: number;
4
+ highDelegationPrompts: number;
5
+ filesWithoutReview: number;
6
+ sessionsWithoutSecurityMention: number;
7
+ totalSessions: number;
8
+ totalPrompts: number;
9
+ findingsFromBlindChains: number;
10
+ }
11
+ export declare function analyzeVibePatterns(sessions: ClaudeSession[], findings: Finding[]): VibeAnalysis;
@@ -0,0 +1,105 @@
1
+ const GENERIC_PROMPT_RE = /^(ok|oui|yes|yep|go|continue|next|sure|d'accord|parfait|merci|thanks|good|bien|c'est bon|les autres|et les autres|la suite)/i;
2
+ const SECURITY_KEYWORDS = [
3
+ "security", "auth", "validation", "rls", "sanitize", "encrypt",
4
+ "permission", "policy", "access control", "xss", "injection",
5
+ "csrf", "cors", "secret", "credential", "token verification",
6
+ "signature", "webhook secret", "row level",
7
+ ];
8
+ const BLIND_CHAIN_THRESHOLD = 3;
9
+ const HIGH_DELEGATION_RATIO = 20;
10
+ function isGeneric(text) {
11
+ const clean = text.replace(/\s+/g, " ").trim();
12
+ return clean.length < 25 || GENERIC_PROMPT_RE.test(clean);
13
+ }
14
+ function wordCount(text) {
15
+ return text.trim().split(/\s+/).filter(Boolean).length;
16
+ }
17
+ export function analyzeVibePatterns(sessions, findings) {
18
+ let blindChains = 0;
19
+ let highDelegationPrompts = 0;
20
+ let filesWithoutReview = 0;
21
+ let sessionsWithoutSecurityMention = 0;
22
+ let totalPrompts = 0;
23
+ const blindChainFiles = new Set();
24
+ for (const session of sessions) {
25
+ const prompts = session.prompts;
26
+ totalPrompts += prompts.length;
27
+ // Signal 1: blind approval chains
28
+ let consecutiveGeneric = 0;
29
+ for (const prompt of prompts) {
30
+ if (isGeneric(prompt.text)) {
31
+ consecutiveGeneric++;
32
+ if (consecutiveGeneric >= BLIND_CHAIN_THRESHOLD) {
33
+ if (consecutiveGeneric === BLIND_CHAIN_THRESHOLD)
34
+ blindChains++;
35
+ for (const f of prompt.filesGenerated) {
36
+ blindChainFiles.add(f);
37
+ }
38
+ }
39
+ }
40
+ else {
41
+ consecutiveGeneric = 0;
42
+ }
43
+ }
44
+ // Signal 2: high delegation ratio
45
+ for (const prompt of prompts) {
46
+ if (prompt.toolCalls.length === 0)
47
+ continue;
48
+ const words = wordCount(prompt.text);
49
+ if (words < 3)
50
+ continue;
51
+ let linesGenerated = 0;
52
+ for (const tc of prompt.toolCalls) {
53
+ if (tc.content) {
54
+ linesGenerated += tc.content.split("\n").length;
55
+ }
56
+ }
57
+ if (linesGenerated > 0 && linesGenerated / words > HIGH_DELEGATION_RATIO) {
58
+ highDelegationPrompts++;
59
+ }
60
+ }
61
+ // Signal 3: files accepted without review
62
+ const allGeneratedFiles = new Set();
63
+ const mentionedInFollowUp = new Set();
64
+ for (let i = 0; i < prompts.length; i++) {
65
+ for (const f of prompts[i].filesGenerated) {
66
+ allGeneratedFiles.add(f);
67
+ }
68
+ // Check if later prompts mention any previously generated files
69
+ if (i > 0) {
70
+ const promptLower = prompts[i].text.toLowerCase();
71
+ for (const f of allGeneratedFiles) {
72
+ const basename = f.split("/").pop() || f;
73
+ if (promptLower.includes(basename.toLowerCase())) {
74
+ mentionedInFollowUp.add(f);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ filesWithoutReview += allGeneratedFiles.size - mentionedInFollowUp.size;
80
+ // Signal 4: no security mention
81
+ const hasSecurityMention = prompts.some((p) => {
82
+ const lower = p.text.toLowerCase();
83
+ return SECURITY_KEYWORDS.some((kw) => lower.includes(kw));
84
+ });
85
+ if (!hasSecurityMention) {
86
+ sessionsWithoutSecurityMention++;
87
+ }
88
+ }
89
+ // Cross-reference: how many findings come from blind chain files
90
+ const findingsFromBlindChains = findings.filter((f) => {
91
+ if (!f.trace)
92
+ return false;
93
+ return Array.from(blindChainFiles).some((bcf) => bcf.endsWith(f.path) || f.path.endsWith(bcf.split("/").pop() || ""));
94
+ }).length;
95
+ return {
96
+ blindChains,
97
+ highDelegationPrompts,
98
+ filesWithoutReview,
99
+ sessionsWithoutSecurityMention,
100
+ totalSessions: sessions.length,
101
+ totalPrompts,
102
+ findingsFromBlindChains,
103
+ };
104
+ }
105
+ //# sourceMappingURL=behavior.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior.js","sourceRoot":"","sources":["../../src/analysis/behavior.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,6 @@ export function correlateFindings(findings, sessions, repoPath) {
6
6
  const correlation = findCorrelation(finding, sessions, repoPath);
7
7
  if (correlation) {
8
8
  finding.trace = correlation.trace;
9
- finding.fix = correlation.fix;
10
9
  }
11
10
  else if (!finding.manual) {
12
11
  finding.manual = guessManualNote(finding);
@@ -52,9 +51,8 @@ function findCorrelation(finding, sessions, repoPath) {
52
51
  return false;
53
52
  });
54
53
  if (matchedFile) {
55
- const trace = buildTrace(finding, prompt, session, matchedFile);
56
- const fix = generateFix(finding, prompt);
57
- return { trace, fix };
54
+ const trace = buildTrace(finding, prompt, session, matchedFile, repoPath);
55
+ return { trace };
58
56
  }
59
57
  }
60
58
  }
@@ -71,14 +69,22 @@ function extractFilePath(path) {
71
69
  // "supabase/migrations/0007_orgs.sql" or "app/api/upload/route.ts"
72
70
  return path;
73
71
  }
74
- function buildTrace(finding, prompt, session, matchedFile) {
72
+ function relativize(filePath, repoPath) {
73
+ const prefix = repoPath.endsWith("/") ? repoPath : repoPath + "/";
74
+ if (filePath.startsWith(prefix))
75
+ return filePath.slice(prefix.length);
76
+ return filePath;
77
+ }
78
+ function buildTrace(finding, prompt, session, matchedFile, repoPath) {
75
79
  const ts = formatTimestamp(prompt.timestamp || session.timestamp);
76
80
  const lineCount = estimateLineCount(prompt, matchedFile);
81
+ const relFile = relativize(matchedFile, repoPath);
77
82
  return {
78
83
  prompt: `"${truncate(prompt.text, 120)}"`,
79
84
  session: `${ts} · claude code`,
80
- file: `${matchedFile}${lineCount ? ` (+${lineCount} lines)` : ""}`,
85
+ file: `${relFile}${lineCount ? ` (+${lineCount} lines)` : ""}`,
81
86
  result: inferResult(finding),
87
+ missingConstraints: detectMissingConstraints(finding, prompt),
82
88
  };
83
89
  }
84
90
  function inferResult(finding) {
@@ -112,67 +118,79 @@ function inferResult(finding) {
112
118
  }
113
119
  return `The prompt produced this code without the security constraint. The omission led to ${finding.title.toLowerCase()}.`;
114
120
  }
115
- function generateFix(finding, prompt) {
116
- const originalPrompt = prompt.text.toLowerCase();
121
+ const CONCERN_MAP = {
122
+ crypto: [
123
+ { keywords: ["auth tag", "authentication tag", "gcm tag", "tag verification", "verify tag"], label: "No mention of auth tag verification for GCM mode" },
124
+ { keywords: ["key derivation", "kdf", "pbkdf", "scrypt", "argon"], label: "No mention of key derivation function" },
125
+ { keywords: ["tamper", "integrity", "reject ciphertext", "verify integrity"], label: "No mention of tampered ciphertext rejection" },
126
+ { keywords: ["iv", "nonce", "initialization vector", "random iv"], label: "No mention of IV/nonce management" },
127
+ ],
128
+ rls: [
129
+ { keywords: ["rls", "row level security", "enable rls"], label: "No mention of Row Level Security" },
130
+ { keywords: ["policy", "policies", "access policy"], label: "No mention of access policy definition" },
131
+ { keywords: ["anon", "anonymous", "deny anon", "block anon"], label: "No mention of denying anonymous access" },
132
+ ],
133
+ injection: [
134
+ { keywords: ["parameterized", "prepared statement", "bind param", "placeholder"], label: "No mention of parameterized queries" },
135
+ { keywords: ["validate input", "input validation", "sanitize input"], label: "No mention of input validation" },
136
+ ],
137
+ webhook: [
138
+ { keywords: ["signature", "verify signature", "stripe-signature", "webhook secret"], label: "No mention of signature verification" },
139
+ { keywords: ["replay", "idempotency", "idempotent"], label: "No mention of replay protection" },
140
+ ],
141
+ xss: [
142
+ { keywords: ["sanitize", "sanitization", "escape", "encoding", "encode"], label: "No mention of output sanitization/encoding" },
143
+ { keywords: ["csp", "content-security-policy", "content security"], label: "No mention of Content Security Policy" },
144
+ { keywords: ["innerhtml", "dangerouslysetinnerhtml", "raw html"], label: "No mention of avoiding raw HTML insertion" },
145
+ ],
146
+ auth: [
147
+ { keywords: ["session", "token", "jwt", "verify token", "check session"], label: "No mention of session/token verification" },
148
+ { keywords: ["access control", "authorization", "permission", "role"], label: "No mention of access control" },
149
+ { keywords: ["401", "unauthorized", "reject unauthenticated"], label: "No mention of rejecting unauthenticated requests" },
150
+ ],
151
+ upload: [
152
+ { keywords: ["mime", "file type", "content-type", "allowed types"], label: "No mention of MIME type validation" },
153
+ { keywords: ["size limit", "max size", "file size", "cap size"], label: "No mention of file size limit" },
154
+ { keywords: ["filename", "sanitize name", "path traversal"], label: "No mention of filename sanitization" },
155
+ ],
156
+ };
157
+ function categorizeFinding(finding) {
117
158
  const title = finding.title.toLowerCase();
118
- if (title.includes("rls") || title.includes("row level security")) {
119
- return [
120
- `"${truncate(prompt.text, 80)}.`,
121
- `Enable row level security and add a policy so a user can only select rows`,
122
- `for their own records. Deny anon access by default."`,
123
- ];
124
- }
125
- if (title.includes("upload") || title.includes("validation")) {
126
- return [
127
- `"${truncate(prompt.text, 80)}.`,
128
- `Validate MIME type (images only), cap size at 5MB, sanitize the filename`,
129
- `against path traversal, require an authenticated session, and enforce an`,
130
- `RLS policy so a user can only write to their own folder."`,
131
- ];
132
- }
133
- if (title.includes("injection") || title.includes("interpolat")) {
134
- return [
135
- `"${truncate(prompt.text, 80)}.`,
136
- `Validate the params as ISO dates and use parameterized Supabase filters —`,
137
- `never string-concatenate user input into the query."`,
138
- ];
139
- }
140
- if (title.includes("webhook") || title.includes("signature")) {
141
- return [
142
- `"${truncate(prompt.text, 80)}.`,
143
- `Verify the Stripe-Signature header against the webhook secret and reject`,
144
- `any event that fails verification."`,
145
- ];
146
- }
147
- if (title.includes("xss") || title.includes("cross-site")) {
148
- return [
149
- `"${truncate(prompt.text, 80)}.`,
150
- `Sanitize all user-provided content before rendering. Use proper encoding`,
151
- `and never set innerHTML with unescaped user data."`,
152
- ];
153
- }
159
+ const meta = finding.meta.toLowerCase();
160
+ if (title.includes("rls") || title.includes("row level security"))
161
+ return "rls";
162
+ if (title.includes("upload") || title.includes("validation"))
163
+ return "upload";
164
+ if (title.includes("injection") || title.includes("interpolat"))
165
+ return "injection";
166
+ if (title.includes("webhook") || title.includes("signature"))
167
+ return "webhook";
168
+ if (title.includes("xss") || title.includes("cross-site"))
169
+ return "xss";
154
170
  if (title.includes("cipher") || title.includes("crypto") ||
155
171
  title.includes("gcm") || title.includes("decipher") ||
156
- title.includes("hash") || title.includes("hmac")) {
157
- return [
158
- `"${truncate(prompt.text, 80)}.`,
159
- `Use authenticated encryption (e.g. GCM with auth tag verification),`,
160
- `a strong key derivation function, and reject tampered ciphertext."`,
161
- ];
162
- }
163
- if (title.includes("auth") && !title.includes("webhook")) {
164
- return [
165
- `"${truncate(prompt.text, 80)}.`,
166
- `Add authentication middleware that verifies the session token before`,
167
- `processing the request. Reject unauthenticated requests with 401."`,
168
- ];
169
- }
170
- // Generic fallback fix
171
- return [
172
- `"${truncate(prompt.text, 80)}.`,
173
- `Add security constraints: validate inputs, enforce authentication,`,
174
- `and follow least-privilege defaults."`,
175
- ];
172
+ title.includes("hash") || title.includes("hmac"))
173
+ return "crypto";
174
+ if (meta.includes("auth") || title.includes("auth"))
175
+ return "auth";
176
+ return null;
177
+ }
178
+ function detectMissingConstraints(finding, prompt) {
179
+ const category = categorizeFinding(finding);
180
+ if (!category)
181
+ return [];
182
+ const concerns = CONCERN_MAP[category];
183
+ if (!concerns)
184
+ return [];
185
+ const promptText = prompt.text.toLowerCase();
186
+ const missing = [];
187
+ for (const concern of concerns) {
188
+ const mentioned = concern.keywords.some((kw) => promptText.includes(kw));
189
+ if (!mentioned) {
190
+ missing.push(concern.label);
191
+ }
192
+ }
193
+ return missing;
176
194
  }
177
195
  function formatTimestamp(ts) {
178
196
  if (!ts)
@@ -1 +1 @@
1
- {"version":3,"file":"correlator.js","sourceRoot":"","sources":["../../src/claude/correlator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"correlator.js","sourceRoot":"","sources":["../../src/claude/correlator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function isHookInstalled(repoPath: string): boolean;
2
+ export declare function installHook(repoPath: string): Promise<void>;
3
+ export declare function removeHook(repoPath: string): Promise<void>;
@@ -0,0 +1,94 @@
1
+ import { writeFile, unlink, readFile, chmod, mkdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import pc from "picocolors";
5
+ const MARKER = "# vibecheck hook";
6
+ const VIBECHECK_BLOCK = `${MARKER}
7
+ npx vibe-checking --with-cursor-history --with-claude-history
8
+ if [ $? -ne 0 ]; then exit 1; fi`;
9
+ const PRE_PUSH_SCRIPT = `#!/bin/sh
10
+ ${VIBECHECK_BLOCK}
11
+ `;
12
+ /** Insert vibecheck before the first bare `exit` or `exit 0`, or append if none found. */
13
+ function insertBeforeFirstExit(content, block) {
14
+ const lines = content.split("\n");
15
+ const exitPattern = /^\s*exit(\s+0)?\s*(#.*)?$/;
16
+ for (let i = 0; i < lines.length; i++) {
17
+ if (exitPattern.test(lines[i])) {
18
+ const before = lines.slice(0, i);
19
+ const after = lines.slice(i);
20
+ return [...before, "", block, "", ...after].join("\n");
21
+ }
22
+ }
23
+ return content.trimEnd() + "\n\n" + block + "\n";
24
+ }
25
+ function hookPath(repoPath) {
26
+ return join(repoPath, ".git", "hooks", "pre-push");
27
+ }
28
+ export function isHookInstalled(repoPath) {
29
+ const path = hookPath(repoPath);
30
+ if (!existsSync(path))
31
+ return false;
32
+ try {
33
+ const content = readFileSync(path, "utf-8");
34
+ return content.includes(MARKER);
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ export async function installHook(repoPath) {
41
+ const hooksDir = join(repoPath, ".git", "hooks");
42
+ if (!existsSync(join(repoPath, ".git"))) {
43
+ console.log(pc.red("not a git repository — cannot install hook."));
44
+ return;
45
+ }
46
+ const path = hookPath(repoPath);
47
+ if (existsSync(path)) {
48
+ const existing = await readFile(path, "utf-8");
49
+ if (existing.includes(MARKER)) {
50
+ console.log(pc.dim("vibecheck hook is already installed."));
51
+ return;
52
+ }
53
+ await writeFile(path, insertBeforeFirstExit(existing, VIBECHECK_BLOCK), "utf-8");
54
+ console.log(pc.green("✓ vibecheck added to existing pre-push hook."));
55
+ }
56
+ else {
57
+ if (!existsSync(hooksDir)) {
58
+ await mkdir(hooksDir, { recursive: true });
59
+ }
60
+ await writeFile(path, PRE_PUSH_SCRIPT, "utf-8");
61
+ await chmod(path, 0o755);
62
+ console.log(pc.green("✓ pre-push hook installed."));
63
+ }
64
+ console.log(pc.dim("vibecheck will run automatically on every git push."));
65
+ }
66
+ export async function removeHook(repoPath) {
67
+ const path = hookPath(repoPath);
68
+ if (!existsSync(path)) {
69
+ console.log(pc.dim("no pre-push hook found."));
70
+ return;
71
+ }
72
+ const content = await readFile(path, "utf-8");
73
+ if (!content.includes(MARKER)) {
74
+ console.log(pc.dim("pre-push hook exists but was not installed by vibecheck."));
75
+ return;
76
+ }
77
+ // If the hook only contains our script, remove the file
78
+ const lines = content.split("\n");
79
+ const otherLines = lines.filter((l) => !l.includes(MARKER) && !l.includes("vibe-checking") && l.trim() !== "#!/bin/sh" && l.trim() !== "");
80
+ if (otherLines.length === 0) {
81
+ await unlink(path);
82
+ console.log(pc.green("✓ pre-push hook removed."));
83
+ }
84
+ else {
85
+ // Remove just our section
86
+ const cleaned = content
87
+ .replace(/\n*# vibecheck hook\nnpx vibe-checking[^\n]*\nif \[ \$\? -ne 0 \]; then exit 1; fi/g, "")
88
+ .replace(/\n*# vibecheck hook\nnpx vibe-checking[^\n]*/g, "")
89
+ .trimEnd() + "\n";
90
+ await writeFile(path, cleaned, "utf-8");
91
+ console.log(pc.green("✓ vibecheck removed from pre-push hook."));
92
+ }
93
+ }
94
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/hooks/installer.ts"],"names":[],"mappings":"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"}