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 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
- # Navigate to your project
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
- Claude reads `.claude/state/task.md` (as instructed by CLAUDE.md) and continues:
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
- ### Example 9: Pattern Discovery
295
-
296
- ```
297
- You: I need to add a new API endpoint. What patterns does this
298
- project use?
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 | What it does |
23
+ | Command | Description |
393
24
  |---------|-------------|
394
- | `/task <desc>` | Start working on something |
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
- ## Skills
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
- ```markdown
416
- # Current Task
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
- When you resume a session, Claude reads this file and continues where you left off.
37
+ ## Tip
440
38
 
441
- ## Global .gitignore
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
- ## Permissions
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
- 1. **Be specific with tasks** - "Add login endpoint" is better than "work on auth"
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.8",
4
- "description": "A lightweight framework for AI-assisted development with Claude Code",
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": "./init"
23
+ "claude-code-starter": "./dist/cli.js"
23
24
  },
24
25
  "files": [
25
- "init",
26
- "CLAUDE.md",
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": ">=14.0.0"
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