Do you know Stream Deck?
It's so cool, isn't it? I've been admiring it for about two years.
However, when I looked into it, I found it somewhat lacking for developers—you can't dynamically add buttons, and the only context-switching mechanism is based on which application window has focus...
That would make it just a glorified shortcut launcher, and as a developer, I tend to just memorize the shortcuts I need. So I had no reason to buy one and kept hesitating.
But about two weeks ago, I had a sudden urge to get a Stream Deck, and I made a decision.
I just needed to invent a reason to buy one.
So I built a Stream Deck plugin + VSCode extension that can dynamically display and execute NPM Scripts from VSCode. It occupies one page on the Stream Deck and follows dynamic context changes in VSCode.
As I kept hacking on it with the real device, it somehow evolved into a multi-language-capable VSCode–Stream Deck integration framework + NPM Scripts provider.
I'll explain the VSCode Stream Deck integration framework later.
This is convenient when you want to run multiple long-running scripts simultaneously, or when executing scripts with long names that are difficult to autocomplete due to NPM Scripts conventions (like test:sub:ui).
It supports multiple VSCode instances, monorepos, and multiple Stream Deck devices. Display is also customizable.
Even without a physical Stream Deck device, you can easily try it on your PC using Virtual Stream Deck. But of course, trying it on the real device is the best.
Because it looks this cool!
Installation
Install the VSCode extension NPM Scripts Deck.
Stream Deck Integration will also be installed as a dependency. This is the VSCode Stream Deck integration framework mentioned later.
You also need to install a plugin on the Stream Deck side. I'd like you to install VSCode Runner from the Elgato Marketplace, but currently there's an issue with Elgato Marketplace's submission system, and the review process is taking quite a while. So I'm patiently working through that, but for now, please download com.ugaya40.vscode-runner.streamDeckPlugin from the GitHub Releases and double-click to install.
You can uninstall it using the same procedure as other Stream Deck plugins. Manual installation doesn't leave any extra traces in your environment.
Usage
Just open a folder containing package.json in VSCode. Even with a monorepo, buttons are displayed based on the ancestor package.json relative to the active editor file.
Press a button to execute the target npm script. While running, it shows "Running" status, and success/failure is displayed with visual feedback for a few seconds.
For long-running tasks, you can cancel by pressing the button again. The result is also shown with visual feedback.
For example, with a package.json like this:
{
"scripts": {
"build": "...",
"build:server": "...",
"build:client": "...",
"dev": "...",
"dev:server": "...",
"dev:client": "...",
"lint": "...",
"preview": "..."
}
}
It displays with some color coding by default.
ns-deck.json
If you don't want to display certain packages or scripts, want more flexible color coding, or want to change icons, place an ns-deck.json in the same directory as package.json.
The file can be empty. If there's even one ns-deck.json in the workspace opened by VSCode, only the NPM Scripts from package.json files in the same directory as an ns-deck.json will be displayed on Stream Deck. NPM Scripts from package.json files without a corresponding ns-deck.json in the same directory won't be shown.
For details, please refer to the NPM Scripts Deck documentation page, but for example, if you configure ns-deck.json like this, the default display above changes to this:
{
"styles": [
{ "match": "build", "icon": "Package", "textColor": "#ffffff" },
{ "match": "/build/", "icon": "Hammer" },
{ "match": "/server/", "textColor": "#00bfff" },
{ "match": "/client/", "textColor": "#ff6600" }
]
}
Stream Deck Integration
Stream Deck Integration is a VSCode extension that handles communication with Stream Deck, integration of multiple VSCode instances, and coordination of multiple Providers.
A single VSCode instance can communicate between extensions using the Extension API.
However, there's no built-in way for multiple VSCode windows to communicate with each other. This means Stream Deck cannot follow the context of multiple windows. I implemented this VSCode extension as a foundation to handle all these problems.
Among the VSCode instances with this extension installed, one becomes the Leader, the others become Followers, and the Leader communicates with Stream Deck on behalf of all instances.
It uses WebSocket and GET/POST for Stream Deck and Leader↔Follower communication.
A promotion system when the Leader instance crashes is also implemented, and when implementing your own Provider compatible with Stream Deck Integration, you can relatively easily implement your own Provider without being aware of multiple VSCode instances.
For details, please see the Stream Deck Integration documentation page. It also describes settings for when multiple Providers coexist.
Implementing Custom Providers
By leveraging the Stream Deck Integration framework, you can easily implement providers for other languages or shortcut providers for VSCode. Git, Docker, dotnet, etc.—the possibilities are endless.
Multiple Providers can coexist on Stream Deck Integration, and no matter how many Providers are added or updated, Stream Deck Integration and VSCode Runner (Stream Deck side plugin) don't need updates.
For details, please refer to the Custom Provider Guide, but there are basically only 4 things a custom Provider needs to implement:
- Call
registerProvider(registration API for Stream Deck Integration) - Implement
getSlotsfunction (corresponds to/listin communication—retrieves button data to display) - Implement
runfunction (corresponds to/runin communication—executes command for the button) - Call
notifyChangewhen the buttons to display on Stream Deck change
If you want to support long-running tasks for your Provider, you'll also need to:
- Implement
cancelfunction (corresponds to/cancelin communication) - Notify status through
notifyTaskCompletewhen task completes
That's it. By implementing just these without worrying about multiple VSCode instances, you automatically get multiple VSCode instance support.
Conclusion
This project itself is a monorepo (NPM Scripts Deck / Stream Deck Integration / VSCode Runner), and I developed it with just one ns-deck.json placed in the same directory as the root package.json.
It's quite convenient, so please buy a Stream Deck!
It boosts your development mood too!
Originally published in Japanese on Zenn





Top comments (0)