feat(open): add 'open vscode' and 'open ssms', remove retired 'open ads'#688
Open
dlevy-msft-sql wants to merge 71 commits into
Open
feat(open): add 'open vscode' and 'open ssms', remove retired 'open ads'#688dlevy-msft-sql wants to merge 71 commits into
dlevy-msft-sql wants to merge 71 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds support for opening Visual Studio Code and SQL Server Management Studio (SSMS) to work with SQL Server connections managed by sqlcmd, addressing the deprecation of Azure Data Studio. The implementation uses clipboard-based password sharing since both tools use sandboxed credential storage.
Changes:
- Adds
sqlcmd open vscodecommand that creates connection profiles in VS Code settings and auto-installs the MSSQL extension - Adds
sqlcmd open ssmscommand (Windows-only) that launches SSMS with pre-configured connection parameters - Implements cross-platform clipboard support for secure password sharing
- Includes comprehensive tests and documentation updates
Reviewed changes
Copilot reviewed 30 out of 31 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
cmd/modern/root/open.go |
Updates open command to include VSCode and SSMS subcommands |
cmd/modern/root/open/vscode.go |
Main VSCode command implementation with settings file manipulation |
cmd/modern/root/open/vscode_*.go |
Platform-specific VSCode implementations |
cmd/modern/root/open/ssms.go |
Main SSMS command implementation |
cmd/modern/root/open/ssms_*.go |
Platform-specific SSMS implementations (Fatal on non-Windows) |
cmd/modern/root/open/clipboard.go |
Helper function for clipboard-based password sharing |
cmd/modern/root/open/*_test.go |
Comprehensive test coverage for new commands |
internal/tools/tool/vscode*.go |
VSCode tool detection and configuration |
internal/tools/tool/ssms*.go |
SSMS tool detection and configuration |
internal/pal/clipboard*.go |
Cross-platform clipboard implementation using native APIs |
internal/tools/tools.go |
Registers VSCode and SSMS tools |
README.md |
Adds clear documentation with usage examples |
.gitignore |
Adds /modern build artifact |
…pty id Match the documented contract instead of panicking. Callers like the vscode launcher inspect optional container IDs and rely on the empty-string fallback.
On Windows, suggest USERPROFILE instead of HOME since that's what os.UserHomeDir consults.
- clipboard.go: guard user.BasicAuth != nil for consistency with other call sites - ssms.go/ssms_unix.go: drop '(Windows only)' suffix from Short text so it matches existing catalog entry - ssms_unix.go: drop localizer wrap on the Windows-only fatal stub message (string is unique to !windows build and not in the catalog)
- vscode.go: use %s with err.Error() so gotext extracts the home dir error - ssms_unix.go: wrap the unix-only fatal in localizer.Sprintf - regenerate catalog under GOOS=linux to register the !windows-tagged string
…and ssms integrated auth - tool.go: normalize argv[0] to match cmd.Path so darwin's open-based invocation is consistent with windows/linux - vscode.go: guard against empty home with nil error to avoid panic in err.Error() - ssms.go: append -E for integrated Windows auth when context has no SQL basic credentials
Moves the Ssms struct, DefineCommand, and its localizable strings into an untagged ssms.go so gotext extraction picks them up on every GOOS, eliminating catalog drift between Windows and non-Windows builds. Platform-specific run() bodies stay in ssms_run_windows.go and ssms_unix.go.
…detection - Verify VS Code is installed before creating settings.json, so a failed launch no longer leaves behind a fresh settings file (and possibly a plaintext local-context password) when the build is missing. - Detect whether the PATH-resolved code/code-insiders entry is a bin\\code.cmd shim before walking up two directories. Falls back to one-up when the install dir itself is on PATH (Code.exe directly). - Move the non-Windows ssms unsupported-platform message behind a helper in the untagged ssms.go so gotext extracts it regardless of host GOOS.
Removes the mssql.connections entry (and any inline password persisted for container-backed endpoints) from both stable and insiders VS Code settings.json when the underlying sqlcmd context is deleted. Best-effort: missing files or parse errors never fail the delete. JSONC comments and unrelated keys are preserved via hujson Patch.
Two security comments from Copilot review: - clipExePath returned bare 'clip.exe' when SystemRoot was unset, which re-introduces the PATH/cwd search the comment said we were avoiding. Chain SystemRoot -> WINDIR -> SystemDrive\Windows before defaulting to an absolute C:\Windows\System32\clip.exe. - vscodeWindowsBuildInfo built tier-3 install paths by joining USERPROFILE/ProgramFiles unconditionally; when either env var was empty, filepath.Join produced a relative path (e.g. AppData\...\Code.exe) that could match a binary in the working directory. Skip tier-3 entries whose base env var is empty.
… context Without a current context, both commands would call config.CurrentContext() (returning zero-value endpoint/user) and proceed to write an empty profile or launch with an empty host. Match start/stop/uninstall by exiting with 'No current context' and a hint to 'sqlcmd config get-contexts'.
When HOME was unset, filepath.Join produced relative per-user paths (.local/bin/code, Applications/Visual Studio Code.app) that could match an unintended binary or directory in the working directory. Skip those entries when HOME is empty.
`open -a <App> --args` only forwards args on a cold launch; when VS Code is already running macOS drops the args and the vscode:// URL never reaches the mssql extension, so `sqlcmd open vscode` silently no-ops. Add a platform-specific VSCode.launch that on darwin execs <App>/Contents/Resources/app/bin/code --open-url <url> directly, bypassing /usr/bin/open. Linux and Windows continue to use tool.Run unchanged. Extract tool.runCmd so platform launchers can supply their own *exec.Cmd while keeping the early-exit / stdio handling.
localizer.Sprintf routes through golang.org/x/text/message, which formats %v on an int with the locale's number formatter (e.g. en-US prints 1433 as '1,433'). Pre-format the port as a string so the displayed hint reads "port: '1433'".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds two new subcommands and removes one that no longer applies:
sqlcmd open vscode— writes a connection profile for the current context into VS Code'ssettings.jsonand launches VS Code on it via thevscode://URL handler (which prompts to install the MSSQL extension on first use if needed).sqlcmd open ssms— launches SSMS connected to the current context (Ssms.exe -S host,port -nosplash [-C] [-U user]with the password handed off via the clipboard).sqlcmd open adsis removed: Azure Data Studio was retired in August 2025.Password handling for VS Code
The VS Code profile includes the SQL password inline in
settings.jsonrather than prompting the user for it.sqlcmd's containers are short-lived local development instances with throwaway credentials, and the goal ofopen vscodeis one-shot, zero-prompt connect. The MSSQL extension migrates the password out ofsettings.jsonand into the OS credential store on first read, so the on-disk window is brief; we accept that trade-off in exchange for not requiring the user to paste a password they did not choose. This applies only to the local-container dev flow; users connecting to real servers should manage credentials through the extension directly.Editor discovery (Windows)
PATH(code/code-insiders) → Inno Setup uninstall registry → default install dirs.--build stable|insidersselects which build to launch; the connection profile is written to that build'ssettings.jsonso the profile and the launched build always match.vswhere -products Microsoft.VisualStudio.Product.Ssms, which finds SSMS 21+ on any drive.--versionpins a major version; values below 21 are rejected (older SSMS releases are legacy-MSI and aren't registered with the VS Installer).Why not
ssms://?An earlier revision used the
ssms://protocol handler. Its grammar only acceptss/a/u/d/h/q/dnand silently drops-C(trust server certificate) and-P. Local container connections need-C, so the URL path could not connect to a fresh local SQL container regardless of SSMS version. That commit was reverted; the argv launch path is what ships.Testing
go build ./...on windows/linux/darwingo test ./internal/tools/tool/... ./cmd/modern/root/open/...settings.jsonrouting.