about summary refs log tree commit diff stats
path: root/tree-sitter/dsk/dsk-cli
diff options
context:
space:
mode:
Diffstat (limited to 'tree-sitter/dsk/dsk-cli')
-rw-r--r--tree-sitter/dsk/dsk-cli/.gitignore175
-rw-r--r--tree-sitter/dsk/dsk-cli/README.md126
-rwxr-xr-xtree-sitter/dsk/dsk-cli/bun.lockbbin0 -> 30832 bytes
-rw-r--r--tree-sitter/dsk/dsk-cli/package.json33
-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
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/default/README.md82
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/default/corpus/examples.txt85
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/default/examples/hello.__EXT__7
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/default/package.json9
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/js-addon/binding.gyp28
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/js-addon/bindings/node.cc16
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts3
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts.map1
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/js-addon/index.js15
-rw-r--r--tree-sitter/dsk/dsk-cli/templates/js-addon/package.json31
-rw-r--r--tree-sitter/dsk/dsk-cli/test-inference.d.ts5
-rw-r--r--tree-sitter/dsk/dsk-cli/test-inference.d.ts.map1
-rw-r--r--tree-sitter/dsk/dsk-cli/test-inference.js.map1
-rw-r--r--tree-sitter/dsk/dsk-cli/tsconfig.json37
29 files changed, 3026 insertions, 0 deletions
diff --git a/tree-sitter/dsk/dsk-cli/.gitignore b/tree-sitter/dsk/dsk-cli/.gitignore
new file mode 100644
index 0000000..9b1ee42
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/.gitignore
@@ -0,0 +1,175 @@
+# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
+
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Caches
+
+.cache
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+
+web_modules/
+
+# TypeScript cache
+
+*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Optional stylelint cache
+
+.stylelintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variable files
+
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.parcel-cache
+
+# Next.js build output
+
+.next
+out
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+# Comment in the public line in if your project uses Gatsby and not Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+
+.temp
+
+# Docusaurus cache and generated files
+
+.docusaurus
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
diff --git a/tree-sitter/dsk/dsk-cli/README.md b/tree-sitter/dsk/dsk-cli/README.md
new file mode 100644
index 0000000..d07a9dd
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/README.md
@@ -0,0 +1,126 @@
+# dsk-cli
+
+DSL Development Kit (DSK) – a CLI that helps you design, build, test, and ship Tree-sitter based Domain-Specific Languages (DSLs) with a convention-over-configuration workflow.
+
+## Why this is helpful
+- **Lower barrier to entry**: Generate a working Tree-sitter `grammar.js` from examples via an interactive flow.
+- **No boilerplate**: One command builds both a C static library and a Node.js addon package.
+- **Fast iteration**: Built-in watch mode (`dsk dev`) and testing (`dsk test`).
+- **Editor-ready**: Generate Tree-sitter highlight queries and editor scaffolds (Neovim, Emacs, VS Code).
+- **Consistent outputs**: Standardized project layout and generated artifacts under `generated/` and `dist/`.
+
+## Prerequisites
+- macOS or Linux
+- [Bun](https://bun.sh) (to run `dsk`)
+- [tree-sitter CLI](https://tree-sitter.github.io/tree-sitter/creating-parsers#installation) (`npm i -g tree-sitter-cli` or `brew install tree-sitter`)
+- C toolchain: clang/gcc and `ar` (macOS: `xcode-select --install`, Ubuntu: `build-essential`)
+- For the generated JS addon builds: Python 3 and make are typically required by node-gyp (the template depends on `node-gyp`)
+
+## Install (for developing this CLI)
+```bash
+bun install
+bunx tsc
+bun link  # optional: exposes `dsk` on your PATH during development
+```
+
+## Quickstart (creating a DSL)
+```bash
+# 1) Scaffold a new DSL project interactively
+dsk new my-lang --interactive
+
+# 2) Move into the project directory
+cd my-lang
+
+# 3) Build (generates parser, C lib, and JS addon)
+dsk build
+
+# 4) Run tests (expects corpus in `corpus/` or queries)
+dsk test -v
+
+# 5) Iterate with watch mode
+dsk dev --debounce 150
+
+# 6) Generate editor highlighting scaffolds
+dsk highlight
+
+# 7) Package outputs for distribution
+dsk package
+```
+
+## Command reference
+
+### `dsk new <name> [--interactive]`
+Creates a new DSL project. With `--interactive`, it asks for examples and infers common token patterns, then generates a starter `grammar.js` and project structure using templates.
+
+### `dsk build` [--verbose] [--skip-c] [--skip-js]
+Builds your DSL:
+- Runs `tree-sitter generate`
+- Builds a C static library and header under `generated/c/`
+- Creates a Node.js addon package under `generated/js/` (compiles via node-gyp)
+
+Outputs:
+- `generated/c/include/<dsl>.h`
+- `generated/c/lib/lib<dsl>.a`
+- `generated/js/` (package.json, binding.gyp, compiled addon, copied `src/`)
+
+### `dsk test` [-u|--update] [-f|--filter <regex>] [--cwd <dir>] [-v|--verbose] [patterns...]
+Thin wrapper around `tree-sitter test` that streams output directly.
+- `--update`: updates expected output snapshots
+- `--filter <regex>`: only run tests whose description matches
+- `--cwd <dir>`: run tests in a different directory
+- `--verbose`: pass through verbose output
+
+Examples:
+```bash
+dsk test
+dsk test -v -f numbers
+dsk test -u corpus/examples.txt
+```
+
+### `dsk dev` [--debounce <ms>] [--quiet] [-v|--verbose]
+Watches `grammar.js` and on changes runs `dsk build` then `dsk test`.
+- `--debounce <ms>`: delay rebuild after changes (default: 150)
+- `--quiet`: suppress non-error logs
+- `--verbose`: pass to `dsk build` (more detailed build logs)
+
+### `dsk highlight`
+Generates highlighting assets and editor scaffolds:
+- `generated/editors/tree-sitter/highlights.scm`
+- `generated/editors/neovim/setup-instructions.md`
+- `generated/editors/emacs/<lang>-mode.el`
+- `generated/editors/vscode/syntaxes/<lang>.tmLanguage.json`
+- `generated/editors/vscode/language-configuration.json`
+
+### `dsk package`
+Packages build outputs into `dist/`:
+- Archives `generated/c/` as `dist/c-artifacts.tar.gz`
+- Packs the JS addon under `generated/js/` via `bun pack` (falls back to `npm pack`)
+
+### `dsk self:package`
+Builds and packages the `dsk` CLI itself into a tarball under `release/`.
+```bash
+dsk self:package
+# → release/dsk-cli-<version>.tgz
+```
+
+## Project structure (generated DSL project)
+- `grammar.js`: Tree-sitter grammar
+- `src/`: generated parser sources after `tree-sitter generate`
+- `corpus/`: test cases for `tree-sitter test`
+- `generated/`: build outputs (C and JS targets)
+- `generated/editors/`: highlight queries and editor scaffolds
+- `dist/`: packaged artifacts
+
+## Notes about the JS addon template
+- Depends on `node-addon-api` and `node-gyp` (declared in template `package.json`)
+- `binding.gyp` includes Node-API headers and defines `NAPI_VERSION=8`
+- Builds via `npm install` or `bun install` in `generated/js/` (auto-detected)
+
+## Troubleshooting
+- `tree-sitter` not found: install with `npm i -g tree-sitter-cli` or `brew install tree-sitter`
+- C compiler not found: macOS `xcode-select --install`; Linux install `build-essential`
+- node-gyp build issues: ensure Python 3 and make are available; re-run `dsk build -v`
+
+---
+
+This project was created using `bun init` in bun v1.1.29. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
diff --git a/tree-sitter/dsk/dsk-cli/bun.lockb b/tree-sitter/dsk/dsk-cli/bun.lockb
new file mode 100755
index 0000000..31f4569
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/bun.lockb
Binary files differdiff --git a/tree-sitter/dsk/dsk-cli/package.json b/tree-sitter/dsk/dsk-cli/package.json
new file mode 100644
index 0000000..ef6f9fd
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/package.json
@@ -0,0 +1,33 @@
+{
+  "name": "dsk-cli",
+  "version": "0.1.0",
+  "description": "DSL Development Kit - Command-line tool for creating Domain-Specific Languages",
+  "main": "dist/index.js",
+  "module": "index.ts",
+  "type": "module",
+  "bin": {
+    "dsk": "./dist/index.js"
+  },
+  "scripts": {
+    "build": "bunx tsc",
+    "dev": "bun run --watch src/index.ts",
+    "start": "bun run dist/index.js"
+  },
+  "devDependencies": {
+    "@types/bun": "latest",
+    "@types/fs-extra": "^11.0.4",
+    "@types/inquirer": "^9.0.9",
+    "@types/node": "^24.2.1"
+  },
+  "peerDependencies": {
+    "typescript": "^5.9.2"
+  },
+  "dependencies": {
+    "chalk": "^5.5.0",
+    "chokidar": "^4.0.3",
+    "commander": "^14.0.0",
+    "execa": "^9.6.0",
+    "fs-extra": "^11.3.1",
+    "inquirer": "^12.9.1"
+  }
+}
\ No newline at end of file
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';
+}
diff --git a/tree-sitter/dsk/dsk-cli/templates/default/README.md b/tree-sitter/dsk/dsk-cli/templates/default/README.md
new file mode 100644
index 0000000..4560c6a
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/default/README.md
@@ -0,0 +1,82 @@
+# __DSL_NAME__
+
+A Domain-Specific Language created with DSK (DSL Development Kit).
+
+## Overview
+
+- **Language Type**: __PARADIGM__
+- **Purpose**: __PURPOSE__
+- **Data Philosophy**: __DATA_PHILOSOPHY__
+
+## Getting Started
+
+### Prerequisites
+
+- [Tree-sitter CLI](https://tree-sitter.github.io/tree-sitter/creating-parsers#installation)
+- Node.js or Bun (for JavaScript bindings)
+- C compiler (gcc/clang) for native compilation
+
+### Development
+
+```bash
+# Start development mode with file watching
+dsk dev
+
+# Run tests
+dsk test
+
+# Build parser and packages
+dsk build
+
+# Generate editor syntax highlighting
+dsk highlight
+
+# Package for distribution
+dsk package
+```
+
+## Project Structure
+
+```
+__DSL_NAME__/
+├── grammar.js          # Tree-sitter grammar definition
+├── corpus/             # Test cases for the grammar
+│   └── examples.txt
+├── generated/          # Generated artifacts (created by dsk build)
+│   ├── c/             # C static library
+│   ├── js/            # JavaScript/Node.js package
+│   └── editors/       # Editor configurations
+└── examples/          # Example programs in your language
+    └── hello.__EXT__
+```
+
+## Language Features
+
+__FEATURES_LIST__
+
+## Grammar Rules
+
+The grammar includes rules for:
+
+- **Tokens**: Identifiers, numbers, strings, comments
+- **Expressions**: Based on your language paradigm
+- **Statements**: Control flow and declarations
+- **Data Structures**: __DATA_STRUCTURES__
+
+## Next Steps
+
+1. **Customize the Grammar**: Edit `grammar.js` to refine your language syntax
+2. **Add Test Cases**: Create examples in `corpus/examples.txt`
+3. **Write Example Programs**: Add sample code to `examples/`
+4. **Generate Editor Support**: Run `dsk highlight` for syntax highlighting
+5. **Build and Test**: Use `dsk dev` for iterative development
+
+## Resources
+
+- [Tree-sitter Documentation](https://tree-sitter.github.io/tree-sitter/)
+- [DSK Documentation](https://github.com/your-org/dsk)
+- [Language Implementation Patterns](https://pragprog.com/titles/tpdsl/)
+
+---
+
+Generated by [DSK](https://github.com/your-org/dsk) - DSL Development Kit
diff --git a/tree-sitter/dsk/dsk-cli/templates/default/corpus/examples.txt b/tree-sitter/dsk/dsk-cli/templates/default/corpus/examples.txt
new file mode 100644
index 0000000..94f199e
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/default/corpus/examples.txt
@@ -0,0 +1,85 @@
+================================================================================
+Basic Examples
+================================================================================
+
+Simple variable declaration
+---
+
+__VARIABLE_EXAMPLE__
+
+---
+
+(source_file
+  (statement
+    (variable_declaration
+      (identifier)
+      (expression (number)))))
+
+================================================================================
+Comments
+================================================================================
+
+Line comment
+---
+
+__COMMENT_EXAMPLE__ This is a comment
+__VARIABLE_EXAMPLE__
+
+---
+
+(source_file
+  (statement
+    (variable_declaration
+      (identifier)
+      (expression (number)))))
+
+================================================================================
+Expressions
+================================================================================
+
+String literal via variable declaration
+---
+
+__VARIABLE_KEYWORD__ message __ASSIGNMENT_OPERATOR__ __STRING_EXAMPLE____TERMINATOR__
+
+---
+
+(source_file
+  (statement
+    (variable_declaration
+      (identifier)
+      (expression (string)))))
+
+================================================================================
+Numbers
+================================================================================
+
+Integer via variable declaration
+---
+
+__VARIABLE_KEYWORD__ count __ASSIGNMENT_OPERATOR__ __NUMBER_EXAMPLE____TERMINATOR__
+
+---
+
+(source_file
+  (statement
+    (variable_declaration
+      (identifier)
+      (expression (number)))))
+
+================================================================================
+Identifiers
+================================================================================
+
+Valid identifier via variable declaration
+---
+
+__VARIABLE_KEYWORD__ __IDENTIFIER_EXAMPLE__ __ASSIGNMENT_OPERATOR__ 42__TERMINATOR__
+
+---
+
+(source_file
+  (statement
+    (variable_declaration
+      (identifier)
+      (expression (number)))))
diff --git a/tree-sitter/dsk/dsk-cli/templates/default/examples/hello.__EXT__ b/tree-sitter/dsk/dsk-cli/templates/default/examples/hello.__EXT__
new file mode 100644
index 0000000..07769f6
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/default/examples/hello.__EXT__
@@ -0,0 +1,7 @@
+__COMMENT_EXAMPLE__ Hello World example for __DSL_NAME__
+
+__PARADIGM_EXAMPLE__
+
+__COMMENT_EXAMPLE__ More examples:
+__VARIABLE_EXAMPLE__
+__VARIABLE_KEYWORD__ __IDENTIFIER_EXAMPLE__ __ASSIGNMENT_OPERATOR__ __STRING_EXAMPLE____TERMINATOR__
diff --git a/tree-sitter/dsk/dsk-cli/templates/default/package.json b/tree-sitter/dsk/dsk-cli/templates/default/package.json
new file mode 100644
index 0000000..ab3d0c4
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/default/package.json
@@ -0,0 +1,9 @@
+{
+  "name": "__DSL_NAME__-dsl",
+  "private": true,
+  "type": "commonjs",
+  "description": "DSL project for __DSL_NAME__ generated by DSK",
+  "license": "MIT"
+}
+
+
diff --git a/tree-sitter/dsk/dsk-cli/templates/js-addon/binding.gyp b/tree-sitter/dsk/dsk-cli/templates/js-addon/binding.gyp
new file mode 100644
index 0000000..ddb424b
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/js-addon/binding.gyp
@@ -0,0 +1,28 @@
+{
+  "targets": [
+    {
+      "target_name": "tree_sitter___DSL_NAME___binding",
+      "dependencies": [
+        "<!(node -p \"require('node-addon-api').gyp\")"
+      ],
+      "include_dirs": [
+        "<!@(node -p \"require('node-addon-api').include\")",
+        "src"
+      ],
+      "sources": [
+        "bindings/node.cc",
+        "src/parser.c"
+      ],
+      "cflags_c": [
+        "-std=c99"
+      ],
+      "cflags_cc": [
+        "-std=c++14"
+      ],
+      "defines": [
+        "NAPI_DISABLE_CPP_EXCEPTIONS",
+        "NAPI_VERSION=8"
+      ]
+    }
+  ]
+}
diff --git a/tree-sitter/dsk/dsk-cli/templates/js-addon/bindings/node.cc b/tree-sitter/dsk/dsk-cli/templates/js-addon/bindings/node.cc
new file mode 100644
index 0000000..d0ba098
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/js-addon/bindings/node.cc
@@ -0,0 +1,16 @@
+#include "napi.h"
+
+typedef struct TSLanguage TSLanguage;
+
+extern "C" TSLanguage *tree_sitter___DSL_NAME__();
+
+// "tree_sitter___DSL_NAME___binding" is the symbol that gets exported
+// when this file is compiled as a Node.js addon.
+Napi::Object Init(Napi::Env env, Napi::Object exports) {
+  exports["name"] = Napi::String::New(env, "__DSL_NAME__");
+  auto language = tree_sitter___DSL_NAME__();
+  exports["language"] = Napi::External<TSLanguage>::New(env, language);
+  return exports;
+}
+
+NODE_API_MODULE(tree_sitter___DSL_NAME___binding, Init)
diff --git a/tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts b/tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts
new file mode 100644
index 0000000..d25eae0
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts
@@ -0,0 +1,3 @@
+declare const _exports: any;
+export = _exports;
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts.map b/tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts.map
new file mode 100644
index 0000000..ca7a93a
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/js-addon/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/tree-sitter/dsk/dsk-cli/templates/js-addon/index.js b/tree-sitter/dsk/dsk-cli/templates/js-addon/index.js
new file mode 100644
index 0000000..4780f31
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/js-addon/index.js
@@ -0,0 +1,15 @@
+try {
+  module.exports = require("./build/Release/tree_sitter___DSL_NAME___binding");
+} catch (error1) {
+  if (error1.code !== 'MODULE_NOT_FOUND') {
+    throw error1;
+  }
+  try {
+    module.exports = require("./build/Debug/tree_sitter___DSL_NAME___binding");
+  } catch (error2) {
+    if (error2.code !== 'MODULE_NOT_FOUND') {
+      throw error2;
+    }
+    throw error1
+  }
+}
diff --git a/tree-sitter/dsk/dsk-cli/templates/js-addon/package.json b/tree-sitter/dsk/dsk-cli/templates/js-addon/package.json
new file mode 100644
index 0000000..c7a0488
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/templates/js-addon/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "tree-sitter-__DSL_NAME__",
+  "version": "1.0.0",
+  "description": "Tree-sitter parser for __DSL_NAME__",
+  "main": "index.js",
+  "keywords": [
+    "tree-sitter",
+    "parser",
+    "__DSL_NAME__"
+  ],
+  "author": "Generated by DSK",
+  "license": "MIT",
+  "dependencies": {
+    "node-addon-api": "^7.0.0",
+    "node-gyp": "^10.0.0"
+  },
+  "devDependencies": {
+    "tree-sitter-cli": "^0.20.0"
+  },
+  "scripts": {
+    "install": "node-gyp rebuild",
+    "test": "tree-sitter test"
+  },
+  "gypfile": true,
+  "files": [
+    "grammar.js",
+    "src",
+    "index.js",
+    "binding.gyp"
+  ]
+}
diff --git a/tree-sitter/dsk/dsk-cli/test-inference.d.ts b/tree-sitter/dsk/dsk-cli/test-inference.d.ts
new file mode 100644
index 0000000..53c18d9
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/test-inference.d.ts
@@ -0,0 +1,5 @@
+/**
+ * Quick test of the inference engine
+ */
+export {};
+//# sourceMappingURL=test-inference.d.ts.map
\ No newline at end of file
diff --git a/tree-sitter/dsk/dsk-cli/test-inference.d.ts.map b/tree-sitter/dsk/dsk-cli/test-inference.d.ts.map
new file mode 100644
index 0000000..ecf80f8
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/test-inference.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"test-inference.d.ts","sourceRoot":"","sources":["test-inference.ts"],"names":[],"mappings":"AAAA;;GAEG"}
\ No newline at end of file
diff --git a/tree-sitter/dsk/dsk-cli/test-inference.js.map b/tree-sitter/dsk/dsk-cli/test-inference.js.map
new file mode 100644
index 0000000..5d9b120
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/test-inference.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"test-inference.js","sourceRoot":"","sources":["test-inference.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AAErD,8BAA8B;AAC9B,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AACpF,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACrD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;AACrD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/C,OAAO,CAAC,GAAG,EAAE,CAAC;AAEd,kBAAkB;AAClB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AACvC,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AACpE,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACrD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;AACrD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/C,OAAO,CAAC,GAAG,EAAE,CAAC;AAEd,kBAAkB;AAClB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;AAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AACjF,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACrD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;AACrD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/C,OAAO,CAAC,GAAG,EAAE,CAAC;AAEd,mBAAmB;AACnB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;AACpD,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;AACxD,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,MAAM,CAAC,CAAC;AAC/D,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/C,OAAO,CAAC,GAAG,EAAE,CAAC;AAEd,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC"}
\ No newline at end of file
diff --git a/tree-sitter/dsk/dsk-cli/tsconfig.json b/tree-sitter/dsk/dsk-cli/tsconfig.json
new file mode 100644
index 0000000..e1599f7
--- /dev/null
+++ b/tree-sitter/dsk/dsk-cli/tsconfig.json
@@ -0,0 +1,37 @@
+{
+  "compilerOptions": {
+    // Enable latest features
+    "lib": ["ESNext", "DOM"],
+    "target": "ESNext",
+    "module": "ESNext",
+    "moduleDetection": "force",
+    "allowJs": true,
+
+    // Output configuration for CLI tool
+    "moduleResolution": "node",
+    "types": ["node"],
+    "outDir": "./dist",
+    "rootDir": "./src",
+    "declaration": true,
+    "declarationMap": true,
+    "sourceMap": true,
+
+    // Best practices
+    "strict": true,
+    "skipLibCheck": true,
+    "noFallthroughCasesInSwitch": true,
+
+    // Some stricter flags (disabled by default)
+    "noUnusedLocals": false,
+    "noUnusedParameters": false,
+    "noPropertyAccessFromIndexSignature": false
+  },
+  "include": [
+    "src/**/*"
+  ],
+  "exclude": [
+    "templates/**/*",
+    "dist/**/*",
+    "node_modules"
+  ]
+}