Vscode: Suggestion: Start VSCode debugger from the command-line

Created on 26 Aug 2016  ·  42Comments  ·  Source: microsoft/vscode

It would be nice to be able to start the VSCode debugger from the command line, for example:

# within a workspace
code --start-debug "Launch" # start debugger using "Launch" configuration in .vscode/launch.json

# outside of a workspace
code --launch "node ./file.js arg" # launch "node" debugger for file.js
code --attach "node" # attach "node" debugger using command.PickProcess
code --attach "node:5858" # attach "node" debugger to port 5858

In addition, it would be nice to be able to launch another instance of vscode in debug mode as part of a debug configuration entry in .vscode/launch.json.

This would serve to make extension development easier (e.g. debug with the language client in one vscode instance, and start another instance to debug the language server).

*extension-candidate debug feature-request

Most helpful comment

I've just implemented this and what I proposed (configuration-less debugging) in Debug Launcher.

Before getting to what the extension actually does I'd like to say a few things:

  • @weinand I'm implementing the ability to start the debugger from the CLI via a URI handler, this means that every single time the user uses it he is prompted with a dialog, which gets pretty annoying pretty quickly. I think this is a good enough reason for implementing something like code --launch '{...}' into VSC itself, what do you say? If you know of a better way of implementing this that doesn't require URI handlers I'm all ears.
  • It's ok if the implementation of some features is effectively deferred to extensions authors, but sometimes we don't have to right tools to make good extensions (https://github.com/Microsoft/vscode/issues/30810#issue-243247163 https://github.com/Microsoft/vscode/issues/31079#issuecomment-324947324 https://github.com/Microsoft/vscode/issues/33094#issuecomment-434543383)
  • @octref I've found the documentation pretty lacking, here it doesn't mention that any other option supported by the debug provider can be used. It also says Type: The type of the debug session. which doesn't mean much to me. It should be clarified that type is actually the name of the debug provider to start (I think 🤷‍♂️ ). It also says Request: The request type of the debug session. this is also pretty meaningless on its own to me.
  • debug.startDebugging is supposed to also accept the name of a launch configuration, but it's not working (https://github.com/Microsoft/vscode/issues/62230)
  • In order to debug a VSCode extension we need set runtimeExecutable: '${execPath}' in its launch configuration, and execPath isn't documented anywhere (https://github.com/Microsoft/vscode/issues/62231)
  • I've stumbled upon a minor issue when passing custom arguments, they are parsed in a way I wasn't expecting, I'm not sure if this is a bug or not (https://github.com/Microsoft/vscode/issues/62233)

Getting back to the extension, it allows us to launch the debugger with a custom configuration just by running something like this in the shell:

open 'vscode://fabiospampinato.vscode-debug-launcher/launch?args={"type":"node","name":"Foo","request":"launch","program":"/path/to/foo.js"}'

Here's a demo of this, but I'm actually using a custom plugin for zsh instead of calling that url directly (details included in the readme):

terminal

The extension also allows us to debug whole projects and single files (this is pretty nice) without needing to write tedious launch configurations or tasks. Currently only JS projects/files and VSCode extensions are supported, other kinds of projects/files could be added easily:

file

Enjoy!

All 42 comments

This would enable integration with React Native - Debugging using custom debugger.

https://facebook.github.io/react-native/docs/debugging.html#debugging-using-a-custom-javascript-debugger

One would then simply press "Debug in Remote Debugger" in the app developer menu in the React Native app on the device/emulator and VSCode would launch and attach to the packager.

I'll try to investigate what to do here in March.
But don't expect to get this issue resolved in March.

Hi I am very interested in this feature and would like to contribute, but I am new to the VS Code codebase. Perhaps I can work with someone?

@isidorn please advise (since I'm on vacation until October 22).

@warric11 a good example to follow would be the .code --diff flag. Here's a code pointer which you can follow and try to do everything that the diff is doing, from doumentation to how it is propagetd and added to the interfaces
https://github.com/Microsoft/vscode/blob/master/src/vs/platform/environment/common/environment.ts#L15
You will probably also have to add a 'debugMode' in IOpenConfiguaration
https://github.com/Microsoft/vscode/blob/master/src/vs/platform/windows/electron-main/windows.ts#L94

And then if we start in that mode just get the debugService and call startDebugging on it with the passed name.

@warric11 the second feature of the original request "launch another instance of vscode in debug mode as part of a debug configuration" is no longer necessary as VS Code supports concurrent debug sessions with the compound feature.

Yes. I would aslo call this flag
--start-debug
Or
--debug
@weinand preference?

--debug (and --run for nodebug sessions).

@weinand For my work I don't need the second feature because I am only debugging a single thread of a process, but I definitely want to be able to issue the --debug and give the Python file on the commandline so that I start up the Python file in a debug session.

@isidorn thanks for the example to follow, I will take a look at it soon.

@warric11 please focus on passing a "launch config name" first, e.g. code --debug server (where server is the name of the launch config).

Passing additional command line arguments like code --debug "python ./file.py foo" is difficult because there is no way to assign the individual arguments to the corresponding launch config attributes (which are needed by the debug adapter protocol). So it is not possible to launch a debug session from within VS Code by using a command line like "python ./file.py foo".

So the only viable solution would be to pass a stringified json of the launch config (because that contains the names of the affected attributes). E.g. code --debug '{ "type": "python", "program": "file.py", "args": [ "foo"] }'.

Another approach would be to use a named launch config and a mechanism to replace individual attributes, e.g. code --debug server --attribute program=file.py. But it will be cumbersome to pass an array of arguments or env variables this way.

So I expect you to investigate these (and more) approaches before submitting a PR.

+1 what @weinand is saying. We will not support passing the full json. Only the name of the configuraiton.

Well I for one would very much like to be able to pass a full launch configuration so I hope you'll consider adding that once you've got support for a named configuration working.

One could write a .vscode/launch.json to a temporary folder and pass that folder to code.

Oh if there's a way to do that then fine.

_Copying over my post from #46496:_

I like the debugger that comes with Code, and I'd like to use it more often, but in some cases starting it up is cumbersome.

My use case:

  • I install an NPM package globally (npm i -g foo).
  • I use it a bit and for some reason I want to start up a debug session to find what exactly happens when I execute foo --flag1 in the terminal.

As far as I know the only way to do that would be to create a launch configuration file, which would look like this:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "program": "/whatever/foo.js",
            "args": ["--flag1"]
        }
    ]
}

I have some problems with this approach:

  • I don't want to pollute every single project I want to debug with launch configuration files.
  • I can already do node --inspect-brk /whatever/foo.js --flag1 and with the help of NiM I immediately get the devtools open, why isn't it as easy, or easier, to do the same with Code?
  • Never mind if you also want to debug foo --flag2, go write another configuration for it.

Basically always requiring the creation of a launch configuration files leads to an awful user experience for me.

Proposed solution:

Node has the --inspect and --inspect-brk command line flags, I think similar flags should be added to Code itself. Code already comes with the --inspect-extensions and --inspect-brk-extensions flags, so the lack of those other flags seems like a major overlooking to me.

With the auto-attach feature you can just start your node program from the command line and VS Code will automatically attach to it. Would this address your problem?

A first cut of this will appear in the March release. See https://github.com/Microsoft/vscode/issues/42521

@weinand not really. I've tried your extension and I've found these problems this it:

  • Even in your demo gif you can see that it is not working, "hello world: 0" gets printed without the debugger pausing the execution.
  • It doesn't work at all if I don't disable NiM first.
  • Even with NiM disabled, running node --inspect foo.js in the integrated terminal isn't always detected. The actual shell could be running inside a terminal multiplexer and your extension doesn't detect this.

    1. screen -D -R demo

    2. node --inspect foo.js

  • Even if it actually worked I don't want this, I might want to use chrome devtools for profiling the execution or taking an heap snapshot and Code for debugging, it would be pretty awkward if I had to open a standalone terminal app just to avoid Code messing with my workflow.

Wouldn't it be better to add code --inspect and code --inspect-brk?


A first cut of this will appear in the March release. See #42521

Please make sure there will be an option for disabling this.

@fabiospampinato Sorry, but it is working as expected. Since hello.js is launched with --inspect and not with --inspect-brk the program immediately starts (and is able to print the first "Hello" before the debugger had a chance to attach to it and register the breakpoint.

Yes, the fix for terminal multiplexers is in the works.

Please define the semantics of code --inspect et al.
Since I know the semantics of code --inspect-extensions, for me code --inspect would mean "start everything in code in debug mode so that I can attach a debugger to it". I don't see how this would help with your issue.

the program immediately starts (and is able to print the first "Hello" before the debugger had a chance to attach to it and register the breakpoint.

@weinand Exactly, I don't think the debugger is attaching itself fast enough. I'm not sure this can actually be done in every case, but we could certainly avoid the 1s delay between polls if we used code --inspect or something like that. It's also worth noting that constantly polling is a waste of resources, albeit small.

Please define the semantics of code --inspect et al.

code --inspect would basically mean: run node --inspect passing along all other arguments to it and immediately attach the debugger, so that code --inspect foo.js --flag would practically be the same as calling node --inspect foo.js --flag and immediately attaching Code's debugger. code --inspect-brk would work in an analogous way.

This would fix my issue because:

  • I could use Code's debugger without writing tedious launch configurations.
  • I could use whichever debugger is best for the job (auto-attaching Code's debugger breaks this if I run node --inspect from the integrated terminal).
  • If the debugger doesn't attach quickly enough for debugging startup code, the --xxxx-brk options should be used. They exist exactly for this purpose.
  • polling can always be tweaked but using --xxxx-brk is the way to go. My auto-attach extension is a prototype. The final feature is more sophisticated. BTW NiM is using polling too.
  • the semantics of code --inspect meaning node --inspect is very node.js-centric and does not make a lot of sense on a general purpose editor. If every debugger supported by VS Code would ask for a similar option, VS Code would drown by the number of options... It seems that you did not really understand the purpose of the VS Code --inspect-extensions option. This is used to pass the inspect flag to VS code's internal processes for troubleshooting but it neither attaches a debugger to it nor is it meant to be used to run some code outside of VS Code.

BTW NiM is using polling too.

If I knew a way to attach chrome's debugger programmatically I would do that instead.

It seems that you did not really understand the purpose of the VS Code --inspect-extensions option.

I've never used it so you're definitely right. I took for granted that those options where named after node's --inspect and --inspect-brk options, implying that whoever added those into Code probably thought about code --inspect too. I'm sorry for the confusion.

the semantics of code --inspect meaning node --inspect is very node.js-centric and does not make a lot of sense on a general purpose editor

I'm sorry I should have defined it in a more general way. Take that instead as an example of what it could do for .js files, support for other file types can always be added at a later time.

If every debugger supported by VS Code would ask for a similar option, VS Code would drown by the number of options...

What about a single option that works for everything, something like code --launch '{}' where {} can be a string representation of the launch configuration or a path to it? It wouldn't be practical to use this option manually but at least the creation of the configuration object can be automated.

In this scenario you could view code --inspect as a shortcut for code --launch /path/to/default_config_for_file_type.json.

What do you think about this?

@fabiospampinato yes, something like code --launch '{ .... }' makes sense and aligns well with our thinking.

BTW, the extensions API for debugging supports to start debugging with a single statement:

   vscode.debug.startDebugging(undefined, {
        type: "node",
        name: "hello.js",
        request: "launch",
        program: "hello.js"
   }    

Maybe you could use that already today to do what you want?

@weinand Is there a way to set things up so that the extensions API can be invoked from an external process (e.g. npm scripts)?

I want starting the debugger with src/foo/bar.js to do something with the corresponding compiled file at dist/foo/bar.js. The existing launch.json variables provide no way to do this AFAICT, but it's a simple string substitution that would be trivial in an NPM script.

In order to make something like the above work, I'd need a way to fetch the variables that are available in launch.json using the command line (possibly stdout of code --var '${file}'?) as well as the ability to pass JSON in for starting a task.

@masaeedu Sure, the extension API can be invoked from an external process if you write an extension that implements this.

But in your case this approach is probably not needed.

I do not know what exactly you want "to do with the compiled file at dist/foo/bar.js" but there are at least four approaches to achieve that with existing functionality:

  • if your transpilation step from src to dist is able to generate "source maps", then VS Code will use these maps to automatically translate between src and dist. Just make sure that the source maps are generated and optionally add an outFiles attribute to the launch configuration.
  • create an npm-script based task and add this as a prelaunchTask attribute to the launch config. VS Code will execute this task before starting the debug session. See https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes
  • create an npm-script that does your pre-processing and then launches your program in debug mode. Use this script with the workspaceExecutable attribute as described here: https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_launch-configuration-support-for-npm-and-other-tools
  • do everything necessary in an npm script (including launching your node program in debug mode). Then create an "attach" configuration that attaches the debugger to your program. Pressing "F5" starts debugging.
  • Or last but not least use the new "Auto attach" mode that attaches to your program automatically.

Which version of vscode includes the auto attach feature? I'm on version 1.16.1 but have no option for it.

@tamj0rd2 The current stable version is at 1.24. You are 8 months behind, I suggest to always upgrade to the latest. Please click on the gear button in the lower left corner.

This feature would be great for we want to launch vscode into the debugger. Please add this feature.

I've just implemented this and what I proposed (configuration-less debugging) in Debug Launcher.

Before getting to what the extension actually does I'd like to say a few things:

  • @weinand I'm implementing the ability to start the debugger from the CLI via a URI handler, this means that every single time the user uses it he is prompted with a dialog, which gets pretty annoying pretty quickly. I think this is a good enough reason for implementing something like code --launch '{...}' into VSC itself, what do you say? If you know of a better way of implementing this that doesn't require URI handlers I'm all ears.
  • It's ok if the implementation of some features is effectively deferred to extensions authors, but sometimes we don't have to right tools to make good extensions (https://github.com/Microsoft/vscode/issues/30810#issue-243247163 https://github.com/Microsoft/vscode/issues/31079#issuecomment-324947324 https://github.com/Microsoft/vscode/issues/33094#issuecomment-434543383)
  • @octref I've found the documentation pretty lacking, here it doesn't mention that any other option supported by the debug provider can be used. It also says Type: The type of the debug session. which doesn't mean much to me. It should be clarified that type is actually the name of the debug provider to start (I think 🤷‍♂️ ). It also says Request: The request type of the debug session. this is also pretty meaningless on its own to me.
  • debug.startDebugging is supposed to also accept the name of a launch configuration, but it's not working (https://github.com/Microsoft/vscode/issues/62230)
  • In order to debug a VSCode extension we need set runtimeExecutable: '${execPath}' in its launch configuration, and execPath isn't documented anywhere (https://github.com/Microsoft/vscode/issues/62231)
  • I've stumbled upon a minor issue when passing custom arguments, they are parsed in a way I wasn't expecting, I'm not sure if this is a bug or not (https://github.com/Microsoft/vscode/issues/62233)

Getting back to the extension, it allows us to launch the debugger with a custom configuration just by running something like this in the shell:

open 'vscode://fabiospampinato.vscode-debug-launcher/launch?args={"type":"node","name":"Foo","request":"launch","program":"/path/to/foo.js"}'

Here's a demo of this, but I'm actually using a custom plugin for zsh instead of calling that url directly (details included in the readme):

terminal

The extension also allows us to debug whole projects and single files (this is pretty nice) without needing to write tedious launch configurations or tasks. Currently only JS projects/files and VSCode extensions are supported, other kinds of projects/files could be added easily:

file

Enjoy!

@fabiospampinato very cool and interesting approach!

Some comments:

  • many VS Code debuggers already support debugging without launch configs. E.g. pressing F5 on a node.js program debugs it without a launch.json. In this case the DebugConfigurationProvider creates a launch config in memory (and looks into package.json for entry point etc.). The problem with your approach is that your extension will have to learn all the different debuggers, their launch config attributes, and the different artifacts they could use. This could become a catchup game and a maintenance problem.
  • launching the debugger from the command line is still planned (see "On Deck" milestone"). One issue is that there must be a way to target a workspace and or folder. So if you have three workspaces open and you run the command `code --debug=serverLaunch" in a terminal the launch config "serverLaunch" could be ambiguous and then needs a workspace name. Even if the command is run in an integrated terminal (where the corresponding workspace is implicit), it must be possible to communicate the workspace back to VS Code so that the launch config can be properly looked up and variable substitution is done in the correct context.

many VS Code debuggers already support debugging without launch configs.

That's pretty great, I didn't know about that. It seems that I can't debug single files if the whole project has a package.json though 🤔

This could become a catchup game and a maintenance problem.

True, but on the flip side with my approach one can have a customized default configuration for each debugger (say I want stopOnEntry to be true rather than false) and tasks can also be replaced with plain shell commands.

One issue is that there must be a way to target a workspace and or folder

Maybe something like code --launch 'Foo' --launch-cwd '/path/to/foo' could be enough. 🤔

The code that analyses the package.json is here: https://github.com/Microsoft/vscode-node-debug/blob/70c5980becc2bfbf1aafa290cc8ef3c3720cf6c0/src/node/extension/configurationProvider.ts#L230

A workspace or folder is not just a directory path (or 'cwd') but some entity with a uri.

@fabiospampinato @weinand I developed a npm package called easy-attach and a vscode extension which launches a rpc server to make attaching even easier:
gif

The only downside is that you have to touch the code you want to debug. However, in contrast to the auto-attach feature of vscode, you don't have to launch your app from within vscode and you can debug more than one target as the debug port is chosen randomly.

I use it to debug my typescript language service plugin that is being hosted in another vscode instance.

I need to debug a cli program which is installed via npm. I am using nvm and the cli code is downloaded and available in:

/Users/Chetan/.nvm/versions/node/v10.4.0/bin/asar

This is a symbolic link and gets added in PATH. Code for the same can be found in

/Users/Chetan/.nvm/versions/node/v10.4.0/lib/node_modules/asar

This cli accepts various cli arguments. I want to debug code in

/Users/Chetan/.nvm/versions/node/v10.4.0/lib/node_modules/asar

when this command is invoked from iTerm2, such that I could debug this in VS Code. I have tried different configuration options available for debugging, but can't figure out which setting I should use in vscode to do the same.

Note: If I use Node.js Launch Program, debugging works, but then I always have to run this within VS Code terminal. Attach to process, doesn't work because the program doesn't wait for debugger to attach.

What command line arguments I can use to start a debugging session for any npm module which is installed on my machine?

@cksachdev have a look at easy attach. It was designed exactly for usecases like yours (where the process to debug is not launched from within vscode).
With the extension VS Code RPC Server you can then debug your app in vscode.

If I understand @cksachdev correctly then "asar" is a short running command line program, not a server. So I'm not sure that the "easy attach" extension would help here.

I was able to debug "asar" easily with the following launch config:

        {
            "type": "node",
            "request": "launch",
            "name": "Launch asar",
            "program": "/Users/weinand/.nvm/versions/node/v10.15.1/bin/asar",
            "stopOnEntry": true,
            "args": [
                // add any command line args here
            ]
        }

Alternatively you can launch "asar" from the terminal in debug mode as follows:

node --inspect-brk "/Users/weinand/.nvm/versions/node/v10.15.1/bin/asar" asar arguments...

and then use this VS Code generic "attach" config to debug it:

        {
            "type": "node",
            "request": "attach",
            "name": "Attach to any node program",
            "port": 9229
        },

The "brk" in "--inspect-brk" makes node.js wait for the debugger to attach.

And please see our doc for node.js debugging: https://code.visualstudio.com/docs/nodejs/nodejs-debugging

It is precisely what easy-attach is meant for, given that you have access to asar's source:

easy-attach-asar

I've been using VSCode quite a bit lately and must say I am very happy with it. Recently I needed a way to grab a particular inspect process and this post may help: https://blog.june07.com/socket-watcher/

Further the NiMS VSCode extension helps if you want to debug VSCode processes in Chrome DevTools as it publishes the inspect metadata that gets swallowed by VSCode.

There was a lot in this thread so I figured I'd add what may be helpful info.

When this feature would be available? if not soon any work around to achieve the same.

Any chance this feature could make it into a future iteration plan? This would be really helpful to automate debugging workflows with VSCode.

One work around I found is to send key sequences to the vs code window from terminal.
I use a script to restart the debug session after compiling is done for new file changes.

I use Ubuntu as host with docker dev container setup. Below is my helper script:

window_title="${PWD} - Visual Studio Code"
command_string="xdotool windowactivate --sync \$(xdotool search --name '$window_title' | head -n 1) key Ctrl+Shift+F5"
echo $command_string >> local/docker_host.pipe

Ctrl+Shift+F5 is the keyboard shortcut I use to restart debug in debug mode and start debug session if not in debug mode.
local/docker_host.pipe is shared between host and the dev container via bind mount to allow running shell commands on host from dev container without compromising security.

You can start a screen session on host to read and execute commands from this pipe upon container start with below setting in devcontainer.json:

  "initializeCommand": ["/bin/sh", "listen_to_command_pipe_in_screen.sh"],

This setup works well for me. Hope this helps. :tada:

We try to keep VS Code lean and we think the functionality you're asking for is great for a VS Code extension. Maybe you can already find one that suits you in the VS Code Marketplace. Just in case, in a few simple steps you can get started writing your own extension. See also our issue reporting guidelines.

Happy Coding!

Was this page helpful?
0 / 5 - 0 ratings