claude-code-starter 0.2.0 → 0.3.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 (3) hide show
  1. package/README.md +24 -10
  2. package/dist/cli.js +723 -24
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Claude Code Starter
2
2
 
3
+ [![CI](https://github.com/cassmtnr/claude-code-starter/actions/workflows/pr-check.yml/badge.svg)](https://github.com/cassmtnr/claude-code-starter/actions/workflows/pr-check.yml)
4
+ [![codecov](https://codecov.io/gh/cassmtnr/claude-code-starter/graph/badge.svg)](https://codecov.io/gh/cassmtnr/claude-code-starter)
5
+ [![npm version](https://img.shields.io/npm/v/claude-code-starter.svg)](https://www.npmjs.com/package/claude-code-starter)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)](https://nodejs.org/)
8
+ [![Bun](https://img.shields.io/badge/Bun-compatible-f472b6.svg)](https://bun.sh/)
9
+
3
10
  Intelligent CLI that bootstraps Claude Code configurations tailored to your project's tech stack.
4
11
 
5
12
  ## Quick Start
@@ -39,12 +46,13 @@ Based on your stack, creates:
39
46
 
40
47
  ## Commands
41
48
 
42
- | Command | Description |
43
- | ----------------- | ------------------- |
44
- | `/task <desc>` | Start a new task |
45
- | `/status` | Show current task |
46
- | `/done` | Mark task complete |
47
- | `/analyze <area>` | Deep dive into code |
49
+ | Command | Description |
50
+ | ----------------- | ---------------------------------------- |
51
+ | `/task <desc>` | Start a new task |
52
+ | `/status` | Show current task |
53
+ | `/done` | Mark task complete |
54
+ | `/analyze <area>` | Deep dive into code |
55
+ | `/code-review` | Review changes for quality and security |
48
56
 
49
57
  ## CLI Options
50
58
 
@@ -75,7 +83,7 @@ npx claude-code-starter --help # Show help
75
83
  ✅ Configuration complete! (14 files)
76
84
 
77
85
  Generated for your stack:
78
- 📚 4 skills (pattern-discovery, testing-methodology, nextjs-patterns, ...)
86
+ 📚 9 skills (pattern-discovery, iterative-development, security, nextjs-patterns, ...)
79
87
  🤖 2 agents (code-reviewer, test-writer)
80
88
  📏 2 rules
81
89
  ```
@@ -95,15 +103,21 @@ After running, your project will have:
95
103
  │ ├── task.md
96
104
  │ ├── status.md
97
105
  │ ├── done.md
98
- └── analyze.md
106
+ ├── analyze.md
107
+ │ └── code-review.md
99
108
  ├── rules/ # Code style rules
100
109
  │ ├── typescript.md # (or python.md, etc.)
101
110
  │ └── code-style.md
102
- ├── skills/ # Framework-specific patterns
111
+ ├── skills/ # Methodology guides + patterns
103
112
  │ ├── pattern-discovery.md
104
113
  │ ├── systematic-debugging.md
105
114
  │ ├── testing-methodology.md
106
- └── nextjs-patterns.md # (or fastapi-patterns.md, etc.)
115
+ ├── iterative-development.md
116
+ │ ├── commit-hygiene.md
117
+ │ ├── code-deduplication.md
118
+ │ ├── simplicity-rules.md
119
+ │ ├── security.md
120
+ │ └── nextjs-patterns.md # (framework-specific)
107
121
  └── state/
108
122
  └── task.md # Current task tracking
109
123
  ```
package/dist/cli.js CHANGED
@@ -539,6 +539,7 @@ function generateClaudeMd(projectInfo) {
539
539
  sections.push("| `/status` | Show current task state |");
540
540
  sections.push("| `/done` | Mark current task complete |");
541
541
  sections.push("| `/analyze <area>` | Deep-dive into specific code |");
542
+ sections.push("| `/code-review` | Review changes for quality and security |");
542
543
  sections.push("");
543
544
  sections.push("## Common Operations");
544
545
  sections.push("");
@@ -553,6 +554,18 @@ function generateClaudeMd(projectInfo) {
553
554
  sections.push("3. **Test Before Done** - Run tests before marking complete");
554
555
  sections.push("4. **Update State** - Keep task.md current as you work");
555
556
  sections.push("5. **Match Patterns** - Follow existing code conventions");
557
+ sections.push("6. **TDD Workflow** - Write failing tests first, then implement");
558
+ sections.push("");
559
+ sections.push("## Quality Gates");
560
+ sections.push("");
561
+ sections.push("Enforced constraints for code quality:");
562
+ sections.push("");
563
+ sections.push("| Constraint | Limit | Action |");
564
+ sections.push("|------------|-------|--------|");
565
+ sections.push("| Lines per function | 20 max | Decompose immediately |");
566
+ sections.push("| Parameters per function | 3 max | Use options object |");
567
+ sections.push("| Lines per file | 200 max | Split by responsibility |");
568
+ sections.push("| Test coverage | 80% min | Add tests before merge |");
556
569
  sections.push("");
557
570
  sections.push("## Skills");
558
571
  sections.push("");
@@ -757,9 +770,16 @@ function generateSettings(stack) {
757
770
  }
758
771
  function getSkillsForStack(stack) {
759
772
  const skills = [
773
+ // Core methodology skills
760
774
  { name: "pattern-discovery", description: "Finding codebase patterns" },
761
775
  { name: "systematic-debugging", description: "Debugging approach" },
762
- { name: "testing-methodology", description: "Testing strategy" }
776
+ { name: "testing-methodology", description: "Testing strategy" },
777
+ // Process discipline skills
778
+ { name: "iterative-development", description: "TDD loops until tests pass" },
779
+ { name: "commit-hygiene", description: "Atomic commits and PR size limits" },
780
+ { name: "code-deduplication", description: "Prevent semantic code duplication" },
781
+ { name: "simplicity-rules", description: "Code complexity constraints" },
782
+ { name: "security", description: "Security patterns and secrets management" }
763
783
  ];
764
784
  if (stack.frameworks.includes("nextjs")) {
765
785
  skills.push({ name: "nextjs-patterns", description: "Next.js App Router patterns" });
@@ -783,6 +803,11 @@ function generateSkills(stack) {
783
803
  artifacts.push(generatePatternDiscoverySkill());
784
804
  artifacts.push(generateSystematicDebuggingSkill());
785
805
  artifacts.push(generateTestingMethodologySkill(stack));
806
+ artifacts.push(generateIterativeDevelopmentSkill(stack));
807
+ artifacts.push(generateCommitHygieneSkill());
808
+ artifacts.push(generateCodeDeduplicationSkill());
809
+ artifacts.push(generateSimplicityRulesSkill());
810
+ artifacts.push(generateSecuritySkill(stack));
786
811
  if (stack.frameworks.includes("nextjs")) {
787
812
  artifacts.push(generateNextJsSkill());
788
813
  }
@@ -1634,6 +1659,615 @@ describe('UsersService', () => {
1634
1659
  isNew: true
1635
1660
  };
1636
1661
  }
1662
+ function generateIterativeDevelopmentSkill(stack) {
1663
+ const testCmd = getTestCommand(stack);
1664
+ const lintCmd = getLintCommand(stack);
1665
+ return {
1666
+ type: "skill",
1667
+ path: ".claude/skills/iterative-development.md",
1668
+ content: `---
1669
+ name: iterative-development
1670
+ description: TDD-driven iterative loops until tests pass
1671
+ globs:
1672
+ - "**/*.ts"
1673
+ - "**/*.tsx"
1674
+ - "**/*.js"
1675
+ - "**/*.py"
1676
+ - "**/*.go"
1677
+ ---
1678
+
1679
+ # Iterative Development (TDD Loops)
1680
+
1681
+ Self-referential development loops where you iterate until completion criteria are met.
1682
+
1683
+ ## Core Philosophy
1684
+
1685
+ \`\`\`
1686
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
1687
+ \u2502 ITERATION > PERFECTION \u2502
1688
+ \u2502 Don't aim for perfect on first try. \u2502
1689
+ \u2502 Let the loop refine the work. \u2502
1690
+ \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
1691
+ \u2502 FAILURES ARE DATA \u2502
1692
+ \u2502 Failed tests, lint errors, type mismatches are signals. \u2502
1693
+ \u2502 Use them to guide the next iteration. \u2502
1694
+ \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
1695
+ \u2502 CLEAR COMPLETION CRITERIA \u2502
1696
+ \u2502 Define exactly what "done" looks like. \u2502
1697
+ \u2502 Tests passing. Coverage met. Lint clean. \u2502
1698
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
1699
+ \`\`\`
1700
+
1701
+ ## TDD Workflow (Mandatory)
1702
+
1703
+ Every implementation task MUST follow this workflow:
1704
+
1705
+ ### 1. RED: Write Tests First
1706
+ \`\`\`bash
1707
+ # Write tests based on requirements
1708
+ # Run tests - they MUST FAIL
1709
+ ${testCmd}
1710
+ \`\`\`
1711
+
1712
+ ### 2. GREEN: Implement Feature
1713
+ \`\`\`bash
1714
+ # Write minimum code to pass tests
1715
+ # Run tests - they MUST PASS
1716
+ ${testCmd}
1717
+ \`\`\`
1718
+
1719
+ ### 3. VALIDATE: Quality Gates
1720
+ \`\`\`bash
1721
+ # Full quality check
1722
+ ${lintCmd ? `${lintCmd} && ` : ""}${testCmd}
1723
+ \`\`\`
1724
+
1725
+ ## Completion Criteria Template
1726
+
1727
+ For any implementation task, define:
1728
+
1729
+ \`\`\`markdown
1730
+ ### Completion Criteria
1731
+ - [ ] All tests passing
1732
+ - [ ] Coverage >= 80% (on new code)
1733
+ - [ ] Lint clean (no errors)
1734
+ - [ ] Type check passing
1735
+ \`\`\`
1736
+
1737
+ ## When to Use This Workflow
1738
+
1739
+ | Task Type | Use TDD Loop? |
1740
+ |-----------|---------------|
1741
+ | New feature | \u2705 Always |
1742
+ | Bug fix | \u2705 Always (write test that reproduces bug first) |
1743
+ | Refactoring | \u2705 Always (existing tests must stay green) |
1744
+ | Spike/exploration | \u274C Skip (but document findings) |
1745
+ | Documentation | \u274C Skip |
1746
+
1747
+ ## Anti-Patterns
1748
+
1749
+ - \u274C Writing code before tests
1750
+ - \u274C Skipping the RED phase (tests that never fail are useless)
1751
+ - \u274C Moving on when tests fail
1752
+ - \u274C Large batches (prefer small, focused iterations)
1753
+ `,
1754
+ isNew: true
1755
+ };
1756
+ }
1757
+ function generateCommitHygieneSkill() {
1758
+ return {
1759
+ type: "skill",
1760
+ path: ".claude/skills/commit-hygiene.md",
1761
+ content: `---
1762
+ name: commit-hygiene
1763
+ description: Atomic commits, PR size limits, commit thresholds
1764
+ globs:
1765
+ - "**/*"
1766
+ ---
1767
+
1768
+ # Commit Hygiene
1769
+
1770
+ Keep commits atomic, PRs reviewable, and git history clean.
1771
+
1772
+ ## Size Thresholds
1773
+
1774
+ | Metric | \u{1F7E2} Good | \u{1F7E1} Warning | \u{1F534} Commit Now |
1775
+ |--------|---------|------------|---------------|
1776
+ | Files changed | 1-5 | 6-10 | > 10 |
1777
+ | Lines added | < 150 | 150-300 | > 300 |
1778
+ | Total changes | < 250 | 250-400 | > 400 |
1779
+
1780
+ **Research shows:** PRs > 400 lines have 40%+ defect rates vs 15% for smaller changes.
1781
+
1782
+ ## When to Commit
1783
+
1784
+ ### Commit Triggers (Any = Commit)
1785
+
1786
+ | Trigger | Action |
1787
+ |---------|--------|
1788
+ | Test passes | Just got a test green \u2192 commit |
1789
+ | Feature complete | Finished a function \u2192 commit |
1790
+ | Refactor done | Renamed across files \u2192 commit |
1791
+ | Bug fixed | Fixed the issue \u2192 commit |
1792
+ | Threshold hit | > 5 files or > 200 lines \u2192 commit |
1793
+
1794
+ ### Commit Immediately If
1795
+
1796
+ - \u2705 Tests are passing after being red
1797
+ - \u2705 You're about to make a "big change"
1798
+ - \u2705 You've been coding for 30+ minutes
1799
+ - \u2705 You're about to try something risky
1800
+ - \u2705 The current state is "working"
1801
+
1802
+ ## Atomic Commit Patterns
1803
+
1804
+ ### Good Commits \u2705
1805
+
1806
+ \`\`\`
1807
+ "Add email validation to signup form"
1808
+ - 3 files: validator.ts, signup.tsx, signup.test.ts
1809
+ - 120 lines changed
1810
+ - Single purpose: email validation
1811
+
1812
+ "Fix null pointer in user lookup"
1813
+ - 2 files: userService.ts, userService.test.ts
1814
+ - 25 lines changed
1815
+ - Single purpose: fix one bug
1816
+ \`\`\`
1817
+
1818
+ ### Bad Commits \u274C
1819
+
1820
+ \`\`\`
1821
+ "Add authentication, fix bugs, update styles"
1822
+ - 25 files changed, 800 lines
1823
+ - Multiple unrelated purposes
1824
+
1825
+ "WIP" / "Updates" / "Fix stuff"
1826
+ - Unknown scope, no clear purpose
1827
+ \`\`\`
1828
+
1829
+ ## Quick Status Check
1830
+
1831
+ Run frequently to check current state:
1832
+
1833
+ \`\`\`bash
1834
+ # See what's changed
1835
+ git status --short
1836
+
1837
+ # Count changes
1838
+ git diff --shortstat
1839
+
1840
+ # Full summary
1841
+ git diff --stat HEAD
1842
+ \`\`\`
1843
+
1844
+ ## PR Size Rules
1845
+
1846
+ | PR Size | Review Time | Quality |
1847
+ |---------|-------------|---------|
1848
+ | < 200 lines | < 30 min | High confidence |
1849
+ | 200-400 lines | 30-60 min | Good confidence |
1850
+ | 400-1000 lines | 1-2 hours | Declining quality |
1851
+ | > 1000 lines | Often skipped | Rubber-stamped |
1852
+
1853
+ **Best practice:** If a PR will be > 400 lines, split into stacked PRs.
1854
+ `,
1855
+ isNew: true
1856
+ };
1857
+ }
1858
+ function generateCodeDeduplicationSkill() {
1859
+ return {
1860
+ type: "skill",
1861
+ path: ".claude/skills/code-deduplication.md",
1862
+ content: `---
1863
+ name: code-deduplication
1864
+ description: Prevent semantic code duplication with capability index
1865
+ globs:
1866
+ - "**/*.ts"
1867
+ - "**/*.tsx"
1868
+ - "**/*.js"
1869
+ - "**/*.py"
1870
+ ---
1871
+
1872
+ # Code Deduplication
1873
+
1874
+ Prevent semantic duplication by maintaining awareness of existing capabilities.
1875
+
1876
+ ## Core Principle
1877
+
1878
+ \`\`\`
1879
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
1880
+ \u2502 CHECK BEFORE YOU WRITE \u2502
1881
+ \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502
1882
+ \u2502 AI doesn't copy/paste - it reimplements. \u2502
1883
+ \u2502 The problem isn't duplicate code, it's duplicate PURPOSE. \u2502
1884
+ \u2502 \u2502
1885
+ \u2502 Before writing ANY new function: \u2502
1886
+ \u2502 1. Search codebase for similar functionality \u2502
1887
+ \u2502 2. Check utils/, helpers/, lib/ for existing implementations \u2502
1888
+ \u2502 3. Extend existing code if possible \u2502
1889
+ \u2502 4. Only create new if nothing suitable exists \u2502
1890
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
1891
+ \`\`\`
1892
+
1893
+ ## Before Writing New Code
1894
+
1895
+ ### Search Checklist
1896
+
1897
+ 1. **Search by purpose**: "format date", "validate email", "fetch user"
1898
+ 2. **Search common locations**:
1899
+ - \`src/utils/\` or \`lib/\`
1900
+ - \`src/helpers/\`
1901
+ - \`src/common/\`
1902
+ - \`src/shared/\`
1903
+ 3. **Search by function signature**: Similar inputs/outputs
1904
+
1905
+ ### Common Duplicate Candidates
1906
+
1907
+ | Category | Look For |
1908
+ |----------|----------|
1909
+ | Date/Time | formatDate, parseDate, isExpired, addDays |
1910
+ | Validation | isEmail, isPhone, isURL, isUUID |
1911
+ | Strings | slugify, truncate, capitalize, pluralize |
1912
+ | API | fetchUser, createItem, handleError |
1913
+ | Auth | validateToken, requireAuth, getCurrentUser |
1914
+
1915
+ ## If Similar Code Exists
1916
+
1917
+ ### Option 1: Reuse directly
1918
+ \`\`\`typescript
1919
+ // Import and use existing function
1920
+ import { formatDate } from '@/utils/dates';
1921
+ \`\`\`
1922
+
1923
+ ### Option 2: Extend with options
1924
+ \`\`\`typescript
1925
+ // Add optional parameter to existing function
1926
+ export function formatDate(
1927
+ date: Date,
1928
+ format: string = 'short',
1929
+ locale?: string // NEW: added locale support
1930
+ ): string { ... }
1931
+ \`\`\`
1932
+
1933
+ ### Option 3: Compose from existing
1934
+ \`\`\`typescript
1935
+ // Build on existing utilities
1936
+ export function formatDateRange(start: Date, end: Date) {
1937
+ return \`\${formatDate(start)} - \${formatDate(end)}\`;
1938
+ }
1939
+ \`\`\`
1940
+
1941
+ ## File Header Pattern
1942
+
1943
+ Document what each file provides:
1944
+
1945
+ \`\`\`typescript
1946
+ /**
1947
+ * @file User validation utilities
1948
+ * @description Email, phone, and identity validation functions.
1949
+ *
1950
+ * Key exports:
1951
+ * - isEmail(email) - Validates email format
1952
+ * - isPhone(phone, country?) - Validates phone with country
1953
+ * - isValidUsername(username) - Checks username rules
1954
+ */
1955
+ \`\`\`
1956
+
1957
+ ## Anti-Patterns
1958
+
1959
+ - \u274C Writing date formatter without checking utils/
1960
+ - \u274C Creating new API client when one exists
1961
+ - \u274C Duplicating validation logic across files
1962
+ - \u274C Copy-pasting functions between files
1963
+ - \u274C "I'll refactor later" (you won't)
1964
+ `,
1965
+ isNew: true
1966
+ };
1967
+ }
1968
+ function generateSimplicityRulesSkill() {
1969
+ return {
1970
+ type: "skill",
1971
+ path: ".claude/skills/simplicity-rules.md",
1972
+ content: `---
1973
+ name: simplicity-rules
1974
+ description: Enforced code complexity constraints
1975
+ globs:
1976
+ - "**/*.ts"
1977
+ - "**/*.tsx"
1978
+ - "**/*.js"
1979
+ - "**/*.py"
1980
+ - "**/*.go"
1981
+ ---
1982
+
1983
+ # Simplicity Rules
1984
+
1985
+ Complexity is the enemy. Every line of code is a liability.
1986
+
1987
+ ## Enforced Limits
1988
+
1989
+ **CRITICAL: These limits are non-negotiable. Check and enforce for EVERY file.**
1990
+
1991
+ ### Function Level
1992
+
1993
+ | Constraint | Limit | Action if Exceeded |
1994
+ |------------|-------|-------------------|
1995
+ | Lines per function | 20 max | Decompose immediately |
1996
+ | Parameters | 3 max | Use options object |
1997
+ | Nesting levels | 2 max | Flatten with early returns |
1998
+
1999
+ ### File Level
2000
+
2001
+ | Constraint | Limit | Action if Exceeded |
2002
+ |------------|-------|-------------------|
2003
+ | Lines per file | 200 max | Split by responsibility |
2004
+ | Functions per file | 10 max | Split into modules |
2005
+
2006
+ ### Module Level
2007
+
2008
+ | Constraint | Limit | Reason |
2009
+ |------------|-------|--------|
2010
+ | Directory nesting | 3 levels max | Flat is better |
2011
+ | Circular deps | 0 | Never acceptable |
2012
+
2013
+ ## Enforcement Protocol
2014
+
2015
+ **Before completing ANY file:**
2016
+
2017
+ \`\`\`
2018
+ 1. Count total lines \u2192 if > 200, STOP and split
2019
+ 2. Count functions \u2192 if > 10, STOP and split
2020
+ 3. Check function length \u2192 if any > 20 lines, decompose
2021
+ 4. Check parameters \u2192 if any > 3, refactor to options object
2022
+ \`\`\`
2023
+
2024
+ ## Violation Response
2025
+
2026
+ When limits are exceeded:
2027
+
2028
+ \`\`\`
2029
+ \u26A0\uFE0F FILE SIZE VIOLATION DETECTED
2030
+
2031
+ [filename] has [X] lines (limit: 200)
2032
+
2033
+ Splitting into:
2034
+ - [filename-a].ts - [responsibility A]
2035
+ - [filename-b].ts - [responsibility B]
2036
+ \`\`\`
2037
+
2038
+ **Never defer refactoring.** Fix violations immediately.
2039
+
2040
+ ## Decomposition Patterns
2041
+
2042
+ ### Long Function \u2192 Multiple Functions
2043
+
2044
+ \`\`\`typescript
2045
+ // BEFORE: 40 lines
2046
+ function processOrder(order) {
2047
+ // validate... 10 lines
2048
+ // calculate totals... 15 lines
2049
+ // apply discounts... 10 lines
2050
+ // save... 5 lines
2051
+ }
2052
+
2053
+ // AFTER: 4 functions, each < 15 lines
2054
+ function processOrder(order) {
2055
+ validateOrder(order);
2056
+ const totals = calculateTotals(order);
2057
+ const finalPrice = applyDiscounts(totals, order.coupons);
2058
+ return saveOrder({ ...order, finalPrice });
2059
+ }
2060
+ \`\`\`
2061
+
2062
+ ### Many Parameters \u2192 Options Object
2063
+
2064
+ \`\`\`typescript
2065
+ // BEFORE: 6 parameters
2066
+ function createUser(name, email, password, role, team, settings) { }
2067
+
2068
+ // AFTER: 1 options object
2069
+ interface CreateUserOptions {
2070
+ name: string;
2071
+ email: string;
2072
+ password: string;
2073
+ role?: string;
2074
+ team?: string;
2075
+ settings?: UserSettings;
2076
+ }
2077
+ function createUser(options: CreateUserOptions) { }
2078
+ \`\`\`
2079
+
2080
+ ### Deep Nesting \u2192 Early Returns
2081
+
2082
+ \`\`\`typescript
2083
+ // BEFORE: 4 levels deep
2084
+ function process(data) {
2085
+ if (data) {
2086
+ if (data.valid) {
2087
+ if (data.items) {
2088
+ for (const item of data.items) {
2089
+ // actual logic here
2090
+ }
2091
+ }
2092
+ }
2093
+ }
2094
+ }
2095
+
2096
+ // AFTER: 1 level deep
2097
+ function process(data) {
2098
+ if (!data?.valid || !data.items) return;
2099
+
2100
+ for (const item of data.items) {
2101
+ // actual logic here
2102
+ }
2103
+ }
2104
+ \`\`\`
2105
+
2106
+ ## Anti-Patterns
2107
+
2108
+ - \u274C God objects/files (do everything)
2109
+ - \u274C "Just one more line" (compound violations)
2110
+ - \u274C "I'll split it later" (you won't)
2111
+ - \u274C Deep inheritance hierarchies
2112
+ - \u274C Complex conditionals without extraction
2113
+ `,
2114
+ isNew: true
2115
+ };
2116
+ }
2117
+ function generateSecuritySkill(stack) {
2118
+ const isJS = stack.languages.includes("typescript") || stack.languages.includes("javascript");
2119
+ const isPython = stack.languages.includes("python");
2120
+ return {
2121
+ type: "skill",
2122
+ path: ".claude/skills/security.md",
2123
+ content: `---
2124
+ name: security
2125
+ description: Security best practices, secrets management, OWASP patterns
2126
+ globs:
2127
+ - "**/*"
2128
+ ---
2129
+
2130
+ # Security Best Practices
2131
+
2132
+ Security is not optional. Every project must pass security checks.
2133
+
2134
+ ## Required .gitignore Entries
2135
+
2136
+ **NEVER commit these:**
2137
+
2138
+ \`\`\`gitignore
2139
+ # Environment files
2140
+ .env
2141
+ .env.*
2142
+ !.env.example
2143
+
2144
+ # Secrets and credentials
2145
+ *.pem
2146
+ *.key
2147
+ *.p12
2148
+ credentials.json
2149
+ secrets.json
2150
+ *-credentials.json
2151
+ service-account*.json
2152
+
2153
+ # IDE secrets
2154
+ .idea/
2155
+ .vscode/settings.json
2156
+ \`\`\`
2157
+
2158
+ ## Environment Variables
2159
+
2160
+ ### Create .env.example
2161
+
2162
+ Document required vars without values:
2163
+
2164
+ \`\`\`bash
2165
+ # Server-side only (never expose to client)
2166
+ DATABASE_URL=
2167
+ API_SECRET_KEY=
2168
+ ANTHROPIC_API_KEY=
2169
+
2170
+ # Client-side safe (public, non-sensitive)
2171
+ ${isJS ? "VITE_API_URL=\nNEXT_PUBLIC_SITE_URL=" : "API_BASE_URL="}
2172
+ \`\`\`
2173
+
2174
+ ${isJS ? `### Frontend Exposure Rules
2175
+
2176
+ | Framework | Client-Exposed Prefix | Server-Only |
2177
+ |-----------|----------------------|-------------|
2178
+ | Vite | \`VITE_*\` | No prefix |
2179
+ | Next.js | \`NEXT_PUBLIC_*\` | No prefix |
2180
+ | CRA | \`REACT_APP_*\` | N/A |
2181
+
2182
+ **CRITICAL:** Never put secrets in client-exposed env vars!
2183
+
2184
+ \`\`\`typescript
2185
+ // \u274C WRONG - Secret exposed to browser
2186
+ const key = import.meta.env.VITE_API_SECRET;
2187
+
2188
+ // \u2705 CORRECT - Secret stays server-side
2189
+ const key = process.env.API_SECRET; // in API route only
2190
+ \`\`\`
2191
+ ` : ""}
2192
+
2193
+ ### Validate at Startup
2194
+
2195
+ ${isJS ? `\`\`\`typescript
2196
+ import { z } from 'zod';
2197
+
2198
+ const envSchema = z.object({
2199
+ DATABASE_URL: z.string().url(),
2200
+ API_SECRET_KEY: z.string().min(32),
2201
+ NODE_ENV: z.enum(['development', 'production', 'test']),
2202
+ });
2203
+
2204
+ export const env = envSchema.parse(process.env);
2205
+ \`\`\`` : ""}
2206
+ ${isPython ? `\`\`\`python
2207
+ from pydantic_settings import BaseSettings
2208
+
2209
+ class Settings(BaseSettings):
2210
+ database_url: str
2211
+ api_secret_key: str
2212
+ environment: str = "development"
2213
+
2214
+ class Config:
2215
+ env_file = ".env"
2216
+
2217
+ settings = Settings()
2218
+ \`\`\`` : ""}
2219
+
2220
+ ## OWASP Top 10 Checklist
2221
+
2222
+ | Vulnerability | Prevention |
2223
+ |---------------|------------|
2224
+ | Injection (SQL, NoSQL, Command) | Parameterized queries, input validation |
2225
+ | Broken Auth | Secure session management, MFA |
2226
+ | Sensitive Data Exposure | Encryption at rest and in transit |
2227
+ | XXE | Disable external entity processing |
2228
+ | Broken Access Control | Verify permissions on every request |
2229
+ | Security Misconfiguration | Secure defaults, minimal permissions |
2230
+ | XSS | Output encoding, CSP headers |
2231
+ | Insecure Deserialization | Validate all serialized data |
2232
+ | Using Vulnerable Components | Keep dependencies updated |
2233
+ | Insufficient Logging | Log security events, monitor |
2234
+
2235
+ ## Input Validation
2236
+
2237
+ \`\`\`
2238
+ RULE: Never trust user input. Validate everything.
2239
+
2240
+ - Validate type, length, format, range
2241
+ - Sanitize before storage
2242
+ - Encode before output
2243
+ - Use allowlists over denylists
2244
+ \`\`\`
2245
+
2246
+ ## Secrets Detection
2247
+
2248
+ Before committing, check for:
2249
+
2250
+ - API keys (usually 32+ chars, specific patterns)
2251
+ - Passwords in code
2252
+ - Connection strings with credentials
2253
+ - Private keys (BEGIN RSA/EC/PRIVATE KEY)
2254
+ - Tokens (jwt, bearer, oauth)
2255
+
2256
+ ## Security Review Checklist
2257
+
2258
+ Before PR merge:
2259
+
2260
+ - [ ] No secrets in code or config
2261
+ - [ ] Input validation on all user data
2262
+ - [ ] Output encoding where displayed
2263
+ - [ ] Authentication checked on protected routes
2264
+ - [ ] Authorization verified for resources
2265
+ - [ ] Dependencies scanned for vulnerabilities
2266
+ - [ ] Error messages don't leak internals
2267
+ `,
2268
+ isNew: true
2269
+ };
2270
+ }
1637
2271
  function getAgentsForStack(stack) {
1638
2272
  const agents = [
1639
2273
  { name: "code-reviewer", description: "Reviews code for quality and security" },
@@ -1948,7 +2582,8 @@ function generateCommands() {
1948
2582
  generateTaskCommand(),
1949
2583
  generateStatusCommand(),
1950
2584
  generateDoneCommand(),
1951
- generateAnalyzeCommand()
2585
+ generateAnalyzeCommand(),
2586
+ generateCodeReviewCommand()
1952
2587
  ];
1953
2588
  }
1954
2589
  function generateTaskCommand() {
@@ -2092,6 +2727,71 @@ Any improvements or concerns noted.
2092
2727
  isNew: true
2093
2728
  };
2094
2729
  }
2730
+ function generateCodeReviewCommand() {
2731
+ return {
2732
+ type: "command",
2733
+ path: ".claude/commands/code-review.md",
2734
+ content: `---
2735
+ allowed-tools: Read, Glob, Grep, Bash(git diff), Bash(git status), Bash(git log)
2736
+ description: Review code changes for quality, security, and best practices
2737
+ ---
2738
+
2739
+ # Code Review
2740
+
2741
+ ## Changes to Review
2742
+
2743
+ !git diff --stat HEAD~1 2>/dev/null || git diff --stat
2744
+
2745
+ ## Review Process
2746
+
2747
+ Analyze all changes for:
2748
+
2749
+ ### 1. Security (Critical)
2750
+ - [ ] No secrets/credentials in code
2751
+ - [ ] Input validation present
2752
+ - [ ] Output encoding where needed
2753
+ - [ ] Auth/authz checks on protected routes
2754
+
2755
+ ### 2. Quality
2756
+ - [ ] Functions \u2264 20 lines
2757
+ - [ ] Files \u2264 200 lines
2758
+ - [ ] No code duplication
2759
+ - [ ] Clear naming
2760
+ - [ ] Proper error handling
2761
+
2762
+ ### 3. Testing
2763
+ - [ ] Tests exist for new code
2764
+ - [ ] Edge cases covered
2765
+ - [ ] Tests are meaningful (not just for coverage)
2766
+
2767
+ ### 4. Style
2768
+ - [ ] Matches existing patterns
2769
+ - [ ] Consistent formatting
2770
+ - [ ] No commented-out code
2771
+
2772
+ ## Output Format
2773
+
2774
+ For each finding, include file:line reference:
2775
+
2776
+ ### Critical (Must Fix)
2777
+ Issues that block merge
2778
+
2779
+ ### Warning (Should Fix)
2780
+ Issues that should be addressed
2781
+
2782
+ ### Suggestion (Consider)
2783
+ Optional improvements
2784
+
2785
+ ## Summary
2786
+
2787
+ Provide:
2788
+ 1. Overall assessment (Ready / Changes Needed / Not Ready)
2789
+ 2. Count of findings by severity
2790
+ 3. Top priorities to address
2791
+ `,
2792
+ isNew: true
2793
+ };
2794
+ }
2095
2795
  function formatLanguage(lang) {
2096
2796
  const names = {
2097
2797
  typescript: "TypeScript",
@@ -2203,15 +2903,14 @@ ${pc.bold("MORE INFO")}
2203
2903
  `);
2204
2904
  }
2205
2905
  function showBanner() {
2206
- console.log(pc.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2207
- console.log(pc.cyan(`\u2551 Claude Code Starter v${VERSION.padEnd(24)}\u2551`));
2208
- console.log(pc.cyan("\u2551 Intelligent AI-Assisted Development Setup \u2551"));
2209
- console.log(pc.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2906
+ console.log();
2907
+ console.log(pc.bold("Claude Code Starter") + pc.gray(` v${VERSION}`));
2908
+ console.log(pc.gray("Intelligent AI-Assisted Development Setup"));
2210
2909
  console.log();
2211
2910
  }
2212
2911
  function showTechStack(projectInfo, verbose) {
2213
2912
  const { techStack } = projectInfo;
2214
- console.log(pc.blue("\u{1F4CA} Tech Stack Analysis"));
2913
+ console.log(pc.bold("Tech Stack"));
2215
2914
  console.log();
2216
2915
  if (techStack.primaryLanguage) {
2217
2916
  console.log(` ${pc.bold("Language:")} ${formatLanguage2(techStack.primaryLanguage)}`);
@@ -2251,7 +2950,7 @@ async function promptNewProject(args) {
2251
2950
  if (!args.interactive) {
2252
2951
  return null;
2253
2952
  }
2254
- console.log(pc.yellow("\u{1F195} New project detected - let's set it up!"));
2953
+ console.log(pc.yellow("New project detected - let's set it up!"));
2255
2954
  console.log();
2256
2955
  const response = await prompts([
2257
2956
  {
@@ -2441,7 +3140,7 @@ async function main() {
2441
3140
  }
2442
3141
  showBanner();
2443
3142
  const projectDir = process.cwd();
2444
- console.log(pc.blue("\u{1F50D} Analyzing repository..."));
3143
+ console.log(pc.gray("Analyzing repository..."));
2445
3144
  console.log();
2446
3145
  const projectInfo = analyzeRepository(projectDir);
2447
3146
  showTechStack(projectInfo, args.verbose);
@@ -2457,11 +3156,11 @@ async function main() {
2457
3156
  projectInfo.description = preferences.description;
2458
3157
  }
2459
3158
  } else {
2460
- console.log(pc.green(`\u{1F4C1} Existing project \xB7 ${projectInfo.fileCount} source files`));
3159
+ console.log(pc.gray(`Existing project with ${projectInfo.fileCount} source files`));
2461
3160
  console.log();
2462
3161
  }
2463
3162
  if (projectInfo.techStack.hasClaudeConfig && !args.force) {
2464
- console.log(pc.yellow("\u26A0\uFE0F Existing .claude/ configuration detected"));
3163
+ console.log(pc.yellow("Existing .claude/ configuration detected"));
2465
3164
  console.log();
2466
3165
  if (args.interactive) {
2467
3166
  const { proceed } = await prompts({
@@ -2477,32 +3176,32 @@ async function main() {
2477
3176
  }
2478
3177
  console.log();
2479
3178
  }
2480
- console.log(pc.blue("\u2699\uFE0F Generating Claude Code configuration..."));
3179
+ console.log(pc.gray("Generating configuration..."));
2481
3180
  console.log();
2482
3181
  const result = generateArtifacts(projectInfo);
2483
3182
  const { created, updated, skipped } = writeArtifacts(result.artifacts, projectDir, args.force);
2484
3183
  if (created.length > 0) {
2485
- console.log(pc.green(" Created:"));
3184
+ console.log(pc.green("Created:"));
2486
3185
  for (const file of created) {
2487
- console.log(pc.green(` \u2713 ${file}`));
3186
+ console.log(pc.green(` + ${file}`));
2488
3187
  }
2489
3188
  }
2490
3189
  if (updated.length > 0) {
2491
- console.log(pc.blue(" Updated:"));
3190
+ console.log(pc.blue("Updated:"));
2492
3191
  for (const file of updated) {
2493
- console.log(pc.blue(` \u21BB ${file}`));
3192
+ console.log(pc.blue(` ~ ${file}`));
2494
3193
  }
2495
3194
  }
2496
3195
  if (skipped.length > 0 && args.verbose) {
2497
- console.log(pc.gray(" Preserved:"));
3196
+ console.log(pc.gray("Preserved:"));
2498
3197
  for (const file of skipped) {
2499
- console.log(pc.gray(` - ${file}`));
3198
+ console.log(pc.gray(` - ${file}`));
2500
3199
  }
2501
3200
  }
2502
3201
  console.log();
2503
3202
  createTaskFile(projectInfo, preferences);
2504
3203
  const totalFiles = created.length + updated.length;
2505
- console.log(pc.green(`\u2705 Configuration complete! (${totalFiles} files)`));
3204
+ console.log(pc.green(`Done! (${totalFiles} files)`));
2506
3205
  console.log();
2507
3206
  console.log(pc.bold("Generated for your stack:"));
2508
3207
  const skills = result.artifacts.filter((a) => a.type === "skill");
@@ -2510,24 +3209,24 @@ async function main() {
2510
3209
  const rules = result.artifacts.filter((a) => a.type === "rule");
2511
3210
  if (skills.length > 0) {
2512
3211
  console.log(
2513
- ` \u{1F4DA} ${skills.length} skills (${skills.map((s) => path3.basename(s.path, ".md")).join(", ")})`
3212
+ ` ${skills.length} skills (${skills.map((s) => path3.basename(s.path, ".md")).join(", ")})`
2514
3213
  );
2515
3214
  }
2516
3215
  if (agents.length > 0) {
2517
3216
  console.log(
2518
- ` \u{1F916} ${agents.length} agents (${agents.map((a) => path3.basename(a.path, ".md")).join(", ")})`
3217
+ ` ${agents.length} agents (${agents.map((a) => path3.basename(a.path, ".md")).join(", ")})`
2519
3218
  );
2520
3219
  }
2521
3220
  if (rules.length > 0) {
2522
- console.log(` \u{1F4CF} ${rules.length} rules`);
3221
+ console.log(` ${rules.length} rules`);
2523
3222
  }
2524
3223
  console.log();
2525
3224
  console.log(`${pc.cyan("Next step:")} Run ${pc.bold("claude")} to start working!`);
2526
3225
  console.log();
2527
3226
  if (!projectInfo.isExisting) {
2528
- console.log(pc.gray("\u{1F4A1} Tip: Use /task to define your first task"));
3227
+ console.log(pc.gray("Tip: Use /task to define your first task"));
2529
3228
  } else {
2530
- console.log(pc.gray("\u{1F4A1} Tip: Use /analyze to explore specific areas of your codebase"));
3229
+ console.log(pc.gray("Tip: Use /analyze to explore specific areas of your codebase"));
2531
3230
  }
2532
3231
  }
2533
3232
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-starter",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "A lightweight starter kit for AI-assisted development with Claude Code",
5
5
  "keywords": [
6
6
  "claude",