Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
69f2e32
feat(open): add sqlcmd open vscode and sqlcmd open ssms commands
dlevy-msft-sql Feb 6, 2026
5cf8ad9
fix: handle JSONC in VS Code settings.json and use atomic write
dlevy-msft-sql Apr 17, 2026
0ee752c
fix: prevent TestVSCode from writing to real settings.json
dlevy-msft-sql Apr 17, 2026
759dd91
fix: suppress errcheck lint for best-effort os.Remove on cleanup paths
dlevy-msft-sql Apr 18, 2026
992947a
fix: RunWithOutput stdout conflict and clipboard security warning
dlevy-msft-sql Apr 20, 2026
642aee4
i18n: localize Linux clipboard fallback error
dlevy-msft-sql May 27, 2026
3fe54df
feat: remove sqlcmd open ads (Azure Data Studio retired)
dlevy-msft-sql May 27, 2026
f377082
feat(open): launch SSMS via ssms:// URL handler with registry-based d…
dlevy-msft-sql May 28, 2026
1974251
revert: launch SSMS via ssms:// URL handler
dlevy-msft-sql May 28, 2026
932d9fc
feat(open): discover SSMS via vswhere and add --version flag
dlevy-msft-sql May 28, 2026
1ad7d48
feat(open): add --build flag and build-aware VS Code discovery
dlevy-msft-sql May 28, 2026
59899f5
fix(tools): include exe name as argv[0] on Windows so first flag is n…
dlevy-msft-sql May 28, 2026
c2cc250
fix(tools): launch tools detached so sqlcmd returns immediately
dlevy-msft-sql May 28, 2026
8899d6f
fix(open): connect via mssql --open-url instead of opening empty window
dlevy-msft-sql May 28, 2026
6cbd13b
fix(tools): redirect gui child stdio to null device so sqlcmd exits
dlevy-msft-sql May 28, 2026
b8ff423
feat(open): finalize vscode launch for mssql extension
dlevy-msft-sql May 28, 2026
7854f08
fix(open): satisfy golangci-lint (errcheck, QF1007)
dlevy-msft-sql May 28, 2026
703aa92
fix(open): return empty string when container inspect fails
dlevy-msft-sql May 28, 2026
4e251b5
fix(open): use Mandatory encrypt enum and honor VSCODE_EXTENSIONS
dlevy-msft-sql May 28, 2026
d22cba4
refactor(open): drop ai-slop comments and tautological clipboard tests
dlevy-msft-sql May 28, 2026
eba3f16
fix(tools): launch macOS vscode via in-bundle binary not the .app dir…
dlevy-msft-sql May 29, 2026
4d21c4f
fix(open): pass ssms username argv raw without bogus shell-escape
dlevy-msft-sql May 29, 2026
3cfb01d
fix(open): back up settings.json when vscode comments would be lost
dlevy-msft-sql May 29, 2026
019b59c
refactor(open): drop dead vscode RunWithOutput and tautological tests
dlevy-msft-sql May 29, 2026
3b318e2
revert: keep macOS vscode searchLocations on the .app bundle
dlevy-msft-sql May 29, 2026
4a48da5
fix(open): don't claim mssql extension install succeeded when we only…
dlevy-msft-sql May 29, 2026
bff614f
fix(tools): detach stdio when /dev/null open fails to avoid pipe-drai…
dlevy-msft-sql May 29, 2026
b570c12
test(open): assert full settings.json path tail per OS not just Code
dlevy-msft-sql May 29, 2026
4c4ada0
refactor(open): drop --install-extension; vscode:// URL already prompts
dlevy-msft-sql May 29, 2026
526da86
docs: address PR feedback on open vscode/ssms
dlevy-msft-sql May 29, 2026
337f562
refactor(tools): drop unused RunWithOutput and stale --install-extens…
dlevy-msft-sql May 29, 2026
398fb72
fix(i18n): restore translation catalog after rebase
dlevy-msft-sql May 29, 2026
b7d00e0
fix(open): drop tcp: prefix and base64-encode test password
dlevy-msft-sql May 29, 2026
f54a3ee
feat(open): platform-conditional vscode/ssms hints in help
dlevy-msft-sql May 29, 2026
7d60dc0
test(ssms): cover partial-install case; drop trivial Name() test
dlevy-msft-sql May 29, 2026
b1ceef5
refactor(open): preserve vscode settings.json comments via hujson
dlevy-msft-sql May 29, 2026
de68315
feat(open): enable 'sqlcmd open' on linux
dlevy-msft-sql May 29, 2026
3a0f060
refactor(root): drop tautological GOOS gate on open subcommand
dlevy-msft-sql May 29, 2026
7d8e49b
fix(open): resolve vscode settings path for snap, XDG, and missing HOME
dlevy-msft-sql May 29, 2026
b5a7e51
fix(open): scope persisted credentials and clipboard copy to the inst…
dlevy-msft-sql May 30, 2026
bb25b99
fix: address copilot review on PR #688
dlevy-msft-sql May 30, 2026
8de3474
chore: remove accidentally committed scratch files
dlevy-msft-sql May 30, 2026
858bdc7
fix(container): return empty string when ContainerName called with em…
dlevy-msft-sql May 30, 2026
7da4284
fix(open): use platform-appropriate home-dir hint
dlevy-msft-sql May 30, 2026
46d2c39
fix: address copilot review on basic auth guard and ssms help text
dlevy-msft-sql May 30, 2026
d5649e4
fix: localize home directory error and ssms_unix fatal message
dlevy-msft-sql May 30, 2026
061c494
fix: address copilot review on argv normalization, home dir nil err, …
dlevy-msft-sql May 30, 2026
a0d890f
refactor: hoist ssms struct and DefineCommand to untagged file
dlevy-msft-sql May 30, 2026
370dad1
fix: verify vscode install before writing settings; harden code shim …
dlevy-msft-sql May 30, 2026
4f5219f
refactor: rename Ssms type to SSMS for acronym consistency
dlevy-msft-sql May 30, 2026
5dad958
fix: detect early-exit failures in tool.Run and show SSMS install help
dlevy-msft-sql May 30, 2026
6363710
fix: guard copyPasswordToClipboard against nil output
dlevy-msft-sql May 30, 2026
f087a31
test: gate COMSPEC-based tool tests to Windows
dlevy-msft-sql May 30, 2026
7b90192
docs: update tool.Run stdio comment to match Wait goroutine
dlevy-msft-sql May 30, 2026
d609275
fix: restrict isLocalEndpoint to container-backed endpoints
dlevy-msft-sql May 30, 2026
39b14e5
fix: drop redundant port field from vscode mssql profile
dlevy-msft-sql May 30, 2026
934a58d
fix: resolve clip.exe via SystemRoot to avoid PATH hijack
dlevy-msft-sql May 30, 2026
6bd9f17
fix: clean up vscode connection profile when sqlcmd delete runs
dlevy-msft-sql Jun 1, 2026
2a488ed
fix: harden Windows path fallbacks for clip.exe and VS Code probing
dlevy-msft-sql Jun 1, 2026
dfe38f9
fix(open): fail fast on 'open vscode' and 'open ssms' with no current…
dlevy-msft-sql Jun 1, 2026
7b42463
fix(open): guard linux/darwin VS Code probes against empty HOME
dlevy-msft-sql Jun 1, 2026
4cbea7d
refactor: drop restate-the-code comments from open/clipboard files
dlevy-msft-sql Jun 1, 2026
f9348bb
feat: stage password to clipboard for VS Code remote SQL auth
dlevy-msft-sql Jun 1, 2026
904c306
test: reset shared config between open tests to make them order-indep…
dlevy-msft-sql Jun 1, 2026
329fc50
fix: harden vscode settings dir perms, pin pbcopy path, isolate more …
dlevy-msft-sql Jun 1, 2026
8593451
fix: pin linux clipboard helper to LookPath result to prevent PATH races
dlevy-msft-sql Jun 1, 2026
4e2a655
fix: suggest install options when linux clipboard helper is missing
dlevy-msft-sql Jun 1, 2026
e7e743f
fix: list per-WM install commands in linux clipboard error
dlevy-msft-sql Jun 1, 2026
76adf78
fix(open vscode): launch via in-bundle code CLI on macOS
dlevy-msft-sql Jun 2, 2026
654d381
fix(config add-endpoint): don't apply locale thousands separator to port
dlevy-msft-sql Jun 2, 2026
d8110b3
refactor(open): trim restate-the-code and dramatic comments
dlevy-msft-sql Jun 2, 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))
}
2 changes: 1 addition & 1 deletion cmd/modern/root/config/add-endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,5 @@ func (c *AddEndpoint) run() {
{localizer.Sprintf("View all endpoints details"), "sqlcmd config get-endpoints --detailed"},
{localizer.Sprintf("Delete this endpoint"), fmt.Sprintf("sqlcmd config delete-endpoint %v", uniqueEndpointName)},
},
localizer.Sprintf("Endpoint '%v' added (address: '%v', port: '%v')", uniqueEndpointName, c.address, c.port))
localizer.Sprintf("Endpoint '%v' added (address: '%v', port: '%v')", uniqueEndpointName, c.address, fmt.Sprintf("%d", c.port)))
Comment thread
dlevy-msft-sql marked this conversation as resolved.
}
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