Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1f6f5b3
feat(open): add sqlcmd open vscode and sqlcmd open ssms commands
dlevy-msft-sql Feb 6, 2026
33795b4
fix: handle JSONC in VS Code settings.json and use atomic write
dlevy-msft-sql Apr 17, 2026
a0b4f9d
fix: prevent TestVSCode from writing to real settings.json
dlevy-msft-sql Apr 17, 2026
27456da
fix: suppress errcheck lint for best-effort os.Remove on cleanup paths
dlevy-msft-sql Apr 18, 2026
3d9db6b
fix: RunWithOutput stdout conflict and clipboard security warning
dlevy-msft-sql Apr 20, 2026
0f24d13
i18n: localize Linux clipboard fallback error
dlevy-msft-sql May 27, 2026
c3725f2
feat: remove sqlcmd open ads (Azure Data Studio retired)
dlevy-msft-sql May 27, 2026
6beabc9
feat(open): launch SSMS via ssms:// URL handler with registry-based d…
dlevy-msft-sql May 28, 2026
6e83c64
revert: launch SSMS via ssms:// URL handler
dlevy-msft-sql May 28, 2026
32d2200
feat(open): discover SSMS via vswhere and add --version flag
dlevy-msft-sql May 28, 2026
264d888
feat(open): add --build flag and build-aware VS Code discovery
dlevy-msft-sql May 28, 2026
639da60
fix(tools): include exe name as argv[0] on Windows so first flag is n…
dlevy-msft-sql May 28, 2026
87bfee0
fix(tools): launch tools detached so sqlcmd returns immediately
dlevy-msft-sql May 28, 2026
b7b2357
fix(open): connect via mssql --open-url instead of opening empty window
dlevy-msft-sql May 28, 2026
ad23b30
fix(tools): redirect gui child stdio to null device so sqlcmd exits
dlevy-msft-sql May 28, 2026
e8ad757
feat(open): finalize vscode launch for mssql extension
dlevy-msft-sql May 28, 2026
b516248
fix(open): satisfy golangci-lint (errcheck, QF1007)
dlevy-msft-sql May 28, 2026
f9c9012
fix(open): return empty string when container inspect fails
dlevy-msft-sql May 28, 2026
89bafde
fix(open): use Mandatory encrypt enum and honor VSCODE_EXTENSIONS
dlevy-msft-sql May 28, 2026
89150a0
refactor(open): drop ai-slop comments and tautological clipboard tests
dlevy-msft-sql May 28, 2026
b88feeb
fix(tools): launch macOS vscode via in-bundle binary not the .app dir…
dlevy-msft-sql May 29, 2026
3b237e3
fix(open): pass ssms username argv raw without bogus shell-escape
dlevy-msft-sql May 29, 2026
e68d8cf
fix(open): back up settings.json when vscode comments would be lost
dlevy-msft-sql May 29, 2026
42acd04
refactor(open): drop dead vscode RunWithOutput and tautological tests
dlevy-msft-sql May 29, 2026
f83ddd0
revert: keep macOS vscode searchLocations on the .app bundle
dlevy-msft-sql May 29, 2026
5fd497d
fix(open): don't claim mssql extension install succeeded when we only…
dlevy-msft-sql May 29, 2026
bf37b55
fix(tools): detach stdio when /dev/null open fails to avoid pipe-drai…
dlevy-msft-sql May 29, 2026
b89b51f
test(open): assert full settings.json path tail per OS not just Code
dlevy-msft-sql May 29, 2026
98bf667
refactor(open): drop --install-extension; vscode:// URL already prompts
dlevy-msft-sql May 29, 2026
24a3a29
docs: address PR feedback on open vscode/ssms
dlevy-msft-sql May 29, 2026
406fc0b
refactor(tools): drop unused RunWithOutput and stale --install-extens…
dlevy-msft-sql May 29, 2026
f72ee89
fix(i18n): restore translation catalog after rebase
dlevy-msft-sql May 29, 2026
f3c6199
fix(open): drop tcp: prefix and base64-encode test password
dlevy-msft-sql May 29, 2026
0d117d3
feat(open): platform-conditional vscode/ssms hints in help
dlevy-msft-sql May 29, 2026
85a8635
test(ssms): cover partial-install case; drop trivial Name() test
dlevy-msft-sql May 29, 2026
30facd1
refactor(open): preserve vscode settings.json comments via hujson
dlevy-msft-sql May 29, 2026
d7151bc
feat(open): enable 'sqlcmd open' on linux
dlevy-msft-sql May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ First build takes ~5 minutes.
- **Password**: `$SQLCMDPASSWORD` env var (`SqlCmd@2025!` for local dev)
- **Database**: `master` or `SqlCmdTest`

Port 1433 is forwarded — connect from host tools (ADS, SSMS) using same credentials.
Port 1433 is forwarded — connect from host tools (VS Code, SSMS) using same credentials.

## Two sqlcmd Versions

Expand Down
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,46 @@ The Homebrew package manager may be used on Linux and Windows Subsystem for Linu

Use `sqlcmd` to create SQL Server instances using a local container runtime (e.g. [Docker][] or [Podman][])

### Create SQL Server instance using local container runtime and connect using Azure Data Studio
### Create SQL Server instance using local container runtime

To create a local SQL Server instance with the AdventureWorksLT database restored, query it, and connect to it using Azure Data Studio, run:
To create a local SQL Server instance with the AdventureWorksLT database restored, run:

```
sqlcmd create mssql --accept-eula --using https://aka.ms/AdventureWorksLT.bak
sqlcmd query "SELECT DB_NAME()"
sqlcmd open ads
```

Use `sqlcmd --help` to view all the available sub-commands. Use `sqlcmd -?` to view the original ODBC `sqlcmd` flags.

### Connect using Visual Studio Code

Use `sqlcmd open vscode` to open Visual Studio Code with a connection profile configured for the current context:

```
sqlcmd open vscode
```

This command will:
1. **Create a connection profile** in VS Code's user settings with the current context name
2. **Launch VS Code** via the `vscode://` URL handler, which opens the MSSQL extension on the new profile

If the MSSQL extension is not installed, VS Code prompts to install it the first time the URL is opened.

Once VS Code opens, use the MSSQL extension's Object Explorer to connect using the profile. When you connect to the container, VS Code will automatically detect it as a Docker container and provide additional container management features (start/stop/delete) directly from the Object Explorer.

### Connect using SQL Server Management Studio (Windows)

On Windows, use `sqlcmd open ssms` to open SQL Server Management Studio pre-configured to connect to the current context:

```
sqlcmd open ssms
```

This command will:
1. **Copy the password to clipboard** so you can paste it in the login dialog
2. **Launch SSMS** with the server and username pre-filled
3. You'll be prompted for the password - just paste from clipboard (Ctrl+V)

### The ~/.sqlcmd/sqlconfig file

Each time `sqlcmd create` completes, a new context is created (e.g. mssql, mssql2, mssql3 etc.). A context contains the endpoint and user configuration detail. To switch between contexts, run `sqlcmd config use <context-name>`, to view name of the current context, run `sqlcmd config current-context`, to list all contexts, run `sqlcmd config get-contexts`.
Expand Down
12 changes: 7 additions & 5 deletions cmd/modern/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ type Root struct {
// It also provides usage examples for sqlcmd.
func (c *Root) DefineCommand(...cmdparser.CommandOptions) {
// Example usage steps
steps := []string{"sqlcmd create mssql --accept-eula --using https://aka.ms/AdventureWorksLT.bak"}
steps := []string{
"sqlcmd create mssql --accept-eula --using https://aka.ms/AdventureWorksLT.bak",
"sqlcmd open vscode",
}

if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
steps = append(steps, "sqlcmd open ads")
if runtime.GOOS == "windows" {
Comment thread
dlevy-msft-sql marked this conversation as resolved.
steps = append(steps, "sqlcmd open ssms")
}

steps = append(steps, `sqlcmd query "SELECT @@version"`)
Expand Down Expand Up @@ -73,8 +76,7 @@ func (c *Root) SubCommands() []cmdparser.Command {
cmdparser.New[*root.Uninstall](dependencies),
}

// BUG(stuartpa): - Add Linux support
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "linux" {
subCommands = append(subCommands, cmdparser.New[*root.Open](dependencies))
}

Expand Down
16 changes: 11 additions & 5 deletions cmd/modern/root/config/add-context.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package config

import (
"fmt"
"runtime"

"github.com/microsoft/go-sqlcmd/cmd/modern/sqlconfig"
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
Expand Down Expand Up @@ -88,9 +89,14 @@ func (c *AddContext) run() {

context.Name = config.AddContext(context)
config.SetCurrentContextName(context.Name)
output.InfoWithHintExamples([][]string{
{localizer.Sprintf("Open in Azure Data Studio"), "sqlcmd open ads"},
{localizer.Sprintf("To start interactive query session"), "sqlcmd query"},
{localizer.Sprintf("To run a query"), "sqlcmd query \"SELECT @@version\""},
}, localizer.Sprintf("Current Context '%v'", context.Name))
hints := [][]string{}
if runtime.GOOS == "windows" {
hints = append(hints, []string{localizer.Sprintf("Open in SQL Server Management Studio"), "sqlcmd open ssms"})
}
hints = append(hints,
[]string{localizer.Sprintf("Open in Visual Studio Code"), "sqlcmd open vscode"},
[]string{localizer.Sprintf("To start interactive query session"), "sqlcmd query"},
[]string{localizer.Sprintf("To run a query"), "sqlcmd query \"SELECT @@version\""},
)
output.InfoWithHintExamples(hints, localizer.Sprintf("Current Context '%v'", context.Name))
}
6 changes: 3 additions & 3 deletions cmd/modern/root/install/mssql-base.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,10 @@ func (c *MssqlBase) createContainer(imageName string, contextName string) {

hints := [][]string{}

// TODO: sqlcmd open ads only support on Windows right now, add Mac support
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
hints = append(hints, []string{localizer.Sprintf("Open in Azure Data Studio"), "sqlcmd open ads"})
if runtime.GOOS == "windows" {
hints = append(hints, []string{localizer.Sprintf("Open in SQL Server Management Studio"), "sqlcmd open ssms"})
}
hints = append(hints, []string{localizer.Sprintf("Open in Visual Studio Code"), "sqlcmd open vscode"})

hints = append(hints, []string{localizer.Sprintf("Run a query"), "sqlcmd query \"SELECT @@version\""})
hints = append(hints, []string{localizer.Sprintf("Start interactive session"), "sqlcmd query"})
Expand Down
7 changes: 4 additions & 3 deletions cmd/modern/root/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@ type Open struct {
func (c *Open) DefineCommand(...cmdparser.CommandOptions) {
options := cmdparser.CommandOptions{
Use: "open",
Short: localizer.Sprintf("Open tools (e.g Azure Data Studio) for current context"),
Short: localizer.Sprintf("Open tools (e.g., Visual Studio Code, SSMS) for current context"),
SubCommands: c.SubCommands(),
}

c.Cmd.DefineCommand(options)
}

// SubCommands sets up the sub-commands for `sqlcmd open` such as
// `sqlcmd open ads`
// `sqlcmd open vscode` and `sqlcmd open ssms`
func (c *Open) SubCommands() []cmdparser.Command {
dependencies := c.Dependencies()

return []cmdparser.Command{
cmdparser.New[*open.Ads](dependencies),
cmdparser.New[*open.VSCode](dependencies),
cmdparser.New[*open.Ssms](dependencies),
}
Comment thread
dlevy-msft-sql marked this conversation as resolved.
Comment thread
dlevy-msft-sql marked this conversation as resolved.
}
100 changes: 0 additions & 100 deletions cmd/modern/root/open/ads.go

This file was deleted.

37 changes: 0 additions & 37 deletions cmd/modern/root/open/ads_darwin.go

This file was deleted.

24 changes: 0 additions & 24 deletions cmd/modern/root/open/ads_linux.go

This file was deleted.

Loading
Loading