about summary refs log tree commit diff stats
path: root/tree-sitter/dsk/dsk-cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'tree-sitter/dsk/dsk-cli/src')
-rw-r--r--tree-sitter/dsk/dsk-cli/src/commands/build.ts429
-rw-r--r--tree-sitter/dsk/dsk-cli/src/commands/dev.ts105
-rw-r--r--tree-sitter/dsk/dsk-cli/src/commands/highlight.ts141
-rw-r--r--tree-sitter/dsk/dsk-cli/src/commands/new.ts485
-rw-r--r--tree-sitter/dsk/dsk-cli/src/commands/package.ts66
-rw-r--r--tree-sitter/dsk/dsk-cli/src/commands/self.ts71
-rw-r--r--tree-sitter/dsk/dsk-cli/src/commands/test.ts50
-rw-r--r--tree-sitter/dsk/dsk-cli/src/index.ts80
-rw-r--r--tree-sitter/dsk/dsk-cli/src/utils/grammar-generator.ts466
-rw-r--r--tree-sitter/dsk/dsk-cli/src/utils/inference.ts286
-rw-r--r--tree-sitter/dsk/dsk-cli/src/utils/template-processor.ts192
11 files changed, 2371 insertions, 0 deletions
diff --git a/tree-sitter/dsk/dsk-cli/src/commands/build.ts b/tree-sitter/dsk/dsk-cli/src/commands/build.ts
new file mode 100644
index 0000000..811788f
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/commands/build.ts
@@ -0,0 +1,429 @@
+/**
+ * Build Command - Core Build Process
+ * 
+ * Compiles grammar.js into C static library and JavaScript package
+ */
+
+import { Command } from 'commander';
+import { execa } from 'execa';
+import chalk from 'chalk';
+import { existsSync, mkdirSync, writeFileSync, copyFileSync, readFileSync, cpSync } from 'fs';
+import { join, dirname, basename } from 'path';
+import { fileURLToPath } from 'url';
+
+/**
+ * Create the build command
+ */
+export function createBuildCommand(): Command {
+  const buildCommand = new Command('build');
+  
+  buildCommand
+    .description('Build the DSL parser and packages')
+    .option('-v, --verbose', 'Show detailed build output')
+    .option('--skip-c', 'Skip C library generation')
+    .option('--skip-js', 'Skip JavaScript package generation')
+    .action(async (options) => {
+      console.log(chalk.blue('๐Ÿ—๏ธ  Building DSL parser and packages...'));
+      console.log();
+      
+      try {
+        await runBuildProcess(options);
+        
+        console.log();
+        console.log(chalk.green('โœ… Build completed successfully!'));
+        console.log();
+        console.log(chalk.blue('Generated artifacts:'));
+        console.log(`  ${chalk.gray('โ€ข')} C library: generated/c/lib/`);
+        console.log(`  ${chalk.gray('โ€ข')} C headers: generated/c/include/`);
+        console.log(`  ${chalk.gray('โ€ข')} JS package: generated/js/`);
+        
+      } catch (error) {
+        console.error(chalk.red('โŒ Build failed:'), error instanceof Error ? error.message : error);
+        process.exit(1);
+      }
+    });
+
+  return buildCommand;
+}
+
+/**
+ * Run the complete build process
+ */
+async function runBuildProcess(options: { verbose?: boolean; skipC?: boolean; skipJs?: boolean }): Promise<void> {
+  // Verify we're in a DSL project directory
+  if (!existsSync('grammar.js')) {
+    throw new Error('No grammar.js found. Are you in a DSL project directory?');
+  }
+
+  // Ensure CommonJS semantics locally so tree-sitter can load grammar.js (uses module.exports)
+  ensureCommonJsPackageJson();
+
+  // Step 1: Generate parser with Tree-sitter
+  console.log(chalk.blue('1๏ธโƒฃ  Generating parser with Tree-sitter...'));
+  await generateParser(options.verbose);
+  console.log(chalk.green('   โœ… Parser generated'));
+
+  // Step 2: Build C library (unless skipped)
+  if (!options.skipC) {
+    console.log(chalk.blue('2๏ธโƒฃ  Building C static library...'));
+    await buildCLibrary(options.verbose);
+    console.log(chalk.green('   โœ… C library built'));
+  } else {
+    console.log(chalk.yellow('   โญ๏ธ  Skipping C library build'));
+  }
+
+  // Step 3: Build JavaScript package (unless skipped)
+  if (!options.skipJs) {
+    console.log(chalk.blue('3๏ธโƒฃ  Building JavaScript package...'));
+    await buildJavaScriptPackage(options.verbose);
+    console.log(chalk.green('   โœ… JavaScript package built'));
+  } else {
+    console.log(chalk.yellow('   โญ๏ธ  Skipping JavaScript package build'));
+  }
+}
+
+/**
+ * Step 1: Generate parser using tree-sitter generate
+ */
+async function generateParser(verbose?: boolean): Promise<void> {
+  try {
+    // Check if tree-sitter CLI is available
+    await checkTreeSitterAvailable();
+    
+    // Run tree-sitter generate
+    const result = await execa('tree-sitter', ['generate'], {
+      stdio: verbose ? 'inherit' : 'pipe'
+    });
+    
+    if (!verbose && result.stdout) {
+      console.log(chalk.gray(`   ${result.stdout.split('\n').slice(-2, -1)[0] || 'Generated successfully'}`));
+    }
+    
+  } catch (error: any) {
+    if (error.command) {
+      throw new Error(`Tree-sitter generation failed: ${error.message}`);
+    }
+    throw error;
+  }
+}
+
+/**
+ * Step 2: Build C static library
+ */
+async function buildCLibrary(verbose?: boolean): Promise<void> {
+  // Create output directories
+  const libDir = 'generated/c/lib';
+  const includeDir = 'generated/c/include';
+  
+  mkdirSync(libDir, { recursive: true });
+  mkdirSync(includeDir, { recursive: true });
+
+  // Get project name from grammar.js or directory
+  const projectName = getProjectName();
+  
+  // Compile parser.c to object file
+  const objectFile = join(libDir, `${projectName}.o`);
+  const libraryFile = join(libDir, `lib${projectName}.a`);
+  
+  try {
+    // Detect C compiler
+    const compiler = await detectCCompiler();
+    console.log(chalk.gray(`   Using compiler: ${compiler}`));
+    
+    // Compile to object file
+    const compileArgs = [
+      '-c',                    // Compile only, don't link
+      '-fPIC',                 // Position independent code
+      '-O2',                   // Optimize
+      'src/parser.c',          // Input file
+      '-o', objectFile         // Output file
+    ];
+    
+    await execa(compiler, compileArgs, {
+      stdio: verbose ? 'inherit' : 'pipe'
+    });
+    
+    // Create static library with ar
+    const arArgs = [
+      'rcs',                   // Create archive, insert files, write symbol table
+      libraryFile,             // Output library
+      objectFile               // Input object file
+    ];
+    
+    await execa('ar', arArgs, {
+      stdio: verbose ? 'inherit' : 'pipe'
+    });
+    
+    // Generate header file
+    await generateHeaderFile(projectName, includeDir);
+    
+    console.log(chalk.gray(`   Library: ${libraryFile}`));
+    console.log(chalk.gray(`   Header: ${join(includeDir, projectName + '.h')}`));
+    
+  } catch (error: any) {
+    throw new Error(`C library build failed: ${error.message}`);
+  }
+}
+
+/**
+ * Step 3: Build JavaScript package
+ */
+async function buildJavaScriptPackage(verbose?: boolean): Promise<void> {
+  const jsDir = 'generated/js';
+  
+  // Create JS package directory
+  mkdirSync(jsDir, { recursive: true });
+  
+  // Copy JS addon templates
+  await copyJSAddonTemplates(jsDir);
+  
+  // Copy src directory from tree-sitter generation
+  await copySourceFiles(jsDir);
+  
+  // Update binding.gyp based on available files
+  await updateBindingGyp(jsDir);
+  
+  // Update package.json with project name
+  await updateJSPackageJson(jsDir);
+  
+  // Detect runtime and install dependencies
+  const runtime = await detectRuntime();
+  console.log(chalk.gray(`   Using runtime: ${runtime}`));
+  
+  try {
+    // Install dependencies and build native addon
+    if (runtime === 'bun') {
+      await execa('bun', ['install'], {
+        cwd: jsDir,
+        stdio: verbose ? 'inherit' : 'pipe'
+      });
+    } else {
+      await execa('npm', ['install'], {
+        cwd: jsDir,
+        stdio: verbose ? 'inherit' : 'pipe'
+      });
+    }
+    
+    console.log(chalk.gray(`   Package: ${jsDir}/`));
+    
+  } catch (error: any) {
+    throw new Error(`JavaScript package build failed: ${error.message}`);
+  }
+}
+
+/**
+ * Check if tree-sitter CLI is available
+ */
+async function checkTreeSitterAvailable(): Promise<void> {
+  try {
+    await execa('tree-sitter', ['--version'], { stdio: 'pipe' });
+  } catch (error) {
+    throw new Error(
+      'tree-sitter CLI not found. Please install it:\n' +
+      '  npm install -g tree-sitter-cli\n' +
+      '  # or\n' +
+      '  brew install tree-sitter'
+    );
+  }
+}
+
+/**
+ * Detect available C compiler
+ */
+async function detectCCompiler(): Promise<string> {
+  const compilers = ['clang', 'gcc', 'cc'];
+  
+  for (const compiler of compilers) {
+    try {
+      await execa(compiler, ['--version'], { stdio: 'pipe' });
+      return compiler;
+    } catch {
+      // Try next compiler
+    }
+  }
+  
+  throw new Error(
+    'No C compiler found. Please install one:\n' +
+    '  macOS: xcode-select --install\n' +
+    '  Linux: sudo apt install build-essential (Ubuntu) or equivalent'
+  );
+}
+
+/**
+ * Detect runtime (bun vs npm)
+ */
+async function detectRuntime(): Promise<'bun' | 'npm'> {
+  try {
+    await execa('bun', ['--version'], { stdio: 'pipe' });
+    return 'bun';
+  } catch {
+    return 'npm';
+  }
+}
+
+/**
+ * Get project name from grammar.js or directory name
+ */
+function getProjectName(): string {
+  try {
+    const grammarContent = readFileSync('grammar.js', 'utf-8');
+    const nameMatch = grammarContent.match(/name:\s*['"]([^'"]+)['"]/);
+    if (nameMatch) {
+      return nameMatch[1];
+    }
+  } catch {
+    // Fall back to directory name
+  }
+  
+  return basename(process.cwd());
+}
+
+/**
+ * Ensure the current directory is treated as CommonJS for Node resolution,
+ * so that tree-sitter can load `grammar.js` (which uses module.exports).
+ * If no local package.json exists, create a minimal one with "type": "commonjs".
+ */
+function ensureCommonJsPackageJson(): void {
+  const packageJsonPath = 'package.json';
+  if (!existsSync(packageJsonPath)) {
+    const projectName = basename(process.cwd());
+    const minimal = {
+      name: `${projectName}-dsl`,
+      private: true,
+      type: 'commonjs',
+      description: `DSL project for ${projectName} generated by DSK`,
+      license: 'MIT'
+    } as const;
+    writeFileSync(packageJsonPath, JSON.stringify(minimal, null, 2));
+    console.log(chalk.gray('   Created local package.json with { "type": "commonjs" }'));
+  }
+}
+
+/**
+ * Generate C header file
+ */
+async function generateHeaderFile(projectName: string, includeDir: string): Promise<void> {
+  const headerContent = `#ifndef TREE_SITTER_${projectName.toUpperCase()}_H_
+#define TREE_SITTER_${projectName.toUpperCase()}_H_
+
+typedef struct TSLanguage TSLanguage;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const TSLanguage *tree_sitter_${projectName}(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // TREE_SITTER_${projectName.toUpperCase()}_H_
+`;
+
+  writeFileSync(join(includeDir, `${projectName}.h`), headerContent);
+}
+
+/**
+ * Copy JS addon template files
+ */
+async function copyJSAddonTemplates(jsDir: string): Promise<void> {
+  const __filename = fileURLToPath(import.meta.url);
+  const __dirname = dirname(__filename);
+  const templateDir = join(__dirname, '..', '..', 'templates', 'js-addon');
+  
+  if (!existsSync(templateDir)) {
+    throw new Error(`JS addon template directory not found: ${templateDir}`);
+  }
+  
+  // Copy all template files
+  const { processTemplate } = await import('../utils/template-processor.js');
+  const projectName = getProjectName();
+  
+  const templateContext = {
+    architecture: { 
+      name: projectName, 
+      paradigm: 'mixed' as const, 
+      purpose: 'DSL', 
+      dataPhilosophy: 'mixed' as const 
+    },
+    features: { controlFlow: [], dataStructures: [], functionTypes: [] },
+    syntax: {
+      comments: { type: 'line_comment', pattern: '//' },
+      identifiers: { pattern: '[a-zA-Z_][a-zA-Z0-9_]*', examples: ['identifier'] },
+      numbers: { pattern: '\\d+', examples: ['42'] },
+      strings: { pattern: '"[^"]*"', examples: ['"string"'] },
+      variables: { keyword: 'let', operator: '=', terminator: ';', example: 'let x = 42;' },
+      paradigmExamples: {}
+    }
+  };
+  
+  processTemplate(templateDir, jsDir, templateContext);
+}
+
+/**
+ * Copy source files from tree-sitter generation to JS package
+ */
+async function copySourceFiles(jsDir: string): Promise<void> {
+  const srcDir = 'src';
+  const targetSrcDir = join(jsDir, 'src');
+  
+  if (!existsSync(srcDir)) {
+    throw new Error('src/ directory not found. Run tree-sitter generate first.');
+  }
+  
+  // Copy the entire src directory
+  cpSync(srcDir, targetSrcDir, { recursive: true });
+  
+  console.log(chalk.gray(`   Copied src files to ${targetSrcDir}`));
+}
+
+/**
+ * Update binding.gyp based on available source files
+ */
+async function updateBindingGyp(jsDir: string): Promise<void> {
+  const bindingGypPath = join(jsDir, 'binding.gyp');
+  const scannerPath = join(jsDir, 'src', 'scanner.c');
+  
+  if (existsSync(bindingGypPath)) {
+    let bindingGyp = JSON.parse(readFileSync(bindingGypPath, 'utf-8'));
+    
+    // Add scanner.c if it exists
+    if (existsSync(scannerPath)) {
+      const target = bindingGyp.targets[0];
+      if (!target.sources.includes('src/scanner.c')) {
+        target.sources.push('src/scanner.c');
+        console.log(chalk.gray(`   Added scanner.c to build`));
+      }
+    } else {
+      console.log(chalk.gray(`   No scanner.c found, skipping`));
+    }
+    
+    writeFileSync(bindingGypPath, JSON.stringify(bindingGyp, null, 2));
+  }
+}
+
+/**
+ * Update package.json in JS package
+ */
+async function updateJSPackageJson(jsDir: string): Promise<void> {
+  const projectName = getProjectName();
+  const packageJsonPath = join(jsDir, 'package.json');
+  
+  if (existsSync(packageJsonPath)) {
+    let packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
+    
+    // Update name and description
+    packageJson.name = `tree-sitter-${projectName}`;
+    packageJson.description = `Tree-sitter parser for ${projectName}`;
+    
+    // Update keywords
+    if (packageJson.keywords && Array.isArray(packageJson.keywords)) {
+      packageJson.keywords = packageJson.keywords.map((keyword: string) => 
+        keyword === '__DSL_NAME__' ? projectName : keyword
+      );
+    }
+    
+    writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
+  }
+}
diff --git a/tree-sitter/dsk/dsk-cli/src/commands/dev.ts b/tree-sitter/dsk/dsk-cli/src/commands/dev.ts
new file mode 100644
index 0000000..92b2867
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/commands/dev.ts
@@ -0,0 +1,105 @@
+/**
+ * Dev Command - Watch grammar.js and rebuild/test on change
+ */
+
+import { Command } from 'commander';
+import chokidar from 'chokidar';
+import chalk from 'chalk';
+import { existsSync } from 'fs';
+import { execa } from 'execa';
+
+/**
+ * Create the dev command
+ */
+export function createDevCommand(): Command {
+  const devCommand = new Command('dev');
+
+  devCommand
+    .description('Watch grammar.js and run build + test on changes')
+    .option('-v, --verbose', 'Show detailed build output')
+    .option('--quiet', 'Suppress non-error logs')
+    .option('--debounce <ms>', 'Debounce delay in milliseconds', '150')
+    .action(async (options) => {
+      if (!existsSync('grammar.js')) {
+        console.error(chalk.red('โŒ No grammar.js found. Are you in a DSL project directory?'));
+        process.exit(1);
+      }
+
+      const verbose: boolean = Boolean(options.verbose);
+      const quiet: boolean = Boolean(options.quiet);
+      const debounceMs: number = Number.parseInt(options.debounce, 10) || 150;
+
+      if (!quiet) {
+        console.log(chalk.blue('๐Ÿ‘€ Watching grammar.js for changes...'));
+      }
+
+      // Initial build + test
+      await runBuildAndTest({ verbose, quiet });
+
+      // Watcher with debounced rebuilds
+      const watcher = chokidar.watch('grammar.js', { ignoreInitial: true });
+      let isRunning = false;
+      let rerunRequested = false;
+      let debounceTimer: NodeJS.Timeout | null = null;
+
+      const runOnce = async () => {
+        if (isRunning) {
+          rerunRequested = true;
+          return;
+        }
+        isRunning = true;
+        if (!quiet) {
+          console.log(chalk.yellow('โ†ป Change detected. Rebuilding...'));
+        }
+        try {
+          await runBuildAndTest({ verbose, quiet });
+          if (!quiet) {
+            console.log(chalk.green('โœ… Rebuild and tests completed.'));
+          }
+        } catch (e) {
+          // Errors already printed by build/test
+        } finally {
+          isRunning = false;
+          if (rerunRequested) {
+            rerunRequested = false;
+            runOnce();
+          }
+        }
+      };
+
+      const debouncedTrigger = () => {
+        if (debounceTimer) clearTimeout(debounceTimer);
+        debounceTimer = setTimeout(runOnce, debounceMs);
+      };
+
+      watcher.on('change', debouncedTrigger);
+    });
+
+  return devCommand;
+}
+
+async function runBuildAndTest(opts: { verbose?: boolean; quiet?: boolean }): Promise<void> {
+  const { verbose, quiet } = opts;
+  if (!quiet) {
+    console.log(chalk.blue('๐Ÿ—๏ธ  Building...'));
+  }
+  try {
+    const buildArgs = ['build', ...(verbose ? ['--verbose'] : [])];
+    await execa('dsk', buildArgs, { stdio: 'inherit' });
+  } catch (error: any) {
+    console.error(chalk.red('โŒ Build failed. Fix errors and save again.'));
+    throw error;
+  }
+
+  if (!quiet) {
+    console.log(chalk.blue('๐Ÿงช Testing...'));
+  }
+  try {
+    await execa('dsk', ['test'], { stdio: 'inherit' });
+  } catch (error: any) {
+    console.error(chalk.red('โŒ Tests failed. Fix tests and save again.'));
+    throw error;
+  }
+}
+
+
diff --git a/tree-sitter/dsk/dsk-cli/src/commands/highlight.ts b/tree-sitter/dsk/dsk-cli/src/commands/highlight.ts
new file mode 100644
index 0000000..fd0d419
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/commands/highlight.ts
@@ -0,0 +1,141 @@
+/**
+ * Highlight Command - Generate Tree-sitter highlights and editor scaffolds
+ */
+
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
+import { join } from 'path';
+
+/**
+ * Create the highlight command
+ */
+export function createHighlightCommand(): Command {
+  const highlightCommand = new Command('highlight');
+
+  highlightCommand
+    .description('Generate Tree-sitter highlights and editor scaffolds (tree-sitter, neovim, emacs, vscode)')
+    .action(async () => {
+      if (!existsSync('grammar.js')) {
+        console.error(chalk.red('โŒ No grammar.js found. Are you in a DSL project directory?'));
+        process.exit(1);
+      }
+
+      const languageName = getProjectName();
+
+      // Tree-sitter highlights
+      const tsOutDir = 'generated/editors/tree-sitter';
+      mkdirSync(tsOutDir, { recursive: true });
+      const highlights = `
+; Minimal highlights scaffold. Extend as needed.
+
+; Comments
+(comment) @comment
+
+; Strings
+(string) @string
+
+; Numbers
+(number) @number
+
+; Keywords (example)
+[("if") ("else") ("let") ("function")] @keyword
+`;
+      const tsFile = join(tsOutDir, 'highlights.scm');
+      writeFileSync(tsFile, highlights.trim() + '\n', 'utf-8');
+      console.log(chalk.green(`โœ… Generated ${tsFile}`));
+
+      // Neovim instructions
+      const nvimDir = 'generated/editors/neovim';
+      mkdirSync(nvimDir, { recursive: true });
+      const nvimMd = `# Neovim setup for ${languageName}
+
+1. Copy queries to your runtimepath: queries/${languageName}/highlights.scm
+2. Configure nvim-treesitter:
+
+\`\`\`lua
+require('nvim-treesitter.configs').setup({
+  ensure_installed = {},
+  highlight = { enable = true },
+})
+\`\`\`
+`;
+      writeFileSync(join(nvimDir, 'setup-instructions.md'), nvimMd, 'utf-8');
+      console.log(chalk.green(`โœ… Generated ${join(nvimDir, 'setup-instructions.md')}`));
+
+      // Emacs major mode (minimal)
+      const emacsDir = 'generated/editors/emacs';
+      mkdirSync(emacsDir, { recursive: true });
+      const emacsEl = `;;; ${languageName}-mode.el --- ${languageName} mode -*- lexical-binding: t; -*-
+
+(require 'treesit)
+
+(define-derived-mode ${languageName}-mode prog-mode "${languageName}"
+  "Major mode for ${languageName} using Tree-sitter."
+  (when (treesit-ready-p '${languageName})
+    (treesit-parser-create '${languageName})))
+
+(add-to-list 'auto-mode-alist '("\\.${languageName}$" . ${languageName}-mode))
+
+(provide '${languageName}-mode)
+`;
+      writeFileSync(join(emacsDir, `${languageName}-mode.el`), emacsEl, 'utf-8');
+      console.log(chalk.green(`โœ… Generated ${join(emacsDir, `${languageName}-mode.el`)}`));
+
+      // VS Code: TextMate grammar + language configuration (basic placeholders)
+      const vscodeSyntaxDir = 'generated/editors/vscode/syntaxes';
+      const vscodeDir = 'generated/editors/vscode';
+      mkdirSync(vscodeSyntaxDir, { recursive: true });
+      mkdirSync(vscodeDir, { recursive: true });
+      const scope = `source.${languageName}`;
+      const tmLanguage = {
+        name: languageName,
+        scopeName: scope,
+        patterns: [
+          { include: '#comment' },
+          { include: '#string' },
+          { include: '#number' },
+          { include: '#keyword' }
+        ],
+        repository: {
+          comment: { patterns: [{ name: 'comment.line.double-slash', match: '//.*$' }] },
+          string: { patterns: [{ name: 'string.quoted.double', begin: '"', end: '"' }] },
+          number: { patterns: [{ name: 'constant.numeric', match: '-?\\b[0-9]+(\\.[0-9]+)?\\b' }] },
+          keyword: { patterns: [{ name: 'keyword.control', match: '\\b(if|else|let|function)\\b' }] }
+        }
+      } as const;
+      writeFileSync(join(vscodeSyntaxDir, `${languageName}.tmLanguage.json`), JSON.stringify(tmLanguage, null, 2));
+      const langConfig = {
+        comments: { lineComment: '//' },
+        brackets: [["{","}"],["[","]"],["(",")"]],
+        autoClosingPairs: [
+          { open: '"', close: '"' },
+          { open: '{', close: '}' },
+          { open: '(', close: ')' },
+          { open: '[', close: ']' }
+        ],
+        surroundingPairs: [
+          { open: '"', close: '"' },
+          { open: '{', close: '}' },
+          { open: '(', close: ')' },
+          { open: '[', close: ']' }
+        ]
+      };
+      writeFileSync(join(vscodeDir, 'language-configuration.json'), JSON.stringify(langConfig, null, 2));
+      console.log(chalk.green(`โœ… Generated VS Code syntax and configuration`));
+    });
+
+  return highlightCommand;
+}
+
+function getProjectName(): string {
+  try {
+    const grammarContent = readFileSync('grammar.js', 'utf-8');
+    const nameMatch = grammarContent.match(/name:\s*['"]([^'"]+)['"]/);
+    if (nameMatch) return nameMatch[1];
+  } catch {}
+  const parts = process.cwd().split(/[\\/]/);
+  return parts[parts.length - 1] || 'dsl';
+}
+
+
diff --git a/tree-sitter/dsk/dsk-cli/src/commands/new.ts b/tree-sitter/dsk/dsk-cli/src/commands/new.ts
new file mode 100644
index 0000000..1829a21
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/commands/new.ts
@@ -0,0 +1,485 @@
+/**
+ * New Command - Interactive Grammar Scaffolding
+ * 
+ * Creates a new DSL project with paradigm-aware grammar generation
+ */
+
+import { Command } from 'commander';
+import inquirer from 'inquirer';
+import chalk from 'chalk';
+import { existsSync, mkdirSync, writeFileSync } from 'fs';
+import { join, dirname } from 'path';
+import { fileURLToPath } from 'url';
+import { inferPattern, validatePattern, generateCustomPattern } from '../utils/inference.js';
+import { generateGrammar, generateGrammarFile } from '../utils/grammar-generator.js';
+import { processTemplate } from '../utils/template-processor.js';
+
+// Type definitions for our interactive flow
+export interface LanguageArchitecture {
+  name: string;
+  purpose: string;
+  paradigm: 'functional' | 'object-oriented' | 'procedural' | 'declarative' | 'mixed';
+  dataPhilosophy: 'immutable' | 'mutable' | 'mixed';
+}
+
+export interface LanguageFeatures {
+  controlFlow: string[];
+  dataStructures: string[];
+  functionTypes: string[];
+}
+
+export interface LanguageSyntax {
+  comments: { type: string; pattern: string };
+  identifiers: { pattern: string; examples: string[] };
+  numbers: { pattern: string; examples: string[] };
+  strings: { pattern: string; examples: string[] };
+  variables: { keyword: string; operator: string; terminator: string; example: string };
+  paradigmExamples: { [key: string]: string };
+}
+
+/**
+ * Create the new command
+ */
+export function createNewCommand(): Command {
+  const newCommand = new Command('new');
+  
+  newCommand
+    .description('Create a new DSL project')
+    .argument('<name>', 'Name of the DSL project')
+    .option('-i, --interactive', 'Use interactive grammar scaffolding')
+    .option('-t, --template <template>', 'Use a specific template (default: basic)')
+    .action(async (name: string, options) => {
+      console.log(chalk.blue('๐Ÿš€ Creating DSL project:'), chalk.bold(name));
+      
+      if (options.interactive) {
+        await runInteractiveFlow(name);
+      } else {
+        await createBasicProject(name, options.template || 'basic');
+      }
+    });
+
+  return newCommand;
+}
+
+/**
+ * Run the interactive grammar scaffolding flow
+ */
+async function runInteractiveFlow(projectName: string): Promise<void> {
+  console.log();
+  console.log(chalk.green('๐ŸŽฏ Welcome to the DSK Grammar Scaffolder!'));
+  console.log(chalk.gray('I\'ll ask you a few questions about your new language.'));
+  console.log(chalk.gray('Just provide examples, and I\'ll build a starter grammar for you.'));
+  console.log();
+
+  try {
+    // Phase A: Language Architecture & Paradigm
+    console.log(chalk.blue('๐Ÿ“‹ Phase A: Language Architecture & Paradigm'));
+    const architecture = await gatherArchitecture(projectName);
+    console.log(chalk.green('โœ”'), 'Architecture defined');
+
+    // Phase B: Core Language Features  
+    console.log();
+    console.log(chalk.blue('๐Ÿ”ง Phase B: Core Language Features'));
+    const features = await gatherFeatures(architecture);
+    console.log(chalk.green('โœ”'), 'Features defined');
+
+    // Phase C: Syntax & Tokens
+    console.log();
+    console.log(chalk.blue('๐Ÿ”ค Phase C: Syntax & Tokens'));
+    const syntax = await gatherSyntax(architecture, features);
+    console.log(chalk.green('โœ”'), 'Syntax defined');
+
+    // Generate the project
+    console.log();
+    console.log(chalk.blue('๐Ÿ—๏ธ  Generating project...'));
+    await generateProject(projectName, architecture, features, syntax);
+    
+    // Success message
+    console.log();
+    console.log(chalk.green('๐ŸŽ‰ All done!'));
+    console.log(`Your ${chalk.bold('grammar.js')} has been created with rules for:`);
+    console.log(`  ${chalk.gray('โ€ข')} Comments, Identifiers, Numbers, Strings`);
+    console.log(`  ${chalk.gray('โ€ข')} Variable Declarations`);
+    console.log(`  ${chalk.gray('โ€ข')} ${architecture.paradigm} language constructs`);
+    console.log();
+    console.log(chalk.yellow('To start editing and testing, run:'));
+    console.log(`  ${chalk.cyan('cd')} ${projectName}`);
+    console.log(`  ${chalk.cyan('dsk dev')}`);
+    console.log();
+
+  } catch (error) {
+    console.error(chalk.red('โŒ Error during interactive flow:'), error);
+    process.exit(1);
+  }
+}
+
+/**
+ * Phase A: Gather language architecture information
+ */
+async function gatherArchitecture(projectName: string): Promise<LanguageArchitecture> {
+  const purposeAnswer = await inquirer.prompt({
+    type: 'input',
+    name: 'purpose',
+    message: 'What is your language designed for? (e.g., configuration, scripting, domain modeling)',
+    default: 'General purpose scripting'
+  });
+
+  const paradigmAnswer = await inquirer.prompt({
+    type: 'list',
+    name: 'paradigm',
+    message: 'What programming style does your language follow?',
+    choices: [
+      { name: 'Functional (immutable data, functions as first-class)', value: 'functional' },
+      { name: 'Object-Oriented (classes, inheritance, methods)', value: 'object-oriented' },
+      { name: 'Procedural (step-by-step instructions, functions)', value: 'procedural' },
+      { name: 'Declarative (describe what, not how)', value: 'declarative' },
+      { name: 'Mixed (combination of above)', value: 'mixed' }
+    ],
+    default: 'procedural'
+  });
+
+  const dataAnswer = await inquirer.prompt({
+    type: 'list',
+    name: 'dataPhilosophy',
+    message: 'How does your language handle data?',
+    choices: [
+      { name: 'Immutable by default (functional style)', value: 'immutable' },
+      { name: 'Mutable variables (imperative style)', value: 'mutable' },
+      { name: 'Mixed approach', value: 'mixed' }
+    ],
+    default: 'mutable'
+  });
+
+  return {
+    name: projectName,
+    purpose: purposeAnswer.purpose,
+    paradigm: paradigmAnswer.paradigm,
+    dataPhilosophy: dataAnswer.dataPhilosophy
+  };
+}
+
+/**
+ * Phase B: Gather core language features
+ */
+async function gatherFeatures(architecture: LanguageArchitecture): Promise<LanguageFeatures> {
+  const controlFlowAnswer = await inquirer.prompt({
+    type: 'checkbox',
+    name: 'controlFlow',
+    message: 'What control structures does your language support?',
+    choices: [
+      { name: 'Conditionals (if/else)', value: 'conditionals', checked: true },
+      { name: 'Loops (for, while)', value: 'loops' },
+      { name: 'Pattern matching', value: 'pattern_matching' },
+      { name: 'Exception handling (try/catch)', value: 'exceptions' },
+      { name: 'Early returns/breaks', value: 'early_returns' }
+    ]
+  });
+
+  const dataStructuresAnswer = await inquirer.prompt({
+    type: 'checkbox', 
+    name: 'dataStructures',
+    message: 'What built-in data structures does your language have?',
+    choices: [
+      { name: 'Arrays/Lists: [1, 2, 3]', value: 'arrays', checked: true },
+      { name: 'Objects/Maps: {key: value}', value: 'objects' },
+      { name: 'Tuples: (a, b, c)', value: 'tuples' },
+      { name: 'Sets: {1, 2, 3}', value: 'sets' }
+    ]
+  });
+
+  const functionTypesAnswer = await inquirer.prompt({
+    type: 'checkbox',
+    name: 'functionTypes',
+    message: 'How are functions defined in your language?',
+    choices: [
+      { name: 'Named functions: function foo() { ... }', value: 'named', checked: true },
+      { name: 'Anonymous functions: (x) => x + 1', value: 'anonymous' },
+      { name: 'Methods on objects: obj.method()', value: 'methods' },
+      { name: 'First-class functions (can be passed around)', value: 'first_class' }
+    ]
+  });
+
+  return {
+    controlFlow: controlFlowAnswer.controlFlow,
+    dataStructures: dataStructuresAnswer.dataStructures,
+    functionTypes: functionTypesAnswer.functionTypes
+  };
+}
+
+/**
+ * Phase C: Gather syntax and token information
+ */
+async function gatherSyntax(architecture: LanguageArchitecture, features: LanguageFeatures): Promise<LanguageSyntax> {
+  const syntax: Partial<LanguageSyntax> = {};
+
+  // Comments
+  const commentAnswer = await inquirer.prompt({
+    type: 'input',
+    name: 'comment',
+    message: 'How do you write a single-line comment? (e.g., //, #, --, ;)',
+    default: '//'
+  });
+
+  const commentPrefix = String(commentAnswer.comment).trim().split(/\s+/)[0];
+  syntax.comments = {
+    type: 'line_comment',
+    pattern: commentPrefix
+  };
+
+  // Identifiers with inference
+  syntax.identifiers = await gatherTokenWithInference(
+    'identifier',
+    'Provide 3-5 examples of valid identifiers',
+    'Now provide 2-3 examples of invalid identifiers (optional)',
+    ['myVar', 'userName', '_private']
+  );
+
+  // Numbers with inference
+  syntax.numbers = await gatherTokenWithInference(
+    'number',
+    'Provide examples of numbers in your language',
+    'Provide examples of invalid numbers (optional)',
+    ['42', '3.14', '-17']
+  );
+
+  // Strings with inference (treat input as a single example, not space-split)
+  const stringValid = await inquirer.prompt({
+    type: 'input',
+    name: 'examples',
+    message: 'Provide an example of a string literal',
+    default: '"hello world"'
+  });
+  const stringInvalid = await inquirer.prompt({
+    type: 'input',
+    name: 'examples',
+    message: 'Provide examples of invalid strings (optional)',
+    default: ''
+  });
+  const stringValidExamples = stringValid.examples ? [String(stringValid.examples)] : ['"hello world"'];
+  const stringInvalidExamples = stringInvalid.examples ? [String(stringInvalid.examples)] : [];
+  const stringResult = inferPattern(stringValidExamples, stringInvalidExamples);
+  if (stringResult.pattern && stringResult.confidence > 0.7) {
+    syntax.strings = { pattern: stringResult.pattern.regex.source, examples: stringValidExamples };
+  } else {
+    syntax.strings = { pattern: '"[^"]*"', examples: stringValidExamples };
+  }
+
+  // Variable declarations
+  const varAnswer = await inquirer.prompt({
+    type: 'input',
+    name: 'example',
+    message: 'Show me how you declare a variable x with value 42 (helps identify keywords)',
+    default: 'let x = 42;'
+  });
+
+  const varParts = parseVariableDeclaration(varAnswer.example);
+  syntax.variables = varParts;
+
+  // Paradigm-specific examples
+  syntax.paradigmExamples = {};
+  
+  if (architecture.paradigm === 'object-oriented' || architecture.paradigm === 'mixed') {
+    const classAnswer = await inquirer.prompt({
+      type: 'input',
+      name: 'classExample',
+      message: 'Show me how you define a class with a method',
+      default: 'class Person { getName() { return this.name; } }'
+    });
+    syntax.paradigmExamples.class = classAnswer.classExample;
+  }
+
+  if (architecture.paradigm === 'functional' || architecture.paradigm === 'mixed') {
+    const funcAnswer = await inquirer.prompt({
+      type: 'input',
+      name: 'funcExample', 
+      message: 'Show me how you define and call a function',
+      default: 'function add(a, b) { return a + b; }'
+    });
+    syntax.paradigmExamples.function = funcAnswer.funcExample;
+  }
+
+  if (architecture.paradigm === 'declarative') {
+    const ruleAnswer = await inquirer.prompt({
+      type: 'input',
+      name: 'ruleExample',
+      message: 'Show me a typical declaration/rule in your language',
+      default: 'rule user_can_edit when user.role == "admin"'
+    });
+    syntax.paradigmExamples.rule = ruleAnswer.ruleExample;
+  }
+
+  return syntax as LanguageSyntax;
+}
+
+/**
+ * Gather token information with automatic pattern inference
+ */
+async function gatherTokenWithInference(
+  tokenType: string,
+  validPrompt: string,
+  invalidPrompt: string,
+  defaultExamples: string[]
+): Promise<{ pattern: string; examples: string[] }> {
+  
+  // Get valid examples
+  const validAnswer = await inquirer.prompt({
+    type: 'input',
+    name: 'examples',
+    message: `${validPrompt} (separate with spaces)`,
+    default: defaultExamples.join(' ')
+  });
+
+  const validExamples = validAnswer.examples.split(/\s+/).filter((ex: string) => ex.length > 0);
+
+  // Get invalid examples (optional)
+  const invalidAnswer = await inquirer.prompt({
+    type: 'input',
+    name: 'examples',
+    message: `${invalidPrompt} (separate with spaces, or press Enter to skip)`,
+    default: ''
+  });
+
+  const invalidExamples = invalidAnswer.examples 
+    ? invalidAnswer.examples.split(/\s+/).filter((ex: string) => ex.length > 0)
+    : [];
+
+  // Try inference
+  const result = inferPattern(validExamples, invalidExamples);
+  
+  if (result.pattern && result.confidence > 0.7) {
+    // Successful inference - confirm with user
+    const confirmAnswer = await inquirer.prompt({
+      type: 'confirm',
+      name: 'confirmed',
+      message: `I've inferred the pattern for ${tokenType} as: ${chalk.cyan(result.pattern.regex.source)}. Does this look correct?`,
+      default: true
+    });
+
+    if (confirmAnswer.confirmed) {
+      return {
+        pattern: result.pattern.regex.source,
+        examples: validExamples
+      };
+    }
+  }
+
+  // Inference failed or user rejected - offer alternatives
+  console.log(chalk.yellow(`I couldn't determine a reliable pattern from those examples.`));
+  
+  const fallbackAnswer = await inquirer.prompt({
+    type: 'list',
+    name: 'option',
+    message: 'How would you like to proceed?',
+    choices: [
+      { name: 'Provide a custom regular expression', value: 'custom_regex' },
+      { name: 'Generate a simple pattern from examples', value: 'simple_pattern' },
+      { name: 'Try different examples', value: 'retry' }
+    ]
+  });
+
+  if (fallbackAnswer.option === 'custom_regex') {
+    const regexAnswer = await inquirer.prompt({
+      type: 'input',
+      name: 'regex',
+      message: `Enter a regular expression for ${tokenType}:`,
+      validate: (input: string) => {
+        const validation = validatePattern(input, validExamples, invalidExamples);
+        return validation.isValid || validation.errors.join(', ');
+      }
+    });
+    
+    return {
+      pattern: regexAnswer.regex,
+      examples: validExamples
+    };
+  }
+
+  if (fallbackAnswer.option === 'simple_pattern') {
+    const simplePattern = generateCustomPattern(validExamples, invalidExamples);
+    return {
+      pattern: simplePattern,
+      examples: validExamples
+    };
+  }
+
+  // Retry with different examples
+  return await gatherTokenWithInference(tokenType, validPrompt, invalidPrompt, defaultExamples);
+}
+
+/**
+ * Parse variable declaration to extract components
+ */
+function parseVariableDeclaration(example: string): { keyword: string; operator: string; terminator: string; example: string } {
+  // Simple parsing - look for common patterns
+  const patterns = [
+    /^(\w+)\s+(\w+)\s*([=:])\s*[^;]*([;]?)/, // let x = 42;
+    /^(\w+)\s*([=:])\s*[^;]*([;]?)/, // x = 42;
+  ];
+
+  for (const pattern of patterns) {
+    const match = example.match(pattern);
+    if (match) {
+      return {
+        keyword: match[1] || '',
+        operator: match[3] || '=',
+        terminator: match[4] || ';',
+        example
+      };
+    }
+  }
+
+  // Fallback
+  return {
+    keyword: 'let',
+    operator: '=', 
+    terminator: ';',
+    example
+  };
+}
+
+/**
+ * Generate the project with collected information
+ */
+async function generateProject(
+  name: string,
+  architecture: LanguageArchitecture,
+  features: LanguageFeatures,
+  syntax: LanguageSyntax
+): Promise<void> {
+  // Create project directory
+  if (existsSync(name)) {
+    throw new Error(`Directory ${name} already exists`);
+  }
+
+  mkdirSync(name, { recursive: true });
+
+  // Generate grammar.js file
+  console.log(chalk.gray('๐Ÿ”ง Generating grammar.js...'));
+  const grammar = generateGrammar(architecture, features, syntax);
+  const grammarContent = generateGrammarFile(grammar);
+  writeFileSync(join(name, 'grammar.js'), grammarContent, 'utf-8');
+
+  // Process template files
+  console.log(chalk.gray('๐Ÿ“‹ Creating project structure...'));
+  const __filename = fileURLToPath(import.meta.url);
+  const __dirname = dirname(__filename);
+  const templateDir = join(__dirname, '..', '..', 'templates', 'default');
+  
+  const templateContext = {
+    architecture,
+    features,
+    syntax
+  };
+  
+  processTemplate(templateDir, name, templateContext);
+  
+  console.log(chalk.gray(`๐Ÿ“ Created project directory: ${name}/`));
+  console.log(chalk.green('โœจ Project generated successfully!'));
+}
+
+/**
+ * Create a basic project without interactive flow
+ */
+async function createBasicProject(name: string, template: string): Promise<void> {
+  console.log(chalk.yellow(`๐Ÿšง Basic project creation (template: ${template}) coming soon!`));
+}
diff --git a/tree-sitter/dsk/dsk-cli/src/commands/package.ts b/tree-sitter/dsk/dsk-cli/src/commands/package.ts
new file mode 100644
index 0000000..515c2ce
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/commands/package.ts
@@ -0,0 +1,66 @@
+/**
+ * Package Command - Create distributable artifacts for C and JS outputs
+ */
+
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
+import { join } from 'path';
+import { execa } from 'execa';
+
+/**
+ * Create the package command
+ */
+export function createPackageCommand(): Command {
+  const pkgCommand = new Command('package');
+
+  pkgCommand
+    .description('Package C and JS artifacts into distributable archives')
+    .action(async () => {
+      if (!existsSync('grammar.js')) {
+        console.error(chalk.red('โŒ No grammar.js found. Are you in a DSL project directory?'));
+        process.exit(1);
+      }
+
+      console.log(chalk.blue('๐Ÿ“ฆ Packaging artifacts...'));
+
+      // Ensure build is up to date
+      await execa('dsk', ['build'], { stdio: 'inherit' });
+
+      const distDir = 'dist';
+      mkdirSync(distDir, { recursive: true });
+
+      // Zip C outputs (simple tar.gz using system tar to avoid extra deps)
+      const cDir = 'generated/c';
+      if (existsSync(cDir)) {
+        const cArchive = join(distDir, 'c-artifacts.tar.gz');
+        await execa('tar', ['-czf', cArchive, '-C', 'generated', 'c'], { stdio: 'inherit' });
+        console.log(chalk.green(`โœ… C artifacts: ${cArchive}`));
+      }
+
+      // Pack JS package
+      const jsDir = 'generated/js';
+      if (existsSync(jsDir)) {
+        // Prefer bun pack, fallback to npm pack
+        let pkgPath = '';
+        try {
+          const { stdout } = await execa('bun', ['pack'], { cwd: jsDir });
+          pkgPath = stdout.trim();
+        } catch {
+          const { stdout } = await execa('npm', ['pack'], { cwd: jsDir });
+          pkgPath = stdout.trim();
+        }
+        const fileName = pkgPath.split(/\s|\n/).pop() as string;
+        const srcPath = join(jsDir, fileName);
+        const destPath = join(distDir, fileName);
+        await execa('bash', ['-lc', `cp ${JSON.stringify(srcPath)} ${JSON.stringify(destPath)}`]);
+        console.log(chalk.green(`โœ… JS package: ${destPath}`));
+      }
+
+      console.log(chalk.blue('๐ŸŽ‰ Packaging complete.'));
+    });
+
+  return pkgCommand;
+}
+
+
diff --git a/tree-sitter/dsk/dsk-cli/src/commands/self.ts b/tree-sitter/dsk/dsk-cli/src/commands/self.ts
new file mode 100644
index 0000000..2b43fd6
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/commands/self.ts
@@ -0,0 +1,71 @@
+/**
+ * Self Packaging Command - Build and package the dsk CLI for distribution
+ */
+
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { execa } from 'execa';
+import { existsSync, mkdirSync, readFileSync } from 'fs';
+import { dirname, join } from 'path';
+import { fileURLToPath } from 'url';
+
+/**
+ * Create the self:package command
+ */
+export function createSelfPackageCommand(): Command {
+  const cmd = new Command('self:package');
+
+  cmd
+    .description('Build and package the dsk CLI into a .tgz for distribution')
+    .option('-v, --verbose', 'Show detailed build output')
+    .action(async (options) => {
+      const projectRoot = resolveProjectRoot();
+      if (!existsSync(join(projectRoot, 'package.json'))) {
+        console.error(chalk.red('โŒ Could not locate package.json for dsk-cli'));
+        process.exit(1);
+      }
+
+      const pkg = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf-8'));
+      console.log(chalk.blue(`๐Ÿ“ฆ Packaging ${pkg.name}@${pkg.version}`));
+
+      // 1) Build TypeScript โ†’ dist
+      console.log(chalk.blue('๐Ÿ—๏ธ  Building CLI...'));
+      await execa('bun', ['x', 'tsc'], { cwd: projectRoot, stdio: options.verbose ? 'inherit' : 'inherit' });
+
+      // 2) Pack npm tarball using bun pack (fallback to npm pack)
+      console.log(chalk.blue('๐Ÿงฐ Creating package tarball...'));
+      let tgzName = '';
+      try {
+        const { stdout } = await execa('bun', ['pack'], { cwd: projectRoot });
+        tgzName = stdout.trim().split(/\s|\n/).pop() || '';
+      } catch {
+        const { stdout } = await execa('npm', ['pack'], { cwd: projectRoot });
+        tgzName = stdout.trim().split(/\s|\n/).pop() || '';
+      }
+
+      if (!tgzName) {
+        console.error(chalk.red('โŒ Failed to determine generated package filename'));
+        process.exit(1);
+      }
+
+      const releaseDir = join(projectRoot, 'release');
+      mkdirSync(releaseDir, { recursive: true });
+      const src = join(projectRoot, tgzName);
+      const dest = join(releaseDir, tgzName);
+      await execa('bash', ['-lc', `mv -f ${JSON.stringify(src)} ${JSON.stringify(dest)}`]);
+
+      console.log(chalk.green(`โœ… Created ${dest}`));
+    });
+
+  return cmd;
+}
+
+function resolveProjectRoot(): string {
+  const __filename = fileURLToPath(import.meta.url);
+  const __dirname = dirname(__filename);
+  // When compiled, this file lives under dist/commands. Project root is two levels up.
+  const candidate = join(__dirname, '..', '..');
+  return candidate;
+}
+
+
diff --git a/tree-sitter/dsk/dsk-cli/src/commands/test.ts b/tree-sitter/dsk/dsk-cli/src/commands/test.ts
new file mode 100644
index 0000000..694acc7
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/commands/test.ts
@@ -0,0 +1,50 @@
+/**
+ * Test Command - Wrapper around `tree-sitter test`
+ *
+ * Streams test output directly to the console.
+ */
+
+import { Command } from 'commander';
+import { execa } from 'execa';
+import chalk from 'chalk';
+import { existsSync } from 'fs';
+
+/**
+ * Create the test command
+ */
+export function createTestCommand(): Command {
+  const testCommand = new Command('test');
+
+  testCommand
+    .description('Run tree-sitter tests and stream output')
+    .allowExcessArguments(true)
+    .option('-u, --update', 'Update expected outputs (snapshots)')
+    .option('-f, --filter <regex>', 'Only run tests whose descriptions match the regex')
+    .option('--cwd <dir>', 'Run tests with a different working directory')
+    .option('-v, --verbose', 'Show verbose output (passes through to tree-sitter)')
+    .argument('[patterns...]', 'Optional test patterns (filenames or test names)')
+    .action(async (patterns: string[], options) => {
+      if (!existsSync('grammar.js')) {
+        console.error(chalk.red('โŒ No grammar.js found. Are you in a DSL project directory?'));
+        process.exit(1);
+      }
+
+      try {
+        console.log(chalk.blue('๐Ÿงช Running tests...'));
+        const args = ['test'];
+        if (options.update) args.push('-u');
+        if (options.filter) args.push('-f', String(options.filter));
+        if (options.verbose) args.push('--verbose');
+        args.push(...patterns);
+        await execa('tree-sitter', args, { stdio: 'inherit', cwd: options.cwd || process.cwd() });
+      } catch (error: any) {
+        const message = error?.message || error || 'Unknown error';
+        console.error(chalk.red('โŒ Tests failed:'), message);
+        process.exit(1);
+      }
+    });
+
+  return testCommand;
+}
+
+
diff --git a/tree-sitter/dsk/dsk-cli/src/index.ts b/tree-sitter/dsk/dsk-cli/src/index.ts
new file mode 100644
index 0000000..42c75c5
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/index.ts
@@ -0,0 +1,80 @@
+#!/usr/bin/env node
+
+/**
+ * DSK - DSL Development Kit
+ * Command-line tool for creating Domain-Specific Languages with Tree-sitter
+ */
+
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { readFileSync } from 'fs';
+import { fileURLToPath } from 'url';
+import { dirname, join } from 'path';
+
+// Get package.json for version info
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+const packagePath = join(__dirname, '..', 'package.json');
+const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
+
+const program = new Command();
+
+// Configure main command
+program
+  .name('dsk')
+  .description('DSL Development Kit - Streamline Domain-Specific Language creation')
+  .version(packageJson.version);
+
+// Welcome message for help
+program.on('--help', () => {
+  console.log('');
+  console.log(chalk.blue('Getting Started:'));
+  console.log('  $ dsk new my-language --interactive');
+  console.log('  $ cd my-language');
+  console.log('  $ dsk dev');
+  console.log('');
+  console.log(chalk.yellow('Learn more at: https://github.com/your-org/dsk'));
+});
+
+// Import and register commands
+import { createNewCommand } from './commands/new.js';
+import { createBuildCommand } from './commands/build.js';
+import { createTestCommand } from './commands/test.js';
+import { createDevCommand } from './commands/dev.js';
+import { createHighlightCommand } from './commands/highlight.js';
+import { createPackageCommand } from './commands/package.js';
+import { createSelfPackageCommand } from './commands/self.js';
+
+const newCommand = createNewCommand();
+const buildCommand = createBuildCommand();
+const testCommand = createTestCommand();
+const devCommand = createDevCommand();
+const highlightCommand = createHighlightCommand();
+const packageCommand = createPackageCommand();
+const selfPackageCommand = createSelfPackageCommand();
+
+program.addCommand(newCommand);
+program.addCommand(buildCommand);
+program.addCommand(testCommand);
+program.addCommand(devCommand);
+program.addCommand(highlightCommand);
+program.addCommand(packageCommand);
+program.addCommand(selfPackageCommand);
+
+// TODO: Import remaining commands
+// import { devCommand } from './commands/dev.js';
+// import { testCommand } from './commands/test.js';
+// import { highlightCommand } from './commands/highlight.js';
+// import { packageCommand } from './commands/package.js';
+
+// program.addCommand(devCommand);
+// program.addCommand(testCommand);
+// program.addCommand(highlightCommand);
+// program.addCommand(packageCommand);
+
+
+
+// legacy placeholder removed; real dev command registered above
+
+// Parse command line arguments
+program.parse();
diff --git a/tree-sitter/dsk/dsk-cli/src/utils/grammar-generator.ts b/tree-sitter/dsk/dsk-cli/src/utils/grammar-generator.ts
new file mode 100644
index 0000000..1b40eff
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/utils/grammar-generator.ts
@@ -0,0 +1,466 @@
+/**
+ * Grammar Generator
+ * 
+ * Converts collected user information into Tree-sitter grammar.js files
+ * with paradigm-aware rule generation
+ */
+
+import { LanguageArchitecture, LanguageFeatures, LanguageSyntax } from '../commands/new.js';
+
+export interface GrammarRule {
+  name: string;
+  definition: string;
+  comment?: string;
+}
+
+export interface GeneratedGrammar {
+  name: string;
+  rules: GrammarRule[];
+  extras: string[];
+  conflicts: string[][];
+  precedences: string[][];
+  word?: string;
+}
+
+/**
+ * Generate a complete Tree-sitter grammar from user specifications
+ */
+export function generateGrammar(
+  architecture: LanguageArchitecture,
+  features: LanguageFeatures,
+  syntax: LanguageSyntax
+): GeneratedGrammar {
+  const rules: GrammarRule[] = [];
+  const extras: string[] = [];
+  
+  // Start with the root rule - this varies by paradigm
+  rules.push(generateRootRule(architecture, features));
+  
+  // Add basic token rules
+  rules.push(...generateTokenRules(syntax));
+  
+  // Add paradigm-specific rules
+  rules.push(...generateParadigmRules(architecture, features, syntax));
+  
+  // Add data structure rules if specified
+  if (features.dataStructures.length > 0) {
+    rules.push(...generateDataStructureRules(features.dataStructures));
+  }
+  
+  // Add control flow rules if specified
+  if (features.controlFlow.length > 0) {
+    rules.push(...generateControlFlowRules(features.controlFlow, syntax));
+  }
+  
+  // Set up extras (whitespace and comments)
+  extras.push('/\\s/', `$.${getCommentRuleName(syntax.comments.pattern)}`);
+  
+  return {
+    name: architecture.name,
+    rules,
+    extras,
+    conflicts: [], // TODO: Add conflicts if needed
+    precedences: generatePrecedences(architecture, features),
+    word: 'identifier' // Most languages use identifier as word token
+  };
+}
+
+/**
+ * Generate the root rule based on language paradigm
+ */
+function generateRootRule(architecture: LanguageArchitecture, features: LanguageFeatures): GrammarRule {
+  let definition: string;
+  
+  switch (architecture.paradigm) {
+    case 'declarative':
+      definition = 'repeat(choice($.rule_declaration, $.constraint, $.fact))';
+      break;
+    case 'functional':
+      definition = 'repeat(choice($.function_definition, $.expression, $.binding))';
+      break;
+    case 'object-oriented':
+      definition = 'repeat(choice($.class_definition, $.statement, $.expression))';
+      break;
+    case 'procedural':
+    case 'mixed':
+    default:
+      definition = 'repeat(choice($.statement, $.expression, $.declaration))';
+      break;
+  }
+  
+  return {
+    name: 'source_file',
+    definition,
+    comment: `Root rule for ${architecture.paradigm} language`
+  };
+}
+
+/**
+ * Generate basic token rules (identifiers, numbers, strings, comments)
+ */
+function generateTokenRules(syntax: LanguageSyntax): GrammarRule[] {
+  const rules: GrammarRule[] = [];
+  
+  // Identifier
+  rules.push({
+    name: 'identifier',
+    definition: `/${syntax.identifiers.pattern}/`,
+    comment: `Identifiers: ${syntax.identifiers.examples.join(', ')}`
+  });
+  
+  // Numbers
+  rules.push({
+    name: 'number',
+    definition: `/${syntax.numbers.pattern}/`,
+    comment: `Numbers: ${syntax.numbers.examples.join(', ')}`
+  });
+  
+  // Strings
+  rules.push({
+    name: 'string',
+    definition: `/${syntax.strings.pattern}/`,
+    comment: `Strings: ${syntax.strings.examples.join(', ')}`
+  });
+  
+  // Comments
+  const commentRuleName = getCommentRuleName(syntax.comments.pattern);
+  rules.push({
+    name: commentRuleName,
+    definition: `/${escapeRegex(syntax.comments.pattern)}.*$/`,
+    comment: `Line comments starting with ${syntax.comments.pattern}`
+  });
+  
+  return rules;
+}
+
+/**
+ * Generate paradigm-specific rules
+ */
+function generateParadigmRules(
+  architecture: LanguageArchitecture,
+  features: LanguageFeatures,
+  syntax: LanguageSyntax
+): GrammarRule[] {
+  const rules: GrammarRule[] = [];
+  
+  // Variable declarations (common to most paradigms)
+  rules.push({
+    name: 'variable_declaration',
+    definition: `seq("${syntax.variables.keyword}", $.identifier, "${syntax.variables.operator}", $.expression, "${syntax.variables.terminator}")`,
+    comment: `Variable declarations: ${syntax.variables.example}`
+  });
+  
+  // Expression rule (fundamental to all paradigms)
+  rules.push(generateExpressionRule(architecture, features));
+  
+  // Statement rule (for imperative paradigms)
+  if (['procedural', 'object-oriented', 'mixed'].includes(architecture.paradigm)) {
+    rules.push(generateStatementRule(architecture, features));
+  }
+  
+  // Add paradigm-specific constructs
+  switch (architecture.paradigm) {
+    case 'object-oriented':
+      if (syntax.paradigmExamples.class) {
+        rules.push(generateClassRule(syntax.paradigmExamples.class));
+      }
+      break;
+    case 'functional':
+      if (syntax.paradigmExamples.function) {
+        rules.push(generateFunctionRule(syntax.paradigmExamples.function, features.functionTypes));
+      }
+      break;
+    case 'declarative':
+      if (syntax.paradigmExamples.rule) {
+        rules.push(generateDeclarativeRule(syntax.paradigmExamples.rule));
+      }
+      break;
+  }
+  
+  return rules;
+}
+
+/**
+ * Generate expression rule based on paradigm
+ */
+function generateExpressionRule(architecture: LanguageArchitecture, features: LanguageFeatures): GrammarRule {
+  const choices = [
+    '$.identifier',
+    '$.number', 
+    '$.string',
+    '$.parenthesized_expression'
+  ];
+  
+  // Add function calls if functions are supported
+  if (features.functionTypes.length > 0) {
+    choices.push('$.function_call');
+  }
+  
+  // Add data structure literals
+  if (features.dataStructures.includes('arrays')) {
+    choices.push('$.array_literal');
+  }
+  if (features.dataStructures.includes('objects')) {
+    choices.push('$.object_literal');
+  }
+  
+  // Add binary operations for most paradigms
+  if (architecture.paradigm !== 'declarative') {
+    choices.push('$.binary_expression');
+  }
+  
+  return {
+    name: 'expression',
+    definition: `choice(${choices.join(', ')})`,
+    comment: 'Expression rule covering all expression types'
+  };
+}
+
+/**
+ * Generate statement rule for imperative paradigms
+ */
+function generateStatementRule(architecture: LanguageArchitecture, features: LanguageFeatures): GrammarRule {
+  const choices = [
+    '$.variable_declaration',
+    '$.expression_statement'
+  ];
+  
+  // Add control flow statements
+  if (features.controlFlow.includes('conditionals')) {
+    choices.push('$.if_statement');
+  }
+  if (features.controlFlow.includes('loops')) {
+    choices.push('$.for_statement', '$.while_statement');
+  }
+  
+  return {
+    name: 'statement',
+    definition: `choice(${choices.join(', ')})`,
+    comment: 'Statement rule for imperative constructs'
+  };
+}
+
+/**
+ * Generate data structure rules
+ */
+function generateDataStructureRules(dataStructures: string[]): GrammarRule[] {
+  const rules: GrammarRule[] = [];
+  
+  if (dataStructures.includes('arrays')) {
+    rules.push({
+      name: 'array_literal',
+      definition: 'seq("[", optional(seq($.expression, repeat(seq(",", $.expression)))), "]")',
+      comment: 'Array literals: [1, 2, 3]'
+    });
+  }
+  
+  if (dataStructures.includes('objects')) {
+    rules.push({
+      name: 'object_literal',
+      definition: 'seq("{", optional(seq($.property, repeat(seq(",", $.property)))), "}")',
+      comment: 'Object literals: {key: value}'
+    });
+    
+    rules.push({
+      name: 'property',
+      definition: 'seq(choice($.identifier, $.string), ":", $.expression)',
+      comment: 'Object property: key: value'
+    });
+  }
+  
+  if (dataStructures.includes('tuples')) {
+    rules.push({
+      name: 'tuple_literal',
+      definition: 'seq("(", $.expression, repeat1(seq(",", $.expression)), ")")',
+      comment: 'Tuple literals: (a, b, c)'
+    });
+  }
+  
+  return rules;
+}
+
+/**
+ * Generate control flow rules
+ */
+function generateControlFlowRules(controlFlow: string[], syntax: LanguageSyntax): GrammarRule[] {
+  const rules: GrammarRule[] = [];
+  
+  if (controlFlow.includes('conditionals')) {
+    rules.push({
+      name: 'if_statement',
+      definition: 'seq("if", "(", $.expression, ")", $.block, optional(seq("else", choice($.if_statement, $.block))))',
+      comment: 'If-else statements'
+    });
+    
+    rules.push({
+      name: 'block',
+      definition: 'seq("{", repeat($.statement), "}")',
+      comment: 'Code blocks'
+    });
+  }
+  
+  if (controlFlow.includes('loops')) {
+    rules.push({
+      name: 'while_statement',
+      definition: 'seq("while", "(", $.expression, ")", $.block)',
+      comment: 'While loops'
+    });
+    
+    rules.push({
+      name: 'for_statement',
+      definition: 'seq("for", "(", optional($.statement), ";", optional($.expression), ";", optional($.expression), ")", $.block)',
+      comment: 'For loops'
+    });
+  }
+  
+  return rules;
+}
+
+/**
+ * Generate class rule from user example
+ */
+function generateClassRule(classExample: string): GrammarRule {
+  // Simple class rule - could be enhanced with more parsing
+  return {
+    name: 'class_definition',
+    definition: 'seq("class", $.identifier, "{", repeat($.method_definition), "}")',
+    comment: `Class definition based on: ${classExample}`
+  };
+}
+
+/**
+ * Generate function rule from user example
+ */
+function generateFunctionRule(functionExample: string, functionTypes: string[]): GrammarRule {
+  let definition = 'seq("function", $.identifier, "(", optional($.parameter_list), ")", $.block)';
+  
+  // Add arrow functions if supported
+  if (functionTypes.includes('anonymous')) {
+    definition = `choice(${definition}, $.arrow_function)`;
+  }
+  
+  return {
+    name: 'function_definition',
+    definition,
+    comment: `Function definition based on: ${functionExample}`
+  };
+}
+
+/**
+ * Generate declarative rule from user example
+ */
+function generateDeclarativeRule(ruleExample: string): GrammarRule {
+  return {
+    name: 'rule_declaration',
+    definition: 'seq("rule", $.identifier, optional(seq("when", $.expression)))',
+    comment: `Rule declaration based on: ${ruleExample}`
+  };
+}
+
+/**
+ * Generate precedences based on paradigm
+ */
+function generatePrecedences(architecture: LanguageArchitecture, features: LanguageFeatures): string[][] {
+  // Basic precedence for binary operations
+  const precedences = [
+    ['$.binary_expression']
+  ];
+  
+  // Add function call precedence if functions are supported
+  if (features.functionTypes.length > 0) {
+    precedences.push(['$.function_call']);
+  }
+  
+  return precedences;
+}
+
+/**
+ * Generate the complete grammar.js file content
+ */
+export function generateGrammarFile(grammar: GeneratedGrammar): string {
+  const lines: string[] = [];
+  
+  lines.push('/**');
+  lines.push(` * Grammar for ${grammar.name}`);
+  lines.push(' * Generated by DSK (DSL Development Kit)');
+  lines.push(' */');
+  lines.push('');
+  lines.push('module.exports = grammar({');
+  lines.push(`  name: '${grammar.name}',`);
+  lines.push('');
+  
+  // Add word token if specified
+  if (grammar.word) {
+    lines.push(`  word: $ => $.${grammar.word},`);
+    lines.push('');
+  }
+  
+  // Add rules
+  lines.push('  rules: {');
+  
+  grammar.rules.forEach((rule, index) => {
+    if (rule.comment) {
+      lines.push(`    // ${rule.comment}`);
+    }
+    lines.push(`    ${rule.name}: $ => ${rule.definition}${index < grammar.rules.length - 1 ? ',' : ''}`);
+    if (index < grammar.rules.length - 1) {
+      lines.push('');
+    }
+  });
+  
+  lines.push('  }');
+  
+  // Add extras
+  if (grammar.extras.length > 0) {
+    lines.push(',');
+    lines.push('');
+    lines.push('  extras: $ => [');
+    grammar.extras.forEach((extra, index) => {
+      lines.push(`    ${extra}${index < grammar.extras.length - 1 ? ',' : ''}`);
+    });
+    lines.push('  ]');
+  }
+  
+  // Add conflicts if any
+  if (grammar.conflicts.length > 0) {
+    lines.push(',');
+    lines.push('');
+    lines.push('  conflicts: $ => [');
+    grammar.conflicts.forEach((conflict, index) => {
+      lines.push(`    [${conflict.join(', ')}]${index < grammar.conflicts.length - 1 ? ',' : ''}`);
+    });
+    lines.push('  ]');
+  }
+  
+  // Add precedences if any
+  if (grammar.precedences.length > 0) {
+    lines.push(',');
+    lines.push('');
+    lines.push('  precedences: $ => [');
+    grammar.precedences.forEach((prec, index) => {
+      lines.push(`    [${prec.join(', ')}]${index < grammar.precedences.length - 1 ? ',' : ''}`);
+    });
+    lines.push('  ]');
+  }
+  
+  lines.push('});');
+  lines.push('');
+  
+  return lines.join('\n');
+}
+
+/**
+ * Helper functions
+ */
+function getCommentRuleName(commentPattern: string): string {
+  switch (commentPattern) {
+    case '//': return 'line_comment_slash';
+    case '#': return 'line_comment_hash';
+    case ';': return 'line_comment_semicolon';
+    default: return 'line_comment';
+  }
+}
+
+function escapeRegex(pattern: string): string {
+  return pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+}
diff --git a/tree-sitter/dsk/dsk-cli/src/utils/inference.ts b/tree-sitter/dsk/dsk-cli/src/utils/inference.ts
new file mode 100644
index 0000000..f49e176
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/utils/inference.ts
@@ -0,0 +1,286 @@
+/**
+ * Pattern Inference Engine
+ * 
+ * Infers regular expression patterns from user examples.
+ * Uses an extensible library of common token patterns with solid defaults.
+ */
+
+export interface TokenPattern {
+  name: string;
+  description: string;
+  regex: RegExp;
+  examples: string[];
+  priority: number; // Higher priority patterns are tried first
+}
+
+export interface InferenceResult {
+  pattern: TokenPattern | null;
+  confidence: number; // 0-1 score indicating match quality
+  matchedExamples: string[];
+  rejectedExamples: string[];
+}
+
+/**
+ * Default token pattern library with common programming language constructs
+ */
+export const DEFAULT_PATTERNS: TokenPattern[] = [
+  // Identifiers
+  {
+    name: 'c_identifier',
+    description: 'C-style identifier (letters, digits, underscore, must start with letter/underscore)',
+    regex: /^[a-zA-Z_][a-zA-Z0-9_]*$/,
+    examples: ['myVar', 'userName', '_private', 'MAX_SIZE'],
+    priority: 10
+  },
+  {
+    name: 'js_identifier',
+    description: 'JavaScript-style identifier (letters, digits, $, _, must start with letter/$/_)',
+    regex: /^[A-Za-z_$][A-Za-z0-9_$]*$/,
+    examples: ['x', 'var1', '$var', '_var', 'Var3', 'BananaFruitStand'],
+    priority: 11
+  },
+  {
+    name: 'kebab_identifier', 
+    description: 'Kebab-case identifier (letters, digits, hyphens)',
+    regex: /^[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9]$/,
+    examples: ['my-var', 'user-name', 'max-size'],
+    priority: 8
+  },
+  {
+    name: 'camel_identifier',
+    description: 'CamelCase identifier (letters and digits, no separators)',
+    regex: /^[a-zA-Z][a-zA-Z0-9]*$/,
+    examples: ['myVar', 'userName', 'maxSize'],
+    priority: 9
+  },
+
+  // Numbers
+  {
+    name: 'number_general',
+    description: 'Integer or floating point number (optional sign)',
+    regex: /^[+-]?(?:\d*\.\d+|\d+\.\d*|\d+)$/,
+    examples: ['1', '-7', '1.24', '10000', '+0.5', '2.'],
+    priority: 16
+  },
+  {
+    name: 'integer',
+    description: 'Integer number (optional sign, digits)',
+    regex: /^[+-]?\d+$/,
+    examples: ['42', '-17', '+123', '0'],
+    priority: 15
+  },
+  {
+    name: 'float',
+    description: 'Floating point number (optional sign, decimal point)',
+    regex: /^[+-]?\d*\.\d+$/,
+    examples: ['3.14', '-2.5', '+0.123', '.5'],
+    priority: 14
+  },
+  {
+    name: 'scientific',
+    description: 'Scientific notation number',
+    regex: /^[+-]?\d*\.?\d+[eE][+-]?\d+$/,
+    examples: ['1e10', '3.14e-2', '-2.5E+3'],
+    priority: 12
+  },
+  {
+    name: 'hex_number',
+    description: 'Hexadecimal number (0x prefix)',
+    regex: /^0[xX][0-9a-fA-F]+$/,
+    examples: ['0xFF', '0x123ABC', '0X00'],
+    priority: 13
+  },
+
+  // Strings
+  {
+    name: 'double_quoted_string',
+    description: 'Double-quoted string literal',
+    regex: /^".*"$/,
+    examples: ['"hello"', '"world"', '""'],
+    priority: 11
+  },
+  {
+    name: 'single_quoted_string',
+    description: 'Single-quoted string literal',
+    regex: /^'.*'$/,
+    examples: ["'hello'", "'world'", "''"],
+    priority: 11
+  },
+  {
+    name: 'backtick_string',
+    description: 'Backtick-quoted string literal (template strings)',
+    regex: /^`.*`$/,
+    examples: ['`hello`', '`world ${var}`', '``'],
+    priority: 7
+  },
+
+  // Comments
+  {
+    name: 'c_line_comment',
+    description: 'C-style line comment (// prefix)',
+    regex: /^\/\/.*$/,
+    examples: ['// comment', '// TODO: fix this'],
+    priority: 16
+  },
+  {
+    name: 'hash_line_comment',
+    description: 'Hash line comment (# prefix)',
+    regex: /^#.*$/,
+    examples: ['# comment', '# TODO: fix this'],
+    priority: 16
+  },
+  {
+    name: 'semicolon_line_comment',
+    description: 'Semicolon line comment (; prefix)',
+    regex: /^;.*$/,
+    examples: ['; comment', '; TODO: fix this'],
+    priority: 16
+  },
+
+  // Special patterns
+  {
+    name: 'boolean',
+    description: 'Boolean literal',
+    regex: /^(true|false)$/,
+    examples: ['true', 'false'],
+    priority: 17
+  },
+  {
+    name: 'null_literal',
+    description: 'Null/nil literal',
+    regex: /^(null|nil|None|undefined)$/,
+    examples: ['null', 'nil', 'None', 'undefined'],
+    priority: 17
+  }
+];
+
+/**
+ * Infer a pattern from valid and invalid examples
+ */
+export function inferPattern(
+  validExamples: string[],
+  invalidExamples: string[] = [],
+  customPatterns: TokenPattern[] = []
+): InferenceResult {
+  if (validExamples.length === 0) {
+    return {
+      pattern: null,
+      confidence: 0,
+      matchedExamples: [],
+      rejectedExamples: invalidExamples
+    };
+  }
+
+  // Combine default patterns with custom patterns
+  const allPatterns = [...customPatterns, ...DEFAULT_PATTERNS]
+    .sort((a, b) => b.priority - a.priority);
+
+  // Try each pattern
+  for (const pattern of allPatterns) {
+    const validMatches = validExamples.filter(example => pattern.regex.test(example));
+    const invalidMatches = invalidExamples.filter(example => pattern.regex.test(example));
+
+    // Pattern must match ALL valid examples and NO invalid examples
+    if (validMatches.length === validExamples.length && invalidMatches.length === 0) {
+      const confidence = calculateConfidence(validExamples, invalidExamples, pattern);
+      
+      return {
+        pattern,
+        confidence,
+        matchedExamples: validMatches,
+        rejectedExamples: invalidExamples
+      };
+    }
+  }
+
+  // No pattern found
+  return {
+    pattern: null,
+    confidence: 0,
+    matchedExamples: [],
+    rejectedExamples: invalidExamples
+  };
+}
+
+/**
+ * Calculate confidence score for a pattern match
+ */
+function calculateConfidence(
+  validExamples: string[],
+  invalidExamples: string[],
+  pattern: TokenPattern
+): number {
+  let confidence = 0.8; // Base confidence
+
+  // Boost confidence for more valid examples
+  if (validExamples.length >= 3) confidence += 0.1;
+  if (validExamples.length >= 5) confidence += 0.05;
+
+  // Boost confidence for having invalid examples that were correctly rejected
+  if (invalidExamples.length > 0) confidence += 0.05;
+
+  // Boost confidence if examples match the pattern's own examples
+  const patternExampleMatches = validExamples.filter(ex => 
+    pattern.examples.some(pex => ex === pex)
+  );
+  if (patternExampleMatches.length > 0) {
+    confidence += 0.05 * patternExampleMatches.length;
+  }
+
+  return Math.min(confidence, 1.0);
+}
+
+/**
+ * Generate a custom regex pattern from examples (fallback when inference fails)
+ */
+export function generateCustomPattern(
+  validExamples: string[],
+  invalidExamples: string[] = []
+): string {
+  if (validExamples.length === 0) return '';
+
+  // Simple approach: create alternation of literal examples
+  // This is a fallback - not as robust as proper pattern matching
+  const escapedExamples = validExamples.map(ex => 
+    ex.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+  );
+
+  return `^(${escapedExamples.join('|')})$`;
+}
+
+/**
+ * Validate that a pattern works correctly with given examples
+ */
+export function validatePattern(
+  pattern: string,
+  validExamples: string[],
+  invalidExamples: string[] = []
+): { isValid: boolean; errors: string[] } {
+  const errors: string[] = [];
+  
+  try {
+    const regex = new RegExp(pattern);
+    
+    // Check valid examples
+    for (const example of validExamples) {
+      if (!regex.test(example)) {
+        errors.push(`Pattern does not match valid example: "${example}"`);
+      }
+    }
+    
+    // Check invalid examples
+    for (const example of invalidExamples) {
+      if (regex.test(example)) {
+        errors.push(`Pattern incorrectly matches invalid example: "${example}"`);
+      }
+    }
+    
+  } catch (e) {
+    errors.push(`Invalid regular expression: ${e instanceof Error ? e.message : 'Unknown error'}`);
+  }
+
+  return {
+    isValid: errors.length === 0,
+    errors
+  };
+}
diff --git a/tree-sitter/dsk/dsk-cli/src/utils/template-processor.ts b/tree-sitter/dsk/dsk-cli/src/utils/template-processor.ts
new file mode 100644
index 0000000..e237048
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/src/utils/template-processor.ts
@@ -0,0 +1,192 @@
+/**
+ * Template Processor
+ * 
+ * Processes template files by replacing placeholders with actual values
+ */
+
+import { readFileSync, writeFileSync, readdirSync, statSync, mkdirSync, copyFileSync } from 'fs';
+import { join, dirname, basename, extname } from 'path';
+import { LanguageArchitecture, LanguageFeatures, LanguageSyntax } from '../commands/new.js';
+
+export interface TemplateContext {
+  architecture: LanguageArchitecture;
+  features: LanguageFeatures;
+  syntax: LanguageSyntax;
+}
+
+/**
+ * Process a template directory and create a project
+ */
+export function processTemplate(
+  templateDir: string,
+  outputDir: string,
+  context: TemplateContext
+): void {
+  // Create output directory
+  mkdirSync(outputDir, { recursive: true });
+  
+  // Process all files in template directory
+  processDirectory(templateDir, outputDir, context);
+}
+
+/**
+ * Process a directory recursively
+ */
+function processDirectory(
+  sourceDir: string,
+  targetDir: string,
+  context: TemplateContext
+): void {
+  const items = readdirSync(sourceDir);
+  
+  for (const item of items) {
+    const sourcePath = join(sourceDir, item);
+    const targetPath = join(targetDir, processFileName(item, context));
+    
+    const stat = statSync(sourcePath);
+    
+    if (stat.isDirectory()) {
+      mkdirSync(targetPath, { recursive: true });
+      processDirectory(sourcePath, targetPath, context);
+    } else {
+      processFile(sourcePath, targetPath, context);
+    }
+  }
+}
+
+/**
+ * Process a single file
+ */
+function processFile(
+  sourcePath: string,
+  targetPath: string,
+  context: TemplateContext
+): void {
+  const content = readFileSync(sourcePath, 'utf-8');
+  const processedContent = processContent(content, context);
+  
+  // Ensure target directory exists
+  mkdirSync(dirname(targetPath), { recursive: true });
+  
+  writeFileSync(targetPath, processedContent, 'utf-8');
+}
+
+/**
+ * Process file name placeholders
+ */
+function processFileName(fileName: string, context: TemplateContext): string {
+  const replacements = getReplacements(context);
+  
+  let processed = fileName;
+  for (const [placeholder, value] of Object.entries(replacements)) {
+    processed = processed.replace(new RegExp(placeholder, 'g'), value);
+  }
+  
+  return processed;
+}
+
+/**
+ * Process file content placeholders
+ */
+function processContent(content: string, context: TemplateContext): string {
+  const replacements = getReplacements(context);
+  
+  let processed = content;
+  for (const [placeholder, value] of Object.entries(replacements)) {
+    processed = processed.replace(new RegExp(placeholder, 'g'), value);
+  }
+  
+  return processed;
+}
+
+/**
+ * Get all placeholder replacements
+ */
+function getReplacements(context: TemplateContext): Record<string, string> {
+  const { architecture, features, syntax } = context;
+  
+  return {
+    '__DSL_NAME__': architecture.name,
+    '__PARADIGM__': architecture.paradigm,
+    '__PURPOSE__': architecture.purpose,
+    '__DATA_PHILOSOPHY__': architecture.dataPhilosophy,
+    
+    // Syntax elements
+    '__VARIABLE_KEYWORD__': syntax.variables.keyword,
+    '__ASSIGNMENT_OPERATOR__': syntax.variables.operator,
+    '__TERMINATOR__': syntax.variables.terminator,
+    '__VARIABLE_EXAMPLE__': syntax.variables.example,
+    
+    '__COMMENT_EXAMPLE__': syntax.comments.pattern,
+    '__STRING_EXAMPLE__': syntax.strings.examples[0] || '"hello"',
+    '__NUMBER_EXAMPLE__': syntax.numbers.examples[0] || '42',
+    '__IDENTIFIER_EXAMPLE__': syntax.identifiers.examples[0] || 'myVar',
+    
+    // Paradigm-specific examples
+    '__PARADIGM_EXAMPLE__': getParadigmExample(architecture, syntax),
+    
+    // File extension
+    '__EXT__': getFileExtension(architecture.name),
+    
+    // Feature lists
+    '__FEATURES_LIST__': generateFeaturesList(features),
+    '__DATA_STRUCTURES__': features.dataStructures.join(', ') || 'Basic types',
+    
+    // Control flow
+    '__CONTROL_FLOW__': features.controlFlow.join(', ') || 'Sequential execution'
+  };
+}
+
+/**
+ * Get paradigm-specific example code
+ */
+function getParadigmExample(architecture: LanguageArchitecture, syntax: LanguageSyntax): string {
+  if (syntax.paradigmExamples.class) {
+    return syntax.paradigmExamples.class;
+  }
+  if (syntax.paradigmExamples.function) {
+    return syntax.paradigmExamples.function;
+  }
+  if (syntax.paradigmExamples.rule) {
+    return syntax.paradigmExamples.rule;
+  }
+  
+  // Fallback to variable example
+  return syntax.variables.example;
+}
+
+/**
+ * Get appropriate file extension for the language
+ */
+function getFileExtension(languageName: string): string {
+  // Simple heuristic - could be made configurable
+  const name = languageName.toLowerCase();
+  
+  if (name.includes('script')) return 'script';
+  if (name.includes('lang')) return 'lang';
+  if (name.includes('dsl')) return 'dsl';
+  
+  // Default: use first 3 characters of name
+  return name.substring(0, 3);
+}
+
+/**
+ * Generate features list for README
+ */
+function generateFeaturesList(features: LanguageFeatures): string {
+  const items: string[] = [];
+  
+  if (features.controlFlow.length > 0) {
+    items.push(`- **Control Flow**: ${features.controlFlow.join(', ')}`);
+  }
+  
+  if (features.dataStructures.length > 0) {
+    items.push(`- **Data Structures**: ${features.dataStructures.join(', ')}`);
+  }
+  
+  if (features.functionTypes.length > 0) {
+    items.push(`- **Functions**: ${features.functionTypes.join(', ')}`);
+  }
+  
+  return items.length > 0 ? items.join('\n') : '- Basic language constructs';
+}