Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 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
08cbf77
refactor(root): drop tautological GOOS gate on open subcommand
dlevy-msft-sql May 29, 2026
22fcd75
fix(open): resolve vscode settings path for snap, XDG, and missing HOME
dlevy-msft-sql May 29, 2026
8d51629
fix(open): scope persisted credentials and clipboard copy to the inst…
dlevy-msft-sql May 30, 2026
2567bf8
fix: address copilot review on PR #688
dlevy-msft-sql May 30, 2026
b14f426
chore: remove accidentally committed scratch files
dlevy-msft-sql May 30, 2026
c4c4d01
fix(container): return empty string when ContainerName called with em…
dlevy-msft-sql May 30, 2026
d8bc4a1
fix(open): use platform-appropriate home-dir hint
dlevy-msft-sql May 30, 2026
53a829a
fix: address copilot review on basic auth guard and ssms help text
dlevy-msft-sql May 30, 2026
b131c82
fix: localize home directory error and ssms_unix fatal message
dlevy-msft-sql May 30, 2026
25393b3
fix: address copilot review on argv normalization, home dir nil err, …
dlevy-msft-sql May 30, 2026
b78d951
refactor: hoist ssms struct and DefineCommand to untagged file
dlevy-msft-sql May 30, 2026
3dc8dc8
fix: verify vscode install before writing settings; harden code shim …
dlevy-msft-sql May 30, 2026
102a19a
refactor: rename Ssms type to SSMS for acronym consistency
dlevy-msft-sql May 30, 2026
b8798fb
fix: detect early-exit failures in tool.Run and show SSMS install help
dlevy-msft-sql May 30, 2026
eca68ad
fix: guard copyPasswordToClipboard against nil output
dlevy-msft-sql May 30, 2026
831f9ea
test: gate COMSPEC-based tool tests to Windows
dlevy-msft-sql May 30, 2026
eefc8b4
docs: update tool.Run stdio comment to match Wait goroutine
dlevy-msft-sql May 30, 2026
44aafd7
fix: restrict isLocalEndpoint to container-backed endpoints
dlevy-msft-sql May 30, 2026
fd0d50c
fix: drop redundant port field from vscode mssql profile
dlevy-msft-sql May 30, 2026
067d42a
fix: resolve clip.exe via SystemRoot to avoid PATH hijack
dlevy-msft-sql May 30, 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
31 changes: 28 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,43 @@ 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 launches SSMS with the server and username pre-filled. When the current context uses SQL authentication, sqlcmd also copies the password to the clipboard so you can paste it (Ctrl+V) into the SSMS login dialog. Contexts using integrated (Windows) authentication skip the clipboard step and connect without a password prompt.

### 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
15 changes: 7 additions & 8 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 @@ -67,17 +70,13 @@ func (c *Root) SubCommands() []cmdparser.Command {
subCommands := []cmdparser.Command{
cmdparser.New[*root.Config](dependencies),
cmdparser.New[*root.Install](dependencies),
cmdparser.New[*root.Open](dependencies),
cmdparser.New[*root.Query](dependencies),
cmdparser.New[*root.Start](dependencies),
cmdparser.New[*root.Stop](dependencies),
cmdparser.New[*root.Uninstall](dependencies),
}

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

return subCommands
}

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