claude-code-templates 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +291 -0
  2. package/bin/create-claude-config.js +59 -0
  3. package/package.json +51 -0
  4. package/src/file-operations.js +66 -0
  5. package/src/index.js +81 -0
  6. package/src/prompts.js +110 -0
  7. package/src/templates.js +134 -0
  8. package/src/utils.js +172 -0
  9. package/templates/common/CLAUDE.md +109 -0
  10. package/templates/common/README.md +96 -0
  11. package/templates/javascript-typescript/.claude/commands/api-endpoint.md +1 -0
  12. package/templates/javascript-typescript/.claude/commands/debug.md +1 -0
  13. package/templates/javascript-typescript/.claude/commands/lint.md +1 -0
  14. package/templates/javascript-typescript/.claude/commands/npm-scripts.md +1 -0
  15. package/templates/javascript-typescript/.claude/commands/react-component.md +1 -0
  16. package/templates/javascript-typescript/.claude/commands/refactor.md +1 -0
  17. package/templates/javascript-typescript/.claude/commands/test.md +1 -0
  18. package/templates/javascript-typescript/.claude/commands/typescript-migrate.md +1 -0
  19. package/templates/javascript-typescript/.claude/hooks/format-on-save.json +1 -0
  20. package/templates/javascript-typescript/.claude/hooks/lint-on-save.json +1 -0
  21. package/templates/javascript-typescript/.claude/hooks/typescript-check.json +1 -0
  22. package/templates/javascript-typescript/.claude/settings.json +103 -0
  23. package/templates/javascript-typescript/CLAUDE.md +185 -0
  24. package/templates/javascript-typescript/README.md +233 -0
  25. package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +1 -0
  26. package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +1 -0
  27. package/templates/javascript-typescript/examples/node-api/CLAUDE.md +1 -0
  28. package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +1 -0
  29. package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +1 -0
  30. package/templates/javascript-typescript/examples/react-app/CLAUDE.md +1 -0
  31. package/templates/python/CLAUDE.md +276 -0
@@ -0,0 +1,134 @@
1
+ const path = require('path');
2
+
3
+ const TEMPLATES_CONFIG = {
4
+ 'common': {
5
+ name: 'Common (Language-agnostic)',
6
+ description: 'Universal configuration for any project',
7
+ files: [
8
+ { source: 'common/CLAUDE.md', destination: 'CLAUDE.md' },
9
+ { source: 'common/.claude', destination: '.claude' }
10
+ ]
11
+ },
12
+ 'javascript-typescript': {
13
+ name: 'JavaScript/TypeScript',
14
+ description: 'Optimized for modern JS/TS development',
15
+ files: [
16
+ { source: 'javascript-typescript/CLAUDE.md', destination: 'CLAUDE.md' },
17
+ { source: 'javascript-typescript/.claude', destination: '.claude' }
18
+ ],
19
+ frameworks: {
20
+ 'react': {
21
+ name: 'React',
22
+ additionalFiles: [
23
+ { source: 'javascript-typescript/examples/react-app/.claude/commands', destination: '.claude/commands' }
24
+ ]
25
+ },
26
+ 'vue': {
27
+ name: 'Vue.js',
28
+ additionalFiles: []
29
+ },
30
+ 'angular': {
31
+ name: 'Angular',
32
+ additionalFiles: []
33
+ },
34
+ 'node': {
35
+ name: 'Node.js',
36
+ additionalFiles: [
37
+ { source: 'javascript-typescript/examples/node-api/.claude/commands', destination: '.claude/commands' }
38
+ ]
39
+ }
40
+ }
41
+ },
42
+ 'python': {
43
+ name: 'Python',
44
+ description: 'Optimized for Python development',
45
+ files: [
46
+ { source: 'python/CLAUDE.md', destination: 'CLAUDE.md' },
47
+ { source: 'python/.claude', destination: '.claude' }
48
+ ],
49
+ frameworks: {
50
+ 'django': {
51
+ name: 'Django',
52
+ additionalFiles: []
53
+ },
54
+ 'flask': {
55
+ name: 'Flask',
56
+ additionalFiles: []
57
+ },
58
+ 'fastapi': {
59
+ name: 'FastAPI',
60
+ additionalFiles: []
61
+ }
62
+ }
63
+ },
64
+ 'rust': {
65
+ name: 'Rust',
66
+ description: 'Configuration for Rust projects (Coming Soon)',
67
+ files: [
68
+ { source: 'common/CLAUDE.md', destination: 'CLAUDE.md' },
69
+ { source: 'common/.claude', destination: '.claude' }
70
+ ],
71
+ comingSoon: true
72
+ },
73
+ 'go': {
74
+ name: 'Go',
75
+ description: 'Configuration for Go projects (Coming Soon)',
76
+ files: [
77
+ { source: 'common/CLAUDE.md', destination: 'CLAUDE.md' },
78
+ { source: 'common/.claude', destination: '.claude' }
79
+ ],
80
+ comingSoon: true
81
+ }
82
+ };
83
+
84
+ function getAvailableLanguages() {
85
+ return Object.keys(TEMPLATES_CONFIG).map(key => ({
86
+ value: key,
87
+ name: TEMPLATES_CONFIG[key].name,
88
+ description: TEMPLATES_CONFIG[key].description,
89
+ disabled: TEMPLATES_CONFIG[key].comingSoon ? 'Coming Soon' : false
90
+ }));
91
+ }
92
+
93
+ function getFrameworksForLanguage(language) {
94
+ const config = TEMPLATES_CONFIG[language];
95
+ if (!config || !config.frameworks) return [];
96
+
97
+ return Object.keys(config.frameworks).map(key => ({
98
+ value: key,
99
+ name: config.frameworks[key].name
100
+ }));
101
+ }
102
+
103
+ function getTemplateConfig(selections) {
104
+ const { language, framework } = selections;
105
+ const baseConfig = TEMPLATES_CONFIG[language];
106
+
107
+ if (!baseConfig) {
108
+ throw new Error(`Unknown language template: ${language}`);
109
+ }
110
+
111
+ let files = [...baseConfig.files];
112
+
113
+ // Add framework-specific files
114
+ if (framework && framework !== 'none' && baseConfig.frameworks && baseConfig.frameworks[framework]) {
115
+ const frameworkConfig = baseConfig.frameworks[framework];
116
+ if (frameworkConfig.additionalFiles) {
117
+ files = files.concat(frameworkConfig.additionalFiles);
118
+ }
119
+ }
120
+
121
+ return {
122
+ language,
123
+ framework,
124
+ files,
125
+ config: baseConfig
126
+ };
127
+ }
128
+
129
+ module.exports = {
130
+ TEMPLATES_CONFIG,
131
+ getAvailableLanguages,
132
+ getFrameworksForLanguage,
133
+ getTemplateConfig
134
+ };
package/src/utils.js ADDED
@@ -0,0 +1,172 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ async function detectProject(targetDir) {
5
+ const detectedLanguages = [];
6
+ const detectedFrameworks = [];
7
+
8
+ // Check for package.json (JavaScript/TypeScript)
9
+ const packageJsonPath = path.join(targetDir, 'package.json');
10
+ if (await fs.pathExists(packageJsonPath)) {
11
+ try {
12
+ const packageJson = await fs.readJson(packageJsonPath);
13
+ detectedLanguages.push('javascript-typescript');
14
+
15
+ // Detect frameworks
16
+ const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
17
+
18
+ if (dependencies.react || dependencies['@types/react']) {
19
+ detectedFrameworks.push('react');
20
+ }
21
+ if (dependencies.vue || dependencies['@vue/cli']) {
22
+ detectedFrameworks.push('vue');
23
+ }
24
+ if (dependencies['@angular/core']) {
25
+ detectedFrameworks.push('angular');
26
+ }
27
+ if (dependencies.express || dependencies.fastify || dependencies.koa) {
28
+ detectedFrameworks.push('node');
29
+ }
30
+ } catch (error) {
31
+ console.warn('Could not parse package.json');
32
+ }
33
+ }
34
+
35
+ // Check for Python files
36
+ const pythonFiles = await findFilesByExtension(targetDir, ['.py']);
37
+ if (pythonFiles.length > 0) {
38
+ detectedLanguages.push('python');
39
+
40
+ // Check for Python frameworks
41
+ const requirementsPath = path.join(targetDir, 'requirements.txt');
42
+ const pipfilePath = path.join(targetDir, 'Pipfile');
43
+ const pyprojectPath = path.join(targetDir, 'pyproject.toml');
44
+
45
+ if (await fs.pathExists(requirementsPath)) {
46
+ const requirements = await fs.readFile(requirementsPath, 'utf-8');
47
+ if (requirements.includes('django')) detectedFrameworks.push('django');
48
+ if (requirements.includes('flask')) detectedFrameworks.push('flask');
49
+ if (requirements.includes('fastapi')) detectedFrameworks.push('fastapi');
50
+ }
51
+
52
+ // Check for Django settings
53
+ if (await findFilesByPattern(targetDir, 'settings.py').length > 0) {
54
+ detectedFrameworks.push('django');
55
+ }
56
+
57
+ // Check for Flask app
58
+ if (await findFilesByPattern(targetDir, 'app.py').length > 0) {
59
+ detectedFrameworks.push('flask');
60
+ }
61
+ }
62
+
63
+ // Check for Rust files
64
+ const rustFiles = await findFilesByExtension(targetDir, ['.rs']);
65
+ const cargoPath = path.join(targetDir, 'Cargo.toml');
66
+ if (rustFiles.length > 0 || await fs.pathExists(cargoPath)) {
67
+ detectedLanguages.push('rust');
68
+ }
69
+
70
+ // Check for Go files
71
+ const goFiles = await findFilesByExtension(targetDir, ['.go']);
72
+ const goModPath = path.join(targetDir, 'go.mod');
73
+ if (goFiles.length > 0 || await fs.pathExists(goModPath)) {
74
+ detectedLanguages.push('go');
75
+ }
76
+
77
+ return {
78
+ detectedLanguage: detectedLanguages[0] || null,
79
+ detectedFramework: detectedFrameworks[0] || null,
80
+ allLanguages: detectedLanguages,
81
+ allFrameworks: detectedFrameworks,
82
+ projectFiles: await getProjectSummary(targetDir)
83
+ };
84
+ }
85
+
86
+ async function findFilesByExtension(dir, extensions, maxDepth = 2) {
87
+ const files = [];
88
+
89
+ async function searchDir(currentDir, currentDepth) {
90
+ if (currentDepth > maxDepth) return;
91
+
92
+ try {
93
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
94
+
95
+ for (const entry of entries) {
96
+ const fullPath = path.join(currentDir, entry.name);
97
+
98
+ if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
99
+ await searchDir(fullPath, currentDepth + 1);
100
+ } else if (entry.isFile()) {
101
+ const ext = path.extname(entry.name);
102
+ if (extensions.includes(ext)) {
103
+ files.push(fullPath);
104
+ }
105
+ }
106
+ }
107
+ } catch (error) {
108
+ // Directory might not be accessible
109
+ }
110
+ }
111
+
112
+ await searchDir(dir, 0);
113
+ return files;
114
+ }
115
+
116
+ async function findFilesByPattern(dir, pattern, maxDepth = 2) {
117
+ const files = [];
118
+
119
+ async function searchDir(currentDir, currentDepth) {
120
+ if (currentDepth > maxDepth) return;
121
+
122
+ try {
123
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
124
+
125
+ for (const entry of entries) {
126
+ const fullPath = path.join(currentDir, entry.name);
127
+
128
+ if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
129
+ await searchDir(fullPath, currentDepth + 1);
130
+ } else if (entry.isFile() && entry.name.includes(pattern)) {
131
+ files.push(fullPath);
132
+ }
133
+ }
134
+ } catch (error) {
135
+ // Directory might not be accessible
136
+ }
137
+ }
138
+
139
+ await searchDir(dir, 0);
140
+ return files;
141
+ }
142
+
143
+ async function getProjectSummary(targetDir) {
144
+ const summary = {
145
+ hasGit: await fs.pathExists(path.join(targetDir, '.git')),
146
+ hasNodeModules: await fs.pathExists(path.join(targetDir, 'node_modules')),
147
+ hasVenv: await fs.pathExists(path.join(targetDir, 'venv')) || await fs.pathExists(path.join(targetDir, '.venv')),
148
+ configFiles: []
149
+ };
150
+
151
+ // Check for common config files
152
+ const configFiles = [
153
+ 'package.json', 'tsconfig.json', 'webpack.config.js', 'vite.config.js',
154
+ 'requirements.txt', 'setup.py', 'pyproject.toml', 'Pipfile',
155
+ 'Cargo.toml', 'go.mod', '.gitignore', 'README.md'
156
+ ];
157
+
158
+ for (const configFile of configFiles) {
159
+ if (await fs.pathExists(path.join(targetDir, configFile))) {
160
+ summary.configFiles.push(configFile);
161
+ }
162
+ }
163
+
164
+ return summary;
165
+ }
166
+
167
+ module.exports = {
168
+ detectProject,
169
+ findFilesByExtension,
170
+ findFilesByPattern,
171
+ getProjectSummary
172
+ };
@@ -0,0 +1,109 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Universal Development Guidelines
6
+
7
+ ### Code Quality Standards
8
+ - Write clean, readable, and maintainable code
9
+ - Follow consistent naming conventions across the project
10
+ - Use meaningful variable and function names
11
+ - Keep functions focused and single-purpose
12
+ - Add comments for complex logic and business rules
13
+
14
+ ### Git Workflow
15
+ - Use descriptive commit messages following conventional commits format
16
+ - Create feature branches for new development
17
+ - Keep commits atomic and focused on single changes
18
+ - Use pull requests for code review before merging
19
+ - Maintain a clean commit history
20
+
21
+ ### Documentation
22
+ - Keep README.md files up to date
23
+ - Document public APIs and interfaces
24
+ - Include usage examples for complex features
25
+ - Maintain inline code documentation
26
+ - Update documentation when making changes
27
+
28
+ ### Testing Approach
29
+ - Write tests for new features and bug fixes
30
+ - Maintain good test coverage
31
+ - Use descriptive test names that explain the expected behavior
32
+ - Organize tests logically by feature or module
33
+ - Run tests before committing changes
34
+
35
+ ### Security Best Practices
36
+ - Never commit sensitive information (API keys, passwords, tokens)
37
+ - Use environment variables for configuration
38
+ - Validate input data and sanitize outputs
39
+ - Follow principle of least privilege
40
+ - Keep dependencies updated
41
+
42
+ ## Project Structure Guidelines
43
+
44
+ ### File Organization
45
+ - Group related files in logical directories
46
+ - Use consistent file and folder naming conventions
47
+ - Separate source code from configuration files
48
+ - Keep build artifacts out of version control
49
+ - Organize assets and resources appropriately
50
+
51
+ ### Configuration Management
52
+ - Use configuration files for environment-specific settings
53
+ - Centralize configuration in dedicated files
54
+ - Use environment variables for sensitive or environment-specific data
55
+ - Document configuration options and their purposes
56
+ - Provide example configuration files
57
+
58
+ ## Development Workflow
59
+
60
+ ### Before Starting Work
61
+ 1. Pull latest changes from main branch
62
+ 2. Create a new feature branch
63
+ 3. Review existing code and architecture
64
+ 4. Plan the implementation approach
65
+
66
+ ### During Development
67
+ 1. Make incremental commits with clear messages
68
+ 2. Run tests frequently to catch issues early
69
+ 3. Follow established coding standards
70
+ 4. Update documentation as needed
71
+
72
+ ### Before Submitting
73
+ 1. Run full test suite
74
+ 2. Check code quality and formatting
75
+ 3. Update documentation if necessary
76
+ 4. Create clear pull request description
77
+
78
+ ## Common Patterns
79
+
80
+ ### Error Handling
81
+ - Use appropriate error handling mechanisms for the language
82
+ - Provide meaningful error messages
83
+ - Log errors appropriately for debugging
84
+ - Handle edge cases gracefully
85
+ - Don't expose sensitive information in error messages
86
+
87
+ ### Performance Considerations
88
+ - Profile code for performance bottlenecks
89
+ - Optimize database queries and API calls
90
+ - Use caching where appropriate
91
+ - Consider memory usage and resource management
92
+ - Monitor and measure performance metrics
93
+
94
+ ### Code Reusability
95
+ - Extract common functionality into reusable modules
96
+ - Use dependency injection for better testability
97
+ - Create utility functions for repeated operations
98
+ - Design interfaces for extensibility
99
+ - Follow DRY (Don't Repeat Yourself) principle
100
+
101
+ ## Review Checklist
102
+
103
+ Before marking any task as complete:
104
+ - [ ] Code follows established conventions
105
+ - [ ] Tests are written and passing
106
+ - [ ] Documentation is updated
107
+ - [ ] Security considerations are addressed
108
+ - [ ] Performance impact is considered
109
+ - [ ] Code is reviewed for maintainability
@@ -0,0 +1,96 @@
1
+ # Common Claude Code Templates
2
+
3
+ This folder contains language-agnostic templates and configurations that can be used across different programming languages and project types.
4
+
5
+ ## What's Included
6
+
7
+ ### Core Files
8
+ - `CLAUDE.md` - Base configuration for Claude Code with universal best practices
9
+ - `.claude/commands/` - Custom commands for common development tasks
10
+
11
+ ### Common Custom Commands
12
+ - `git-workflow.md` - Git operations and workflow automation
13
+ - `code-review.md` - Code review and quality assurance tasks
14
+ - `project-setup.md` - Project initialization and configuration
15
+ - `documentation.md` - Documentation generation and maintenance
16
+
17
+ ## How to Use
18
+
19
+ ### For New Projects
20
+ Copy the entire `common/` folder contents to your project root:
21
+
22
+ ```bash
23
+ cp -r claude-code-templates/common/* your-project/
24
+ ```
25
+
26
+ ### For Existing Projects
27
+ Merge the relevant files with your existing Claude Code configuration:
28
+
29
+ ```bash
30
+ # Copy custom commands
31
+ cp -r claude-code-templates/common/.claude/commands/* your-project/.claude/commands/
32
+
33
+ # Review and merge CLAUDE.md content
34
+ cat claude-code-templates/common/CLAUDE.md >> your-project/CLAUDE.md
35
+ ```
36
+
37
+ ## Customization
38
+
39
+ ### CLAUDE.md
40
+ The base CLAUDE.md file includes:
41
+ - Universal development best practices
42
+ - Common project patterns and conventions
43
+ - Git workflow guidelines
44
+ - Code quality standards
45
+
46
+ Customize it by:
47
+ - Adding project-specific information
48
+ - Modifying coding standards to match your team's preferences
49
+ - Including technology-specific guidelines
50
+
51
+ ### Custom Commands
52
+ The included commands are designed to be generic and widely applicable. You can:
53
+ - Modify existing commands to match your workflow
54
+ - Add new commands for project-specific tasks
55
+ - Remove commands that don't apply to your project
56
+
57
+ ## Language-Specific Integration
58
+
59
+ This common template is designed to work alongside language-specific templates:
60
+
61
+ 1. Start with the common template
62
+ 2. Add language-specific configurations from the appropriate folder
63
+ 3. Customize both to match your project needs
64
+
65
+ ## Examples
66
+
67
+ ### Multi-language Projects
68
+ For projects using multiple programming languages:
69
+
70
+ ```bash
71
+ # Copy common base
72
+ cp -r claude-code-templates/common/* your-project/
73
+
74
+ # Add language-specific configurations
75
+ cp -r claude-code-templates/javascript-typescript/.claude/commands/* your-project/.claude/commands/
76
+ cp -r claude-code-templates/python/.claude/commands/* your-project/.claude/commands/
77
+ ```
78
+
79
+ ### Team Standardization
80
+ Organizations can use this as a base template and customize it for their specific needs:
81
+
82
+ 1. Fork this repository
83
+ 2. Modify the common templates to match your standards
84
+ 3. Distribute to development teams
85
+ 4. Keep synchronized with updates
86
+
87
+ ## Best Practices
88
+
89
+ - **Start Simple**: Begin with the common template and add complexity as needed
90
+ - **Document Changes**: Keep track of customizations in your project's documentation
91
+ - **Regular Updates**: Periodically review and update your Claude Code configuration
92
+ - **Team Alignment**: Ensure all team members understand the custom commands and workflows
93
+
94
+ ## Contributing
95
+
96
+ If you create useful generic commands or improvements to the common template, consider contributing them back to this repository to help other developers.
@@ -0,0 +1 @@
1
+ # API Endpoint Command
@@ -0,0 +1 @@
1
+ # Debug Command
@@ -0,0 +1 @@
1
+ # Lint Command
@@ -0,0 +1 @@
1
+ # NPM Scripts Command
@@ -0,0 +1 @@
1
+ # React Component Command
@@ -0,0 +1 @@
1
+ # Refactor Command
@@ -0,0 +1 @@
1
+ # Test Command
@@ -0,0 +1 @@
1
+ # TypeScript Migrate Command
@@ -0,0 +1,103 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash",
5
+ "Edit",
6
+ "MultiEdit",
7
+ "Write",
8
+ "Bash(npm:*)",
9
+ "Bash(yarn:*)",
10
+ "Bash(npx:*)",
11
+ "Bash(node:*)",
12
+ "Bash(git:*)",
13
+ "Bash(eslint:*)",
14
+ "Bash(prettier:*)",
15
+ "Bash(tsc:*)",
16
+ "Bash(jest:*)",
17
+ "Bash(vitest:*)",
18
+ "Bash(webpack:*)",
19
+ "Bash(vite:*)"
20
+ ],
21
+ "deny": [
22
+ "Bash(curl:*)",
23
+ "Bash(wget:*)",
24
+ "Bash(rm -rf:*)"
25
+ ],
26
+ "defaultMode": "allowEdits"
27
+ },
28
+ "env": {
29
+ "BASH_DEFAULT_TIMEOUT_MS": "30000",
30
+ "BASH_MAX_OUTPUT_LENGTH": "10000",
31
+ "CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1",
32
+ "NODE_ENV": "development"
33
+ },
34
+ "includeCoAuthoredBy": true,
35
+ "cleanupPeriodDays": 30,
36
+ "hooks": {
37
+ "PreToolUse": [
38
+ {
39
+ "matcher": "Bash",
40
+ "hooks": [
41
+ {
42
+ "type": "command",
43
+ "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
44
+ }
45
+ ]
46
+ },
47
+ {
48
+ "matcher": "Write",
49
+ "hooks": [
50
+ {
51
+ "type": "command",
52
+ "command": "if [[ \"$(jq -r '.tool_input.file_path' | grep -E '\\.js$|\\.jsx$|\\.ts$|\\.tsx$')\" != \"\" && $(jq -r '.tool_input.content' | grep -E 'console\\.log') != \"\" ]]; then echo 'Warning: console.log statements should be removed before committing' >&2; fi"
53
+ }
54
+ ]
55
+ }
56
+ ],
57
+ "PostToolUse": [
58
+ {
59
+ "matcher": "Write|Edit|MultiEdit",
60
+ "hooks": [
61
+ {
62
+ "type": "command",
63
+ "command": "FILE=$(echo $STDIN_JSON | jq -r '.tool_input.file_path // \"\"'); if [[ \"$FILE\" =~ \\.(js|jsx|ts|tsx)$ ]]; then npx prettier --write \"$FILE\"; fi",
64
+ "timeout": 30
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ "matcher": "Write|Edit|MultiEdit",
70
+ "hooks": [
71
+ {
72
+ "type": "command",
73
+ "command": "FILE=$(echo $STDIN_JSON | jq -r '.tool_input.file_path // \"\"'); if [[ \"$FILE\" =~ \\.(ts|tsx)$ ]]; then npx tsc --noEmit; fi",
74
+ "timeout": 30
75
+ }
76
+ ]
77
+ }
78
+ ],
79
+ "Notification": [
80
+ {
81
+ "matcher": "",
82
+ "hooks": [
83
+ {
84
+ "type": "command",
85
+ "command": "echo \"Claude Code notification: $(date)\" >> ~/.claude/notifications.log"
86
+ }
87
+ ]
88
+ }
89
+ ],
90
+ "Stop": [
91
+ {
92
+ "matcher": "",
93
+ "hooks": [
94
+ {
95
+ "type": "command",
96
+ "command": "if [[ -f package.json && $(git status --porcelain | grep -E '\\.js$|\\.jsx$|\\.ts$|\\.tsx$') ]]; then echo 'Running linter on changed files...'; npx eslint $(git diff --name-only --diff-filter=ACMR | grep -E '\\.js$|\\.jsx$|\\.ts$|\\.tsx$'); fi",
97
+ "timeout": 60
98
+ }
99
+ ]
100
+ }
101
+ ]
102
+ }
103
+ }