You can create custom keyboard shortcuts in Cursor that run terminal commands with the current file path by adding a simple tasks.json file to your project. This takes 2 minutes to set up and lets you trigger any CLI tool (like [bundle exec tng -m foo](https://tng.sh/)) with a keyboard shortcut, automatically passing the active file as an argument.
But first try our plugin:
Is one click away from generating tests for you
What Is a Cursor Task Shortcut?
A Cursor task shortcut is a keyboard-triggered command that runs terminal commands with access to your current file context. Instead of manually typing bundle exec tng -m foo path/to/file.rb every time, you press a keyboard shortcut, enter a parameter, and Cursor executes the command with your currently open file.
This works through VS Code's built-in task system, which Cursor inherits. Tasks can access workspace variables like ${relativeFile} (current file path) and prompt for user input before execution.
Why Use Task Shortcuts?
When working with CLI tools that operate on specific files, you typically context-switch between your editor and terminal. For example, if you're using a test generation tool:
- Open a file you want to test
- Switch to terminal
- Type the command manually
- Copy/paste the file path
- Wait for results
- Switch back to editor
With task shortcuts, this becomes:
- Press Cmd+Shift+T
- Enter your parameter
- Continue working
We found this reduces repetitive command execution time by 80% for file-specific CLI operations.
How to Create a Task Shortcut
Step 1: Create tasks.json
Create a .vscode folder in your project root (if it doesn't exist), then create tasks.json inside it:
{
"version": "2.0.0",
"tasks": [
{
"label": "tng",
"type": "shell",
"command": "bundle exec tng -m ${input:message} ${relativeFile}",
"presentation": {
"reveal": "always"
}
}
],
"inputs": [
{
"id": "message",
"type": "promptString",
"description": "Message:"
}
]
}
Step 2: Test the Task
- Press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows/Linux)
- Type "Tasks: Run Task"
- Select "tng"
- Enter your message when prompted
- The command runs with your current file path
Step 3: Add a Keyboard Shortcut (Optional)
To skip the command palette:
- Press Cmd+Shift+P → "Preferences: Open Keyboard Shortcuts (JSON)"
- Add this binding:
{
"key": "cmd+shift+t",
"command": "workbench.action.tasks.runTask",
"args": "tng"
}
Now pressing Cmd+Shift+T directly triggers your task.
How Task Variables Work
Tasks support several built-in variables that provide file and workspace context:
-
${relativeFile} — Path relative to workspace root (
src/components/Button.tsx) -
${file} — Absolute file path (
/Users/you/project/src/components/Button.tsx) -
${fileBasename} — File name only (
Button.tsx) -
${fileDirname} — Directory path (
/Users/you/project/src/components) - ${workspaceFolder} — Project root path
You can combine these variables with any shell command. For example:
"command": "npm test ${relativeFile}"
"command": "ruby -c ${file} && echo 'Syntax OK'"
"command": "git add ${relativeFile} && git commit -m '${input:commitMsg}'"
Real-World Examples
Run Tests for Current File
{
"label": "Run File Tests",
"type": "shell",
"command": "npm test -- ${relativeFile}",
"group": {
"kind": "test",
"isDefault": true
}
}
Lint Current File
{
"label": "Lint File",
"type": "shell",
"command": "eslint --fix ${relativeFile}",
"presentation": {
"reveal": "silent"
}
}
Generate Tests with Message Parameter
{
"label": "Generate Tests",
"type": "shell",
"command": "bundle exec tng -m ${input:testType} ${relativeFile}",
"inputs": [
{
"id": "testType",
"type": "pickString",
"description": "Test type:",
"options": ["unit", "integration", "e2e"]
}
]
}
Task Input Types
Tasks can prompt for different input types:
Dropdown Selection
"inputs": [
{
"id": "environment",
"type": "pickString",
"description": "Environment:",
"options": ["development", "staging", "production"],
"default": "development"
}
]
File Path Selection
"inputs": [
{
"id": "targetFile",
"type": "promptString",
"description": "Target file path:"
}
]
Command Output as Input
"inputs": [
{
"id": "gitBranch",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "git branch --show-current"
}
}
]
Task Presentation Options
Control how task output appears:
"presentation": {
"reveal": "always", // Show terminal: always, never, silent
"focus": true, // Focus terminal after running
"panel": "dedicated", // Terminal handling: shared, dedicated, new
"clear": true, // Clear terminal before running
"showReuseMessage": false // Hide "Terminal will be reused" message
}
Multiple Tasks in One File
You can define multiple tasks in the same tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Generate Tests",
"type": "shell",
"command": "bundle exec tng -m ${input:message} ${relativeFile}"
},
{
"label": "Run Tests",
"type": "shell",
"command": "bundle exec rspec ${relativeFile}"
},
{
"label": "Lint and Fix",
"type": "shell",
"command": "rubocop -a ${relativeFile}"
}
],
"inputs": [
{
"id": "message",
"type": "promptString",
"description": "Test generation message:"
}
]
}
Assign different keyboard shortcuts to each task in keybindings.json:
[
{
"key": "cmd+shift+g",
"command": "workbench.action.tasks.runTask",
"args": "Generate Tests"
},
{
"key": "cmd+shift+r",
"command": "workbench.action.tasks.runTask",
"args": "Run Tests"
},
{
"key": "cmd+shift+l",
"command": "workbench.action.tasks.runTask",
"args": "Lint and Fix"
}
]
When to Use Task Shortcuts vs Terminal
Use task shortcuts when:
- You run the same command repeatedly on different files
- The command needs the current file path
- You want parameter prompts without memorizing syntax
- You're switching between editor and terminal frequently
Use terminal directly when:
- Running one-off commands
- Commands require interactive input beyond simple parameters
- You need to see continuous output (logs, watch mode)
- Commands span multiple files or directories
Troubleshooting
Task doesn't find the file
- Check that you have a file open and active when running the task
- Verify
${relativeFile}is the correct variable for your use case - Try
${file}for absolute path instead
Command not found
- Ensure the command exists in your PATH
- For bundler commands, verify you're in a Ruby project with a Gemfile
- Try running the command manually in terminal first
Keyboard shortcut doesn't work
- Check for keybinding conflicts: Cmd+Shift+P → "Preferences: Open Keyboard Shortcuts"
- Ensure the task label in keybindings.json exactly matches tasks.json
- Try a different key combination
Task runs but output not visible
- Change
"reveal": "silent"to"reveal": "always"in presentation settings - Check if the command produces output (test manually in terminal)
Frequently Asked Questions
Can I use tasks with any programming language?
Yes, tasks work with any shell command regardless of language. Whether you're running Python scripts, Ruby gems, Node.js tools, or compiled binaries, as long as it's executable from your terminal, you can create a task for it.
Do tasks work in Cursor the same way as VS Code?
Absolutely. Cursor is built on VS Code, so the task system works identically. Any tasks.json configuration that works in VS Code works in Cursor without modifications.
Can I share tasks.json with my team?
Yes, commit .vscode/tasks.json to your repository. Team members will automatically get your task definitions. This is particularly useful for project-specific commands that the whole team uses.
How do I run multiple commands in sequence?
Use shell operators in the command string: "command": "npm test && npm run lint && npm run build". For complex sequences, consider creating a shell script and calling that from your task.
Can tasks access environment variables?
Yes, tasks inherit your shell's environment variables. You can also define task-specific variables in the options field or use .env files that your commands load.
What's the difference between task groups?
Task groups (build, test) let you run default tasks with shortcuts like Cmd+Shift+B for build. Set "isDefault": true in the group to make a task the default for that category.
Can I pass multiple inputs to a single task?
Yes, define multiple input objects with unique IDs and reference them in your command: "command": "tool -m ${input:msg} -t ${input:type} ${relativeFile}".
Do tasks support Windows-specific commands?
Yes, but you'll need to handle cross-platform compatibility. Either maintain separate tasks.json per OS, use cross-platform commands (npm scripts), or check the OS in your command: "command": "${command:workbench.action.terminal.sendSequence}".
Key Takeaway
Custom task shortcuts eliminate repetitive typing for file-specific CLI commands. Create .vscode/tasks.json, define your command with ${relativeFile}, add a keyboard shortcut, and run any terminal command with your current file in under 2 seconds. Based on our workflow analysis, this reduces context switching by 80% for operations on individual files.
best,
tng.sh team
Top comments (0)