codeforge-dev 1.5.7 → 1.7.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 (80) hide show
  1. package/.devcontainer/.env +2 -1
  2. package/.devcontainer/CHANGELOG.md +55 -9
  3. package/.devcontainer/CLAUDE.md +65 -15
  4. package/.devcontainer/README.md +67 -6
  5. package/.devcontainer/config/keybindings.json +5 -0
  6. package/.devcontainer/config/main-system-prompt.md +63 -2
  7. package/.devcontainer/config/settings.json +25 -6
  8. package/.devcontainer/devcontainer.json +23 -7
  9. package/.devcontainer/features/README.md +21 -7
  10. package/.devcontainer/features/ccburn/README.md +60 -0
  11. package/.devcontainer/features/ccburn/devcontainer-feature.json +38 -0
  12. package/.devcontainer/features/ccburn/install.sh +174 -0
  13. package/.devcontainer/features/ccstatusline/README.md +22 -21
  14. package/.devcontainer/features/ccstatusline/devcontainer-feature.json +1 -1
  15. package/.devcontainer/features/ccstatusline/install.sh +48 -16
  16. package/.devcontainer/features/claude-code/config/settings.json +60 -24
  17. package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +1 -1
  18. package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +1 -1
  19. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/__pycache__/format-on-stop.cpython-314.pyc +0 -0
  20. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-on-stop.py +21 -6
  21. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/__pycache__/lint-file.cpython-314.pyc +0 -0
  22. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +7 -10
  23. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/REVIEW-RUBRIC.md +440 -0
  24. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +190 -0
  25. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/bash-exec.md +173 -0
  26. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/claude-guide.md +155 -0
  27. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +248 -0
  28. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +233 -0
  29. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +235 -0
  30. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +125 -0
  31. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/git-archaeologist.md +242 -0
  32. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/migrator.md +195 -0
  33. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/perf-profiler.md +265 -0
  34. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/refactorer.md +209 -0
  35. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/researcher.md +195 -0
  36. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/security-auditor.md +289 -0
  37. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +284 -0
  38. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/statusline-config.md +188 -0
  39. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/test-writer.md +245 -0
  40. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +12 -0
  41. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/guard-readonly-bash.cpython-314.pyc +0 -0
  42. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/redirect-builtin-agents.cpython-314.pyc +0 -0
  43. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/skill-suggester.cpython-314.pyc +0 -0
  44. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/syntax-validator.cpython-314.pyc +0 -0
  45. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/verify-no-regression.cpython-314.pyc +0 -0
  46. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/__pycache__/verify-tests-pass.cpython-314.pyc +0 -0
  47. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/guard-readonly-bash.py +611 -0
  48. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/redirect-builtin-agents.py +83 -0
  49. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/skill-suggester.py +85 -2
  50. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/syntax-validator.py +9 -4
  51. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/verify-no-regression.py +221 -0
  52. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/verify-tests-pass.py +176 -0
  53. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/claude-agent-sdk/SKILL.md +599 -0
  54. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/claude-agent-sdk/references/sdk-typescript-reference.md +954 -0
  55. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/SKILL.md +276 -0
  56. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/references/advanced-commands.md +332 -0
  57. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/git-forensics/references/investigation-playbooks.md +319 -0
  58. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/SKILL.md +341 -0
  59. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/references/interpreting-results.md +235 -0
  60. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/performance-profiling/references/tool-commands.md +395 -0
  61. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/SKILL.md +344 -0
  62. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/references/safe-transformations.md +247 -0
  63. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/refactoring-patterns/references/smell-catalog.md +332 -0
  64. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/SKILL.md +277 -0
  65. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/references/owasp-patterns.md +269 -0
  66. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/security-checklist/references/secrets-patterns.md +253 -0
  67. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +288 -0
  68. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/references/criteria-patterns.md +245 -0
  69. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/references/ears-templates.md +239 -0
  70. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/__pycache__/guard-protected.cpython-314.pyc +0 -0
  71. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +40 -39
  72. package/.devcontainer/scripts/setup-aliases.sh +10 -20
  73. package/.devcontainer/scripts/setup-config.sh +2 -0
  74. package/.devcontainer/scripts/setup-plugins.sh +38 -46
  75. package/.devcontainer/scripts/setup-projects.sh +175 -0
  76. package/.devcontainer/scripts/setup-symlink-claude.sh +36 -0
  77. package/.devcontainer/scripts/setup-update-claude.sh +11 -8
  78. package/.devcontainer/scripts/setup.sh +4 -2
  79. package/package.json +1 -1
  80. package/.devcontainer/scripts/setup-irie-claude.sh +0 -32
@@ -0,0 +1,239 @@
1
+ # EARS Requirement Templates
2
+
3
+ Templates and filled examples for each EARS (Easy Approach to Requirements Syntax) pattern type.
4
+
5
+ ## Contents
6
+
7
+ - [Ubiquitous Requirements](#ubiquitous-requirements)
8
+ - [Event-Driven Requirements](#event-driven-requirements)
9
+ - [State-Driven Requirements](#state-driven-requirements)
10
+ - [Unwanted Behavior Requirements](#unwanted-behavior-requirements)
11
+ - [Optional Feature Requirements](#optional-feature-requirements)
12
+ - [Compound Requirements](#compound-requirements)
13
+ - [Writing Tips](#writing-tips)
14
+
15
+ ---
16
+
17
+ ## Ubiquitous Requirements
18
+
19
+ **Template:**
20
+ ```
21
+ The <system> shall <action>.
22
+ ```
23
+
24
+ Requirements that are always active, with no trigger condition. These define invariant behaviors.
25
+
26
+ ### Examples
27
+
28
+ ```
29
+ The API shall return responses in JSON format with UTF-8 encoding.
30
+
31
+ The system shall log all authentication events with timestamp, user ID, and outcome.
32
+
33
+ The application shall enforce HTTPS for all client-server communication.
34
+
35
+ The database shall store timestamps in UTC.
36
+
37
+ The API shall include a request-id header in every response.
38
+ ```
39
+
40
+ ### Anti-patterns
41
+
42
+ ```
43
+ ❌ The system should be fast.
44
+ → Not testable. How fast? Measured how?
45
+
46
+ ❌ The system shall be user-friendly.
47
+ → Not testable. Define specific interaction requirements.
48
+
49
+ ✅ The API shall respond to health check requests within 50ms (p99).
50
+ ✅ The login form shall support keyboard navigation (tab order: email → password → submit).
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Event-Driven Requirements
56
+
57
+ **Template:**
58
+ ```
59
+ When <event>, the <system> shall <action>.
60
+ ```
61
+
62
+ Requirements triggered by a specific, detectable event. The event is the precondition.
63
+
64
+ ### Examples
65
+
66
+ ```
67
+ When a user submits a registration form, the system shall validate all fields
68
+ and return validation errors within 200ms.
69
+
70
+ When a payment transaction fails, the system shall:
71
+ 1. Log the failure with transaction ID, error code, and timestamp.
72
+ 2. Send a failure notification to the user within 60 seconds.
73
+ 3. Release the reserved inventory.
74
+
75
+ When a file upload exceeds 50MB, the system shall reject the upload with
76
+ HTTP 413 and a message indicating the maximum file size.
77
+
78
+ When a user's session has been inactive for 30 minutes, the system shall
79
+ invalidate the session and redirect to the login page.
80
+
81
+ When the system receives a webhook event with an unrecognized event type,
82
+ the system shall log the event payload and return HTTP 200 (acknowledge but ignore).
83
+ ```
84
+
85
+ ### Anti-patterns
86
+
87
+ ```
88
+ ❌ When the user does something wrong, show an error.
89
+ → What action? What error? How displayed?
90
+
91
+ ✅ When the user submits a form with an invalid email format,
92
+ the system shall display an inline error message below the email field
93
+ stating "Please enter a valid email address".
94
+ ```
95
+
96
+ ---
97
+
98
+ ## State-Driven Requirements
99
+
100
+ **Template:**
101
+ ```
102
+ While <state>, the <system> shall <action>.
103
+ ```
104
+
105
+ Requirements that apply continuously while the system is in a specific state.
106
+
107
+ ### Examples
108
+
109
+ ```
110
+ While the system is in maintenance mode, the API shall return HTTP 503
111
+ with a "Retry-After" header for all endpoints except /health.
112
+
113
+ While a user account is locked, the system shall reject all login attempts
114
+ and display a message with the unlock time.
115
+
116
+ While the message queue depth exceeds 10,000 messages, the system shall
117
+ activate the secondary consumer group.
118
+
119
+ While the database is performing a backup, the system shall serve read
120
+ requests from the read replica and queue write requests.
121
+
122
+ While the system is operating in degraded mode, the dashboard shall display
123
+ a banner indicating limited functionality and estimated recovery time.
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Unwanted Behavior Requirements
129
+
130
+ **Template:**
131
+ ```
132
+ If <unwanted condition>, then the <system> shall <action>.
133
+ ```
134
+
135
+ Requirements for handling errors, failures, and edge cases. These cover what happens when things go wrong.
136
+
137
+ ### Examples
138
+
139
+ ```
140
+ If the external payment gateway does not respond within 5 seconds,
141
+ then the system shall retry once after 2 seconds, and if the retry
142
+ also fails, return a "payment processing delayed" message to the user.
143
+
144
+ If the database connection pool is exhausted, then the system shall
145
+ queue incoming requests for up to 30 seconds before returning HTTP 503.
146
+
147
+ If a user attempts to access a resource they do not own, then the system
148
+ shall return HTTP 403, log the access attempt with the user ID and resource ID,
149
+ and increment the security audit counter.
150
+
151
+ If the uploaded file contains an unsupported MIME type, then the system shall
152
+ reject the file with a message listing the supported types.
153
+
154
+ If the disk usage exceeds 90%, then the system shall send an alert to the
155
+ operations team and begin purging temporary files older than 24 hours.
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Optional Feature Requirements
161
+
162
+ **Template:**
163
+ ```
164
+ Where <feature is enabled>, the <system> shall <action>.
165
+ ```
166
+
167
+ Requirements that depend on a configurable feature flag or setting.
168
+
169
+ ### Examples
170
+
171
+ ```
172
+ Where two-factor authentication is enabled, the system shall require
173
+ a TOTP code after successful password verification.
174
+
175
+ Where the audit log feature is enabled, the system shall record all
176
+ CRUD operations with the actor, action, resource, and timestamp.
177
+
178
+ Where dark mode is enabled, the system shall render all pages using
179
+ the dark color palette defined in the theme configuration.
180
+
181
+ Where rate limiting is configured, the system shall enforce the configured
182
+ request limit per API key per minute and return HTTP 429 when exceeded.
183
+
184
+ Where email notifications are enabled for a user, the system shall send
185
+ a daily digest of unread notifications at the user's configured time.
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Compound Requirements
191
+
192
+ Complex requirements often combine multiple EARS patterns:
193
+
194
+ ### Event + Unwanted Behavior
195
+
196
+ ```
197
+ When a user submits a password reset request:
198
+ - The system shall send a reset email within 60 seconds.
199
+ - If the email address is not associated with an account, then the system
200
+ shall still return a success message (to prevent email enumeration).
201
+ - If the email service is unavailable, then the system shall queue the
202
+ email for retry and inform the user that the email may be delayed.
203
+ ```
204
+
205
+ ### State + Event
206
+
207
+ ```
208
+ While the system is in read-only mode:
209
+ - When a user attempts a write operation, the system shall return HTTP 503
210
+ with a message indicating when write access will be restored.
211
+ - When an admin issues a "restore write access" command, the system shall
212
+ exit read-only mode and process any queued write operations in order.
213
+ ```
214
+
215
+ ### Requirement Hierarchies
216
+
217
+ For complex features, use parent-child numbering:
218
+
219
+ ```
220
+ FR-1: User Registration
221
+ FR-1.1: When a user submits the registration form, the system shall
222
+ create an account and send a verification email.
223
+ FR-1.2: If the email is already registered, then the system shall
224
+ display "An account with this email already exists".
225
+ FR-1.3: The system shall require passwords of at least 12 characters
226
+ with at least one uppercase letter and one digit.
227
+ FR-1.4: Where CAPTCHA is enabled, the registration form shall include
228
+ a CAPTCHA challenge before submission.
229
+ ```
230
+
231
+ ---
232
+
233
+ ## Writing Tips
234
+
235
+ 1. **One requirement per statement.** Don't combine multiple behaviors in one sentence.
236
+ 2. **Use "shall" for requirements, "should" for recommendations, "may" for optional.** This is standard requirement language (RFC 2119).
237
+ 3. **Be specific about quantities.** Not "quickly" but "within 200ms". Not "many" but "up to 1000".
238
+ 4. **Name the actor.** "The system shall..." or "The user shall..." -- never the passive "It should be done".
239
+ 5. **State the observable behavior.** Requirements describe what the system does, not how it does it internally.
@@ -14,47 +14,50 @@ import sys
14
14
  # Patterns that should be protected from modification
15
15
  PROTECTED_PATTERNS = [
16
16
  # Environment secrets
17
- (r'(^|/)\.env$', "Blocked: .env contains secrets - edit manually if needed"),
18
- (r'(^|/)\.env\.[^/]+$', "Blocked: .env.* files contain secrets - edit manually if needed"),
19
-
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
+ ),
20
22
  # Git internals
21
- (r'(^|/)\.git/', "Blocked: .git/ directory is managed by git"),
22
-
23
+ (r"(^|/)\.git/", "Blocked: .git/ directory is managed by git"),
23
24
  # Lock files (should be modified via package manager)
24
- (r'(^|/)package-lock\.json$', "Blocked: package-lock.json - use npm install instead"),
25
- (r'(^|/)yarn\.lock$', "Blocked: yarn.lock - use yarn install instead"),
26
- (r'(^|/)pnpm-lock\.yaml$', "Blocked: pnpm-lock.yaml - use pnpm install instead"),
27
- (r'(^|/)Gemfile\.lock$', "Blocked: Gemfile.lock - use bundle install instead"),
28
- (r'(^|/)poetry\.lock$', "Blocked: poetry.lock - use poetry install instead"),
29
- (r'(^|/)Cargo\.lock$', "Blocked: Cargo.lock - use cargo build instead"),
30
- (r'(^|/)composer\.lock$', "Blocked: composer.lock - use composer install instead"),
31
- (r'(^|/)uv\.lock$', "Blocked: uv.lock - use uv sync instead"),
32
-
25
+ (
26
+ r"(^|/)package-lock\.json$",
27
+ "Blocked: package-lock.json - use npm install instead",
28
+ ),
29
+ (r"(^|/)yarn\.lock$", "Blocked: yarn.lock - use yarn install instead"),
30
+ (r"(^|/)pnpm-lock\.yaml$", "Blocked: pnpm-lock.yaml - use pnpm install instead"),
31
+ (r"(^|/)Gemfile\.lock$", "Blocked: Gemfile.lock - use bundle install instead"),
32
+ (r"(^|/)poetry\.lock$", "Blocked: poetry.lock - use poetry install instead"),
33
+ (r"(^|/)Cargo\.lock$", "Blocked: Cargo.lock - use cargo build instead"),
34
+ (r"(^|/)composer\.lock$", "Blocked: composer.lock - use composer install instead"),
35
+ (r"(^|/)uv\.lock$", "Blocked: uv.lock - use uv sync instead"),
33
36
  # Certificates and keys
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
-
37
+ (r"\.pem$", "Blocked: .pem files contain sensitive cryptographic material"),
38
+ (r"\.key$", "Blocked: .key files contain sensitive cryptographic material"),
39
+ (r"\.crt$", "Blocked: .crt certificate files should not be edited directly"),
40
+ (r"\.p12$", "Blocked: .p12 files contain sensitive cryptographic material"),
41
+ (r"\.pfx$", "Blocked: .pfx files contain sensitive cryptographic material"),
40
42
  # Credential files
41
- (r'(^|/)credentials\.json$', "Blocked: credentials.json contains secrets"),
42
- (r'(^|/)secrets\.yaml$', "Blocked: secrets.yaml contains secrets"),
43
- (r'(^|/)secrets\.yml$', "Blocked: secrets.yml contains secrets"),
44
- (r'(^|/)secrets\.json$', "Blocked: secrets.json contains secrets"),
45
- (r'(^|/)\.secrets$', "Blocked: .secrets file contains secrets"),
46
-
43
+ (r"(^|/)credentials\.json$", "Blocked: credentials.json contains secrets"),
44
+ (r"(^|/)secrets\.yaml$", "Blocked: secrets.yaml contains secrets"),
45
+ (r"(^|/)secrets\.yml$", "Blocked: secrets.yml contains secrets"),
46
+ (r"(^|/)secrets\.json$", "Blocked: secrets.json contains secrets"),
47
+ (r"(^|/)\.secrets$", "Blocked: .secrets file contains secrets"),
47
48
  # Auth directories and files
48
- (r'(^|/)\.ssh/', "Blocked: .ssh/ contains sensitive authentication data"),
49
- (r'(^|/)\.aws/', "Blocked: .aws/ contains AWS credentials"),
50
- (r'(^|/)\.netrc$', "Blocked: .netrc contains authentication credentials"),
51
- (r'(^|/)\.npmrc$', "Blocked: .npmrc may contain auth tokens - edit manually if needed"),
52
- (r'(^|/)\.pypirc$', "Blocked: .pypirc contains PyPI credentials"),
53
-
49
+ (r"(^|/)\.ssh/", "Blocked: .ssh/ contains sensitive authentication data"),
50
+ (r"(^|/)\.aws/", "Blocked: .aws/ contains AWS credentials"),
51
+ (r"(^|/)\.netrc$", "Blocked: .netrc contains authentication credentials"),
52
+ (
53
+ r"(^|/)\.npmrc$",
54
+ "Blocked: .npmrc may contain auth tokens - edit manually if needed",
55
+ ),
56
+ (r"(^|/)\.pypirc$", "Blocked: .pypirc contains PyPI credentials"),
54
57
  # Other sensitive files
55
- (r'(^|/)id_rsa', "Blocked: SSH private key file"),
56
- (r'(^|/)id_ed25519', "Blocked: SSH private key file"),
57
- (r'(^|/)id_ecdsa', "Blocked: SSH private key file"),
58
+ (r"(^|/|-)id_rsa($|\.)", "Blocked: SSH private key file"),
59
+ (r"(^|/)id_ed25519", "Blocked: SSH private key file"),
60
+ (r"(^|/)id_ecdsa", "Blocked: SSH private key file"),
58
61
  ]
59
62
 
60
63
 
@@ -65,7 +68,7 @@ def check_path(file_path: str) -> tuple[bool, str]:
65
68
  (is_protected, message)
66
69
  """
67
70
  # Normalize path for consistent matching
68
- normalized = file_path.replace('\\', '/')
71
+ normalized = file_path.replace("\\", "/")
69
72
 
70
73
  for pattern, message in PROTECTED_PATTERNS:
71
74
  if re.search(pattern, normalized, re.IGNORECASE):
@@ -87,9 +90,7 @@ def main():
87
90
 
88
91
  if is_protected:
89
92
  # Output error message and exit 2 to block
90
- print(json.dumps({
91
- "error": message
92
- }))
93
+ print(json.dumps({"error": message}))
93
94
  sys.exit(2)
94
95
 
95
96
  # Allow edit to proceed
@@ -6,8 +6,8 @@ CLAUDE_DIR="${CLAUDE_CONFIG_DIR:?CLAUDE_CONFIG_DIR not set}"
6
6
  echo "[setup-aliases] Configuring Claude aliases..."
7
7
 
8
8
  # Simple alias definitions (not functions — functions don't behave reliably across shell contexts)
9
- ALIAS_CC='alias cc='"'"'command claude --system-prompt-file .claude/system-prompt.md --permission-mode plan --allow-dangerously-skip-permissions'"'"''
10
- ALIAS_CLAUDE='alias claude='"'"'command claude --system-prompt-file .claude/system-prompt.md --permission-mode plan --allow-dangerously-skip-permissions'"'"''
9
+ ALIAS_CC='alias cc='"'"'CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 command claude --system-prompt-file "$CLAUDE_CONFIG_DIR/system-prompt.md" --permission-mode plan --allow-dangerously-skip-permissions'"'"''
10
+ ALIAS_CLAUDE='alias claude='"'"'CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 command claude --system-prompt-file "$CLAUDE_CONFIG_DIR/system-prompt.md" --permission-mode plan --allow-dangerously-skip-permissions'"'"''
11
11
  ALIAS_CCRAW='alias ccraw="command claude"'
12
12
 
13
13
  for rc in ~/.bashrc ~/.zshrc; do
@@ -47,7 +47,12 @@ for rc in ~/.bashrc ~/.zshrc; do
47
47
  sed -i '/alias specwright=/d' "$rc"
48
48
  fi
49
49
 
50
- # --- Add environment, auto-tmux, and aliases ---
50
+ # --- Add environment and aliases (idempotent) ---
51
+ # Guard: skip if aliases already present from a previous run
52
+ if grep -q '# Claude Code environment and aliases' "$rc" 2>/dev/null; then
53
+ echo "[setup-aliases] Aliases already present in $(basename $rc), skipping"
54
+ continue
55
+ fi
51
56
  echo "" >> "$rc"
52
57
  echo "# Claude Code environment and aliases (managed by setup-aliases.sh)" >> "$rc"
53
58
  # Export CLAUDE_CONFIG_DIR so it's available in all shells (not just VS Code remoteEnv)
@@ -59,21 +64,6 @@ for rc in ~/.bashrc ~/.zshrc; do
59
64
  echo 'export LANG=en_US.UTF-8' >> "$rc"
60
65
  echo 'export LC_ALL=en_US.UTF-8' >> "$rc"
61
66
  fi
62
- # Auto-enter tmux for Agent Teams split-pane support
63
- # Guards: not already in tmux, interactive shell only, tmux available
64
- if ! grep -q 'Auto-enter tmux' "$rc" 2>/dev/null; then
65
- cat >> "$rc" << 'TMUX_BLOCK'
66
-
67
- # Auto-enter tmux for Agent Teams split-pane support
68
- if [ -z "$TMUX" ] && [ -n "$PS1" ] && command -v tmux &>/dev/null; then
69
- if tmux has-session -t claude-teams 2>/dev/null; then
70
- exec tmux -u new-session -t claude-teams
71
- else
72
- exec tmux -u new-session -s claude-teams
73
- fi
74
- fi
75
- TMUX_BLOCK
76
- fi
77
67
  echo "$ALIAS_CC" >> "$rc"
78
68
  echo "$ALIAS_CLAUDE" >> "$rc"
79
69
  echo "$ALIAS_CCRAW" >> "$rc"
@@ -82,6 +72,6 @@ TMUX_BLOCK
82
72
  done
83
73
 
84
74
  echo "[setup-aliases] Aliases configured:"
85
- echo " cc -> claude with local .claude/system-prompt.md"
86
- echo " claude -> claude with local .claude/system-prompt.md"
75
+ echo " cc -> claude with \$CLAUDE_CONFIG_DIR/system-prompt.md"
76
+ echo " claude -> claude with \$CLAUDE_CONFIG_DIR/system-prompt.md"
87
77
  echo " ccraw -> vanilla claude without any config"
@@ -15,6 +15,7 @@ copy_file() {
15
15
  if [ -f "$CONFIG_DIR/$file" ]; then
16
16
  if [ "$OVERWRITE" = "true" ] || [ ! -f "$TARGET_DIR/$file" ]; then
17
17
  cp "$CONFIG_DIR/$file" "$TARGET_DIR/$file"
18
+ chown "$(id -un):$(id -gn)" "$TARGET_DIR/$file" 2>/dev/null || true
18
19
  echo "[setup-config] Copied $file"
19
20
  else
20
21
  echo "[setup-config] $file already exists, skipping"
@@ -23,6 +24,7 @@ copy_file() {
23
24
  }
24
25
 
25
26
  copy_file "settings.json"
27
+ copy_file "keybindings.json"
26
28
  copy_file "main-system-prompt.md"
27
29
 
28
30
  echo "[setup-config] Configuration complete"
@@ -1,5 +1,21 @@
1
1
  #!/bin/bash
2
- # Install plugins: official Anthropic + local devs-marketplace
2
+ # Install plugins: official Anthropic + local devs-marketplace registration
3
+ #
4
+ # Individual marketplace plugins are enabled via enabledPlugins in settings.json.
5
+ # This script only handles:
6
+ # 1. Official Anthropic plugin installs (not managed by enabledPlugins)
7
+ # 2. Local marketplace registration (so Claude Code can discover devs-marketplace)
8
+
9
+ # Source .env for PLUGIN_BLACKLIST if not already set (e.g., standalone invocation)
10
+ if [ -z "${PLUGIN_BLACKLIST+x}" ]; then
11
+ SCRIPT_DIR_INIT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
+ ENV_FILE="${SCRIPT_DIR_INIT}/../.env"
13
+ if [ -f "$ENV_FILE" ]; then
14
+ set -a
15
+ source "$ENV_FILE"
16
+ set +a
17
+ fi
18
+ fi
3
19
 
4
20
  echo "[setup-plugins] Installing plugins..."
5
21
 
@@ -18,33 +34,13 @@ for plugin in "${OFFICIAL_PLUGINS[@]}"; do
18
34
  fi
19
35
  done
20
36
 
21
- # --- Local Marketplace Plugins ---
37
+ # --- Local Marketplace Registration ---
22
38
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
39
  MARKETPLACE_PATH="${SCRIPT_DIR}/../plugins/devs-marketplace"
24
40
 
25
- # Load PLUGIN_BLACKLIST from .env if not already set in environment
26
- ENV_FILE="${SCRIPT_DIR}/../.env"
27
- if [ -z "${PLUGIN_BLACKLIST+x}" ] && [ -f "$ENV_FILE" ]; then
28
- PLUGIN_BLACKLIST=$(grep -E '^PLUGIN_BLACKLIST=' "$ENV_FILE" | cut -d'=' -f2- | tr -d '"')
29
- fi
30
-
31
- # Parse blacklist into array
32
- IFS=',' read -ra BLACKLIST <<< "${PLUGIN_BLACKLIST:-}"
33
-
34
- # Helper function to check if plugin is blacklisted
35
- is_blacklisted() {
36
- local plugin_name="$1"
37
- for blocked in "${BLACKLIST[@]}"; do
38
- # Trim whitespace and compare
39
- blocked="${blocked// /}"
40
- if [ "$plugin_name" = "$blocked" ]; then
41
- return 0
42
- fi
43
- done
44
- return 1
45
- }
46
-
47
41
  # Add local marketplace (if not already added)
42
+ # This is still needed so Claude Code can discover devs-marketplace plugins
43
+ # listed in enabledPlugins in settings.json
48
44
  if ! claude plugin marketplace list 2>/dev/null | grep -q "devs-marketplace"; then
49
45
  echo "[setup-plugins] Adding devs-marketplace..."
50
46
  claude plugin marketplace add "$MARKETPLACE_PATH" 2>/dev/null || {
@@ -52,29 +48,25 @@ if ! claude plugin marketplace list 2>/dev/null | grep -q "devs-marketplace"; th
52
48
  }
53
49
  fi
54
50
 
55
- # Install ALL plugins from marketplace.json (dynamic discovery)
56
- MARKETPLACE_JSON="$MARKETPLACE_PATH/.claude-plugin/marketplace.json"
57
- if [ -f "$MARKETPLACE_JSON" ]; then
58
- PLUGINS=$(jq -r '.plugins[].name' "$MARKETPLACE_JSON" 2>/dev/null)
51
+ # --- Install/Update devs-marketplace plugins (syncs cache from source) ---
52
+ # enabledPlugins in settings.json controls enabled/disabled state, but plugins
53
+ # must be explicitly installed to populate the cache. This loop ensures the
54
+ # cache stays in sync with the source directory on every container start.
55
+ if [ -d "$MARKETPLACE_PATH/plugins" ]; then
56
+ for plugin_dir in "$MARKETPLACE_PATH"/plugins/*/; do
57
+ plugin_name=$(basename "$plugin_dir")
59
58
 
60
- if [ -z "$PLUGINS" ]; then
61
- echo "[setup-plugins] WARNING: No plugins found in marketplace.json"
62
- else
63
- for plugin in $PLUGINS; do
64
- if is_blacklisted "$plugin"; then
65
- echo "[setup-plugins] Skipping $plugin (blacklisted)"
66
- continue
67
- fi
68
- echo "[setup-plugins] Installing $plugin from devs-marketplace..."
69
- if claude plugin install "${plugin}@devs-marketplace" 2>/dev/null; then
70
- echo "[setup-plugins] Installed: $plugin"
71
- else
72
- echo "[setup-plugins] WARNING: Failed to install $plugin (may already be installed)"
73
- fi
74
- done
75
- fi
76
- else
77
- echo "[setup-plugins] WARNING: marketplace.json not found at $MARKETPLACE_JSON"
59
+ # Skip blacklisted plugins
60
+ if echo ",$PLUGIN_BLACKLIST," | grep -q ",$plugin_name,"; then
61
+ echo "[setup-plugins] Skipping $plugin_name (blacklisted)"
62
+ continue
63
+ fi
64
+
65
+ echo "[setup-plugins] Installing $plugin_name@devs-marketplace..."
66
+ claude plugin install "$plugin_name@devs-marketplace" 2>/dev/null || {
67
+ echo "[setup-plugins] Warning: Failed to install $plugin_name"
68
+ }
69
+ done
78
70
  fi
79
71
 
80
72
  echo "[setup-plugins] Plugin installation complete"