codeforge-dev 1.8.0 → 1.10.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 (55) hide show
  1. package/.devcontainer/.env +3 -0
  2. package/.devcontainer/CHANGELOG.md +107 -0
  3. package/.devcontainer/CLAUDE.md +30 -9
  4. package/.devcontainer/README.md +61 -2
  5. package/.devcontainer/config/defaults/main-system-prompt.md +162 -128
  6. package/.devcontainer/config/defaults/rules/spec-workflow.md +75 -0
  7. package/.devcontainer/config/defaults/rules/workspace-scope.md +7 -0
  8. package/.devcontainer/config/defaults/settings.json +63 -66
  9. package/.devcontainer/config/file-manifest.json +30 -18
  10. package/.devcontainer/connect-external-terminal.sh +17 -17
  11. package/.devcontainer/devcontainer.json +143 -144
  12. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +104 -97
  13. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/.claude-plugin/plugin.json +7 -0
  14. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/README.md +158 -0
  15. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/hooks/hooks.json +39 -0
  16. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/collect-edited-files.py +47 -0
  17. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/format-on-stop.py +297 -0
  18. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/lint-file.py +536 -0
  19. package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/syntax-validator.py +146 -0
  20. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/architect.md +81 -4
  21. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/debug-logs.md +18 -0
  22. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/dependency-analyst.md +18 -0
  23. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/doc-writer.md +89 -4
  24. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/explorer.md +18 -0
  25. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/generalist.md +142 -8
  26. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/git-archaeologist.md +18 -0
  27. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/migrator.md +108 -1
  28. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/perf-profiler.md +24 -0
  29. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/refactorer.md +97 -1
  30. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/researcher.md +33 -1
  31. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/security-auditor.md +24 -0
  32. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/spec-writer.md +50 -12
  33. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/agents/test-writer.md +96 -1
  34. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/hooks/hooks.json +100 -95
  35. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/advisory-test-runner.py +186 -13
  36. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/scripts/spec-reminder.py +122 -0
  37. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/documentation-patterns/SKILL.md +1 -1
  38. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-check/SKILL.md +98 -0
  39. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/SKILL.md +99 -0
  40. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/backlog-template.md +23 -0
  41. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-init/references/roadmap-template.md +33 -0
  42. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/SKILL.md +110 -0
  43. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-new/references/template.md +129 -0
  44. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-refine/SKILL.md +194 -0
  45. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/spec-update/SKILL.md +142 -0
  46. package/.devcontainer/plugins/devs-marketplace/plugins/code-directive/skills/specification-writing/SKILL.md +19 -12
  47. package/.devcontainer/scripts/check-setup.sh +24 -25
  48. package/.devcontainer/scripts/setup-aliases.sh +88 -76
  49. package/.devcontainer/scripts/setup-config.sh +86 -83
  50. package/.devcontainer/scripts/setup-projects.sh +172 -131
  51. package/.devcontainer/scripts/setup-terminal.sh +48 -0
  52. package/.devcontainer/scripts/setup-update-claude.sh +49 -107
  53. package/.devcontainer/scripts/setup.sh +4 -17
  54. package/README.md +2 -2
  55. package/package.json +42 -42
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: spec-update
3
+ description: >-
4
+ This skill should be used when the user asks to "update the spec",
5
+ "mark spec as implemented", "as-built update", "spec maintenance",
6
+ "update spec status", "finish the spec", or after implementing a
7
+ feature when the spec needs to reflect what was actually built.
8
+ version: 0.1.0
9
+ ---
10
+
11
+ # As-Built Spec Update
12
+
13
+ ## Mental Model
14
+
15
+ Specs that say "planned" after code ships cause the next AI session to re-plan already-done work. The as-built update is the final step of every implementation — it closes the loop between what was planned and what was built.
16
+
17
+ This is not optional. Every implementation ends with a spec update.
18
+
19
+ ---
20
+
21
+ ## Approval Gate
22
+
23
+ Before performing an as-built update, check the spec's `**Approval:**` status:
24
+ - If `user-approved` → proceed with the update
25
+ - If `draft` → warn the user: "This spec is still `draft`. It should have gone through `/spec-refine` before implementation. Run `/spec-refine` now to validate, or proceed with the as-built update if the user confirms."
26
+
27
+ This is a warning, not a blocker — the user decides whether to refine first or update as-is.
28
+
29
+ ---
30
+
31
+ ## The 6-Step Workflow
32
+
33
+ ### Step 1: Find the Spec
34
+
35
+ ```
36
+ Glob: .specs/**/*.md
37
+ ```
38
+
39
+ Search for the feature name in spec file names and content. If the user provides a spec path or feature name as `$ARGUMENTS`, use that directly.
40
+
41
+ If no spec exists:
42
+ - For substantial changes: create one using `/spec-new`
43
+ - For trivial changes (bug fixes, config): note "spec not needed" and stop
44
+
45
+ ### Step 2: Set Status
46
+
47
+ Update the `**Status:**` field:
48
+ - `implemented` — all acceptance criteria are met
49
+ - `partial` — some criteria met, work ongoing or deferred
50
+
51
+ Never leave status as `planned` after implementation work has been done.
52
+
53
+ ### Step 3: Check Off Acceptance Criteria
54
+
55
+ Review each acceptance criterion in the spec:
56
+ - Mark as `[x]` if the criterion is met and verified (tests pass, behavior confirmed)
57
+ - Leave as `[ ]` if not yet implemented
58
+ - Add a note next to deferred criteria explaining why
59
+
60
+ If criteria were met through different means than originally planned, note the deviation.
61
+
62
+ ### Step 4: Add Implementation Notes
63
+
64
+ In the `## Implementation Notes` section, document:
65
+ - **Deviations from the original spec** — what changed and why
66
+ - **Key design decisions made during implementation** — choices that weren't in the spec
67
+ - **Surprising findings** — edge cases discovered, performance characteristics, limitations
68
+ - **Trade-offs accepted** — what was sacrificed and why
69
+
70
+ Keep notes concise. Reference file paths, not code.
71
+
72
+ ### Step 5: Update File Paths
73
+
74
+ In the `## Key Files` section:
75
+ - Add files that were created during implementation
76
+ - Remove files that no longer exist
77
+ - Update paths that moved
78
+
79
+ Verify paths exist before listing them. Use absolute project-relative paths.
80
+
81
+ ### Step 6: Update Metadata
82
+
83
+ - Set `**Last Updated:**` to today's date (YYYY-MM-DD)
84
+ - Verify `**Version:**` is correct
85
+ - Preserve the `**Approval:**` status — do NOT downgrade `user-approved` to `draft`
86
+ - If the as-built update introduces new decisions not in the original spec, add them to `## Resolved Questions` if the user confirmed them, or `## Open Questions` if they were assumed during implementation
87
+
88
+ ---
89
+
90
+ ## Handling Edge Cases
91
+
92
+ ### Spec Already "Implemented"
93
+
94
+ If the spec is already marked `implemented` and new changes affect the feature:
95
+ 1. Check if acceptance criteria still hold
96
+ 2. Update Implementation Notes with the new changes
97
+ 3. Add any new Discrepancies between spec and current code
98
+ 4. Update Last Updated date
99
+
100
+ ### No Spec Exists
101
+
102
+ If there is no spec for the feature:
103
+ 1. Ask: is this a substantial feature or a minor fix?
104
+ 2. For substantial features: create one with `/spec-new`, then update it
105
+ 3. For minor fixes: no spec needed — report this and stop
106
+
107
+ ### Spec Has Unresolved Discrepancies
108
+
109
+ If the `## Discrepancies` section has open items:
110
+ 1. Check if the current implementation resolves any of them
111
+ 2. Remove resolved discrepancies
112
+ 3. Add any new discrepancies discovered
113
+
114
+ ---
115
+
116
+ ## Validation Checklist
117
+
118
+ Before finishing the update:
119
+ - [ ] Status reflects the actual implementation state
120
+ - [ ] All implemented acceptance criteria are checked off
121
+ - [ ] Implementation Notes document deviations from original spec
122
+ - [ ] File paths in Key Files are accurate and verified
123
+ - [ ] Last Updated date is today
124
+ - [ ] `**Approval:**` status is preserved (not downgraded)
125
+ - [ ] New implementation decisions are tracked in Resolved Questions or Open Questions
126
+ - [ ] If the spec has grown past ~200 lines, note it and suggest splitting in a future pass
127
+ - [ ] If `**Approval:**` is still `draft`, user was warned and confirmed proceeding
128
+ - [ ] No source code was pasted inline (references only)
129
+
130
+ ---
131
+
132
+ ## Ambiguity Policy
133
+
134
+ - If unclear which spec to update, list all candidates and ask the user.
135
+ - If the implementation deviated significantly from the spec, document it
136
+ honestly in Implementation Notes — do not retroactively change the original
137
+ requirements to match what was built.
138
+ - If acceptance criteria are ambiguous about whether they're met, note the
139
+ ambiguity in Discrepancies rather than checking them off optimistically.
140
+ - A spec-reminder advisory hook fires at Stop when code was modified but
141
+ specs weren't updated. If you see "[Spec Reminder]" in context, that's
142
+ the trigger — use this skill to resolve it.
@@ -30,11 +30,11 @@ Write specifications with a hostile reader in mind -- someone who will interpret
30
30
 
31
31
  ---
32
32
 
33
- ## Spec Sizing & AI Context Rules
33
+ ## Spec Sizing Guidelines
34
34
 
35
35
  Specifications are loaded into AI context windows with limited capacity. Design for consumption.
36
36
 
37
- **Hard limit:** 200 lines per spec file. If a feature needs more, split into sub-specs (one per sub-feature) with a ≤50 line overview linking them.
37
+ **Recommended target:** ~200 lines per spec file. When a spec grows beyond that, consider splitting into sub-specs (one per sub-feature) with a concise overview linking them. Complex features may justify longer specs — completeness matters more than hitting a number.
38
38
 
39
39
  **Reference, don't reproduce:** Never inline source code, SQL DDL, Pydantic models, or TypeScript interfaces. Reference the file path and line range instead. The code is the source of truth — duplicated snippets go stale silently.
40
40
 
@@ -179,9 +179,10 @@ Every spec file starts with metadata:
179
179
  **Version:** v0.X.0
180
180
  **Status:** implemented | partial | planned
181
181
  **Last Updated:** YYYY-MM-DD
182
+ **Approval:** draft | user-approved
182
183
  ```
183
184
 
184
- Status tells you whether to trust it, version tells you where it belongs, last-updated tells you when it was last verified.
185
+ Status tells you whether to trust it, version tells you where it belongs, last-updated tells you when it was last verified. Approval tells you whether decisions in the spec have been explicitly validated by the user (`user-approved`) or are AI-generated hypotheses (`draft`).
185
186
 
186
187
  ### 1. Problem Statement
187
188
  What problem does this feature solve? Who has this problem? What's the cost of not solving it? (2-3 sentences)
@@ -218,20 +219,22 @@ so that [I can detect suspicious reset patterns].
218
219
  Use EARS format. Number each requirement for traceability:
219
220
 
220
221
  ```markdown
221
- - FR-1: When a user requests a password reset, the system shall send a reset email
222
+ - FR-1 [assumed]: When a user requests a password reset, the system shall send a reset email
222
223
  to the registered email address within 60 seconds.
223
- - FR-2: The reset link shall contain a cryptographically random token (min 32 bytes).
224
- - FR-3: If the reset token is expired or already used, then the system shall display
224
+ - FR-2 [assumed]: The reset link shall contain a cryptographically random token (min 32 bytes).
225
+ - FR-3 [assumed]: If the reset token is expired or already used, then the system shall display
225
226
  an error message and offer to send a new reset email.
227
+
228
+ Tag each requirement `[assumed]` when first written. Requirements become `[user-approved]` only after explicit user validation via `/spec-refine`.
226
229
  ```
227
230
 
228
231
  ### 5. Non-Functional Requirements
229
232
  Performance, security, scalability, accessibility:
230
233
 
231
234
  ```markdown
232
- - NFR-1: The password reset endpoint shall respond within 200ms (p95).
233
- - NFR-2: Reset tokens shall be stored as bcrypt hashes, not plaintext.
234
- - NFR-3: The reset flow shall be accessible with screen readers (WCAG 2.1 AA).
235
+ - NFR-1 [assumed]: The password reset endpoint shall respond within 200ms (p95).
236
+ - NFR-2 [assumed]: Reset tokens shall be stored as bcrypt hashes, not plaintext.
237
+ - NFR-3 [assumed]: The reset flow shall be accessible with screen readers (WCAG 2.1 AA).
235
238
  ```
236
239
 
237
240
  ### 6. Edge Cases
@@ -249,13 +252,16 @@ The cases nobody thinks about until they happen:
249
252
  ### 7. Out of Scope
250
253
  Explicit non-goals to prevent scope creep (can reference the Scope section or expand here).
251
254
 
252
- ### 8. Key Files
255
+ ### 8. Resolved Questions
256
+ Decisions explicitly approved by the user via `/spec-refine`. Each entry: decision topic, chosen option, options considered, date, brief rationale. This section starts empty and is populated during the refinement process.
257
+
258
+ ### 9. Key Files
253
259
  Source files most relevant to this feature — paths an implementer should read.
254
260
 
255
- ### 9. Implementation Notes
261
+ ### 10. Implementation Notes
256
262
  Post-implementation only. Capture deviations from the original spec — what changed and why.
257
263
 
258
- ### 10. Discrepancies
264
+ ### 11. Discrepancies
259
265
  Gaps between spec intent and actual build. Prevents the next session from re-planning decided work.
260
266
 
261
267
  ---
@@ -309,6 +315,7 @@ These defaults apply when the user does not specify a preference. State the assu
309
315
  - **Edge cases:** Always include at least: empty input, maximum input, concurrent access, and external service failure.
310
316
  - **Out of scope:** Always include an out-of-scope section, even if brief, to establish boundaries.
311
317
  - **Numbering:** Number all requirements (FR-1, NFR-1) for traceability in code reviews and tests.
318
+ - **Approval markers:** All requirements start as `[assumed]`. Only `/spec-refine` with explicit user validation upgrades them to `[user-approved]`. Spec-level `**Approval:**` starts as `draft` and becomes `user-approved` only when all requirements are `[user-approved]`.
312
319
 
313
320
  ---
314
321
 
@@ -5,34 +5,37 @@
5
5
  echo "CodeForge Setup Check"
6
6
  echo "━━━━━━━━━━━━━━━━━━━━"
7
7
 
8
- PASS=0; FAIL=0; WARN=0
8
+ PASS=0
9
+ FAIL=0
10
+ WARN=0
9
11
 
10
12
  check() {
11
- local label="$1" cmd="$2"
12
- if eval "$cmd" >/dev/null 2>&1; then
13
- printf " ✓ %s\n" "$label"
14
- PASS=$((PASS + 1))
15
- else
16
- printf " ✗ %s\n" "$label"
17
- FAIL=$((FAIL + 1))
18
- fi
13
+ local label="$1" cmd="$2"
14
+ if eval "$cmd" >/dev/null 2>&1; then
15
+ printf " ✓ %s\n" "$label"
16
+ PASS=$((PASS + 1))
17
+ else
18
+ printf " ✗ %s\n" "$label"
19
+ FAIL=$((FAIL + 1))
20
+ fi
19
21
  }
20
22
 
21
23
  warn_check() {
22
- local label="$1" cmd="$2"
23
- if eval "$cmd" >/dev/null 2>&1; then
24
- printf " ✓ %s\n" "$label"
25
- PASS=$((PASS + 1))
26
- else
27
- printf " ⚠ %s\n" "$label"
28
- WARN=$((WARN + 1))
29
- fi
24
+ local label="$1" cmd="$2"
25
+ if eval "$cmd" >/dev/null 2>&1; then
26
+ printf " ✓ %s\n" "$label"
27
+ PASS=$((PASS + 1))
28
+ else
29
+ printf " ⚠ %s\n" "$label"
30
+ WARN=$((WARN + 1))
31
+ fi
30
32
  }
31
33
 
32
34
  echo ""
33
35
  echo "Core:"
34
36
  check "Claude Code installed" "command -v claude"
35
- check "cc alias available" "type cc"
37
+ warn_check "Claude native binary" "[ -x /usr/local/bin/claude ]"
38
+ check "cc alias configured" "grep -q 'alias cc=' ~/.bashrc 2>/dev/null || grep -q 'alias cc=' ~/.zshrc 2>/dev/null"
36
39
  check "Config directory exists" "[ -d '${CLAUDE_CONFIG_DIR:-/workspaces/.claude}' ]"
37
40
  check "Settings file exists" "[ -f '${CLAUDE_CONFIG_DIR:-/workspaces/.claude}/settings.json' ]"
38
41
 
@@ -54,10 +57,6 @@ echo ""
54
57
  echo "Development:"
55
58
  warn_check "biome" "command -v biome"
56
59
  warn_check "ruff" "command -v ruff"
57
- warn_check "dprint" "command -v dprint"
58
- warn_check "shfmt" "command -v shfmt"
59
- warn_check "shellcheck" "command -v shellcheck"
60
- warn_check "hadolint" "command -v hadolint"
61
60
  warn_check "ast-grep" "command -v ast-grep"
62
61
  warn_check "tmux" "command -v tmux"
63
62
 
@@ -66,7 +65,7 @@ echo "━━━━━━━━━━━━━━━━━━━━"
66
65
  echo " $PASS passed, $FAIL failed, $WARN warnings"
67
66
 
68
67
  if [ $FAIL -gt 0 ]; then
69
- echo ""
70
- echo " Run 'cc-tools' for detailed version info."
71
- exit 1
68
+ echo ""
69
+ echo " Run 'cc-tools' for detailed version info."
70
+ exit 1
72
71
  fi
@@ -6,82 +6,94 @@ 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='"'"'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
- ALIAS_CCRAW='alias ccraw="command claude"'
9
+ # Aliases reference $_CLAUDE_BIN which is resolved at shell startup to prefer the native binary.
10
+ ALIAS_CC='alias cc='"'"'CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 command "$_CLAUDE_BIN" --system-prompt-file "$CLAUDE_CONFIG_DIR/system-prompt.md" --permission-mode plan --allow-dangerously-skip-permissions'"'"''
11
+ ALIAS_CLAUDE='alias claude='"'"'CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 command "$_CLAUDE_BIN" --system-prompt-file "$CLAUDE_CONFIG_DIR/system-prompt.md" --permission-mode plan --allow-dangerously-skip-permissions'"'"''
12
+ ALIAS_CCRAW='alias ccraw='"'"'command "$_CLAUDE_BIN"'"'"''
12
13
 
13
14
  for rc in ~/.bashrc ~/.zshrc; do
14
- if [ -f "$rc" ]; then
15
- # --- Backup before modifying ---
16
- cp "$rc" "${rc}.bak.$(date +%s)" 2>/dev/null || true
17
- # Clean old backups (keep last 3)
18
- ls -t "${rc}.bak."* 2>/dev/null | tail -n +4 | xargs rm -f 2>/dev/null || true
15
+ if [ -f "$rc" ]; then
16
+ # --- Backup before modifying ---
17
+ cp "$rc" "${rc}.bak.$(date +%s)" 2>/dev/null || true
18
+ # Clean old backups (keep last 3)
19
+ ls -t "${rc}.bak."* 2>/dev/null | tail -n +4 | xargs rm -f 2>/dev/null || true
19
20
 
20
- # --- Cleanup old definitions ---
21
+ # --- Cleanup old definitions ---
21
22
 
22
- # Remove old cc alias
23
- if grep -q "alias cc=" "$rc" 2>/dev/null; then
24
- sed -i '/alias cc=/d' "$rc"
25
- echo "[setup-aliases] Removed old cc alias from $(basename $rc)"
26
- fi
27
- # Remove old cc function (single-line or multi-line)
28
- if grep -q "^cc()" "$rc" 2>/dev/null; then
29
- sed -i '/^cc() {/,/^}/d' "$rc"
30
- echo "[setup-aliases] Removed old cc function from $(basename $rc)"
31
- fi
32
- # Remove old _claude_with_config function
33
- if grep -q "^_claude_with_config()" "$rc" 2>/dev/null; then
34
- sed -i '/^_claude_with_config() {/,/^}/d' "$rc"
35
- echo "[setup-aliases] Removed old _claude_with_config function from $(basename $rc)"
36
- fi
37
- # Remove old claude function override
38
- if grep -q "^claude() {" "$rc" 2>/dev/null; then
39
- sed -i '/^claude() { _claude_with_config/d' "$rc"
40
- echo "[setup-aliases] Removed old claude function from $(basename $rc)"
41
- fi
42
- # Remove old claude alias
43
- if grep -q "alias claude=" "$rc" 2>/dev/null; then
44
- sed -i '/alias claude=/d' "$rc"
45
- fi
46
- # Remove old ccraw alias
47
- if grep -q "alias ccraw=" "$rc" 2>/dev/null; then
48
- sed -i '/alias ccraw=/d' "$rc"
49
- fi
50
- # Remove old specwright alias
51
- if grep -q "alias specwright=" "$rc" 2>/dev/null; then
52
- sed -i '/alias specwright=/d' "$rc"
53
- fi
54
- # Remove old cc-tools/check-setup functions
55
- if grep -q "^cc-tools()" "$rc" 2>/dev/null; then
56
- sed -i '/^cc-tools() {/,/^}/d' "$rc"
57
- fi
58
- if grep -q "alias check-setup=" "$rc" 2>/dev/null; then
59
- sed -i '/alias check-setup=/d' "$rc"
60
- fi
23
+ # Remove old cc alias
24
+ if grep -q "alias cc=" "$rc" 2>/dev/null; then
25
+ sed -i '/alias cc=/d' "$rc"
26
+ echo "[setup-aliases] Removed old cc alias from $(basename $rc)"
27
+ fi
28
+ # Remove old cc function (single-line or multi-line)
29
+ if grep -q "^cc()" "$rc" 2>/dev/null; then
30
+ sed -i '/^cc() {/,/^}/d' "$rc"
31
+ echo "[setup-aliases] Removed old cc function from $(basename $rc)"
32
+ fi
33
+ # Remove old _claude_with_config function
34
+ if grep -q "^_claude_with_config()" "$rc" 2>/dev/null; then
35
+ sed -i '/^_claude_with_config() {/,/^}/d' "$rc"
36
+ echo "[setup-aliases] Removed old _claude_with_config function from $(basename $rc)"
37
+ fi
38
+ # Remove old claude function override
39
+ if grep -q "^claude() {" "$rc" 2>/dev/null; then
40
+ sed -i '/^claude() { _claude_with_config/d' "$rc"
41
+ echo "[setup-aliases] Removed old claude function from $(basename $rc)"
42
+ fi
43
+ # Remove old claude alias
44
+ if grep -q "alias claude=" "$rc" 2>/dev/null; then
45
+ sed -i '/alias claude=/d' "$rc"
46
+ fi
47
+ # Remove old ccraw alias
48
+ if grep -q "alias ccraw=" "$rc" 2>/dev/null; then
49
+ sed -i '/alias ccraw=/d' "$rc"
50
+ fi
51
+ # Remove old specwright alias
52
+ if grep -q "alias specwright=" "$rc" 2>/dev/null; then
53
+ sed -i '/alias specwright=/d' "$rc"
54
+ fi
55
+ # Remove old cc-tools/check-setup functions
56
+ if grep -q "^cc-tools()" "$rc" 2>/dev/null; then
57
+ sed -i '/^cc-tools() {/,/^}/d' "$rc"
58
+ fi
59
+ if grep -q "alias check-setup=" "$rc" 2>/dev/null; then
60
+ sed -i '/alias check-setup=/d' "$rc"
61
+ fi
62
+ # --- Add environment and aliases (idempotent) ---
63
+ # Guard: skip if aliases already present from a previous run
64
+ if grep -q '# Claude Code environment and aliases' "$rc" 2>/dev/null; then
65
+ echo "[setup-aliases] Aliases already present in $(basename $rc), skipping"
66
+ continue
67
+ fi
68
+ echo "" >>"$rc"
69
+ echo "# Claude Code environment and aliases (managed by setup-aliases.sh)" >>"$rc"
70
+ # Export CLAUDE_CONFIG_DIR so it's available in all shells (not just VS Code remoteEnv)
71
+ if ! grep -q 'export CLAUDE_CONFIG_DIR=' "$rc" 2>/dev/null; then
72
+ echo "export CLAUDE_CONFIG_DIR=\"${CLAUDE_CONFIG_DIR}\"" >>"$rc"
73
+ fi
74
+ # Export UTF-8 locale so tmux renders Unicode correctly (docker exec doesn't inherit locale)
75
+ if ! grep -q 'export LANG=en_US.UTF-8' "$rc" 2>/dev/null; then
76
+ echo 'export LANG=en_US.UTF-8' >>"$rc"
77
+ echo 'export LC_ALL=en_US.UTF-8' >>"$rc"
78
+ fi
79
+ # Prefer native binary over npm-installed version
80
+ # 'claude install' puts the binary at ~/.local/bin/claude
81
+ # Legacy manual installs used /usr/local/bin/claude — check both
82
+ cat >>"$rc" <<'CLAUDEBIN_EOF'
83
+ if [ -x "$HOME/.local/bin/claude" ]; then
84
+ _CLAUDE_BIN="$HOME/.local/bin/claude"
85
+ elif [ -x /usr/local/bin/claude ]; then
86
+ _CLAUDE_BIN=/usr/local/bin/claude
87
+ else
88
+ _CLAUDE_BIN=claude
89
+ fi
90
+ CLAUDEBIN_EOF
91
+ echo "$ALIAS_CC" >>"$rc"
92
+ echo "$ALIAS_CLAUDE" >>"$rc"
93
+ echo "$ALIAS_CCRAW" >>"$rc"
61
94
 
62
- # --- Add environment and aliases (idempotent) ---
63
- # Guard: skip if aliases already present from a previous run
64
- if grep -q '# Claude Code environment and aliases' "$rc" 2>/dev/null; then
65
- echo "[setup-aliases] Aliases already present in $(basename $rc), skipping"
66
- continue
67
- fi
68
- echo "" >> "$rc"
69
- echo "# Claude Code environment and aliases (managed by setup-aliases.sh)" >> "$rc"
70
- # Export CLAUDE_CONFIG_DIR so it's available in all shells (not just VS Code remoteEnv)
71
- if ! grep -q 'export CLAUDE_CONFIG_DIR=' "$rc" 2>/dev/null; then
72
- echo "export CLAUDE_CONFIG_DIR=\"${CLAUDE_CONFIG_DIR}\"" >> "$rc"
73
- fi
74
- # Export UTF-8 locale so tmux renders Unicode correctly (docker exec doesn't inherit locale)
75
- if ! grep -q 'export LANG=en_US.UTF-8' "$rc" 2>/dev/null; then
76
- echo 'export LANG=en_US.UTF-8' >> "$rc"
77
- echo 'export LC_ALL=en_US.UTF-8' >> "$rc"
78
- fi
79
- echo "$ALIAS_CC" >> "$rc"
80
- echo "$ALIAS_CLAUDE" >> "$rc"
81
- echo "$ALIAS_CCRAW" >> "$rc"
82
-
83
- # cc-tools: list all available CodeForge tools with version info
84
- cat >> "$rc" << 'CCTOOLS_EOF'
95
+ # cc-tools: list all available CodeForge tools with version info
96
+ cat >>"$rc" <<'CCTOOLS_EOF'
85
97
  cc-tools() {
86
98
  echo "CodeForge Available Tools"
87
99
  echo "━━━━━━━━━━━━━━━━━━━━━━━━"
@@ -101,12 +113,12 @@ cc-tools() {
101
113
  }
102
114
  CCTOOLS_EOF
103
115
 
104
- # check-setup: alias to the health check script
105
- DEVCONTAINER_SCRIPTS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
106
- echo "alias check-setup='bash ${DEVCONTAINER_SCRIPTS}/check-setup.sh'" >> "$rc"
116
+ # check-setup: alias to the health check script
117
+ DEVCONTAINER_SCRIPTS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
118
+ echo "alias check-setup='bash ${DEVCONTAINER_SCRIPTS}/check-setup.sh'" >>"$rc"
107
119
 
108
- echo "[setup-aliases] Added aliases to $(basename $rc)"
109
- fi
120
+ echo "[setup-aliases] Added aliases to $(basename $rc)"
121
+ fi
110
122
  done
111
123
 
112
124
  echo "[setup-aliases] Aliases configured:"