claude-code-starter 0.0.8 → 0.1.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.
- package/README.md +17 -478
- package/dist/cli.js +291 -0
- package/package.json +26 -10
- package/init +0 -352
- /package/{CLAUDE.md → templates/CLAUDE.md} +0 -0
- /package/{.claude → templates}/commands/analyze.md +0 -0
- /package/{.claude → templates}/commands/done.md +0 -0
- /package/{.claude → templates}/commands/status.md +0 -0
- /package/{.claude → templates}/commands/task.md +0 -0
- /package/{.claude → templates}/settings.json +0 -0
- /package/{.claude → templates}/skills/pattern-discovery.md +0 -0
- /package/{.claude → templates}/skills/systematic-debugging.md +0 -0
- /package/{.claude → templates}/skills/testing-methodology.md +0 -0
- /package/{.claude → templates}/state/task.md +0 -0
package/README.md
CHANGED
|
@@ -2,508 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
A lightweight starter kit for AI-assisted development with Claude Code.
|
|
4
4
|
|
|
5
|
-
**Version:** 0.0.8
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# Install globally via npm
|
|
11
|
-
npm install -g claude-code-starter
|
|
12
|
-
|
|
13
|
-
# Or use npx (no install required)
|
|
14
|
-
npx claude-code-starter
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
After global installation, run with `claude-code-starter`. Or just use `npx` without installing.
|
|
18
|
-
|
|
19
5
|
## Quick Start
|
|
20
6
|
|
|
21
7
|
```bash
|
|
22
|
-
|
|
23
|
-
cd /path/to/your-project
|
|
24
|
-
|
|
25
|
-
# Initialize the framework
|
|
26
|
-
npx claude-code-starter
|
|
27
|
-
|
|
28
|
-
# Then start Claude:
|
|
29
|
-
claude
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## CLI Options
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npx claude-code-starter --help # Show help message
|
|
36
|
-
npx claude-code-starter --version # Show version number
|
|
37
|
-
npx claude-code-starter --force # Force overwrite CLAUDE.md and settings.json
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## Examples
|
|
43
|
-
|
|
44
|
-
### Example 1: New Project
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
mkdir my-new-app
|
|
48
|
-
cd my-new-app
|
|
8
|
+
cd your-project
|
|
49
9
|
npx claude-code-starter
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Output:
|
|
53
|
-
```
|
|
54
|
-
╔═══════════════════════════════════════╗
|
|
55
|
-
║ Claude Code Framework v0.0.2 ║
|
|
56
|
-
╚═══════════════════════════════════════╝
|
|
57
|
-
|
|
58
|
-
Setting up framework files...
|
|
59
|
-
Created CLAUDE.md
|
|
60
|
-
Created .claude/settings.json
|
|
61
|
-
Updated .claude/commands/
|
|
62
|
-
Updated .claude/skills/
|
|
63
|
-
|
|
64
|
-
New project detected
|
|
65
|
-
|
|
66
|
-
What are you building?
|
|
67
|
-
> A REST API for managing todo items
|
|
68
|
-
|
|
69
|
-
Ready! Run claude to start working on: A REST API for managing todo items
|
|
70
|
-
|
|
71
|
-
Tip: Add .claude/ to your global .gitignore
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Then:
|
|
75
|
-
```bash
|
|
76
|
-
claude
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Claude will start with context about your task and begin helping you build it.
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
### Example 2: Existing Project
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
cd /path/to/my-express-app
|
|
87
|
-
npx claude-code-starter
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Output:
|
|
91
|
-
```
|
|
92
|
-
╔═══════════════════════════════════════╗
|
|
93
|
-
║ Claude Code Framework v0.0.2 ║
|
|
94
|
-
╚═══════════════════════════════════════╝
|
|
95
|
-
|
|
96
|
-
Setting up framework files...
|
|
97
|
-
Created CLAUDE.md
|
|
98
|
-
Created .claude/settings.json
|
|
99
|
-
Updated .claude/commands/
|
|
100
|
-
Updated .claude/skills/
|
|
101
|
-
|
|
102
|
-
Detected existing project
|
|
103
|
-
Tech stack: Node.js TypeScript
|
|
104
|
-
|
|
105
|
-
Analyzing codebase...
|
|
106
|
-
|
|
107
|
-
Files: 47 source files
|
|
108
|
-
Directories: src/ lib/ tests/
|
|
109
|
-
Frameworks: Express
|
|
110
|
-
|
|
111
|
-
Ready! Run claude to start.
|
|
112
|
-
|
|
113
|
-
Tip: Add .claude/ to your global .gitignore
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
### Example 3: Starting a Task
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
You: /task Add user authentication with JWT
|
|
122
|
-
|
|
123
|
-
Claude: I'll set up JWT authentication. Let me first understand your current
|
|
124
|
-
project structure...
|
|
125
|
-
|
|
126
|
-
[Claude reads files, creates a plan, updates .claude/state/task.md]
|
|
127
|
-
|
|
128
|
-
I've analyzed your project. Here's my plan:
|
|
129
|
-
|
|
130
|
-
1. Install dependencies (jsonwebtoken, bcrypt)
|
|
131
|
-
2. Create auth middleware in src/middleware/auth.ts
|
|
132
|
-
3. Add login/register endpoints
|
|
133
|
-
4. Protect existing routes
|
|
134
|
-
|
|
135
|
-
Starting with step 1...
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
### Example 4: Checking Status
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
You: /status
|
|
144
|
-
|
|
145
|
-
Claude: ## Current Status
|
|
146
|
-
|
|
147
|
-
**Task:** Add user authentication with JWT
|
|
148
|
-
**Status:** In Progress
|
|
149
|
-
|
|
150
|
-
### Progress
|
|
151
|
-
- [x] Installed dependencies
|
|
152
|
-
- [x] Created auth middleware
|
|
153
|
-
- [ ] Add login/register endpoints
|
|
154
|
-
- [ ] Protect existing routes
|
|
155
|
-
|
|
156
|
-
### Decisions Made
|
|
157
|
-
- Using RS256 for JWT signing
|
|
158
|
-
- Storing refresh tokens in httpOnly cookies
|
|
159
|
-
|
|
160
|
-
### Next Steps
|
|
161
|
-
Creating the login endpoint in src/routes/auth.ts
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
### Example 5: Completing a Task
|
|
167
|
-
|
|
168
|
-
```
|
|
169
|
-
You: /done
|
|
170
|
-
|
|
171
|
-
Claude: ## Task Complete
|
|
172
|
-
|
|
173
|
-
**Task:** Add user authentication with JWT
|
|
174
|
-
|
|
175
|
-
### Summary
|
|
176
|
-
Implemented full JWT authentication system with:
|
|
177
|
-
- Login/register endpoints
|
|
178
|
-
- Token refresh mechanism
|
|
179
|
-
- Protected route middleware
|
|
180
|
-
|
|
181
|
-
### Files Changed
|
|
182
|
-
- src/middleware/auth.ts (new)
|
|
183
|
-
- src/routes/auth.ts (new)
|
|
184
|
-
- src/routes/index.ts (modified)
|
|
185
|
-
- package.json (modified)
|
|
186
|
-
|
|
187
|
-
### Follow-up
|
|
188
|
-
- Consider adding rate limiting to auth endpoints
|
|
189
|
-
- Add password reset functionality
|
|
190
|
-
|
|
191
|
-
State cleared. Ready for next task.
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
### Example 6: Deep Analysis
|
|
197
|
-
|
|
198
|
-
```
|
|
199
|
-
You: /analyze authentication flow
|
|
200
|
-
|
|
201
|
-
Claude: ## Analysis: Authentication Flow
|
|
202
|
-
|
|
203
|
-
### Entry Points
|
|
204
|
-
- `POST /api/auth/login` → src/routes/auth.ts:23
|
|
205
|
-
- `POST /api/auth/register` → src/routes/auth.ts:45
|
|
206
|
-
- `POST /api/auth/refresh` → src/routes/auth.ts:67
|
|
207
|
-
|
|
208
|
-
### Middleware Chain
|
|
209
|
-
1. `validateBody()` → src/middleware/validate.ts:12
|
|
210
|
-
2. `authMiddleware()` → src/middleware/auth.ts:8
|
|
211
|
-
|
|
212
|
-
### Token Flow
|
|
213
|
-
```
|
|
214
|
-
Login Request
|
|
215
|
-
↓
|
|
216
|
-
Validate credentials (bcrypt.compare)
|
|
217
|
-
↓
|
|
218
|
-
Generate access token (15min) + refresh token (7d)
|
|
219
|
-
↓
|
|
220
|
-
Set refresh token as httpOnly cookie
|
|
221
|
-
↓
|
|
222
|
-
Return access token in response body
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Potential Issues
|
|
226
|
-
- No rate limiting on login attempts
|
|
227
|
-
- Refresh tokens not stored in DB (can't revoke)
|
|
228
|
-
|
|
229
|
-
### Recommendations
|
|
230
|
-
1. Add rate limiting with express-rate-limit
|
|
231
|
-
2. Store refresh tokens in Redis for revocation
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
### Example 7: Resuming Work
|
|
237
|
-
|
|
238
|
-
When you close Claude and come back later:
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
10
|
claude
|
|
242
11
|
```
|
|
243
12
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
```
|
|
247
|
-
Claude: Welcome back. I see you were working on:
|
|
248
|
-
|
|
249
|
-
**Task:** Add user authentication with JWT
|
|
250
|
-
**Status:** In Progress
|
|
251
|
-
|
|
252
|
-
Last time we completed the auth middleware. Next step is
|
|
253
|
-
creating the login endpoint.
|
|
254
|
-
|
|
255
|
-
Should I continue with that?
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
---
|
|
259
|
-
|
|
260
|
-
### Example 8: Using Skills
|
|
261
|
-
|
|
262
|
-
Skills are referenced when relevant. You can also ask directly:
|
|
263
|
-
|
|
264
|
-
```
|
|
265
|
-
You: I'm debugging why login fails for some users. Help me use
|
|
266
|
-
the systematic debugging approach.
|
|
267
|
-
|
|
268
|
-
Claude: I'll follow the systematic debugging methodology.
|
|
269
|
-
|
|
270
|
-
### 1. Reproduce
|
|
271
|
-
First, let me understand the failure pattern...
|
|
272
|
-
- Which users fail? New users? Existing users?
|
|
273
|
-
- Any error messages in logs?
|
|
274
|
-
|
|
275
|
-
### 2. Isolate
|
|
276
|
-
[Claude narrows down the issue]
|
|
277
|
-
|
|
278
|
-
### 3. Trace
|
|
279
|
-
Looking at the code path:
|
|
280
|
-
- src/routes/auth.ts:23 → login handler
|
|
281
|
-
- src/services/auth.ts:15 → validatePassword
|
|
282
|
-
...
|
|
283
|
-
|
|
284
|
-
### 4. Root Cause
|
|
285
|
-
Found it: The password comparison fails for users migrated
|
|
286
|
-
from the old system because they use MD5 hashing, not bcrypt.
|
|
287
|
-
|
|
288
|
-
### 5. Fix
|
|
289
|
-
I'll add a migration check in the login flow...
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
---
|
|
13
|
+
## What It Does
|
|
293
14
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
Claude: Let me analyze the existing patterns...
|
|
301
|
-
|
|
302
|
-
### API Endpoint Pattern
|
|
303
|
-
Based on src/routes/*.ts:
|
|
304
|
-
|
|
305
|
-
```typescript
|
|
306
|
-
// Pattern: Route files export a router
|
|
307
|
-
import { Router } from 'express';
|
|
308
|
-
import { validateBody } from '../middleware/validate';
|
|
309
|
-
import { schema } from '../schemas/resourceSchema';
|
|
310
|
-
|
|
311
|
-
const router = Router();
|
|
312
|
-
|
|
313
|
-
router.post('/',
|
|
314
|
-
validateBody(schema),
|
|
315
|
-
async (req, res, next) => {
|
|
316
|
-
try {
|
|
317
|
-
const result = await service.create(req.body);
|
|
318
|
-
res.status(201).json(result);
|
|
319
|
-
} catch (error) {
|
|
320
|
-
next(error);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
);
|
|
324
|
-
|
|
325
|
-
export default router;
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### Conventions Found
|
|
329
|
-
- Validation middleware before handlers
|
|
330
|
-
- Async handlers with try/catch
|
|
331
|
-
- Services handle business logic
|
|
332
|
-
- 201 for creates, 200 for updates
|
|
333
|
-
|
|
334
|
-
Should I create your new endpoint following this pattern?
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
---
|
|
338
|
-
|
|
339
|
-
### Example 10: Multi-Step Feature
|
|
340
|
-
|
|
341
|
-
```
|
|
342
|
-
You: /task Build a complete user profile feature with avatar upload
|
|
343
|
-
|
|
344
|
-
Claude: This is a multi-step feature. I'll break it down:
|
|
345
|
-
|
|
346
|
-
## Plan
|
|
347
|
-
|
|
348
|
-
1. **Database**: Add profile fields to User model
|
|
349
|
-
2. **Storage**: Set up file upload for avatars
|
|
350
|
-
3. **API**: Create profile endpoints (GET/PATCH)
|
|
351
|
-
4. **Validation**: Add profile update schema
|
|
352
|
-
5. **Tests**: Write tests for new endpoints
|
|
353
|
-
|
|
354
|
-
I'll update state as we complete each step.
|
|
355
|
-
|
|
356
|
-
Starting with the database changes...
|
|
357
|
-
|
|
358
|
-
[After completing step 1]
|
|
359
|
-
|
|
360
|
-
✓ Step 1 complete. Updated .claude/state/task.md
|
|
361
|
-
|
|
362
|
-
Moving to step 2: Setting up avatar uploads...
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
---
|
|
366
|
-
|
|
367
|
-
## Structure
|
|
368
|
-
|
|
369
|
-
After init, your project has:
|
|
370
|
-
|
|
371
|
-
```
|
|
372
|
-
your-project/
|
|
373
|
-
├── CLAUDE.md # Instructions for Claude
|
|
374
|
-
└── .claude/
|
|
375
|
-
├── .version # Framework version
|
|
376
|
-
├── settings.json # Permissions
|
|
377
|
-
├── commands/ # Slash commands
|
|
378
|
-
│ ├── task.md
|
|
379
|
-
│ ├── status.md
|
|
380
|
-
│ ├── done.md
|
|
381
|
-
│ └── analyze.md
|
|
382
|
-
├── skills/ # Reference guides
|
|
383
|
-
│ ├── pattern-discovery.md
|
|
384
|
-
│ ├── systematic-debugging.md
|
|
385
|
-
│ └── testing-methodology.md
|
|
386
|
-
└── state/
|
|
387
|
-
└── task.md # Current task state
|
|
388
|
-
```
|
|
15
|
+
Sets up your project with:
|
|
16
|
+
- `CLAUDE.md` - Instructions for Claude
|
|
17
|
+
- `.claude/commands/` - Slash commands (`/task`, `/status`, `/done`, `/analyze`)
|
|
18
|
+
- `.claude/skills/` - Methodology guides (debugging, testing, patterns)
|
|
19
|
+
- `.claude/state/task.md` - Task tracking
|
|
389
20
|
|
|
390
21
|
## Commands
|
|
391
22
|
|
|
392
|
-
| Command |
|
|
23
|
+
| Command | Description |
|
|
393
24
|
|---------|-------------|
|
|
394
|
-
| `/task <desc>` | Start
|
|
25
|
+
| `/task <desc>` | Start a new task |
|
|
395
26
|
| `/status` | Show current task |
|
|
396
27
|
| `/done` | Mark task complete |
|
|
397
28
|
| `/analyze <area>` | Deep dive into code |
|
|
398
29
|
|
|
399
|
-
##
|
|
400
|
-
|
|
401
|
-
The framework includes methodology guides in `.claude/skills/`:
|
|
402
|
-
|
|
403
|
-
| Skill | Use When |
|
|
404
|
-
|-------|----------|
|
|
405
|
-
| **pattern-discovery.md** | Adding new code that should match existing patterns |
|
|
406
|
-
| **systematic-debugging.md** | Investigating bugs or unexpected behavior |
|
|
407
|
-
| **testing-methodology.md** | Writing tests or improving test coverage |
|
|
408
|
-
|
|
409
|
-
Claude references these when the situation calls for it.
|
|
410
|
-
|
|
411
|
-
## State Management
|
|
412
|
-
|
|
413
|
-
All state lives in `.claude/state/task.md`. Example:
|
|
30
|
+
## Options
|
|
414
31
|
|
|
415
|
-
```
|
|
416
|
-
#
|
|
417
|
-
|
|
418
|
-
## Status: In Progress
|
|
419
|
-
|
|
420
|
-
**Task:** Add user authentication
|
|
421
|
-
|
|
422
|
-
## Context
|
|
423
|
-
|
|
424
|
-
Building JWT-based auth for the Express API.
|
|
425
|
-
|
|
426
|
-
## Next Steps
|
|
427
|
-
|
|
428
|
-
1. Create auth middleware
|
|
429
|
-
2. Add login endpoint
|
|
430
|
-
3. Test
|
|
431
|
-
|
|
432
|
-
## Decisions
|
|
433
|
-
|
|
434
|
-
- Using RS256 for JWT signing
|
|
435
|
-
- Refresh tokens in httpOnly cookies
|
|
436
|
-
- Access tokens expire in 15 minutes
|
|
32
|
+
```bash
|
|
33
|
+
npx claude-code-starter --help # Show help
|
|
34
|
+
npx claude-code-starter --force # Overwrite existing files
|
|
437
35
|
```
|
|
438
36
|
|
|
439
|
-
|
|
37
|
+
## Tip
|
|
440
38
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
Add `.claude/` to your global gitignore so it's ignored in all projects:
|
|
39
|
+
Add `.claude/` to your global gitignore:
|
|
444
40
|
|
|
445
41
|
```bash
|
|
446
42
|
echo ".claude/" >> ~/.gitignore
|
|
447
43
|
git config --global core.excludesfile ~/.gitignore
|
|
448
44
|
```
|
|
449
45
|
|
|
450
|
-
##
|
|
451
|
-
|
|
452
|
-
The `settings.json` pre-approves common dev commands:
|
|
453
|
-
|
|
454
|
-
- **Git**: status, diff, log, add, commit, etc.
|
|
455
|
-
- **Package managers**: npm, yarn, pnpm, bun, pip, cargo
|
|
456
|
-
- **Build tools**: node, tsc, make, docker
|
|
457
|
-
- **Test runners**: jest, vitest
|
|
458
|
-
- **Linters**: eslint, prettier
|
|
459
|
-
|
|
460
|
-
Edit `.claude/settings.json` to customize for your stack.
|
|
461
|
-
|
|
462
|
-
## Troubleshooting
|
|
463
|
-
|
|
464
|
-
### Init script fails on macOS
|
|
465
|
-
|
|
466
|
-
The script is compatible with Bash 3.x (macOS default). If you see errors:
|
|
467
|
-
|
|
468
|
-
```bash
|
|
469
|
-
# Check your bash version
|
|
470
|
-
bash --version
|
|
471
|
-
|
|
472
|
-
# If installed globally, run with explicit bash
|
|
473
|
-
bash $(which claude-code-starter)
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
### Commands not recognized
|
|
477
|
-
|
|
478
|
-
If `/task`, `/status`, etc. don't work:
|
|
479
|
-
|
|
480
|
-
1. Check that `.claude/commands/` exists in your project
|
|
481
|
-
2. Verify files have YAML frontmatter (lines starting with `---`)
|
|
482
|
-
3. Re-run init to refresh command files
|
|
483
|
-
|
|
484
|
-
### Settings keep resetting
|
|
485
|
-
|
|
486
|
-
The init script preserves your `settings.json` if it exists. If it's being overwritten:
|
|
487
|
-
|
|
488
|
-
1. Check you're not running from inside the framework folder
|
|
489
|
-
2. Verify `.claude/settings.json` exists before running init
|
|
490
|
-
|
|
491
|
-
### Claude doesn't read task state
|
|
492
|
-
|
|
493
|
-
Make sure `CLAUDE.md` exists in your project root. It tells Claude to check `.claude/state/task.md` on startup.
|
|
494
|
-
|
|
495
|
-
### Framework version
|
|
496
|
-
|
|
497
|
-
Check your installed version:
|
|
498
|
-
|
|
499
|
-
```bash
|
|
500
|
-
cat .claude/.version
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
## Tips
|
|
46
|
+
## License
|
|
504
47
|
|
|
505
|
-
|
|
506
|
-
2. **Check status often** - `/status` helps you and Claude stay aligned
|
|
507
|
-
3. **Let Claude update state** - Don't manually edit `.claude/state/task.md`
|
|
508
|
-
4. **Use analyze for exploration** - `/analyze` before diving into unfamiliar code
|
|
509
|
-
5. **Complete tasks properly** - `/done` creates a clean break for the next task
|
|
48
|
+
MIT
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import prompts from "prompts";
|
|
8
|
+
import pc from "picocolors";
|
|
9
|
+
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
var TEMPLATES_DIR = path.join(__dirname, "..", "templates");
|
|
11
|
+
var VERSION = JSON.parse(
|
|
12
|
+
fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf-8")
|
|
13
|
+
).version;
|
|
14
|
+
function parseArgs(args) {
|
|
15
|
+
return {
|
|
16
|
+
help: args.includes("-h") || args.includes("--help"),
|
|
17
|
+
version: args.includes("-v") || args.includes("--version"),
|
|
18
|
+
force: args.includes("-f") || args.includes("--force")
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function detectProject(projectDir) {
|
|
22
|
+
const techStack = [];
|
|
23
|
+
const frameworks = [];
|
|
24
|
+
const directories = [];
|
|
25
|
+
let isExisting = false;
|
|
26
|
+
const checks = [
|
|
27
|
+
["package.json", "Node.js"],
|
|
28
|
+
["tsconfig.json", "TypeScript"],
|
|
29
|
+
["requirements.txt", "Python"],
|
|
30
|
+
["pyproject.toml", "Python"],
|
|
31
|
+
["Cargo.toml", "Rust"],
|
|
32
|
+
["go.mod", "Go"],
|
|
33
|
+
["pom.xml", "Java"],
|
|
34
|
+
["build.gradle", "Java/Kotlin"],
|
|
35
|
+
["Gemfile", "Ruby"]
|
|
36
|
+
];
|
|
37
|
+
for (const [file, tech] of checks) {
|
|
38
|
+
if (fs.existsSync(path.join(projectDir, file))) {
|
|
39
|
+
if (!techStack.includes(tech)) techStack.push(tech);
|
|
40
|
+
isExisting = true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const keyDirs = ["src", "lib", "app", "api", "components", "pages", "tests", "test"];
|
|
44
|
+
for (const dir of keyDirs) {
|
|
45
|
+
if (fs.existsSync(path.join(projectDir, dir))) {
|
|
46
|
+
directories.push(dir);
|
|
47
|
+
isExisting = true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
51
|
+
if (fs.existsSync(pkgPath)) {
|
|
52
|
+
try {
|
|
53
|
+
const pkg = fs.readFileSync(pkgPath, "utf-8");
|
|
54
|
+
const frameworkChecks = [
|
|
55
|
+
['"react"', "React"],
|
|
56
|
+
['"next"', "Next.js"],
|
|
57
|
+
['"vue"', "Vue"],
|
|
58
|
+
['"express"', "Express"],
|
|
59
|
+
['"fastify"', "Fastify"],
|
|
60
|
+
['"@nestjs"', "NestJS"]
|
|
61
|
+
];
|
|
62
|
+
for (const [pattern, name] of frameworkChecks) {
|
|
63
|
+
if (pkg.includes(pattern)) frameworks.push(name);
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let fileCount = 0;
|
|
69
|
+
const extensions = [".js", ".ts", ".tsx", ".py", ".go", ".rs", ".java", ".rb"];
|
|
70
|
+
const ignoreDirs = ["node_modules", ".git", "dist", "build", ".claude"];
|
|
71
|
+
function countFiles(dir, depth = 0) {
|
|
72
|
+
if (depth > 3) return;
|
|
73
|
+
try {
|
|
74
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
75
|
+
for (const entry of entries) {
|
|
76
|
+
if (ignoreDirs.includes(entry.name)) continue;
|
|
77
|
+
const fullPath = path.join(dir, entry.name);
|
|
78
|
+
if (entry.isDirectory()) {
|
|
79
|
+
countFiles(fullPath, depth + 1);
|
|
80
|
+
} else if (extensions.some((ext) => entry.name.endsWith(ext))) {
|
|
81
|
+
fileCount++;
|
|
82
|
+
isExisting = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
countFiles(projectDir);
|
|
89
|
+
return { isExisting, techStack, frameworks, directories, fileCount };
|
|
90
|
+
}
|
|
91
|
+
function copyDir(src, dest) {
|
|
92
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
93
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
const srcPath = path.join(src, entry.name);
|
|
96
|
+
const destPath = path.join(dest, entry.name);
|
|
97
|
+
if (entry.isDirectory()) {
|
|
98
|
+
copyDir(srcPath, destPath);
|
|
99
|
+
} else {
|
|
100
|
+
fs.copyFileSync(srcPath, destPath);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function copyFile(src, dest, force) {
|
|
105
|
+
const exists = fs.existsSync(dest);
|
|
106
|
+
if (!force && exists) {
|
|
107
|
+
return "skipped";
|
|
108
|
+
}
|
|
109
|
+
fs.copyFileSync(src, dest);
|
|
110
|
+
return exists ? "updated" : "created";
|
|
111
|
+
}
|
|
112
|
+
function getVersion() {
|
|
113
|
+
return VERSION;
|
|
114
|
+
}
|
|
115
|
+
function getTemplatesDir() {
|
|
116
|
+
return TEMPLATES_DIR;
|
|
117
|
+
}
|
|
118
|
+
function showHelp() {
|
|
119
|
+
console.log(`
|
|
120
|
+
${pc.cyan("Claude Code Starter")} v${VERSION}
|
|
121
|
+
|
|
122
|
+
A lightweight starter kit for AI-assisted development with Claude Code.
|
|
123
|
+
|
|
124
|
+
${pc.bold("USAGE")}
|
|
125
|
+
npx claude-code-starter [OPTIONS]
|
|
126
|
+
|
|
127
|
+
${pc.bold("OPTIONS")}
|
|
128
|
+
-h, --help Show this help message
|
|
129
|
+
-v, --version Show version number
|
|
130
|
+
-f, --force Force overwrite of CLAUDE.md and settings.json
|
|
131
|
+
|
|
132
|
+
${pc.bold("MORE INFO")}
|
|
133
|
+
https://github.com/cassmtnr/claude-code-starter
|
|
134
|
+
`);
|
|
135
|
+
}
|
|
136
|
+
function showBanner() {
|
|
137
|
+
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\u2557"));
|
|
138
|
+
console.log(pc.cyan(`\u2551 Claude Code Starter v${VERSION.padEnd(13)}\u2551`));
|
|
139
|
+
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\u255D"));
|
|
140
|
+
console.log();
|
|
141
|
+
}
|
|
142
|
+
async function main() {
|
|
143
|
+
const args = parseArgs(process.argv.slice(2));
|
|
144
|
+
if (args.help) {
|
|
145
|
+
showHelp();
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
if (args.version) {
|
|
149
|
+
console.log(`claude-code-starter v${VERSION}`);
|
|
150
|
+
process.exit(0);
|
|
151
|
+
}
|
|
152
|
+
showBanner();
|
|
153
|
+
const projectDir = process.cwd();
|
|
154
|
+
if (!fs.existsSync(TEMPLATES_DIR)) {
|
|
155
|
+
console.error(pc.red("Error: Templates directory not found."));
|
|
156
|
+
console.error("The installation appears to be incomplete.");
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
fs.mkdirSync(path.join(projectDir, ".claude", "state"), { recursive: true });
|
|
160
|
+
fs.mkdirSync(path.join(projectDir, ".claude", "commands"), { recursive: true });
|
|
161
|
+
fs.mkdirSync(path.join(projectDir, ".claude", "skills"), { recursive: true });
|
|
162
|
+
console.log(pc.blue("Setting up framework files..."));
|
|
163
|
+
const claudeMdResult = copyFile(
|
|
164
|
+
path.join(TEMPLATES_DIR, "CLAUDE.md"),
|
|
165
|
+
path.join(projectDir, "CLAUDE.md"),
|
|
166
|
+
args.force
|
|
167
|
+
);
|
|
168
|
+
if (claudeMdResult === "skipped") {
|
|
169
|
+
console.log(" CLAUDE.md exists (use --force to overwrite)");
|
|
170
|
+
} else {
|
|
171
|
+
console.log(` ${claudeMdResult === "updated" ? "Updated" : "Created"} CLAUDE.md`);
|
|
172
|
+
}
|
|
173
|
+
const settingsResult = copyFile(
|
|
174
|
+
path.join(TEMPLATES_DIR, "settings.json"),
|
|
175
|
+
path.join(projectDir, ".claude", "settings.json"),
|
|
176
|
+
args.force
|
|
177
|
+
);
|
|
178
|
+
if (settingsResult === "skipped") {
|
|
179
|
+
console.log(" settings.json exists (use --force to overwrite)");
|
|
180
|
+
} else {
|
|
181
|
+
console.log(` ${settingsResult === "updated" ? "Updated" : "Created"} .claude/settings.json`);
|
|
182
|
+
}
|
|
183
|
+
copyDir(path.join(TEMPLATES_DIR, "commands"), path.join(projectDir, ".claude", "commands"));
|
|
184
|
+
console.log(" Updated .claude/commands/");
|
|
185
|
+
copyDir(path.join(TEMPLATES_DIR, "skills"), path.join(projectDir, ".claude", "skills"));
|
|
186
|
+
console.log(" Updated .claude/skills/");
|
|
187
|
+
fs.writeFileSync(path.join(projectDir, ".claude", ".version"), VERSION);
|
|
188
|
+
console.log();
|
|
189
|
+
const project = detectProject(projectDir);
|
|
190
|
+
if (project.isExisting) {
|
|
191
|
+
console.log(pc.green("Detected existing project"));
|
|
192
|
+
if (project.techStack.length > 0) {
|
|
193
|
+
console.log(`Tech stack: ${pc.cyan(project.techStack.join(" "))}`);
|
|
194
|
+
}
|
|
195
|
+
console.log();
|
|
196
|
+
console.log(pc.blue("Analyzing codebase..."));
|
|
197
|
+
console.log();
|
|
198
|
+
console.log(` Files: ${project.fileCount} source files`);
|
|
199
|
+
if (project.directories.length > 0) {
|
|
200
|
+
console.log(` Directories: ${project.directories.map((d) => d + "/").join(" ")}`);
|
|
201
|
+
}
|
|
202
|
+
if (project.frameworks.length > 0) {
|
|
203
|
+
console.log(` Frameworks: ${project.frameworks.join(" ")}`);
|
|
204
|
+
}
|
|
205
|
+
console.log();
|
|
206
|
+
const taskPath = path.join(projectDir, ".claude", "state", "task.md");
|
|
207
|
+
if (!fs.existsSync(taskPath)) {
|
|
208
|
+
fs.writeFileSync(
|
|
209
|
+
taskPath,
|
|
210
|
+
`# Current Task
|
|
211
|
+
|
|
212
|
+
## Status: Ready
|
|
213
|
+
|
|
214
|
+
No active task. Start one with \`/task <description>\`.
|
|
215
|
+
|
|
216
|
+
## Project Summary
|
|
217
|
+
|
|
218
|
+
This is an existing codebase. Use \`/analyze\` to explore specific areas.
|
|
219
|
+
|
|
220
|
+
## Quick Commands
|
|
221
|
+
|
|
222
|
+
- \`/task\` - Start working on something
|
|
223
|
+
- \`/status\` - See current state
|
|
224
|
+
- \`/analyze\` - Deep dive into code
|
|
225
|
+
- \`/done\` - Mark task complete
|
|
226
|
+
`
|
|
227
|
+
);
|
|
228
|
+
console.log(" Created .claude/state/task.md");
|
|
229
|
+
} else {
|
|
230
|
+
console.log(" Task state preserved (.claude/state/task.md)");
|
|
231
|
+
}
|
|
232
|
+
console.log();
|
|
233
|
+
console.log(`${pc.green("Ready!")} Run ${pc.cyan("claude")} to start.`);
|
|
234
|
+
} else {
|
|
235
|
+
console.log(pc.yellow("New project detected"));
|
|
236
|
+
console.log();
|
|
237
|
+
const taskPath = path.join(projectDir, ".claude", "state", "task.md");
|
|
238
|
+
if (!fs.existsSync(taskPath)) {
|
|
239
|
+
const response = await prompts({
|
|
240
|
+
type: "text",
|
|
241
|
+
name: "task",
|
|
242
|
+
message: "What are you building?",
|
|
243
|
+
initial: "Explore and set up project"
|
|
244
|
+
});
|
|
245
|
+
const task = response.task || "Explore and set up project";
|
|
246
|
+
fs.writeFileSync(
|
|
247
|
+
taskPath,
|
|
248
|
+
`# Current Task
|
|
249
|
+
|
|
250
|
+
## Status: In Progress
|
|
251
|
+
|
|
252
|
+
**Task:** ${task}
|
|
253
|
+
|
|
254
|
+
## Context
|
|
255
|
+
|
|
256
|
+
New project - no existing code yet.
|
|
257
|
+
|
|
258
|
+
## Next Steps
|
|
259
|
+
|
|
260
|
+
1. Define project structure
|
|
261
|
+
2. Set up development environment
|
|
262
|
+
3. Start implementation
|
|
263
|
+
|
|
264
|
+
## Decisions
|
|
265
|
+
|
|
266
|
+
(None yet - starting fresh)
|
|
267
|
+
`
|
|
268
|
+
);
|
|
269
|
+
console.log();
|
|
270
|
+
console.log(`${pc.green("Ready!")} Run ${pc.cyan("claude")} to start working on: ${task}`);
|
|
271
|
+
} else {
|
|
272
|
+
console.log(" Task state preserved (.claude/state/task.md)");
|
|
273
|
+
console.log();
|
|
274
|
+
console.log(`${pc.green("Ready!")} Run ${pc.cyan("claude")} to continue.`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
console.log();
|
|
278
|
+
console.log(`${pc.blue("Tip:")} Add ${pc.cyan(".claude/")} to your global .gitignore`);
|
|
279
|
+
}
|
|
280
|
+
main().catch((err) => {
|
|
281
|
+
console.error(pc.red("Error:"), err.message);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
});
|
|
284
|
+
export {
|
|
285
|
+
copyDir,
|
|
286
|
+
copyFile,
|
|
287
|
+
detectProject,
|
|
288
|
+
getTemplatesDir,
|
|
289
|
+
getVersion,
|
|
290
|
+
parseArgs
|
|
291
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-starter",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "A lightweight
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight starter kit for AI-assisted development with Claude Code",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
7
7
|
"ai",
|
|
@@ -13,23 +13,39 @@
|
|
|
13
13
|
],
|
|
14
14
|
"author": "Cassiano Montanari",
|
|
15
15
|
"license": "MIT",
|
|
16
|
+
"type": "module",
|
|
16
17
|
"repository": {
|
|
17
18
|
"type": "git",
|
|
18
19
|
"url": "git+https://github.com/cassmtnr/claude-code-starter.git"
|
|
19
20
|
},
|
|
20
21
|
"homepage": "https://github.com/cassmtnr/claude-code-starter#readme",
|
|
21
22
|
"bin": {
|
|
22
|
-
"claude-code-starter": "./
|
|
23
|
+
"claude-code-starter": "./dist/cli.js"
|
|
23
24
|
},
|
|
24
25
|
"files": [
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
".claude/commands/",
|
|
28
|
-
".claude/skills/",
|
|
29
|
-
".claude/settings.json",
|
|
30
|
-
".claude/state/task.md"
|
|
26
|
+
"dist",
|
|
27
|
+
"templates"
|
|
31
28
|
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"dev": "tsup --watch",
|
|
32
|
+
"start": "node dist/cli.js",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"typecheck": "tsc --noEmit"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"picocolors": "^1.1.1",
|
|
39
|
+
"prompts": "^2.4.2"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^22.10.0",
|
|
43
|
+
"@types/prompts": "^2.4.9",
|
|
44
|
+
"tsup": "^8.3.5",
|
|
45
|
+
"typescript": "^5.7.2",
|
|
46
|
+
"vitest": "^4.0.17"
|
|
47
|
+
},
|
|
32
48
|
"engines": {
|
|
33
|
-
"node": ">=
|
|
49
|
+
"node": ">=18.0.0"
|
|
34
50
|
}
|
|
35
51
|
}
|
package/init
DELETED
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# Claude Code Starter - Init Script
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
set -e
|
|
7
|
-
|
|
8
|
-
# Colors
|
|
9
|
-
GREEN='\033[0;32m'
|
|
10
|
-
BLUE='\033[0;34m'
|
|
11
|
-
YELLOW='\033[1;33m'
|
|
12
|
-
CYAN='\033[0;36m'
|
|
13
|
-
RED='\033[0;31m'
|
|
14
|
-
NC='\033[0m'
|
|
15
|
-
|
|
16
|
-
# Default options
|
|
17
|
-
FORCE=false
|
|
18
|
-
|
|
19
|
-
# Get framework directory (resolve symlinks for npm global install)
|
|
20
|
-
SCRIPT_PATH="$0"
|
|
21
|
-
if [ -L "$SCRIPT_PATH" ]; then
|
|
22
|
-
# Resolve symlink
|
|
23
|
-
if command -v readlink >/dev/null 2>&1; then
|
|
24
|
-
SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
|
|
25
|
-
# Handle relative symlinks
|
|
26
|
-
if [[ "$SCRIPT_PATH" != /* ]]; then
|
|
27
|
-
SCRIPT_PATH="$(dirname "$0")/$SCRIPT_PATH"
|
|
28
|
-
fi
|
|
29
|
-
fi
|
|
30
|
-
fi
|
|
31
|
-
FRAMEWORK_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
|
|
32
|
-
|
|
33
|
-
# Get version from package.json (single source of truth)
|
|
34
|
-
VERSION=$(node -p "require('$FRAMEWORK_DIR/package.json').version")
|
|
35
|
-
|
|
36
|
-
# Help message
|
|
37
|
-
show_help() {
|
|
38
|
-
cat << EOF
|
|
39
|
-
Claude Code Starter v${VERSION}
|
|
40
|
-
|
|
41
|
-
A lightweight starter kit for AI-assisted development with Claude Code.
|
|
42
|
-
|
|
43
|
-
USAGE:
|
|
44
|
-
npx claude-code-starter [OPTIONS]
|
|
45
|
-
claude-code-starter [OPTIONS]
|
|
46
|
-
|
|
47
|
-
OPTIONS:
|
|
48
|
-
-h, --help Show this help message
|
|
49
|
-
-v, --version Show version number
|
|
50
|
-
-f, --force Force overwrite of CLAUDE.md and settings.json
|
|
51
|
-
|
|
52
|
-
EXAMPLES:
|
|
53
|
-
# Initialize in current directory (no install required)
|
|
54
|
-
cd /path/to/your-project
|
|
55
|
-
npx claude-code-starter
|
|
56
|
-
|
|
57
|
-
# Force overwrite existing files
|
|
58
|
-
npx claude-code-starter --force
|
|
59
|
-
|
|
60
|
-
# If installed globally
|
|
61
|
-
claude-code-starter
|
|
62
|
-
|
|
63
|
-
WHAT IT DOES:
|
|
64
|
-
1. Creates .claude/ directory structure
|
|
65
|
-
2. Copies CLAUDE.md (instructions for Claude)
|
|
66
|
-
3. Sets up slash commands (/task, /status, /done, /analyze)
|
|
67
|
-
4. Installs skill files for patterns, debugging, testing
|
|
68
|
-
5. Creates initial task state
|
|
69
|
-
|
|
70
|
-
MORE INFO:
|
|
71
|
-
https://github.com/cassmtnr/claude-code-starter
|
|
72
|
-
EOF
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
# Parse arguments
|
|
76
|
-
while [[ $# -gt 0 ]]; do
|
|
77
|
-
case $1 in
|
|
78
|
-
-h|--help)
|
|
79
|
-
show_help
|
|
80
|
-
exit 0
|
|
81
|
-
;;
|
|
82
|
-
-v|--version)
|
|
83
|
-
echo "claude-code-starter v${VERSION}"
|
|
84
|
-
exit 0
|
|
85
|
-
;;
|
|
86
|
-
-f|--force)
|
|
87
|
-
FORCE=true
|
|
88
|
-
shift
|
|
89
|
-
;;
|
|
90
|
-
*)
|
|
91
|
-
echo -e "${RED}Unknown option: $1${NC}"
|
|
92
|
-
echo "Use --help for usage information"
|
|
93
|
-
exit 1
|
|
94
|
-
;;
|
|
95
|
-
esac
|
|
96
|
-
done
|
|
97
|
-
|
|
98
|
-
# Get project directory (current working directory)
|
|
99
|
-
PROJECT_DIR="$(pwd)"
|
|
100
|
-
|
|
101
|
-
# Prevent running init inside the framework folder itself
|
|
102
|
-
if [ "$PROJECT_DIR" = "$FRAMEWORK_DIR" ]; then
|
|
103
|
-
echo -e "${YELLOW}Run this from your project directory, not the framework folder.${NC}"
|
|
104
|
-
echo ""
|
|
105
|
-
echo "Usage:"
|
|
106
|
-
echo " cd /path/to/your-project"
|
|
107
|
-
echo " npx claude-code-starter"
|
|
108
|
-
exit 1
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
|
-
# Validate framework files exist
|
|
112
|
-
validate_framework() {
|
|
113
|
-
local missing=()
|
|
114
|
-
|
|
115
|
-
[ ! -f "$FRAMEWORK_DIR/CLAUDE.md" ] && missing+=("CLAUDE.md")
|
|
116
|
-
[ ! -f "$FRAMEWORK_DIR/.claude/settings.json" ] && missing+=(".claude/settings.json")
|
|
117
|
-
[ ! -d "$FRAMEWORK_DIR/.claude/commands" ] && missing+=(".claude/commands/")
|
|
118
|
-
[ ! -d "$FRAMEWORK_DIR/.claude/skills" ] && missing+=(".claude/skills/")
|
|
119
|
-
|
|
120
|
-
if [ ${#missing[@]} -gt 0 ]; then
|
|
121
|
-
echo -e "${RED}Error: Framework files missing:${NC}"
|
|
122
|
-
for file in "${missing[@]}"; do
|
|
123
|
-
echo " - $file"
|
|
124
|
-
done
|
|
125
|
-
echo ""
|
|
126
|
-
echo "The framework installation appears to be incomplete."
|
|
127
|
-
echo "Try reinstalling: npm install -g claude-code-starter"
|
|
128
|
-
exit 1
|
|
129
|
-
fi
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
validate_framework
|
|
133
|
-
|
|
134
|
-
# Show banner
|
|
135
|
-
echo -e "${CYAN}╔═════════════════════════════════════╗${NC}"
|
|
136
|
-
echo -e "${CYAN}║ Claude Code Starter v${VERSION} ║${NC}"
|
|
137
|
-
echo -e "${CYAN}╚═════════════════════════════════════╝${NC}"
|
|
138
|
-
echo ""
|
|
139
|
-
|
|
140
|
-
# Create .claude directory structure
|
|
141
|
-
mkdir -p "$PROJECT_DIR/.claude/state"
|
|
142
|
-
mkdir -p "$PROJECT_DIR/.claude/commands"
|
|
143
|
-
mkdir -p "$PROJECT_DIR/.claude/skills"
|
|
144
|
-
|
|
145
|
-
# Copy framework files to project
|
|
146
|
-
echo -e "${BLUE}Setting up framework files...${NC}"
|
|
147
|
-
|
|
148
|
-
# Copy CLAUDE.md
|
|
149
|
-
if [ ! -f "$PROJECT_DIR/CLAUDE.md" ] || [ "$FORCE" = true ]; then
|
|
150
|
-
cp -- "$FRAMEWORK_DIR/CLAUDE.md" "$PROJECT_DIR/CLAUDE.md"
|
|
151
|
-
if [ "$FORCE" = true ] && [ -f "$PROJECT_DIR/CLAUDE.md" ]; then
|
|
152
|
-
echo " Updated CLAUDE.md (forced)"
|
|
153
|
-
else
|
|
154
|
-
echo " Created CLAUDE.md"
|
|
155
|
-
fi
|
|
156
|
-
else
|
|
157
|
-
echo " CLAUDE.md exists (use --force to overwrite)"
|
|
158
|
-
fi
|
|
159
|
-
|
|
160
|
-
# Copy settings.json
|
|
161
|
-
if [ ! -f "$PROJECT_DIR/.claude/settings.json" ] || [ "$FORCE" = true ]; then
|
|
162
|
-
cp -- "$FRAMEWORK_DIR/.claude/settings.json" "$PROJECT_DIR/.claude/settings.json"
|
|
163
|
-
if [ "$FORCE" = true ] && [ -f "$PROJECT_DIR/.claude/settings.json" ]; then
|
|
164
|
-
echo " Updated .claude/settings.json (forced)"
|
|
165
|
-
else
|
|
166
|
-
echo " Created .claude/settings.json"
|
|
167
|
-
fi
|
|
168
|
-
else
|
|
169
|
-
echo " settings.json exists (use --force to overwrite)"
|
|
170
|
-
fi
|
|
171
|
-
|
|
172
|
-
# Copy commands (always update - these are framework-managed)
|
|
173
|
-
cp -r -- "$FRAMEWORK_DIR/.claude/commands/"* "$PROJECT_DIR/.claude/commands/"
|
|
174
|
-
echo " Updated .claude/commands/"
|
|
175
|
-
|
|
176
|
-
# Copy skills (always update - these are framework-managed)
|
|
177
|
-
cp -r -- "$FRAMEWORK_DIR/.claude/skills/"* "$PROJECT_DIR/.claude/skills/"
|
|
178
|
-
echo " Updated .claude/skills/"
|
|
179
|
-
|
|
180
|
-
# Write version file
|
|
181
|
-
echo "$VERSION" > "$PROJECT_DIR/.claude/.version"
|
|
182
|
-
|
|
183
|
-
echo ""
|
|
184
|
-
|
|
185
|
-
# Detect project type (bash 3.x compatible - no mapfile)
|
|
186
|
-
detect_project() {
|
|
187
|
-
local has_code=false
|
|
188
|
-
local tech_stack=""
|
|
189
|
-
|
|
190
|
-
# Check for various project indicators
|
|
191
|
-
[ -f "$PROJECT_DIR/package.json" ] && tech_stack+="Node.js " && has_code=true
|
|
192
|
-
[ -f "$PROJECT_DIR/tsconfig.json" ] && tech_stack+="TypeScript " && has_code=true
|
|
193
|
-
[ -f "$PROJECT_DIR/requirements.txt" ] && tech_stack+="Python " && has_code=true
|
|
194
|
-
[ -f "$PROJECT_DIR/pyproject.toml" ] && tech_stack+="Python " && has_code=true
|
|
195
|
-
[ -f "$PROJECT_DIR/Cargo.toml" ] && tech_stack+="Rust " && has_code=true
|
|
196
|
-
[ -f "$PROJECT_DIR/go.mod" ] && tech_stack+="Go " && has_code=true
|
|
197
|
-
[ -f "$PROJECT_DIR/pom.xml" ] && tech_stack+="Java " && has_code=true
|
|
198
|
-
[ -f "$PROJECT_DIR/build.gradle" ] && tech_stack+="Java/Kotlin " && has_code=true
|
|
199
|
-
[ -f "$PROJECT_DIR/Gemfile" ] && tech_stack+="Ruby " && has_code=true
|
|
200
|
-
[ -d "$PROJECT_DIR/src" ] && has_code=true
|
|
201
|
-
[ -d "$PROJECT_DIR/lib" ] && has_code=true
|
|
202
|
-
[ -d "$PROJECT_DIR/app" ] && has_code=true
|
|
203
|
-
|
|
204
|
-
# Check for source files (optimized with -prune)
|
|
205
|
-
if [ "$has_code" = false ]; then
|
|
206
|
-
local file_count
|
|
207
|
-
file_count=$(find "$PROJECT_DIR" -maxdepth 3 \
|
|
208
|
-
\( -name "node_modules" -o -name ".git" -o -name "dist" -o -name "build" \) -prune -o \
|
|
209
|
-
\( -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.java" -o -name "*.rb" \) -print 2>/dev/null | head -20 | wc -l | tr -d ' ')
|
|
210
|
-
[ "$file_count" -gt 0 ] && has_code=true
|
|
211
|
-
fi
|
|
212
|
-
|
|
213
|
-
# Return values via global variables (bash 3.x compatible)
|
|
214
|
-
PROJECT_TYPE="new"
|
|
215
|
-
TECH_STACK=""
|
|
216
|
-
if [ "$has_code" = true ]; then
|
|
217
|
-
PROJECT_TYPE="existing"
|
|
218
|
-
TECH_STACK="$tech_stack"
|
|
219
|
-
fi
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
# Run detection
|
|
223
|
-
detect_project
|
|
224
|
-
|
|
225
|
-
if [ "$PROJECT_TYPE" = "existing" ]; then
|
|
226
|
-
echo -e "${GREEN}Detected existing project${NC}"
|
|
227
|
-
[ -n "$TECH_STACK" ] && echo -e "Tech stack: ${CYAN}$TECH_STACK${NC}"
|
|
228
|
-
echo ""
|
|
229
|
-
|
|
230
|
-
# Run analysis
|
|
231
|
-
echo -e "${BLUE}Analyzing codebase...${NC}"
|
|
232
|
-
|
|
233
|
-
# Count files (optimized with -prune)
|
|
234
|
-
total_files=$(find "$PROJECT_DIR" \
|
|
235
|
-
\( -name "node_modules" -o -name ".git" -o -name "dist" -o -name "build" -o -name ".claude" \) -prune -o \
|
|
236
|
-
-type f \( -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.java" -o -name "*.rb" -o -name "*.php" \) -print 2>/dev/null | wc -l | tr -d ' ')
|
|
237
|
-
|
|
238
|
-
# Detect key directories
|
|
239
|
-
key_dirs=""
|
|
240
|
-
[ -d "$PROJECT_DIR/src" ] && key_dirs+="src/ "
|
|
241
|
-
[ -d "$PROJECT_DIR/lib" ] && key_dirs+="lib/ "
|
|
242
|
-
[ -d "$PROJECT_DIR/app" ] && key_dirs+="app/ "
|
|
243
|
-
[ -d "$PROJECT_DIR/api" ] && key_dirs+="api/ "
|
|
244
|
-
[ -d "$PROJECT_DIR/components" ] && key_dirs+="components/ "
|
|
245
|
-
[ -d "$PROJECT_DIR/pages" ] && key_dirs+="pages/ "
|
|
246
|
-
[ -d "$PROJECT_DIR/tests" ] && key_dirs+="tests/ "
|
|
247
|
-
[ -d "$PROJECT_DIR/test" ] && key_dirs+="test/ "
|
|
248
|
-
[ -d "$PROJECT_DIR/__tests__" ] && key_dirs+="__tests__/ "
|
|
249
|
-
|
|
250
|
-
# Detect frameworks
|
|
251
|
-
frameworks=""
|
|
252
|
-
if [ -f "$PROJECT_DIR/package.json" ]; then
|
|
253
|
-
grep -q '"react"' "$PROJECT_DIR/package.json" 2>/dev/null && frameworks+="React "
|
|
254
|
-
grep -q '"next"' "$PROJECT_DIR/package.json" 2>/dev/null && frameworks+="Next.js "
|
|
255
|
-
grep -q '"vue"' "$PROJECT_DIR/package.json" 2>/dev/null && frameworks+="Vue "
|
|
256
|
-
grep -q '"express"' "$PROJECT_DIR/package.json" 2>/dev/null && frameworks+="Express "
|
|
257
|
-
grep -q '"fastify"' "$PROJECT_DIR/package.json" 2>/dev/null && frameworks+="Fastify "
|
|
258
|
-
grep -q '"@nestjs"' "$PROJECT_DIR/package.json" 2>/dev/null && frameworks+="NestJS "
|
|
259
|
-
fi
|
|
260
|
-
if [ -f "$PROJECT_DIR/requirements.txt" ]; then
|
|
261
|
-
grep -qi 'django' "$PROJECT_DIR/requirements.txt" 2>/dev/null && frameworks+="Django "
|
|
262
|
-
grep -qi 'flask' "$PROJECT_DIR/requirements.txt" 2>/dev/null && frameworks+="Flask "
|
|
263
|
-
grep -qi 'fastapi' "$PROJECT_DIR/requirements.txt" 2>/dev/null && frameworks+="FastAPI "
|
|
264
|
-
fi
|
|
265
|
-
|
|
266
|
-
echo ""
|
|
267
|
-
echo " Files: $total_files source files"
|
|
268
|
-
[ -n "$key_dirs" ] && echo " Directories: $key_dirs"
|
|
269
|
-
[ -n "$frameworks" ] && echo " Frameworks: $frameworks"
|
|
270
|
-
echo ""
|
|
271
|
-
|
|
272
|
-
# Only create task file if it doesn't exist (preserve existing state)
|
|
273
|
-
if [ ! -f "$PROJECT_DIR/.claude/state/task.md" ]; then
|
|
274
|
-
cat > "$PROJECT_DIR/.claude/state/task.md" << 'EOF'
|
|
275
|
-
# Current Task
|
|
276
|
-
|
|
277
|
-
## Status: Ready
|
|
278
|
-
|
|
279
|
-
No active task. Start one with `/task <description>`.
|
|
280
|
-
|
|
281
|
-
## Project Summary
|
|
282
|
-
|
|
283
|
-
This is an existing codebase. Use `/analyze` to explore specific areas.
|
|
284
|
-
|
|
285
|
-
## Quick Commands
|
|
286
|
-
|
|
287
|
-
- `/task` - Start working on something
|
|
288
|
-
- `/status` - See current state
|
|
289
|
-
- `/analyze` - Deep dive into code
|
|
290
|
-
- `/done` - Mark task complete
|
|
291
|
-
EOF
|
|
292
|
-
echo " Created .claude/state/task.md"
|
|
293
|
-
else
|
|
294
|
-
echo " Task state preserved (.claude/state/task.md)"
|
|
295
|
-
fi
|
|
296
|
-
|
|
297
|
-
echo ""
|
|
298
|
-
echo -e "${GREEN}Ready!${NC} Run ${CYAN}claude${NC} to start."
|
|
299
|
-
|
|
300
|
-
else
|
|
301
|
-
echo -e "${YELLOW}New project detected${NC}"
|
|
302
|
-
echo ""
|
|
303
|
-
|
|
304
|
-
# Only ask for task if state doesn't exist
|
|
305
|
-
if [ ! -f "$PROJECT_DIR/.claude/state/task.md" ]; then
|
|
306
|
-
echo "What are you building?"
|
|
307
|
-
echo -n "> "
|
|
308
|
-
read -r initial_task
|
|
309
|
-
|
|
310
|
-
# Sanitize input - remove characters that could break heredoc
|
|
311
|
-
initial_task="${initial_task//\$/}"
|
|
312
|
-
initial_task="${initial_task//\`/}"
|
|
313
|
-
initial_task="${initial_task//\\/}"
|
|
314
|
-
|
|
315
|
-
if [ -z "$initial_task" ]; then
|
|
316
|
-
initial_task="Explore and set up project"
|
|
317
|
-
fi
|
|
318
|
-
|
|
319
|
-
# Create initial task file for new project
|
|
320
|
-
cat > "$PROJECT_DIR/.claude/state/task.md" << TASKEOF
|
|
321
|
-
# Current Task
|
|
322
|
-
|
|
323
|
-
## Status: In Progress
|
|
324
|
-
|
|
325
|
-
**Task:** $initial_task
|
|
326
|
-
|
|
327
|
-
## Context
|
|
328
|
-
|
|
329
|
-
New project - no existing code yet.
|
|
330
|
-
|
|
331
|
-
## Next Steps
|
|
332
|
-
|
|
333
|
-
1. Define project structure
|
|
334
|
-
2. Set up development environment
|
|
335
|
-
3. Start implementation
|
|
336
|
-
|
|
337
|
-
## Decisions
|
|
338
|
-
|
|
339
|
-
(None yet - starting fresh)
|
|
340
|
-
TASKEOF
|
|
341
|
-
|
|
342
|
-
echo ""
|
|
343
|
-
echo -e "${GREEN}Ready!${NC} Run ${CYAN}claude${NC} to start working on: $initial_task"
|
|
344
|
-
else
|
|
345
|
-
echo " Task state preserved (.claude/state/task.md)"
|
|
346
|
-
echo ""
|
|
347
|
-
echo -e "${GREEN}Ready!${NC} Run ${CYAN}claude${NC} to continue."
|
|
348
|
-
fi
|
|
349
|
-
fi
|
|
350
|
-
|
|
351
|
-
echo ""
|
|
352
|
-
echo -e "${BLUE}Tip:${NC} Add ${CYAN}.claude/${NC} to your global .gitignore"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|