Salmon-Loop uses a pluggable architecture to support different programming languages. While TypeScript and JavaScript support is built-in, you can easily extend Salmon-Loop to support other languages like Python, Go, Rust, or even custom DSLs without modifying the core codebase.
When Salmon-Loop starts (in run or chat mode), it scans two locations for language plugins:
- Built-in Plugins: Pre-packaged support (currently TypeScript/JavaScript).
- User Plugins: Custom plugins located in your project's
.salmonloop/languages/directory.
Plugins are loaded dynamically. If a user plugin shares the same ID as a built-in one, the user plugin takes precedence, allowing you to override or enhance built-in behavior.
To add support for a new language, create a directory structure like this in your project root:
.salmonloop/
languages/
my-lang/
index.js # The plugin entry point (ES Module)
parser.wasm # (Optional) Tree-sitter WASM file
Your index.js must export a default object conforming to the LanguagePlugin interface.
// .salmonloop/languages/python/index.js
export default {
meta: {
id: 'python',
name: 'Python Support',
extensions: ['.py']
},
// 1. Detection
detection: {
// Return true if this repository is a Python project
matches: async (repoPath) => {
// e.g. check for requirements.txt
return fs.existsSync(path.join(repoPath, 'requirements.txt'));
}
},
// 2. AST Parsing (using Tree-sitter)
parsing: {
getTreeSitterWasm: async () => {
// Return absolute path to your .wasm file
return path.join(__dirname, 'tree-sitter-python.wasm');
},
queries: {
// Tree-sitter query to find function/class definitions
definitions: `
(function_definition name: (identifier) @name) @def
(class_definition name: (identifier) @name) @def
`,
// Tree-sitter query to find references/calls
references: `
(call function: (identifier) @name) @ref
`
}
},
// 3. Dependency Analysis
dependency: {
extractImports: (content) => {
// Return list of imported file paths
// e.g. Regex to match "import foo" or "from foo import bar"
return [];
},
resolvePath: (basePath, importPath) => {
// Resolve relative path to absolute file path
return path.resolve(basePath, importPath + '.py');
}
},
// 4. Error Diagnostics
diagnostics: {
classifyError: (output) => {
if (output.includes('SyntaxError')) return 'compilation';
if (output.includes('AssertionError')) return 'test';
return undefined;
}
}
};A language plugin provides four key capabilities:
- Detection: Helps Salmon-Loop identify the project type quickly.
- Parsing: Provides Tree-sitter queries to understand code structure (definitions and references). This is crucial for the "Context Shrinking" feature to work effectively.
- Dependency: Enables the system to trace imports and fetch related context automatically.
- Diagnostics: Classifies command output (stdout/stderr) into standard error types (Compilation, Lint, Test, etc.), helping the AI understand why a verification failed.
- Performance: Keep your detection logic fast. Avoid scanning the entire
node_modulesor.venv. - WASM: If you use Tree-sitter, ensure the
.wasmfile is compatible with the version ofweb-tree-sitterused by Salmon-Loop. - Error Handling: Your plugin runs in the main process. While we wrap calls in try-catch blocks, a crashing plugin can still degrade the experience.