claude-think 0.1.2 → 0.1.4
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 +5 -1
- package/CHANGELOG.md +13 -0
- package/bun.lock +9 -0
- package/package.json +2 -1
- package/src/cli/commands/setup.ts +394 -419
- package/src/cli/index.ts +2 -1
|
@@ -19,7 +19,11 @@
|
|
|
19
19
|
"Bash(git commit -m \"$\\(cat <<''EOF''\nv0.1.1: Fix plugin registration\n\n- Use correct .claude-plugin/ directory structure\n- Auto-register plugin in Claude settings.json on sync\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
|
20
20
|
"Bash(bun src/cli/index.ts setup:*)",
|
|
21
21
|
"Bash(printf:*)",
|
|
22
|
-
"Bash(npm publish:*)"
|
|
22
|
+
"Bash(npm publish:*)",
|
|
23
|
+
"Bash(bun install:*)",
|
|
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\\)\")",
|
|
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\\)\")"
|
|
23
27
|
]
|
|
24
28
|
}
|
|
25
29
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ 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.4] - 2025-02-05
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Setup wizard now uses @clack/prompts for better UX
|
|
12
|
+
- Arrow key navigation and space to toggle checkboxes
|
|
13
|
+
- Multi-select for frontend, CSS, database, infrastructure (can pick multiple)
|
|
14
|
+
- Cleaner visual design with spinners and hints
|
|
15
|
+
|
|
16
|
+
## [0.1.3] - 2025-02-05
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- `--version` now reads from package.json instead of hardcoded value
|
|
20
|
+
|
|
8
21
|
## [0.1.2] - 2025-02-05
|
|
9
22
|
|
|
10
23
|
### Added
|
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.4",
|
|
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,289 +16,293 @@ 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
|
-
|
|
40
|
-
const rl = readline.createInterface({
|
|
41
|
-
input: process.stdin,
|
|
42
|
-
output: process.stdout,
|
|
43
|
-
});
|
|
44
19
|
|
|
45
|
-
|
|
46
|
-
return new Promise((resolve) => {
|
|
47
|
-
rl.question(prompt, resolve);
|
|
48
|
-
});
|
|
49
|
-
};
|
|
20
|
+
p.intro(chalk.bgCyan(chalk.black(" think setup ")));
|
|
50
21
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
+
const packageManager = await p.select({
|
|
39
|
+
message: "Preferred package manager?",
|
|
40
|
+
options: [
|
|
41
|
+
{ value: "bun", label: "Bun" },
|
|
42
|
+
{ value: "pnpm", label: "pnpm" },
|
|
43
|
+
{ value: "npm", label: "npm" },
|
|
44
|
+
{ value: "yarn", label: "yarn" },
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
if (p.isCancel(packageManager)) return handleCancel();
|
|
48
|
+
|
|
49
|
+
let bunFeatures: string[] = [];
|
|
50
|
+
if (packageManager === "bun") {
|
|
51
|
+
const features = await p.multiselect({
|
|
52
|
+
message: "Bun features you use?",
|
|
53
|
+
options: [
|
|
54
|
+
{ value: "catalog", label: "Dependency catalog" },
|
|
55
|
+
{ value: "workspaces", label: "Bun workspaces" },
|
|
56
|
+
{ value: "macros", label: "Bun macros" },
|
|
57
|
+
{ value: "shell", label: "Bun shell ($``)" },
|
|
58
|
+
{ value: "sqlite", label: "bun:sqlite" },
|
|
59
|
+
{ value: "test", label: "bun test" },
|
|
60
|
+
],
|
|
61
|
+
required: false,
|
|
58
62
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return options[idx].key;
|
|
63
|
-
}
|
|
64
|
-
return options[0].key;
|
|
65
|
-
};
|
|
63
|
+
if (p.isCancel(features)) return handleCancel();
|
|
64
|
+
bunFeatures = features as string[];
|
|
65
|
+
}
|
|
66
66
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
options:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
const languages = await p.multiselect({
|
|
68
|
+
message: "Primary programming languages?",
|
|
69
|
+
options: [
|
|
70
|
+
{ value: "TypeScript", label: "TypeScript" },
|
|
71
|
+
{ value: "JavaScript", label: "JavaScript" },
|
|
72
|
+
{ value: "Python", label: "Python" },
|
|
73
|
+
{ value: "Ruby", label: "Ruby" },
|
|
74
|
+
{ value: "Rust", label: "Rust" },
|
|
75
|
+
{ value: "Go", label: "Go" },
|
|
76
|
+
{ value: "Java", label: "Java" },
|
|
77
|
+
{ value: "C#", label: "C#" },
|
|
78
|
+
{ value: "PHP", label: "PHP" },
|
|
79
|
+
{ value: "Elixir", label: "Elixir" },
|
|
80
|
+
],
|
|
81
|
+
required: true,
|
|
82
|
+
});
|
|
83
|
+
if (p.isCancel(languages)) return handleCancel();
|
|
84
|
+
|
|
85
|
+
const backend = await p.select({
|
|
86
|
+
message: "Backend framework?",
|
|
87
|
+
options: [
|
|
88
|
+
{ value: "none", label: "None / Custom" },
|
|
89
|
+
{ value: "Rails", label: "Ruby on Rails" },
|
|
90
|
+
{ value: "Django", label: "Django" },
|
|
91
|
+
{ value: "FastAPI", label: "FastAPI" },
|
|
92
|
+
{ value: "Express", label: "Express.js" },
|
|
93
|
+
{ value: "Hono", label: "Hono" },
|
|
94
|
+
{ value: "Phoenix", label: "Phoenix (Elixir)" },
|
|
95
|
+
{ value: "Spring", label: "Spring Boot" },
|
|
96
|
+
{ value: "ASP.NET", label: "ASP.NET Core" },
|
|
97
|
+
{ value: "Laravel", label: "Laravel" },
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
if (p.isCancel(backend)) return handleCancel();
|
|
101
|
+
|
|
102
|
+
const frontend = await p.multiselect({
|
|
103
|
+
message: "Frontend frameworks?",
|
|
104
|
+
options: [
|
|
105
|
+
{ value: "React", label: "React" },
|
|
106
|
+
{ value: "Vue", label: "Vue.js" },
|
|
107
|
+
{ value: "Svelte", label: "Svelte" },
|
|
108
|
+
{ value: "Angular", label: "Angular" },
|
|
109
|
+
{ value: "Solid", label: "SolidJS" },
|
|
110
|
+
{ value: "HTMX", label: "HTMX" },
|
|
111
|
+
],
|
|
112
|
+
required: false,
|
|
113
|
+
});
|
|
114
|
+
if (p.isCancel(frontend)) return handleCancel();
|
|
115
|
+
|
|
116
|
+
const css = await p.multiselect({
|
|
117
|
+
message: "CSS / UI frameworks?",
|
|
118
|
+
options: [
|
|
119
|
+
{ value: "Tailwind", label: "Tailwind CSS" },
|
|
120
|
+
{ value: "Vuetify", label: "Vuetify" },
|
|
121
|
+
{ value: "Bootstrap", label: "Bootstrap" },
|
|
122
|
+
{ value: "Material UI", label: "Material UI" },
|
|
123
|
+
{ value: "shadcn/ui", label: "shadcn/ui" },
|
|
124
|
+
{ value: "CSS Modules", label: "CSS Modules" },
|
|
125
|
+
{ value: "styled-components", label: "styled-components" },
|
|
126
|
+
],
|
|
127
|
+
required: false,
|
|
128
|
+
});
|
|
129
|
+
if (p.isCancel(css)) return handleCancel();
|
|
130
|
+
|
|
131
|
+
const database = await p.multiselect({
|
|
132
|
+
message: "Databases?",
|
|
133
|
+
options: [
|
|
134
|
+
{ value: "PostgreSQL", label: "PostgreSQL" },
|
|
135
|
+
{ value: "MySQL", label: "MySQL" },
|
|
136
|
+
{ value: "MongoDB", label: "MongoDB" },
|
|
137
|
+
{ value: "SQLite", label: "SQLite" },
|
|
138
|
+
{ value: "Redis", label: "Redis" },
|
|
139
|
+
{ value: "Supabase", label: "Supabase" },
|
|
140
|
+
{ value: "Firebase", label: "Firebase" },
|
|
141
|
+
],
|
|
142
|
+
required: false,
|
|
143
|
+
});
|
|
144
|
+
if (p.isCancel(database)) return handleCancel();
|
|
145
|
+
|
|
146
|
+
const orm = await p.multiselect({
|
|
147
|
+
message: "ORM / database tools?",
|
|
148
|
+
options: [
|
|
149
|
+
{ value: "Prisma", label: "Prisma" },
|
|
150
|
+
{ value: "Drizzle", label: "Drizzle" },
|
|
151
|
+
{ value: "TypeORM", label: "TypeORM" },
|
|
152
|
+
{ value: "Kysely", label: "Kysely" },
|
|
153
|
+
{ value: "Sequelize", label: "Sequelize" },
|
|
154
|
+
{ value: "Mongoose", label: "Mongoose" },
|
|
155
|
+
{ value: "ActiveRecord", label: "ActiveRecord (Rails)" },
|
|
156
|
+
{ value: "SQLAlchemy", label: "SQLAlchemy" },
|
|
157
|
+
{ value: "Django ORM", label: "Django ORM" },
|
|
158
|
+
],
|
|
159
|
+
required: false,
|
|
160
|
+
});
|
|
161
|
+
if (p.isCancel(orm)) return handleCancel();
|
|
162
|
+
|
|
163
|
+
const auth = await p.multiselect({
|
|
164
|
+
message: "Authentication?",
|
|
165
|
+
options: [
|
|
166
|
+
{ value: "better-auth", label: "better-auth" },
|
|
167
|
+
{ value: "Auth.js", label: "Auth.js (NextAuth)" },
|
|
168
|
+
{ value: "Lucia", label: "Lucia" },
|
|
169
|
+
{ value: "Clerk", label: "Clerk" },
|
|
170
|
+
{ value: "Supabase Auth", label: "Supabase Auth" },
|
|
171
|
+
{ value: "Firebase Auth", label: "Firebase Auth" },
|
|
172
|
+
{ value: "Passport.js", label: "Passport.js" },
|
|
173
|
+
{ value: "Devise", label: "Devise (Rails)" },
|
|
174
|
+
],
|
|
175
|
+
required: false,
|
|
176
|
+
});
|
|
177
|
+
if (p.isCancel(auth)) return handleCancel();
|
|
178
|
+
|
|
179
|
+
const infrastructure = await p.multiselect({
|
|
180
|
+
message: "Infrastructure / deployment?",
|
|
181
|
+
options: [
|
|
182
|
+
{ value: "Docker Compose", label: "Docker + Compose" },
|
|
183
|
+
{ value: "Docker", label: "Docker only" },
|
|
184
|
+
{ value: "Kubernetes", label: "Kubernetes" },
|
|
185
|
+
{ value: "Fly.io", label: "Fly.io" },
|
|
186
|
+
{ value: "Vercel", label: "Vercel" },
|
|
187
|
+
{ value: "Railway", label: "Railway" },
|
|
188
|
+
{ value: "Render", label: "Render" },
|
|
189
|
+
],
|
|
190
|
+
required: false,
|
|
191
|
+
});
|
|
192
|
+
if (p.isCancel(infrastructure)) return handleCancel();
|
|
193
|
+
|
|
194
|
+
const monorepo = await p.select({
|
|
195
|
+
message: "Monorepo tooling?",
|
|
196
|
+
options: [
|
|
197
|
+
{ value: "none", label: "None / Single repo" },
|
|
198
|
+
{ value: "Turborepo", label: "Turborepo" },
|
|
199
|
+
{ value: "Bun workspaces", label: "Bun workspaces" },
|
|
200
|
+
{ value: "Nx", label: "Nx" },
|
|
201
|
+
{ value: "pnpm workspaces", label: "pnpm workspaces" },
|
|
202
|
+
{ value: "Lerna", label: "Lerna" },
|
|
203
|
+
],
|
|
204
|
+
});
|
|
205
|
+
if (p.isCancel(monorepo)) return handleCancel();
|
|
206
|
+
|
|
207
|
+
const testing = await p.multiselect({
|
|
208
|
+
message: "Testing frameworks?",
|
|
209
|
+
options: [
|
|
210
|
+
{ value: "bun test", label: "bun test" },
|
|
211
|
+
{ value: "Vitest", label: "Vitest" },
|
|
212
|
+
{ value: "Jest", label: "Jest" },
|
|
213
|
+
{ value: "RSpec", label: "RSpec" },
|
|
214
|
+
{ value: "pytest", label: "pytest" },
|
|
215
|
+
{ value: "Playwright", label: "Playwright (E2E)" },
|
|
216
|
+
{ value: "Cypress", label: "Cypress (E2E)" },
|
|
217
|
+
],
|
|
218
|
+
required: false,
|
|
219
|
+
});
|
|
220
|
+
if (p.isCancel(testing)) return handleCancel();
|
|
221
|
+
|
|
222
|
+
const linting = await p.multiselect({
|
|
223
|
+
message: "Linting & formatting?",
|
|
224
|
+
options: [
|
|
225
|
+
{ value: "Biome", label: "Biome" },
|
|
226
|
+
{ value: "ESLint", label: "ESLint" },
|
|
227
|
+
{ value: "Prettier", label: "Prettier" },
|
|
228
|
+
{ value: "oxlint", label: "oxlint" },
|
|
229
|
+
{ value: "Rubocop", label: "Rubocop" },
|
|
230
|
+
{ value: "Ruff", label: "Ruff (Python)" },
|
|
231
|
+
{ value: "rustfmt", label: "rustfmt" },
|
|
232
|
+
{ value: "gofmt", label: "gofmt" },
|
|
233
|
+
],
|
|
234
|
+
required: false,
|
|
235
|
+
});
|
|
236
|
+
if (p.isCancel(linting)) return handleCancel();
|
|
237
|
+
|
|
238
|
+
const validation = await p.multiselect({
|
|
239
|
+
message: "Validation & schema libraries?",
|
|
240
|
+
options: [
|
|
241
|
+
{ value: "Zod", label: "Zod" },
|
|
242
|
+
{ value: "Yup", label: "Yup" },
|
|
243
|
+
{ value: "Valibot", label: "Valibot" },
|
|
244
|
+
{ value: "ArkType", label: "ArkType" },
|
|
245
|
+
{ value: "io-ts", label: "io-ts" },
|
|
246
|
+
{ value: "TypeBox", label: "TypeBox" },
|
|
247
|
+
{ value: "Pydantic", label: "Pydantic" },
|
|
248
|
+
{ value: "Joi", label: "Joi" },
|
|
249
|
+
],
|
|
250
|
+
required: false,
|
|
251
|
+
});
|
|
252
|
+
if (p.isCancel(validation)) return handleCancel();
|
|
253
|
+
|
|
254
|
+
const editor = await p.select({
|
|
255
|
+
message: "Primary editor?",
|
|
256
|
+
options: [
|
|
257
|
+
{ value: "Zed", label: "Zed" },
|
|
258
|
+
{ value: "VS Code", label: "VS Code" },
|
|
259
|
+
{ value: "Cursor", label: "Cursor" },
|
|
260
|
+
{ value: "Neovim", label: "Neovim" },
|
|
261
|
+
{ value: "WebStorm", label: "WebStorm" },
|
|
262
|
+
],
|
|
263
|
+
});
|
|
264
|
+
if (p.isCancel(editor)) return handleCancel();
|
|
265
|
+
|
|
266
|
+
const avoidAnswer = await p.select({
|
|
267
|
+
message: "What should Claude avoid?",
|
|
268
|
+
options: [
|
|
269
|
+
{ value: "all", label: "All", hint: "over-engineering, verbose explanations, extra features" },
|
|
270
|
+
{ value: "some", label: "Just over-engineering" },
|
|
271
|
+
{ value: "none", label: "No specific restrictions" },
|
|
272
|
+
],
|
|
273
|
+
});
|
|
274
|
+
if (p.isCancel(avoidAnswer)) return handleCancel();
|
|
275
|
+
|
|
276
|
+
const s = p.spinner();
|
|
277
|
+
s.start("Generating profile");
|
|
278
|
+
|
|
279
|
+
// Generate profile
|
|
280
|
+
const styleDescriptions: Record<string, string[]> = {
|
|
281
|
+
direct: [
|
|
282
|
+
"Be direct and minimal - no fluff, just answers and code",
|
|
283
|
+
"Skip lengthy reasoning unless asked",
|
|
284
|
+
"Don't explain obvious things",
|
|
285
|
+
],
|
|
286
|
+
conversational: [
|
|
287
|
+
"Be friendly but efficient",
|
|
288
|
+
"Brief explanations when helpful",
|
|
289
|
+
"Keep a conversational tone",
|
|
290
|
+
],
|
|
291
|
+
detailed: [
|
|
292
|
+
"Provide thorough explanations",
|
|
293
|
+
"Include context and reasoning",
|
|
294
|
+
"Explain trade-offs and alternatives",
|
|
295
|
+
],
|
|
80
296
|
};
|
|
81
297
|
|
|
82
|
-
|
|
83
|
-
// Name
|
|
84
|
-
const name = await question(chalk.cyan("What's your name? "));
|
|
85
|
-
console.log();
|
|
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
|
-
}
|
|
117
|
-
|
|
118
|
-
// Languages
|
|
119
|
-
const languages = await multiSelect("Primary programming languages?", [
|
|
120
|
-
{ key: "TypeScript", label: "TypeScript" },
|
|
121
|
-
{ key: "JavaScript", label: "JavaScript" },
|
|
122
|
-
{ key: "Python", label: "Python" },
|
|
123
|
-
{ key: "Ruby", label: "Ruby" },
|
|
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
|
-
};
|
|
311
|
-
|
|
312
|
-
const profileContent = `---
|
|
298
|
+
const profileContent = `---
|
|
313
299
|
name: ${name}
|
|
314
300
|
style: ${style}
|
|
315
301
|
---
|
|
316
302
|
|
|
317
303
|
# Communication Preferences
|
|
318
304
|
|
|
319
|
-
${styleDescriptions[style].map((s) => `- ${s}`).join("\n")}
|
|
305
|
+
${styleDescriptions[style as string].map((s) => `- ${s}`).join("\n")}
|
|
320
306
|
- No emojis unless explicitly requested
|
|
321
307
|
- Show code when it's clearer than explanation
|
|
322
308
|
|
|
@@ -326,136 +312,127 @@ ${styleDescriptions[style].map((s) => `- ${s}`).join("\n")}
|
|
|
326
312
|
- Match existing code patterns in the project
|
|
327
313
|
`;
|
|
328
314
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
315
|
+
await writeFile(thinkPath(CONFIG.files.profile), profileContent);
|
|
316
|
+
|
|
317
|
+
// Generate tools preferences
|
|
318
|
+
const toolsSections: string[] = ["# Tool Preferences"];
|
|
319
|
+
|
|
320
|
+
// Runtime & Package Manager
|
|
321
|
+
const pmAlternatives = ["npm", "pnpm", "yarn", "Node.js"].filter(
|
|
322
|
+
(pm) => pm.toLowerCase() !== (packageManager as string).toLowerCase()
|
|
323
|
+
);
|
|
324
|
+
const pmSection = [`- Use ${packageManager === "bun" ? "Bun" : packageManager}${pmAlternatives.length ? ` (not ${pmAlternatives.join(", ")})` : ""}`];
|
|
325
|
+
|
|
326
|
+
if (bunFeatures.length > 0) {
|
|
327
|
+
if (bunFeatures.includes("catalog")) pmSection.push("- Use Bun dependency catalog for shared deps");
|
|
328
|
+
if (bunFeatures.includes("workspaces")) pmSection.push("- Use Bun workspaces for monorepos");
|
|
329
|
+
if (bunFeatures.includes("macros")) pmSection.push("- Use Bun macros for compile-time code");
|
|
330
|
+
if (bunFeatures.includes("shell")) pmSection.push("- Use Bun shell ($``) for shell commands");
|
|
331
|
+
if (bunFeatures.includes("sqlite")) pmSection.push("- Use bun:sqlite for embedded database");
|
|
332
|
+
if (bunFeatures.includes("test")) pmSection.push("- Use `bun test` for testing");
|
|
333
|
+
} else {
|
|
334
|
+
pmSection.push(`- Use \`${packageManager} test\` for testing`);
|
|
335
|
+
}
|
|
350
336
|
|
|
351
|
-
|
|
337
|
+
toolsSections.push(`
|
|
352
338
|
## Runtime & Package Manager
|
|
353
339
|
${pmSection.join("\n")}`);
|
|
354
340
|
|
|
355
|
-
|
|
356
|
-
|
|
341
|
+
// Languages
|
|
342
|
+
toolsSections.push(`
|
|
357
343
|
## Languages
|
|
358
|
-
${languages.map((l) => `- ${l}`).join("\n")}`);
|
|
344
|
+
${(languages as string[]).map((l) => `- ${l}`).join("\n")}`);
|
|
359
345
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
346
|
+
// Backend
|
|
347
|
+
if (backend !== "none") {
|
|
348
|
+
toolsSections.push(`
|
|
363
349
|
## Backend
|
|
364
350
|
- ${backend}`);
|
|
365
|
-
|
|
351
|
+
}
|
|
366
352
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
(f) => f.toLowerCase() !== frontend.toLowerCase()
|
|
371
|
-
);
|
|
372
|
-
toolsSections.push(`
|
|
353
|
+
// Frontend
|
|
354
|
+
if ((frontend as string[]).length > 0) {
|
|
355
|
+
toolsSections.push(`
|
|
373
356
|
## Frontend
|
|
374
|
-
|
|
357
|
+
${(frontend as string[]).map((f) => `- ${f}`).join("\n")}
|
|
375
358
|
- Prefer functional components with hooks`);
|
|
359
|
+
}
|
|
376
360
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
361
|
+
// CSS
|
|
362
|
+
if ((css as string[]).length > 0) {
|
|
363
|
+
toolsSections.push(`
|
|
364
|
+
## CSS / UI
|
|
365
|
+
${(css as string[]).map((c) => `- ${c}`).join("\n")}`);
|
|
366
|
+
}
|
|
382
367
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
(d) => d.toLowerCase() !== database.toLowerCase()
|
|
387
|
-
);
|
|
388
|
-
toolsSections.push(`
|
|
368
|
+
// Database
|
|
369
|
+
if ((database as string[]).length > 0) {
|
|
370
|
+
toolsSections.push(`
|
|
389
371
|
## Database
|
|
390
|
-
|
|
391
|
-
|
|
372
|
+
${(database as string[]).map((d) => `- ${d}`).join("\n")}`);
|
|
373
|
+
}
|
|
392
374
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
375
|
+
// ORM
|
|
376
|
+
if ((orm as string[]).length > 0) {
|
|
377
|
+
toolsSections.push(`
|
|
396
378
|
## ORM / Database Tools
|
|
397
|
-
${orm.map((o) => `- ${o}`).join("\n")}`);
|
|
398
|
-
|
|
379
|
+
${(orm as string[]).map((o) => `- ${o}`).join("\n")}`);
|
|
380
|
+
}
|
|
399
381
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
382
|
+
// Auth
|
|
383
|
+
if ((auth as string[]).length > 0) {
|
|
384
|
+
toolsSections.push(`
|
|
403
385
|
## Authentication
|
|
404
|
-
${auth.map((a) => `- ${a}`).join("\n")}`);
|
|
405
|
-
|
|
386
|
+
${(auth as string[]).map((a) => `- ${a}`).join("\n")}`);
|
|
387
|
+
}
|
|
406
388
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
? []
|
|
411
|
-
: ["Kubernetes"];
|
|
412
|
-
toolsSections.push(`
|
|
389
|
+
// Infrastructure
|
|
390
|
+
if ((infrastructure as string[]).length > 0) {
|
|
391
|
+
toolsSections.push(`
|
|
413
392
|
## Infrastructure
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
393
|
+
${(infrastructure as string[]).map((i) => `- ${i}`).join("\n")}`);
|
|
394
|
+
}
|
|
417
395
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
396
|
+
// Monorepo
|
|
397
|
+
if (monorepo !== "none") {
|
|
398
|
+
toolsSections.push(`
|
|
421
399
|
## Monorepo
|
|
422
400
|
- ${monorepo}`);
|
|
423
|
-
|
|
401
|
+
}
|
|
424
402
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
403
|
+
// Testing
|
|
404
|
+
if ((testing as string[]).length > 0) {
|
|
405
|
+
toolsSections.push(`
|
|
428
406
|
## Testing
|
|
429
|
-
${testing.map((t) => `- ${t}`).join("\n")}`);
|
|
430
|
-
|
|
407
|
+
${(testing as string[]).map((t) => `- ${t}`).join("\n")}`);
|
|
408
|
+
}
|
|
431
409
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
410
|
+
// Linting & Formatting
|
|
411
|
+
if ((linting as string[]).length > 0) {
|
|
412
|
+
toolsSections.push(`
|
|
435
413
|
## Linting & Formatting
|
|
436
|
-
${linting.map((l) => `- ${l}`).join("\n")}
|
|
414
|
+
${(linting as string[]).map((l) => `- ${l}`).join("\n")}
|
|
437
415
|
- Use project's existing config when present`);
|
|
438
|
-
|
|
416
|
+
}
|
|
439
417
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
418
|
+
// Validation
|
|
419
|
+
if ((validation as string[]).length > 0) {
|
|
420
|
+
toolsSections.push(`
|
|
443
421
|
## Validation & Schema
|
|
444
|
-
${validation.map((v) => `- ${v}`).join("\n")}`);
|
|
445
|
-
|
|
422
|
+
${(validation as string[]).map((v) => `- ${v}`).join("\n")}`);
|
|
423
|
+
}
|
|
446
424
|
|
|
447
|
-
|
|
448
|
-
|
|
425
|
+
// Editor
|
|
426
|
+
toolsSections.push(`
|
|
449
427
|
## Editor
|
|
450
428
|
- Primary: ${editor}`);
|
|
451
429
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
await writeFile(thinkPath(CONFIG.files.tools), toolsContent);
|
|
430
|
+
const toolsContent = toolsSections.join("\n");
|
|
431
|
+
await writeFile(thinkPath(CONFIG.files.tools), toolsContent);
|
|
455
432
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
433
|
+
// Generate anti-patterns if selected
|
|
434
|
+
if (avoidAnswer === "all") {
|
|
435
|
+
const antiSections: string[] = [`# Anti-Patterns to Avoid
|
|
459
436
|
|
|
460
437
|
## Code Style
|
|
461
438
|
- Don't add comments for obvious code
|
|
@@ -468,53 +445,51 @@ ${validation.map((v) => `- ${v}`).join("\n")}`);
|
|
|
468
445
|
- Don't create unnecessary indirection
|
|
469
446
|
- Don't add "future-proofing" complexity`];
|
|
470
447
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
448
|
+
// Tech choices to avoid
|
|
449
|
+
const techAvoid: string[] = [];
|
|
450
|
+
if (packageManager === "bun") {
|
|
451
|
+
techAvoid.push("- Don't suggest npm/yarn/pnpm - use Bun");
|
|
452
|
+
}
|
|
453
|
+
if ((frontend as string[]).includes("React") && !(frontend as string[]).includes("Next.js")) {
|
|
454
|
+
techAvoid.push("- Don't suggest Next.js - use plain React");
|
|
455
|
+
}
|
|
456
|
+
if ((infrastructure as string[]).includes("Docker") || (infrastructure as string[]).includes("Docker Compose")) {
|
|
457
|
+
if (!(infrastructure as string[]).includes("Kubernetes")) {
|
|
480
458
|
techAvoid.push("- Don't suggest Kubernetes - use Docker");
|
|
481
459
|
}
|
|
482
|
-
|
|
483
|
-
techAvoid.push("- Don't suggest SQLite/MySQL/MongoDB - use PostgreSQL");
|
|
484
|
-
}
|
|
460
|
+
}
|
|
485
461
|
|
|
486
|
-
|
|
487
|
-
|
|
462
|
+
if (techAvoid.length > 0) {
|
|
463
|
+
antiSections.push(`
|
|
488
464
|
## Tech Choices
|
|
489
465
|
${techAvoid.join("\n")}`);
|
|
490
|
-
|
|
466
|
+
}
|
|
491
467
|
|
|
492
|
-
|
|
468
|
+
antiSections.push(`
|
|
493
469
|
## Communication
|
|
494
470
|
- Don't explain obvious things
|
|
495
471
|
- Don't repeat back what was just said
|
|
496
472
|
- Don't pad responses with unnecessary context
|
|
497
473
|
`);
|
|
498
474
|
|
|
499
|
-
|
|
500
|
-
|
|
475
|
+
await writeFile(thinkPath(CONFIG.files.antiPatterns), antiSections.join("\n"));
|
|
476
|
+
}
|
|
501
477
|
|
|
502
|
-
|
|
478
|
+
s.stop("Profile created");
|
|
503
479
|
|
|
504
|
-
|
|
505
|
-
|
|
480
|
+
// Sync
|
|
481
|
+
await syncCommand();
|
|
506
482
|
|
|
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`);
|
|
483
|
+
p.outro(chalk.green("Your profile is ready!"));
|
|
515
484
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
485
|
+
console.log();
|
|
486
|
+
console.log("To customize further:");
|
|
487
|
+
console.log(` ${chalk.cyan("think edit profile")} Edit your profile`);
|
|
488
|
+
console.log(` ${chalk.cyan("think edit patterns")} Add coding patterns`);
|
|
489
|
+
console.log(` ${chalk.cyan("think learn \"...\"")} Add learnings over time`);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function handleCancel(): void {
|
|
493
|
+
p.cancel("Setup cancelled");
|
|
494
|
+
process.exit(0);
|
|
520
495
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -14,13 +14,14 @@ import { helpCommand } from "./commands/help";
|
|
|
14
14
|
import { setupCommand } from "./commands/setup";
|
|
15
15
|
import { printBanner } from "../core/banner";
|
|
16
16
|
import { launchTui } from "../tui";
|
|
17
|
+
import pkg from "../../package.json";
|
|
17
18
|
|
|
18
19
|
const program = new Command();
|
|
19
20
|
|
|
20
21
|
program
|
|
21
22
|
.name("think")
|
|
22
23
|
.description("Personal context manager for Claude")
|
|
23
|
-
.version(
|
|
24
|
+
.version(pkg.version);
|
|
24
25
|
|
|
25
26
|
// Initialize ~/.think
|
|
26
27
|
program
|