claude-think 0.1.4 → 0.1.6
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/.claude/settings.local.json +3 -1
- package/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/src/cli/commands/setup.ts +225 -4
- package/src/core/generator.ts +29 -9
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"Bash(bun install:*)",
|
|
24
24
|
"Bash(bun:*)",
|
|
25
25
|
"Bash(git commit -m \"$\\(cat <<''EOF''\nv0.1.3: Fix --version to read from package.json\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
|
26
|
-
"Bash(git commit -m \"$\\(cat <<''EOF''\nv0.1.4: Improved setup wizard UX with @clack/prompts\n\n- Arrow key navigation and space to toggle checkboxes\n- Multi-select for frontend, CSS, database, infrastructure\n- Cleaner visual design with spinners and hints\n- Better cancel handling\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")"
|
|
26
|
+
"Bash(git commit -m \"$\\(cat <<''EOF''\nv0.1.4: Improved setup wizard UX with @clack/prompts\n\n- Arrow key navigation and space to toggle checkboxes\n- Multi-select for frontend, CSS, database, infrastructure\n- Cleaner visual design with spinners and hints\n- Better cancel handling\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
|
27
|
+
"Bash(npm view:*)",
|
|
28
|
+
"Bash(git commit:*)"
|
|
27
29
|
]
|
|
28
30
|
}
|
|
29
31
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.6] - 2025-02-05
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Plugin now registers in both settings.json and installed_plugins.json
|
|
12
|
+
- Uses `think@local` key format for proper Claude Code discovery
|
|
13
|
+
|
|
14
|
+
## [0.1.5] - 2025-02-05
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Enhanced profile section with role and experience level
|
|
18
|
+
- Claude personality selection (pair programmer, mentor, assistant, etc.)
|
|
19
|
+
- SDLC preferences: planning, testing, code review, git workflow
|
|
20
|
+
- Documentation, debugging, and refactoring preferences
|
|
21
|
+
- Generated profile now includes full development workflow guidance
|
|
22
|
+
|
|
8
23
|
## [0.1.4] - 2025-02-05
|
|
9
24
|
|
|
10
25
|
### Changed
|
package/package.json
CHANGED
|
@@ -35,6 +35,115 @@ export async function setupCommand(): Promise<void> {
|
|
|
35
35
|
});
|
|
36
36
|
if (p.isCancel(style)) return handleCancel();
|
|
37
37
|
|
|
38
|
+
// === PROFILE & PERSONALITY ===
|
|
39
|
+
p.note("Let's understand who you are and how you work");
|
|
40
|
+
|
|
41
|
+
const role = await p.select({
|
|
42
|
+
message: "What's your role?",
|
|
43
|
+
options: [
|
|
44
|
+
{ value: "senior-dev", label: "Senior Developer", hint: "experienced, autonomous" },
|
|
45
|
+
{ value: "mid-dev", label: "Mid-level Developer", hint: "growing, some guidance helpful" },
|
|
46
|
+
{ value: "junior-dev", label: "Junior Developer", hint: "learning, more explanation needed" },
|
|
47
|
+
{ value: "founder", label: "Founder / Tech Lead", hint: "building fast, shipping matters" },
|
|
48
|
+
{ value: "student", label: "Student", hint: "learning fundamentals" },
|
|
49
|
+
{ value: "hobbyist", label: "Hobbyist", hint: "exploring for fun" },
|
|
50
|
+
],
|
|
51
|
+
});
|
|
52
|
+
if (p.isCancel(role)) return handleCancel();
|
|
53
|
+
|
|
54
|
+
const claudePersonality = await p.select({
|
|
55
|
+
message: "How should Claude behave?",
|
|
56
|
+
options: [
|
|
57
|
+
{ value: "pair-programmer", label: "Pair Programmer", hint: "collaborative, thinks out loud" },
|
|
58
|
+
{ value: "senior-dev", label: "Senior Dev", hint: "gives direction, reviews your approach" },
|
|
59
|
+
{ value: "assistant", label: "Efficient Assistant", hint: "executes tasks, minimal chatter" },
|
|
60
|
+
{ value: "mentor", label: "Mentor", hint: "teaches concepts, explains why" },
|
|
61
|
+
{ value: "rubber-duck", label: "Rubber Duck", hint: "helps you think, asks questions" },
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
if (p.isCancel(claudePersonality)) return handleCancel();
|
|
65
|
+
|
|
66
|
+
// === SDLC PREFERENCES ===
|
|
67
|
+
p.note("How do you like to work through the development lifecycle?");
|
|
68
|
+
|
|
69
|
+
const planningApproach = await p.select({
|
|
70
|
+
message: "Planning approach?",
|
|
71
|
+
options: [
|
|
72
|
+
{ value: "plan-first", label: "Plan first", hint: "discuss architecture before coding" },
|
|
73
|
+
{ value: "iterate", label: "Iterate", hint: "rough plan, refine as we go" },
|
|
74
|
+
{ value: "dive-in", label: "Dive in", hint: "start coding, figure it out" },
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
if (p.isCancel(planningApproach)) return handleCancel();
|
|
78
|
+
|
|
79
|
+
const testingApproach = await p.select({
|
|
80
|
+
message: "Testing approach?",
|
|
81
|
+
options: [
|
|
82
|
+
{ value: "tdd", label: "TDD", hint: "write tests first" },
|
|
83
|
+
{ value: "test-after", label: "Test after", hint: "write tests after implementation" },
|
|
84
|
+
{ value: "critical-paths", label: "Critical paths only", hint: "test important stuff" },
|
|
85
|
+
{ value: "minimal", label: "Minimal", hint: "tests when necessary" },
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
if (p.isCancel(testingApproach)) return handleCancel();
|
|
89
|
+
|
|
90
|
+
const codeReview = await p.select({
|
|
91
|
+
message: "Code review preference?",
|
|
92
|
+
options: [
|
|
93
|
+
{ value: "review-before-commit", label: "Review before commit", hint: "Claude reviews changes" },
|
|
94
|
+
{ value: "review-on-request", label: "On request", hint: "review when asked" },
|
|
95
|
+
{ value: "self-review", label: "Self review", hint: "I review my own code" },
|
|
96
|
+
],
|
|
97
|
+
});
|
|
98
|
+
if (p.isCancel(codeReview)) return handleCancel();
|
|
99
|
+
|
|
100
|
+
const gitWorkflow = await p.select({
|
|
101
|
+
message: "Git workflow?",
|
|
102
|
+
options: [
|
|
103
|
+
{ value: "small-commits", label: "Small commits", hint: "atomic, frequent commits" },
|
|
104
|
+
{ value: "feature-branches", label: "Feature branches", hint: "branch per feature, squash merge" },
|
|
105
|
+
{ value: "trunk-based", label: "Trunk-based", hint: "commit to main, feature flags" },
|
|
106
|
+
{ value: "flexible", label: "Flexible", hint: "depends on the project" },
|
|
107
|
+
],
|
|
108
|
+
});
|
|
109
|
+
if (p.isCancel(gitWorkflow)) return handleCancel();
|
|
110
|
+
|
|
111
|
+
const documentationApproach = await p.select({
|
|
112
|
+
message: "Documentation approach?",
|
|
113
|
+
options: [
|
|
114
|
+
{ value: "inline", label: "Inline comments", hint: "document as you code" },
|
|
115
|
+
{ value: "readme-driven", label: "README driven", hint: "docs first, then code" },
|
|
116
|
+
{ value: "minimal", label: "Minimal", hint: "self-documenting code" },
|
|
117
|
+
{ value: "on-request", label: "On request", hint: "document when asked" },
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
if (p.isCancel(documentationApproach)) return handleCancel();
|
|
121
|
+
|
|
122
|
+
const debuggingStyle = await p.select({
|
|
123
|
+
message: "Debugging style?",
|
|
124
|
+
options: [
|
|
125
|
+
{ value: "systematic", label: "Systematic", hint: "isolate, reproduce, trace" },
|
|
126
|
+
{ value: "hypothesis", label: "Hypothesis-driven", hint: "guess likely causes first" },
|
|
127
|
+
{ value: "printf", label: "Printf debugging", hint: "add logs, observe behavior" },
|
|
128
|
+
{ value: "whatever-works", label: "Whatever works", hint: "just fix it" },
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
if (p.isCancel(debuggingStyle)) return handleCancel();
|
|
132
|
+
|
|
133
|
+
const refactoringPreference = await p.select({
|
|
134
|
+
message: "Refactoring preference?",
|
|
135
|
+
options: [
|
|
136
|
+
{ value: "proactive", label: "Proactive", hint: "Claude suggests improvements" },
|
|
137
|
+
{ value: "on-request", label: "On request", hint: "only when asked" },
|
|
138
|
+
{ value: "boy-scout", label: "Boy scout rule", hint: "leave code better than found" },
|
|
139
|
+
{ value: "if-broken", label: "If it ain't broke...", hint: "don't fix what works" },
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
if (p.isCancel(refactoringPreference)) return handleCancel();
|
|
143
|
+
|
|
144
|
+
// === TECH STACK ===
|
|
145
|
+
p.note("Now let's configure your tech stack");
|
|
146
|
+
|
|
38
147
|
const packageManager = await p.select({
|
|
39
148
|
message: "Preferred package manager?",
|
|
40
149
|
options: [
|
|
@@ -295,21 +404,133 @@ export async function setupCommand(): Promise<void> {
|
|
|
295
404
|
],
|
|
296
405
|
};
|
|
297
406
|
|
|
407
|
+
const roleDescriptions: Record<string, string> = {
|
|
408
|
+
"senior-dev": "Senior developer - experienced and autonomous, prefers concise guidance",
|
|
409
|
+
"mid-dev": "Mid-level developer - competent but appreciates context on complex topics",
|
|
410
|
+
"junior-dev": "Junior developer - learning, benefits from more explanation and examples",
|
|
411
|
+
"founder": "Founder/Tech Lead - focused on shipping, pragmatic decisions over perfect code",
|
|
412
|
+
"student": "Student - learning fundamentals, explain concepts when relevant",
|
|
413
|
+
"hobbyist": "Hobbyist - exploring for fun, balance learning with getting things done",
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
const personalityDescriptions: Record<string, string[]> = {
|
|
417
|
+
"pair-programmer": [
|
|
418
|
+
"Act as a pair programmer - think out loud, collaborate on solutions",
|
|
419
|
+
"Discuss trade-offs and alternatives when relevant",
|
|
420
|
+
"Catch potential issues early, suggest improvements as we go",
|
|
421
|
+
],
|
|
422
|
+
"senior-dev": [
|
|
423
|
+
"Act as a senior developer - give direction, review approaches",
|
|
424
|
+
"Point out potential issues and better patterns",
|
|
425
|
+
"Be opinionated when it matters, flexible when it doesn't",
|
|
426
|
+
],
|
|
427
|
+
"assistant": [
|
|
428
|
+
"Act as an efficient assistant - execute tasks with minimal chatter",
|
|
429
|
+
"Ask clarifying questions only when truly needed",
|
|
430
|
+
"Focus on delivering what was asked",
|
|
431
|
+
],
|
|
432
|
+
"mentor": [
|
|
433
|
+
"Act as a mentor - teach concepts, explain the 'why'",
|
|
434
|
+
"Use opportunities to share knowledge",
|
|
435
|
+
"Suggest learning resources when helpful",
|
|
436
|
+
],
|
|
437
|
+
"rubber-duck": [
|
|
438
|
+
"Act as a rubber duck - help me think through problems",
|
|
439
|
+
"Ask probing questions rather than giving immediate answers",
|
|
440
|
+
"Help me discover solutions myself",
|
|
441
|
+
],
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
const planningDescriptions: Record<string, string> = {
|
|
445
|
+
"plan-first": "Discuss architecture and approach before writing code",
|
|
446
|
+
"iterate": "Start with a rough plan, refine as we go",
|
|
447
|
+
"dive-in": "Start coding quickly, figure out structure as needed",
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
const testingDescriptions: Record<string, string> = {
|
|
451
|
+
"tdd": "Write tests first (TDD), then implement",
|
|
452
|
+
"test-after": "Write tests after implementation",
|
|
453
|
+
"critical-paths": "Test critical paths and edge cases",
|
|
454
|
+
"minimal": "Minimal testing - add tests when necessary",
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
const reviewDescriptions: Record<string, string> = {
|
|
458
|
+
"review-before-commit": "Review changes before committing - catch issues early",
|
|
459
|
+
"review-on-request": "Review code when explicitly asked",
|
|
460
|
+
"self-review": "I review my own code, no automatic reviews needed",
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const gitDescriptions: Record<string, string> = {
|
|
464
|
+
"small-commits": "Small, atomic commits - easy to review and revert",
|
|
465
|
+
"feature-branches": "Feature branches with squash merges",
|
|
466
|
+
"trunk-based": "Trunk-based development with feature flags",
|
|
467
|
+
"flexible": "Flexible git workflow based on project needs",
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const docDescriptions: Record<string, string> = {
|
|
471
|
+
"inline": "Document with inline comments as code is written",
|
|
472
|
+
"readme-driven": "README-driven development - docs first",
|
|
473
|
+
"minimal": "Minimal documentation - code should be self-documenting",
|
|
474
|
+
"on-request": "Add documentation when requested",
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
const debugDescriptions: Record<string, string> = {
|
|
478
|
+
"systematic": "Debug systematically - isolate, reproduce, trace",
|
|
479
|
+
"hypothesis": "Hypothesis-driven debugging - test likely causes first",
|
|
480
|
+
"printf": "Printf debugging - add logs and observe",
|
|
481
|
+
"whatever-works": "Whatever works to fix the issue quickly",
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const refactorDescriptions: Record<string, string> = {
|
|
485
|
+
"proactive": "Proactively suggest refactoring opportunities",
|
|
486
|
+
"on-request": "Refactor only when asked",
|
|
487
|
+
"boy-scout": "Boy scout rule - leave code better than you found it",
|
|
488
|
+
"if-broken": "Don't refactor working code unless necessary",
|
|
489
|
+
};
|
|
490
|
+
|
|
298
491
|
const profileContent = `---
|
|
299
492
|
name: ${name}
|
|
493
|
+
role: ${role}
|
|
300
494
|
style: ${style}
|
|
495
|
+
personality: ${claudePersonality}
|
|
301
496
|
---
|
|
302
497
|
|
|
303
|
-
#
|
|
498
|
+
# Who I Am
|
|
499
|
+
|
|
500
|
+
${roleDescriptions[role as string]}
|
|
501
|
+
|
|
502
|
+
# How Claude Should Behave
|
|
503
|
+
|
|
504
|
+
${personalityDescriptions[claudePersonality as string].map((s) => `- ${s}`).join("\n")}
|
|
505
|
+
|
|
506
|
+
# Communication Style
|
|
304
507
|
|
|
305
508
|
${styleDescriptions[style as string].map((s) => `- ${s}`).join("\n")}
|
|
306
509
|
- No emojis unless explicitly requested
|
|
307
510
|
- Show code when it's clearer than explanation
|
|
308
511
|
|
|
309
|
-
#
|
|
512
|
+
# Development Workflow
|
|
513
|
+
|
|
514
|
+
## Planning
|
|
515
|
+
- ${planningDescriptions[planningApproach as string]}
|
|
516
|
+
|
|
517
|
+
## Testing
|
|
518
|
+
- ${testingDescriptions[testingApproach as string]}
|
|
519
|
+
|
|
520
|
+
## Code Review
|
|
521
|
+
- ${reviewDescriptions[codeReview as string]}
|
|
522
|
+
|
|
523
|
+
## Git Workflow
|
|
524
|
+
- ${gitDescriptions[gitWorkflow as string]}
|
|
525
|
+
|
|
526
|
+
## Documentation
|
|
527
|
+
- ${docDescriptions[documentationApproach as string]}
|
|
528
|
+
|
|
529
|
+
## Debugging
|
|
530
|
+
- ${debugDescriptions[debuggingStyle as string]}
|
|
310
531
|
|
|
311
|
-
|
|
312
|
-
-
|
|
532
|
+
## Refactoring
|
|
533
|
+
- ${refactorDescriptions[refactoringPreference as string]}
|
|
313
534
|
`;
|
|
314
535
|
|
|
315
536
|
await writeFile(thinkPath(CONFIG.files.profile), profileContent);
|
package/src/core/generator.ts
CHANGED
|
@@ -195,29 +195,49 @@ async function copyDirectory(src: string, dest: string): Promise<void> {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
async function registerPlugin(): Promise<void> {
|
|
198
|
-
const
|
|
198
|
+
const claudeDir = join(homedir(), ".claude");
|
|
199
|
+
const settingsPath = join(claudeDir, "settings.json");
|
|
200
|
+
const installedPluginsPath = join(claudeDir, "plugins", "installed_plugins.json");
|
|
199
201
|
|
|
202
|
+
// 1. Update settings.json to enable the plugin
|
|
200
203
|
let settings: Record<string, unknown> = {};
|
|
201
|
-
|
|
202
|
-
// Read existing settings if they exist
|
|
203
204
|
if (existsSync(settingsPath)) {
|
|
204
205
|
try {
|
|
205
206
|
const content = await readFile(settingsPath, "utf-8");
|
|
206
207
|
settings = JSON.parse(content);
|
|
207
208
|
} catch {
|
|
208
|
-
// If parse fails, start fresh
|
|
209
209
|
settings = {};
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
// Ensure enabledPlugins exists
|
|
214
213
|
if (!settings.enabledPlugins) {
|
|
215
214
|
settings.enabledPlugins = {};
|
|
216
215
|
}
|
|
216
|
+
(settings.enabledPlugins as Record<string, boolean>)["think@local"] = true;
|
|
217
217
|
|
|
218
|
-
// Add think plugin (local plugins don't need @marketplace suffix)
|
|
219
|
-
(settings.enabledPlugins as Record<string, boolean>)["think"] = true;
|
|
220
|
-
|
|
221
|
-
// Write updated settings
|
|
222
218
|
await writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
219
|
+
|
|
220
|
+
// 2. Update installed_plugins.json to register the plugin
|
|
221
|
+
let installedPlugins: Record<string, unknown> = { version: 2, plugins: {} };
|
|
222
|
+
if (existsSync(installedPluginsPath)) {
|
|
223
|
+
try {
|
|
224
|
+
const content = await readFile(installedPluginsPath, "utf-8");
|
|
225
|
+
installedPlugins = JSON.parse(content);
|
|
226
|
+
} catch {
|
|
227
|
+
installedPlugins = { version: 2, plugins: {} };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const plugins = installedPlugins.plugins as Record<string, unknown[]>;
|
|
232
|
+
plugins["think@local"] = [
|
|
233
|
+
{
|
|
234
|
+
scope: "user",
|
|
235
|
+
installPath: CONFIG.pluginDir,
|
|
236
|
+
version: "local",
|
|
237
|
+
installedAt: new Date().toISOString(),
|
|
238
|
+
lastUpdated: new Date().toISOString(),
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
|
|
242
|
+
await writeFile(installedPluginsPath, JSON.stringify(installedPlugins, null, 2));
|
|
223
243
|
}
|