claude-code-starter 0.0.9 → 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,487 +2,47 @@
2
2
 
3
3
  A lightweight starter kit for AI-assisted development with Claude Code.
4
4
 
5
- **Version:** 0.0.9
6
-
7
5
  ## Quick Start
8
6
 
9
7
  ```bash
10
- cd /path/to/your-project
11
- npx claude-code-starter
12
- claude
13
- ```
14
-
15
- ## CLI Options
16
-
17
- ```bash
18
- npx claude-code-starter --help # Show help message
19
- npx claude-code-starter --version # Show version number
20
- npx claude-code-starter --force # Force overwrite CLAUDE.md and settings.json
21
- ```
22
-
23
- ---
24
-
25
- ## Examples
26
-
27
- ### Example 1: New Project
28
-
29
- ```bash
30
- mkdir my-new-app
31
- cd my-new-app
32
- npx claude-code-starter
33
- ```
34
-
35
- Output:
36
- ```
37
- ╔═══════════════════════════════════════╗
38
- ║ Claude Code Starter v0.0.9 ║
39
- ╚═══════════════════════════════════════╝
40
-
41
- Setting up framework files...
42
- Created CLAUDE.md
43
- Created .claude/settings.json
44
- Updated .claude/commands/
45
- Updated .claude/skills/
46
-
47
- New project detected
48
-
49
- What are you building?
50
- > A REST API for managing todo items
51
-
52
- Ready! Run claude to start working on: A REST API for managing todo items
53
-
54
- Tip: Add .claude/ to your global .gitignore
55
- ```
56
-
57
- Then:
58
- ```bash
59
- claude
60
- ```
61
-
62
- Claude will start with context about your task and begin helping you build it.
63
-
64
- ---
65
-
66
- ### Example 2: Existing Project
67
-
68
- ```bash
69
- cd /path/to/my-express-app
8
+ cd your-project
70
9
  npx claude-code-starter
71
- ```
72
-
73
- Output:
74
- ```
75
- ╔═══════════════════════════════════════╗
76
- ║ Claude Code Starter v0.0.9 ║
77
- ╚═══════════════════════════════════════╝
78
-
79
- Setting up framework files...
80
- Created CLAUDE.md
81
- Created .claude/settings.json
82
- Updated .claude/commands/
83
- Updated .claude/skills/
84
-
85
- Detected existing project
86
- Tech stack: Node.js TypeScript
87
-
88
- Analyzing codebase...
89
-
90
- Files: 47 source files
91
- Directories: src/ lib/ tests/
92
- Frameworks: Express
93
-
94
- Ready! Run claude to start.
95
-
96
- Tip: Add .claude/ to your global .gitignore
97
- ```
98
-
99
- ---
100
-
101
- ### Example 3: Starting a Task
102
-
103
- ```
104
- You: /task Add user authentication with JWT
105
-
106
- Claude: I'll set up JWT authentication. Let me first understand your current
107
- project structure...
108
-
109
- [Claude reads files, creates a plan, updates .claude/state/task.md]
110
-
111
- I've analyzed your project. Here's my plan:
112
-
113
- 1. Install dependencies (jsonwebtoken, bcrypt)
114
- 2. Create auth middleware in src/middleware/auth.ts
115
- 3. Add login/register endpoints
116
- 4. Protect existing routes
117
-
118
- Starting with step 1...
119
- ```
120
-
121
- ---
122
-
123
- ### Example 4: Checking Status
124
-
125
- ```
126
- You: /status
127
-
128
- Claude: ## Current Status
129
-
130
- **Task:** Add user authentication with JWT
131
- **Status:** In Progress
132
-
133
- ### Progress
134
- - [x] Installed dependencies
135
- - [x] Created auth middleware
136
- - [ ] Add login/register endpoints
137
- - [ ] Protect existing routes
138
-
139
- ### Decisions Made
140
- - Using RS256 for JWT signing
141
- - Storing refresh tokens in httpOnly cookies
142
-
143
- ### Next Steps
144
- Creating the login endpoint in src/routes/auth.ts
145
- ```
146
-
147
- ---
148
-
149
- ### Example 5: Completing a Task
150
-
151
- ```
152
- You: /done
153
-
154
- Claude: ## Task Complete
155
-
156
- **Task:** Add user authentication with JWT
157
-
158
- ### Summary
159
- Implemented full JWT authentication system with:
160
- - Login/register endpoints
161
- - Token refresh mechanism
162
- - Protected route middleware
163
-
164
- ### Files Changed
165
- - src/middleware/auth.ts (new)
166
- - src/routes/auth.ts (new)
167
- - src/routes/index.ts (modified)
168
- - package.json (modified)
169
-
170
- ### Follow-up
171
- - Consider adding rate limiting to auth endpoints
172
- - Add password reset functionality
173
-
174
- State cleared. Ready for next task.
175
- ```
176
-
177
- ---
178
-
179
- ### Example 6: Deep Analysis
180
-
181
- ```
182
- You: /analyze authentication flow
183
-
184
- Claude: ## Analysis: Authentication Flow
185
-
186
- ### Entry Points
187
- - `POST /api/auth/login` → src/routes/auth.ts:23
188
- - `POST /api/auth/register` → src/routes/auth.ts:45
189
- - `POST /api/auth/refresh` → src/routes/auth.ts:67
190
-
191
- ### Middleware Chain
192
- 1. `validateBody()` → src/middleware/validate.ts:12
193
- 2. `authMiddleware()` → src/middleware/auth.ts:8
194
-
195
- ### Token Flow
196
- ```
197
- Login Request
198
-
199
- Validate credentials (bcrypt.compare)
200
-
201
- Generate access token (15min) + refresh token (7d)
202
-
203
- Set refresh token as httpOnly cookie
204
-
205
- Return access token in response body
206
- ```
207
-
208
- ### Potential Issues
209
- - No rate limiting on login attempts
210
- - Refresh tokens not stored in DB (can't revoke)
211
-
212
- ### Recommendations
213
- 1. Add rate limiting with express-rate-limit
214
- 2. Store refresh tokens in Redis for revocation
215
- ```
216
-
217
- ---
218
-
219
- ### Example 7: Resuming Work
220
-
221
- When you close Claude and come back later:
222
-
223
- ```bash
224
10
  claude
225
11
  ```
226
12
 
227
- Claude reads `.claude/state/task.md` (as instructed by CLAUDE.md) and continues:
228
-
229
- ```
230
- Claude: Welcome back. I see you were working on:
231
-
232
- **Task:** Add user authentication with JWT
233
- **Status:** In Progress
234
-
235
- Last time we completed the auth middleware. Next step is
236
- creating the login endpoint.
237
-
238
- Should I continue with that?
239
- ```
240
-
241
- ---
242
-
243
- ### Example 8: Using Skills
244
-
245
- Skills are referenced when relevant. You can also ask directly:
246
-
247
- ```
248
- You: I'm debugging why login fails for some users. Help me use
249
- the systematic debugging approach.
250
-
251
- Claude: I'll follow the systematic debugging methodology.
252
-
253
- ### 1. Reproduce
254
- First, let me understand the failure pattern...
255
- - Which users fail? New users? Existing users?
256
- - Any error messages in logs?
257
-
258
- ### 2. Isolate
259
- [Claude narrows down the issue]
260
-
261
- ### 3. Trace
262
- Looking at the code path:
263
- - src/routes/auth.ts:23 → login handler
264
- - src/services/auth.ts:15 → validatePassword
265
- ...
266
-
267
- ### 4. Root Cause
268
- Found it: The password comparison fails for users migrated
269
- from the old system because they use MD5 hashing, not bcrypt.
270
-
271
- ### 5. Fix
272
- I'll add a migration check in the login flow...
273
- ```
274
-
275
- ---
276
-
277
- ### Example 9: Pattern Discovery
278
-
279
- ```
280
- You: I need to add a new API endpoint. What patterns does this
281
- project use?
282
-
283
- Claude: Let me analyze the existing patterns...
284
-
285
- ### API Endpoint Pattern
286
- Based on src/routes/*.ts:
287
-
288
- ```typescript
289
- // Pattern: Route files export a router
290
- import { Router } from 'express';
291
- import { validateBody } from '../middleware/validate';
292
- import { schema } from '../schemas/resourceSchema';
293
-
294
- const router = Router();
295
-
296
- router.post('/',
297
- validateBody(schema),
298
- async (req, res, next) => {
299
- try {
300
- const result = await service.create(req.body);
301
- res.status(201).json(result);
302
- } catch (error) {
303
- next(error);
304
- }
305
- }
306
- );
307
-
308
- export default router;
309
- ```
310
-
311
- ### Conventions Found
312
- - Validation middleware before handlers
313
- - Async handlers with try/catch
314
- - Services handle business logic
315
- - 201 for creates, 200 for updates
316
-
317
- Should I create your new endpoint following this pattern?
318
- ```
319
-
320
- ---
321
-
322
- ### Example 10: Multi-Step Feature
323
-
324
- ```
325
- You: /task Build a complete user profile feature with avatar upload
326
-
327
- Claude: This is a multi-step feature. I'll break it down:
328
-
329
- ## Plan
330
-
331
- 1. **Database**: Add profile fields to User model
332
- 2. **Storage**: Set up file upload for avatars
333
- 3. **API**: Create profile endpoints (GET/PATCH)
334
- 4. **Validation**: Add profile update schema
335
- 5. **Tests**: Write tests for new endpoints
336
-
337
- I'll update state as we complete each step.
338
-
339
- Starting with the database changes...
340
-
341
- [After completing step 1]
342
-
343
- ✓ Step 1 complete. Updated .claude/state/task.md
344
-
345
- Moving to step 2: Setting up avatar uploads...
346
- ```
347
-
348
- ---
349
-
350
- ## Structure
13
+ ## What It Does
351
14
 
352
- After init, your project has:
353
-
354
- ```
355
- your-project/
356
- ├── CLAUDE.md # Instructions for Claude
357
- └── .claude/
358
- ├── .version # Framework version
359
- ├── settings.json # Permissions
360
- ├── commands/ # Slash commands
361
- │ ├── task.md
362
- │ ├── status.md
363
- │ ├── done.md
364
- │ └── analyze.md
365
- ├── skills/ # Reference guides
366
- │ ├── pattern-discovery.md
367
- │ ├── systematic-debugging.md
368
- │ └── testing-methodology.md
369
- └── state/
370
- └── task.md # Current task state
371
- ```
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
372
20
 
373
21
  ## Commands
374
22
 
375
- | Command | What it does |
23
+ | Command | Description |
376
24
  |---------|-------------|
377
- | `/task <desc>` | Start working on something |
25
+ | `/task <desc>` | Start a new task |
378
26
  | `/status` | Show current task |
379
27
  | `/done` | Mark task complete |
380
28
  | `/analyze <area>` | Deep dive into code |
381
29
 
382
- ## Skills
383
-
384
- The framework includes methodology guides in `.claude/skills/`:
385
-
386
- | Skill | Use When |
387
- |-------|----------|
388
- | **pattern-discovery.md** | Adding new code that should match existing patterns |
389
- | **systematic-debugging.md** | Investigating bugs or unexpected behavior |
390
- | **testing-methodology.md** | Writing tests or improving test coverage |
391
-
392
- Claude references these when the situation calls for it.
393
-
394
- ## State Management
395
-
396
- All state lives in `.claude/state/task.md`. Example:
30
+ ## Options
397
31
 
398
- ```markdown
399
- # Current Task
400
-
401
- ## Status: In Progress
402
-
403
- **Task:** Add user authentication
404
-
405
- ## Context
406
-
407
- Building JWT-based auth for the Express API.
408
-
409
- ## Next Steps
410
-
411
- 1. Create auth middleware
412
- 2. Add login endpoint
413
- 3. Test
414
-
415
- ## Decisions
416
-
417
- - Using RS256 for JWT signing
418
- - Refresh tokens in httpOnly cookies
419
- - 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
420
35
  ```
421
36
 
422
- When you resume a session, Claude reads this file and continues where you left off.
37
+ ## Tip
423
38
 
424
- ## Global .gitignore
425
-
426
- Add `.claude/` to your global gitignore so it's ignored in all projects:
39
+ Add `.claude/` to your global gitignore:
427
40
 
428
41
  ```bash
429
42
  echo ".claude/" >> ~/.gitignore
430
43
  git config --global core.excludesfile ~/.gitignore
431
44
  ```
432
45
 
433
- ## Permissions
434
-
435
- The `settings.json` pre-approves common dev commands:
436
-
437
- - **Git**: status, diff, log, add, commit, etc.
438
- - **Package managers**: npm, yarn, pnpm, bun, pip, cargo
439
- - **Build tools**: node, tsc, make, docker
440
- - **Test runners**: jest, vitest
441
- - **Linters**: eslint, prettier
442
-
443
- Edit `.claude/settings.json` to customize for your stack.
444
-
445
- ## Troubleshooting
446
-
447
- ### Init script fails on macOS
448
-
449
- The script is compatible with Bash 3.x (macOS default). If you see errors, check your bash version:
450
-
451
- ```bash
452
- bash --version
453
- ```
454
-
455
- ### Commands not recognized
456
-
457
- If `/task`, `/status`, etc. don't work:
458
-
459
- 1. Check that `.claude/commands/` exists in your project
460
- 2. Verify files have YAML frontmatter (lines starting with `---`)
461
- 3. Re-run init to refresh command files
462
-
463
- ### Settings keep resetting
464
-
465
- The init script preserves your `settings.json` if it exists. If it's being overwritten:
466
-
467
- 1. Check you're not running from inside the framework folder
468
- 2. Verify `.claude/settings.json` exists before running init
469
-
470
- ### Claude doesn't read task state
471
-
472
- Make sure `CLAUDE.md` exists in your project root. It tells Claude to check `.claude/state/task.md` on startup.
473
-
474
- ### Framework version
475
-
476
- Check your installed version:
477
-
478
- ```bash
479
- cat .claude/.version
480
- ```
481
-
482
- ## Tips
46
+ ## License
483
47
 
484
- 1. **Be specific with tasks** - "Add login endpoint" is better than "work on auth"
485
- 2. **Check status often** - `/status` helps you and Claude stay aligned
486
- 3. **Let Claude update state** - Don't manually edit `.claude/state/task.md`
487
- 4. **Use analyze for exploration** - `/analyze` before diving into unfamiliar code
488
- 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.9",
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,24 +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",
31
- ".claude/.version"
26
+ "dist",
27
+ "templates"
32
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
+ },
33
48
  "engines": {
34
- "node": ">=14.0.0"
49
+ "node": ">=18.0.0"
35
50
  }
36
51
  }
package/.claude/.version DELETED
@@ -1 +0,0 @@
1
- 0.0.8
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" 2>/dev/null || true
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" 2>/dev/null || true
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/" 2>/dev/null || true
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/" 2>/dev/null || true
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