codeforge-dev 1.4.0 → 1.5.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 (68) hide show
  1. package/.devcontainer/CHANGELOG.md +112 -0
  2. package/.devcontainer/README.md +7 -3
  3. package/.devcontainer/config/main-system-prompt.md +10 -0
  4. package/.devcontainer/config/settings.json +9 -5
  5. package/.devcontainer/connect-external-terminal.ps1 +77 -0
  6. package/.devcontainer/connect-external-terminal.sh +69 -0
  7. package/.devcontainer/devcontainer.json +9 -4
  8. package/.devcontainer/features/agent-browser/install.sh +5 -5
  9. package/.devcontainer/features/biome/devcontainer-feature.json +16 -0
  10. package/.devcontainer/features/biome/install.sh +19 -0
  11. package/.devcontainer/features/tmux/README.md +75 -0
  12. package/.devcontainer/features/tmux/devcontainer-feature.json +17 -0
  13. package/.devcontainer/features/tmux/install.sh +52 -0
  14. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +2 -2
  15. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +1 -1
  16. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +5 -5
  17. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py +177 -0
  18. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +2 -1
  19. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/.claude-plugin/commands/debug.md +86 -0
  20. package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/.claude-plugin/plugin.json +1 -1
  21. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +149 -0
  22. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +46 -0
  23. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/collect-edited-files.py +44 -0
  24. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +229 -0
  25. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/syntax-validator.py +141 -0
  26. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/debugging/SKILL.md +165 -0
  27. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/debugging/references/error-patterns.md +530 -0
  28. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/debugging/references/log-locations.md +430 -0
  29. package/README.md +13 -9
  30. package/package.json +1 -1
  31. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +0 -101
  32. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/claude-code-headless/SKILL.md +0 -0
  33. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/claude-code-headless/references/cli-flags-and-output.md +0 -0
  34. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/claude-code-headless/references/sdk-and-mcp.md +0 -0
  35. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker/SKILL.md +0 -0
  36. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker/references/compose-services.md +0 -0
  37. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker/references/dockerfile-patterns.md +0 -0
  38. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker-py/SKILL.md +0 -0
  39. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker-py/references/container-lifecycle.md +0 -0
  40. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker-py/references/resources-and-security.md +0 -0
  41. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/SKILL.md +0 -0
  42. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/middleware-and-lifespan.md +0 -0
  43. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/pydantic-models.md +0 -0
  44. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/routing-and-dependencies.md +0 -0
  45. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/sse-and-streaming.md +0 -0
  46. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/pydantic-ai/SKILL.md +0 -0
  47. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/pydantic-ai/references/agents-and-tools.md +0 -0
  48. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/pydantic-ai/references/models-and-streaming.md +0 -0
  49. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/SKILL.md +0 -0
  50. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/references/cross-vendor-principles.md +0 -0
  51. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/references/patterns-and-antipatterns.md +0 -0
  52. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/references/skill-authoring-patterns.md +0 -0
  53. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/SKILL.md +0 -0
  54. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/advanced-queries.md +0 -0
  55. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/javascript-patterns.md +0 -0
  56. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/python-patterns.md +0 -0
  57. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/schema-and-pragmas.md +0 -0
  58. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/SKILL.md +0 -0
  59. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/ai-sdk-svelte.md +0 -0
  60. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/component-patterns.md +0 -0
  61. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/layercake.md +0 -0
  62. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/migration-guide.md +0 -0
  63. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/runes-and-reactivity.md +0 -0
  64. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/spa-and-routing.md +0 -0
  65. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/svelte-dnd-action.md +0 -0
  66. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/testing/SKILL.md +0 -0
  67. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/testing/references/fastapi-testing.md +0 -0
  68. /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/testing/references/svelte-testing.md +0 -0
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Unified batch formatter — runs as a Stop hook.
4
+
5
+ Reads file paths collected by collect-edited-files.py during the
6
+ conversation turn, deduplicates them, and formats each based on
7
+ extension:
8
+ .py / .pyi → Black
9
+ .go → gofmt
10
+ .js/.jsx/.ts/.tsx/.mjs/.cjs/.mts/.cts/.css → Biome (safe mode)
11
+
12
+ Always cleans up the temp file. Always exits 0.
13
+ """
14
+
15
+ import json
16
+ import os
17
+ import subprocess
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ # Formatter dispatch by extension
22
+ PYTHON_EXTS = {".py", ".pyi"}
23
+ GO_EXTS = {".go"}
24
+ BIOME_EXTS = {
25
+ ".js",
26
+ ".jsx",
27
+ ".ts",
28
+ ".tsx",
29
+ ".mjs",
30
+ ".cjs",
31
+ ".mts",
32
+ ".cts",
33
+ ".css",
34
+ }
35
+
36
+ BLACK_PATH = "/usr/local/py-utils/bin/black"
37
+ GOFMT_PATH = "/usr/local/go/bin/gofmt"
38
+
39
+
40
+ def find_tool_upward(file_path: str, tool_name: str) -> str | None:
41
+ """Walk up from file directory looking for node_modules/.bin/<tool>."""
42
+ current = Path(file_path).parent
43
+ for _ in range(20):
44
+ candidate = current / "node_modules" / ".bin" / tool_name
45
+ if candidate.is_file():
46
+ return str(candidate)
47
+ parent = current.parent
48
+ if parent == current:
49
+ break
50
+ current = parent
51
+ return None
52
+
53
+
54
+ def find_global_tool(tool_name: str) -> str | None:
55
+ """Check if tool is available globally."""
56
+ try:
57
+ result = subprocess.run(
58
+ ["which", tool_name],
59
+ capture_output=True,
60
+ text=True,
61
+ )
62
+ if result.returncode == 0:
63
+ return result.stdout.strip()
64
+ except Exception:
65
+ pass
66
+ return None
67
+
68
+
69
+ def find_biome(file_path: str) -> str | None:
70
+ """Find biome binary: project-local first, then global."""
71
+ local = find_tool_upward(file_path, "biome")
72
+ if local:
73
+ return local
74
+ return find_global_tool("biome")
75
+
76
+
77
+ def format_python(file_path: str) -> None:
78
+ """Format with Black (quiet mode)."""
79
+ if not os.path.exists(BLACK_PATH):
80
+ return
81
+ try:
82
+ subprocess.run(
83
+ [BLACK_PATH, "--quiet", file_path],
84
+ capture_output=True,
85
+ timeout=10,
86
+ )
87
+ except (subprocess.TimeoutExpired, OSError):
88
+ pass
89
+
90
+
91
+ def format_go(file_path: str) -> None:
92
+ """Format with gofmt."""
93
+ if not os.path.exists(GOFMT_PATH):
94
+ return
95
+ try:
96
+ subprocess.run(
97
+ [GOFMT_PATH, "-w", file_path],
98
+ capture_output=True,
99
+ timeout=10,
100
+ )
101
+ except (subprocess.TimeoutExpired, OSError):
102
+ pass
103
+
104
+
105
+ def format_biome(file_path: str) -> None:
106
+ """Format with Biome in safe mode (no --unsafe)."""
107
+ biome = find_biome(file_path)
108
+ if not biome:
109
+ return
110
+ try:
111
+ subprocess.run(
112
+ [biome, "check", "--write", file_path],
113
+ capture_output=True,
114
+ timeout=12,
115
+ )
116
+ except (subprocess.TimeoutExpired, OSError):
117
+ pass
118
+
119
+
120
+ def format_file(file_path: str) -> None:
121
+ """Dispatch to the correct formatter based on extension."""
122
+ ext = Path(file_path).suffix.lower()
123
+ if ext in PYTHON_EXTS:
124
+ format_python(file_path)
125
+ elif ext in GO_EXTS:
126
+ format_go(file_path)
127
+ elif ext in BIOME_EXTS:
128
+ format_biome(file_path)
129
+
130
+
131
+ def main():
132
+ try:
133
+ input_data = json.load(sys.stdin)
134
+ except (json.JSONDecodeError, ValueError):
135
+ sys.exit(0)
136
+
137
+ # Prevent infinite loops if Stop hook triggers another stop
138
+ if input_data.get("stop_hook_active"):
139
+ sys.exit(0)
140
+
141
+ session_id = input_data.get("session_id", "")
142
+ if not session_id:
143
+ sys.exit(0)
144
+
145
+ tmp_path = f"/tmp/claude-edited-files-{session_id}"
146
+
147
+ try:
148
+ with open(tmp_path) as f:
149
+ raw_paths = f.read().splitlines()
150
+ except FileNotFoundError:
151
+ sys.exit(0)
152
+ except OSError:
153
+ sys.exit(0)
154
+ finally:
155
+ # Always clean up the temp file
156
+ try:
157
+ os.unlink(tmp_path)
158
+ except OSError:
159
+ pass
160
+
161
+ # Deduplicate while preserving order, filter to existing files
162
+ seen: set[str] = set()
163
+ paths: list[str] = []
164
+ for p in raw_paths:
165
+ p = p.strip()
166
+ if p and p not in seen and os.path.isfile(p):
167
+ seen.add(p)
168
+ paths.append(p)
169
+
170
+ for path in paths:
171
+ format_file(path)
172
+
173
+ sys.exit(0)
174
+
175
+
176
+ if __name__ == "__main__":
177
+ main()
@@ -8,7 +8,8 @@
8
8
  {
9
9
  "type": "command",
10
10
  "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/lint-file.py",
11
- "timeout": 60
11
+ "timeout": 15,
12
+ "async": true
12
13
  }
13
14
  ]
14
15
  }
@@ -0,0 +1,86 @@
1
+ ---
2
+ description: Investigate logs and diagnose issues using the debug-logs agent
3
+ argument-hint: [error description, container/service name, or timeframe]
4
+ allowed-tools: Bash, Read, Glob, Grep, Task
5
+ ---
6
+
7
+ # /debug - Log Investigation & Issue Diagnosis
8
+
9
+ Investigate application, container, and system logs to diagnose failures and errors.
10
+
11
+ ## Input
12
+
13
+ `$ARGUMENTS` - Optional scope hint. Can be:
14
+ - An error message or description (e.g., "connection refused on port 5432")
15
+ - A container or service name (e.g., "web", "postgres")
16
+ - A timeframe (e.g., "last 30 minutes", "since deployment")
17
+ - A combination (e.g., "OOM errors in worker container since noon")
18
+ - Empty (triggers a broad scan of all available log sources)
19
+
20
+ ## Process
21
+
22
+ ### Step 1: Load Domain Knowledge
23
+
24
+ **CRITICAL:** Before any log analysis, invoke the `debugging` skill to load log analysis domain knowledge. This ensures you have the full reference material for log locations, error patterns, and diagnosis procedures.
25
+
26
+ ### Step 2: Parse Scope
27
+
28
+ Analyze `$ARGUMENTS` to determine:
29
+ - **Target service/container**: Specific container name, service name, or "all"
30
+ - **Error type**: What kind of error to look for, or "any"
31
+ - **Timeframe**: How far back to look (default: 1 hour)
32
+
33
+ If arguments are empty, set scope to: all sources, any errors, last 1 hour.
34
+
35
+ ### Step 3: Delegate to Debug Agent
36
+
37
+ **CRITICAL:** You MUST use the `debug-logs` agent (via the Task tool) for all log analysis work. Do NOT read logs directly — delegate to the agent.
38
+
39
+ Construct a clear task description for the agent that includes:
40
+ - What to investigate (the parsed scope from Step 2)
41
+ - Any specific error messages or patterns to search for
42
+ - The timeframe to focus on
43
+ - What the user reported as the symptom
44
+
45
+ Example delegation:
46
+ ```
47
+ Investigate logs for the "web" container. The user reports "connection refused" errors.
48
+ Focus on the last 1 hour. Check the web container logs, any dependent service containers
49
+ (database, redis, etc.), and correlate timestamps to find the root cause.
50
+ ```
51
+
52
+ ### Step 4: Present Findings
53
+
54
+ When the agent returns its findings, present them to the user in this format:
55
+
56
+ **Summary** - One-sentence root cause assessment.
57
+
58
+ **What Was Checked** - List of all log sources examined.
59
+
60
+ **Errors Found** - Each error with severity, timestamp, source, and context. Highlight the root cause error distinctly from downstream effects.
61
+
62
+ **Timeline** - Chronological sequence of events if multiple errors were found.
63
+
64
+ **Recommended Actions** - Ordered steps to resolve the issue, with specific commands or code changes.
65
+
66
+ ### Step 5: Follow Up (if inconclusive)
67
+
68
+ If the agent's findings are inconclusive:
69
+ 1. Identify what additional information would help
70
+ 2. Re-invoke the agent with a narrower or different scope
71
+ 3. Consider checking different log sources or expanding the timeframe
72
+ 4. Report partial findings to the user and suggest manual investigation steps
73
+
74
+ ## Examples
75
+
76
+ **Broad scan (no arguments):**
77
+ > User: `/debug`
78
+ > Action: Delegate to agent with "Perform a broad scan of all available log sources from the last hour. List all containers, find all log files, check system logs. Report any errors, warnings, or anomalies."
79
+
80
+ **Specific container:**
81
+ > User: `/debug postgres container keeps restarting`
82
+ > Action: Delegate to agent with "Investigate the postgres container. It is reportedly restarting repeatedly. Check container exit codes, restart count, logs before each crash, memory usage, and health check status."
83
+
84
+ **Error investigation:**
85
+ > User: `/debug 502 Bad Gateway`
86
+ > Action: Delegate to agent with "Investigate 502 Bad Gateway errors. Check the reverse proxy / web server logs (nginx, caddy, etc.) for upstream connection failures, then check the upstream application container logs for crashes or errors that would cause it to be unavailable."
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "codedirective-skills",
2
+ "name": "code-directive",
3
3
  "description": "Coding standards and skills for the CodeDirective project",
4
4
  "version": "1.0.0",
5
5
  "author": {
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: debug-logs
3
+ description: >-
4
+ Read-only agent that finds and analyzes log files across Docker containers,
5
+ application frameworks, and system services to identify errors, crashes,
6
+ and performance issues. Reports structured findings with root cause assessment.
7
+ tools: Bash, Read, Glob, Grep
8
+ model: sonnet
9
+ color: red
10
+ ---
11
+
12
+ # Debug Logs Agent
13
+
14
+ You are a **read-only log analysis specialist**. Your purpose is to find, read, and analyze log files to diagnose issues. You help developers understand what went wrong by examining Docker container logs, application log files, and system logs.
15
+
16
+ ## Critical Constraints
17
+
18
+ - **NEVER** modify any file, configuration, or system state.
19
+ - **NEVER** restart services, containers, or processes.
20
+ - **NEVER** install packages or change permissions.
21
+ - **NEVER** write files, create directories, or alter environment variables.
22
+ - You are strictly **read-only**. Your only actions are reading logs, searching content, and running diagnostic commands that produce output without side effects.
23
+
24
+ ## Log Discovery Strategy
25
+
26
+ When investigating an issue, follow this priority order. Cast a wide net first, then narrow based on findings.
27
+
28
+ ### Priority 1: Docker Container Logs
29
+
30
+ Docker is the most common runtime environment. Start here unless the user specifies otherwise.
31
+
32
+ ```bash
33
+ # List all containers (including stopped ones)
34
+ docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}"
35
+
36
+ # Get recent logs from a specific container (last 200 lines)
37
+ docker logs --tail 200 <container_name>
38
+
39
+ # Get logs with timestamps for chronology
40
+ docker logs --tail 200 --timestamps <container_name>
41
+
42
+ # Get logs from a specific time window
43
+ docker logs --since "1h" <container_name>
44
+ docker logs --since "2025-01-15T10:00:00" <container_name>
45
+
46
+ # Aggregate logs from all Compose services
47
+ docker compose logs --tail 100
48
+
49
+ # Inspect container for exit codes, state, health checks
50
+ docker inspect --format '{{.State.Status}} exit:{{.State.ExitCode}} oom:{{.State.OOMKilled}}' <container_name>
51
+
52
+ # Check recent Docker events
53
+ docker events --since "1h" --until "now" --format '{{.Time}} {{.Type}} {{.Action}} {{.Actor.Attributes.name}}'
54
+ ```
55
+
56
+ If a container has exited, always check its exit code. Key exit codes:
57
+ - **0**: Clean shutdown
58
+ - **1**: Application error
59
+ - **137** (128+9): Killed by SIGKILL (usually OOM or `docker kill`)
60
+ - **143** (128+15): Killed by SIGTERM (graceful stop timed out or `docker stop`)
61
+ - **126**: Permission denied on entrypoint
62
+ - **127**: Entrypoint command not found
63
+
64
+ ### Priority 2: Application Log Files
65
+
66
+ Search for log files in common locations:
67
+
68
+ ```bash
69
+ # Project-local logs
70
+ # Use Glob: ./**/*.log, ./logs/**, ./log/**
71
+
72
+ # Framework-specific paths
73
+ # Python/FastAPI/Uvicorn: ./logs/, /tmp/*.log
74
+ # Node.js/Express: ./logs/, ./combined.log, ./error.log
75
+ # PM2: ~/.pm2/logs/
76
+
77
+ # System-installed application logs
78
+ # /var/log/<app_name>/
79
+ ```
80
+
81
+ Use `Glob` to discover log files, then `Grep` to search for error indicators before reading full files. For large logs, always filter first:
82
+
83
+ ```bash
84
+ # Search for error patterns across discovered log files
85
+ # Use Grep with patterns: ERROR, FATAL, Traceback, panic, CRITICAL, Exception
86
+ ```
87
+
88
+ ### Priority 3: System Logs
89
+
90
+ When Docker and application logs are insufficient:
91
+
92
+ ```bash
93
+ # Recent system journal entries
94
+ journalctl --no-pager -n 100 --since "1 hour ago"
95
+
96
+ # Kernel messages (OOM killer, hardware errors)
97
+ journalctl --no-pager -n 50 -k --since "1 hour ago"
98
+
99
+ # Service-specific journal
100
+ journalctl --no-pager -n 100 -u <service_name> --since "1 hour ago"
101
+
102
+ # Disk space (often the hidden cause)
103
+ df -h
104
+
105
+ # Memory pressure
106
+ free -h
107
+ ```
108
+
109
+ ## Analysis Procedure
110
+
111
+ 1. **Collect Sources** - Identify all available log sources. List what exists before diving deep.
112
+ 2. **Scan for Error Indicators** - Use Grep across all sources for: `ERROR`, `FATAL`, `CRITICAL`, `Traceback`, `panic`, `segfault`, `OOMKilled`, `exit code`, `refused`, `timeout`, `denied`.
113
+ 3. **Establish Chronology** - Sort errors by timestamp. The first error in a cascade is usually the root cause; subsequent errors are often consequences.
114
+ 4. **Correlate Across Sources** - If Service A failed at 10:02 and Service B started erroring at 10:03, Service A is likely the root cause.
115
+ 5. **Assess Root Cause** - Distinguish between the triggering event and its downstream effects. Look for the earliest anomaly.
116
+
117
+ ## Behavioral Rules
118
+
119
+ - **No arguments provided**: Perform a broad scan. List all containers, find all log files, check system logs. Report everything found.
120
+ - **Service/container name provided**: Focus on that service. Check its container logs, any related log files, and its dependencies.
121
+ - **Error description provided**: Search all sources for that specific error pattern. Report where it appears, when, and what preceded it.
122
+ - **Timeframe provided**: Limit all queries to that window.
123
+ - **Always report what was checked**, even if nothing was found. Negative results ("No errors in nginx logs for the past hour") are valuable.
124
+ - For large log files (>1000 lines), use Grep to identify relevant sections before reading. Never dump entire large logs.
125
+
126
+ ## Output Format
127
+
128
+ Structure your findings as follows:
129
+
130
+ ### Sources Examined
131
+ List every log source you checked, with line counts or time ranges.
132
+
133
+ ### Errors Found
134
+ For each error, provide:
135
+ - **Severity**: CRITICAL / ERROR / WARNING
136
+ - **Timestamp**: When it occurred
137
+ - **Source**: Which log file or container
138
+ - **Message**: The actual error text (quoted)
139
+ - **Context**: 2-3 lines before/after the error
140
+ - **Likely Cause**: Your assessment of what triggered this specific error
141
+
142
+ ### Timeline
143
+ Chronological sequence of events leading to the issue. Include the first normal log entry, the first anomaly, and the cascade of failures.
144
+
145
+ ### Root Cause Assessment
146
+ Your best assessment of the underlying cause, based on the evidence. State your confidence level (high/medium/low) and what additional information would increase confidence.
147
+
148
+ ### Recommended Actions
149
+ Ordered list of steps the developer should take to resolve the issue. Be specific — name the exact service, configuration, or code path involved.
@@ -0,0 +1,46 @@
1
+ {
2
+ "description": "Code quality hooks and skill suggestions for the CodeDirective project",
3
+ "hooks": {
4
+ "UserPromptSubmit": [
5
+ {
6
+ "matcher": "*",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/skill-suggester.py",
11
+ "timeout": 3
12
+ }
13
+ ]
14
+ }
15
+ ],
16
+ "SubagentStart": [
17
+ {
18
+ "matcher": "Plan",
19
+ "hooks": [
20
+ {
21
+ "type": "command",
22
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/skill-suggester.py",
23
+ "timeout": 3
24
+ }
25
+ ]
26
+ }
27
+ ],
28
+ "PostToolUse": [
29
+ {
30
+ "matcher": "Edit|Write",
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/syntax-validator.py",
35
+ "timeout": 5
36
+ },
37
+ {
38
+ "type": "command",
39
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/collect-edited-files.py",
40
+ "timeout": 3
41
+ }
42
+ ]
43
+ }
44
+ ]
45
+ }
46
+ }
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Collect edited file paths for batch formatting at Stop.
4
+
5
+ Lightweight PostToolUse hook that appends the edited file path
6
+ to a session-scoped temp file. The auto-formatter Stop hook
7
+ reads this file to know which files need formatting.
8
+
9
+ Non-blocking: always exits 0. Runs in <10ms.
10
+ """
11
+
12
+ import json
13
+ import os
14
+ import sys
15
+
16
+
17
+ def main():
18
+ try:
19
+ input_data = json.load(sys.stdin)
20
+ except (json.JSONDecodeError, ValueError):
21
+ sys.exit(0)
22
+
23
+ session_id = input_data.get("session_id", "")
24
+ tool_input = input_data.get("tool_input", {})
25
+ file_path = tool_input.get("file_path", "")
26
+
27
+ if not file_path or not session_id:
28
+ sys.exit(0)
29
+
30
+ if not os.path.isfile(file_path):
31
+ sys.exit(0)
32
+
33
+ tmp_path = f"/tmp/claude-edited-files-{session_id}"
34
+ try:
35
+ with open(tmp_path, "a") as f:
36
+ f.write(file_path + "\n")
37
+ except OSError:
38
+ pass # non-critical, don't block Claude
39
+
40
+ sys.exit(0)
41
+
42
+
43
+ if __name__ == "__main__":
44
+ main()