MInd Rig is an editor companion that helps to work on, test (in a playground and using evals) defined in source code. Right now it's in progress, so now all features planned are implemented.
This is a monorepo managed by Turborepo and pnpm with the following packages:
VS Code extension package containing the main extension logic and webview provider.
Stack:
- TypeScript
- VS Code Extension API
- Vite as the bundler
- vscode-test (extension integration tests)
Available commands:
pnpm turbo build --filter vscode- Build the extensionpnpm turbo watch --filter vscode- Watch and rebuild on changespnpm turbo package --filter vscode- Package for productionpnpm turbo test --filter vscode- Run e2e testspnpm turbo lint --filter vscode- Lint TypeScript codepnpm turbo pack --filter vscode- Create VSIX packagepnpm turbo publish --filter vscode- Publish to marketplace
React webview application that provides the UI for the MInd Rig panel.
Stack:
- TypeScript
- React 18
- Vite as the bundler
- Tailwind CSS
- PostCSS
Available commands:
pnpm turbo build --filter @mindcontrol/vscode-webview- Build the webviewpnpm turbo watch --filter @mindcontrol/vscode-webview- Watch and rebuild on changespnpm turbo package --filter @mindcontrol/vscode-webview- Package for productionpnpm turbo serve --filter @mindcontrol/vscode-webview- Development serverpnpm turbo lint --filter @mindcontrol/vscode-webview- Lint TypeScript/React code
VS Code synchronization package for managing state and communication between the extension and webview. It includes common types and utilities.
VS Code types package containing common type definitions for the extension and webview.
Shared type definitions using the Genotype programming language for cross-language type safety between TypeScript and Rust packages.
Stack:
- Genotype programming language for type definitions
- Generates TypeScript types in
types/pkgs/ts - Generates Rust types in
types/pkgs/rs - Automatically included in both pnpm (pkg/ts) and Rust (pkg/rs) workspaces
Available commands:
gt build- Generate TypeScript and Rust types from Genotype definitions- IMPORTANT: Never manually edit the generated
types/pkgs/directories
Language Guide: Reference the Genotype language guide and syntax examples
Rust-based parser crate that compiles to WebAssembly to power JS/TS code parsing in the extension.
Stack:
- Rust (edition 2024)
- wasm-bindgen for JS interop
- serde for serialization
- Compiles to WebAssembly module consumed by the extension
- insta for snapshot testing (with inline snapshots preferred)
- watchexec for watching Rust tests
Available commands:
pnpm turbo build --filter @mindcontrol/code-parser- Compile Rust to WebAssemblypnpm test:rs- Run Rust tests (from workspace root)pnpm test:rs:watch- Watch Rust tests with watchexec (from workspace root)pnpm test:rs:review- Review insta snapshots (from workspace root)
Parser-specific commands (from parser/ directory):
pnpm run build- Build WebAssembly modulepnpm run test- Run Rust testspnpm run test:watch- Watch Rust tests with watchexecpnpm run test:review- Review insta snapshots
Important Notes:
- The
parser/pkg/directory is automatically generated by wasm-bindgen during the build process and should never be manually edited. TypeScript definitions and JavaScript bindings are automatically generated from the Rust source code. - We use insta for snapshot testing and prefer storing snapshots inline for easier test readability
- Never accept insta snapshots yourself - always prompt the developer to run
pnpm test:rs:revieworpnpm run test:reviewto accept snapshots - Always run nextest with
--no-fail-fast- This ensures all snapshot tests run and generate diffs, allowing you to review all changes at once instead of one by one
The project uses a Turborepo-orchestrated multi-package architecture with isolated dependencies:
- Extension package: Builds Node.js/CommonJS code for VS Code extension host
- Webview package: Builds React app as ES modules for webview display
- Parser package: Rust crate compiled to WebAssembly, consumed by extension
- Build output: Webview builds into
extension/dist/webview/, extension builds intoextension/dist/extension/ - Distribution: Extension package contains both webview and parser outputs for VS Code marketplace
The parser package requires:
- Rust toolchain (defined in
rust-toolchain.toml) - wasm-pack for WebAssembly compilation
- Build script at
parser/scripts/build.sh
From the root directory using Turborepo:
- Build all packages:
pnpm turbo build - Build specific package:
pnpm turbo build --filter @mindcontrol/code-vscode - Build webview:
pnpm turbo build --filter @mindcontrol/code-webview - Build parser:
pnpm turbo build --filter @mindcontrol/code-parser - Watch extension:
pnpm turbo watch --filter @mindcontrol/code-vscode - Watch webview:
pnpm turbo watch --filter @mindcontrol/code-webview
Or use VS Code tasks:
Ctrl+Shift+P→Tasks: Run Task→build:extensionorbuild:webviewCtrl+Shift+P→Tasks: Run Task→watch:extensionorwatch:webview
From the root directory:
- Run extension e2e tests:
pnpm turbo test --filter vscode
The e2e tests use @vscode/test-cli and Playwright to test the extension in an actual VS Code instance. The tests connect to VS Code using Chromium DevTools protocol and use Playwright's expect API combined with Mocha test framework.
Note: Run the e2e tests whenever the extension setup has changed. For now, webview tests should be skipped until explicitly requested.
- MVP with playground for prompts defined in source code
- Prompts explorer that allows to find all prompts and quickly navigate
- Prompt evals to automatically test project prompts
Use the following pattern for React components:
export namespace ComponentName {
export interface Props {
// Component props interface
}
}
export function ComponentName(props: ComponentName.Props) {
const {
/* Destructure props here */
} = props;
return <div>...</div>;
}Simplification rules:
- If component has no props, omit the Props interface and namespace
- If props are not destructured, omit the destructuring assignment
- Only include what is actually needed
// Simple component with no props
export function SimpleComponent() {
return <div>Simple content</div>;
}This approach provides:
- Clear namespace organization when needed
- Type safety with props interface
- Consistent destructuring pattern
- Explicit function component definition
- Minimal boilerplate for simple cases
Use the following patterns for TypeScript classes:
- Use
#privateNameinstead of theprivatekeyword when possible - Don't add explicit
publickeyword - methods and properties are public by default - Exception: Static members cannot use
#syntax, so useprivate staticfor those
export class ExampleClass {
static readonly CONSTANTS = ["value1", "value2"]; // public static (default)
private static hiddenValue = "secret"; // private static (can't use #)
#privateProperty: string;
regularProperty: number; // public by default
constructor(value: string) {
this.#privateProperty = value;
this.regularProperty = 42;
}
#privateMethod(): void {
// private method implementation
}
regularMethod(): string {
// public by default
return this.#privateProperty;
}
}Benefits:
- Modern JavaScript/TypeScript syntax
- True privacy (not just TypeScript compile-time)
- Cleaner code without redundant
publickeywords - Consistent with current JavaScript standards
- Use pnpm as the package manager for this project
- Always use
pnpmcommands instead ofnpmornpx - Example:
pnpm run watch,pnpm install,pnpm run build
- Use Prettier with default settings (configured in
.prettierrc) - When executing multi-step plans, format code once after the entire plan is executed rather than on each individual step
- This improves efficiency and reduces unnecessary intermediate formatting operations
- Always run
pnpm turbo formatafter completing a plan to ensure consistent code formatting across the entire codebase
- Always use
JSON.stringify()for object logging in both webview and extension code - This ensures objects are fully expanded in the console without needing manual expansion
- Example:
console.log("Debug info", JSON.stringify({ property: value }))instead ofconsole.log("Debug info", { property: value }) - This is especially important for VS Code extension development where console object inspection can be limited
- Always consult relevant specs when planning work in any monorepo package
- Check both the package-level
./specsdirectory and the root./specsdirectory for applicable specifications - Use the
000-index.mdfile in each specs directory to quickly find relevant specifications - Specifications contain detailed requirements, implementation decisions, and technical context
- Keep
000-index.mdfiles updated when adding or modifying specifications - Each monorepo package has its own specs directory:
parser/specs,vscode/extension/specs,vscode/webview/specs - Follow established naming conventions:
001-feature.md,002-component.md, etc. - ALWAYS update the corresponding
000-index.mdfile when creating new specifications to maintain consistency
- Use links for file references instead of plain text
- Example:
package.jsoninstead ofpackage.json - This makes files clickable and easier to navigate in IDEs
- Use checkbox syntax for tasks and future plans:
- [ ]for incomplete,- [x]for completed - This provides clear visual status and allows for easy tracking of progress
- When adding new instructions, ensure they are not redundant with existing content
- Check that new guidelines do not contradict previous instructions
- Keep examples consistent with established patterns and naming conventions
- Remove or update conflicting information when making changes