codeforge-dev 1.10.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 (90) hide show
  1. package/.devcontainer/.env +7 -1
  2. package/.devcontainer/.gitignore +1 -0
  3. package/.devcontainer/CHANGELOG.md +138 -0
  4. package/.devcontainer/CLAUDE.md +87 -8
  5. package/.devcontainer/README.md +55 -18
  6. package/.devcontainer/config/defaults/main-system-prompt.md +132 -152
  7. package/.devcontainer/config/defaults/rules/session-search.md +66 -0
  8. package/.devcontainer/config/defaults/rules/spec-workflow.md +39 -12
  9. package/.devcontainer/config/defaults/settings.json +2 -1
  10. package/.devcontainer/config/defaults/writing-system-prompt.md +185 -0
  11. package/.devcontainer/config/file-manifest.json +12 -0
  12. package/.devcontainer/connect-external-terminal.ps1 +1 -1
  13. package/.devcontainer/devcontainer.json +40 -10
  14. package/.devcontainer/docs/configuration-reference.md +3 -0
  15. package/.devcontainer/docs/plugins.md +9 -2
  16. package/.devcontainer/docs/troubleshooting.md +2 -2
  17. package/.devcontainer/features/README.md +8 -9
  18. package/.devcontainer/features/agent-browser/devcontainer-feature.json +21 -21
  19. package/.devcontainer/features/agent-browser/install.sh +0 -7
  20. package/.devcontainer/features/ast-grep/devcontainer-feature.json +22 -22
  21. package/.devcontainer/features/biome/devcontainer-feature.json +12 -14
  22. package/.devcontainer/features/ccms/README.md +50 -0
  23. package/.devcontainer/features/ccms/devcontainer-feature.json +21 -0
  24. package/.devcontainer/features/ccms/install.sh +122 -0
  25. package/.devcontainer/features/ccstatusline/install.sh +24 -2
  26. package/.devcontainer/features/lsp-servers/devcontainer-feature.json +43 -43
  27. package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +2 -1
  28. package/.devcontainer/features/ruff/devcontainer-feature.json +17 -19
  29. package/.devcontainer/features/tmux/install.sh +2 -2
  30. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +8 -1
  31. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/README.md +81 -0
  32. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/README.md +92 -0
  33. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/README.md +250 -0
  34. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +1 -0
  35. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +2 -2
  36. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +1 -1
  37. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +1 -1
  38. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +4 -4
  39. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +1 -1
  40. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +2 -1
  41. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/git-archaeologist.md +2 -2
  42. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/researcher.md +1 -1
  43. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/security-auditor.md +1 -1
  44. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +8 -8
  45. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +10 -0
  46. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/skill-suggester.cpython-314.pyc +0 -0
  47. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/git-state-injector.py +15 -4
  48. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/inject-cwd.py +37 -0
  49. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +24 -0
  50. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/spec-reminder.py +3 -2
  51. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-build/SKILL.md +353 -0
  52. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-build/references/review-checklist.md +175 -0
  53. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-check/SKILL.md +15 -14
  54. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/SKILL.md +12 -11
  55. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/backlog-template.md +1 -1
  56. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/milestones-template.md +32 -0
  57. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/SKILL.md +17 -18
  58. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/references/template.md +12 -2
  59. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-review/SKILL.md +229 -0
  60. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-update/SKILL.md +6 -2
  61. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +1 -1
  62. package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +38 -5
  63. package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/README.md +41 -0
  64. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/README.md +72 -0
  65. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +73 -47
  66. package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/README.md +42 -0
  67. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/README.md +86 -0
  68. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +25 -15
  69. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected-bash.py +122 -0
  70. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +3 -3
  71. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/README.md +96 -0
  72. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/.claude-plugin/plugin.json +7 -0
  73. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/README.md +94 -0
  74. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/hooks/hooks.json +17 -0
  75. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/__pycache__/guard-workspace-scope.cpython-314.pyc +0 -0
  76. package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py +132 -0
  77. package/.devcontainer/scripts/check-setup.sh +1 -1
  78. package/.devcontainer/scripts/setup-aliases.sh +68 -75
  79. package/.devcontainer/scripts/setup-projects.sh +23 -16
  80. package/.devcontainer/scripts/setup.sh +48 -5
  81. package/README.md +17 -8
  82. package/package.json +1 -2
  83. package/.devcontainer/features/mcp-reasoner/README.md +0 -177
  84. package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +0 -25
  85. package/.devcontainer/features/mcp-reasoner/install.sh +0 -184
  86. package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +0 -67
  87. package/.devcontainer/features/splitrail/README.md +0 -140
  88. package/.devcontainer/features/splitrail/devcontainer-feature.json +0 -39
  89. package/.devcontainer/features/splitrail/install.sh +0 -136
  90. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/roadmap-template.md +0 -33
@@ -13,54 +13,82 @@ import sys
13
13
 
14
14
  DANGEROUS_PATTERNS = [
15
15
  # Destructive filesystem deletion
16
- (r'\brm\s+.*-[^\s]*r[^\s]*f[^\s]*\s+[/~](?:\s|$)',
17
- "Blocked: rm -rf on root or home directory"),
18
- (r'\brm\s+.*-[^\s]*f[^\s]*r[^\s]*\s+[/~](?:\s|$)',
19
- "Blocked: rm -rf on root or home directory"),
20
- (r'\brm\s+-rf\s+/(?:\s|$)',
21
- "Blocked: rm -rf /"),
22
- (r'\brm\s+-rf\s+~(?:\s|$)',
23
- "Blocked: rm -rf ~"),
24
-
16
+ (
17
+ r"\brm\s+.*-[^\s]*r[^\s]*f[^\s]*\s+[/~](?:\s|$)",
18
+ "Blocked: rm -rf on root or home directory",
19
+ ),
20
+ (
21
+ r"\brm\s+.*-[^\s]*f[^\s]*r[^\s]*\s+[/~](?:\s|$)",
22
+ "Blocked: rm -rf on root or home directory",
23
+ ),
24
+ (r"\brm\s+-rf\s+/(?:\s|$)", "Blocked: rm -rf /"),
25
+ (r"\brm\s+-rf\s+~(?:\s|$)", "Blocked: rm -rf ~"),
25
26
  # Root-level file removal
26
- (r'\bsudo\s+rm\b',
27
- "Blocked: sudo rm - use caution with privileged deletion"),
28
-
27
+ (r"\bsudo\s+rm\b", "Blocked: sudo rm - use caution with privileged deletion"),
29
28
  # World-writable permissions
30
- (r'\bchmod\s+777\b',
31
- "Blocked: chmod 777 creates security vulnerability"),
32
- (r'\bchmod\s+-R\s+777\b',
33
- "Blocked: recursive chmod 777 creates security vulnerability"),
34
-
29
+ (r"\bchmod\s+777\b", "Blocked: chmod 777 creates security vulnerability"),
30
+ (
31
+ r"\bchmod\s+-R\s+777\b",
32
+ "Blocked: recursive chmod 777 creates security vulnerability",
33
+ ),
35
34
  # Force push to main/master
36
- (r'\bgit\s+push\s+.*--force.*\s+(origin\s+)?(main|master)\b',
37
- "Blocked: force push to main/master destroys history"),
38
- (r'\bgit\s+push\s+.*-f\s+.*\s+(origin\s+)?(main|master)\b',
39
- "Blocked: force push to main/master destroys history"),
40
- (r'\bgit\s+push\s+-f\s+(origin\s+)?(main|master)\b',
41
- "Blocked: force push to main/master destroys history"),
42
- (r'\bgit\s+push\s+--force\s+(origin\s+)?(main|master)\b',
43
- "Blocked: force push to main/master destroys history"),
44
-
35
+ (
36
+ r"\bgit\s+push\s+.*--force.*\s+(origin\s+)?(main|master)\b",
37
+ "Blocked: force push to main/master destroys history",
38
+ ),
39
+ (
40
+ r"\bgit\s+push\s+.*-f\s+.*\s+(origin\s+)?(main|master)\b",
41
+ "Blocked: force push to main/master destroys history",
42
+ ),
43
+ (
44
+ r"\bgit\s+push\s+-f\s+(origin\s+)?(main|master)\b",
45
+ "Blocked: force push to main/master destroys history",
46
+ ),
47
+ (
48
+ r"\bgit\s+push\s+--force\s+(origin\s+)?(main|master)\b",
49
+ "Blocked: force push to main/master destroys history",
50
+ ),
45
51
  # System directory modification
46
- (r'>\s*/usr/',
47
- "Blocked: writing to /usr system directory"),
48
- (r'>\s*/etc/',
49
- "Blocked: writing to /etc system directory"),
50
- (r'>\s*/bin/',
51
- "Blocked: writing to /bin system directory"),
52
- (r'>\s*/sbin/',
53
- "Blocked: writing to /sbin system directory"),
54
-
52
+ (r">\s*/usr/", "Blocked: writing to /usr system directory"),
53
+ (r">\s*/etc/", "Blocked: writing to /etc system directory"),
54
+ (r">\s*/bin/", "Blocked: writing to /bin system directory"),
55
+ (r">\s*/sbin/", "Blocked: writing to /sbin system directory"),
55
56
  # Disk formatting
56
- (r'\bmkfs\.\w+',
57
- "Blocked: disk formatting command"),
58
- (r'\bdd\s+.*of=/dev/',
59
- "Blocked: dd writing to device"),
60
-
57
+ (r"\bmkfs\.\w+", "Blocked: disk formatting command"),
58
+ (r"\bdd\s+.*of=/dev/", "Blocked: dd writing to device"),
61
59
  # History manipulation
62
- (r'\bgit\s+reset\s+--hard\s+origin/(main|master)\b',
63
- "Blocked: hard reset to remote main/master - destructive operation"),
60
+ (
61
+ r"\bgit\s+reset\s+--hard\s+origin/(main|master)\b",
62
+ "Blocked: hard reset to remote main/master - destructive operation",
63
+ ),
64
+ # Docker container escape
65
+ (
66
+ r"\bdocker\s+run\s+.*--privileged",
67
+ "Blocked: docker run --privileged allows container escape",
68
+ ),
69
+ (
70
+ r"\bdocker\s+run\s+.*-v\s+/:/\w",
71
+ "Blocked: docker run mounting host root filesystem",
72
+ ),
73
+ # Destructive Docker operations
74
+ (
75
+ r"\bdocker\s+(stop|rm|kill|rmi)\s+",
76
+ "Blocked: destructive docker operation - use with caution",
77
+ ),
78
+ # Additional rm patterns
79
+ (r"\brm\s+.*-[^\s]*r[^\s]*f[^\s]*\s+\.\./", "Blocked: rm -rf on parent directory"),
80
+ (r"\bfind\s+.*-exec\s+rm\b", "Blocked: find -exec rm is dangerous"),
81
+ (r"\bfind\s+.*-delete\b", "Blocked: find -delete is dangerous"),
82
+ # Git history destruction
83
+ (r"\bgit\s+push\s+-f\b", "Blocked: bare force push - specify remote and branch"),
84
+ (
85
+ r"\bgit\s+push\s+--force\b",
86
+ "Blocked: bare force push - specify remote and branch",
87
+ ),
88
+ (
89
+ r"\bgit\s+clean\s+-[^\s]*f",
90
+ "Blocked: git clean -f removes untracked files permanently",
91
+ ),
64
92
  ]
65
93
 
66
94
 
@@ -89,17 +117,15 @@ def main():
89
117
 
90
118
  if is_dangerous:
91
119
  # Output error message and exit 2 to block
92
- print(json.dumps({
93
- "error": message
94
- }))
120
+ print(json.dumps({"error": message}))
95
121
  sys.exit(2)
96
122
 
97
123
  # Allow command to proceed
98
124
  sys.exit(0)
99
125
 
100
126
  except json.JSONDecodeError:
101
- # If we can't parse input, allow by default
102
- sys.exit(0)
127
+ # Fail closed: can't parse means can't verify safety
128
+ sys.exit(2)
103
129
  except Exception as e:
104
130
  # Log error but don't block on hook failure
105
131
  print(f"Hook error: {e}", file=sys.stderr)
@@ -0,0 +1,42 @@
1
+ # notify-hook
2
+
3
+ Ultra-lightweight Claude Code plugin that sends a desktop notification and audio chime when Claude finishes responding. No scripts — just a single hook definition that calls the `claude-notify` binary.
4
+
5
+ ## What It Does
6
+
7
+ When Claude stops responding (Stop hook), it runs the `claude-notify` command to:
8
+ 1. Send a desktop notification
9
+ 2. Play an audio chime
10
+
11
+ This lets you switch to other tasks while Claude works and get alerted when it needs your attention.
12
+
13
+ ## How It Works
14
+
15
+ ### Hook Lifecycle
16
+
17
+ ```
18
+ Claude stops responding (Stop event)
19
+
20
+ └─→ claude-notify command fires
21
+
22
+ ├─→ Desktop notification sent
23
+ └─→ Audio chime played
24
+ ```
25
+
26
+ The hook has a 5-second timeout. The plugin contains no scripts of its own — it delegates entirely to the `claude-notify` binary.
27
+
28
+ ## Plugin Structure
29
+
30
+ ```
31
+ notify-hook/
32
+ ├── .claude-plugin/
33
+ │ └── plugin.json # Plugin metadata
34
+ ├── hooks/
35
+ │ └── hooks.json # Stop hook registration
36
+ └── README.md # This file
37
+ ```
38
+
39
+ ## Requirements
40
+
41
+ - Claude Code with plugin hook support
42
+ - The `notify-hook` devcontainer feature must be installed (provides the `claude-notify` binary)
@@ -0,0 +1,86 @@
1
+ # protected-files-guard
2
+
3
+ Claude Code plugin that blocks modifications to sensitive files — environment secrets, lock files, git internals, certificates, and credentials. Covers both direct file edits (Edit/Write tools) and indirect writes through Bash commands.
4
+
5
+ ## What It Does
6
+
7
+ Intercepts file operations and checks target paths against a set of protected patterns. If a match is found, the operation is blocked with an error message explaining why and suggesting the correct approach (e.g., "use npm install instead" for package-lock.json).
8
+
9
+ ### Protected File Categories
10
+
11
+ | Category | Patterns | Reason |
12
+ |----------|----------|--------|
13
+ | Environment secrets | `.env`, `.env.*` | Contains secrets |
14
+ | Git internals | `.git/` | Managed by git |
15
+ | Lock files | `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `Gemfile.lock`, `poetry.lock`, `Cargo.lock`, `composer.lock`, `uv.lock` | Must be modified via package manager |
16
+ | Certificates & keys | `.pem`, `.key`, `.crt`, `.p12`, `.pfx` | Sensitive cryptographic material |
17
+ | Credential files | `credentials.json`, `secrets.yaml`, `secrets.yml`, `secrets.json`, `.secrets` | Contains secrets |
18
+ | Auth directories | `.ssh/`, `.aws/` | Contains authentication data |
19
+ | Auth config files | `.netrc`, `.npmrc`, `.pypirc` | Contains authentication credentials |
20
+ | SSH private keys | `id_rsa`, `id_ed25519`, `id_ecdsa` | SSH private key files |
21
+
22
+ ## How It Works
23
+
24
+ ### Two-Hook Architecture
25
+
26
+ The plugin registers two PreToolUse hooks to cover different attack vectors:
27
+
28
+ ```
29
+ Claude calls Edit or Write tool
30
+
31
+ └─→ guard-protected.py checks file_path against protected patterns
32
+
33
+ ├─→ Match → exit 2 (block)
34
+ └─→ No match → exit 0 (allow)
35
+
36
+ Claude calls Bash tool
37
+
38
+ └─→ guard-protected-bash.py extracts write targets from the command
39
+
40
+ ├─→ Detects: > redirect, >> append, tee, cp, mv, sed -i, cat heredoc
41
+ ├─→ Checks each target against protected patterns
42
+ ├─→ Any match → exit 2 (block)
43
+ └─→ No match → exit 0 (allow)
44
+ ```
45
+
46
+ ### Bash Write Detection
47
+
48
+ The Bash guard parses commands for write-indicating patterns and extracts the target file path:
49
+
50
+ | Pattern | Example |
51
+ |---------|---------|
52
+ | Redirect (`>`, `>>`) | `echo "key=val" > .env` |
53
+ | `tee` / `tee -a` | `cat data \| tee .env` |
54
+ | `cp` / `mv` | `cp template .env` |
55
+ | `sed -i` | `sed -i 's/old/new/' .env` |
56
+ | `cat` heredoc | `cat <<EOF > .env` |
57
+
58
+ ### Error Handling
59
+
60
+ | Scenario | Behavior |
61
+ |----------|----------|
62
+ | JSON parse failure | Fails closed (exit 2) — blocks the operation |
63
+ | Other exceptions | Fails open (exit 0) — logs error, allows the operation |
64
+
65
+ ### Timeout
66
+
67
+ Both hooks have a 5-second timeout.
68
+
69
+ ## Plugin Structure
70
+
71
+ ```
72
+ protected-files-guard/
73
+ ├── .claude-plugin/
74
+ │ └── plugin.json # Plugin metadata
75
+ ├── hooks/
76
+ │ └── hooks.json # PreToolUse hook registrations (Edit|Write + Bash)
77
+ ├── scripts/
78
+ │ ├── guard-protected.py # Edit/Write file path checker
79
+ │ └── guard-protected-bash.py # Bash command write target checker
80
+ └── README.md # This file
81
+ ```
82
+
83
+ ## Requirements
84
+
85
+ - Python 3.11+
86
+ - Claude Code with plugin hook support
@@ -1,17 +1,27 @@
1
1
  {
2
- "description": "Block modifications to protected files",
3
- "hooks": {
4
- "PreToolUse": [
5
- {
6
- "matcher": "Edit|Write",
7
- "hooks": [
8
- {
9
- "type": "command",
10
- "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/guard-protected.py",
11
- "timeout": 5
12
- }
13
- ]
14
- }
15
- ]
16
- }
2
+ "description": "Block modifications to protected files",
3
+ "hooks": {
4
+ "PreToolUse": [
5
+ {
6
+ "matcher": "Edit|Write",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/guard-protected.py",
11
+ "timeout": 5
12
+ }
13
+ ]
14
+ },
15
+ {
16
+ "matcher": "Bash",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/guard-protected-bash.py",
21
+ "timeout": 5
22
+ }
23
+ ]
24
+ }
25
+ ]
26
+ }
17
27
  }
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Block bash commands that write to protected files.
4
+
5
+ Reads tool input from stdin, checks the command field for write operations
6
+ targeting protected file patterns.
7
+ Exit code 2 blocks the command with error message.
8
+ Exit code 0 allows the command to proceed.
9
+ """
10
+
11
+ import json
12
+ import re
13
+ import sys
14
+
15
+ # Same patterns as guard-protected.py
16
+ PROTECTED_PATTERNS = [
17
+ (r"(^|/)\.env$", "Blocked: .env contains secrets - edit manually if needed"),
18
+ (
19
+ r"(^|/)\.env\.[^/]+$",
20
+ "Blocked: .env.* files contain secrets - edit manually if needed",
21
+ ),
22
+ (r"(^|/)\.git(/|$)", "Blocked: .git is managed by git"),
23
+ (
24
+ r"(^|/)package-lock\.json$",
25
+ "Blocked: package-lock.json - use npm install instead",
26
+ ),
27
+ (r"(^|/)yarn\.lock$", "Blocked: yarn.lock - use yarn install instead"),
28
+ (r"(^|/)pnpm-lock\.yaml$", "Blocked: pnpm-lock.yaml - use pnpm install instead"),
29
+ (r"(^|/)Gemfile\.lock$", "Blocked: Gemfile.lock - use bundle install instead"),
30
+ (r"(^|/)poetry\.lock$", "Blocked: poetry.lock - use poetry install instead"),
31
+ (r"(^|/)Cargo\.lock$", "Blocked: Cargo.lock - use cargo build instead"),
32
+ (r"(^|/)composer\.lock$", "Blocked: composer.lock - use composer install instead"),
33
+ (r"(^|/)uv\.lock$", "Blocked: uv.lock - use uv sync instead"),
34
+ (r"\.pem$", "Blocked: .pem files contain sensitive cryptographic material"),
35
+ (r"\.key$", "Blocked: .key files contain sensitive cryptographic material"),
36
+ (r"\.crt$", "Blocked: .crt certificate files should not be edited directly"),
37
+ (r"\.p12$", "Blocked: .p12 files contain sensitive cryptographic material"),
38
+ (r"\.pfx$", "Blocked: .pfx files contain sensitive cryptographic material"),
39
+ (r"(^|/)credentials\.json$", "Blocked: credentials.json contains secrets"),
40
+ (r"(^|/)secrets\.yaml$", "Blocked: secrets.yaml contains secrets"),
41
+ (r"(^|/)secrets\.yml$", "Blocked: secrets.yml contains secrets"),
42
+ (r"(^|/)secrets\.json$", "Blocked: secrets.json contains secrets"),
43
+ (r"(^|/)\.secrets$", "Blocked: .secrets file contains secrets"),
44
+ (r"(^|/)\.ssh/", "Blocked: .ssh/ contains sensitive authentication data"),
45
+ (r"(^|/)\.aws/", "Blocked: .aws/ contains AWS credentials"),
46
+ (r"(^|/)\.netrc$", "Blocked: .netrc contains authentication credentials"),
47
+ (
48
+ r"(^|/)\.npmrc$",
49
+ "Blocked: .npmrc may contain auth tokens - edit manually if needed",
50
+ ),
51
+ (r"(^|/)\.pypirc$", "Blocked: .pypirc contains PyPI credentials"),
52
+ (r"(^|/|-)id_rsa($|\.)", "Blocked: SSH private key file"),
53
+ (r"(^|/)id_ed25519", "Blocked: SSH private key file"),
54
+ (r"(^|/)id_ecdsa", "Blocked: SSH private key file"),
55
+ ]
56
+
57
+ # Patterns that indicate a bash command is writing to a file
58
+ # Each captures the target file path for checking against PROTECTED_PATTERNS
59
+ WRITE_PATTERNS = [
60
+ # Redirect: > file, >> file
61
+ r"(?:>|>>)\s*([^\s;&|]+)",
62
+ # tee: tee file, tee -a file
63
+ r"\btee\s+(?:-a\s+)?([^\s;&|]+)",
64
+ # cp/mv: cp src dest, mv src dest
65
+ r"\b(?:cp|mv)\s+(?:-[^\s]+\s+)*[^\s]+\s+([^\s;&|]+)",
66
+ # sed -i: sed -i '' file
67
+ r'\bsed\s+-i[^\s]*\s+(?:\'[^\']*\'\s+|"[^"]*"\s+|[^\s]+\s+)*([^\s;&|]+)',
68
+ # cat > file (heredoc style)
69
+ r"\bcat\s+(?:<<[^\s]*\s+)?>\s*([^\s;&|]+)",
70
+ ]
71
+
72
+
73
+ def extract_write_targets(command: str) -> list[str]:
74
+ """Extract file paths that the command writes to."""
75
+ targets = []
76
+ for pattern in WRITE_PATTERNS:
77
+ for match in re.finditer(pattern, command):
78
+ target = match.group(1).strip("'\"")
79
+ if target:
80
+ targets.append(target)
81
+ return targets
82
+
83
+
84
+ def check_path(file_path: str) -> tuple[bool, str]:
85
+ """Check if file path matches any protected pattern."""
86
+ normalized = file_path.replace("\\", "/")
87
+ for pattern, message in PROTECTED_PATTERNS:
88
+ if re.search(pattern, normalized, re.IGNORECASE):
89
+ return True, message
90
+ return False, ""
91
+
92
+
93
+ def main():
94
+ try:
95
+ input_data = json.load(sys.stdin)
96
+ tool_input = input_data.get("tool_input", {})
97
+ command = tool_input.get("command", "")
98
+
99
+ if not command:
100
+ sys.exit(0)
101
+
102
+ targets = extract_write_targets(command)
103
+
104
+ for target in targets:
105
+ is_protected, message = check_path(target)
106
+ if is_protected:
107
+ print(json.dumps({"error": f"{message} (via bash command)"}))
108
+ sys.exit(2)
109
+
110
+ sys.exit(0)
111
+
112
+ except json.JSONDecodeError:
113
+ # Fail closed: can't parse means can't verify safety
114
+ sys.exit(2)
115
+ except Exception as e:
116
+ # Log error but don't block on hook failure
117
+ print(f"Hook error: {e}", file=sys.stderr)
118
+ sys.exit(0)
119
+
120
+
121
+ if __name__ == "__main__":
122
+ main()
@@ -20,7 +20,7 @@ PROTECTED_PATTERNS = [
20
20
  "Blocked: .env.* files contain secrets - edit manually if needed",
21
21
  ),
22
22
  # Git internals
23
- (r"(^|/)\.git/", "Blocked: .git/ directory is managed by git"),
23
+ (r"(^|/)\.git(/|$)", "Blocked: .git is managed by git"),
24
24
  # Lock files (should be modified via package manager)
25
25
  (
26
26
  r"(^|/)package-lock\.json$",
@@ -97,8 +97,8 @@ def main():
97
97
  sys.exit(0)
98
98
 
99
99
  except json.JSONDecodeError:
100
- # If we can't parse input, allow by default
101
- sys.exit(0)
100
+ # Fail closed: can't parse means can't verify safety
101
+ sys.exit(2)
102
102
  except Exception as e:
103
103
  # Log error but don't block on hook failure
104
104
  print(f"Hook error: {e}", file=sys.stderr)
@@ -0,0 +1,96 @@
1
+ # ticket-workflow
2
+
3
+ Claude Code plugin that provides an EARS-based ticket workflow with GitHub issues as the single source of truth. Command-driven — no hooks or scripts, just a custom system prompt and four slash commands.
4
+
5
+ ## What It Does
6
+
7
+ Provides a structured workflow for creating, planning, reviewing, and shipping work through GitHub issues. All major decisions, plans, and progress are posted as issue comments to maintain an audit trail.
8
+
9
+ ### Slash Commands
10
+
11
+ | Command | Description |
12
+ |---------|-------------|
13
+ | `/ticket:new` | Transform requirements into a structured GitHub issue with EARS-formatted business requirements |
14
+ | `/ticket:work` | Retrieve a ticket, create a technical implementation plan, and post it to the GitHub issue |
15
+ | `/ticket:review-commit` | Conduct a thorough code review, verify requirements are met, and commit with a detailed message |
16
+ | `/ticket:create-pr` | Create a pull request with aggressive security and architecture review |
17
+
18
+ ### EARS Requirement Format
19
+
20
+ Every requirement uses one of these patterns:
21
+
22
+ | Type | Template |
23
+ |------|----------|
24
+ | Ubiquitous | The `<system>` shall `<response>`. |
25
+ | Event-Driven | WHEN `<trigger>`, the `<system>` shall `<response>`. |
26
+ | State-Driven | WHILE `<state>`, the `<system>` shall `<response>`. |
27
+ | Unwanted Behavior | IF `<condition>`, THEN the `<system>` shall `<response>`. |
28
+ | Optional Feature | WHERE `<feature>`, the `<system>` shall `<response>`. |
29
+
30
+ ## How It Works
31
+
32
+ ### Workflow Lifecycle
33
+
34
+ ```
35
+ /ticket:new [requirements]
36
+
37
+ └─→ Gather requirements → Create EARS-formatted GitHub issue
38
+
39
+ └─→ /ticket:work #123
40
+
41
+ └─→ Fetch issue → Create technical plan → Post plan as issue comment
42
+
43
+ │ ... implementation work ...
44
+
45
+ └─→ /ticket:review-commit
46
+
47
+ └─→ Review changes → Verify requirements → Commit
48
+
49
+ └─→ /ticket:create-pr
50
+
51
+ └─→ Create PR → Security/architecture review → Post findings
52
+ ```
53
+
54
+ ### Ticket Structure
55
+
56
+ Each ticket created by `/ticket:new` includes:
57
+ - **Overview**: Plain language description
58
+ - **Requirements**: EARS-formatted business requirements
59
+ - **Technical Questions**: Open questions for implementation
60
+ - **Acceptance Criteria**: Verifiable conditions for completion
61
+
62
+ ### Audit Trail
63
+
64
+ | Action | Destination |
65
+ |--------|-------------|
66
+ | Plans | Issue comment |
67
+ | Decisions | Issue comment |
68
+ | Requirement changes | Issue comment |
69
+ | Commit summaries | Issue comment |
70
+ | Review findings | PR + issue comment |
71
+ | Created sub-issues | Linked to source ticket |
72
+
73
+ ### Custom System Prompt
74
+
75
+ The plugin injects a system prompt that defines the assistant persona, coding standards (SOLID, DRY, KISS, YAGNI), testing standards, and the ticket workflow rules. This ensures consistent behavior across all four commands.
76
+
77
+ ## Plugin Structure
78
+
79
+ ```
80
+ ticket-workflow/
81
+ ├── .claude-plugin/
82
+ │ ├── plugin.json # Plugin metadata
83
+ │ ├── system-prompt.md # Custom system prompt (persona + workflow rules)
84
+ │ └── commands/
85
+ │ ├── ticket:new.md # Create EARS-formatted issue
86
+ │ ├── ticket:work.md # Implementation planning
87
+ │ ├── ticket:review-commit.md # Review and commit
88
+ │ └── ticket:create-pr.md # PR creation with review
89
+ └── README.md # This file
90
+ ```
91
+
92
+ ## Requirements
93
+
94
+ - Claude Code with plugin command support
95
+ - [GitHub CLI](https://cli.github.com/) (`gh`) installed and authenticated
96
+ - A GitHub repository as the working context
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "workspace-scope-guard",
3
+ "description": "Enforces working directory scope — blocks writes and warns on reads outside the project",
4
+ "author": {
5
+ "name": "AnExiledDev"
6
+ }
7
+ }
@@ -0,0 +1,94 @@
1
+ # workspace-scope-guard
2
+
3
+ Claude Code plugin that enforces working directory scope for all file operations. Blocks writes outside the current project directory and warns on reads outside it. Prevents accidental cross-project modifications in multi-project workspaces.
4
+
5
+ ## What It Does
6
+
7
+ Intercepts file operations (Read, Write, Edit, NotebookEdit, Glob, Grep) and checks whether the target path is within the current working directory:
8
+
9
+ | Operation | Out-of-scope behavior |
10
+ |-----------|-----------------------|
11
+ | Write, Edit, NotebookEdit | **Blocked** (exit 2) with error message |
12
+ | Read, Glob, Grep | **Warned** (exit 0) with advisory context |
13
+
14
+ When the current working directory is `/workspaces` (the workspace root), all operations are unrestricted.
15
+
16
+ ### Allowed Prefixes
17
+
18
+ These paths are always permitted regardless of working directory:
19
+
20
+ | Path | Reason |
21
+ |------|--------|
22
+ | `/workspaces/.claude/` | Claude Code configuration |
23
+ | `/workspaces/.tmp/` | Temporary files |
24
+ | `/workspaces/.devcontainer/` | Container configuration |
25
+ | `/tmp/` | System temp directory |
26
+ | `/home/vscode/` | User home directory |
27
+
28
+ ## How It Works
29
+
30
+ ### Hook Lifecycle
31
+
32
+ ```
33
+ Claude calls Read, Write, Edit, NotebookEdit, Glob, or Grep
34
+
35
+ └─→ PreToolUse hook fires
36
+
37
+ └─→ guard-workspace-scope.py
38
+
39
+ ├─→ cwd is /workspaces? → allow (unrestricted)
40
+ ├─→ No target path? → allow (tool defaults to cwd)
41
+ ├─→ Resolve path via os.path.realpath() (handles symlinks/worktrees)
42
+ ├─→ Path is within cwd? → allow
43
+ ├─→ Path matches allowed prefix? → allow
44
+ ├─→ Write tool + out of scope → exit 2 (block)
45
+ └─→ Read tool + out of scope → exit 0 (warn via additionalContext)
46
+ ```
47
+
48
+ ### Symlink and Worktree Handling
49
+
50
+ Target paths are resolved with `os.path.realpath()` before scope checking. This correctly handles:
51
+ - Symbolic links that point outside the working directory
52
+ - Git worktree paths (`.git` file containing `gitdir:`)
53
+
54
+ ### Path Field Mapping
55
+
56
+ The script extracts the target path from different tool input fields:
57
+
58
+ | Tool | Input Field |
59
+ |------|-------------|
60
+ | Read | `file_path` |
61
+ | Write | `file_path` |
62
+ | Edit | `file_path` |
63
+ | NotebookEdit | `notebook_path` |
64
+ | Glob | `path` |
65
+ | Grep | `path` |
66
+
67
+ ### Error Handling
68
+
69
+ | Scenario | Behavior |
70
+ |----------|----------|
71
+ | JSON parse failure | Fails open (exit 0) |
72
+ | Other exceptions | Fails open (exit 0) — logs error to stderr |
73
+
74
+ ### Timeout
75
+
76
+ The hook has a 5-second timeout.
77
+
78
+ ## Plugin Structure
79
+
80
+ ```
81
+ workspace-scope-guard/
82
+ ├── .claude-plugin/
83
+ │ └── plugin.json # Plugin metadata
84
+ ├── hooks/
85
+ │ └── hooks.json # PreToolUse hook registration
86
+ ├── scripts/
87
+ │ └── guard-workspace-scope.py # Scope enforcement (PreToolUse)
88
+ └── README.md # This file
89
+ ```
90
+
91
+ ## Requirements
92
+
93
+ - Python 3.11+
94
+ - Claude Code with plugin hook support