@felixgeelhaar/cclint
Version:
Catch CLAUDE.md drift before Claude misbehaves. Lints CLAUDE.md, skills, subagents, and hooks for Claude Code projects.
109 lines ⢠4.35 kB
JavaScript
import { Command } from 'commander';
import { existsSync } from 'fs';
import { resolve, basename } from 'path';
import { ProjectDetector } from '../../infrastructure/ProjectDetector.js';
import { Scaffolder, } from '../../infrastructure/Scaffolder.js';
/**
* Validates that a string is a valid template name
*/
function isValidTemplate(name) {
const valid = [
'minimal',
'typescript',
'python',
'go',
'monorepo',
'library',
'api',
];
return valid.includes(name);
}
export const initCommand = new Command('init')
.description('Create a new CLAUDE.md file')
.option('-t, --template <name>', 'Template to use (minimal, typescript, python, go, monorepo, library, api)')
.option('--detect', 'Auto-detect project type', false)
.option('-f, --force', 'Overwrite existing CLAUDE.md', false)
.option('-o, --output <path>', 'Output path', 'CLAUDE.md')
.option('-y, --yes', 'Skip confirmation prompts', false)
.action((options) => {
try {
const outputPath = resolve(process.cwd(), options.output);
const scaffolder = new Scaffolder();
// Check if file exists
if (existsSync(outputPath) && !options.force) {
console.error(`Error: ${options.output} already exists. Use --force to overwrite.`);
process.exit(1);
}
let template = 'minimal';
let projectName = basename(process.cwd());
let projectDescription = 'A brief description of the project.';
let detectionResult = undefined;
// Validate template if provided
if (options.template) {
if (!isValidTemplate(options.template)) {
console.error(`Error: Invalid template "${options.template}". ` +
`Available templates: ${scaffolder.listTemplates().join(', ')}`);
process.exit(1);
}
template = options.template;
}
// Auto-detect project type
if (options.detect || !options.template) {
console.log('š Analyzing project...');
const detector = new ProjectDetector(process.cwd());
detectionResult = detector.detect();
if (detectionResult.confidence > 0) {
console.log(` Type: ${detectionResult.type}`);
console.log(` Structure: ${detectionResult.structure}`);
console.log(` Confidence: ${Math.round(detectionResult.confidence * 100)}%`);
console.log(` Evidence: ${detectionResult.evidence.join(', ')}`);
if (detectionResult.projectName) {
projectName = detectionResult.projectName;
}
if (detectionResult.projectDescription) {
projectDescription = detectionResult.projectDescription;
}
// Use detected template if not explicitly specified
if (!options.template) {
template = scaffolder.getTemplateForDetection(detectionResult);
console.log(`\nš Selected template: ${template}`);
}
}
else {
console.log(' Could not detect project type, using minimal template.');
}
console.log('');
}
// Scaffold the file
console.log(`š Creating ${options.output}...`);
const result = scaffolder.scaffold({
template,
projectName,
projectDescription,
overwrite: options.force,
outputPath,
detection: detectionResult,
});
if (result.wasOverwritten) {
console.log(`ā
Overwrote ${result.path}`);
}
else {
console.log(`ā
Created ${result.path}`);
}
console.log('');
console.log('Next steps:');
console.log(' 1. Review and customize the generated CLAUDE.md');
console.log(' 2. Run `cclint lint CLAUDE.md` to validate');
console.log('');
}
catch (error) {
if (error instanceof Error) {
console.error(`Error: ${error.message}`);
}
else {
console.error('Error: Unknown error occurred');
}
process.exit(1);
}
});
//# sourceMappingURL=init.js.map