codeforge-dev 1.14.2 → 2.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.
- package/{.devcontainer/config/defaults → .codeforge/config}/ccstatusline-settings.json +44 -6
- package/{.devcontainer/config/defaults → .codeforge/config}/main-system-prompt.md +14 -6
- package/.codeforge/config/orchestrator-system-prompt.md +333 -0
- package/{.devcontainer/config/defaults → .codeforge/config}/settings.json +3 -1
- package/{.devcontainer/config → .codeforge}/file-manifest.json +15 -9
- package/{.devcontainer → .codeforge/scripts}/connect-external-terminal.sh +3 -1
- package/.devcontainer/.env.example +5 -5
- package/.devcontainer/.secrets.example +3 -0
- package/.devcontainer/CHANGELOG.md +242 -0
- package/.devcontainer/CLAUDE.md +129 -22
- package/.devcontainer/README.md +34 -19
- package/.devcontainer/devcontainer.json +28 -10
- package/.devcontainer/features/agent-browser/install.sh +2 -0
- package/.devcontainer/features/ast-grep/install.sh +2 -0
- package/.devcontainer/features/biome/install.sh +2 -0
- package/.devcontainer/features/ccburn/install.sh +2 -0
- package/.devcontainer/features/ccms/install.sh +2 -0
- package/.devcontainer/features/ccstatusline/README.md +7 -6
- package/.devcontainer/features/ccstatusline/install.sh +9 -4
- package/.devcontainer/features/ccusage/install.sh +2 -0
- package/.devcontainer/features/chromaterm/chromaterm.yml +2 -2
- package/.devcontainer/features/chromaterm/install.sh +2 -0
- package/.devcontainer/features/claude-code-native/README.md +47 -0
- package/.devcontainer/features/claude-code-native/devcontainer-feature.json +29 -0
- package/.devcontainer/features/claude-code-native/install.sh +131 -0
- package/.devcontainer/features/claude-monitor/install.sh +2 -0
- package/.devcontainer/features/claude-session-dashboard/README.md +2 -2
- package/.devcontainer/features/claude-session-dashboard/install.sh +2 -0
- package/.devcontainer/features/dprint/install.sh +2 -0
- package/.devcontainer/features/hadolint/install.sh +2 -0
- package/.devcontainer/features/kitty-terminfo/README.md +3 -1
- package/.devcontainer/features/kitty-terminfo/install.sh +2 -0
- package/.devcontainer/features/lsp-servers/install.sh +2 -0
- package/.devcontainer/features/mcp-qdrant/CHANGES.md +3 -3
- package/.devcontainer/features/mcp-qdrant/README.md +1 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +1 -1
- package/.devcontainer/features/mcp-qdrant/install.sh +9 -2
- package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +9 -2
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +1 -1
- package/.devcontainer/features/notify-hook/install.sh +2 -0
- package/.devcontainer/features/ruff/install.sh +2 -0
- package/.devcontainer/features/shellcheck/install.sh +2 -0
- package/.devcontainer/features/shfmt/install.sh +2 -0
- package/.devcontainer/features/tmux/README.md +3 -3
- package/.devcontainer/features/tmux/install.sh +3 -1
- package/.devcontainer/features/tree-sitter/install.sh +2 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +27 -11
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/README.md +23 -4
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/claude-guide.md +4 -4
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/documenter.md +254 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/implementer.md +260 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/investigator.md +255 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/tester.md +304 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/README.md +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/advisory-test-runner.py +4 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +2 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/README.md +125 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/pr-review/SKILL.md +325 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/ship/SKILL.md +314 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/.claude-plugin/plugin.json +5 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/README.md +52 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/skills/ps/SKILL.md +37 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected-bash.py +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/README.md +30 -14
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/hooks/hooks.json +13 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/collect-session-edits.py +44 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/commit-reminder.py +89 -10
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/README.md +19 -11
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/scripts/skill-suggester.py +476 -282
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/SKILL.md +227 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/manual-worktree-commands.md +238 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/parallel-workflow-patterns.md +228 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/scripts/ticket-linker.py +2 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/README.md +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py +3 -2
- package/.devcontainer/scripts/check-setup.sh +5 -3
- package/.devcontainer/scripts/preflight.sh +113 -0
- package/.devcontainer/scripts/setup-aliases.sh +13 -8
- package/.devcontainer/scripts/setup-auth.sh +46 -0
- package/.devcontainer/scripts/setup-config.sh +29 -10
- package/.devcontainer/scripts/setup-migrate-claude.sh +80 -0
- package/.devcontainer/scripts/setup-migrate-codeforge.sh +60 -0
- package/.devcontainer/scripts/setup-plugins.sh +3 -1
- package/.devcontainer/scripts/setup-projects.sh +3 -1
- package/.devcontainer/scripts/setup-terminal.sh +3 -1
- package/.devcontainer/scripts/setup-update-claude.sh +22 -27
- package/.devcontainer/scripts/setup.sh +57 -5
- package/LICENSE.txt +14 -0
- package/README.md +79 -5
- package/package.json +2 -1
- package/setup.js +392 -21
- package/.devcontainer/docs/configuration-reference.md +0 -93
- package/.devcontainer/docs/keybindings.md +0 -100
- package/.devcontainer/docs/optional-features.md +0 -64
- package/.devcontainer/docs/plugins.md +0 -176
- package/.devcontainer/docs/troubleshooting.md +0 -128
- package/.devcontainer/scripts/setup-symlink-claude.sh +0 -36
- /package/{.devcontainer/config/defaults → .codeforge/config}/keybindings.json +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/rules/session-search.md +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/rules/spec-workflow.md +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/rules/workspace-scope.md +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/writing-system-prompt.md +0 -0
- /package/{.devcontainer → .codeforge/scripts}/connect-external-terminal.ps1 +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ps
|
|
3
|
+
description: Inject a behavioral prompt snippet by name.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: "[snippet-name]"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /ps — Prompt Snippets
|
|
9
|
+
|
|
10
|
+
Apply the prompt snippet matching `$ARGUMENTS` from the table below. Follow its instruction for the **remainder of this conversation** unless the user explicitly overrides it.
|
|
11
|
+
|
|
12
|
+
If `$ARGUMENTS` does not match any snippet name, list all available snippets and ask the user to pick one.
|
|
13
|
+
|
|
14
|
+
## Available Snippets
|
|
15
|
+
|
|
16
|
+
| Snippet | Instruction |
|
|
17
|
+
|---------|-------------|
|
|
18
|
+
| `noaction` | Investigate and report only. Take no action — no edits, no commands, no file writes. |
|
|
19
|
+
| `brief` | Be concise. Short answers, no filler, no preamble. Answer the question and stop. |
|
|
20
|
+
| `plan` | Build a plan before taking any action. Do not implement until the plan is explicitly approved. |
|
|
21
|
+
| `go` | Proceed without asking for confirmation. Use your best judgment on all decisions. |
|
|
22
|
+
| `review` | Review and audit only. Report findings with specific file paths and line numbers. Do not modify anything. |
|
|
23
|
+
| `ship` | Commit all staged changes, push to remote, and create a pull request. |
|
|
24
|
+
| `deep` | Be thorough and comprehensive. Investigate in depth, consider edge cases, leave no stone unturned. |
|
|
25
|
+
| `hold` | Complete the current task but do not commit, push, or publish. Await my review before any git operations. |
|
|
26
|
+
| `recall` | Search past session history with `ccms --no-color --project "$(pwd)"` to find prior decisions, discussions, and context relevant to the current task. Summarize what you find before proceeding. |
|
|
27
|
+
| `wait` | When done, stop. Do not suggest next steps, ask follow-up questions, or continue with related work. Await further instructions. |
|
|
28
|
+
|
|
29
|
+
## Composing Snippets
|
|
30
|
+
|
|
31
|
+
Multiple snippets can be applied in one invocation by separating names with spaces:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
/ps noaction brief
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Apply all matching snippets. If instructions conflict, the **last snippet wins** for that specific behavior.
|
|
@@ -36,7 +36,7 @@ PROTECTED_PATTERNS = [
|
|
|
36
36
|
(r"\.crt$", "Blocked: .crt certificate files should not be edited directly"),
|
|
37
37
|
(r"\.p12$", "Blocked: .p12 files contain sensitive cryptographic material"),
|
|
38
38
|
(r"\.pfx$", "Blocked: .pfx files contain sensitive cryptographic material"),
|
|
39
|
-
(r"(^|/)credentials\.json$", "Blocked: credentials.json contains secrets"),
|
|
39
|
+
(r"(^|/)\.?credentials\.json$", "Blocked: credentials.json contains secrets"),
|
|
40
40
|
(r"(^|/)secrets\.yaml$", "Blocked: secrets.yaml contains secrets"),
|
|
41
41
|
(r"(^|/)secrets\.yml$", "Blocked: secrets.yml contains secrets"),
|
|
42
42
|
(r"(^|/)secrets\.json$", "Blocked: secrets.json contains secrets"),
|
|
@@ -40,7 +40,7 @@ PROTECTED_PATTERNS = [
|
|
|
40
40
|
(r"\.p12$", "Blocked: .p12 files contain sensitive cryptographic material"),
|
|
41
41
|
(r"\.pfx$", "Blocked: .pfx files contain sensitive cryptographic material"),
|
|
42
42
|
# Credential files
|
|
43
|
-
(r"(^|/)credentials\.json$", "Blocked: credentials.json contains secrets"),
|
|
43
|
+
(r"(^|/)\.?credentials\.json$", "Blocked: credentials.json contains secrets"),
|
|
44
44
|
(r"(^|/)secrets\.yaml$", "Blocked: secrets.yaml contains secrets"),
|
|
45
45
|
(r"(^|/)secrets\.yml$", "Blocked: secrets.yml contains secrets"),
|
|
46
46
|
(r"(^|/)secrets\.json$", "Blocked: secrets.json contains secrets"),
|
|
@@ -4,13 +4,14 @@ Claude Code plugin that injects contextual information at session boundaries. Pr
|
|
|
4
4
|
|
|
5
5
|
## What It Does
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Four hooks that run automatically at session lifecycle boundaries:
|
|
8
8
|
|
|
9
9
|
| Phase | Script | What It Injects |
|
|
10
10
|
|-------|--------|-----------------|
|
|
11
11
|
| Session start | `git-state-injector.py` | Current branch, status, recent commits, uncommitted changes |
|
|
12
12
|
| Session start | `todo-harvester.py` | Count and top 10 TODO/FIXME/HACK/XXX markers in the codebase |
|
|
13
|
-
|
|
|
13
|
+
| PostToolUse (Edit/Write) | `collect-session-edits.py` | Tracks which files the session modified (tmp file) |
|
|
14
|
+
| Stop | `commit-reminder.py` | Advisory about uncommitted changes (only if session edited files) |
|
|
14
15
|
|
|
15
16
|
All hooks are non-blocking and cap their output to prevent context bloat.
|
|
16
17
|
|
|
@@ -31,12 +32,19 @@ Scans source files for tech debt markers and injects a summary:
|
|
|
31
32
|
- Shows total count plus top 10 items
|
|
32
33
|
- Output capped at 800 characters
|
|
33
34
|
|
|
35
|
+
### Edit Tracking
|
|
36
|
+
|
|
37
|
+
Lightweight PostToolUse hook on Edit/Write that records file paths to `/tmp/claude-session-edits-{session_id}`. Used by the commit reminder to determine if this session actually modified files.
|
|
38
|
+
|
|
34
39
|
### Commit Reminder
|
|
35
40
|
|
|
36
|
-
Fires when Claude stops responding
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
41
|
+
Fires when Claude stops responding, using tiered logic based on change significance:
|
|
42
|
+
- Checks the session edit tracker — skips entirely if session was read-only
|
|
43
|
+
- **Meaningful changes** (3+ files, 2+ source files, or test files): suggests committing via advisory `systemMessage`
|
|
44
|
+
- **Small changes** (1-2 non-source files): silent, no output
|
|
45
|
+
- Output wrapped in `<system-reminder>` tags — advisory only, never blocks
|
|
46
|
+
- Instructs Claude not to commit without explicit user approval
|
|
47
|
+
- Uses a guard flag to prevent infinite loops
|
|
40
48
|
|
|
41
49
|
## How It Works
|
|
42
50
|
|
|
@@ -58,6 +66,12 @@ Session starts
|
|
|
58
66
|
| +-> Injects count + top 10 as additionalContext
|
|
59
67
|
|
|
|
60
68
|
| ... Claude works ...
|
|
69
|
+
| |
|
|
70
|
+
| +-> PostToolUse (Edit|Write) fires
|
|
71
|
+
| |
|
|
72
|
+
| +-> collect-session-edits.py
|
|
73
|
+
| |
|
|
74
|
+
| +-> Appends file path to /tmp/claude-session-edits-{session_id}
|
|
61
75
|
|
|
|
62
76
|
Claude stops responding
|
|
63
77
|
|
|
|
@@ -65,14 +79,14 @@ Claude stops responding
|
|
|
65
79
|
|
|
|
66
80
|
+-> commit-reminder.py
|
|
67
81
|
|
|
|
68
|
-
+->
|
|
69
|
-
+->
|
|
70
|
-
+->
|
|
82
|
+
+-> Session edited files? (checks tmp file)
|
|
83
|
+
+-> No edits this session? -> Silent (no output)
|
|
84
|
+
+-> Has edits + uncommitted changes? -> Inject advisory systemMessage
|
|
71
85
|
```
|
|
72
86
|
|
|
73
87
|
### Exit Code Behavior
|
|
74
88
|
|
|
75
|
-
All
|
|
89
|
+
All four scripts exit 0 (advisory only). They never block operations.
|
|
76
90
|
|
|
77
91
|
### Error Handling
|
|
78
92
|
|
|
@@ -88,6 +102,7 @@ All three scripts exit 0 (advisory only). They never block operations.
|
|
|
88
102
|
|------|---------|
|
|
89
103
|
| Git state injection | 10s |
|
|
90
104
|
| TODO harvesting | 8s |
|
|
105
|
+
| Edit tracking | 3s |
|
|
91
106
|
| Commit reminder | 8s |
|
|
92
107
|
|
|
93
108
|
## Installation
|
|
@@ -125,11 +140,12 @@ session-context/
|
|
|
125
140
|
+-- .claude-plugin/
|
|
126
141
|
| +-- plugin.json # Plugin metadata
|
|
127
142
|
+-- hooks/
|
|
128
|
-
| +-- hooks.json
|
|
143
|
+
| +-- hooks.json # Hook registrations (SessionStart + PostToolUse + Stop)
|
|
129
144
|
+-- scripts/
|
|
130
|
-
| +-- git-state-injector.py
|
|
131
|
-
| +-- todo-harvester.py
|
|
132
|
-
| +--
|
|
145
|
+
| +-- git-state-injector.py # Git state context (SessionStart)
|
|
146
|
+
| +-- todo-harvester.py # Tech debt markers (SessionStart)
|
|
147
|
+
| +-- collect-session-edits.py # Edit tracking (PostToolUse)
|
|
148
|
+
| +-- commit-reminder.py # Uncommitted changes advisory (Stop)
|
|
133
149
|
+-- README.md # This file
|
|
134
150
|
```
|
|
135
151
|
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Context injection at session boundaries: git state, TODO harvesting, commit reminders",
|
|
2
|
+
"description": "Context injection at session boundaries: git state, TODO harvesting, edit tracking, commit reminders",
|
|
3
3
|
"hooks": {
|
|
4
|
+
"PostToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "Edit|Write",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/collect-session-edits.py",
|
|
11
|
+
"timeout": 3
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
],
|
|
4
16
|
"SessionStart": [
|
|
5
17
|
{
|
|
6
18
|
"matcher": "",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Collect edited file paths for session-aware Stop hooks.
|
|
4
|
+
|
|
5
|
+
Lightweight PostToolUse hook that appends the edited file path
|
|
6
|
+
to a session-scoped temp file. The commit-reminder Stop hook
|
|
7
|
+
reads this file to determine if the session modified any files.
|
|
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-session-edits-{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()
|
package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/commit-reminder.py
CHANGED
|
@@ -2,21 +2,31 @@
|
|
|
2
2
|
"""
|
|
3
3
|
Commit reminder — Stop hook that advises about uncommitted changes.
|
|
4
4
|
|
|
5
|
-
On Stop, checks
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
On Stop, checks whether this session edited any files (via the tmp file
|
|
6
|
+
written by collect-session-edits.py) and whether uncommitted changes exist.
|
|
7
|
+
Uses tiered logic: meaningful changes (3+ files, 2+ source files, or test
|
|
8
|
+
files touched) get an advisory suggestion; small changes are silent.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
before finishing. The stop_hook_active guard prevents infinite loops.
|
|
10
|
+
Output is a systemMessage wrapped in <system-reminder> tags — advisory only,
|
|
11
|
+
never blocks. The stop_hook_active guard prevents loops.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
|
+
import os
|
|
15
16
|
import subprocess
|
|
16
17
|
import sys
|
|
17
18
|
|
|
18
19
|
GIT_CMD_TIMEOUT = 5
|
|
19
20
|
|
|
21
|
+
# Extensions considered source code (not config/docs)
|
|
22
|
+
SOURCE_EXTS = frozenset((
|
|
23
|
+
".py", ".ts", ".tsx", ".js", ".jsx", ".go", ".rs",
|
|
24
|
+
".java", ".kt", ".rb", ".svelte", ".vue", ".c", ".cpp", ".h",
|
|
25
|
+
))
|
|
26
|
+
|
|
27
|
+
# Patterns that indicate test files
|
|
28
|
+
TEST_PATTERNS = ("test_", "_test.", ".test.", ".spec.", "/tests/", "/test/")
|
|
29
|
+
|
|
20
30
|
|
|
21
31
|
def _run_git(args: list[str]) -> str | None:
|
|
22
32
|
"""Run a git command and return stdout, or None on any failure."""
|
|
@@ -34,6 +44,58 @@ def _run_git(args: list[str]) -> str | None:
|
|
|
34
44
|
return None
|
|
35
45
|
|
|
36
46
|
|
|
47
|
+
def _read_session_edits(session_id: str) -> list[str]:
|
|
48
|
+
"""Read the list of files edited this session."""
|
|
49
|
+
tmp_path = f"/tmp/claude-session-edits-{session_id}"
|
|
50
|
+
try:
|
|
51
|
+
with open(tmp_path, "r") as f:
|
|
52
|
+
raw = f.read()
|
|
53
|
+
except OSError:
|
|
54
|
+
return []
|
|
55
|
+
|
|
56
|
+
seen: set[str] = set()
|
|
57
|
+
result: list[str] = []
|
|
58
|
+
for line in raw.strip().splitlines():
|
|
59
|
+
path = line.strip()
|
|
60
|
+
if path and path not in seen:
|
|
61
|
+
seen.add(path)
|
|
62
|
+
result.append(path)
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _is_source_file(path: str) -> bool:
|
|
67
|
+
"""Check if a file path looks like source code."""
|
|
68
|
+
_, ext = os.path.splitext(path)
|
|
69
|
+
return ext.lower() in SOURCE_EXTS
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _is_test_file(path: str) -> bool:
|
|
73
|
+
"""Check if a file path looks like a test file."""
|
|
74
|
+
lower = path.lower()
|
|
75
|
+
return any(pattern in lower for pattern in TEST_PATTERNS)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _is_meaningful(edited_files: list[str]) -> bool:
|
|
79
|
+
"""Determine if the session's edits are meaningful enough to suggest committing.
|
|
80
|
+
|
|
81
|
+
Meaningful when any of:
|
|
82
|
+
- 3+ total files edited
|
|
83
|
+
- 2+ source code files edited
|
|
84
|
+
- Any test files edited (suggests feature work)
|
|
85
|
+
"""
|
|
86
|
+
if len(edited_files) >= 3:
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
source_count = sum(1 for f in edited_files if _is_source_file(f))
|
|
90
|
+
if source_count >= 2:
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
if any(_is_test_file(f) for f in edited_files):
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
|
|
37
99
|
def main():
|
|
38
100
|
try:
|
|
39
101
|
input_data = json.load(sys.stdin)
|
|
@@ -44,7 +106,20 @@ def main():
|
|
|
44
106
|
if input_data.get("stop_hook_active"):
|
|
45
107
|
sys.exit(0)
|
|
46
108
|
|
|
47
|
-
#
|
|
109
|
+
# Only fire if this session actually edited files
|
|
110
|
+
session_id = input_data.get("session_id", "")
|
|
111
|
+
if not session_id:
|
|
112
|
+
sys.exit(0)
|
|
113
|
+
|
|
114
|
+
edited_files = _read_session_edits(session_id)
|
|
115
|
+
if not edited_files:
|
|
116
|
+
sys.exit(0)
|
|
117
|
+
|
|
118
|
+
# Small changes — stay silent
|
|
119
|
+
if not _is_meaningful(edited_files):
|
|
120
|
+
sys.exit(0)
|
|
121
|
+
|
|
122
|
+
# Check if there are any uncommitted changes
|
|
48
123
|
porcelain = _run_git(["status", "--porcelain"])
|
|
49
124
|
if porcelain is None:
|
|
50
125
|
# Not a git repo or git not available
|
|
@@ -79,11 +154,15 @@ def main():
|
|
|
79
154
|
summary = ", ".join(parts) if parts else f"{total} changed"
|
|
80
155
|
|
|
81
156
|
message = (
|
|
82
|
-
|
|
83
|
-
"
|
|
157
|
+
"<system-reminder>\n"
|
|
158
|
+
f"[Session Summary] Modified {total} files ({summary}). "
|
|
159
|
+
"This looks like a complete unit of work.\n"
|
|
160
|
+
"Consider asking the user if they would like to commit.\n"
|
|
161
|
+
"Do NOT commit without explicit user approval.\n"
|
|
162
|
+
"</system-reminder>"
|
|
84
163
|
)
|
|
85
164
|
|
|
86
|
-
json.dump({"
|
|
165
|
+
json.dump({"systemMessage": message}, sys.stdout)
|
|
87
166
|
sys.exit(0)
|
|
88
167
|
|
|
89
168
|
|
package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/.claude-plugin/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skill-engine",
|
|
3
|
-
"description": "
|
|
3
|
+
"description": "22 coding knowledge packs with auto-suggestion for frameworks, tools, and patterns",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "AnExiledDev"
|
|
6
6
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# skill-engine
|
|
2
2
|
|
|
3
|
-
Claude Code plugin that provides
|
|
3
|
+
Claude Code plugin that provides 22 coding knowledge packs (skills) with automatic suggestion based on user prompts. Each skill contains domain-specific instructions and reference material that Claude loads on demand via the `/skill` command.
|
|
4
4
|
|
|
5
5
|
## What It Does
|
|
6
6
|
|
|
7
7
|
Two capabilities:
|
|
8
8
|
|
|
9
|
-
1. **Skill library** —
|
|
9
|
+
1. **Skill library** — 22 skills covering frameworks, tools, and development patterns. Each skill is a structured knowledge pack with a `SKILL.md` entrypoint and `references/` subdirectory containing detailed reference docs.
|
|
10
10
|
|
|
11
11
|
2. **Auto-suggestion** — A `UserPromptSubmit` hook watches user prompts for keyword matches and suggests relevant skills as context, so Claude can proactively load the right knowledge.
|
|
12
12
|
|
|
@@ -35,14 +35,18 @@ Two capabilities:
|
|
|
35
35
|
| svelte5 | Runes, reactivity, components, SPA routing, LayerCake |
|
|
36
36
|
| team | Agent team orchestration, parallel workstreams, task coordination |
|
|
37
37
|
| testing | Testing frameworks, FastAPI testing, Svelte testing |
|
|
38
|
+
| worktree | Git worktree lifecycle, EnterWorktree, parallel development |
|
|
38
39
|
|
|
39
40
|
### Auto-Suggestion
|
|
40
41
|
|
|
41
|
-
The `skill-suggester.py` hook
|
|
42
|
+
The `skill-suggester.py` hook scores user prompts against keyword maps for each skill using weighted matching. Suggestions are ranked by confidence and capped at **3 skills maximum** per prompt.
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
- **Phrases** —
|
|
45
|
-
- **Terms** —
|
|
44
|
+
Each skill defines:
|
|
45
|
+
- **Phrases** — `(substring, weight)` tuples. Weight 0.0–1.0 reflects specificity (e.g., `("build a fastapi app", 1.0)` vs `("pydantic model", 0.3)`)
|
|
46
|
+
- **Terms** — Whole-word regex patterns, all scored at 0.6
|
|
47
|
+
- **Negative patterns** — Substrings that instantly disqualify a skill (e.g., `"pydanticai"` suppresses `fastapi`)
|
|
48
|
+
- **Context guards** — Required co-occurring words for low-confidence matches. When the best score is below 0.6, at least one guard word must appear in the prompt or the match is dropped
|
|
49
|
+
- **Priority** — Integer tie-breaker (10 = commands, 7 = tech, 5 = patterns, 3 = generic)
|
|
46
50
|
|
|
47
51
|
## How It Works
|
|
48
52
|
|
|
@@ -55,9 +59,12 @@ User submits a prompt
|
|
|
55
59
|
|
|
|
56
60
|
+-> skill-suggester.py
|
|
57
61
|
|
|
|
58
|
-
+->
|
|
59
|
-
+->
|
|
60
|
-
+->
|
|
62
|
+
+-> Check negative patterns (instant disqualify)
|
|
63
|
+
+-> Score phrases (best weight) and terms (0.6)
|
|
64
|
+
+-> Enforce context guards on low-confidence matches
|
|
65
|
+
+-> Rank by score desc, priority desc
|
|
66
|
+
+-> Return top 3 as additionalContext
|
|
67
|
+
+-> No matches above threshold? -> Silent (no output)
|
|
61
68
|
```
|
|
62
69
|
|
|
63
70
|
### Skill Structure
|
|
@@ -126,9 +133,9 @@ skill-engine/
|
|
|
126
133
|
+-- hooks/
|
|
127
134
|
| +-- hooks.json # UserPromptSubmit hook registration
|
|
128
135
|
+-- scripts/
|
|
129
|
-
| +-- skill-suggester.py #
|
|
136
|
+
| +-- skill-suggester.py # Weighted scoring skill auto-suggestion
|
|
130
137
|
+-- skills/
|
|
131
|
-
| +-- api-design/ #
|
|
138
|
+
| +-- api-design/ # 22 skill directories
|
|
132
139
|
| +-- ast-grep-patterns/
|
|
133
140
|
| +-- claude-agent-sdk/
|
|
134
141
|
| +-- claude-code-headless/
|
|
@@ -149,6 +156,7 @@ skill-engine/
|
|
|
149
156
|
| +-- svelte5/
|
|
150
157
|
| +-- team/
|
|
151
158
|
| +-- testing/
|
|
159
|
+
| +-- worktree/
|
|
152
160
|
+-- README.md # This file
|
|
153
161
|
```
|
|
154
162
|
|