reactive-vscode: writing VS Code extensions with Vue refs instead of manual updates
Develop VSCode extension with Vue Reactivity API
At a glance
- What is it?
- A TypeScript library that ports Vue's reactivity model to the VS Code extension API, so a status bar item or a command can depend on a ref and update itself, with a mock package for testing extensions outside the editor.
- Who is it for?
- Adopt reactive-vscode if you write VS Code extensions in TypeScript and keep hitting the pattern where a value changes and you must remember to push it into the UI yourself, since the composables remove that bookkeeping. Do not adopt it if your extension is a one-shot command with no persistent state, and read the documentation before relying on a specific function, because the project notes it is still in its 0.x line and may have minor API changes.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 179 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is remembering to call update()
Writing a VS Code extension in plain TypeScript means writing the same small ceremony over and over. A counter lives in a variable. The status bar item shows a string derived from it. When the counter changes, something has to push the new text into the item, and that something is a function the author has to remember to call from every mutation site. Miss one and the UI silently shows a stale value.
reactive-vscode applies Vue's reactivity model to that problem. The counter becomes a `ref`, the status bar text becomes a function of the ref, and the update happens because the value changed. The counter example in the documentation shows the whole extension:
import { defineExtension, ref, useCommands, useStatusBarItem } from 'reactive-vscode'
import { StatusBarAlignment } from 'vscode'
export = defineExtension(() => {
const counter = ref(0)
useStatusBarItem({
alignment: StatusBarAlignment.Right,
priority: 100,
text: () => `Hello ${counter.value}`,
})
useCommands({
'extension.sayHello': () => counter.value++,
'extension.sayGoodbye': () => counter.value--,
})
})The documentation keeps the original VS Code API version of the same extension alongside it, so the comparison is direct. The original version creates the status bar item, defines an `updateStatusBar` function that sets the text and shows the item, calls it once at activation, and then calls it again inside each of the two registered command callbacks. The reactive version drops the update function entirely and lets `text` be a getter over the ref.
The size difference is the point of the library. The mechanism underneath is the same as Vue's: a dependency is tracked while a getter runs, and the consumer is re-run when the tracked value changes.
Composables for the extension API surface
The project says most of the VS Code APIs are covered, and it documents its functions on a dedicated page. The two used in the counter example illustrate the pattern: `useStatusBarItem` takes an options object with alignment, priority and a text function, and `useCommands` takes a map of command identifiers to handlers.
The shape is the Vue composable shape. A function is called inside the extension setup, it registers what it needs against the extension context, and it returns cleanup that is disposed when the extension deactivates. That is what makes it safe to call these inside a `defineExtension` callback rather than in a module scope function, and it is why the API can be written as a set of composables rather than as a bag of register functions.
`useCommands` accepting a plain object of command ids to handlers is worth pausing on, because it is where the ergonomics differ most from the raw API. The raw form is a `commands.registerCommand` call per command, each one pushed onto `extensionContext.subscriptions` separately. The reactive form is one call with a map, and the disposal is handled by the library rather than by the author remembering the subscriptions array.
The `text` option on the status bar item is the other telling detail. It is a function, not a string, which is what allows it to read `counter.value` and be re-evaluated. A status bar item API that took a plain string could not be reactive without a separate update mechanism.
Who is already using it, and how it is packaged
The documentation lists three projects that use the library. Vue - Official, which is the Volar based extension from the vuejs language-tools repository, Slidev for VSCode, and Iconify IntelliSense. The first of those is the meaningful signal: an extension that ships to a very large audience of Vue developers is built on this reactivity layer.
The project is a pnpm workspace. The root package.json declares `packageManager` as `[email protected]`, sets `"type": "module"`, and its scripts fan out to the individual packages: `core:build` runs the build for reactive-vscode and its dependencies, `demo:dev` and `demo:build` handle the demo workspace, `metadata:dev` and `metadata:build` handle a metadata package, `creator:dev` and `creator:build` a creator package, and `docs:dev`, `docs:build` and `docs:preview` the documentation site. There is a `packages/` directory, a `demo/` directory with its own package.json, tsconfig, vite config and a tsdown config, a `docs/` directory, a `test/` directory, and `scripts/`.
Two release-related notes. The `release` script runs `bumpp` across the root package.json and every package under packages/, so versioning is handled by a single command across the workspace. And `prepare` runs `simple-git-hooks` with a `pre-commit` hook that runs `pnpm lint-staged`, which in turn runs `eslint --fix` on staged files.
There is also a dedicated metadata package and a creator package, which suggests the project provides tooling for publishing extension metadata and for scaffolding new extensions, beyond the runtime library itself.
A mock package so extensions can be tested outside the editor
Testing a VS Code extension normally means running it in the extension host, which is slow and awkward for unit tests. The project ships a `mock` package, and the licensing note in the documentation says the source in the `./packages/mock` directory references the implementation of VS Code itself.
That is a separate package from the reactivity core. The reactivity source in `./packages/reactivity` is ported from `@vue/runtime-core` in the Vue core repository, and the mock package references VS Code's own implementation. So the two halves of the project have different origins: one brings Vue's reactivity primitives, the other brings a stand-in for the editor API.
The practical value is that an extension's composables can be exercised in a plain Node test process, where a mock stands in for `vscode` imports. The root test script is `nr -C test test`, which delegates to a separate `test/` workspace with its own package.json, and the demo directory also carries a `test/` folder, so the repository has more than one place where tests live.
The demo directory also contains a `shim.d.ts`, which is the conventional way to type a module that does not exist at runtime, and it fits with the mock approach.
The licence has one non-commercial catch
The project is MIT licensed, with the licence file at the repository root and the copyright held by Kerman for 2024 to the present. The README is careful to attribute the borrowed parts.
Three attributions are given. The source in `./packages/reactivity` is ported from `@vue/runtime-core` and is MIT licensed. The source in `./packages/mock` references the implementation of VS Code and is MIT licensed. Part of the docs website is ported from VueUse and is MIT licensed.
The fourth is the exception worth knowing about. The logo is modified from the Vue Reactivity Artworks and is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. That is a non-commercial and share-alike licence attached to one asset rather than to the code. If you fork this project and publish a commercial extension using the logo, you have a problem the MIT grant on the source code does not solve. Using the code without the logo, or replacing the logo, keeps you clear of it. That is a reading of the licence files, not legal advice.
The VueUse integration is documented as a separate page, so if you already use VueUse composables in your extension, there is an existing bridge rather than a parallel set of conventions to learn.
Pre-1.0 API stability is the caveat
The documentation states that the project is still in its 0.x and may have minor API changes, and invites issues if you hit problems. That is a candid statement, and it is the main risk in adopting the library.
The tags tell a slightly different story. The recent releases are v1.0.2 on 2026-04-26, v1.0.1 on 2026-04-13 and v1.0.0 on 2026-04-12, and the root package.json version is 1.0.2. So the published package has moved past 1.0 while the documentation text still describes the project as 0.x. The three 1.0 releases landed within two weeks of each other in April 2026, which reads like a stabilisation pass rather than a slow 0.x crawl.
The repository is not archived and the last push was on 2026-04-29, three days after the v1.0.2 tag. That is recent enough to say the code is not frozen, and it means you should pin the version you use rather than tracking main.
The honest reading is that the API is close to stable but not promised to be. Because the composable surface is what your extension code actually touches, an API change would hit you at the source level rather than at a version bump you could ignore. Reading the functions documentation before you commit to it, and treating the 1.x tag as a pin, are the practical mitigations.
The alternative to weigh against is writing the extension against the raw VS Code API directly. The counter example in the documentation is not hypothetical, it is roughly twenty lines, and it has no dependency and no version risk. What reactive-vscode buys is the removal of manual update calls as your extension grows, and that benefit grows with the number of reactive values in the extension. For a small extension with one or two pieces of state, the raw API is likely less code.
Editorial conclusion
Adopt reactive-vscode if you write VS Code extensions in TypeScript and keep hitting the pattern where a value changes and you must remember to push it into the UI yourself, since the composables remove that bookkeeping. Do not adopt it if your extension is a one-shot command with no persistent state, and read the documentation before relying on a specific function, because the project notes it is still in its 0.x line and may have minor API changes. Verify first that your extension host process can use the library's lifecycle model, and check the MIT and CC BY-NC-SA attribution obligations if you reuse the logo artwork.
Frequently asked questions
What does reactive-vscode do?
It is a library for developing VS Code extensions with the Vue Reactivity API, so values can be held in refs and derived UI such as a status bar item can depend on them without the extension author writing update calls by hand.
How do I create a reactive status bar item with reactive-vscode?
Call useStatusBarItem with alignment, priority and a text function that reads the ref, for example text: () => `Hello ${counter.value}`. The library re-evaluates the function when the value changes.
Which projects use reactive-vscode?
The documentation lists Vue - Official, the Volar extension from the vuejs language-tools repository, Slidev for VSCode, and Iconify IntelliSense.
Can I test an extension that uses reactive-vscode outside VS Code?
The repository includes a mock package whose source references the VS Code implementation, alongside a separate test workspace and a demo directory with its own test folder, which is the setup for exercising composables without the editor.
Is reactive-vscode stable enough to depend on?
The documentation says the project is still in its 0.x and may have minor API changes, while the published package is at 1.0.2 with releases v1.0.0, v1.0.1 and v1.0.2 in April 2026. Pin the version you use and read the functions documentation first.
What licence does reactive-vscode use?
The source is MIT licensed. The reactivity package is ported from @vue/runtime-core, the mock package references the VS Code implementation, and part of the docs site is ported from VueUse, all under MIT, but the logo is modified from the Vue Reactivity Artworks under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 licence.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kermanx-reactive-vscode)Was this useful?