Why I wrote 33 VSCode extensions and how I manage them

By Fabio Spampinato

They say posts with great images attract more viewers…

Hey there 👋 I’m Fabio, a self-taught developer passionate about open source and empowering people. I also like to make my own tools, so naturally I ended up writing a lot of extensions for one of the programs I spend a lot of my time on: VSCode.

I’d like to share with you a bit of my workflow when developing and managing VSCode extensions as well as talking about all the ones I created.

I’m going to mention many, mostly unknown, tools and extensions that I created, so whether you want to get started developing extensions, want to find cool new extensions, or just have a lot of repositories to manage I promise you’ll find something interesting in here!

I like productivity and automation, so the way I start new projects is very streamlined.

I wrote template for starting new projects quickly, it’s very simple:

  1. it takes a folder as input (the “template”).
  2. it processes all its files with handlebars asking you for replacements for each placeholder it finds (i.e. {{name}}).
  3. it outputs a new folder with all placeholders replaced.

I’ve taken a look at yeoman but it seems overly complicated for my use cases. I’ve used khaos but it’s unmaintained and it doesn’t update templates automatically, I can’t be asked to update them manually every time I want to use them.

I’m then using my template-vscode-extension template for starting a new VSCode extension.

And now I have a working Hello-World-ish extension. That template includes many helper functions I end up using frequently: it supports loading a custom configuration file from the .vscode folder, it automatically registers commands, it can infer the current root based on the active file etc.

If I could go back in time I’d probably put all these helper functions into a standalone vscode-utils package rather than duplicating them in all my extensions, unfortunately I didn’t know from the beginning that I’ll be making 10s of extensions, now updating all of them would require quite a bit of time.

If you’re thinking about making VSCode extensions I’d recommend you to make your own template, perhaps starting from mine as a basis.

I always have the docs open when I’m developing extensions. It’s kind of a long page and it’s not that straightforward to find the API you need if you don’t know it exists already, but give it a quick read and you’ll soon get familiar with it, overall I’m pretty satisfied with the available APIs.

You’ll want to read the whole section about “Extensibility Reference” too.

Believe it or not some of the extensions I made help me actually develop other extensions, more on this later.

As I said I like productivity, so most of my extensions are productivity-related. I try not to reinvent the wheel too much, and to keep features well separated between extensions while ensuring that they work well with each other.

For good or for worse I find making extensions fun, and there’s no shortage of things that could be automated, that’s why after the first extension I did a second one, a third one… and a thirty-third one!

Check each extension’s page for more detailed info and screenshots.

#1 Debug Launcher: Start debugging (even single files!), without having to define any tasks or launch configurations, even from the terminal. I didn’t want to clutter my repositories with repetitive launch configurations and tasks (who uses tasks anyway?). Launching the debugger from the terminal should really be included in VSCode itself though.

Launching the debugger from the terminal

#2 StatusBar Debugger: Adds a debugger to the statusbar, less intrusive than the default floating one. Because the default toolbar just sucks. If only they exposed more state this extension could be so much better.

#3 Install .VSIX: Install .vsix extensions right from the explorer, with a right click. Because installing .vsix sucks too.

#4 Bump: Bump your project’s version and update the changelog. Opinionated but configurable. Every respectable extension needs a changelog, but that doesn’t mean that you have to write one manually. This extensions is one of my favorites, I’ll probably make a CLI version out of it, and in the future I want it to make GitHub releases for me too.

Bump usage

#5 Optimize Images: Optimize one or all the images in your project using your favorite app. Just one command and you’re done.

#6 Projects+: An extension for managing projects. Feature rich, customizable, automatically finds your projects. Project Manager is the most used extension of this kind, but I have more than a hundred repositories, I need the right tools for managing them, one of which is indefinitely nestable groups.

Projects+ customizable quickpick

#7 Todo+: Manage todo lists with ease. Powerful, easy to use and customizable. If you don’t need syntax highlighting for TODO files, and perhaps you want basic highlighting built-in you might want to check out Todo Tree, it’s pretty good.

Todo+ syntax highlight and project-level statistics

#8 Highlight: Advanced text highlighter based on regexes. Useful for todos, annotations etc. Most people just use TODO Highlight, but mine is way more general and way more powerful, it’s probably faster too.

#9 Markdown Todo: Manage todo lists inside markdown files with ease. Nothing fancy, but makes some Todo+’s shortcuts that you know and love basically work inside Markdown files.

#10 Projects+ Todo+: Bird’s-eye view over your projects, view all your todo files aggregated into one. If you’re using Projects+ for managing for projects, and Todo+ for managing your todos, you can now aggregate all your todos across all (or some) of your projects into one file.

Switching quickly between different apps/websites is important for me, this is way I made many Open in... extensions.

#11 Open in Application: Open an arbitrary file in its default app, or the app you want. A generalized Open in... extension.

#12 Open in Browsers: Adds some commands for opening the current file or project in any browser you like, even all of them simultaneously.

#13 Open in Code: Switch between Code and Code Insiders with ease.

#14 Open in Finder: Adds a few commands for opening the current file or project in Finder.

#15 Open in GitHub: Open the current project or file in github.com. There are many other extensions for this, but when I tried them they were just super bloated with stuff I don’t need or didn’t work.

#16 Open in GitTower: Adds a command for opening the current project in GitTower.

#17 Open in Marketplace: Adds a command for opening the current project in the Marketplace.

#18 Open in node_modules: Open the current selection or arbitrary string node_modules. Useful when you want to dive deeper into the modules you’re using.

#19 Open in NPM: Open the current selection, project, or arbitrary string, in npmjs.com. Useful for quickly viewing the readme.

#20 Open in Ship: Adds a command for opening the current project in Ship. Unfortunately Ship has been deprecated and it doesn’t work anymore. I now have a dedicated tab in Noty for managing upcoming issues.

#21 Open in Terminal: Adds a few commands for opening the current project in Terminal.

#22 Open in Transmit: Adds a few commands for opening the current file or project in Transmit.

#23 Browser Refresh: Refresh the browser with a ⌘R, right from Code. No need to switch focus to it. Useful when you can’t use hot reloading, and if you don’t want browser-sync to refresh the page when not necessary.

#24 Commands: Trigger arbitrary commands from the statusbar. Supports passing arguments!

Custom commands defined via Commands

#25 Diff: Diff 2 opened files with ease. Because running code — diff path1 path2 is too slow.

#26 Git File History: View or diff against previous versions of the current file. There are many other extensions for this, but when I tried them they were just super bloated with stuff I don’t need or didn’t work.

#27 GitHub Notifications: A secure, customizable, statusbar icon that notifies you about notifications on GitHub.

#28 Monokai Night Theme: A complete, dark and minimalistic Monokai-inspired theme. No one theme that I tried looked just right, I had to make my own.

Monokai Night Theme

#29 No [Unsupported]: An extension for removing “[Unsupported]” from the titlebar. This is deprecated now, I recommend Fix VSCode Checksums instead. Unfortunately after some discussion, and some more discussion, the “[Unsupported]” suffix is this there, ready to annoy us.

#30 Open Multiple Files: Open all files in a folder at once, optionally filtering by a glob.

#31 Search — Open All Results: Open all search results at once with a single command.

#32 Terminals Manager: An extension for setting-up multiple terminals at once, or just running some commands. This was actually my first extension! If you use terminals at all you should check this one out, it’s pretty great.

#33 Transmit: Adds a few commands for interacting with Transmit.

Phew! That took a while. Fun bit of trivia: I think I have the account with the most extensions published in the Marketplace right after Microsoft, at least if there’s somebody with more extensions published I haven’t found him/her.

Managing multiple repositories can be a challenge, here’s how I’m doing it.

Sooner or later you’ll want to change something in all of your repositories, that means doing basically the same commits across multiple repositories, which gets boring quickly.

For automating these kinds of tasks I’ve made autogit, a tool for executing commands across multiple repositories.

Example shell command executed via autogit

I keep finding uses for it, just recently I used it for making the following changes across all my extensions’ repositories:

  • Bundling with webpack: I’m seeing improved startup times up to ~80%.
  • Ignored package-lock.json: It’s just noise in my commits history, read Sindre Sorhus’ reasons for ignoring it here.
  • Updating tsconfig.json for outputting modern code: async functions, which I use pretty heavily, get transpiled to slow code when the target version is <= es5, and since VSCode is shipping with a modern version of Node.js there’s no need for this.
  • Removed TSLint: I noticed I basically ignored it’s output, so I removed support for linting in general.
  • Using the hi-res logo in the readme: using the hi-res logo in the readme instead of the 128x128 one I was using before contributes to a better readme, unfortunately I don’t have particularly good logos but that’s another story :)

You can see how doing just these 5 changes, but across 33 repositories, adds up quickly.

This is something one doesn’t have to do, but it would be nice if there was a tool that does this for you. Luckily autogit and the autogit-command-github-sync command can do that too:

Synchronizing via autogit

I also made autogit-command-github-publish for automating the creation of GitHub repositories.

Soon after making the first few extensions I became interested in knowing how many new downloads they were getting. You can view all your extensions in a single page, here you can find mine for instance, but that doesn’t really solve the problem if you don’t remember how many downloads your extensions had the previous time you checked. This is why I made rssa, a tool that tells you when things change. You can monitor pretty much anything reachable with an URL with it.

Custom rssa output

Wouldn’t it be great to have charts too? I haven’t published this tool yet, but leveraging rssa’s history we can generate charts, here’s a chart of the number of downloads of Todo+:

Todo+ downloads

Notice how there’s a sharp increase in downloads sometimes, that happens when a new update is published: updates are counted as downloads 😅 Anyone can have an extension with a million downloads just by pushing many updates, that’s one of the issues of the Marketplace.

Awesome, you made it till the end! Thank you for listening, I hope you found something useful in here.

How do you develop VSCode extensions? And what extensions are you using?