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.
- package/.devcontainer/CHANGELOG.md +112 -0
- package/.devcontainer/README.md +7 -3
- package/.devcontainer/config/main-system-prompt.md +10 -0
- package/.devcontainer/config/settings.json +9 -5
- package/.devcontainer/connect-external-terminal.ps1 +77 -0
- package/.devcontainer/connect-external-terminal.sh +69 -0
- package/.devcontainer/devcontainer.json +9 -4
- package/.devcontainer/features/agent-browser/install.sh +5 -5
- package/.devcontainer/features/biome/devcontainer-feature.json +16 -0
- package/.devcontainer/features/biome/install.sh +19 -0
- package/.devcontainer/features/tmux/README.md +75 -0
- package/.devcontainer/features/tmux/devcontainer-feature.json +17 -0
- package/.devcontainer/features/tmux/install.sh +52 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +2 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +5 -5
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py +177 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +2 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/.claude-plugin/commands/debug.md +86 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +149 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +46 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/collect-edited-files.py +44 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +229 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/syntax-validator.py +141 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/debugging/SKILL.md +165 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/debugging/references/error-patterns.md +530 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/debugging/references/log-locations.md +430 -0
- package/README.md +13 -9
- package/package.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +0 -101
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/claude-code-headless/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/claude-code-headless/references/cli-flags-and-output.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/claude-code-headless/references/sdk-and-mcp.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker/references/compose-services.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker/references/dockerfile-patterns.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker-py/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker-py/references/container-lifecycle.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/docker-py/references/resources-and-security.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/middleware-and-lifespan.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/pydantic-models.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/routing-and-dependencies.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/fastapi/references/sse-and-streaming.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/pydantic-ai/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/pydantic-ai/references/agents-and-tools.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/pydantic-ai/references/models-and-streaming.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/references/cross-vendor-principles.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/references/patterns-and-antipatterns.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/skill-building/references/skill-authoring-patterns.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/advanced-queries.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/javascript-patterns.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/python-patterns.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/sqlite/references/schema-and-pragmas.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/ai-sdk-svelte.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/component-patterns.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/layercake.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/migration-guide.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/runes-and-reactivity.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/spa-and-routing.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/svelte5/references/svelte-dnd-action.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/testing/SKILL.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/testing/references/fastapi-testing.md +0 -0
- /package/.devcontainer/plugins/devs-marketplace/plugins/{codedirective-skills → code-directive}/skills/testing/references/svelte-testing.md +0 -0
package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py
ADDED
|
@@ -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()
|
|
@@ -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."
|
|
@@ -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()
|