@paths.design/caws-cli 8.0.0 → 8.1.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.
Files changed (149) hide show
  1. package/dist/budget-derivation.d.ts +74 -0
  2. package/dist/budget-derivation.d.ts.map +1 -0
  3. package/dist/cicd-optimizer.d.ts +142 -0
  4. package/dist/cicd-optimizer.d.ts.map +1 -0
  5. package/dist/commands/archive.d.ts +51 -0
  6. package/dist/commands/archive.d.ts.map +1 -0
  7. package/dist/commands/archive.js +114 -6
  8. package/dist/commands/burnup.d.ts +6 -0
  9. package/dist/commands/burnup.d.ts.map +1 -0
  10. package/dist/commands/burnup.js +109 -10
  11. package/dist/commands/diagnose.d.ts +52 -0
  12. package/dist/commands/diagnose.d.ts.map +1 -0
  13. package/dist/commands/diagnose.js +1 -1
  14. package/dist/commands/evaluate.d.ts +8 -0
  15. package/dist/commands/evaluate.d.ts.map +1 -0
  16. package/dist/commands/init.d.ts +5 -0
  17. package/dist/commands/init.d.ts.map +1 -0
  18. package/dist/commands/iterate.d.ts +8 -0
  19. package/dist/commands/iterate.d.ts.map +1 -0
  20. package/dist/commands/mode.d.ts +24 -0
  21. package/dist/commands/mode.d.ts.map +1 -0
  22. package/dist/commands/mode.js +24 -14
  23. package/dist/commands/plan.d.ts +49 -0
  24. package/dist/commands/plan.d.ts.map +1 -0
  25. package/dist/commands/provenance.d.ts +32 -0
  26. package/dist/commands/provenance.d.ts.map +1 -0
  27. package/dist/commands/provenance.js +216 -93
  28. package/dist/commands/quality-gates.d.ts +6 -0
  29. package/dist/commands/quality-gates.d.ts.map +1 -0
  30. package/dist/commands/quality-gates.js +82 -3
  31. package/dist/commands/quality-monitor.d.ts +17 -0
  32. package/dist/commands/quality-monitor.d.ts.map +1 -0
  33. package/dist/commands/specs.d.ts +71 -0
  34. package/dist/commands/specs.d.ts.map +1 -0
  35. package/dist/commands/specs.js +184 -6
  36. package/dist/commands/status.d.ts +44 -0
  37. package/dist/commands/status.d.ts.map +1 -0
  38. package/dist/commands/status.js +134 -10
  39. package/dist/commands/templates.d.ts +74 -0
  40. package/dist/commands/templates.d.ts.map +1 -0
  41. package/dist/commands/templates.js +2 -2
  42. package/dist/commands/tool.d.ts +13 -0
  43. package/dist/commands/tool.d.ts.map +1 -0
  44. package/dist/commands/troubleshoot.d.ts +8 -0
  45. package/dist/commands/troubleshoot.d.ts.map +1 -0
  46. package/dist/commands/tutorial.d.ts +55 -0
  47. package/dist/commands/tutorial.d.ts.map +1 -0
  48. package/dist/commands/validate.d.ts +15 -0
  49. package/dist/commands/validate.d.ts.map +1 -0
  50. package/dist/commands/waivers.d.ts +8 -0
  51. package/dist/commands/waivers.d.ts.map +1 -0
  52. package/dist/commands/workflow.d.ts +85 -0
  53. package/dist/commands/workflow.d.ts.map +1 -0
  54. package/dist/config/index.d.ts +29 -0
  55. package/dist/config/index.d.ts.map +1 -0
  56. package/dist/config/modes.d.ts +225 -0
  57. package/dist/config/modes.d.ts.map +1 -0
  58. package/dist/constants/spec-types.d.ts +41 -0
  59. package/dist/constants/spec-types.d.ts.map +1 -0
  60. package/dist/error-handler.d.ts +164 -0
  61. package/dist/error-handler.d.ts.map +1 -0
  62. package/dist/error-handler.js +6 -98
  63. package/dist/generators/jest-config-generator.js +242 -0
  64. package/dist/generators/jest-config.d.ts +32 -0
  65. package/dist/generators/jest-config.d.ts.map +1 -0
  66. package/dist/generators/working-spec.d.ts +13 -0
  67. package/dist/generators/working-spec.d.ts.map +1 -0
  68. package/dist/index-new.d.ts +5 -0
  69. package/dist/index-new.d.ts.map +1 -0
  70. package/dist/index-new.js +317 -0
  71. package/dist/index.d.ts +5 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +14 -7
  74. package/dist/index.js.backup +4711 -0
  75. package/dist/minimal-cli.d.ts +3 -0
  76. package/dist/minimal-cli.d.ts.map +1 -0
  77. package/dist/minimal-cli.js +3 -1
  78. package/dist/policy/PolicyManager.d.ts +104 -0
  79. package/dist/policy/PolicyManager.d.ts.map +1 -0
  80. package/dist/scaffold/claude-hooks.js +316 -0
  81. package/dist/scaffold/cursor-hooks.d.ts +7 -0
  82. package/dist/scaffold/cursor-hooks.d.ts.map +1 -0
  83. package/dist/scaffold/git-hooks.d.ts +38 -0
  84. package/dist/scaffold/git-hooks.d.ts.map +1 -0
  85. package/dist/scaffold/index.d.ts +15 -0
  86. package/dist/scaffold/index.d.ts.map +1 -0
  87. package/dist/scaffold/index.js +18 -0
  88. package/dist/spec/SpecFileManager.d.ts +146 -0
  89. package/dist/spec/SpecFileManager.d.ts.map +1 -0
  90. package/dist/templates/.claude/README.md +190 -0
  91. package/dist/templates/.claude/hooks/audit.sh +96 -0
  92. package/dist/templates/.claude/hooks/block-dangerous.sh +90 -0
  93. package/dist/templates/.claude/hooks/naming-check.sh +97 -0
  94. package/dist/templates/.claude/hooks/quality-check.sh +68 -0
  95. package/dist/templates/.claude/hooks/scan-secrets.sh +85 -0
  96. package/dist/templates/.claude/hooks/scope-guard.sh +105 -0
  97. package/dist/templates/.claude/hooks/validate-spec.sh +76 -0
  98. package/dist/templates/.claude/settings.json +95 -0
  99. package/dist/test-analysis.d.ts +182 -0
  100. package/dist/test-analysis.d.ts.map +1 -0
  101. package/dist/test-analysis.js +203 -10
  102. package/dist/tool-interface.d.ts +236 -0
  103. package/dist/tool-interface.d.ts.map +1 -0
  104. package/dist/tool-loader.d.ts +77 -0
  105. package/dist/tool-loader.d.ts.map +1 -0
  106. package/dist/tool-validator.d.ts +72 -0
  107. package/dist/tool-validator.d.ts.map +1 -0
  108. package/dist/utils/async-utils.d.ts +73 -0
  109. package/dist/utils/async-utils.d.ts.map +1 -0
  110. package/dist/utils/command-wrapper.d.ts +66 -0
  111. package/dist/utils/command-wrapper.d.ts.map +1 -0
  112. package/dist/utils/detection.d.ts +14 -0
  113. package/dist/utils/detection.d.ts.map +1 -0
  114. package/dist/utils/error-categories.js +210 -0
  115. package/dist/utils/finalization.d.ts +17 -0
  116. package/dist/utils/finalization.d.ts.map +1 -0
  117. package/dist/utils/git-lock.d.ts +13 -0
  118. package/dist/utils/git-lock.d.ts.map +1 -0
  119. package/dist/utils/gitignore-updater.d.ts +39 -0
  120. package/dist/utils/gitignore-updater.d.ts.map +1 -0
  121. package/dist/utils/project-analysis.d.ts +34 -0
  122. package/dist/utils/project-analysis.d.ts.map +1 -0
  123. package/dist/utils/promise-utils.d.ts +30 -0
  124. package/dist/utils/promise-utils.d.ts.map +1 -0
  125. package/dist/utils/quality-gates-utils.js +402 -0
  126. package/dist/utils/quality-gates.d.ts +49 -0
  127. package/dist/utils/quality-gates.d.ts.map +1 -0
  128. package/dist/utils/spec-resolver.d.ts +80 -0
  129. package/dist/utils/spec-resolver.d.ts.map +1 -0
  130. package/dist/utils/typescript-detector.d.ts +63 -0
  131. package/dist/utils/typescript-detector.d.ts.map +1 -0
  132. package/dist/utils/typescript-detector.js +36 -90
  133. package/dist/utils/yaml-validation.d.ts +32 -0
  134. package/dist/utils/yaml-validation.d.ts.map +1 -0
  135. package/dist/validation/spec-validation.d.ts +43 -0
  136. package/dist/validation/spec-validation.d.ts.map +1 -0
  137. package/dist/validation/spec-validation.js +59 -6
  138. package/dist/waivers-manager.d.ts +167 -0
  139. package/dist/waivers-manager.d.ts.map +1 -0
  140. package/package.json +5 -3
  141. package/templates/.claude/README.md +190 -0
  142. package/templates/.claude/hooks/audit.sh +96 -0
  143. package/templates/.claude/hooks/block-dangerous.sh +90 -0
  144. package/templates/.claude/hooks/naming-check.sh +97 -0
  145. package/templates/.claude/hooks/quality-check.sh +68 -0
  146. package/templates/.claude/hooks/scan-secrets.sh +85 -0
  147. package/templates/.claude/hooks/scope-guard.sh +105 -0
  148. package/templates/.claude/hooks/validate-spec.sh +76 -0
  149. package/templates/.claude/settings.json +95 -0
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Spec File Manager - Handles WorkingSpec file operations and YAML conversion
3
+ *
4
+ * Features:
5
+ * - Bidirectional WorkingSpec ↔ YAML conversion
6
+ * - Temporary file support for validation workflows
7
+ * - Backup/restore capabilities
8
+ * - Automatic cleanup of old temporary files
9
+ */
10
+ export class SpecFileManager {
11
+ constructor(config?: {});
12
+ projectRoot: any;
13
+ useTemporaryFiles: any;
14
+ tempDir: any;
15
+ /**
16
+ * Convert WorkingSpec object to YAML string
17
+ *
18
+ * @param {Object} spec - WorkingSpec to convert
19
+ * @returns {string} YAML string representation
20
+ */
21
+ specToYaml(spec: any): string;
22
+ /**
23
+ * Parse YAML string to WorkingSpec object
24
+ *
25
+ * @param {string} yamlContent - YAML string to parse
26
+ * @returns {Object} Parsed WorkingSpec object
27
+ * @throws {Error} If YAML is invalid or doesn't match WorkingSpec schema
28
+ */
29
+ yamlToSpec(yamlContent: string): any;
30
+ /**
31
+ * Get path to .caws/working-spec.yaml in project
32
+ *
33
+ * @returns {string} Absolute path to working spec file
34
+ */
35
+ getSpecFilePath(): string;
36
+ /**
37
+ * Check if working spec file exists
38
+ *
39
+ * @returns {Promise<boolean>} True if file exists
40
+ */
41
+ specFileExists(): Promise<boolean>;
42
+ /**
43
+ * Read working spec from .caws/working-spec.yaml
44
+ *
45
+ * @returns {Promise<Object>} Parsed WorkingSpec object
46
+ * @throws {Error} If file doesn't exist or is invalid
47
+ */
48
+ readSpecFile(): Promise<any>;
49
+ /**
50
+ * Write WorkingSpec to file
51
+ *
52
+ * Writes to .caws/working-spec.yaml or a temporary file based on configuration.
53
+ *
54
+ * @param {Object} spec - WorkingSpec to write
55
+ * @param {Object} options - Write options
56
+ * @param {boolean} options.useTemp - Override temp file usage
57
+ * @param {boolean} options.backup - Create backup before writing
58
+ * @returns {Promise<Object>} Write result with file path and cleanup function
59
+ */
60
+ writeSpecFile(spec: any, options?: {
61
+ useTemp: boolean;
62
+ backup: boolean;
63
+ }): Promise<any>;
64
+ /**
65
+ * Update existing working spec file
66
+ *
67
+ * Reads current spec, merges changes, and writes back.
68
+ *
69
+ * @param {Object} updates - Partial WorkingSpec with fields to update
70
+ * @returns {Promise<Object>} Updated WorkingSpec
71
+ */
72
+ updateSpecFile(updates: any): Promise<any>;
73
+ /**
74
+ * Create backup of working spec
75
+ *
76
+ * @returns {Promise<string>} Path to backup file
77
+ */
78
+ backupSpecFile(): Promise<string>;
79
+ /**
80
+ * Restore working spec from backup
81
+ *
82
+ * @param {string} backupPath - Path to backup file
83
+ * @returns {Promise<void>}
84
+ */
85
+ restoreSpecFile(backupPath: string): Promise<void>;
86
+ /**
87
+ * List all backup files
88
+ *
89
+ * @returns {Promise<string[]>} Array of backup file paths
90
+ */
91
+ listBackups(): Promise<string[]>;
92
+ /**
93
+ * Delete old backup files
94
+ *
95
+ * @param {Object} options - Cleanup options
96
+ * @param {number} options.maxAge - Maximum age in milliseconds (default: 7 days)
97
+ * @param {number} options.keep - Minimum number of backups to keep (default: 5)
98
+ * @returns {Promise<number>} Number of backups deleted
99
+ */
100
+ cleanupBackups(options?: {
101
+ maxAge: number;
102
+ keep: number;
103
+ }): Promise<number>;
104
+ /**
105
+ * Validate spec file exists and is parseable
106
+ *
107
+ * @returns {Promise<Object>} Validation result
108
+ */
109
+ validateSpecFile(): Promise<any>;
110
+ /**
111
+ * Clean up old temporary spec files
112
+ *
113
+ * Removes temp files older than specified age.
114
+ *
115
+ * @param {number} maxAge - Maximum age in milliseconds (default: 1 hour)
116
+ * @returns {Promise<number>} Number of files cleaned up
117
+ */
118
+ cleanupTempFiles(maxAge?: number): Promise<number>;
119
+ /**
120
+ * Get spec file stats (size, modified date, etc.)
121
+ *
122
+ * @returns {Promise<Object>} File stats
123
+ */
124
+ getSpecFileStats(): Promise<any>;
125
+ /**
126
+ * Create a new SpecFileManager instance with different configuration
127
+ *
128
+ * @param {Object} config - New configuration
129
+ * @returns {SpecFileManager} New instance
130
+ */
131
+ withConfig(config: any): SpecFileManager;
132
+ }
133
+ export const defaultSpecFileManager: SpecFileManager;
134
+ /**
135
+ * Create a SpecFileManager instance with default configuration
136
+ *
137
+ * @param {string} projectRoot - Project root directory
138
+ * @param {Object} options - Additional options
139
+ * @returns {SpecFileManager} SpecFileManager instance
140
+ */
141
+ export function createSpecFileManager(projectRoot: string, options?: any): SpecFileManager;
142
+ export declare function specToYaml(spec: any): string;
143
+ export declare function yamlToSpec(yaml: any): any;
144
+ export declare function readSpecFile(projectRoot: any): Promise<any>;
145
+ export declare function writeSpecFile(spec: any, projectRoot: any, options: any): Promise<any>;
146
+ //# sourceMappingURL=SpecFileManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpecFileManager.d.ts","sourceRoot":"","sources":["../../src/spec/SpecFileManager.js"],"names":[],"mappings":"AAaA;;;;;;;;GAQG;AACH;IACE,yBAIC;IAHC,iBAAsD;IACtD,uBAA0D;IAC1D,aAA4C;IAG9C;;;;;OAKG;IACH,uBAFa,MAAM,CASlB;IAED;;;;;;OAMG;IACH,wBAJW,MAAM,OAqBhB;IAED;;;;OAIG;IACH,mBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,kBAFa,OAAO,CAAC,OAAO,CAAC,CAS5B;IAED;;;;;OAKG;IACH,gBAHa,OAAO,KAAQ,CAe3B;IAED;;;;;;;;;;OAUG;IACH,mCAJG;QAAyB,OAAO,EAAxB,OAAO;QACU,MAAM,EAAvB,OAAO;KACf,GAAU,OAAO,KAAQ,CA2C3B;IAED;;;;;;;OAOG;IACH,8BAFa,OAAO,KAAQ,CAa3B;IAED;;;;OAIG;IACH,kBAFa,OAAO,CAAC,MAAM,CAAC,CAS3B;IAED;;;;;OAKG;IACH,4BAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;;OAIG;IACH,eAFa,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB7B;IAED;;;;;;;OAOG;IACH,yBAJG;QAAwB,MAAM,EAAtB,MAAM;QACU,IAAI,EAApB,MAAM;KACd,GAAU,OAAO,CAAC,MAAM,CAAC,CA+B3B;IAED;;;;OAIG;IACH,oBAFa,OAAO,KAAQ,CAe3B;IAED;;;;;;;OAOG;IACH,0BAHW,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CA6B3B;IAED;;;;OAIG;IACH,oBAFa,OAAO,KAAQ,CA0B3B;IAED;;;;;OAKG;IACH,yBAFa,eAAe,CAS3B;CACF;AAiBD,qDAAqD;AAfrD;;;;;;GAMG;AACH,mDAJW,MAAM,kBAEJ,eAAe,CAO3B;AAWa,sDAAiD;AACjD,mDAAiD;AAC/C,qEAKb;AACc,+FAKd"}
@@ -0,0 +1,190 @@
1
+ # Claude Code Integration for CAWS
2
+
3
+ This directory contains Claude Code hooks and configuration for CAWS (Coding Agent Working Standard) integration.
4
+
5
+ ## Overview
6
+
7
+ CAWS hooks for Claude Code provide:
8
+
9
+ - **Safety Gates**: Block dangerous commands and scan for secrets
10
+ - **Quality Gates**: Run CAWS quality checks after file edits
11
+ - **Scope Guards**: Validate edits against the working spec's scope
12
+ - **Audit Logging**: Track agent actions for compliance
13
+
14
+ ## Directory Structure
15
+
16
+ ```
17
+ .claude/
18
+ ├── settings.json # Claude Code settings with hooks configuration
19
+ ├── hooks/ # Hook scripts
20
+ │ ├── audit.sh # Session and action logging
21
+ │ ├── block-dangerous.sh # Block destructive commands
22
+ │ ├── scan-secrets.sh # Warn when reading sensitive files
23
+ │ ├── quality-check.sh # Run CAWS quality gates
24
+ │ ├── validate-spec.sh # Validate spec files
25
+ │ ├── scope-guard.sh # Check scope boundaries
26
+ │ └── naming-check.sh # Validate file naming conventions
27
+ ├── logs/ # Audit logs (gitignored)
28
+ └── README.md # This file
29
+ ```
30
+
31
+ ## Hook Events
32
+
33
+ ### PreToolUse Hooks
34
+
35
+ Run before Claude executes a tool:
36
+
37
+ | Hook | Matcher | Purpose |
38
+ |------|---------|---------|
39
+ | `block-dangerous.sh` | `Bash` | Block destructive shell commands |
40
+ | `scan-secrets.sh` | `Read` | Warn when reading sensitive files |
41
+ | `scope-guard.sh` | `Write\|Edit` | Check scope boundaries before edits |
42
+
43
+ ### PostToolUse Hooks
44
+
45
+ Run after Claude executes a tool:
46
+
47
+ | Hook | Matcher | Purpose |
48
+ |------|---------|---------|
49
+ | `quality-check.sh` | `Write\|Edit` | Run CAWS quality gates |
50
+ | `validate-spec.sh` | `Write\|Edit` | Validate spec file changes |
51
+ | `naming-check.sh` | `Write` | Check file naming conventions |
52
+ | `audit.sh` | `Write\|Edit\|Bash` | Log tool usage |
53
+
54
+ ### Session Hooks
55
+
56
+ | Hook | Event | Purpose |
57
+ |------|-------|---------|
58
+ | `audit.sh session-start` | `SessionStart` | Log session start |
59
+ | `audit.sh stop` | `Stop` | Log session end |
60
+
61
+ ## Configuration
62
+
63
+ ### Enable/Disable Hooks
64
+
65
+ Edit `settings.json` to enable or disable specific hooks. Remove entries from the `hooks` object to disable them.
66
+
67
+ ### Hook Levels
68
+
69
+ The scaffold supports four hook levels:
70
+
71
+ - **safety**: Block dangerous commands, scan for secrets
72
+ - **quality**: Run quality gates on file edits
73
+ - **scope**: Validate edits against spec scope
74
+ - **audit**: Log all agent actions
75
+
76
+ Run `caws init --hooks=safety,quality` to enable specific levels.
77
+
78
+ ## Audit Logs
79
+
80
+ Audit logs are written to `.claude/logs/`:
81
+
82
+ - `audit.log` - All-time log (appended)
83
+ - `audit-YYYY-MM-DD.log` - Daily logs
84
+
85
+ Logs are JSON-formatted for easy parsing:
86
+
87
+ ```json
88
+ {
89
+ "timestamp": "2024-01-15T10:30:00Z",
90
+ "session_id": "abc123",
91
+ "event": "tool_use",
92
+ "tool": "Write",
93
+ "file": "src/index.ts",
94
+ "cwd": "/project"
95
+ }
96
+ ```
97
+
98
+ ## Customization
99
+
100
+ ### Adding Custom Hooks
101
+
102
+ 1. Create a new script in `.claude/hooks/`
103
+ 2. Make it executable: `chmod +x .claude/hooks/my-hook.sh`
104
+ 3. Add it to `settings.json`:
105
+
106
+ ```json
107
+ {
108
+ "hooks": {
109
+ "PostToolUse": [
110
+ {
111
+ "matcher": "Write|Edit",
112
+ "hooks": [
113
+ {
114
+ "type": "command",
115
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/my-hook.sh",
116
+ "timeout": 10
117
+ }
118
+ ]
119
+ }
120
+ ]
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### Hook Input/Output
126
+
127
+ Hooks receive JSON input via stdin:
128
+
129
+ ```json
130
+ {
131
+ "session_id": "abc123",
132
+ "hook_event_name": "PostToolUse",
133
+ "tool_name": "Write",
134
+ "tool_input": {
135
+ "file_path": "/path/to/file.ts",
136
+ "content": "..."
137
+ },
138
+ "tool_response": { "success": true }
139
+ }
140
+ ```
141
+
142
+ Hooks can output JSON to control Claude's behavior:
143
+
144
+ ```json
145
+ {
146
+ "decision": "block",
147
+ "reason": "Quality gate failed: ..."
148
+ }
149
+ ```
150
+
151
+ Or add context:
152
+
153
+ ```json
154
+ {
155
+ "hookSpecificOutput": {
156
+ "hookEventName": "PostToolUse",
157
+ "additionalContext": "Remember to update the tests."
158
+ }
159
+ }
160
+ ```
161
+
162
+ ## Troubleshooting
163
+
164
+ ### Hooks Not Running
165
+
166
+ 1. Check `settings.json` syntax: `cat .claude/settings.json | jq .`
167
+ 2. Verify scripts are executable: `ls -la .claude/hooks/`
168
+ 3. Test hooks manually: `echo '{}' | .claude/hooks/audit.sh`
169
+
170
+ ### Permission Errors
171
+
172
+ Make all hook scripts executable:
173
+
174
+ ```bash
175
+ chmod +x .claude/hooks/*.sh
176
+ ```
177
+
178
+ ### Debug Hooks
179
+
180
+ Run Claude Code with `--debug` to see hook execution details:
181
+
182
+ ```bash
183
+ claude --debug
184
+ ```
185
+
186
+ ## Further Reading
187
+
188
+ - [Claude Code Hooks Documentation](https://code.claude.com/docs/en/hooks)
189
+ - [CAWS Quality Gates](../../docs/quality-gates.md)
190
+ - [CAWS Scope Management](../../docs/scope-management.md)
@@ -0,0 +1,96 @@
1
+ #!/bin/bash
2
+ # CAWS Audit Hook for Claude Code
3
+ # Logs agent actions for compliance and debugging
4
+ # @author @darianrosebrook
5
+
6
+ set -euo pipefail
7
+
8
+ # Get event type from argument or input
9
+ EVENT_TYPE="${1:-tool-use}"
10
+
11
+ # Read JSON input from stdin
12
+ INPUT=$(cat)
13
+
14
+ # Parse common fields from Claude Code hook input
15
+ SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
16
+ CWD=$(echo "$INPUT" | jq -r '.cwd // "."')
17
+ HOOK_EVENT=$(echo "$INPUT" | jq -r '.hook_event_name // "unknown"')
18
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
19
+ PERMISSION_MODE=$(echo "$INPUT" | jq -r '.permission_mode // "default"')
20
+
21
+ # Ensure log directory exists
22
+ LOG_DIR="${CLAUDE_PROJECT_DIR:-.}/.claude/logs"
23
+ mkdir -p "$LOG_DIR"
24
+
25
+ # Log file path
26
+ LOG_FILE="$LOG_DIR/audit.log"
27
+ DATE_LOG_FILE="$LOG_DIR/audit-$(date +%Y-%m-%d).log"
28
+
29
+ # Timestamp
30
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
31
+
32
+ # Build log entry based on event type
33
+ case "$EVENT_TYPE" in
34
+ session-start)
35
+ SOURCE=$(echo "$INPUT" | jq -r '.source // "unknown"')
36
+ MODEL=$(echo "$INPUT" | jq -r '.model // "unknown"')
37
+ LOG_ENTRY=$(jq -n \
38
+ --arg ts "$TIMESTAMP" \
39
+ --arg sid "$SESSION_ID" \
40
+ --arg event "session_start" \
41
+ --arg source "$SOURCE" \
42
+ --arg model "$MODEL" \
43
+ --arg cwd "$CWD" \
44
+ '{timestamp: $ts, session_id: $sid, event: $event, source: $source, model: $model, cwd: $cwd}')
45
+ ;;
46
+
47
+ stop)
48
+ STOP_HOOK_ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false')
49
+ LOG_ENTRY=$(jq -n \
50
+ --arg ts "$TIMESTAMP" \
51
+ --arg sid "$SESSION_ID" \
52
+ --arg event "session_stop" \
53
+ --arg cwd "$CWD" \
54
+ --argjson hook_active "$STOP_HOOK_ACTIVE" \
55
+ '{timestamp: $ts, session_id: $sid, event: $event, cwd: $cwd, stop_hook_active: $hook_active}')
56
+ ;;
57
+
58
+ tool-use)
59
+ # Extract tool-specific info
60
+ TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}')
61
+ TOOL_RESPONSE=$(echo "$INPUT" | jq -c '.tool_response // {}')
62
+ TOOL_USE_ID=$(echo "$INPUT" | jq -r '.tool_use_id // ""')
63
+
64
+ # For file operations, extract the path
65
+ FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // ""')
66
+ COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // ""')
67
+
68
+ LOG_ENTRY=$(jq -n \
69
+ --arg ts "$TIMESTAMP" \
70
+ --arg sid "$SESSION_ID" \
71
+ --arg event "tool_use" \
72
+ --arg tool "$TOOL_NAME" \
73
+ --arg file "$FILE_PATH" \
74
+ --arg cmd "$COMMAND" \
75
+ --arg cwd "$CWD" \
76
+ --arg mode "$PERMISSION_MODE" \
77
+ '{timestamp: $ts, session_id: $sid, event: $event, tool: $tool, file: $file, command: $cmd, cwd: $cwd, permission_mode: $mode}')
78
+ ;;
79
+
80
+ *)
81
+ LOG_ENTRY=$(jq -n \
82
+ --arg ts "$TIMESTAMP" \
83
+ --arg sid "$SESSION_ID" \
84
+ --arg event "$EVENT_TYPE" \
85
+ --arg hook "$HOOK_EVENT" \
86
+ --arg cwd "$CWD" \
87
+ '{timestamp: $ts, session_id: $sid, event: $event, hook_event: $hook, cwd: $cwd}')
88
+ ;;
89
+ esac
90
+
91
+ # Append to log files
92
+ echo "$LOG_ENTRY" >> "$LOG_FILE"
93
+ echo "$LOG_ENTRY" >> "$DATE_LOG_FILE"
94
+
95
+ # Success - allow operation to continue
96
+ exit 0
@@ -0,0 +1,90 @@
1
+ #!/bin/bash
2
+ # CAWS Dangerous Command Blocker for Claude Code
3
+ # Blocks potentially destructive shell commands
4
+ # @author @darianrosebrook
5
+
6
+ set -euo pipefail
7
+
8
+ # Read JSON input from Claude Code
9
+ INPUT=$(cat)
10
+
11
+ # Extract tool info
12
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
13
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
14
+
15
+ # Only check Bash tool
16
+ if [[ "$TOOL_NAME" != "Bash" ]] || [[ -z "$COMMAND" ]]; then
17
+ exit 0
18
+ fi
19
+
20
+ # Dangerous command patterns
21
+ DANGEROUS_PATTERNS=(
22
+ # Destructive file operations
23
+ 'rm -rf /'
24
+ 'rm -rf ~'
25
+ 'rm -rf \*'
26
+ 'rm -rf \.'
27
+ 'rm -rf /\*'
28
+ 'dd if=/dev/zero'
29
+ 'dd if=/dev/random'
30
+ 'mkfs\.'
31
+ 'fdisk'
32
+ '> /dev/sd'
33
+
34
+ # Fork bombs and resource exhaustion
35
+ ':\(\)\{:\|:\&\};:'
36
+ 'while true.*fork'
37
+
38
+ # Credential/secret exposure
39
+ 'cat.*\.env'
40
+ 'cat.*/etc/passwd'
41
+ 'cat.*/etc/shadow'
42
+ 'cat.*id_rsa'
43
+ 'cat.*\.ssh/'
44
+ 'cat.*credentials'
45
+ 'cat.*\.aws/'
46
+
47
+ # Network exfiltration
48
+ 'curl.*\|.*sh'
49
+ 'wget.*\|.*sh'
50
+ 'curl.*\|.*bash'
51
+ 'wget.*\|.*bash'
52
+
53
+ # Permission escalation
54
+ 'chmod 777'
55
+ 'chmod -R 777'
56
+ 'chmod.*\+s'
57
+
58
+ # History manipulation
59
+ 'history -c'
60
+ 'rm.*\.bash_history'
61
+ 'rm.*\.zsh_history'
62
+
63
+ # System modification
64
+ 'shutdown'
65
+ 'reboot'
66
+ 'init 0'
67
+ 'init 6'
68
+ )
69
+
70
+ # Check command against dangerous patterns
71
+ for pattern in "${DANGEROUS_PATTERNS[@]}"; do
72
+ if echo "$COMMAND" | grep -qiE "$pattern"; then
73
+ # Output to stderr for Claude to see
74
+ echo "BLOCKED: Command matches dangerous pattern: $pattern" >&2
75
+ echo "Command was: $COMMAND" >&2
76
+
77
+ # Exit code 2 blocks the tool and shows stderr to Claude
78
+ exit 2
79
+ fi
80
+ done
81
+
82
+ # Check for sudo without specific allowed commands
83
+ if echo "$COMMAND" | grep -qE '^sudo\s' && ! echo "$COMMAND" | grep -qE 'sudo (npm|yarn|pnpm|brew|apt-get|apt|dnf|yum)'; then
84
+ echo "BLOCKED: sudo commands require explicit approval" >&2
85
+ echo "If this command is safe, please run it manually in your terminal" >&2
86
+ exit 2
87
+ fi
88
+
89
+ # Allow the command
90
+ exit 0
@@ -0,0 +1,97 @@
1
+ #!/bin/bash
2
+ # CAWS Naming Convention Check Hook for Claude Code
3
+ # Validates file naming against CAWS conventions
4
+ # @author @darianrosebrook
5
+
6
+ set -euo pipefail
7
+
8
+ # Read JSON input from Claude Code
9
+ INPUT=$(cat)
10
+
11
+ # Extract file path from PostToolUse input
12
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
13
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
14
+
15
+ # Only check Write tool (new files)
16
+ if [[ "$TOOL_NAME" != "Write" ]]; then
17
+ exit 0
18
+ fi
19
+
20
+ if [[ -z "$FILE_PATH" ]]; then
21
+ exit 0
22
+ fi
23
+
24
+ # Get filename
25
+ FILENAME=$(basename "$FILE_PATH")
26
+
27
+ # Banned modifiers that indicate incomplete/temporary naming
28
+ BANNED_MODIFIERS=(
29
+ "enhanced"
30
+ "unified"
31
+ "simplified"
32
+ "better"
33
+ "new"
34
+ "next"
35
+ "final"
36
+ "copy"
37
+ "revamp"
38
+ "improved"
39
+ "alt"
40
+ "tmp"
41
+ "scratch"
42
+ "wip"
43
+ "test-"
44
+ "-test"
45
+ "_test"
46
+ "temp"
47
+ "old"
48
+ "backup"
49
+ )
50
+
51
+ # Convert filename to lowercase for checking
52
+ FILENAME_LOWER=$(echo "$FILENAME" | tr '[:upper:]' '[:lower:]')
53
+
54
+ # Check for banned modifiers
55
+ for modifier in "${BANNED_MODIFIERS[@]}"; do
56
+ if [[ "$FILENAME_LOWER" == *"$modifier"* ]]; then
57
+ # Special case: allow test files that follow conventions
58
+ if [[ "$modifier" == "test-" ]] || [[ "$modifier" == "-test" ]] || [[ "$modifier" == "_test" ]]; then
59
+ if [[ "$FILENAME_LOWER" =~ \.(test|spec)\.(js|ts|jsx|tsx|py|go|rs)$ ]]; then
60
+ continue
61
+ fi
62
+ fi
63
+
64
+ echo '{
65
+ "hookSpecificOutput": {
66
+ "hookEventName": "PostToolUse",
67
+ "additionalContext": "Warning: The filename '\'''"$FILENAME"''\'' contains the modifier '\'''"$modifier"''\'' which may indicate temporary or non-canonical naming. Consider using a more descriptive, permanent name. See CAWS naming conventions in .caws/canonical-map.yaml or run '\''caws naming check'\''."
68
+ }
69
+ }'
70
+ exit 0
71
+ fi
72
+ done
73
+
74
+ # Check for version suffixes (e.g., file-v2.js, file_v3.ts)
75
+ if [[ "$FILENAME_LOWER" =~ [-_]v[0-9]+\. ]]; then
76
+ echo '{
77
+ "hookSpecificOutput": {
78
+ "hookEventName": "PostToolUse",
79
+ "additionalContext": "Warning: The filename '\'''"$FILENAME"''\'' contains a version suffix. Version control should be handled by git, not file names. Consider removing the version suffix."
80
+ }
81
+ }'
82
+ exit 0
83
+ fi
84
+
85
+ # Check for date stamps (e.g., file-2024-01-15.js)
86
+ if [[ "$FILENAME_LOWER" =~ [0-9]{4}[-_][0-9]{2}[-_][0-9]{2} ]]; then
87
+ echo '{
88
+ "hookSpecificOutput": {
89
+ "hookEventName": "PostToolUse",
90
+ "additionalContext": "Warning: The filename '\'''"$FILENAME"''\'' contains a date stamp. Version control should be handled by git, not file names. Consider removing the date."
91
+ }
92
+ }'
93
+ exit 0
94
+ fi
95
+
96
+ # File naming is OK
97
+ exit 0
@@ -0,0 +1,68 @@
1
+ #!/bin/bash
2
+ # CAWS Quality Check Hook for Claude Code
3
+ # Runs CAWS quality validation after file edits
4
+ # @author @darianrosebrook
5
+
6
+ set -euo pipefail
7
+
8
+ # Read JSON input from Claude Code
9
+ INPUT=$(cat)
10
+
11
+ # Extract file info from PostToolUse input
12
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
13
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
14
+
15
+ # Only run on Write/Edit of source files
16
+ if [[ "$TOOL_NAME" != "Write" ]] && [[ "$TOOL_NAME" != "Edit" ]]; then
17
+ exit 0
18
+ fi
19
+
20
+ # Skip non-source files and node_modules/dist
21
+ if [[ ! "$FILE_PATH" =~ \.(js|ts|jsx|tsx|py|go|rs|java|mjs|cjs)$ ]] || \
22
+ [[ "$FILE_PATH" =~ node_modules ]] || \
23
+ [[ "$FILE_PATH" =~ dist/ ]] || \
24
+ [[ "$FILE_PATH" =~ build/ ]]; then
25
+ exit 0
26
+ fi
27
+
28
+ # Determine project directory
29
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
30
+
31
+ # Check if we're in a CAWS project
32
+ if [[ ! -f "$PROJECT_DIR/.caws/working-spec.yaml" ]]; then
33
+ exit 0
34
+ fi
35
+
36
+ # Check if CAWS CLI is available
37
+ if ! command -v caws &> /dev/null; then
38
+ # Suggest installing CAWS
39
+ echo '{
40
+ "hookSpecificOutput": {
41
+ "hookEventName": "PostToolUse",
42
+ "additionalContext": "CAWS CLI not available. Consider installing with: npm install -g @caws/cli"
43
+ }
44
+ }'
45
+ exit 0
46
+ fi
47
+
48
+ # Run CAWS quality gates in quiet mode for quick feedback
49
+ if caws quality-gates --context=commit --quiet 2>/dev/null; then
50
+ # Quality check passed - provide positive feedback
51
+ echo '{
52
+ "hookSpecificOutput": {
53
+ "hookEventName": "PostToolUse",
54
+ "additionalContext": "Quality gates passed for this change."
55
+ }
56
+ }'
57
+ else
58
+ # Quality check failed - provide feedback to Claude
59
+ # Run again to get violations summary
60
+ VIOLATIONS=$(caws quality-gates --context=commit --json 2>/dev/null | jq -r '.violations[:3] | .[] | "- \(.gate): \(.message)"' 2>/dev/null || echo "Run 'caws quality-gates' for details")
61
+
62
+ echo '{
63
+ "decision": "block",
64
+ "reason": "Quality gate violations detected. Please address the following issues before continuing:\n'"$VIOLATIONS"'\n\nRun '\''caws quality-gates'\'' for full details."
65
+ }'
66
+ fi
67
+
68
+ exit 0