cc-starter 1.0.2 → 1.0.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/bin/cc-starter.js +11 -8
- package/lib/constants.js +103 -0
- package/lib/plugins.js +14 -10
- package/lib/scaffold.js +41 -29
- package/lib/wizard.js +36 -12
- package/package.json +1 -1
- package/template/CLAUDE.md.de.hbs +48 -0
- package/template/CLAUDE.md.en.hbs +48 -0
- package/template/claude/rules/de/01-general.md +36 -0
- package/template/claude/rules/de/02-code-standards.md +23 -0
- package/template/claude/rules/de/03-dev-ops.md +20 -0
- package/template/claude/rules/de/04-token-efficiency.md +45 -0
- package/template/claude/rules/en/01-general.md +36 -0
- package/template/claude/rules/en/02-code-standards.md +23 -0
- package/template/claude/rules/en/03-dev-ops.md +20 -0
- package/template/claude/rules/en/04-token-efficiency.md +45 -0
package/bin/cc-starter.js
CHANGED
|
@@ -5,6 +5,7 @@ import { detect } from '../lib/detect.js';
|
|
|
5
5
|
import { wizard } from '../lib/wizard.js';
|
|
6
6
|
import { scaffold } from '../lib/scaffold.js';
|
|
7
7
|
import { installPlugins } from '../lib/plugins.js';
|
|
8
|
+
import { I18N } from '../lib/constants.js';
|
|
8
9
|
|
|
9
10
|
async function main() {
|
|
10
11
|
// 1. Banner
|
|
@@ -26,25 +27,27 @@ async function main() {
|
|
|
26
27
|
console.log(chalk.dim(' No specific tech stack detected (empty or new project)\n'));
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
// 3. Interactive wizard
|
|
30
|
+
// 3. Interactive wizard (language selection happens first inside wizard)
|
|
30
31
|
const config = await wizard(techStack);
|
|
32
|
+
const lang = config.lang || 'en';
|
|
33
|
+
const t = I18N[lang];
|
|
31
34
|
|
|
32
35
|
// 4. Scaffold files
|
|
33
|
-
console.log(chalk.cyan(
|
|
36
|
+
console.log(chalk.cyan(`\n ${t.scaffold.scaffolding}\n`));
|
|
34
37
|
const result = await scaffold(config);
|
|
35
38
|
|
|
36
39
|
// 5. Install plugins
|
|
37
|
-
await installPlugins(config.plugins);
|
|
40
|
+
await installPlugins(config.plugins, lang);
|
|
38
41
|
|
|
39
42
|
// 6. Summary
|
|
40
43
|
console.log(chalk.green.bold(`
|
|
41
44
|
══════════════════════════════════════════
|
|
42
|
-
|
|
45
|
+
${t.summary.done}
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
node scripts/stats/cocomo.js →
|
|
46
|
-
node scripts/stats/vibe-code.js help →
|
|
47
|
-
node scripts/stats/project-report.js →
|
|
47
|
+
${t.summary.quickCommands}
|
|
48
|
+
node scripts/stats/cocomo.js → ${t.summary.costEstimate}
|
|
49
|
+
node scripts/stats/vibe-code.js help → ${t.summary.tokenTools}
|
|
50
|
+
node scripts/stats/project-report.js → ${t.summary.htmlStats}
|
|
48
51
|
══════════════════════════════════════════
|
|
49
52
|
`));
|
|
50
53
|
}
|
package/lib/constants.js
CHANGED
|
@@ -30,3 +30,106 @@ export const REPORT_STYLES = {
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
export const DEFAULT_HOURLY_RATE = 80;
|
|
33
|
+
|
|
34
|
+
export const I18N = {
|
|
35
|
+
de: {
|
|
36
|
+
wizard: {
|
|
37
|
+
title: 'cc-starter — Projekt-Kickstart Assistent',
|
|
38
|
+
langQuestion: 'Sprache / Language:',
|
|
39
|
+
projectName: 'Projektname:',
|
|
40
|
+
projectDescription: 'Kurze Projektbeschreibung (was baust du?):',
|
|
41
|
+
hourlyRate: 'Stundensatz für COCOMO-Schätzung (€):',
|
|
42
|
+
reportStyle: 'Report-Stil:',
|
|
43
|
+
pluginPreset: 'Plugin-Auswahl:',
|
|
44
|
+
selectPlugins: 'Plugins auswählen:',
|
|
45
|
+
detectedStack: 'Erkannter Tech-Stack: ',
|
|
46
|
+
custom: 'Individuell — einzelne Plugins wählen'
|
|
47
|
+
},
|
|
48
|
+
scaffold: {
|
|
49
|
+
scaffolding: 'Projekt wird eingerichtet...',
|
|
50
|
+
existingClaude: 'Vorhandenes .claude/ gefunden. Was soll passieren?',
|
|
51
|
+
overwrite: 'Überschreiben — alle Dateien ersetzen',
|
|
52
|
+
merge: 'Zusammenführen — bestehende behalten, fehlende ergänzen',
|
|
53
|
+
skip: 'Überspringen — .claude/ nicht ändern',
|
|
54
|
+
existingClaudeMd: 'Vorhandene CLAUDE.md gefunden. Was soll passieren?',
|
|
55
|
+
overwriteMd: 'Überschreiben — durch cc-starter Version ersetzen',
|
|
56
|
+
appendMd: 'Anhängen — cc-starter Abschnitt am Ende einfügen',
|
|
57
|
+
skipMd: 'Überspringen — CLAUDE.md nicht ändern',
|
|
58
|
+
created: 'erstellt',
|
|
59
|
+
skipped: 'übersprungen',
|
|
60
|
+
appended: 'angehängt',
|
|
61
|
+
updated: 'aktualisiert',
|
|
62
|
+
alreadyUpToDate: 'bereits aktuell',
|
|
63
|
+
done: 'Fertig!',
|
|
64
|
+
files: 'Dateien'
|
|
65
|
+
},
|
|
66
|
+
plugins: {
|
|
67
|
+
installing: 'Plugins werden installiert...',
|
|
68
|
+
noPlugins: 'Keine Plugins ausgewählt.',
|
|
69
|
+
cliNotFound: 'Claude Code CLI nicht gefunden. Plugin-Installation übersprungen.',
|
|
70
|
+
installFirst: 'Installiere zuerst Claude Code: https://claude.ai/download',
|
|
71
|
+
manualInstall: 'Dann installiere Plugins manuell:',
|
|
72
|
+
installed: 'installiert',
|
|
73
|
+
manualNeeded: 'manuelle Installation nötig:',
|
|
74
|
+
pluginsInstalled: 'Plugin(s) installiert',
|
|
75
|
+
pluginsManual: 'Plugin(s) brauchen manuelle Installation'
|
|
76
|
+
},
|
|
77
|
+
summary: {
|
|
78
|
+
done: "Fertig! Starte mit 'claude' zum Coden.",
|
|
79
|
+
quickCommands: 'Schnellbefehle:',
|
|
80
|
+
costEstimate: 'Projekt-Kostenschätzung',
|
|
81
|
+
tokenTools: 'Token-sparende Tools',
|
|
82
|
+
htmlStats: 'HTML-Statistiken'
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
en: {
|
|
86
|
+
wizard: {
|
|
87
|
+
title: 'cc-starter — project kickstart wizard',
|
|
88
|
+
langQuestion: 'Sprache / Language:',
|
|
89
|
+
projectName: 'Project name:',
|
|
90
|
+
projectDescription: 'Short project description (what are you building?):',
|
|
91
|
+
hourlyRate: 'Hourly rate for COCOMO estimation (€):',
|
|
92
|
+
reportStyle: 'Report style:',
|
|
93
|
+
pluginPreset: 'Plugin preset:',
|
|
94
|
+
selectPlugins: 'Select plugins:',
|
|
95
|
+
detectedStack: 'Detected tech stack: ',
|
|
96
|
+
custom: 'Custom — pick individual plugins'
|
|
97
|
+
},
|
|
98
|
+
scaffold: {
|
|
99
|
+
scaffolding: 'Scaffolding project...',
|
|
100
|
+
existingClaude: 'Existing .claude/ found. What should we do?',
|
|
101
|
+
overwrite: 'Overwrite — replace all files',
|
|
102
|
+
merge: 'Merge — keep existing, add missing files only',
|
|
103
|
+
skip: 'Skip — leave .claude/ untouched',
|
|
104
|
+
existingClaudeMd: 'Existing CLAUDE.md found. What should we do?',
|
|
105
|
+
overwriteMd: 'Overwrite — replace with cc-starter version',
|
|
106
|
+
appendMd: 'Append — add cc-starter section at the end',
|
|
107
|
+
skipMd: 'Skip — leave CLAUDE.md untouched',
|
|
108
|
+
created: 'created',
|
|
109
|
+
skipped: 'skipped',
|
|
110
|
+
appended: 'appended',
|
|
111
|
+
updated: 'updated',
|
|
112
|
+
alreadyUpToDate: 'already up to date',
|
|
113
|
+
done: 'Done!',
|
|
114
|
+
files: 'files'
|
|
115
|
+
},
|
|
116
|
+
plugins: {
|
|
117
|
+
installing: 'Installing plugins...',
|
|
118
|
+
noPlugins: 'No plugins selected.',
|
|
119
|
+
cliNotFound: 'Claude Code CLI not found. Skipping plugin installation.',
|
|
120
|
+
installFirst: 'Install Claude Code first: https://claude.ai/download',
|
|
121
|
+
manualInstall: 'Then install plugins manually:',
|
|
122
|
+
installed: 'installed',
|
|
123
|
+
manualNeeded: 'manual install needed:',
|
|
124
|
+
pluginsInstalled: 'plugin(s) installed',
|
|
125
|
+
pluginsManual: 'plugin(s) need manual installation'
|
|
126
|
+
},
|
|
127
|
+
summary: {
|
|
128
|
+
done: "Done! Run 'claude' to start coding.",
|
|
129
|
+
quickCommands: 'Quick commands:',
|
|
130
|
+
costEstimate: 'Project cost estimate',
|
|
131
|
+
tokenTools: 'Token-saving tools',
|
|
132
|
+
htmlStats: 'HTML statistics'
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
package/lib/plugins.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
+
import { I18N } from './constants.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Check whether the `claude` CLI is available on this machine.
|
|
@@ -23,19 +24,22 @@ function isClaudeAvailable() {
|
|
|
23
24
|
* to manual instructions on failure.
|
|
24
25
|
*
|
|
25
26
|
* @param {Array<{ name: string, source: string }>} plugins
|
|
27
|
+
* @param {string} [lang='en'] - Language code ('de' or 'en')
|
|
26
28
|
*/
|
|
27
|
-
export async function installPlugins(plugins) {
|
|
29
|
+
export async function installPlugins(plugins, lang = 'en') {
|
|
30
|
+
const t = I18N[lang];
|
|
31
|
+
|
|
28
32
|
if (!plugins || plugins.length === 0) {
|
|
29
|
-
console.log(chalk.dim(
|
|
33
|
+
console.log(chalk.dim(` ${t.plugins.noPlugins}`));
|
|
30
34
|
return;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
// ── Pre-flight: is the CLI installed? ─────────────────────────────
|
|
34
38
|
|
|
35
39
|
if (!isClaudeAvailable()) {
|
|
36
|
-
console.log(chalk.yellow(
|
|
37
|
-
console.log(chalk.dim(
|
|
38
|
-
console.log(chalk.dim(
|
|
40
|
+
console.log(chalk.yellow(`\n ⚠ ${t.plugins.cliNotFound}`));
|
|
41
|
+
console.log(chalk.dim(` ${t.plugins.installFirst}`));
|
|
42
|
+
console.log(chalk.dim(` ${t.plugins.manualInstall}\n`));
|
|
39
43
|
for (const p of plugins) {
|
|
40
44
|
console.log(chalk.dim(` claude plugin install ${p.name}@${p.source}`));
|
|
41
45
|
}
|
|
@@ -44,7 +48,7 @@ export async function installPlugins(plugins) {
|
|
|
44
48
|
|
|
45
49
|
// ── Install each plugin ───────────────────────────────────────────
|
|
46
50
|
|
|
47
|
-
console.log(chalk.cyan(
|
|
51
|
+
console.log(chalk.cyan(`\n ${t.plugins.installing}\n`));
|
|
48
52
|
|
|
49
53
|
// Show what will be installed
|
|
50
54
|
for (const p of plugins) {
|
|
@@ -63,10 +67,10 @@ export async function installPlugins(plugins) {
|
|
|
63
67
|
stdio: 'inherit',
|
|
64
68
|
timeout: 30000,
|
|
65
69
|
});
|
|
66
|
-
console.log(chalk.green(` ✓ ${plugin.name}`));
|
|
70
|
+
console.log(chalk.green(` ✓ ${plugin.name}`) + chalk.dim(` — ${t.plugins.installed}`));
|
|
67
71
|
installed++;
|
|
68
72
|
} catch {
|
|
69
|
-
console.log(chalk.yellow(` ⚠ ${plugin.name} —
|
|
73
|
+
console.log(chalk.yellow(` ⚠ ${plugin.name} — ${t.plugins.manualNeeded}`));
|
|
70
74
|
console.log(chalk.dim(` claude plugin install ${ref}`));
|
|
71
75
|
failed++;
|
|
72
76
|
}
|
|
@@ -75,6 +79,6 @@ export async function installPlugins(plugins) {
|
|
|
75
79
|
// ── Summary ───────────────────────────────────────────────────────
|
|
76
80
|
|
|
77
81
|
console.log('');
|
|
78
|
-
if (installed > 0) console.log(chalk.green(` ${installed}
|
|
79
|
-
if (failed > 0) console.log(chalk.yellow(` ${failed}
|
|
82
|
+
if (installed > 0) console.log(chalk.green(` ${installed} ${t.plugins.pluginsInstalled}`));
|
|
83
|
+
if (failed > 0) console.log(chalk.yellow(` ${failed} ${t.plugins.pluginsManual}`));
|
|
80
84
|
}
|
package/lib/scaffold.js
CHANGED
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
import Handlebars from 'handlebars';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
+
import { I18N } from './constants.js';
|
|
7
8
|
|
|
8
9
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
const TEMPLATE_DIR = path.join(__dirname, '..', 'template');
|
|
@@ -15,6 +16,8 @@ const TEMPLATE_DIR = path.join(__dirname, '..', 'template');
|
|
|
15
16
|
* @returns {Promise<{ filesCreated: number, filesSkipped: number }>}
|
|
16
17
|
*/
|
|
17
18
|
export async function scaffold(config, cwd = process.cwd()) {
|
|
19
|
+
const lang = config.lang || 'en';
|
|
20
|
+
const t = I18N[lang];
|
|
18
21
|
let filesCreated = 0;
|
|
19
22
|
let filesSkipped = 0;
|
|
20
23
|
|
|
@@ -27,21 +30,21 @@ export async function scaffold(config, cwd = process.cwd()) {
|
|
|
27
30
|
const answer = await inquirer.prompt([{
|
|
28
31
|
type: 'list',
|
|
29
32
|
name: 'action',
|
|
30
|
-
message:
|
|
33
|
+
message: t.scaffold.existingClaude,
|
|
31
34
|
choices: [
|
|
32
|
-
{ name:
|
|
33
|
-
{ name:
|
|
34
|
-
{ name:
|
|
35
|
+
{ name: t.scaffold.overwrite, value: 'overwrite' },
|
|
36
|
+
{ name: t.scaffold.merge, value: 'merge' },
|
|
37
|
+
{ name: t.scaffold.skip, value: 'skip' }
|
|
35
38
|
]
|
|
36
39
|
}]);
|
|
37
40
|
claudeAction = answer.action;
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
if (claudeAction === 'skip') {
|
|
41
|
-
console.log(chalk.yellow(' ⊘ .claude/') + chalk.dim(
|
|
44
|
+
console.log(chalk.yellow(' ⊘ .claude/') + chalk.dim(` ${t.scaffold.skipped}`));
|
|
42
45
|
filesSkipped += countFiles(path.join(TEMPLATE_DIR, 'claude'));
|
|
43
46
|
} else {
|
|
44
|
-
const result = copyClaudeDir(claudeAction, cwd);
|
|
47
|
+
const result = copyClaudeDir(claudeAction, cwd, lang, t);
|
|
45
48
|
filesCreated += result.created;
|
|
46
49
|
filesSkipped += result.skipped;
|
|
47
50
|
}
|
|
@@ -55,53 +58,54 @@ export async function scaffold(config, cwd = process.cwd()) {
|
|
|
55
58
|
const answer = await inquirer.prompt([{
|
|
56
59
|
type: 'list',
|
|
57
60
|
name: 'action',
|
|
58
|
-
message:
|
|
61
|
+
message: t.scaffold.existingClaudeMd,
|
|
59
62
|
choices: [
|
|
60
|
-
{ name:
|
|
61
|
-
{ name:
|
|
62
|
-
{ name:
|
|
63
|
+
{ name: t.scaffold.overwriteMd, value: 'overwrite' },
|
|
64
|
+
{ name: t.scaffold.appendMd, value: 'append' },
|
|
65
|
+
{ name: t.scaffold.skipMd, value: 'skip' }
|
|
63
66
|
]
|
|
64
67
|
}]);
|
|
65
68
|
claudeMdAction = answer.action;
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
if (claudeMdAction === 'skip') {
|
|
69
|
-
console.log(chalk.yellow(' ⊘ CLAUDE.md') + chalk.dim(
|
|
72
|
+
console.log(chalk.yellow(' ⊘ CLAUDE.md') + chalk.dim(` ${t.scaffold.skipped}`));
|
|
70
73
|
filesSkipped += 1;
|
|
71
74
|
} else {
|
|
72
|
-
renderClaudeMd(config, claudeMdAction, cwd);
|
|
75
|
+
renderClaudeMd(config, claudeMdAction, cwd, lang);
|
|
73
76
|
filesCreated += 1;
|
|
74
|
-
console.log(chalk.green(' ✓ CLAUDE.md') + chalk.dim(` ${claudeMdAction === 'append' ?
|
|
77
|
+
console.log(chalk.green(' ✓ CLAUDE.md') + chalk.dim(` ${claudeMdAction === 'append' ? t.scaffold.appended : t.scaffold.created}`));
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
// ── 3. Copy scripts/stats/ (always overwrite) ─────────────────────
|
|
78
81
|
const scriptsResult = copyScriptsStats(cwd);
|
|
79
82
|
filesCreated += scriptsResult.created;
|
|
80
|
-
console.log(chalk.green(' ✓ scripts/stats/') + chalk.dim(` ${scriptsResult.created} files`));
|
|
83
|
+
console.log(chalk.green(' ✓ scripts/stats/') + chalk.dim(` ${scriptsResult.created} ${t.scaffold.files}`));
|
|
81
84
|
|
|
82
85
|
// ── 4. Create .cc-starter.json (always overwrite) ──────────────────
|
|
83
86
|
const ccConfig = {
|
|
84
87
|
projectName: config.projectName,
|
|
85
88
|
hourlyRate: config.hourlyRate,
|
|
86
89
|
reportStyle: config.reportStyle,
|
|
90
|
+
lang,
|
|
87
91
|
createdAt: new Date().toISOString(),
|
|
88
92
|
version: '1.0.0'
|
|
89
93
|
};
|
|
90
94
|
fs.writeJsonSync(path.join(cwd, '.cc-starter.json'), ccConfig, { spaces: 2 });
|
|
91
95
|
filesCreated += 1;
|
|
92
|
-
console.log(chalk.green(' ✓ .cc-starter.json') + chalk.dim(
|
|
96
|
+
console.log(chalk.green(' ✓ .cc-starter.json') + chalk.dim(` ${t.scaffold.created}`));
|
|
93
97
|
|
|
94
98
|
// ── 5. Update .gitignore ───────────────────────────────────────────
|
|
95
99
|
const gitignoreUpdated = updateGitignore(cwd);
|
|
96
100
|
if (gitignoreUpdated) {
|
|
97
101
|
filesCreated += 1;
|
|
98
|
-
console.log(chalk.green(' ✓ .gitignore') + chalk.dim(
|
|
102
|
+
console.log(chalk.green(' ✓ .gitignore') + chalk.dim(` ${t.scaffold.updated}`));
|
|
99
103
|
} else {
|
|
100
|
-
console.log(chalk.dim(
|
|
104
|
+
console.log(chalk.dim(` - .gitignore ${t.scaffold.alreadyUpToDate}`));
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
console.log();
|
|
104
|
-
console.log(chalk.bold.green(`
|
|
108
|
+
console.log(chalk.bold.green(` ${t.scaffold.done}`) + chalk.dim(` ${filesCreated} ${t.scaffold.created}, ${filesSkipped} ${t.scaffold.skipped}`));
|
|
105
109
|
|
|
106
110
|
return { filesCreated, filesSkipped };
|
|
107
111
|
}
|
|
@@ -111,15 +115,20 @@ export async function scaffold(config, cwd = process.cwd()) {
|
|
|
111
115
|
/**
|
|
112
116
|
* Copy the template/claude/ tree into cwd/.claude/.
|
|
113
117
|
* In 'merge' mode, only copies files that don't already exist.
|
|
118
|
+
* Rules are copied from the language-specific subfolder.
|
|
114
119
|
*/
|
|
115
|
-
function copyClaudeDir(action, cwd) {
|
|
120
|
+
function copyClaudeDir(action, cwd, lang, t) {
|
|
116
121
|
const src = path.join(TEMPLATE_DIR, 'claude');
|
|
117
122
|
const dest = path.join(cwd, '.claude');
|
|
118
123
|
let created = 0;
|
|
119
124
|
let skipped = 0;
|
|
120
125
|
|
|
126
|
+
// Rules come from the language-specific subfolder
|
|
127
|
+
const rulesSrc = path.join(src, 'rules', lang);
|
|
128
|
+
const rulesFiles = ['01-general.md', '02-code-standards.md', '03-dev-ops.md', '04-token-efficiency.md'];
|
|
129
|
+
|
|
121
130
|
const subdirs = [
|
|
122
|
-
{ dir: 'rules', files:
|
|
131
|
+
{ dir: 'rules', files: rulesFiles, srcOverride: rulesSrc },
|
|
123
132
|
{ dir: 'memory', files: ['MEMORY.md'] },
|
|
124
133
|
{ dir: 'project', files: ['README.md'] },
|
|
125
134
|
{ dir: 'reference', files: ['README.md'] },
|
|
@@ -129,13 +138,14 @@ function copyClaudeDir(action, cwd) {
|
|
|
129
138
|
// Also copy settings.json at the root of .claude/
|
|
130
139
|
const rootFiles = ['settings.json'];
|
|
131
140
|
|
|
132
|
-
for (const { dir, files } of subdirs) {
|
|
141
|
+
for (const { dir, files, srcOverride } of subdirs) {
|
|
133
142
|
const destDir = path.join(dest, dir);
|
|
143
|
+
const srcDir = srcOverride || path.join(src, dir);
|
|
134
144
|
fs.ensureDirSync(destDir);
|
|
135
145
|
let dirCreated = 0;
|
|
136
146
|
|
|
137
147
|
for (const file of files) {
|
|
138
|
-
const srcFile = path.join(
|
|
148
|
+
const srcFile = path.join(srcDir, file);
|
|
139
149
|
const destFile = path.join(destDir, file);
|
|
140
150
|
|
|
141
151
|
if (action === 'merge' && fs.existsSync(destFile)) {
|
|
@@ -149,9 +159,9 @@ function copyClaudeDir(action, cwd) {
|
|
|
149
159
|
}
|
|
150
160
|
|
|
151
161
|
if (dirCreated > 0) {
|
|
152
|
-
console.log(chalk.green(` ✓ .claude/${dir}/`) + chalk.dim(` ${dirCreated}
|
|
162
|
+
console.log(chalk.green(` ✓ .claude/${dir}/`) + chalk.dim(` ${dirCreated} ${dirCreated !== 1 ? t.scaffold.files : 'file'}`));
|
|
153
163
|
} else {
|
|
154
|
-
console.log(chalk.yellow(` ⊘ .claude/${dir}/`) + chalk.dim(
|
|
164
|
+
console.log(chalk.yellow(` ⊘ .claude/${dir}/`) + chalk.dim(` ${t.scaffold.skipped} (exists)`));
|
|
155
165
|
}
|
|
156
166
|
}
|
|
157
167
|
|
|
@@ -161,28 +171,30 @@ function copyClaudeDir(action, cwd) {
|
|
|
161
171
|
|
|
162
172
|
if (action === 'merge' && fs.existsSync(destFile)) {
|
|
163
173
|
skipped += 1;
|
|
164
|
-
console.log(chalk.yellow(` ⊘ .claude/${file}`) + chalk.dim(
|
|
174
|
+
console.log(chalk.yellow(` ⊘ .claude/${file}`) + chalk.dim(` ${t.scaffold.skipped} (exists)`));
|
|
165
175
|
continue;
|
|
166
176
|
}
|
|
167
177
|
|
|
168
178
|
fs.copySync(srcFile, destFile);
|
|
169
179
|
created += 1;
|
|
170
|
-
console.log(chalk.green(` ✓ .claude/${file}`) + chalk.dim(
|
|
180
|
+
console.log(chalk.green(` ✓ .claude/${file}`) + chalk.dim(` ${t.scaffold.created}`));
|
|
171
181
|
}
|
|
172
182
|
|
|
173
183
|
return { created, skipped };
|
|
174
184
|
}
|
|
175
185
|
|
|
176
186
|
/**
|
|
177
|
-
* Render CLAUDE.md from Handlebars template.
|
|
187
|
+
* Render CLAUDE.md from Handlebars template (language-specific).
|
|
178
188
|
*/
|
|
179
|
-
function renderClaudeMd(config, action, cwd) {
|
|
180
|
-
const
|
|
189
|
+
function renderClaudeMd(config, action, cwd, lang) {
|
|
190
|
+
const templateFile = `CLAUDE.md.${lang}.hbs`;
|
|
191
|
+
const templateSrc = fs.readFileSync(path.join(TEMPLATE_DIR, templateFile), 'utf-8');
|
|
181
192
|
const template = Handlebars.compile(templateSrc);
|
|
182
193
|
|
|
183
194
|
const techStack = config.techStack || { languages: [], frameworks: [] };
|
|
184
195
|
const rendered = template({
|
|
185
196
|
projectName: config.projectName,
|
|
197
|
+
projectDescription: config.projectDescription || '',
|
|
186
198
|
techStack
|
|
187
199
|
});
|
|
188
200
|
|
package/lib/wizard.js
CHANGED
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
PLUGIN_PRESETS,
|
|
7
7
|
ALL_PLUGINS,
|
|
8
8
|
REPORT_STYLES,
|
|
9
|
-
DEFAULT_HOURLY_RATE
|
|
9
|
+
DEFAULT_HOURLY_RATE,
|
|
10
|
+
I18N
|
|
10
11
|
} from './constants.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -25,16 +26,32 @@ function detectProjectName() {
|
|
|
25
26
|
/**
|
|
26
27
|
* Interactive setup wizard.
|
|
27
28
|
* @param {string[]} techStack - Auto-detected technologies (e.g. ['Node.js', 'TypeScript', 'React'])
|
|
28
|
-
* @returns {Promise<{projectName: string, hourlyRate: number, reportStyle: string, plugins: object[], techStack: string[]}>}
|
|
29
|
+
* @returns {Promise<{projectName: string, hourlyRate: number, reportStyle: string, plugins: object[], techStack: string[], lang: string}>}
|
|
29
30
|
*/
|
|
30
31
|
export async function wizard(techStack = []) {
|
|
32
|
+
// Language selection FIRST — before anything else
|
|
33
|
+
const { lang } = await inquirer.prompt([{
|
|
34
|
+
type: 'list',
|
|
35
|
+
name: 'lang',
|
|
36
|
+
message: 'Sprache / Language:',
|
|
37
|
+
choices: [
|
|
38
|
+
{ name: 'Deutsch', value: 'de' },
|
|
39
|
+
{ name: 'English', value: 'en' }
|
|
40
|
+
]
|
|
41
|
+
}]);
|
|
42
|
+
|
|
43
|
+
const t = I18N[lang];
|
|
44
|
+
|
|
31
45
|
console.log();
|
|
32
|
-
console.log(chalk.bold.cyan('
|
|
46
|
+
console.log(chalk.bold.cyan(' ' + t.wizard.title));
|
|
33
47
|
console.log();
|
|
34
48
|
|
|
35
49
|
if (techStack.length > 0) {
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
const detected = [...(techStack.languages || []), ...(techStack.frameworks || [])];
|
|
51
|
+
if (detected.length > 0) {
|
|
52
|
+
console.log(chalk.dim(' ' + t.wizard.detectedStack) + chalk.yellow(detected.join(', ')));
|
|
53
|
+
console.log();
|
|
54
|
+
}
|
|
38
55
|
}
|
|
39
56
|
|
|
40
57
|
const defaultName = detectProjectName();
|
|
@@ -43,19 +60,24 @@ export async function wizard(techStack = []) {
|
|
|
43
60
|
{
|
|
44
61
|
type: 'input',
|
|
45
62
|
name: 'projectName',
|
|
46
|
-
message:
|
|
63
|
+
message: t.wizard.projectName,
|
|
47
64
|
default: defaultName
|
|
48
65
|
},
|
|
66
|
+
{
|
|
67
|
+
type: 'input',
|
|
68
|
+
name: 'projectDescription',
|
|
69
|
+
message: t.wizard.projectDescription
|
|
70
|
+
},
|
|
49
71
|
{
|
|
50
72
|
type: 'number',
|
|
51
73
|
name: 'hourlyRate',
|
|
52
|
-
message:
|
|
74
|
+
message: t.wizard.hourlyRate,
|
|
53
75
|
default: DEFAULT_HOURLY_RATE
|
|
54
76
|
},
|
|
55
77
|
{
|
|
56
78
|
type: 'list',
|
|
57
79
|
name: 'reportStyle',
|
|
58
|
-
message:
|
|
80
|
+
message: t.wizard.reportStyle,
|
|
59
81
|
choices: Object.entries(REPORT_STYLES).map(([key, val]) => ({
|
|
60
82
|
name: val.label,
|
|
61
83
|
value: key
|
|
@@ -64,18 +86,18 @@ export async function wizard(techStack = []) {
|
|
|
64
86
|
{
|
|
65
87
|
type: 'list',
|
|
66
88
|
name: 'pluginPreset',
|
|
67
|
-
message:
|
|
89
|
+
message: t.wizard.pluginPreset,
|
|
68
90
|
choices: [
|
|
69
91
|
{ name: `Minimal — ${PLUGIN_PRESETS.minimal.map(p => p.name).join(', ')}`, value: 'minimal' },
|
|
70
92
|
{ name: `Standard — ${PLUGIN_PRESETS.standard.map(p => p.name).join(', ')}`, value: 'standard' },
|
|
71
93
|
{ name: `Full — ${PLUGIN_PRESETS.full.map(p => p.name).join(', ')}`, value: 'full' },
|
|
72
|
-
{ name:
|
|
94
|
+
{ name: t.wizard.custom, value: 'custom' }
|
|
73
95
|
]
|
|
74
96
|
},
|
|
75
97
|
{
|
|
76
98
|
type: 'checkbox',
|
|
77
99
|
name: 'customPlugins',
|
|
78
|
-
message:
|
|
100
|
+
message: t.wizard.selectPlugins,
|
|
79
101
|
when: (ans) => ans.pluginPreset === 'custom',
|
|
80
102
|
choices: ALL_PLUGINS.map((p) => ({
|
|
81
103
|
name: `${p.name} ${chalk.dim('— ' + p.desc)}`,
|
|
@@ -91,9 +113,11 @@ export async function wizard(techStack = []) {
|
|
|
91
113
|
|
|
92
114
|
return {
|
|
93
115
|
projectName: answers.projectName,
|
|
116
|
+
projectDescription: answers.projectDescription || '',
|
|
94
117
|
hourlyRate: answers.hourlyRate,
|
|
95
118
|
reportStyle: answers.reportStyle,
|
|
96
119
|
plugins,
|
|
97
|
-
techStack
|
|
120
|
+
techStack,
|
|
121
|
+
lang
|
|
98
122
|
};
|
|
99
123
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# CLAUDE.md - {{projectName}}
|
|
2
|
+
|
|
3
|
+
## Projektübersicht
|
|
4
|
+
**Projekt:** {{projectName}}
|
|
5
|
+
{{#if projectDescription}}
|
|
6
|
+
**Beschreibung:** {{projectDescription}}
|
|
7
|
+
{{/if}}
|
|
8
|
+
{{#if techStack.languages.length}}
|
|
9
|
+
**Sprachen:** {{#each techStack.languages}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
|
10
|
+
{{/if}}
|
|
11
|
+
{{#if techStack.frameworks.length}}
|
|
12
|
+
**Frameworks:** {{#each techStack.frameworks}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
|
13
|
+
{{/if}}
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Kurzreferenz
|
|
18
|
+
|
|
19
|
+
### Token-sparende Scripts
|
|
20
|
+
```bash
|
|
21
|
+
node scripts/stats/vibe-code.js help # Code-Analyse (~90% Tokens sparen)
|
|
22
|
+
node scripts/stats/vibe-code.js types <f> # Types/Interfaces extrahieren
|
|
23
|
+
node scripts/stats/vibe-code.js tree [dir] # Verzeichnisstruktur anzeigen
|
|
24
|
+
node scripts/stats/vibe-code.js imports <f> # Imports anzeigen
|
|
25
|
+
node scripts/stats/vibe-code.js funcs <f> # Funktions-Signaturen
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Projekt-Statistiken
|
|
29
|
+
```bash
|
|
30
|
+
node scripts/stats/cocomo.js # Projekt-Kostenschätzung
|
|
31
|
+
node scripts/stats/project-report.js # HTML-Statistik-Report
|
|
32
|
+
node scripts/stats/vibe-stats.js report # Token-Einsparungs-Report
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Regeln
|
|
36
|
+
Siehe `.claude/rules/` für Arbeitsregeln:
|
|
37
|
+
- `01-general.md` — Aufgaben-Tracking, Planung, Verifikation
|
|
38
|
+
- `02-code-standards.md` — Code-Qualität, Sicherheit, Tests
|
|
39
|
+
- `03-dev-ops.md` — Git, Umgebung, Deployment
|
|
40
|
+
- `04-token-efficiency.md` — **PFLICHT:** Vibe-Code Scripts nutzen bevor Dateien gelesen werden
|
|
41
|
+
|
|
42
|
+
### Memory-System
|
|
43
|
+
Persistenter Speicher über Sessions hinweg in `.claude/memory/`.
|
|
44
|
+
Index: `.claude/memory/MEMORY.md`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
*Generiert von [cc-starter](https://www.npmjs.com/package/cc-starter)*
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# CLAUDE.md - {{projectName}}
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
**Project:** {{projectName}}
|
|
5
|
+
{{#if projectDescription}}
|
|
6
|
+
**Description:** {{projectDescription}}
|
|
7
|
+
{{/if}}
|
|
8
|
+
{{#if techStack.languages.length}}
|
|
9
|
+
**Languages:** {{#each techStack.languages}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
|
10
|
+
{{/if}}
|
|
11
|
+
{{#if techStack.frameworks.length}}
|
|
12
|
+
**Frameworks:** {{#each techStack.frameworks}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
|
|
13
|
+
{{/if}}
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick Reference
|
|
18
|
+
|
|
19
|
+
### Token-Saving Scripts
|
|
20
|
+
```bash
|
|
21
|
+
node scripts/stats/vibe-code.js help # Code analysis (save ~90% tokens)
|
|
22
|
+
node scripts/stats/vibe-code.js types <f> # Extract types/interfaces
|
|
23
|
+
node scripts/stats/vibe-code.js tree [dir] # Clean directory tree
|
|
24
|
+
node scripts/stats/vibe-code.js imports <f> # Show imports
|
|
25
|
+
node scripts/stats/vibe-code.js funcs <f> # Function signatures
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Project Statistics
|
|
29
|
+
```bash
|
|
30
|
+
node scripts/stats/cocomo.js # Project cost estimation
|
|
31
|
+
node scripts/stats/project-report.js # HTML statistics report
|
|
32
|
+
node scripts/stats/vibe-stats.js report # Token savings report
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Rules
|
|
36
|
+
See `.claude/rules/` for working rules:
|
|
37
|
+
- `01-general.md` — Task tracking, planning, verification
|
|
38
|
+
- `02-code-standards.md` — Code quality, security, testing
|
|
39
|
+
- `03-dev-ops.md` — Git, environment, deployment
|
|
40
|
+
- `04-token-efficiency.md` — **MANDATORY:** Use Vibe-Code Scripts before reading files
|
|
41
|
+
|
|
42
|
+
### Memory System
|
|
43
|
+
Persistent memory across sessions in `.claude/memory/`.
|
|
44
|
+
Index: `.claude/memory/MEMORY.md`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
*Generated by [cc-starter](https://www.npmjs.com/package/cc-starter)*
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Allgemeine Arbeitsregeln
|
|
2
|
+
|
|
3
|
+
## 1. Aufgaben-Tracking
|
|
4
|
+
Bei Tasks mit **3+ Schritten** IMMER:
|
|
5
|
+
- Aufgaben-Tracking verwenden um Arbeitspakete zu verwalten
|
|
6
|
+
- Jeden Schritt als Aufgabe anlegen BEVOR du anfängst
|
|
7
|
+
- Jeden Punkt sofort als erledigt markieren wenn er fertig ist
|
|
8
|
+
|
|
9
|
+
## 2. Dokumentation modular halten
|
|
10
|
+
- Keine ausufernden Status-Dateien erstellen
|
|
11
|
+
- Updates gehören in die passende Dokumentation (Feature-Docs, Architektur-Docs)
|
|
12
|
+
- Saubere Trennung der Zuständigkeiten einhalten
|
|
13
|
+
|
|
14
|
+
## 3. Vor dem Coden
|
|
15
|
+
- Bei Unklarheiten: Erst fragen, dann implementieren
|
|
16
|
+
- Bei mehreren Lösungswegen: Optionen vorstellen und Entscheidung abwarten
|
|
17
|
+
|
|
18
|
+
## 4. Wenn es nicht klappt: STOPP & Neu planen
|
|
19
|
+
- Wenn ein Ansatz nicht funktioniert: **Sofort stoppen**, nicht weiter probieren
|
|
20
|
+
- Neu planen statt den gleichen Fehler zu wiederholen
|
|
21
|
+
- Ursachen finden — keine temporären Workarounds oder Hacks
|
|
22
|
+
- Frage dich: "Ist das die elegante Lösung oder ein Quick-Fix?"
|
|
23
|
+
|
|
24
|
+
## 5. Verifikation: Diff gegen Main vor "Fertig"
|
|
25
|
+
- Vor der Fertigmeldung: `git diff main` um sicherzustellen dass alle Änderungen beabsichtigt sind
|
|
26
|
+
- Frage dich: "Würde ein Senior Engineer das so abnehmen?"
|
|
27
|
+
- Build muss grün sein
|
|
28
|
+
- Keine unbeabsichtigten Änderungen in unbeteiligten Dateien
|
|
29
|
+
|
|
30
|
+
## 6. Design-Dokumentation
|
|
31
|
+
Bei Design-Entscheidungen den Prozess dokumentieren:
|
|
32
|
+
- Zusammenfassung der finalen Entscheidungen
|
|
33
|
+
- Gestellte Fragen mit Optionen und gewählten Antworten
|
|
34
|
+
- Begründung für jede Wahl
|
|
35
|
+
- Technische Details
|
|
36
|
+
- Offene Punkte
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Code-Standards
|
|
2
|
+
|
|
3
|
+
## Sicherheit zuerst
|
|
4
|
+
- Niemals Secrets, API-Keys oder Zugangsdaten committen
|
|
5
|
+
- Alle externen Eingaben validieren
|
|
6
|
+
- Parameterisierte Queries für Datenbanken verwenden
|
|
7
|
+
- OWASP Top 10 Richtlinien befolgen
|
|
8
|
+
|
|
9
|
+
## Code-Qualität
|
|
10
|
+
- Selbstdokumentierenden Code mit klarer Benennung schreiben
|
|
11
|
+
- Funktionen fokussiert halten (Single Responsibility)
|
|
12
|
+
- Komposition statt Vererbung bevorzugen
|
|
13
|
+
- Fehler explizit behandeln — keine stillen Catches
|
|
14
|
+
|
|
15
|
+
## Tests
|
|
16
|
+
- Tests für neue Features und Bugfixes schreiben
|
|
17
|
+
- Edge Cases und Fehlerpfade testen
|
|
18
|
+
- Nicht mocken was dir nicht gehört — wenn möglich Integrationstests verwenden
|
|
19
|
+
|
|
20
|
+
## Internationalisierung (falls zutreffend)
|
|
21
|
+
- Keine hardcodierten User-facing Strings
|
|
22
|
+
- Die i18n-Lösung des Projekts konsistent verwenden
|
|
23
|
+
- Übersetzungsdateien über alle Sprachen synchron halten
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# DevOps & Deployment Regeln
|
|
2
|
+
|
|
3
|
+
## Git-Disziplin
|
|
4
|
+
- Zuständigkeiten in Commits trennen (App-Code vs. Infrastruktur vs. Docs)
|
|
5
|
+
- Aussagekräftige Commit-Messages schreiben die das WARUM erklären, nicht nur das WAS
|
|
6
|
+
- Niemals Force-Push auf main/master ohne Team-Absprache
|
|
7
|
+
|
|
8
|
+
## Umgebungsvariablen
|
|
9
|
+
- Neue ENV-Variablen müssen dokumentiert werden
|
|
10
|
+
- Niemals .env-Dateien mit echten Werten committen
|
|
11
|
+
- .env.example mit Platzhalter-Werten bereitstellen
|
|
12
|
+
|
|
13
|
+
## Port-Management
|
|
14
|
+
- Einen Dev-Server-Port verwenden — nicht mehrere starten
|
|
15
|
+
- Verwaiste Prozesse beenden bevor neue Dev-Server gestartet werden
|
|
16
|
+
|
|
17
|
+
## Build-Verifikation
|
|
18
|
+
- Immer Build/Lint vor dem Committen ausführen
|
|
19
|
+
- Warnungen beheben, nicht unterdrücken
|
|
20
|
+
- CI/CD-Pipeline grün halten
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Token Efficiency Rules
|
|
2
|
+
|
|
3
|
+
## PFLICHT: Vibe-Code Scripts BEVOR du große Dateien liest!
|
|
4
|
+
|
|
5
|
+
**Diese Scripts sparen ~90% Tokens. Nutze sie IMMER bevor du eine Datei mit Read öffnest.**
|
|
6
|
+
|
|
7
|
+
### Verfügbare Commands
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Types/Interfaces/Enums einer Datei extrahieren (statt ganze Datei zu lesen)
|
|
11
|
+
node scripts/stats/vibe-code.js types <file>
|
|
12
|
+
|
|
13
|
+
# Verzeichnisstruktur anzeigen (statt jeden Ordner einzeln zu lesen)
|
|
14
|
+
node scripts/stats/vibe-code.js tree [dir]
|
|
15
|
+
|
|
16
|
+
# Imports einer Datei anzeigen (für Dependency-Checks)
|
|
17
|
+
node scripts/stats/vibe-code.js imports <file>
|
|
18
|
+
|
|
19
|
+
# Funktions-Signaturen extrahieren (statt ganze Datei zu lesen)
|
|
20
|
+
node scripts/stats/vibe-code.js functions <file>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Wann nutzen
|
|
24
|
+
|
|
25
|
+
| Situation | Statt | Nutze |
|
|
26
|
+
|-----------|-------|-------|
|
|
27
|
+
| Du willst wissen welche Types eine Datei hat | `Read` der ganzen Datei | `vibe-code.js types <file>` |
|
|
28
|
+
| Du brauchst einen Überblick über einen Ordner | Mehrere `Read`/`ls` Aufrufe | `vibe-code.js tree <dir>` |
|
|
29
|
+
| Du willst Abhängigkeiten einer Datei checken | `Read` und manuell suchen | `vibe-code.js imports <file>` |
|
|
30
|
+
| Du willst die API einer Datei verstehen | `Read` der ganzen Datei | `vibe-code.js functions <file>` |
|
|
31
|
+
|
|
32
|
+
### NIEMALS
|
|
33
|
+
|
|
34
|
+
- Große Dateien (200+ Zeilen) komplett lesen ohne vorher `types` oder `functions` zu checken
|
|
35
|
+
- Ordnerstrukturen manuell mit `ls` oder `Glob` erkunden wenn `tree` das in einem Aufruf erledigt
|
|
36
|
+
- Token verschwenden indem du Code liest den du nicht brauchst
|
|
37
|
+
|
|
38
|
+
### Token-Tracking
|
|
39
|
+
|
|
40
|
+
Nach der Nutzung werden Einsparungen automatisch in `.vibe-stats.json` getrackt.
|
|
41
|
+
Fortschritt prüfen:
|
|
42
|
+
```bash
|
|
43
|
+
node scripts/stats/vibe-stats.js summary # Einzeiler: Gesamt-Einsparung
|
|
44
|
+
node scripts/stats/vibe-stats.js report # Detaillierter Report
|
|
45
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# General Working Rules
|
|
2
|
+
|
|
3
|
+
## 1. Task Tracking
|
|
4
|
+
For tasks with **3+ steps** ALWAYS:
|
|
5
|
+
- Use task tracking to manage work items
|
|
6
|
+
- Create each step as a task BEFORE starting
|
|
7
|
+
- Mark each task as completed immediately when done
|
|
8
|
+
|
|
9
|
+
## 2. Keep Documentation Modular
|
|
10
|
+
- Don't create sprawling status files
|
|
11
|
+
- Updates belong in the matching doc (feature docs, architecture docs)
|
|
12
|
+
- Keep a clean separation of concerns
|
|
13
|
+
|
|
14
|
+
## 3. Before Coding
|
|
15
|
+
- When unclear: Ask first, then implement
|
|
16
|
+
- When multiple approaches exist: Present options and wait for decision
|
|
17
|
+
|
|
18
|
+
## 4. When Things Go Wrong: STOP & Re-plan
|
|
19
|
+
- If an approach isn't working: **Stop immediately**, don't keep pushing
|
|
20
|
+
- Re-plan instead of repeating the same mistake
|
|
21
|
+
- Find root causes — no temporary workarounds or hacks
|
|
22
|
+
- Ask yourself: "Is this the elegant solution or a quick-fix?"
|
|
23
|
+
|
|
24
|
+
## 5. Verification: Diff Against Main Before "Done"
|
|
25
|
+
- Before claiming "done": run `git diff main` to check all changes are intentional
|
|
26
|
+
- Ask yourself: "Would a staff engineer approve this?"
|
|
27
|
+
- Build must be green
|
|
28
|
+
- No unintended changes in unrelated files
|
|
29
|
+
|
|
30
|
+
## 6. Design Documentation
|
|
31
|
+
When making design decisions, document the process:
|
|
32
|
+
- Summary of final decisions
|
|
33
|
+
- Questions asked with options and chosen answers
|
|
34
|
+
- Reasoning for each choice
|
|
35
|
+
- Technical details
|
|
36
|
+
- Open points
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Code Standards
|
|
2
|
+
|
|
3
|
+
## Security First
|
|
4
|
+
- Never commit secrets, API keys, or credentials
|
|
5
|
+
- Validate all external input
|
|
6
|
+
- Use parameterized queries for databases
|
|
7
|
+
- Follow OWASP Top 10 guidelines
|
|
8
|
+
|
|
9
|
+
## Code Quality
|
|
10
|
+
- Write self-documenting code with clear naming
|
|
11
|
+
- Keep functions focused (single responsibility)
|
|
12
|
+
- Prefer composition over inheritance
|
|
13
|
+
- Handle errors explicitly — no silent catches
|
|
14
|
+
|
|
15
|
+
## Testing
|
|
16
|
+
- Write tests for new features and bug fixes
|
|
17
|
+
- Test edge cases and error paths
|
|
18
|
+
- Don't mock what you don't own — use integration tests where possible
|
|
19
|
+
|
|
20
|
+
## Internationalization (if applicable)
|
|
21
|
+
- No hardcoded user-facing strings
|
|
22
|
+
- Use your project's i18n solution consistently
|
|
23
|
+
- Keep translation files in sync across locales
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# DevOps & Deployment Rules
|
|
2
|
+
|
|
3
|
+
## Git Discipline
|
|
4
|
+
- Separate concerns in commits (app code vs. infrastructure vs. docs)
|
|
5
|
+
- Write descriptive commit messages explaining WHY, not just WHAT
|
|
6
|
+
- Never force-push to main/master without team agreement
|
|
7
|
+
|
|
8
|
+
## Environment Variables
|
|
9
|
+
- New env vars must be documented
|
|
10
|
+
- Never commit .env files with real values
|
|
11
|
+
- Provide .env.example with placeholder values
|
|
12
|
+
|
|
13
|
+
## Port Management
|
|
14
|
+
- Stick to one dev server port — don't spawn multiple
|
|
15
|
+
- Kill orphan processes before starting new dev servers
|
|
16
|
+
|
|
17
|
+
## Build Verification
|
|
18
|
+
- Always run build/lint before committing
|
|
19
|
+
- Fix warnings, don't suppress them
|
|
20
|
+
- Keep CI/CD pipeline green
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Token Efficiency Rules
|
|
2
|
+
|
|
3
|
+
## MANDATORY: Use Vibe-Code Scripts BEFORE reading large files!
|
|
4
|
+
|
|
5
|
+
**These scripts save ~90% tokens. ALWAYS use them before opening a file with Read.**
|
|
6
|
+
|
|
7
|
+
### Available Commands
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Extract types/interfaces/enums from a file (instead of reading the whole file)
|
|
11
|
+
node scripts/stats/vibe-code.js types <file>
|
|
12
|
+
|
|
13
|
+
# Show directory structure (instead of reading each folder individually)
|
|
14
|
+
node scripts/stats/vibe-code.js tree [dir]
|
|
15
|
+
|
|
16
|
+
# Show imports of a file (for dependency checks)
|
|
17
|
+
node scripts/stats/vibe-code.js imports <file>
|
|
18
|
+
|
|
19
|
+
# Extract function signatures (instead of reading the whole file)
|
|
20
|
+
node scripts/stats/vibe-code.js functions <file>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### When to Use
|
|
24
|
+
|
|
25
|
+
| Situation | Instead of | Use |
|
|
26
|
+
|-----------|------------|-----|
|
|
27
|
+
| You want to know what types a file has | `Read` the whole file | `vibe-code.js types <file>` |
|
|
28
|
+
| You need an overview of a folder | Multiple `Read`/`ls` calls | `vibe-code.js tree <dir>` |
|
|
29
|
+
| You want to check a file's dependencies | `Read` and search manually | `vibe-code.js imports <file>` |
|
|
30
|
+
| You want to understand a file's API | `Read` the whole file | `vibe-code.js functions <file>` |
|
|
31
|
+
|
|
32
|
+
### NEVER
|
|
33
|
+
|
|
34
|
+
- Read large files (200+ lines) completely without first checking `types` or `functions`
|
|
35
|
+
- Explore folder structures manually with `ls` or `Glob` when `tree` does it in one call
|
|
36
|
+
- Waste tokens by reading code you don't need
|
|
37
|
+
|
|
38
|
+
### Token Tracking
|
|
39
|
+
|
|
40
|
+
After usage, savings are automatically tracked in `.vibe-stats.json`.
|
|
41
|
+
Check progress:
|
|
42
|
+
```bash
|
|
43
|
+
node scripts/stats/vibe-stats.js summary # One-liner: total savings
|
|
44
|
+
node scripts/stats/vibe-stats.js report # Detailed report
|
|
45
|
+
```
|