code-auditor-mcp 3.0.5 → 3.0.7

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 (76) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +31 -1
  3. package/dist/cli.js +416 -111
  4. package/dist/cli.js.map +1 -1
  5. package/dist/generators/AWSQConfigGenerator.d.ts +20 -0
  6. package/dist/generators/AWSQConfigGenerator.d.ts.map +1 -1
  7. package/dist/generators/AWSQConfigGenerator.js +48 -19
  8. package/dist/generators/AWSQConfigGenerator.js.map +1 -1
  9. package/dist/generators/AiderConfigGenerator.d.ts +18 -0
  10. package/dist/generators/AiderConfigGenerator.d.ts.map +1 -1
  11. package/dist/generators/AiderConfigGenerator.js +48 -10
  12. package/dist/generators/AiderConfigGenerator.js.map +1 -1
  13. package/dist/generators/ClaudeConfigGenerator.d.ts +9 -3
  14. package/dist/generators/ClaudeConfigGenerator.d.ts.map +1 -1
  15. package/dist/generators/ClaudeConfigGenerator.js +30 -42
  16. package/dist/generators/ClaudeConfigGenerator.js.map +1 -1
  17. package/dist/generators/ClineConfigGenerator.d.ts +13 -0
  18. package/dist/generators/ClineConfigGenerator.d.ts.map +1 -1
  19. package/dist/generators/ClineConfigGenerator.js +44 -11
  20. package/dist/generators/ClineConfigGenerator.js.map +1 -1
  21. package/dist/generators/CodeiumConfigGenerator.d.ts +15 -0
  22. package/dist/generators/CodeiumConfigGenerator.d.ts.map +1 -1
  23. package/dist/generators/CodeiumConfigGenerator.js +45 -15
  24. package/dist/generators/CodeiumConfigGenerator.js.map +1 -1
  25. package/dist/generators/CodexConfigGenerator.d.ts +29 -0
  26. package/dist/generators/CodexConfigGenerator.d.ts.map +1 -0
  27. package/dist/generators/CodexConfigGenerator.js +80 -0
  28. package/dist/generators/CodexConfigGenerator.js.map +1 -0
  29. package/dist/generators/ConfigGeneratorFactory.d.ts +10 -1
  30. package/dist/generators/ConfigGeneratorFactory.d.ts.map +1 -1
  31. package/dist/generators/ConfigGeneratorFactory.js +22 -8
  32. package/dist/generators/ConfigGeneratorFactory.js.map +1 -1
  33. package/dist/generators/ContinueConfigGenerator.d.ts +16 -1
  34. package/dist/generators/ContinueConfigGenerator.d.ts.map +1 -1
  35. package/dist/generators/ContinueConfigGenerator.js +41 -73
  36. package/dist/generators/ContinueConfigGenerator.js.map +1 -1
  37. package/dist/generators/CopilotConfigGenerator.d.ts +13 -2
  38. package/dist/generators/CopilotConfigGenerator.d.ts.map +1 -1
  39. package/dist/generators/CopilotConfigGenerator.js +31 -51
  40. package/dist/generators/CopilotConfigGenerator.js.map +1 -1
  41. package/dist/generators/CursorConfigGenerator.d.ts +8 -1
  42. package/dist/generators/CursorConfigGenerator.d.ts.map +1 -1
  43. package/dist/generators/CursorConfigGenerator.js +27 -51
  44. package/dist/generators/CursorConfigGenerator.js.map +1 -1
  45. package/dist/generators/GeminiConfigGenerator.d.ts +23 -0
  46. package/dist/generators/GeminiConfigGenerator.d.ts.map +1 -0
  47. package/dist/generators/GeminiConfigGenerator.js +59 -0
  48. package/dist/generators/GeminiConfigGenerator.js.map +1 -0
  49. package/dist/generators/JetBrainsConfigGenerator.d.ts +11 -0
  50. package/dist/generators/JetBrainsConfigGenerator.d.ts.map +1 -1
  51. package/dist/generators/JetBrainsConfigGenerator.js +39 -21
  52. package/dist/generators/JetBrainsConfigGenerator.js.map +1 -1
  53. package/dist/generators/VSCodeConfigGenerator.d.ts +14 -0
  54. package/dist/generators/VSCodeConfigGenerator.d.ts.map +1 -1
  55. package/dist/generators/VSCodeConfigGenerator.js +43 -15
  56. package/dist/generators/VSCodeConfigGenerator.js.map +1 -1
  57. package/dist/hooks/codex.d.ts +20 -0
  58. package/dist/hooks/codex.d.ts.map +1 -0
  59. package/dist/hooks/codex.js +91 -0
  60. package/dist/hooks/codex.js.map +1 -0
  61. package/dist/hooks/core.d.ts +62 -0
  62. package/dist/hooks/core.d.ts.map +1 -0
  63. package/dist/hooks/core.js +119 -0
  64. package/dist/hooks/core.js.map +1 -0
  65. package/dist/hooks/cursor.d.ts +72 -0
  66. package/dist/hooks/cursor.d.ts.map +1 -0
  67. package/dist/hooks/cursor.js +163 -0
  68. package/dist/hooks/cursor.js.map +1 -0
  69. package/dist/installer.d.ts +30 -0
  70. package/dist/installer.d.ts.map +1 -0
  71. package/dist/installer.js +355 -0
  72. package/dist/installer.js.map +1 -0
  73. package/dist/mcp-tools/whitelistTools.d.ts +1 -1
  74. package/package.json +3 -2
  75. package/plugin/.claude-plugin/plugin.json +1 -1
  76. package/plugin/skills/code-auditor/SKILL.md +13 -5
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Codex hook adapter — `code-audit codex-hook`.
4
+ *
5
+ * Reads Codex's PostToolUse stdin JSON and runs a diff-scoped audit.
6
+ *
7
+ * Phase 0 verification (2026-07-19):
8
+ * - Source: learn.chatgpt.com/docs/hooks
9
+ * - PostToolUse is BLOCKING: exit 2 replaces the tool result with feedback
10
+ * - Matcher in hooks.json: "apply_patch" (Codex's file-editing tool)
11
+ * - stdin shape: { session_id, tool_name, tool_use_id, tool_input, tool_response }
12
+ * - tool_input.file_path contains the edited file
13
+ *
14
+ * Exit codes:
15
+ * 0 — no critical violations found
16
+ * 2 — critical violations found (blocking feedback loop)
17
+ * 1 — internal error (adapter crash, not violation-related)
18
+ */
19
+ import { readStdin, runHookAudit } from './core.js';
20
+ import chalk from 'chalk';
21
+ async function main() {
22
+ const raw = await readStdin();
23
+ if (!raw) {
24
+ // No stdin data — nothing to audit
25
+ process.exit(0);
26
+ }
27
+ let event;
28
+ try {
29
+ event = JSON.parse(raw);
30
+ }
31
+ catch {
32
+ console.error(chalk.red('[code-auditor codex-hook] Failed to parse stdin JSON'));
33
+ process.exit(0); // Degrade gracefully
34
+ }
35
+ const filePath = event.tool_input?.file_path || event.tool_input?.path;
36
+ if (!filePath) {
37
+ // No file path — nothing to audit
38
+ process.exit(0);
39
+ }
40
+ const projectRoot = process.cwd();
41
+ try {
42
+ const output = await runHookAudit({
43
+ filePaths: [filePath],
44
+ projectRoot,
45
+ failOn: 'critical',
46
+ });
47
+ if (output.violations.length > 0) {
48
+ // Codex PostToolUse: exit 2 replaces tool result with feedback
49
+ // Write violations as JSON to stdout — Codex feeds this back to the agent
50
+ const criticals = output.violations.filter((v) => v.severity === 'critical');
51
+ if (criticals.length > 0) {
52
+ const feedback = {
53
+ decision: 'block',
54
+ reason: `code-auditor found ${criticals.length} critical violation(s)`,
55
+ violations: output.violations.map((v) => ({
56
+ severity: v.severity,
57
+ message: v.message,
58
+ file: v.file,
59
+ line: v.line,
60
+ rule: v.rule,
61
+ suggestion: v.suggestion || null,
62
+ })),
63
+ };
64
+ process.stdout.write(JSON.stringify(feedback, null, 2) + '\n');
65
+ process.exit(2);
66
+ }
67
+ // Non-critical violations: report but don't block
68
+ const warnings = output.violations.filter((v) => v.severity === 'warning');
69
+ if (warnings.length > 0) {
70
+ const advisory = {
71
+ decision: 'allow',
72
+ warnings: warnings.map((v) => ({
73
+ message: v.message,
74
+ file: v.file,
75
+ line: v.line,
76
+ suggestion: v.suggestion || null,
77
+ })),
78
+ };
79
+ process.stdout.write(JSON.stringify(advisory, null, 2) + '\n');
80
+ }
81
+ }
82
+ process.exit(0);
83
+ }
84
+ catch (error) {
85
+ // Internal error — report and exit 0 (never wedge the agent loop on errors)
86
+ console.error(chalk.red(`[code-auditor codex-hook] Error: ${error instanceof Error ? error.message : String(error)}`));
87
+ process.exit(0);
88
+ }
89
+ }
90
+ main();
91
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/hooks/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Shared hook adapter core — reads stdin, runs a diff-scoped audit, writes stdout.
3
+ *
4
+ * Each tool's hook adapter (cursor.ts, codex.ts) is a thin payload mapper that:
5
+ * 1. Reads the tool-specific stdin JSON
6
+ * 2. Extracts edited file paths
7
+ * 3. Calls runHookAudit() with those paths
8
+ * 4. Maps audit results back to the tool's stdout contract
9
+ *
10
+ * Phase 0 live-docs verification (2026-07-20):
11
+ * - Cursor postToolUse (Write matcher): BLOCKING (exit 2, additional_context)
12
+ * Verified: cursor.com/docs/hooks + cursor.com/docs/reference/third-party-hooks
13
+ * - Cursor afterFileEdit: EXISTS but observation-only — NOT used for blocking
14
+ * - Codex PostToolUse: blocking (exit 2 replaces tool result with feedback)
15
+ * Verified: learn.chatgpt.com/docs/extend/hooks
16
+ * - Claude Code PostToolUse: blocking (exit 2 blocks the edit)
17
+ * Cursor reads .claude/settings.json natively via third-party hooks compat
18
+ */
19
+ import type { Severity } from '../types.js';
20
+ export interface HookAuditInput {
21
+ filePaths: string[];
22
+ projectRoot: string;
23
+ failOn: Severity;
24
+ }
25
+ export interface HookViolation {
26
+ analyzer: string;
27
+ rule: string;
28
+ severity: Severity;
29
+ message: string;
30
+ file: string;
31
+ line?: number;
32
+ column?: number;
33
+ endLine?: number;
34
+ endColumn?: number;
35
+ enclosingSymbol?: string;
36
+ suggestion?: string;
37
+ details?: string;
38
+ }
39
+ export interface HookAuditOutput {
40
+ violations: HookViolation[];
41
+ summary: {
42
+ total: number;
43
+ critical: number;
44
+ warning: number;
45
+ suggestion: number;
46
+ };
47
+ filesAnalyzed: number;
48
+ }
49
+ /**
50
+ * Read all of stdin as a string. Returns empty string on EOF/error.
51
+ */
52
+ export declare function readStdin(): Promise<string>;
53
+ /**
54
+ * Run a diff-scoped audit on the given file paths.
55
+ * This is the shared core — all hook adapters call this.
56
+ */
57
+ export declare function runHookAudit(input: HookAuditInput): Promise<HookAuditOutput>;
58
+ /**
59
+ * Check if violations at or above failOn severity exist.
60
+ */
61
+ export declare function hasViolationsAtOrAbove(violations: HookViolation[], failOn: Severity): boolean;
62
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/hooks/core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CA+BjD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CA4DlF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,aAAa,EAAE,EAC3B,MAAM,EAAE,QAAQ,GACf,OAAO,CAOT"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Shared hook adapter core — reads stdin, runs a diff-scoped audit, writes stdout.
3
+ *
4
+ * Each tool's hook adapter (cursor.ts, codex.ts) is a thin payload mapper that:
5
+ * 1. Reads the tool-specific stdin JSON
6
+ * 2. Extracts edited file paths
7
+ * 3. Calls runHookAudit() with those paths
8
+ * 4. Maps audit results back to the tool's stdout contract
9
+ *
10
+ * Phase 0 live-docs verification (2026-07-20):
11
+ * - Cursor postToolUse (Write matcher): BLOCKING (exit 2, additional_context)
12
+ * Verified: cursor.com/docs/hooks + cursor.com/docs/reference/third-party-hooks
13
+ * - Cursor afterFileEdit: EXISTS but observation-only — NOT used for blocking
14
+ * - Codex PostToolUse: blocking (exit 2 replaces tool result with feedback)
15
+ * Verified: learn.chatgpt.com/docs/extend/hooks
16
+ * - Claude Code PostToolUse: blocking (exit 2 blocks the edit)
17
+ * Cursor reads .claude/settings.json natively via third-party hooks compat
18
+ */
19
+ import { createInterface } from 'node:readline';
20
+ import { resolve } from 'node:path';
21
+ import { createAuditRunner } from '../auditRunner.js';
22
+ import { initParsers } from '../languages/index.js';
23
+ /**
24
+ * Read all of stdin as a string. Returns empty string on EOF/error.
25
+ */
26
+ export async function readStdin() {
27
+ return new Promise((resolve) => {
28
+ // If stdin is a TTY, there's nothing to read
29
+ if (process.stdin.isTTY) {
30
+ resolve('');
31
+ return;
32
+ }
33
+ const rl = createInterface({
34
+ input: process.stdin,
35
+ output: undefined,
36
+ terminal: false,
37
+ });
38
+ const lines = [];
39
+ rl.on('line', (line) => {
40
+ lines.push(line);
41
+ });
42
+ rl.on('close', () => {
43
+ resolve(lines.join('\n'));
44
+ });
45
+ rl.on('error', () => {
46
+ resolve(lines.join('\n'));
47
+ });
48
+ // Timeout: if nothing arrives in 5s, assume no input
49
+ setTimeout(() => {
50
+ rl.close();
51
+ resolve(lines.join('\n'));
52
+ }, 5000).unref();
53
+ });
54
+ }
55
+ /**
56
+ * Run a diff-scoped audit on the given file paths.
57
+ * This is the shared core — all hook adapters call this.
58
+ */
59
+ export async function runHookAudit(input) {
60
+ // Initialize parsers (idempotent once loaded)
61
+ await initParsers();
62
+ if (input.filePaths.length === 0) {
63
+ return {
64
+ violations: [],
65
+ summary: { total: 0, critical: 0, warning: 0, suggestion: 0 },
66
+ filesAnalyzed: 0,
67
+ };
68
+ }
69
+ // Convert to absolute paths
70
+ const resolvedPaths = [...new Set(input.filePaths.map((f) => resolve(input.projectRoot, f)))];
71
+ // Create runner with the resolved scope
72
+ const runner = createAuditRunner({
73
+ projectRoot: input.projectRoot,
74
+ scope: resolvedPaths,
75
+ analyzerConcurrency: 4,
76
+ });
77
+ const result = await runner.run();
78
+ // Collect all violations
79
+ const allViolations = Object.values(result.analyzerResults).flatMap((r) => r.violations || []);
80
+ const violations = allViolations.map((v) => ({
81
+ analyzer: v.analyzer || '',
82
+ rule: v.rule || v.type || '',
83
+ severity: v.severity,
84
+ message: v.message,
85
+ file: v.file || '',
86
+ line: v.line ?? v.start?.line,
87
+ column: v.column ?? v.start?.column ?? 1,
88
+ endLine: v.end?.line,
89
+ endColumn: v.end?.column,
90
+ enclosingSymbol: v.symbol || v.enclosingFunction || '',
91
+ suggestion: v.suggestion || '',
92
+ details: v.details || '',
93
+ }));
94
+ const criticalCount = violations.filter((v) => v.severity === 'critical').length;
95
+ const warningCount = violations.filter((v) => v.severity === 'warning').length;
96
+ const suggestionCount = violations.filter((v) => v.severity === 'suggestion').length;
97
+ return {
98
+ violations,
99
+ summary: {
100
+ total: violations.length,
101
+ critical: criticalCount,
102
+ warning: warningCount,
103
+ suggestion: suggestionCount,
104
+ },
105
+ filesAnalyzed: result.metadata.filesAnalyzed,
106
+ };
107
+ }
108
+ /**
109
+ * Check if violations at or above failOn severity exist.
110
+ */
111
+ export function hasViolationsAtOrAbove(violations, failOn) {
112
+ const severityOrder = ['critical', 'warning', 'suggestion'];
113
+ const failIndex = severityOrder.indexOf(failOn);
114
+ return violations.some((v) => {
115
+ const vIndex = severityOrder.indexOf(v.severity);
116
+ return vIndex >= 0 && vIndex <= failIndex;
117
+ });
118
+ }
119
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/hooks/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Cursor hook adapter — `code-audit cursor-hook`.
4
+ *
5
+ * Reads Cursor's postToolUse stdin JSON (native or Claude Code compat) and
6
+ * runs a scoped audit on edited files. Blocks edits with critical violations.
7
+ *
8
+ * Phase 0 verification (2026-07-20):
9
+ * - Source: cursor.com/docs/hooks + cursor.com/docs/reference/third-party-hooks
10
+ * - postToolUse with Write matcher IS BLOCKING: exit 2 blocks the action
11
+ * - additional_context is injected into the conversation after the tool result
12
+ * - afterFileEdit EXISTS but is observation-only ("No output fields defined")
13
+ * - Cursor natively reads .claude/settings.json hooks (PostToolUse→postToolUse)
14
+ * - Tool name mapping: Edit→Write, Bash→Shell
15
+ * - Dual response format support: both Claude nested format and Cursor flat format
16
+ *
17
+ * Input formats (both accepted):
18
+ * Cursor native: { tool_name, tool_input, tool_output, tool_use_id, cwd, ... }
19
+ * Claude Code compat: { tool_name, tool_input, tool_output, session_id, cwd, ... }
20
+ * (CLAUDE_PROJECT_DIR env var set in Claude Code compat mode)
21
+ *
22
+ * Exit codes:
23
+ * 0 — no critical violations found
24
+ * 2 — critical violations found (blocks the action, additional_context injected)
25
+ * 1 — internal error (adapter crash, not violation-related)
26
+ */
27
+ import type { HookAuditOutput } from './core.js';
28
+ export interface CursorPostToolUse {
29
+ tool_name?: string;
30
+ tool_input?: Record<string, unknown>;
31
+ tool_output?: unknown;
32
+ tool_use_id?: string;
33
+ toolName?: string;
34
+ toolInput?: Record<string, unknown>;
35
+ toolOutput?: unknown;
36
+ session_id?: string;
37
+ transcript_path?: string;
38
+ cwd?: string;
39
+ }
40
+ export interface CursorHookResult {
41
+ exitCode: number;
42
+ stdout: string;
43
+ stderr: string;
44
+ }
45
+ /**
46
+ * Detect whether this is a Write/Edit tool invocation we should audit.
47
+ */
48
+ export declare function isWriteOrEdit(event: CursorPostToolUse): boolean;
49
+ /**
50
+ * Extract the edited file path from tool_input.
51
+ * Cursor Write: tool_input.file_path
52
+ * Claude Code Edit: tool_input.file_path
53
+ */
54
+ export declare function extractFilePath(event: CursorPostToolUse): string | null;
55
+ /**
56
+ * Build the additional_context string for violations.
57
+ */
58
+ export declare function formatViolationContext(output: HookAuditOutput): {
59
+ context: string;
60
+ isBlocking: boolean;
61
+ };
62
+ /**
63
+ * Process a Cursor postToolUse event and return the hook result.
64
+ * Extracted from main() for testability — tests inject a mock audit function.
65
+ */
66
+ export declare function processCursorEvent(rawStdin: string, auditFn?: (filePaths: string[], projectRoot: string) => Promise<HookAuditOutput>): Promise<CursorHookResult>;
67
+ /**
68
+ * CLI entry point — reads stdin, processes, writes result, exits.
69
+ * Exported so the CLI can call it explicitly after importing.
70
+ */
71
+ export declare function main(): Promise<void>;
72
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/hooks/cursor.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,MAAM,WAAW,iBAAiB;IAEhC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAQvE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,GAAG;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;CACrB,CAgDA;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAChB,GAC7D,OAAO,CAAC,gBAAgB,CAAC,CAyD3B;AAED;;;GAGG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAW1C"}
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Cursor hook adapter — `code-audit cursor-hook`.
4
+ *
5
+ * Reads Cursor's postToolUse stdin JSON (native or Claude Code compat) and
6
+ * runs a scoped audit on edited files. Blocks edits with critical violations.
7
+ *
8
+ * Phase 0 verification (2026-07-20):
9
+ * - Source: cursor.com/docs/hooks + cursor.com/docs/reference/third-party-hooks
10
+ * - postToolUse with Write matcher IS BLOCKING: exit 2 blocks the action
11
+ * - additional_context is injected into the conversation after the tool result
12
+ * - afterFileEdit EXISTS but is observation-only ("No output fields defined")
13
+ * - Cursor natively reads .claude/settings.json hooks (PostToolUse→postToolUse)
14
+ * - Tool name mapping: Edit→Write, Bash→Shell
15
+ * - Dual response format support: both Claude nested format and Cursor flat format
16
+ *
17
+ * Input formats (both accepted):
18
+ * Cursor native: { tool_name, tool_input, tool_output, tool_use_id, cwd, ... }
19
+ * Claude Code compat: { tool_name, tool_input, tool_output, session_id, cwd, ... }
20
+ * (CLAUDE_PROJECT_DIR env var set in Claude Code compat mode)
21
+ *
22
+ * Exit codes:
23
+ * 0 — no critical violations found
24
+ * 2 — critical violations found (blocks the action, additional_context injected)
25
+ * 1 — internal error (adapter crash, not violation-related)
26
+ */
27
+ import { readStdin, runHookAudit } from './core.js';
28
+ import chalk from 'chalk';
29
+ /**
30
+ * Detect whether this is a Write/Edit tool invocation we should audit.
31
+ */
32
+ export function isWriteOrEdit(event) {
33
+ const toolName = (event.tool_name || event.toolName || '').toLowerCase();
34
+ // Cursor native: "Write" (camelCase mapped). Claude Code compat: "Edit".
35
+ // Also accept "edit", "write" for robustness.
36
+ return toolName === 'write' || toolName === 'edit';
37
+ }
38
+ /**
39
+ * Extract the edited file path from tool_input.
40
+ * Cursor Write: tool_input.file_path
41
+ * Claude Code Edit: tool_input.file_path
42
+ */
43
+ export function extractFilePath(event) {
44
+ const input = event.tool_input || event.toolInput;
45
+ if (!input)
46
+ return null;
47
+ const filePath = input.file_path;
48
+ if (filePath && typeof filePath === 'string')
49
+ return filePath;
50
+ return null;
51
+ }
52
+ /**
53
+ * Build the additional_context string for violations.
54
+ */
55
+ export function formatViolationContext(output) {
56
+ const criticals = output.violations.filter((v) => v.severity === 'critical');
57
+ const warnings = output.violations.filter((v) => v.severity === 'warning');
58
+ const suggestions = output.violations.filter((v) => v.severity === 'suggestion');
59
+ if (criticals.length > 0) {
60
+ const lines = [
61
+ `🚨 **Code Auditor found ${criticals.length} critical violation(s)**`,
62
+ '',
63
+ ...criticals.map((v) => `- **${v.file}${v.line ? `:${v.line}` : ''}** — ${v.message}` +
64
+ (v.suggestion ? `\n Suggestion: ${v.suggestion}` : '')),
65
+ ];
66
+ if (warnings.length > 0 || suggestions.length > 0) {
67
+ lines.push('', `Also found: ${warnings.length} warning(s), ${suggestions.length} suggestion(s).`);
68
+ }
69
+ lines.push('', 'Fix the critical violations above and retry. The edit has been blocked.');
70
+ return { context: lines.join('\n'), isBlocking: true };
71
+ }
72
+ if (warnings.length > 0 || suggestions.length > 0) {
73
+ const notes = [];
74
+ if (warnings.length > 0) {
75
+ notes.push(`${warnings.length} warning(s):`);
76
+ warnings.forEach((v) => {
77
+ notes.push(` - ${v.file}${v.line ? `:${v.line}` : ''} — ${v.message}`);
78
+ });
79
+ }
80
+ if (suggestions.length > 0) {
81
+ notes.push(`${suggestions.length} suggestion(s):`);
82
+ suggestions.forEach((v) => {
83
+ notes.push(` - ${v.file}${v.line ? `:${v.line}` : ''} — ${v.message}`);
84
+ });
85
+ }
86
+ return {
87
+ context: `ℹ️ **Code Auditor notes:**\n${notes.join('\n')}`,
88
+ isBlocking: false,
89
+ };
90
+ }
91
+ return { context: '', isBlocking: false };
92
+ }
93
+ /**
94
+ * Process a Cursor postToolUse event and return the hook result.
95
+ * Extracted from main() for testability — tests inject a mock audit function.
96
+ */
97
+ export async function processCursorEvent(rawStdin, auditFn = async (filePaths, projectRoot) => runHookAudit({ filePaths, projectRoot, failOn: 'critical' })) {
98
+ const result = { exitCode: 0, stdout: '', stderr: '' };
99
+ if (!rawStdin) {
100
+ return result;
101
+ }
102
+ let event;
103
+ try {
104
+ event = JSON.parse(rawStdin);
105
+ }
106
+ catch (err) {
107
+ result.stderr = chalk.red(`[code-auditor cursor-hook] Failed to parse stdin JSON: ${err instanceof Error ? err.message : String(err)}`);
108
+ // Degrade gracefully — never wedge the agent on parse errors
109
+ return result;
110
+ }
111
+ // Guard: only audit Write/Edit tool calls
112
+ if (!isWriteOrEdit(event)) {
113
+ return result;
114
+ }
115
+ const filePath = extractFilePath(event);
116
+ if (!filePath) {
117
+ return result;
118
+ }
119
+ // Determine project root:
120
+ // 1. cwd from the event (native Cursor)
121
+ // 2. CLAUDE_PROJECT_DIR env var (Claude Code compat mode)
122
+ // 3. process.cwd() fallback
123
+ const projectRoot = (event.cwd && event.cwd.trim()) ||
124
+ process.env.CLAUDE_PROJECT_DIR ||
125
+ process.cwd();
126
+ try {
127
+ const output = await auditFn([filePath], projectRoot);
128
+ const { context, isBlocking } = formatViolationContext(output);
129
+ if (context) {
130
+ const response = { additional_context: context };
131
+ result.stdout = JSON.stringify(response) + '\n';
132
+ if (isBlocking) {
133
+ result.exitCode = 2;
134
+ }
135
+ }
136
+ }
137
+ catch (error) {
138
+ result.stderr = chalk.red(`[code-auditor cursor-hook] Error: ${error instanceof Error ? error.message : String(error)}`);
139
+ // Internal error — never wedge the agent loop
140
+ }
141
+ return result;
142
+ }
143
+ /**
144
+ * CLI entry point — reads stdin, processes, writes result, exits.
145
+ * Exported so the CLI can call it explicitly after importing.
146
+ */
147
+ export async function main() {
148
+ const raw = await readStdin();
149
+ const result = await processCursorEvent(raw);
150
+ if (result.stderr) {
151
+ console.error(result.stderr);
152
+ }
153
+ if (result.stdout) {
154
+ process.stdout.write(result.stdout);
155
+ }
156
+ process.exit(result.exitCode);
157
+ }
158
+ // Auto-run when executed as an entry point (not imported by tests)
159
+ // vitest sets process.env.VITEST; when set, tests call processCursorEvent directly
160
+ if (!process.env.VITEST) {
161
+ main();
162
+ }
163
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/hooks/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Installer — code-audit install subcommand logic.
3
+ *
4
+ * Copies the skill folder to agent-specific paths and optionally wires hooks.
5
+ * Phase 0 live-docs verification (2026-07-19):
6
+ * - Cursor: project-only skills, ~/.cursor/skills/ does NOT exist
7
+ * - Codex: both ~/.codex/skills/ (user) and .codex/skills/ (project)
8
+ * - Cursor afterFileEdit is advisory only (cannot block retroactively)
9
+ * - Codex PostToolUse is blocking (exit 2 replaces tool result)
10
+ */
11
+ export interface InstallOptions {
12
+ agent: string;
13
+ scope: 'user' | 'project';
14
+ hooks: boolean;
15
+ list: boolean;
16
+ }
17
+ export interface InstallResult {
18
+ agent: string;
19
+ displayName: string;
20
+ skillPath: string;
21
+ installed: boolean;
22
+ hooksWired: boolean;
23
+ skipped: boolean;
24
+ skipReason?: string;
25
+ }
26
+ /**
27
+ * Main entry point for `code-audit install`.
28
+ */
29
+ export declare function runInstall(options: InstallOptions): Promise<void>;
30
+ //# sourceMappingURL=installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CvE"}