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.
Files changed (106) hide show
  1. package/{.devcontainer/config/defaults → .codeforge/config}/ccstatusline-settings.json +44 -6
  2. package/{.devcontainer/config/defaults → .codeforge/config}/main-system-prompt.md +14 -6
  3. package/.codeforge/config/orchestrator-system-prompt.md +333 -0
  4. package/{.devcontainer/config/defaults → .codeforge/config}/settings.json +3 -1
  5. package/{.devcontainer/config → .codeforge}/file-manifest.json +15 -9
  6. package/{.devcontainer → .codeforge/scripts}/connect-external-terminal.sh +3 -1
  7. package/.devcontainer/.env.example +5 -5
  8. package/.devcontainer/.secrets.example +3 -0
  9. package/.devcontainer/CHANGELOG.md +242 -0
  10. package/.devcontainer/CLAUDE.md +129 -22
  11. package/.devcontainer/README.md +34 -19
  12. package/.devcontainer/devcontainer.json +28 -10
  13. package/.devcontainer/features/agent-browser/install.sh +2 -0
  14. package/.devcontainer/features/ast-grep/install.sh +2 -0
  15. package/.devcontainer/features/biome/install.sh +2 -0
  16. package/.devcontainer/features/ccburn/install.sh +2 -0
  17. package/.devcontainer/features/ccms/install.sh +2 -0
  18. package/.devcontainer/features/ccstatusline/README.md +7 -6
  19. package/.devcontainer/features/ccstatusline/install.sh +9 -4
  20. package/.devcontainer/features/ccusage/install.sh +2 -0
  21. package/.devcontainer/features/chromaterm/chromaterm.yml +2 -2
  22. package/.devcontainer/features/chromaterm/install.sh +2 -0
  23. package/.devcontainer/features/claude-code-native/README.md +47 -0
  24. package/.devcontainer/features/claude-code-native/devcontainer-feature.json +29 -0
  25. package/.devcontainer/features/claude-code-native/install.sh +131 -0
  26. package/.devcontainer/features/claude-monitor/install.sh +2 -0
  27. package/.devcontainer/features/claude-session-dashboard/README.md +2 -2
  28. package/.devcontainer/features/claude-session-dashboard/install.sh +2 -0
  29. package/.devcontainer/features/dprint/install.sh +2 -0
  30. package/.devcontainer/features/hadolint/install.sh +2 -0
  31. package/.devcontainer/features/kitty-terminfo/README.md +3 -1
  32. package/.devcontainer/features/kitty-terminfo/install.sh +2 -0
  33. package/.devcontainer/features/lsp-servers/install.sh +2 -0
  34. package/.devcontainer/features/mcp-qdrant/CHANGES.md +3 -3
  35. package/.devcontainer/features/mcp-qdrant/README.md +1 -0
  36. package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +1 -1
  37. package/.devcontainer/features/mcp-qdrant/install.sh +9 -2
  38. package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +9 -2
  39. package/.devcontainer/features/notify-hook/devcontainer-feature.json +1 -1
  40. package/.devcontainer/features/notify-hook/install.sh +2 -0
  41. package/.devcontainer/features/ruff/install.sh +2 -0
  42. package/.devcontainer/features/shellcheck/install.sh +2 -0
  43. package/.devcontainer/features/shfmt/install.sh +2 -0
  44. package/.devcontainer/features/tmux/README.md +3 -3
  45. package/.devcontainer/features/tmux/install.sh +3 -1
  46. package/.devcontainer/features/tree-sitter/install.sh +2 -0
  47. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +27 -11
  48. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/README.md +23 -4
  49. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/claude-guide.md +4 -4
  50. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/documenter.md +254 -0
  51. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/implementer.md +260 -0
  52. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/investigator.md +255 -0
  53. package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/tester.md +304 -0
  54. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/README.md +1 -1
  55. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/advisory-test-runner.py +4 -2
  56. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +2 -2
  57. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/.claude-plugin/plugin.json +7 -0
  58. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/README.md +125 -0
  59. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/pr-review/SKILL.md +325 -0
  60. package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/ship/SKILL.md +314 -0
  61. package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/.claude-plugin/plugin.json +5 -0
  62. package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/README.md +52 -0
  63. package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/skills/ps/SKILL.md +37 -0
  64. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected-bash.py +1 -1
  65. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +1 -1
  66. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/README.md +30 -14
  67. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/hooks/hooks.json +13 -1
  68. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/collect-session-edits.py +44 -0
  69. package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/commit-reminder.py +89 -10
  70. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/.claude-plugin/plugin.json +1 -1
  71. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/README.md +19 -11
  72. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/scripts/skill-suggester.py +476 -282
  73. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/SKILL.md +227 -0
  74. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/manual-worktree-commands.md +238 -0
  75. package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/parallel-workflow-patterns.md +228 -0
  76. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/scripts/ticket-linker.py +2 -2
  77. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/README.md +1 -1
  78. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py +3 -2
  79. package/.devcontainer/scripts/check-setup.sh +5 -3
  80. package/.devcontainer/scripts/preflight.sh +113 -0
  81. package/.devcontainer/scripts/setup-aliases.sh +13 -8
  82. package/.devcontainer/scripts/setup-auth.sh +46 -0
  83. package/.devcontainer/scripts/setup-config.sh +29 -10
  84. package/.devcontainer/scripts/setup-migrate-claude.sh +80 -0
  85. package/.devcontainer/scripts/setup-migrate-codeforge.sh +60 -0
  86. package/.devcontainer/scripts/setup-plugins.sh +3 -1
  87. package/.devcontainer/scripts/setup-projects.sh +3 -1
  88. package/.devcontainer/scripts/setup-terminal.sh +3 -1
  89. package/.devcontainer/scripts/setup-update-claude.sh +22 -27
  90. package/.devcontainer/scripts/setup.sh +57 -5
  91. package/LICENSE.txt +14 -0
  92. package/README.md +79 -5
  93. package/package.json +2 -1
  94. package/setup.js +392 -21
  95. package/.devcontainer/docs/configuration-reference.md +0 -93
  96. package/.devcontainer/docs/keybindings.md +0 -100
  97. package/.devcontainer/docs/optional-features.md +0 -64
  98. package/.devcontainer/docs/plugins.md +0 -176
  99. package/.devcontainer/docs/troubleshooting.md +0 -128
  100. package/.devcontainer/scripts/setup-symlink-claude.sh +0 -36
  101. /package/{.devcontainer/config/defaults → .codeforge/config}/keybindings.json +0 -0
  102. /package/{.devcontainer/config/defaults → .codeforge/config}/rules/session-search.md +0 -0
  103. /package/{.devcontainer/config/defaults → .codeforge/config}/rules/spec-workflow.md +0 -0
  104. /package/{.devcontainer/config/defaults → .codeforge/config}/rules/workspace-scope.md +0 -0
  105. /package/{.devcontainer/config/defaults → .codeforge/config}/writing-system-prompt.md +0 -0
  106. /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
- Three hooks that run automatically at session lifecycle boundaries:
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
- | Stop | `commit-reminder.py` | Advisory about staged/unstaged changes that should be committed |
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 and checks for uncommitted work:
37
- - Detects staged and unstaged changes
38
- - Injects an advisory so Claude can naturally ask if the user wants to commit
39
- - Uses a guard flag to prevent infinite loops (the reminder itself is a Stop event)
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
- +-> Checks git status for changes
69
- +-> Has changes? -> Inject commit advisory
70
- +-> No changes? -> Silent (no output)
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 three scripts exit 0 (advisory only). They never block operations.
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 # Hook registrations (SessionStart + Stop)
143
+ | +-- hooks.json # Hook registrations (SessionStart + PostToolUse + Stop)
129
144
  +-- scripts/
130
- | +-- git-state-injector.py # Git state context (SessionStart)
131
- | +-- todo-harvester.py # Tech debt markers (SessionStart)
132
- | +-- commit-reminder.py # Uncommitted changes advisory (Stop)
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()
@@ -2,21 +2,31 @@
2
2
  """
3
3
  Commit reminder — Stop hook that advises about uncommitted changes.
4
4
 
5
- On Stop, checks for uncommitted changes (staged + unstaged) and injects
6
- an advisory reminder as additionalContext. Claude sees it and can
7
- naturally ask the user if they want to commit.
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
- Reads hook input from stdin (JSON). Returns JSON on stdout.
10
- Blocks with decision/reason so Claude addresses uncommitted changes
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
- # Check if there are any changes at all
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
- f"[Uncommitted Changes] {total} files with changes ({summary}).\n"
83
- "Consider asking the user if they'd like to commit before finishing."
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({"decision": "block", "reason": message}, sys.stdout)
165
+ json.dump({"systemMessage": message}, sys.stdout)
87
166
  sys.exit(0)
88
167
 
89
168
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-engine",
3
- "description": "21 coding knowledge packs with auto-suggestion for frameworks, tools, and patterns",
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 21 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.
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** — 21 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.
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 matches user prompts against keyword maps defined in each skill. When a match is found, it injects a suggestion via `additionalContext` so Claude knows a relevant skill is available.
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
- Keywords are defined per skill as:
44
- - **Phrases** — Multi-word patterns (e.g., "docker compose", "REST API")
45
- - **Terms** — Single keywords (e.g., "FastAPI", "pytest")
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
- +-> Scan prompt against all skill keyword maps
59
- +-> Match found? -> Inject skill suggestion as additionalContext
60
- +-> No match? -> Silent (no output)
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 # Keyword-based skill auto-suggestion
136
+ | +-- skill-suggester.py # Weighted scoring skill auto-suggestion
130
137
  +-- skills/
131
- | +-- api-design/ # 21 skill directories
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