claude-think 0.1.3 → 0.1.5
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 +4 -1
- package/CHANGELOG.md +17 -0
- package/bun.lock +9 -0
- package/package.json +2 -1
- package/src/cli/commands/setup.ts +614 -418
|
@@ -22,7 +22,10 @@
|
|
|
22
22
|
"Bash(npm publish:*)",
|
|
23
23
|
"Bash(bun install:*)",
|
|
24
24
|
"Bash(bun:*)",
|
|
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\\)\")"
|
|
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\\)\")",
|
|
27
|
+
"Bash(npm view:*)",
|
|
28
|
+
"Bash(git commit:*)"
|
|
26
29
|
]
|
|
27
30
|
}
|
|
28
31
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ 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.5] - 2025-02-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Enhanced profile section with role and experience level
|
|
12
|
+
- Claude personality selection (pair programmer, mentor, assistant, etc.)
|
|
13
|
+
- SDLC preferences: planning, testing, code review, git workflow
|
|
14
|
+
- Documentation, debugging, and refactoring preferences
|
|
15
|
+
- Generated profile now includes full development workflow guidance
|
|
16
|
+
|
|
17
|
+
## [0.1.4] - 2025-02-05
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Setup wizard now uses @clack/prompts for better UX
|
|
21
|
+
- Arrow key navigation and space to toggle checkboxes
|
|
22
|
+
- Multi-select for frontend, CSS, database, infrastructure (can pick multiple)
|
|
23
|
+
- Cleaner visual design with spinners and hints
|
|
24
|
+
|
|
8
25
|
## [0.1.3] - 2025-02-05
|
|
9
26
|
|
|
10
27
|
### Fixed
|
package/bun.lock
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"": {
|
|
6
6
|
"name": "think",
|
|
7
7
|
"dependencies": {
|
|
8
|
+
"@clack/prompts": "^1.0.0",
|
|
8
9
|
"chalk": "^5.6.2",
|
|
9
10
|
"commander": "^14.0.3",
|
|
10
11
|
"gray-matter": "^4.0.3",
|
|
@@ -25,6 +26,10 @@
|
|
|
25
26
|
"packages": {
|
|
26
27
|
"@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.2.4", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-HTgrrTgZ9Jgeo6Z3oqbQ7lifOVvRR14vaDuBGPPUxk9Thm+vObaO4QfYYYWw4Zo5CWQDBEfsinFA6Gre+AqwNQ=="],
|
|
27
28
|
|
|
29
|
+
"@clack/core": ["@clack/core@1.0.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-Orf9Ltr5NeiEuVJS8Rk2XTw3IxNC2Bic3ash7GgYeA8LJ/zmSNpSQ/m5UAhe03lA6KFgklzZ5KTHs4OAMA/SAQ=="],
|
|
30
|
+
|
|
31
|
+
"@clack/prompts": ["@clack/prompts@1.0.0", "", { "dependencies": { "@clack/core": "1.0.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-rWPXg9UaCFqErJVQ+MecOaWsozjaxol4yjnmYcGNipAWzdaWa2x+VJmKfGq7L0APwBohQOYdHC+9RO4qRXej+A=="],
|
|
32
|
+
|
|
28
33
|
"@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
|
|
29
34
|
|
|
30
35
|
"@types/node": ["@types/node@25.2.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg=="],
|
|
@@ -97,6 +102,8 @@
|
|
|
97
102
|
|
|
98
103
|
"patch-console": ["patch-console@2.0.0", "", {}, "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA=="],
|
|
99
104
|
|
|
105
|
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
106
|
+
|
|
100
107
|
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
|
101
108
|
|
|
102
109
|
"react-reconciler": ["react-reconciler@0.33.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA=="],
|
|
@@ -109,6 +116,8 @@
|
|
|
109
116
|
|
|
110
117
|
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
|
111
118
|
|
|
119
|
+
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
|
120
|
+
|
|
112
121
|
"slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
|
|
113
122
|
|
|
114
123
|
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-think",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Personal context manager for Claude - manage your preferences, patterns, and memory",
|
|
5
5
|
"author": "Amit Feldman",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"typescript": "^5"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@clack/prompts": "^1.0.0",
|
|
30
31
|
"chalk": "^5.6.2",
|
|
31
32
|
"commander": "^14.0.3",
|
|
32
33
|
"gray-matter": "^4.0.3",
|
|
@@ -1,29 +1,11 @@
|
|
|
1
|
-
import { writeFile
|
|
1
|
+
import { writeFile } from "fs/promises";
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
|
-
import * as
|
|
3
|
+
import * as p from "@clack/prompts";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { CONFIG, thinkPath } from "../../core/config";
|
|
6
6
|
import { printBanner } from "../../core/banner";
|
|
7
7
|
import { syncCommand } from "./sync";
|
|
8
8
|
|
|
9
|
-
interface SetupAnswers {
|
|
10
|
-
name: string;
|
|
11
|
-
style: "direct" | "conversational" | "detailed";
|
|
12
|
-
packageManager: "bun" | "pnpm" | "npm" | "yarn";
|
|
13
|
-
languages: string[];
|
|
14
|
-
backend: string;
|
|
15
|
-
frontend: string;
|
|
16
|
-
css: string;
|
|
17
|
-
database: string;
|
|
18
|
-
infrastructure: string;
|
|
19
|
-
monorepo: string;
|
|
20
|
-
testing: string[];
|
|
21
|
-
linting: string[];
|
|
22
|
-
validation: string[];
|
|
23
|
-
editor: string;
|
|
24
|
-
avoidAll: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
9
|
/**
|
|
28
10
|
* Interactive profile setup wizard
|
|
29
11
|
*/
|
|
@@ -34,428 +16,644 @@ export async function setupCommand(): Promise<void> {
|
|
|
34
16
|
}
|
|
35
17
|
|
|
36
18
|
printBanner();
|
|
37
|
-
console.log(chalk.bold("Profile Setup\n"));
|
|
38
|
-
console.log(chalk.dim("Let's configure your preferences.\n"));
|
|
39
19
|
|
|
40
|
-
|
|
41
|
-
input: process.stdin,
|
|
42
|
-
output: process.stdout,
|
|
43
|
-
});
|
|
20
|
+
p.intro(chalk.bgCyan(chalk.black(" think setup ")));
|
|
44
21
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
22
|
+
const name = await p.text({
|
|
23
|
+
message: "What's your name?",
|
|
24
|
+
placeholder: "Your name",
|
|
25
|
+
});
|
|
26
|
+
if (p.isCancel(name)) return handleCancel();
|
|
27
|
+
|
|
28
|
+
const style = await p.select({
|
|
29
|
+
message: "What communication style do you prefer?",
|
|
30
|
+
options: [
|
|
31
|
+
{ value: "direct", label: "Direct & minimal", hint: "no fluff, just answers" },
|
|
32
|
+
{ value: "conversational", label: "Conversational", hint: "friendly but efficient" },
|
|
33
|
+
{ value: "detailed", label: "Detailed", hint: "thorough explanations" },
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
if (p.isCancel(style)) return handleCancel();
|
|
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
|
+
|
|
147
|
+
const packageManager = await p.select({
|
|
148
|
+
message: "Preferred package manager?",
|
|
149
|
+
options: [
|
|
150
|
+
{ value: "bun", label: "Bun" },
|
|
151
|
+
{ value: "pnpm", label: "pnpm" },
|
|
152
|
+
{ value: "npm", label: "npm" },
|
|
153
|
+
{ value: "yarn", label: "yarn" },
|
|
154
|
+
],
|
|
155
|
+
});
|
|
156
|
+
if (p.isCancel(packageManager)) return handleCancel();
|
|
157
|
+
|
|
158
|
+
let bunFeatures: string[] = [];
|
|
159
|
+
if (packageManager === "bun") {
|
|
160
|
+
const features = await p.multiselect({
|
|
161
|
+
message: "Bun features you use?",
|
|
162
|
+
options: [
|
|
163
|
+
{ value: "catalog", label: "Dependency catalog" },
|
|
164
|
+
{ value: "workspaces", label: "Bun workspaces" },
|
|
165
|
+
{ value: "macros", label: "Bun macros" },
|
|
166
|
+
{ value: "shell", label: "Bun shell ($``)" },
|
|
167
|
+
{ value: "sqlite", label: "bun:sqlite" },
|
|
168
|
+
{ value: "test", label: "bun test" },
|
|
169
|
+
],
|
|
170
|
+
required: false,
|
|
48
171
|
});
|
|
172
|
+
if (p.isCancel(features)) return handleCancel();
|
|
173
|
+
bunFeatures = features as string[];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const languages = await p.multiselect({
|
|
177
|
+
message: "Primary programming languages?",
|
|
178
|
+
options: [
|
|
179
|
+
{ value: "TypeScript", label: "TypeScript" },
|
|
180
|
+
{ value: "JavaScript", label: "JavaScript" },
|
|
181
|
+
{ value: "Python", label: "Python" },
|
|
182
|
+
{ value: "Ruby", label: "Ruby" },
|
|
183
|
+
{ value: "Rust", label: "Rust" },
|
|
184
|
+
{ value: "Go", label: "Go" },
|
|
185
|
+
{ value: "Java", label: "Java" },
|
|
186
|
+
{ value: "C#", label: "C#" },
|
|
187
|
+
{ value: "PHP", label: "PHP" },
|
|
188
|
+
{ value: "Elixir", label: "Elixir" },
|
|
189
|
+
],
|
|
190
|
+
required: true,
|
|
191
|
+
});
|
|
192
|
+
if (p.isCancel(languages)) return handleCancel();
|
|
193
|
+
|
|
194
|
+
const backend = await p.select({
|
|
195
|
+
message: "Backend framework?",
|
|
196
|
+
options: [
|
|
197
|
+
{ value: "none", label: "None / Custom" },
|
|
198
|
+
{ value: "Rails", label: "Ruby on Rails" },
|
|
199
|
+
{ value: "Django", label: "Django" },
|
|
200
|
+
{ value: "FastAPI", label: "FastAPI" },
|
|
201
|
+
{ value: "Express", label: "Express.js" },
|
|
202
|
+
{ value: "Hono", label: "Hono" },
|
|
203
|
+
{ value: "Phoenix", label: "Phoenix (Elixir)" },
|
|
204
|
+
{ value: "Spring", label: "Spring Boot" },
|
|
205
|
+
{ value: "ASP.NET", label: "ASP.NET Core" },
|
|
206
|
+
{ value: "Laravel", label: "Laravel" },
|
|
207
|
+
],
|
|
208
|
+
});
|
|
209
|
+
if (p.isCancel(backend)) return handleCancel();
|
|
210
|
+
|
|
211
|
+
const frontend = await p.multiselect({
|
|
212
|
+
message: "Frontend frameworks?",
|
|
213
|
+
options: [
|
|
214
|
+
{ value: "React", label: "React" },
|
|
215
|
+
{ value: "Vue", label: "Vue.js" },
|
|
216
|
+
{ value: "Svelte", label: "Svelte" },
|
|
217
|
+
{ value: "Angular", label: "Angular" },
|
|
218
|
+
{ value: "Solid", label: "SolidJS" },
|
|
219
|
+
{ value: "HTMX", label: "HTMX" },
|
|
220
|
+
],
|
|
221
|
+
required: false,
|
|
222
|
+
});
|
|
223
|
+
if (p.isCancel(frontend)) return handleCancel();
|
|
224
|
+
|
|
225
|
+
const css = await p.multiselect({
|
|
226
|
+
message: "CSS / UI frameworks?",
|
|
227
|
+
options: [
|
|
228
|
+
{ value: "Tailwind", label: "Tailwind CSS" },
|
|
229
|
+
{ value: "Vuetify", label: "Vuetify" },
|
|
230
|
+
{ value: "Bootstrap", label: "Bootstrap" },
|
|
231
|
+
{ value: "Material UI", label: "Material UI" },
|
|
232
|
+
{ value: "shadcn/ui", label: "shadcn/ui" },
|
|
233
|
+
{ value: "CSS Modules", label: "CSS Modules" },
|
|
234
|
+
{ value: "styled-components", label: "styled-components" },
|
|
235
|
+
],
|
|
236
|
+
required: false,
|
|
237
|
+
});
|
|
238
|
+
if (p.isCancel(css)) return handleCancel();
|
|
239
|
+
|
|
240
|
+
const database = await p.multiselect({
|
|
241
|
+
message: "Databases?",
|
|
242
|
+
options: [
|
|
243
|
+
{ value: "PostgreSQL", label: "PostgreSQL" },
|
|
244
|
+
{ value: "MySQL", label: "MySQL" },
|
|
245
|
+
{ value: "MongoDB", label: "MongoDB" },
|
|
246
|
+
{ value: "SQLite", label: "SQLite" },
|
|
247
|
+
{ value: "Redis", label: "Redis" },
|
|
248
|
+
{ value: "Supabase", label: "Supabase" },
|
|
249
|
+
{ value: "Firebase", label: "Firebase" },
|
|
250
|
+
],
|
|
251
|
+
required: false,
|
|
252
|
+
});
|
|
253
|
+
if (p.isCancel(database)) return handleCancel();
|
|
254
|
+
|
|
255
|
+
const orm = await p.multiselect({
|
|
256
|
+
message: "ORM / database tools?",
|
|
257
|
+
options: [
|
|
258
|
+
{ value: "Prisma", label: "Prisma" },
|
|
259
|
+
{ value: "Drizzle", label: "Drizzle" },
|
|
260
|
+
{ value: "TypeORM", label: "TypeORM" },
|
|
261
|
+
{ value: "Kysely", label: "Kysely" },
|
|
262
|
+
{ value: "Sequelize", label: "Sequelize" },
|
|
263
|
+
{ value: "Mongoose", label: "Mongoose" },
|
|
264
|
+
{ value: "ActiveRecord", label: "ActiveRecord (Rails)" },
|
|
265
|
+
{ value: "SQLAlchemy", label: "SQLAlchemy" },
|
|
266
|
+
{ value: "Django ORM", label: "Django ORM" },
|
|
267
|
+
],
|
|
268
|
+
required: false,
|
|
269
|
+
});
|
|
270
|
+
if (p.isCancel(orm)) return handleCancel();
|
|
271
|
+
|
|
272
|
+
const auth = await p.multiselect({
|
|
273
|
+
message: "Authentication?",
|
|
274
|
+
options: [
|
|
275
|
+
{ value: "better-auth", label: "better-auth" },
|
|
276
|
+
{ value: "Auth.js", label: "Auth.js (NextAuth)" },
|
|
277
|
+
{ value: "Lucia", label: "Lucia" },
|
|
278
|
+
{ value: "Clerk", label: "Clerk" },
|
|
279
|
+
{ value: "Supabase Auth", label: "Supabase Auth" },
|
|
280
|
+
{ value: "Firebase Auth", label: "Firebase Auth" },
|
|
281
|
+
{ value: "Passport.js", label: "Passport.js" },
|
|
282
|
+
{ value: "Devise", label: "Devise (Rails)" },
|
|
283
|
+
],
|
|
284
|
+
required: false,
|
|
285
|
+
});
|
|
286
|
+
if (p.isCancel(auth)) return handleCancel();
|
|
287
|
+
|
|
288
|
+
const infrastructure = await p.multiselect({
|
|
289
|
+
message: "Infrastructure / deployment?",
|
|
290
|
+
options: [
|
|
291
|
+
{ value: "Docker Compose", label: "Docker + Compose" },
|
|
292
|
+
{ value: "Docker", label: "Docker only" },
|
|
293
|
+
{ value: "Kubernetes", label: "Kubernetes" },
|
|
294
|
+
{ value: "Fly.io", label: "Fly.io" },
|
|
295
|
+
{ value: "Vercel", label: "Vercel" },
|
|
296
|
+
{ value: "Railway", label: "Railway" },
|
|
297
|
+
{ value: "Render", label: "Render" },
|
|
298
|
+
],
|
|
299
|
+
required: false,
|
|
300
|
+
});
|
|
301
|
+
if (p.isCancel(infrastructure)) return handleCancel();
|
|
302
|
+
|
|
303
|
+
const monorepo = await p.select({
|
|
304
|
+
message: "Monorepo tooling?",
|
|
305
|
+
options: [
|
|
306
|
+
{ value: "none", label: "None / Single repo" },
|
|
307
|
+
{ value: "Turborepo", label: "Turborepo" },
|
|
308
|
+
{ value: "Bun workspaces", label: "Bun workspaces" },
|
|
309
|
+
{ value: "Nx", label: "Nx" },
|
|
310
|
+
{ value: "pnpm workspaces", label: "pnpm workspaces" },
|
|
311
|
+
{ value: "Lerna", label: "Lerna" },
|
|
312
|
+
],
|
|
313
|
+
});
|
|
314
|
+
if (p.isCancel(monorepo)) return handleCancel();
|
|
315
|
+
|
|
316
|
+
const testing = await p.multiselect({
|
|
317
|
+
message: "Testing frameworks?",
|
|
318
|
+
options: [
|
|
319
|
+
{ value: "bun test", label: "bun test" },
|
|
320
|
+
{ value: "Vitest", label: "Vitest" },
|
|
321
|
+
{ value: "Jest", label: "Jest" },
|
|
322
|
+
{ value: "RSpec", label: "RSpec" },
|
|
323
|
+
{ value: "pytest", label: "pytest" },
|
|
324
|
+
{ value: "Playwright", label: "Playwright (E2E)" },
|
|
325
|
+
{ value: "Cypress", label: "Cypress (E2E)" },
|
|
326
|
+
],
|
|
327
|
+
required: false,
|
|
328
|
+
});
|
|
329
|
+
if (p.isCancel(testing)) return handleCancel();
|
|
330
|
+
|
|
331
|
+
const linting = await p.multiselect({
|
|
332
|
+
message: "Linting & formatting?",
|
|
333
|
+
options: [
|
|
334
|
+
{ value: "Biome", label: "Biome" },
|
|
335
|
+
{ value: "ESLint", label: "ESLint" },
|
|
336
|
+
{ value: "Prettier", label: "Prettier" },
|
|
337
|
+
{ value: "oxlint", label: "oxlint" },
|
|
338
|
+
{ value: "Rubocop", label: "Rubocop" },
|
|
339
|
+
{ value: "Ruff", label: "Ruff (Python)" },
|
|
340
|
+
{ value: "rustfmt", label: "rustfmt" },
|
|
341
|
+
{ value: "gofmt", label: "gofmt" },
|
|
342
|
+
],
|
|
343
|
+
required: false,
|
|
344
|
+
});
|
|
345
|
+
if (p.isCancel(linting)) return handleCancel();
|
|
346
|
+
|
|
347
|
+
const validation = await p.multiselect({
|
|
348
|
+
message: "Validation & schema libraries?",
|
|
349
|
+
options: [
|
|
350
|
+
{ value: "Zod", label: "Zod" },
|
|
351
|
+
{ value: "Yup", label: "Yup" },
|
|
352
|
+
{ value: "Valibot", label: "Valibot" },
|
|
353
|
+
{ value: "ArkType", label: "ArkType" },
|
|
354
|
+
{ value: "io-ts", label: "io-ts" },
|
|
355
|
+
{ value: "TypeBox", label: "TypeBox" },
|
|
356
|
+
{ value: "Pydantic", label: "Pydantic" },
|
|
357
|
+
{ value: "Joi", label: "Joi" },
|
|
358
|
+
],
|
|
359
|
+
required: false,
|
|
360
|
+
});
|
|
361
|
+
if (p.isCancel(validation)) return handleCancel();
|
|
362
|
+
|
|
363
|
+
const editor = await p.select({
|
|
364
|
+
message: "Primary editor?",
|
|
365
|
+
options: [
|
|
366
|
+
{ value: "Zed", label: "Zed" },
|
|
367
|
+
{ value: "VS Code", label: "VS Code" },
|
|
368
|
+
{ value: "Cursor", label: "Cursor" },
|
|
369
|
+
{ value: "Neovim", label: "Neovim" },
|
|
370
|
+
{ value: "WebStorm", label: "WebStorm" },
|
|
371
|
+
],
|
|
372
|
+
});
|
|
373
|
+
if (p.isCancel(editor)) return handleCancel();
|
|
374
|
+
|
|
375
|
+
const avoidAnswer = await p.select({
|
|
376
|
+
message: "What should Claude avoid?",
|
|
377
|
+
options: [
|
|
378
|
+
{ value: "all", label: "All", hint: "over-engineering, verbose explanations, extra features" },
|
|
379
|
+
{ value: "some", label: "Just over-engineering" },
|
|
380
|
+
{ value: "none", label: "No specific restrictions" },
|
|
381
|
+
],
|
|
382
|
+
});
|
|
383
|
+
if (p.isCancel(avoidAnswer)) return handleCancel();
|
|
384
|
+
|
|
385
|
+
const s = p.spinner();
|
|
386
|
+
s.start("Generating profile");
|
|
387
|
+
|
|
388
|
+
// Generate profile
|
|
389
|
+
const styleDescriptions: Record<string, string[]> = {
|
|
390
|
+
direct: [
|
|
391
|
+
"Be direct and minimal - no fluff, just answers and code",
|
|
392
|
+
"Skip lengthy reasoning unless asked",
|
|
393
|
+
"Don't explain obvious things",
|
|
394
|
+
],
|
|
395
|
+
conversational: [
|
|
396
|
+
"Be friendly but efficient",
|
|
397
|
+
"Brief explanations when helpful",
|
|
398
|
+
"Keep a conversational tone",
|
|
399
|
+
],
|
|
400
|
+
detailed: [
|
|
401
|
+
"Provide thorough explanations",
|
|
402
|
+
"Include context and reasoning",
|
|
403
|
+
"Explain trade-offs and alternatives",
|
|
404
|
+
],
|
|
49
405
|
};
|
|
50
406
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
const answer = await question(chalk.dim("Enter number: "));
|
|
60
|
-
const idx = parseInt(answer) - 1;
|
|
61
|
-
if (idx >= 0 && idx < options.length) {
|
|
62
|
-
return options[idx].key;
|
|
63
|
-
}
|
|
64
|
-
return options[0].key;
|
|
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",
|
|
65
414
|
};
|
|
66
415
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
+
],
|
|
80
442
|
};
|
|
81
443
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Communication style
|
|
88
|
-
const style = await select("What communication style do you prefer?", [
|
|
89
|
-
{ key: "direct", label: "Direct & minimal - no fluff, just answers" },
|
|
90
|
-
{ key: "conversational", label: "Conversational - friendly but efficient" },
|
|
91
|
-
{ key: "detailed", label: "Detailed - thorough explanations" },
|
|
92
|
-
]);
|
|
93
|
-
console.log();
|
|
94
|
-
|
|
95
|
-
// Package manager
|
|
96
|
-
const packageManager = await select("Preferred package manager?", [
|
|
97
|
-
{ key: "bun", label: "bun" },
|
|
98
|
-
{ key: "pnpm", label: "pnpm" },
|
|
99
|
-
{ key: "npm", label: "npm" },
|
|
100
|
-
{ key: "yarn", label: "yarn" },
|
|
101
|
-
]);
|
|
102
|
-
console.log();
|
|
103
|
-
|
|
104
|
-
// Bun-specific features
|
|
105
|
-
let bunFeatures: string[] = [];
|
|
106
|
-
if (packageManager === "bun") {
|
|
107
|
-
bunFeatures = await multiSelect("Bun features you use?", [
|
|
108
|
-
{ key: "catalog", label: "Dependency catalog" },
|
|
109
|
-
{ key: "workspaces", label: "Bun workspaces" },
|
|
110
|
-
{ key: "macros", label: "Bun macros" },
|
|
111
|
-
{ key: "shell", label: "Bun shell ($``)" },
|
|
112
|
-
{ key: "sqlite", label: "bun:sqlite" },
|
|
113
|
-
{ key: "test", label: "bun test" },
|
|
114
|
-
]);
|
|
115
|
-
console.log();
|
|
116
|
-
}
|
|
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
|
+
};
|
|
117
449
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{ key: "Rust", label: "Rust" },
|
|
125
|
-
{ key: "Go", label: "Go" },
|
|
126
|
-
{ key: "Java", label: "Java" },
|
|
127
|
-
{ key: "C#", label: "C#" },
|
|
128
|
-
{ key: "PHP", label: "PHP" },
|
|
129
|
-
{ key: "Elixir", label: "Elixir" },
|
|
130
|
-
]);
|
|
131
|
-
console.log();
|
|
132
|
-
|
|
133
|
-
// Backend framework
|
|
134
|
-
const backend = await select("Backend framework?", [
|
|
135
|
-
{ key: "none", label: "None / Custom" },
|
|
136
|
-
{ key: "Rails", label: "Ruby on Rails" },
|
|
137
|
-
{ key: "Django", label: "Django" },
|
|
138
|
-
{ key: "FastAPI", label: "FastAPI" },
|
|
139
|
-
{ key: "Express", label: "Express.js" },
|
|
140
|
-
{ key: "Hono", label: "Hono" },
|
|
141
|
-
{ key: "Phoenix", label: "Phoenix (Elixir)" },
|
|
142
|
-
{ key: "Spring", label: "Spring Boot" },
|
|
143
|
-
{ key: "ASP.NET", label: "ASP.NET Core" },
|
|
144
|
-
{ key: "Laravel", label: "Laravel" },
|
|
145
|
-
]);
|
|
146
|
-
console.log();
|
|
147
|
-
|
|
148
|
-
// Frontend framework
|
|
149
|
-
const frontend = await select("Frontend framework?", [
|
|
150
|
-
{ key: "none", label: "None / Backend only" },
|
|
151
|
-
{ key: "React", label: "React" },
|
|
152
|
-
{ key: "Vue", label: "Vue.js" },
|
|
153
|
-
{ key: "Svelte", label: "Svelte" },
|
|
154
|
-
{ key: "Angular", label: "Angular" },
|
|
155
|
-
{ key: "Solid", label: "SolidJS" },
|
|
156
|
-
{ key: "HTMX", label: "HTMX" },
|
|
157
|
-
]);
|
|
158
|
-
console.log();
|
|
159
|
-
|
|
160
|
-
// CSS/UI framework
|
|
161
|
-
const css = await select("CSS / UI framework?", [
|
|
162
|
-
{ key: "none", label: "Plain CSS / None" },
|
|
163
|
-
{ key: "Tailwind", label: "Tailwind CSS" },
|
|
164
|
-
{ key: "Vuetify", label: "Vuetify" },
|
|
165
|
-
{ key: "Bootstrap", label: "Bootstrap" },
|
|
166
|
-
{ key: "Material UI", label: "Material UI" },
|
|
167
|
-
{ key: "shadcn/ui", label: "shadcn/ui" },
|
|
168
|
-
{ key: "CSS Modules", label: "CSS Modules" },
|
|
169
|
-
{ key: "styled-components", label: "styled-components" },
|
|
170
|
-
]);
|
|
171
|
-
console.log();
|
|
172
|
-
|
|
173
|
-
// Database
|
|
174
|
-
const database = await select("Primary database?", [
|
|
175
|
-
{ key: "none", label: "None" },
|
|
176
|
-
{ key: "PostgreSQL", label: "PostgreSQL" },
|
|
177
|
-
{ key: "MySQL", label: "MySQL" },
|
|
178
|
-
{ key: "MongoDB", label: "MongoDB" },
|
|
179
|
-
{ key: "SQLite", label: "SQLite" },
|
|
180
|
-
{ key: "Redis", label: "Redis" },
|
|
181
|
-
{ key: "Supabase", label: "Supabase" },
|
|
182
|
-
{ key: "Firebase", label: "Firebase" },
|
|
183
|
-
]);
|
|
184
|
-
console.log();
|
|
185
|
-
|
|
186
|
-
// ORM / Database tools
|
|
187
|
-
const orm = await multiSelect("ORM / database tools?", [
|
|
188
|
-
{ key: "Prisma", label: "Prisma" },
|
|
189
|
-
{ key: "Drizzle", label: "Drizzle" },
|
|
190
|
-
{ key: "TypeORM", label: "TypeORM" },
|
|
191
|
-
{ key: "Kysely", label: "Kysely" },
|
|
192
|
-
{ key: "Sequelize", label: "Sequelize" },
|
|
193
|
-
{ key: "Mongoose", label: "Mongoose" },
|
|
194
|
-
{ key: "ActiveRecord", label: "ActiveRecord (Rails)" },
|
|
195
|
-
{ key: "SQLAlchemy", label: "SQLAlchemy" },
|
|
196
|
-
{ key: "Django ORM", label: "Django ORM" },
|
|
197
|
-
]);
|
|
198
|
-
console.log();
|
|
199
|
-
|
|
200
|
-
// Auth
|
|
201
|
-
const auth = await multiSelect("Authentication?", [
|
|
202
|
-
{ key: "better-auth", label: "better-auth" },
|
|
203
|
-
{ key: "Auth.js", label: "Auth.js (NextAuth)" },
|
|
204
|
-
{ key: "Lucia", label: "Lucia" },
|
|
205
|
-
{ key: "Clerk", label: "Clerk" },
|
|
206
|
-
{ key: "Supabase Auth", label: "Supabase Auth" },
|
|
207
|
-
{ key: "Firebase Auth", label: "Firebase Auth" },
|
|
208
|
-
{ key: "Passport.js", label: "Passport.js" },
|
|
209
|
-
{ key: "Devise", label: "Devise (Rails)" },
|
|
210
|
-
]);
|
|
211
|
-
console.log();
|
|
212
|
-
|
|
213
|
-
// Infrastructure
|
|
214
|
-
const infrastructure = await select("Infrastructure / containerization?", [
|
|
215
|
-
{ key: "none", label: "None" },
|
|
216
|
-
{ key: "Docker Compose", label: "Docker + Compose" },
|
|
217
|
-
{ key: "Docker", label: "Docker only" },
|
|
218
|
-
{ key: "Kubernetes", label: "Kubernetes" },
|
|
219
|
-
{ key: "Fly.io", label: "Fly.io" },
|
|
220
|
-
{ key: "Vercel", label: "Vercel" },
|
|
221
|
-
{ key: "Railway", label: "Railway" },
|
|
222
|
-
]);
|
|
223
|
-
console.log();
|
|
224
|
-
|
|
225
|
-
// Monorepo
|
|
226
|
-
const monorepo = await select("Monorepo tooling?", [
|
|
227
|
-
{ key: "none", label: "None / Single repo" },
|
|
228
|
-
{ key: "Turborepo", label: "Turborepo" },
|
|
229
|
-
{ key: "Bun workspaces", label: "Bun workspaces" },
|
|
230
|
-
{ key: "Nx", label: "Nx" },
|
|
231
|
-
{ key: "pnpm workspaces", label: "pnpm workspaces" },
|
|
232
|
-
{ key: "Lerna", label: "Lerna" },
|
|
233
|
-
]);
|
|
234
|
-
console.log();
|
|
235
|
-
|
|
236
|
-
// Testing
|
|
237
|
-
const testing = await multiSelect("Testing frameworks?", [
|
|
238
|
-
{ key: "bun test", label: "bun test" },
|
|
239
|
-
{ key: "Vitest", label: "Vitest" },
|
|
240
|
-
{ key: "Jest", label: "Jest" },
|
|
241
|
-
{ key: "RSpec", label: "RSpec" },
|
|
242
|
-
{ key: "pytest", label: "pytest" },
|
|
243
|
-
{ key: "Playwright", label: "Playwright (E2E)" },
|
|
244
|
-
{ key: "Cypress", label: "Cypress (E2E)" },
|
|
245
|
-
]);
|
|
246
|
-
console.log();
|
|
247
|
-
|
|
248
|
-
// Linting/Formatting
|
|
249
|
-
const linting = await multiSelect("Linting & formatting?", [
|
|
250
|
-
{ key: "Biome", label: "Biome" },
|
|
251
|
-
{ key: "ESLint", label: "ESLint" },
|
|
252
|
-
{ key: "Prettier", label: "Prettier" },
|
|
253
|
-
{ key: "oxlint", label: "oxlint" },
|
|
254
|
-
{ key: "Rubocop", label: "Rubocop" },
|
|
255
|
-
{ key: "Ruff", label: "Ruff (Python)" },
|
|
256
|
-
{ key: "rustfmt", label: "rustfmt" },
|
|
257
|
-
{ key: "gofmt", label: "gofmt" },
|
|
258
|
-
]);
|
|
259
|
-
console.log();
|
|
260
|
-
|
|
261
|
-
// Validation/Schema
|
|
262
|
-
const validation = await multiSelect("Validation & schema libraries?", [
|
|
263
|
-
{ key: "Zod", label: "Zod" },
|
|
264
|
-
{ key: "Yup", label: "Yup" },
|
|
265
|
-
{ key: "Valibot", label: "Valibot" },
|
|
266
|
-
{ key: "ArkType", label: "ArkType" },
|
|
267
|
-
{ key: "io-ts", label: "io-ts" },
|
|
268
|
-
{ key: "TypeBox", label: "TypeBox" },
|
|
269
|
-
{ key: "Pydantic", label: "Pydantic" },
|
|
270
|
-
{ key: "Joi", label: "Joi" },
|
|
271
|
-
]);
|
|
272
|
-
console.log();
|
|
273
|
-
|
|
274
|
-
// Editor
|
|
275
|
-
const editor = await select("Primary editor?", [
|
|
276
|
-
{ key: "Zed", label: "Zed" },
|
|
277
|
-
{ key: "VS Code", label: "VS Code" },
|
|
278
|
-
{ key: "Cursor", label: "Cursor" },
|
|
279
|
-
{ key: "Neovim", label: "Neovim" },
|
|
280
|
-
]);
|
|
281
|
-
console.log();
|
|
282
|
-
|
|
283
|
-
// Avoid patterns
|
|
284
|
-
const avoidAnswer = await select("What should Claude avoid?", [
|
|
285
|
-
{ key: "all", label: "All: over-engineering, verbose explanations, extra features" },
|
|
286
|
-
{ key: "some", label: "Just over-engineering" },
|
|
287
|
-
{ key: "none", label: "No specific restrictions" },
|
|
288
|
-
]);
|
|
289
|
-
console.log();
|
|
290
|
-
|
|
291
|
-
rl.close();
|
|
292
|
-
|
|
293
|
-
// Generate profile
|
|
294
|
-
const styleDescriptions: Record<string, string[]> = {
|
|
295
|
-
direct: [
|
|
296
|
-
"Be direct and minimal - no fluff, just answers and code",
|
|
297
|
-
"Skip lengthy reasoning unless asked",
|
|
298
|
-
"Don't explain obvious things",
|
|
299
|
-
],
|
|
300
|
-
conversational: [
|
|
301
|
-
"Be friendly but efficient",
|
|
302
|
-
"Brief explanations when helpful",
|
|
303
|
-
"Keep a conversational tone",
|
|
304
|
-
],
|
|
305
|
-
detailed: [
|
|
306
|
-
"Provide thorough explanations",
|
|
307
|
-
"Include context and reasoning",
|
|
308
|
-
"Explain trade-offs and alternatives",
|
|
309
|
-
],
|
|
310
|
-
};
|
|
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
|
+
};
|
|
311
456
|
|
|
312
|
-
|
|
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
|
+
|
|
491
|
+
const profileContent = `---
|
|
313
492
|
name: ${name}
|
|
493
|
+
role: ${role}
|
|
314
494
|
style: ${style}
|
|
495
|
+
personality: ${claudePersonality}
|
|
315
496
|
---
|
|
316
497
|
|
|
317
|
-
#
|
|
498
|
+
# Who I Am
|
|
318
499
|
|
|
319
|
-
${
|
|
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
|
|
507
|
+
|
|
508
|
+
${styleDescriptions[style as string].map((s) => `- ${s}`).join("\n")}
|
|
320
509
|
- No emojis unless explicitly requested
|
|
321
510
|
- Show code when it's clearer than explanation
|
|
322
511
|
|
|
323
|
-
#
|
|
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]}
|
|
324
531
|
|
|
325
|
-
|
|
326
|
-
-
|
|
532
|
+
## Refactoring
|
|
533
|
+
- ${refactorDescriptions[refactoringPreference as string]}
|
|
327
534
|
`;
|
|
328
535
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
536
|
+
await writeFile(thinkPath(CONFIG.files.profile), profileContent);
|
|
537
|
+
|
|
538
|
+
// Generate tools preferences
|
|
539
|
+
const toolsSections: string[] = ["# Tool Preferences"];
|
|
540
|
+
|
|
541
|
+
// Runtime & Package Manager
|
|
542
|
+
const pmAlternatives = ["npm", "pnpm", "yarn", "Node.js"].filter(
|
|
543
|
+
(pm) => pm.toLowerCase() !== (packageManager as string).toLowerCase()
|
|
544
|
+
);
|
|
545
|
+
const pmSection = [`- Use ${packageManager === "bun" ? "Bun" : packageManager}${pmAlternatives.length ? ` (not ${pmAlternatives.join(", ")})` : ""}`];
|
|
546
|
+
|
|
547
|
+
if (bunFeatures.length > 0) {
|
|
548
|
+
if (bunFeatures.includes("catalog")) pmSection.push("- Use Bun dependency catalog for shared deps");
|
|
549
|
+
if (bunFeatures.includes("workspaces")) pmSection.push("- Use Bun workspaces for monorepos");
|
|
550
|
+
if (bunFeatures.includes("macros")) pmSection.push("- Use Bun macros for compile-time code");
|
|
551
|
+
if (bunFeatures.includes("shell")) pmSection.push("- Use Bun shell ($``) for shell commands");
|
|
552
|
+
if (bunFeatures.includes("sqlite")) pmSection.push("- Use bun:sqlite for embedded database");
|
|
553
|
+
if (bunFeatures.includes("test")) pmSection.push("- Use `bun test` for testing");
|
|
554
|
+
} else {
|
|
555
|
+
pmSection.push(`- Use \`${packageManager} test\` for testing`);
|
|
556
|
+
}
|
|
350
557
|
|
|
351
|
-
|
|
558
|
+
toolsSections.push(`
|
|
352
559
|
## Runtime & Package Manager
|
|
353
560
|
${pmSection.join("\n")}`);
|
|
354
561
|
|
|
355
|
-
|
|
356
|
-
|
|
562
|
+
// Languages
|
|
563
|
+
toolsSections.push(`
|
|
357
564
|
## Languages
|
|
358
|
-
${languages.map((l) => `- ${l}`).join("\n")}`);
|
|
565
|
+
${(languages as string[]).map((l) => `- ${l}`).join("\n")}`);
|
|
359
566
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
567
|
+
// Backend
|
|
568
|
+
if (backend !== "none") {
|
|
569
|
+
toolsSections.push(`
|
|
363
570
|
## Backend
|
|
364
571
|
- ${backend}`);
|
|
365
|
-
|
|
572
|
+
}
|
|
366
573
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
(f) => f.toLowerCase() !== frontend.toLowerCase()
|
|
371
|
-
);
|
|
372
|
-
toolsSections.push(`
|
|
574
|
+
// Frontend
|
|
575
|
+
if ((frontend as string[]).length > 0) {
|
|
576
|
+
toolsSections.push(`
|
|
373
577
|
## Frontend
|
|
374
|
-
|
|
578
|
+
${(frontend as string[]).map((f) => `- ${f}`).join("\n")}
|
|
375
579
|
- Prefer functional components with hooks`);
|
|
580
|
+
}
|
|
376
581
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
582
|
+
// CSS
|
|
583
|
+
if ((css as string[]).length > 0) {
|
|
584
|
+
toolsSections.push(`
|
|
585
|
+
## CSS / UI
|
|
586
|
+
${(css as string[]).map((c) => `- ${c}`).join("\n")}`);
|
|
587
|
+
}
|
|
382
588
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
(d) => d.toLowerCase() !== database.toLowerCase()
|
|
387
|
-
);
|
|
388
|
-
toolsSections.push(`
|
|
589
|
+
// Database
|
|
590
|
+
if ((database as string[]).length > 0) {
|
|
591
|
+
toolsSections.push(`
|
|
389
592
|
## Database
|
|
390
|
-
|
|
391
|
-
|
|
593
|
+
${(database as string[]).map((d) => `- ${d}`).join("\n")}`);
|
|
594
|
+
}
|
|
392
595
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
596
|
+
// ORM
|
|
597
|
+
if ((orm as string[]).length > 0) {
|
|
598
|
+
toolsSections.push(`
|
|
396
599
|
## ORM / Database Tools
|
|
397
|
-
${orm.map((o) => `- ${o}`).join("\n")}`);
|
|
398
|
-
|
|
600
|
+
${(orm as string[]).map((o) => `- ${o}`).join("\n")}`);
|
|
601
|
+
}
|
|
399
602
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
603
|
+
// Auth
|
|
604
|
+
if ((auth as string[]).length > 0) {
|
|
605
|
+
toolsSections.push(`
|
|
403
606
|
## Authentication
|
|
404
|
-
${auth.map((a) => `- ${a}`).join("\n")}`);
|
|
405
|
-
|
|
607
|
+
${(auth as string[]).map((a) => `- ${a}`).join("\n")}`);
|
|
608
|
+
}
|
|
406
609
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
? []
|
|
411
|
-
: ["Kubernetes"];
|
|
412
|
-
toolsSections.push(`
|
|
610
|
+
// Infrastructure
|
|
611
|
+
if ((infrastructure as string[]).length > 0) {
|
|
612
|
+
toolsSections.push(`
|
|
413
613
|
## Infrastructure
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
614
|
+
${(infrastructure as string[]).map((i) => `- ${i}`).join("\n")}`);
|
|
615
|
+
}
|
|
417
616
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
617
|
+
// Monorepo
|
|
618
|
+
if (monorepo !== "none") {
|
|
619
|
+
toolsSections.push(`
|
|
421
620
|
## Monorepo
|
|
422
621
|
- ${monorepo}`);
|
|
423
|
-
|
|
622
|
+
}
|
|
424
623
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
624
|
+
// Testing
|
|
625
|
+
if ((testing as string[]).length > 0) {
|
|
626
|
+
toolsSections.push(`
|
|
428
627
|
## Testing
|
|
429
|
-
${testing.map((t) => `- ${t}`).join("\n")}`);
|
|
430
|
-
|
|
628
|
+
${(testing as string[]).map((t) => `- ${t}`).join("\n")}`);
|
|
629
|
+
}
|
|
431
630
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
631
|
+
// Linting & Formatting
|
|
632
|
+
if ((linting as string[]).length > 0) {
|
|
633
|
+
toolsSections.push(`
|
|
435
634
|
## Linting & Formatting
|
|
436
|
-
${linting.map((l) => `- ${l}`).join("\n")}
|
|
635
|
+
${(linting as string[]).map((l) => `- ${l}`).join("\n")}
|
|
437
636
|
- Use project's existing config when present`);
|
|
438
|
-
|
|
637
|
+
}
|
|
439
638
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
639
|
+
// Validation
|
|
640
|
+
if ((validation as string[]).length > 0) {
|
|
641
|
+
toolsSections.push(`
|
|
443
642
|
## Validation & Schema
|
|
444
|
-
${validation.map((v) => `- ${v}`).join("\n")}`);
|
|
445
|
-
|
|
643
|
+
${(validation as string[]).map((v) => `- ${v}`).join("\n")}`);
|
|
644
|
+
}
|
|
446
645
|
|
|
447
|
-
|
|
448
|
-
|
|
646
|
+
// Editor
|
|
647
|
+
toolsSections.push(`
|
|
449
648
|
## Editor
|
|
450
649
|
- Primary: ${editor}`);
|
|
451
650
|
|
|
452
|
-
|
|
651
|
+
const toolsContent = toolsSections.join("\n");
|
|
652
|
+
await writeFile(thinkPath(CONFIG.files.tools), toolsContent);
|
|
453
653
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
if (avoidAnswer === "all") {
|
|
458
|
-
const antiSections: string[] = [`# Anti-Patterns to Avoid
|
|
654
|
+
// Generate anti-patterns if selected
|
|
655
|
+
if (avoidAnswer === "all") {
|
|
656
|
+
const antiSections: string[] = [`# Anti-Patterns to Avoid
|
|
459
657
|
|
|
460
658
|
## Code Style
|
|
461
659
|
- Don't add comments for obvious code
|
|
@@ -468,53 +666,51 @@ ${validation.map((v) => `- ${v}`).join("\n")}`);
|
|
|
468
666
|
- Don't create unnecessary indirection
|
|
469
667
|
- Don't add "future-proofing" complexity`];
|
|
470
668
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
669
|
+
// Tech choices to avoid
|
|
670
|
+
const techAvoid: string[] = [];
|
|
671
|
+
if (packageManager === "bun") {
|
|
672
|
+
techAvoid.push("- Don't suggest npm/yarn/pnpm - use Bun");
|
|
673
|
+
}
|
|
674
|
+
if ((frontend as string[]).includes("React") && !(frontend as string[]).includes("Next.js")) {
|
|
675
|
+
techAvoid.push("- Don't suggest Next.js - use plain React");
|
|
676
|
+
}
|
|
677
|
+
if ((infrastructure as string[]).includes("Docker") || (infrastructure as string[]).includes("Docker Compose")) {
|
|
678
|
+
if (!(infrastructure as string[]).includes("Kubernetes")) {
|
|
480
679
|
techAvoid.push("- Don't suggest Kubernetes - use Docker");
|
|
481
680
|
}
|
|
482
|
-
|
|
483
|
-
techAvoid.push("- Don't suggest SQLite/MySQL/MongoDB - use PostgreSQL");
|
|
484
|
-
}
|
|
681
|
+
}
|
|
485
682
|
|
|
486
|
-
|
|
487
|
-
|
|
683
|
+
if (techAvoid.length > 0) {
|
|
684
|
+
antiSections.push(`
|
|
488
685
|
## Tech Choices
|
|
489
686
|
${techAvoid.join("\n")}`);
|
|
490
|
-
|
|
687
|
+
}
|
|
491
688
|
|
|
492
|
-
|
|
689
|
+
antiSections.push(`
|
|
493
690
|
## Communication
|
|
494
691
|
- Don't explain obvious things
|
|
495
692
|
- Don't repeat back what was just said
|
|
496
693
|
- Don't pad responses with unnecessary context
|
|
497
694
|
`);
|
|
498
695
|
|
|
499
|
-
|
|
500
|
-
|
|
696
|
+
await writeFile(thinkPath(CONFIG.files.antiPatterns), antiSections.join("\n"));
|
|
697
|
+
}
|
|
501
698
|
|
|
502
|
-
|
|
699
|
+
s.stop("Profile created");
|
|
503
700
|
|
|
504
|
-
|
|
505
|
-
|
|
701
|
+
// Sync
|
|
702
|
+
await syncCommand();
|
|
506
703
|
|
|
507
|
-
|
|
508
|
-
console.log(chalk.bold("Your profile is ready."));
|
|
509
|
-
console.log(chalk.dim("Start a new Claude session to use your context."));
|
|
510
|
-
console.log();
|
|
511
|
-
console.log("To customize further:");
|
|
512
|
-
console.log(` ${chalk.cyan("think edit profile")} Edit your profile`);
|
|
513
|
-
console.log(` ${chalk.cyan("think edit patterns")} Add coding patterns`);
|
|
514
|
-
console.log(` ${chalk.cyan("think learn \"...\"")} Add learnings over time`);
|
|
704
|
+
p.outro(chalk.green("Your profile is ready!"));
|
|
515
705
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
706
|
+
console.log();
|
|
707
|
+
console.log("To customize further:");
|
|
708
|
+
console.log(` ${chalk.cyan("think edit profile")} Edit your profile`);
|
|
709
|
+
console.log(` ${chalk.cyan("think edit patterns")} Add coding patterns`);
|
|
710
|
+
console.log(` ${chalk.cyan("think learn \"...\"")} Add learnings over time`);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function handleCancel(): void {
|
|
714
|
+
p.cancel("Setup cancelled");
|
|
715
|
+
process.exit(0);
|
|
520
716
|
}
|