SkillAgentSearch skills...

Vs.remote

A Visual Studio Code remote filesystem implementation with dotnet core backend, based on protocol buffers, gRPC and asp.net

Install / Use

/learn @mattiamerzi/Vs.remote
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

GitHub GitHub issues Code Climate maintainability AppVeyor Nuget

Vs.Remote

A Visual Studio Code remote filesystem implementation with dotnet core backend, based on protocol buffers, gRPC and ASP.NET Core.

Vs.Remote allows you to connect your Visual Studio Code workspace to a generic remote filesystem, where the backend is based on a custom dotnet core implementation.

You can store your files wherever you need them to be: on a database, in memory, on a real filesystem ...

The backend package is available on nuget.org as VsRemote, and the vscode extension is available on the Visual Studio Code Marketplace; alternatively, the extension might be installed manually; you can grab your .vsix extension file HERE

Quick Start

This example has been created using Visual Studio 2022 Community and Visual Studio Code 1.74.2 (user setup); your mileage may vary.

Create an empty .net 6+ ASP.NET Core Web API project named TestVsRemote

<img src="https://i.ibb.co/VptBmTN/new-vs-project.png" alt="new-vs-project" border="0">

Uncheck all the various checkboxes and set authentication type to "None", this should provide you with the simplest project possible.

<img src="https://i.ibb.co/rv4d275/vs-project-config.png" alt="vs-project-config" border="0">

Add the "VsRemote" nuget package to the project; in the nuget search options you should check the "Include prerelease" checkbox.

<img src="https://i.ibb.co/D8x1wCB/add-nuget-pkg.png" alt="add-nuget-pkg" border="0">

Import the sample in-memory filesystem into your project from this URL:

InMemoryIndexedDictionaryFilesystem.cs

and place it into the root folder of your project.

Open Program.cs, remove all the code that's been generated inside and copy paste this code:

using VsRemote.Interfaces;
using VsRemote.Providers;
using VsRemote.Sample;
using VsRemote.Startup;

var builder = WebApplication.CreateBuilder(args);
IVsRemoteFileSystemProvider fsProvider =
    new RootFsProvider(
        new InMemoryIndexedDictionaryFilesystem());
builder.Services.AddVsRemote(fsProvider);
var app = builder.Build();
app.MapVsRemote();
app.Run();

Open appsettings.json and update the content with this:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft.AspNetCore": "Warning"
    },
    "Console": {
      "FormatterName": "Simple",
      "FormatterOptions": {
        "SingleLine":  true
      },
      "LogLevel": {
        "Default": "Debug",
        "Microsoft": "Warning",
        "Grpc": "Warning"
      }
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }
}

this basically enables Http2 on Kestrel and sets the interesting logs log level to "Debug".

Open Properties/launchSettings.json and update the content with this:

{
  "profiles": {
    "TestVsRemote": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "http://localhost:5090",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

The vscode extension is available on the Visual Studio Code Marketplace; alternatively, grab the Visual Studio Code extension file from here: vsremote-0.0.1.vsix

Then open Visual Studio code, go to the Extensions tab and manually install the extension:

<img src="https://i.ibb.co/TTKTBH9/vscode-install-vsix.png" alt="vscode-install-vsix" border="0">

After having installed the Visual Studio Code extension, go to File => Preferences => Settings and open the json settings file clicking the "Open Settings (JSON)" icon on the top right corner:

<img src="https://i.ibb.co/PY2X6qz/open-settings-json.png" alt="open-settings-json" border="0">

Append this json block to the end of the file:

"vs.remote": {
    "remotes": {
        "test2fs": {
            "host": "localhost",
            "port": 5090
        }
    }
}
<img src="https://i.ibb.co/r7JGrkx/edit-settings-json-file.png" alt="edit-settings-json-file" border="0">

Save and close. Now, assuming the backend project is still running, open the commands dialog ( SHIFT + CTRL + P ) and search for Vs.Remote: Add Vs.Remote folder to Workspace

<img src="https://i.ibb.co/xYZ2cnm/vsremote-command.png" alt="vsremote-command" border="0">

launch that command, choose the only option that will appear in the next dialog

<img src="https://i.ibb.co/r09PnGS/test2fs-command.png" alt="test2fs-command" border="0">

now, in your vscode workspace there should be a new folder containing a single sample.txt file

<img src="https://i.ibb.co/BzG2xKX/vsremote-folder.png" alt="vsremote-folder" border="0">

That's it! Visual Studio Code is connected to your sample backend project, and the files you will create or store will reside into the sample in-memory filesystem you have just created. The sample project included in the backend solution contains some other interesting stuff, like a local filesystem mapper and a simple authentication backend (more details about this in the next sections).

In the next sections you'll find more details on how to create a filesystem and adapt the backend to your needs. If you find any trouble working with Vs.Remote, feel free to open an issue on github.

Create your own filesystem

Depending on how your backend works, you can choose to implement your filesystem as path-based or index-based. If your backend provides some "keys" that can be used to obtain a direct reference to a file or folder, then you should proceed with a key-based approach. The key can be of any type, as long as it implements the IEquatable<T> interface.

On the contrary, if your backend has no "keys" ready to be used, you need to rely on a path-based approach.

A key-based filesystem should be created extending the VsRemoteFileSystem<T> abstract class, providing a type for the Key; e.g.:

public class ExampleRelationalDatabaseBasedFilesystem : VsRemoteFileSystem<long>

A path-based filesystem, instead, should be created extending the VsRemoteFileSystem abstract class.

Although these two abstract classes provide you most of the base validation, exception handling, and various other checks already made, if you need a more fine-grained and maybe a more efficient solution you can implement either the IVsRemoteFileSystem or IVsRemoteFileSystem<T> interfaces and write all the boring stuff by yourself.

If you need any more detail, please refer to the examples and classes documentation.

After having decided which of these approaches best fits your needs, you can proceed with the tricky part: implementing the filesystem APIs.

If you have chosen a path-based approach, the APIs will receive their parameters based on the full path to the files, split into string arrays, plus an IVsRemoteINode, that is a file descriptor with this structure:

public interface IVsRemoteINode
{
    string Name { get; } // the name of the file
    VsRemoteFileType FileType { get; } // the file type (only File or Directory, atm)
    long CTime { get; } // create time (unix timestamp)
    long MTime { get; } // last modify time (unix timestamp)
    long Size { get; } // size in bytes (0 for directories)
}

for example:

public abstract Task CreateDirectory(string directoryName, IVsRemoteINode parentDir, string[] parentPath);

If you have chosen a key-based approach instead, the APIs will receive their parameters based on the IVsRemoteINode<T> class; this class adds to the IVsRemoteINode the Key and Parent properties of type T, for example:

public abstract Task CreateDirectory(string directoryName, IVsRemoteINode<T> parentDir);

As you can see, the full path to the directory is missing, hence you shouldn't rely on that on your key-based implementation.

Whenever you need to create a IVsRemoteINode instance you can instantiate an object of type VsRemoteINode (or VsRemoteINode<T>), that is the default implementation; for the special case of the root directory, there is a VsRemoteRootINode facility.

Mounting the filesystems

The Vs.Remote subsystem requires the user to provide an instance of IVsRemoteFileSystemProvider, that is, a factory that maps paths to IVsRemoteFilesystem implementations.

This allows you, for example, to expose multiple filesystems on a single interface.

This interface has a single method FromPath whose logic is: given a path and optionally an authentication token (more on this later), a tuple containing a particular filesystem and the path you just provided, relativized on the returned filesystem's path will be returned.

public (string RelativePath, IVsRemoteFileSystem RemoteFs) FromPath(string path, string? auth_token);

Bundled with Vs.Remote you'll find two different implementations of filesystem provider: RootFsProvider and BasePathFsProvider.

RootFsProvider is the simplest case: you pass a single filesystem implementation to the constructor, a

View on GitHub
GitHub Stars4
CategoryDevelopment
Updated8mo ago
Forks0

Languages

C#

Security Score

77/100

Audited on Jul 29, 2025

No findings