Execute commands automatically on file save in Visual Studio Code.
Catalyst enables you to automate development workflows by executing shell commands instantly whenever specific files are saved. Whether you need to apply formatters, linters, code generators, tests, or build tasks, this extension handles it seamlessly in the background.
Automatically format TypeScript, JavaScript, and JSON files on save:
{
"catalyst-run-on-save.actions": [
{
"name": "Prettier Format",
"command": "npx prettier --write \"${file}\"",
"include": ["**/*.ts", "**/*.js", "**/*.json"],
"exclude": ["**/node_modules/**"]
}
]
}Automatically fix linting issues in TypeScript and JavaScript files on save:
{
"catalyst-run-on-save.actions": [
{
"name": "ESLint Fix",
"command": "npx eslint --fix \"${file}\"",
"include": ["**/*.ts", "**/*.js"],
"exclude": ["**/node_modules/**"]
}
]
}Run different Gradle scripts based on the active operating system to format Java and Kotlin files:
{
"catalyst-run-on-save.actions": [
{
"name": "Spotless Format (Gradle)",
"command": {
"windows": "${workspaceFolder}\\gradlew.bat spotlessApply -PspotlessFiles=\"${file}\"",
"default": "${workspaceFolder}/gradlew spotlessApply -PspotlessFiles=\"${file}\""
},
"include": ["**/*.java", "**/*.kt"],
"exclude": ["**/build/**"]
}
]
}Automatically compile and run tests in a Go project when code changes:
{
"catalyst-run-on-save.actions": [
{
"name": "Build & Test Go Project",
"command": "go build ./... && go test ./...",
"include": ["**/*.go"],
"exclude": ["**/vendor/**"]
}
]
}Configure the extension inside your VS Code settings.json file.
| Setting | Type | Default | Description |
|---|---|---|---|
catalyst-run-on-save.actions |
array |
[] |
List of actions to execute on file save. |
catalyst-run-on-save.showErrorPopups |
boolean |
true |
Show notification popups if an action command exits with an error. |
catalyst-run-on-save.showOutput |
string |
"onError" |
Auto-reveal output channel behavior ("never", "onError", "always"). |
Each action object in catalyst-run-on-save.actions supports the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
name |
string |
No | A descriptive label for the action (used in logs and error notifications). |
command |
string or object |
Yes | The shell command to run. To use platform-specific commands, pass an object with keys: windows, macos, linux, or default. |
include |
string[] |
No | Glob patterns indicating which files trigger the action. Matches all files if omitted. |
exclude |
string[] |
No | Glob patterns to prevent matching files from triggering the action. |
shell |
string |
No | Absolute path to a custom shell executable (e.g., /bin/zsh, powershell.exe). |
timeout |
number |
No | Execution timeout limit in milliseconds. The process is terminated if it exceeds this threshold. Omitted or 0 disables timeout. |
cwd |
string |
No | Custom working directory for executing the command. Supports variable placeholders (defaults to ${workspaceFolder}). |
env |
object |
No | Key-value map of environment variables passed to the spawned process (e.g. { "NODE_ENV": "development" }). |
Note: Globs are evaluated relative to your workspace root directory. They support both standard file extension patterns (e.g.,
**/*.ts) and directory-specific exclusions.
You can embed the following placeholders in your command strings:
| Variable | Description | Example Output |
|---|---|---|
${workspaceFolder} |
Absolute path of the active workspace folder | /Users/alice/Code/my-app |
${workspaceFolderBasename} |
The folder name of the workspace root | my-app |
${file} |
Absolute path of the saved file | /Users/alice/Code/my-app/src/config.json |
${relativeFile} |
Workspace-relative path of the saved file | src/config.json |
${relativeFileDirname} |
Workspace-relative directory of saved file | src |
${fileBasename} |
Filename including extension | config.json |
${fileBasenameNoExtension} |
Filename excluding extension | config |
${fileExtname} |
Only the file extension | .json |
${fileDirname} |
Absolute path of the saved file's directory | /Users/alice/Code/my-app/src |
${pathSeparator} |
System path separator (/ or \) |
/ |
${env:VAR_NAME} |
Value of environment variable VAR_NAME |
alice |
Catalyst contributes interactive commands via the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) and a status bar indicator:
| Command | Title | Description |
|---|---|---|
catalyst.toggle |
Catalyst: Toggle Execution on Save | Globally enable or disable automatic execution on file save. Also toggled by clicking the status bar item. |
catalyst.run |
Catalyst: Run Actions for Active File | Manually trigger matching run-on-save actions for the active text editor document. |
catalyst.showOutput |
Catalyst: Show Output Channel | Open the Catalyst log output channel. |
Problem: Commands are not running or are failing silently, making it difficult to debug the issue.
Solution: Check the extension logs in VS Code:
- Open the Output panel in VS Code (
View>OutputorCmd+Shift+U/Ctrl+Shift+U). - Select Catalyst from the dropdown menu in the top-right corner.
- Review the execution logs to inspect target file matches, resolved command strings, and shell exit codes.
Problem: If your file paths contain spaces or special characters, commands might fail or parse incorrectly.
Solution: Always wrap ${file} and other path variables in double quotes within your command template, for example: npx prettier --write "${file}".
Problem: VS Code commands run in a non-interactive shell environment that might not load all of your user profile configurations (like custom alias settings or dynamic PATH expansions from .bashrc or .zshrc), causing commands to fail because they cannot be found.
Solution:
- Use absolute paths for commands (e.g.,
/usr/local/bin/nodeinstead of justnode) if they cannot be found. - Specify a custom shell executable using the
shelloption (e.g.,/bin/zshorpowershell.exe) if you need a specific shell context.
Behavior: If a file is saved again while an action for that file is still executing, Catalyst sends a SIGTERM signal to cancel the previous child process before launching the new run, preventing overlapping process contention.
Problem: Running heavy build or compile commands on every save can slow down your workspace and consume high CPU resources.
Solution: Use the exclude property to ignore files in temporary directories (e.g., **/tmp/**), build folders (e.g., **/dist/**, **/build/**), or dependency folders (e.g., **/node_modules/**).