codeforge-dev 1.11.0 → 1.12.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 (56) hide show
  1. package/.devcontainer/.env +7 -1
  2. package/.devcontainer/.gitignore +1 -0
  3. package/.devcontainer/CHANGELOG.md +69 -0
  4. package/.devcontainer/CLAUDE.md +73 -3
  5. package/.devcontainer/README.md +33 -7
  6. package/.devcontainer/config/defaults/main-system-prompt.md +28 -0
  7. package/.devcontainer/config/defaults/writing-system-prompt.md +46 -4
  8. package/.devcontainer/connect-external-terminal.ps1 +1 -1
  9. package/.devcontainer/devcontainer.json +32 -9
  10. package/.devcontainer/docs/configuration-reference.md +3 -0
  11. package/.devcontainer/docs/plugins.md +9 -2
  12. package/.devcontainer/docs/troubleshooting.md +2 -2
  13. package/.devcontainer/features/README.md +8 -9
  14. package/.devcontainer/features/agent-browser/devcontainer-feature.json +21 -21
  15. package/.devcontainer/features/agent-browser/install.sh +0 -7
  16. package/.devcontainer/features/ast-grep/devcontainer-feature.json +22 -22
  17. package/.devcontainer/features/biome/devcontainer-feature.json +12 -14
  18. package/.devcontainer/features/ccms/install.sh +30 -13
  19. package/.devcontainer/features/lsp-servers/devcontainer-feature.json +43 -43
  20. package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +2 -1
  21. package/.devcontainer/features/ruff/devcontainer-feature.json +17 -19
  22. package/.devcontainer/features/tmux/install.sh +2 -2
  23. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/README.md +81 -0
  24. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/README.md +92 -0
  25. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/README.md +250 -0
  26. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +1 -1
  27. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +1 -1
  28. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +1 -1
  29. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +1 -1
  30. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +1 -1
  31. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/git-archaeologist.md +2 -2
  32. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/researcher.md +1 -1
  33. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/security-auditor.md +1 -1
  34. package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/README.md +41 -0
  35. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/README.md +72 -0
  36. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +73 -47
  37. package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/README.md +42 -0
  38. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/README.md +86 -0
  39. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +25 -15
  40. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected-bash.py +122 -0
  41. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +3 -3
  42. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/README.md +96 -0
  43. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/README.md +94 -0
  44. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py +1 -1
  45. package/.devcontainer/scripts/check-setup.sh +1 -1
  46. package/.devcontainer/scripts/setup-projects.sh +23 -16
  47. package/.devcontainer/scripts/setup.sh +48 -5
  48. package/README.md +17 -8
  49. package/package.json +1 -2
  50. package/.devcontainer/features/mcp-reasoner/README.md +0 -177
  51. package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +0 -25
  52. package/.devcontainer/features/mcp-reasoner/install.sh +0 -184
  53. package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +0 -67
  54. package/.devcontainer/features/splitrail/README.md +0 -140
  55. package/.devcontainer/features/splitrail/devcontainer-feature.json +0 -39
  56. package/.devcontainer/features/splitrail/install.sh +0 -136
@@ -1,23 +1,23 @@
1
1
  {
2
- "id": "agent-browser",
3
- "version": "1.0.0",
4
- "name": "agent-browser",
5
- "description": "Headless browser automation CLI for AI agents (Vercel Labs)",
6
- "documentationURL": "https://github.com/vercel-labs/agent-browser",
7
- "options": {
8
- "version": {
9
- "type": "string",
10
- "description": "agent-browser npm package version",
11
- "default": "latest"
12
- },
13
- "username": {
14
- "type": "string",
15
- "description": "Container user to install for",
16
- "default": "automatic"
17
- }
18
- },
19
- "installsAfter": [
20
- "ghcr.io/devcontainers/features/common-utils:2",
21
- "ghcr.io/devcontainers/features/node:1"
22
- ]
2
+ "id": "agent-browser",
3
+ "version": "1.0.0",
4
+ "name": "agent-browser",
5
+ "description": "Headless browser automation CLI for AI agents (Vercel Labs)",
6
+ "documentationURL": "https://github.com/vercel-labs/agent-browser",
7
+ "options": {
8
+ "version": {
9
+ "type": "string",
10
+ "description": "agent-browser npm package version",
11
+ "default": "0.11.1"
12
+ },
13
+ "username": {
14
+ "type": "string",
15
+ "description": "Container user to install for",
16
+ "default": "automatic"
17
+ }
18
+ },
19
+ "installsAfter": [
20
+ "ghcr.io/devcontainers/features/common-utils:2",
21
+ "ghcr.io/devcontainers/features/node:1"
22
+ ]
23
23
  }
@@ -64,13 +64,6 @@ agent-browser install --with-deps 2>/dev/null || {
64
64
  agent-browser install 2>/dev/null || true
65
65
  }
66
66
 
67
- # Install Playwright Chromium only (not all browsers)
68
- echo "[agent-browser] Installing Playwright Chromium..."
69
- npx playwright install chromium --with-deps 2>/dev/null || {
70
- echo "[agent-browser] WARNING: Playwright chromium install with deps failed, trying without --with-deps"
71
- npx playwright install chromium 2>/dev/null || true
72
- }
73
-
74
67
  echo "[agent-browser] Installed: $(agent-browser --version 2>/dev/null || echo 'unknown')"
75
68
  echo "[agent-browser] Installation complete"
76
69
  echo ""
@@ -1,24 +1,24 @@
1
1
  {
2
- "id": "ast-grep",
3
- "version": "1.0.0",
4
- "name": "ast-grep",
5
- "description": "Installs ast-grep CLI for structural code search, lint, and rewriting using AST matching",
6
- "maintainer": "AnExiledDev",
7
- "documentationURL": "https://ast-grep.github.io/",
8
- "options": {
9
- "version": {
10
- "type": "string",
11
- "description": "@ast-grep/cli npm package version (e.g., 'latest', '0.31.1')",
12
- "default": "latest"
13
- },
14
- "username": {
15
- "type": "string",
16
- "description": "Container user to install for",
17
- "default": "automatic"
18
- }
19
- },
20
- "installsAfter": [
21
- "ghcr.io/devcontainers/features/common-utils:2",
22
- "ghcr.io/devcontainers/features/node:1"
23
- ]
2
+ "id": "ast-grep",
3
+ "version": "1.0.0",
4
+ "name": "ast-grep",
5
+ "description": "Installs ast-grep CLI for structural code search, lint, and rewriting using AST matching",
6
+ "maintainer": "AnExiledDev",
7
+ "documentationURL": "https://ast-grep.github.io/",
8
+ "options": {
9
+ "version": {
10
+ "type": "string",
11
+ "description": "@ast-grep/cli npm package version (e.g., 'latest', '0.31.1')",
12
+ "default": "0.40.5"
13
+ },
14
+ "username": {
15
+ "type": "string",
16
+ "description": "Container user to install for",
17
+ "default": "automatic"
18
+ }
19
+ },
20
+ "installsAfter": [
21
+ "ghcr.io/devcontainers/features/common-utils:2",
22
+ "ghcr.io/devcontainers/features/node:1"
23
+ ]
24
24
  }
@@ -1,16 +1,14 @@
1
1
  {
2
- "id": "biome",
3
- "version": "1.0.0",
4
- "name": "Biome",
5
- "description": "Fast JS/TS/JSON/CSS formatter and linter",
6
- "options": {
7
- "version": {
8
- "type": "string",
9
- "default": "latest",
10
- "description": "Biome version to install"
11
- }
12
- },
13
- "installsAfter": [
14
- "ghcr.io/devcontainers/features/node"
15
- ]
2
+ "id": "biome",
3
+ "version": "1.0.0",
4
+ "name": "Biome",
5
+ "description": "Fast JS/TS/JSON/CSS formatter and linter",
6
+ "options": {
7
+ "version": {
8
+ "type": "string",
9
+ "default": "2.4.2",
10
+ "description": "Biome version to install"
11
+ }
12
+ },
13
+ "installsAfter": ["ghcr.io/devcontainers/features/node"]
16
14
  }
@@ -52,24 +52,41 @@ fi
52
52
 
53
53
  echo "[ccms] Installing for user: ${USERNAME}"
54
54
 
55
+ # === BUILD CACHE ===
56
+ CACHE_DIR="/workspaces/.devcontainer/.build-cache/bin"
57
+
55
58
  # === INSTALL ===
56
59
  REPO_URL="https://github.com/mkusaka/ccms"
57
60
 
58
- if [ "${CCMS_VERSION}" = "latest" ]; then
59
- echo "[ccms] Building from main branch..."
60
- cargo install --git "${REPO_URL}" 2>&1 | tail -5
61
+ if [ -x "${CACHE_DIR}/ccms" ]; then
62
+ echo "[ccms] Using cached binary from ${CACHE_DIR}/ccms"
63
+ cp "${CACHE_DIR}/ccms" /usr/local/bin/ccms
64
+ chmod +x /usr/local/bin/ccms
61
65
  else
62
- echo "[ccms] Building from ref: ${CCMS_VERSION}..."
63
- cargo install --git "${REPO_URL}" --rev "${CCMS_VERSION}" 2>&1 | tail -5
64
- fi
66
+ if [ "${CCMS_VERSION}" = "latest" ]; then
67
+ echo "[ccms] Building from main branch..."
68
+ cargo install --git "${REPO_URL}" --rev f90d259a4476 2>&1 | tail -5
69
+ else
70
+ echo "[ccms] Building from ref: ${CCMS_VERSION}..."
71
+ cargo install --git "${REPO_URL}" --rev "${CCMS_VERSION}" 2>&1 | tail -5
72
+ fi
73
+
74
+ # === ENSURE BINARY IS ON PATH ===
75
+ # cargo install puts binaries in $CARGO_HOME/bin or ~/.cargo/bin
76
+ # Symlink to /usr/local/bin so it's available to all users
77
+ CARGO_BIN="${CARGO_HOME:-$HOME/.cargo}/bin/ccms"
78
+ if [ -f "${CARGO_BIN}" ] && [ ! -f /usr/local/bin/ccms ]; then
79
+ ln -s "${CARGO_BIN}" /usr/local/bin/ccms
80
+ echo "[ccms] Symlinked ${CARGO_BIN} → /usr/local/bin/ccms"
81
+ fi
65
82
 
66
- # === ENSURE BINARY IS ON PATH ===
67
- # cargo install puts binaries in $CARGO_HOME/bin or ~/.cargo/bin
68
- # Symlink to /usr/local/bin so it's available to all users
69
- CARGO_BIN="${CARGO_HOME:-$HOME/.cargo}/bin/ccms"
70
- if [ -f "${CARGO_BIN}" ] && [ ! -f /usr/local/bin/ccms ]; then
71
- ln -s "${CARGO_BIN}" /usr/local/bin/ccms
72
- echo "[ccms] Symlinked ${CARGO_BIN} → /usr/local/bin/ccms"
83
+ # Cache the binary for future rebuilds
84
+ mkdir -p "${CACHE_DIR}"
85
+ CARGO_BIN="${CARGO_HOME:-$HOME/.cargo}/bin/ccms"
86
+ if [ -f "${CARGO_BIN}" ]; then
87
+ cp "${CARGO_BIN}" "${CACHE_DIR}/ccms"
88
+ echo "[ccms] Cached binary to ${CACHE_DIR}/ccms"
89
+ fi
73
90
  fi
74
91
 
75
92
  # === VERIFICATION ===
@@ -1,45 +1,45 @@
1
1
  {
2
- "id": "lsp-servers",
3
- "version": "1.0.0",
4
- "name": "LSP Servers for Claude Code",
5
- "description": "Installs language server binaries for Python (pyright), TypeScript (typescript-language-server), and Go (gopls)",
6
- "maintainer": "AnExiledDev",
7
- "documentationURL": "https://code.claude.com/docs/en/discover-plugins#code-intelligence",
8
- "options": {
9
- "version": {
10
- "type": "string",
11
- "description": "Set to 'none' to skip installation of all LSP servers",
12
- "default": "latest"
13
- },
14
- "pyrightVersion": {
15
- "type": "string",
16
- "description": "Pyright npm package version (e.g., 'latest', '1.1.350')",
17
- "default": "latest"
18
- },
19
- "typescriptLspVersion": {
20
- "type": "string",
21
- "description": "typescript-language-server npm package version (e.g., 'latest', '4.3.0')",
22
- "default": "latest"
23
- },
24
- "typescriptVersion": {
25
- "type": "string",
26
- "description": "TypeScript npm package version (e.g., 'latest', '5.3.0')",
27
- "default": "latest"
28
- },
29
- "goplsVersion": {
30
- "type": "string",
31
- "description": "gopls version (e.g., 'latest', 'v0.16.0')",
32
- "default": "latest"
33
- },
34
- "username": {
35
- "type": "string",
36
- "description": "Container user to install for",
37
- "default": "automatic"
38
- }
39
- },
40
- "installsAfter": [
41
- "ghcr.io/devcontainers/features/common-utils:2",
42
- "ghcr.io/devcontainers/features/node:1",
43
- "ghcr.io/devcontainers/features/go:1"
44
- ]
2
+ "id": "lsp-servers",
3
+ "version": "1.0.0",
4
+ "name": "LSP Servers for Claude Code",
5
+ "description": "Installs language server binaries for Python (pyright), TypeScript (typescript-language-server), and Go (gopls)",
6
+ "maintainer": "AnExiledDev",
7
+ "documentationURL": "https://code.claude.com/docs/en/discover-plugins#code-intelligence",
8
+ "options": {
9
+ "version": {
10
+ "type": "string",
11
+ "description": "Set to 'none' to skip installation of all LSP servers",
12
+ "default": "latest"
13
+ },
14
+ "pyrightVersion": {
15
+ "type": "string",
16
+ "description": "Pyright npm package version (e.g., 'latest', '1.1.350')",
17
+ "default": "1.1.408"
18
+ },
19
+ "typescriptLspVersion": {
20
+ "type": "string",
21
+ "description": "typescript-language-server npm package version (e.g., 'latest', '4.3.0')",
22
+ "default": "5.1.3"
23
+ },
24
+ "typescriptVersion": {
25
+ "type": "string",
26
+ "description": "TypeScript npm package version (e.g., 'latest', '5.3.0')",
27
+ "default": "5.9.3"
28
+ },
29
+ "goplsVersion": {
30
+ "type": "string",
31
+ "description": "gopls version (e.g., 'latest', 'v0.16.0')",
32
+ "default": "latest"
33
+ },
34
+ "username": {
35
+ "type": "string",
36
+ "description": "Container user to install for",
37
+ "default": "automatic"
38
+ }
39
+ },
40
+ "installsAfter": [
41
+ "ghcr.io/devcontainers/features/common-utils:2",
42
+ "ghcr.io/devcontainers/features/node:1",
43
+ "ghcr.io/devcontainers/features/go:1"
44
+ ]
45
45
  }
@@ -35,7 +35,8 @@ if [ -n "${MODEL_URL}" ] && [ ! -d "${FASTEMBED_CACHE}/${MODEL_DIR}" ]; then
35
35
  tar -xzf "${TEMP_TAR}" -C "${FASTEMBED_CACHE}/" 2>/dev/null || true
36
36
  find "${FASTEMBED_CACHE}" -name "._*" -delete 2>/dev/null || true
37
37
  rm -f "${TEMP_TAR}"
38
- chmod -R 777 "${FASTEMBED_CACHE}" 2>/dev/null || true
38
+ chown -R "vscode:vscode" "${FASTEMBED_CACHE}" 2>/dev/null || true
39
+ chmod -R 755 "${FASTEMBED_CACHE}" 2>/dev/null || true
39
40
  echo "[mcp-qdrant] ✓ Embedding model downloaded to ${FASTEMBED_CACHE}/${MODEL_DIR}"
40
41
  else
41
42
  echo "[mcp-qdrant] WARNING: Failed to download embedding model"
@@ -1,21 +1,19 @@
1
1
  {
2
- "id": "ruff",
3
- "version": "1.0.0",
4
- "name": "Ruff",
5
- "description": "Fast Python linter and formatter (replaces Black + Flake8)",
6
- "options": {
7
- "version": {
8
- "type": "string",
9
- "default": "latest",
10
- "description": "Ruff version to install"
11
- },
12
- "username": {
13
- "type": "string",
14
- "default": "automatic",
15
- "description": "Container user to install for"
16
- }
17
- },
18
- "installsAfter": [
19
- "ghcr.io/devcontainers-extra/features/uv"
20
- ]
2
+ "id": "ruff",
3
+ "version": "1.0.0",
4
+ "name": "Ruff",
5
+ "description": "Fast Python linter and formatter (replaces Black + Flake8)",
6
+ "options": {
7
+ "version": {
8
+ "type": "string",
9
+ "default": "0.15.1",
10
+ "description": "Ruff version to install"
11
+ },
12
+ "username": {
13
+ "type": "string",
14
+ "default": "automatic",
15
+ "description": "Container user to install for"
16
+ }
17
+ },
18
+ "installsAfter": ["ghcr.io/devcontainers-extra/features/uv"]
21
19
  }
@@ -11,9 +11,9 @@ fi
11
11
 
12
12
  echo "Installing tmux for Claude Code Agent Teams..."
13
13
 
14
- # Install tmux via apt
14
+ # Install tmux and inotify-tools via apt
15
15
  apt-get update
16
- apt-get install -y tmux
16
+ apt-get install -y tmux inotify-tools
17
17
 
18
18
  # Install Catppuccin theme (shallow clone for fast builds)
19
19
  CATPPUCCIN_DIR="/usr/share/tmux/plugins/catppuccin"
@@ -0,0 +1,81 @@
1
+ # auto-formatter
2
+
3
+ Claude Code plugin that batch-formats edited files when Claude finishes responding. Reads file paths collected by the `code-directive` plugin's `collect-edited-files.py` hook and formats each file based on its extension.
4
+
5
+ ## What It Does
6
+
7
+ When Claude stops responding, the plugin reads the session's list of edited files and formats each one using the appropriate tool:
8
+
9
+ | Language / File Type | Formatter | Fallback |
10
+ |----------------------|-----------|----------|
11
+ | Python (`.py`, `.pyi`) | [ruff format](https://docs.astral.sh/ruff/) | [black](https://github.com/psf/black) |
12
+ | Go (`.go`) | gofmt (bundled with Go) | — |
13
+ | JS/TS/CSS/JSON/GraphQL/HTML (`.js`, `.jsx`, `.ts`, `.tsx`, `.css`, `.json`, `.jsonc`, `.graphql`, `.gql`, `.html`, `.vue`, `.svelte`, `.astro`) | [biome](https://biomejs.dev/) check --write | — |
14
+ | Shell (`.sh`, `.bash`, `.zsh`, `.mksh`, `.bats`) | [shfmt](https://github.com/mvdan/sh) | — |
15
+ | Markdown/YAML/TOML (`.md`, `.markdown`, `.yaml`, `.yml`, `.toml`) | [dprint](https://dprint.dev/) | — |
16
+ | Dockerfile | dprint | — |
17
+ | Rust (`.rs`) | rustfmt (bundled with Rust) | — |
18
+
19
+ All formatting is non-blocking. Missing tools are silently skipped. The plugin always exits 0 — it will never interrupt Claude.
20
+
21
+ ## How It Works
22
+
23
+ ### Hook Lifecycle
24
+
25
+ ```
26
+ code-directive's collect-edited-files.py (PostToolUse on Edit/Write)
27
+
28
+ └─→ Appends edited file path to /tmp/claude-edited-files-{session_id}
29
+
30
+ │ ... Claude keeps working ...
31
+
32
+ Claude stops responding (Stop event)
33
+
34
+ └─→ format-on-stop.py reads the temp file, deduplicates paths,
35
+ formats each file by extension, then cleans up the temp file
36
+ ```
37
+
38
+ ### Dependency on code-directive
39
+
40
+ This plugin does **not** collect file paths itself. It relies on the `code-directive` plugin's `collect-edited-files.py` PostToolUse hook to write edited file paths to `/tmp/claude-edited-files-{session_id}`. Both plugins must be enabled for formatting to work.
41
+
42
+ ### Biome Discovery
43
+
44
+ Biome is resolved in this order:
45
+ 1. **Project-local**: walks up from the edited file looking for `node_modules/.bin/biome`
46
+ 2. **Global**: checks PATH via `which biome`
47
+
48
+ ### dprint Configuration
49
+
50
+ The dprint formatter looks for a config file at `/usr/local/share/dprint/dprint.json`. If this file doesn't exist, dprint formatting is skipped.
51
+
52
+ ### Timeouts
53
+
54
+ | Scope | Timeout |
55
+ |-------|---------|
56
+ | Entire Stop hook | 15s |
57
+ | Individual tool invocation | 10-12s |
58
+
59
+ ## Conflict Warning
60
+
61
+ Do **not** enable this plugin alongside `auto-code-quality`. That plugin bundles its own formatter with the same functionality. Enabling both won't corrupt data (different temp file prefixes: `claude-edited-files-*` vs `claude-cq-*`), but files would be formatted twice.
62
+
63
+ ## Plugin Structure
64
+
65
+ ```
66
+ auto-formatter/
67
+ ├── .claude-plugin/
68
+ │ └── plugin.json # Plugin metadata
69
+ ├── hooks/
70
+ │ └── hooks.json # Stop hook registration
71
+ ├── scripts/
72
+ │ └── format-on-stop.py # Batch formatter (Stop)
73
+ └── README.md # This file
74
+ ```
75
+
76
+ ## Requirements
77
+
78
+ - Python 3.11+
79
+ - Claude Code with plugin hook support
80
+ - `code-directive` plugin enabled (provides the file path collector)
81
+ - Install the formatting tools for the languages you work with — everything is optional
@@ -0,0 +1,92 @@
1
+ # auto-linter
2
+
3
+ Claude Code plugin that batch-lints edited files when Claude finishes responding. Reads file paths collected by the `code-directive` plugin's `collect-edited-files.py` hook and lints each file using the appropriate tool. Lint results are returned as advisory context — never blocking.
4
+
5
+ ## What It Does
6
+
7
+ When Claude stops responding, the plugin reads the session's list of edited files, lints each one, and injects any warnings as `additionalContext` so Claude sees them on its next response.
8
+
9
+ | Language / File Type | Linter(s) |
10
+ |----------------------|-----------|
11
+ | Python (`.py`, `.pyi`) | [pyright](https://github.com/microsoft/pyright) (type checking) + [ruff check](https://docs.astral.sh/ruff/) (style/correctness) |
12
+ | JS/TS/CSS/GraphQL (`.js`, `.jsx`, `.ts`, `.tsx`, `.css`, `.graphql`, `.gql`) | [biome lint](https://biomejs.dev/) |
13
+ | Shell (`.sh`, `.bash`, `.zsh`, `.mksh`, `.bats`) | [shellcheck](https://github.com/koalaman/shellcheck) |
14
+ | Go (`.go`) | go vet (bundled with Go) |
15
+ | Dockerfile | [hadolint](https://github.com/hadolint/hadolint) |
16
+ | Rust (`.rs`) | [clippy](https://doc.rust-lang.org/clippy/) (via cargo) |
17
+
18
+ All linting is non-blocking. Missing tools are silently skipped. The plugin always exits 0 and returns warnings as `additionalContext` — it will never interrupt Claude.
19
+
20
+ ## How It Works
21
+
22
+ ### Hook Lifecycle
23
+
24
+ ```
25
+ code-directive's collect-edited-files.py (PostToolUse on Edit/Write)
26
+
27
+ └─→ Appends edited file path to /tmp/claude-lint-files-{session_id}
28
+
29
+ │ ... Claude keeps working ...
30
+
31
+ Claude stops responding (Stop event)
32
+
33
+ └─→ lint-file.py reads the temp file, deduplicates paths,
34
+ lints each file by extension, groups results by linter,
35
+ injects warnings as additionalContext, then cleans up
36
+ ```
37
+
38
+ ### Dependency on code-directive
39
+
40
+ This plugin relies on the `code-directive` plugin's `collect-edited-files.py` PostToolUse hook to write edited file paths to `/tmp/claude-lint-files-{session_id}`. Both plugins must be enabled for linting to work.
41
+
42
+ ### Output Format
43
+
44
+ Lint results are grouped by linter and returned as `additionalContext`. Each file shows up to 5 issues with severity, line number, and message:
45
+
46
+ ```
47
+ [Auto-linter] Pyright results:
48
+ example.py: 2 issue(s)
49
+ ✗ Line 15: Cannot assign type "str" to declared type "int"
50
+ ! Line 42: Variable "x" is not defined
51
+
52
+ [Auto-linter] Ruff results:
53
+ example.py: 1 issue(s)
54
+ ! Line 8: [F401] `os` imported but unused
55
+ ```
56
+
57
+ ### Biome Discovery
58
+
59
+ Biome is resolved in this order:
60
+ 1. **Project-local**: walks up from the edited file looking for `node_modules/.bin/biome`
61
+ 2. **Global**: checks PATH via `which biome`
62
+
63
+ ### Timeouts
64
+
65
+ | Scope | Timeout |
66
+ |-------|---------|
67
+ | Entire Stop hook | 60s |
68
+ | Individual tool invocation | 10s |
69
+
70
+ ## Conflict Warning
71
+
72
+ Do **not** enable this plugin alongside `auto-code-quality`. That plugin bundles its own linter with the same functionality. Enabling both won't corrupt data (different temp file prefixes: `claude-lint-files-*` vs `claude-cq-*`), but files would be linted twice.
73
+
74
+ ## Plugin Structure
75
+
76
+ ```
77
+ auto-linter/
78
+ ├── .claude-plugin/
79
+ │ └── plugin.json # Plugin metadata
80
+ ├── hooks/
81
+ │ └── hooks.json # Stop hook registration
82
+ ├── scripts/
83
+ │ └── lint-file.py # Batch linter (Stop)
84
+ └── README.md # This file
85
+ ```
86
+
87
+ ## Requirements
88
+
89
+ - Python 3.11+
90
+ - Claude Code with plugin hook support
91
+ - `code-directive` plugin enabled (provides the file path collector)
92
+ - Install the linting tools for the languages you work with — everything is optional