diff --git a/build.ps1 b/build.ps1
index 08df26a9a..6f076e082 100755
--- a/build.ps1
+++ b/build.ps1
@@ -60,7 +60,8 @@ $filesForWindowsPackage = @(
     'RunCommandOnSet.dsc.resource.json',
     'RunCommandOnSet.exe',
     'sshdconfig.exe',
-    'sshdconfig.dsc.resource.json',
+    'sshd-windows.dsc.resource.json',
+    'sshd_config.dsc.resource.json',
     'windowspowershell.dsc.resource.json',
     'wmi.dsc.resource.json',
     'wmi.resource.ps1',
@@ -87,7 +88,7 @@ $filesForLinuxPackage = @(
     'RunCommandOnSet.dsc.resource.json',
     'runcommandonset',
     'sshdconfig',
-    'sshdconfig.dsc.resource.json'
+    'sshd_config.dsc.resource.json'
 )
 
 $filesForMacPackage = @(
@@ -109,7 +110,7 @@ $filesForMacPackage = @(
     'RunCommandOnSet.dsc.resource.json',
     'runcommandonset',
     'sshdconfig',
-    'sshdconfig.dsc.resource.json'
+    'sshd_config.dsc.resource.json'
 )
 
 # the list of files other than the binaries which need to be executable
@@ -173,7 +174,7 @@ if ($null -ne $packageType) {
 
     & $rustup default stable
 
-    ## Test if Node is installed 
+    ## Test if Node is installed
     ## Skipping upgrade as users may have a specific version they want to use
     if (!(Get-Command 'node' -ErrorAction Ignore)) {
         Write-Verbose -Verbose "Node.js not found, installing..."
diff --git a/sshdconfig/Cargo.lock b/sshdconfig/Cargo.lock
index 73c9d0912..d63fad980 100644
--- a/sshdconfig/Cargo.lock
+++ b/sshdconfig/Cargo.lock
@@ -26,6 +26,62 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "anstream"
+version = "0.6.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "arc-swap"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
+
 [[package]]
 name = "atty"
 version = "0.2.14"
@@ -43,6 +99,37 @@ version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
 
+[[package]]
+name = "base62"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10e52a7bcb1d6beebee21fb5053af9e3cbb7a7ed1a4909e534040e676437ab1f"
+dependencies = [
+ "rustversion",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+
+[[package]]
+name = "bstr"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
 [[package]]
 name = "bumpalo"
 version = "3.19.0"
@@ -78,30 +165,219 @@ dependencies = [
  "windows-link",
 ]
 
+[[package]]
+name = "clap"
+version = "4.5.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+
+[[package]]
+name = "convert_case"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7"
+dependencies = [
+ "unicode-segmentation",
+]
+
 [[package]]
 name = "core-foundation-sys"
 version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "crossterm"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
+dependencies = [
+ "bitflags 2.9.1",
+ "crossterm_winapi",
+ "derive_more",
+ "document-features",
+ "mio",
+ "parking_lot",
+ "rustix",
+ "signal-hook",
+ "signal-hook-mio",
+ "winapi",
+]
+
+[[package]]
+name = "crossterm_winapi"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "derive_more"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
+dependencies = [
+ "derive_more-impl",
+]
+
+[[package]]
+name = "derive_more-impl"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "document-features"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d"
+dependencies = [
+ "litrs",
+]
+
 [[package]]
 name = "dyn-clone"
 version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
 
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
 [[package]]
 name = "equivalent"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
+[[package]]
+name = "errno"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
+
+[[package]]
+name = "globset"
+version = "0.4.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata 0.4.9",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "globwalk"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
+dependencies = [
+ "bitflags 1.3.2",
+ "ignore",
+ "walkdir",
+]
+
 [[package]]
 name = "hashbrown"
 version = "0.15.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
 
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
 [[package]]
 name = "hermit-abi"
 version = "0.1.19"
@@ -123,7 +399,7 @@ dependencies = [
  "js-sys",
  "log",
  "wasm-bindgen",
- "windows-core",
+ "windows-core 0.61.2",
 ]
 
 [[package]]
@@ -135,6 +411,22 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "ignore"
+version = "0.4.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b"
+dependencies = [
+ "crossbeam-deque",
+ "globset",
+ "log",
+ "memchr",
+ "regex-automata 0.4.9",
+ "same-file",
+ "walkdir",
+ "winapi-util",
+]
+
 [[package]]
 name = "indexmap"
 version = "2.10.0"
@@ -145,6 +437,21 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "itertools"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itoa"
 version = "1.0.15"
@@ -173,18 +480,70 @@ version = "0.2.174"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
 
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+
+[[package]]
+name = "litrs"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
+
+[[package]]
+name = "lock_api"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
 [[package]]
 name = "log"
 version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
 
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata 0.1.10",
+]
+
 [[package]]
 name = "memchr"
 version = "2.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
 
+[[package]]
+name = "mio"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "normpath"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
 [[package]]
 name = "nu-ansi-term"
 version = "0.46.0"
@@ -210,12 +569,41 @@ version = "1.21.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
 
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
+
 [[package]]
 name = "overload"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
 
+[[package]]
+name = "parking_lot"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
 [[package]]
 name = "pin-project-lite"
 version = "0.2.16"
@@ -240,6 +628,15 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.5.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
+dependencies = [
+ "bitflags 2.9.1",
+]
+
 [[package]]
 name = "regex"
 version = "1.11.1"
@@ -248,8 +645,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-automata",
- "regex-syntax",
+ "regex-automata 0.4.9",
+ "regex-syntax 0.8.5",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
 ]
 
 [[package]]
@@ -260,15 +666,119 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax",
+ "regex-syntax 0.8.5",
 ]
 
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
 [[package]]
 name = "regex-syntax"
 version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
 
+[[package]]
+name = "registry"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "515143bd3c240fd5a47002a552fd7eba71acf8cd3cf7472e5ec392cda2ed3d90"
+dependencies = [
+ "bitflags 1.3.2",
+ "log",
+ "thiserror 1.0.69",
+ "utfx",
+ "windows",
+]
+
+[[package]]
+name = "registry_lib"
+version = "0.1.0"
+dependencies = [
+ "cc",
+ "crossterm",
+ "registry",
+ "rust-i18n",
+ "schemars",
+ "serde",
+ "serde_json",
+ "static_vcruntime",
+ "thiserror 2.0.12",
+ "tracing",
+ "tracing-subscriber",
+ "utfx",
+]
+
+[[package]]
+name = "rust-i18n"
+version = "3.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fda2551fdfaf6cc5ee283adc15e157047b92ae6535cf80f6d4962d05717dc332"
+dependencies = [
+ "globwalk",
+ "once_cell",
+ "regex",
+ "rust-i18n-macro",
+ "rust-i18n-support",
+ "smallvec",
+]
+
+[[package]]
+name = "rust-i18n-macro"
+version = "3.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22baf7d7f56656d23ebe24f6bb57a5d40d2bce2a5f1c503e692b5b2fa450f965"
+dependencies = [
+ "glob",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "rust-i18n-support",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+ "syn",
+]
+
+[[package]]
+name = "rust-i18n-support"
+version = "3.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "940ed4f52bba4c0152056d771e563b7133ad9607d4384af016a134b58d758f19"
+dependencies = [
+ "arc-swap",
+ "base62",
+ "globwalk",
+ "itertools",
+ "lazy_static",
+ "normpath",
+ "once_cell",
+ "proc-macro2",
+ "regex",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+ "siphasher",
+ "toml",
+ "triomphe",
+]
+
+[[package]]
+name = "rustix"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
+dependencies = [
+ "bitflags 2.9.1",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.59.0",
+]
+
 [[package]]
 name = "rustversion"
 version = "1.0.21"
@@ -281,6 +791,15 @@ version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
 [[package]]
 name = "schemars"
 version = "0.8.22"
@@ -305,6 +824,12 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
 [[package]]
 name = "serde"
 version = "1.0.219"
@@ -349,6 +874,28 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "serde_spanned"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_yaml"
+version = "0.9.34+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
+dependencies = [
+ "indexmap",
+ "itoa",
+ "ryu",
+ "serde",
+ "unsafe-libyaml",
+]
+
 [[package]]
 name = "sharded-slab"
 version = "0.1.7"
@@ -364,6 +911,42 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
+[[package]]
+name = "signal-hook"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-mio"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
+dependencies = [
+ "libc",
+ "mio",
+ "signal-hook",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "siphasher"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
+
 [[package]]
 name = "smallvec"
 version = "1.15.1"
@@ -377,10 +960,13 @@ dependencies = [
  "atty",
  "cc",
  "chrono",
+ "clap",
+ "registry_lib",
+ "rust-i18n",
  "schemars",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 2.0.12",
  "tracing",
  "tracing-subscriber",
  "tree-sitter",
@@ -388,12 +974,30 @@ dependencies = [
  "tree-sitter-ssh-server-config",
 ]
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "static_vcruntime"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "954e3e877803def9dc46075bf4060147c55cd70db97873077232eae0269dc89b"
+
 [[package]]
 name = "streaming-iterator"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
 
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
 [[package]]
 name = "syn"
 version = "2.0.104"
@@ -405,13 +1009,33 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl 1.0.69",
+]
+
 [[package]]
 name = "thiserror"
 version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
 dependencies = [
- "thiserror-impl",
+ "thiserror-impl 2.0.12",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -434,6 +1058,47 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "toml"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_write",
+ "winnow",
+]
+
+[[package]]
+name = "toml_write"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
+
 [[package]]
 name = "tracing"
 version = "0.1.41"
@@ -477,18 +1142,35 @@ dependencies = [
  "tracing-core",
 ]
 
+[[package]]
+name = "tracing-serde"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
+dependencies = [
+ "serde",
+ "tracing-core",
+]
+
 [[package]]
 name = "tracing-subscriber"
 version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
 dependencies = [
+ "matchers",
  "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "serde",
+ "serde_json",
  "sharded-slab",
  "smallvec",
  "thread_local",
+ "tracing",
  "tracing-core",
  "tracing-log",
+ "tracing-serde",
 ]
 
 [[package]]
@@ -499,7 +1181,7 @@ checksum = "a7cf18d43cbf0bfca51f657132cc616a5097edc4424d538bae6fa60142eaf9f0"
 dependencies = [
  "cc",
  "regex",
- "regex-syntax",
+ "regex-syntax 0.8.5",
  "serde_json",
  "streaming-iterator",
  "tree-sitter-language",
@@ -531,18 +1213,69 @@ dependencies = [
  "tree-sitter-rust",
 ]
 
+[[package]]
+name = "triomphe"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85"
+dependencies = [
+ "arc-swap",
+ "serde",
+ "stable_deref_trait",
+]
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
+[[package]]
+name = "unicode-segmentation"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+
+[[package]]
+name = "unsafe-libyaml"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "utfx"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "133bf74f01486773317ddfcde8e2e20d2933cc3b68ab797e5d718bef996a81de"
+
 [[package]]
 name = "valuable"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
 
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
 [[package]]
 name = "wasm-bindgen"
 version = "0.2.100"
@@ -617,23 +1350,66 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
+[[package]]
+name = "winapi-util"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
 [[package]]
 name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "windows"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
+dependencies = [
+ "windows-core 0.58.0",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
+dependencies = [
+ "windows-implement 0.58.0",
+ "windows-interface 0.58.0",
+ "windows-result 0.2.0",
+ "windows-strings 0.1.0",
+ "windows-targets 0.52.6",
+]
+
 [[package]]
 name = "windows-core"
 version = "0.61.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
 dependencies = [
- "windows-implement",
- "windows-interface",
+ "windows-implement 0.60.0",
+ "windows-interface 0.59.1",
  "windows-link",
- "windows-result",
- "windows-strings",
+ "windows-result 0.3.4",
+ "windows-strings 0.4.2",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -647,6 +1423,17 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "windows-interface"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "windows-interface"
 version = "0.59.1"
@@ -664,6 +1451,15 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
 
+[[package]]
+name = "windows-result"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
 [[package]]
 name = "windows-result"
 version = "0.3.4"
@@ -673,6 +1469,16 @@ dependencies = [
  "windows-link",
 ]
 
+[[package]]
+name = "windows-strings"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
+dependencies = [
+ "windows-result 0.2.0",
+ "windows-targets 0.52.6",
+]
+
 [[package]]
 name = "windows-strings"
 version = "0.4.2"
@@ -681,3 +1487,158 @@ checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
 dependencies = [
  "windows-link",
 ]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets 0.53.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm 0.52.6",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
+dependencies = [
+ "windows_aarch64_gnullvm 0.53.0",
+ "windows_aarch64_msvc 0.53.0",
+ "windows_i686_gnu 0.53.0",
+ "windows_i686_gnullvm 0.53.0",
+ "windows_i686_msvc 0.53.0",
+ "windows_x86_64_gnu 0.53.0",
+ "windows_x86_64_gnullvm 0.53.0",
+ "windows_x86_64_msvc 0.53.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+
+[[package]]
+name = "winnow"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
+dependencies = [
+ "memchr",
+]
diff --git a/sshdconfig/Cargo.toml b/sshdconfig/Cargo.toml
index b23bc67ca..a46ee2889 100644
--- a/sshdconfig/Cargo.toml
+++ b/sshdconfig/Cargo.toml
@@ -16,6 +16,8 @@ lto = true
 [dependencies]
 atty = { version = "0.2" }
 chrono = { version = "0.4" }
+clap = { version = "4.5", features = ["derive"] }
+rust-i18n = { version = "3.1" }
 schemars = "0.8"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", features = ["preserve_order"] }
@@ -26,5 +28,8 @@ tree-sitter = "0.25"
 tree-sitter-rust = "0.24"
 tree-sitter-ssh-server-config = { path = "../tree-sitter-ssh-server-config" }
 
+[target.'cfg(windows)'.dependencies]
+registry_lib = { path = "../registry_lib" }
+
 [build-dependencies]
 cc="*"
diff --git a/sshdconfig/locales/en-us.toml b/sshdconfig/locales/en-us.toml
new file mode 100644
index 000000000..3ad1ee312
--- /dev/null
+++ b/sshdconfig/locales/en-us.toml
@@ -0,0 +1,45 @@
+_version = 1
+
+[args]
+setInput = "input to set in sshd_config"
+
+[error]
+command = "Command"
+invalidInput = "Invalid Input"
+json = "JSON"
+language = "Language"
+notImplemented = "Not Implemented"
+parser = "Parser"
+parseInt = "Parse Integer"
+registry = "Registry"
+
+[get]
+defaultShellCmdOptionMustBeString = "cmdOption must be a string"
+defaultShellEscapeArgsMustBe0Or1 = "'%{input}' must be a 0 or 1"
+defaultShellEscapeArgsMustBeDWord = "escapeArguments must be a DWord"
+defaultShellMustBeString = "shell must be a string"
+notImplemented = "get not yet implemented for Microsoft.OpenSSH.SSHD/sshd_config"
+windowsOnly = "Microsoft.OpenSSH.SSHD/Windows is only applicable to Windows"
+
+[set]
+failedToParseInput = "failed to parse input as DefaultShell with error: '%{error}'"
+shellPathDoesNotExist = "shell path does not exist: '%{shell}'"
+shellPathMustNotBeRelative = "shell path must not be relative"
+
+[parser]
+failedToParse = "failed to parse: '%{input}'"
+failedToParseAsArray = "value is not an array"
+failedToParseChildNode = "failed to parse child node: '%{input}'"
+failedToParseNode = "failed to parse '%{input}'"
+failedToParseRoot = "failed to parse root: '%{input}'"
+invalidConfig = "invalid config: '%{input}'"
+invalidValue = "operator is an invalid value for node"
+keyNotFound = "key '%{key}' not found"
+keyNotRepeatable = "key '%{key}' is not repeatable"
+missingKeyInChildNode = "missing key in child node: '%{input}'"
+missingValueInChildNode = "missing value in child node: '%{input}'"
+unknownNode = "unknown node: '%{kind}'"
+unknownNodeType = "unknown node type: '%{node}'"
+
+[util]
+sshdElevation = "elevated security context required"
diff --git a/sshdconfig/src/args.rs b/sshdconfig/src/args.rs
new file mode 100644
index 000000000..b8c595c05
--- /dev/null
+++ b/sshdconfig/src/args.rs
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+use clap::{Parser, Subcommand, ValueEnum};
+use rust_i18n::t;
+use schemars::JsonSchema;
+use serde::{Deserialize, Serialize};
+
+#[derive(Parser)]
+pub struct Args {
+    #[clap(subcommand)]
+    pub command: Command,
+}
+
+#[derive(Subcommand)]
+pub enum Command {
+    /// Get default shell, eventually to be used for `sshd_config` and repeatable keywords
+    Get {
+        #[clap(short = 's', long, hide = true)]
+        setting: Setting,
+    },
+    /// Set default shell, eventually to be used for `sshd_config` and repeatable keywords
+    Set {
+        #[clap(short = 'i', long, help = t!("args.setInput").to_string())]
+        input: String
+    },
+    /// Export `sshd_config`
+    Export,
+    Schema {
+        // Used to inform which schema to generate
+        #[clap(short = 's', long, hide = true)]
+        setting: Setting,
+    },
+}
+
+#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
+pub struct DefaultShell {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub shell: Option<String>,
+    #[serde(rename = "cmdOption", skip_serializing_if = "Option::is_none")]
+    pub cmd_option: Option<String>,
+    #[serde(rename = "escapeArguments", skip_serializing_if = "Option::is_none")]
+    pub escape_arguments: Option<bool>,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq, ValueEnum)]
+pub enum Setting {
+    SshdConfig,
+    WindowsGlobal
+}
\ No newline at end of file
diff --git a/sshdconfig/src/error.rs b/sshdconfig/src/error.rs
index bfd931d16..53206aced 100644
--- a/sshdconfig/src/error.rs
+++ b/sshdconfig/src/error.rs
@@ -1,18 +1,26 @@
 // Copyright (c) Microsoft Corporation.
 // Licensed under the MIT License.
 
+use rust_i18n::t;
 use thiserror::Error;
 
 #[derive(Debug, Error)]
 pub enum SshdConfigError {
-    #[error("Command: {0}")]
+    #[error("{t}: {0}", t = t!("error.command"))]
     CommandError(String),
-    #[error("JSON: {0}")]
+    #[error("{t}: {0}", t = t!("error.invalidInput"))]
+    InvalidInput(String),
+    #[error("{t}: {0}", t = t!("error.json"))]
     Json(#[from] serde_json::Error),
-    #[error("Language: {0}")]
+    #[error("{t}: {0}", t = t!("error.language"))]
     LanguageError(#[from] tree_sitter::LanguageError),
-    #[error("Parser: {0}")]
+    #[error("{t}: {0}", t = t!("error.notImplemented"))]
+    NotImplemented(String),
+    #[error("{t}: {0}", t = t!("error.parser"))]
     ParserError(String),
-    #[error("Parser Int: {0}")]
+    #[error("{t}: {0}", t = t!("error.parseInt"))]
     ParseIntError(#[from] std::num::ParseIntError),
+    #[cfg(windows)]
+    #[error("{t}: {0}", t = t!("error.registry"))]
+    RegistryError(#[from] registry_lib::error::RegistryError),
 }
diff --git a/sshdconfig/src/export.rs b/sshdconfig/src/export.rs
index f9e129ff6..bc720c3a7 100644
--- a/sshdconfig/src/export.rs
+++ b/sshdconfig/src/export.rs
@@ -10,9 +10,10 @@ use crate::util::invoke_sshd_config_validation;
 /// # Errors
 ///
 /// This function will return an error if the command cannot invoke sshd -T, parse the return, or convert it to json.
-pub fn invoke_export() -> Result<String, SshdConfigError> {
+pub fn invoke_export() -> Result<(), SshdConfigError> {
     let sshd_config_text = invoke_sshd_config_validation()?;
     let sshd_config: serde_json::Map<String, serde_json::Value> = parse_text_to_map(&sshd_config_text)?;
-    let json = serde_json::to_string_pretty(&sshd_config)?;
-    Ok(json)
+    let json = serde_json::to_string(&sshd_config)?;
+    println!("{json}");
+    Ok(())
 }
diff --git a/sshdconfig/src/get.rs b/sshdconfig/src/get.rs
new file mode 100644
index 000000000..837e8d011
--- /dev/null
+++ b/sshdconfig/src/get.rs
@@ -0,0 +1,81 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#[cfg(windows)]
+use {
+    registry_lib::{config::{Registry, RegistryValueData}, RegistryHelper},
+    crate::args::DefaultShell,
+    crate::metadata::windows::{DEFAULT_SHELL, DEFAULT_SHELL_CMD_OPTION, DEFAULT_SHELL_ESCAPE_ARGS, REGISTRY_PATH},
+};
+
+use crate::args::Setting;
+use crate::error::SshdConfigError;
+use rust_i18n::t;
+
+/// Invoke the get command.
+///
+/// # Errors
+///
+/// This function will return an error if the desired settings cannot be retrieved.
+pub fn invoke_get(setting: &Setting) -> Result<(), SshdConfigError> {
+    match *setting {
+        Setting::SshdConfig => Err(SshdConfigError::NotImplemented(t!("get.notImplemented").to_string())),
+        Setting::WindowsGlobal => get_default_shell()
+    }
+}
+
+#[cfg(windows)]
+fn get_default_shell() -> Result<(), SshdConfigError> {
+    let registry_helper = RegistryHelper::new(REGISTRY_PATH, Some(DEFAULT_SHELL.to_string()), None)?;
+    let default_shell: Registry = registry_helper.get()?;
+    let mut shell = None;
+    // default_shell is a single string consisting of the shell exe path
+    if let Some(value) = default_shell.value_data {
+        match value {
+            RegistryValueData::String(s) => {
+                shell = Some(s);
+            }
+            _ => return Err(SshdConfigError::InvalidInput(t!("get.defaultShellMustBeString").to_string())),
+        }
+    }
+
+    let registry_helper = RegistryHelper::new(REGISTRY_PATH, Some(DEFAULT_SHELL_CMD_OPTION.to_string()), None)?;
+    let option: Registry = registry_helper.get()?;
+    let mut cmd_option = None;
+    if let Some(value) = option.value_data {
+        match value {
+            RegistryValueData::String(s) => cmd_option = Some(s),
+            _ => return Err(SshdConfigError::InvalidInput(t!("get.defaultShellCmdOptionMustBeString").to_string())),
+        }
+    }
+
+    let registry_helper = RegistryHelper::new(REGISTRY_PATH, Some(DEFAULT_SHELL_ESCAPE_ARGS.to_string()), None)?;
+    let escape_args: Registry = registry_helper.get()?;
+    let mut escape_arguments = None;
+    if let Some(value) = escape_args.value_data {
+        if let RegistryValueData::DWord(b) = value {
+            if b == 0 || b == 1 {
+                escape_arguments = if b == 1 { Some(true) } else { Some(false) };
+            } else {
+                return Err(SshdConfigError::InvalidInput(t!("get.defaultShellEscapeArgsMustBe0Or1", input = b).to_string()));
+            }
+        } else {
+            return Err(SshdConfigError::InvalidInput(t!("get.defaultShellEscapeArgsMustBeDWord").to_string()));
+        }
+    }
+
+    let result = DefaultShell {
+        shell,
+        cmd_option,
+        escape_arguments
+    };
+
+    let output = serde_json::to_string(&result)?;
+    println!("{output}");
+    Ok(())
+}
+
+#[cfg(not(windows))]
+fn get_default_shell() -> Result<(), SshdConfigError> {
+    Err(SshdConfigError::InvalidInput(t!("get.windowsOnly").to_string()))
+}
diff --git a/sshdconfig/src/main.rs b/sshdconfig/src/main.rs
index acb5d2c5d..ef2ce3bc3 100644
--- a/sshdconfig/src/main.rs
+++ b/sshdconfig/src/main.rs
@@ -1,43 +1,50 @@
 // Copyright (c) Microsoft Corporation.
 // Licensed under the MIT License.
 
+use clap::{Parser};
+use rust_i18n::i18n;
 use schemars::schema_for;
-use serde_json::to_string_pretty;
-use std::{env::args, process::exit};
 
-use crate::export::invoke_export;
-use crate::parser::SshdConfigParser;
+use args::{Args, Command, DefaultShell, Setting};
+use export::invoke_export;
+use get::invoke_get;
+use parser::SshdConfigParser;
+use set::invoke_set;
 
+mod args;
 mod error;
 mod export;
+mod get;
 mod metadata;
 mod parser;
+mod set;
 mod util;
 
-fn main() {
-
-    // TODO: add support for other commands and use clap for argument parsing
-    let args: Vec<String> = args().collect();
+i18n!("locales", fallback = "en-us");
 
-    if args.len() != 2 || (args[1] != "export" && args[1] != "schema") {
-        eprintln!("Usage: {} <export|schema>", args[0]);
-        exit(1);
-    }
-
-    if args[1] == "schema" {
-        // for dsc tests on linux/mac
-        let schema = schema_for!(SshdConfigParser);
-        println!("{}", to_string_pretty(&schema).unwrap());
-        return;
-    }
-
-    // only supports export for sshdconfig for now
-    match invoke_export() {
-        Ok(result) => {
-            println!("{result}");
-        }
-        Err(e) => {
-            eprintln!("Error exporting SSHD config: {e:?}");
+fn main() {
+    let args = Args::parse();
+
+    let result = match &args.command {
+        Command::Export => invoke_export(),
+        Command::Get { setting } => invoke_get(setting),
+        Command::Set { input } => invoke_set(input),
+        Command::Schema { setting } => {
+            let schema = match setting {
+                Setting::SshdConfig => {
+                    schema_for!(SshdConfigParser)
+                },
+                Setting::WindowsGlobal => {
+                    schema_for!(DefaultShell)
+                }
+            };
+            println!("{}", serde_json::to_string(&schema).unwrap());
+            Ok(())
         }
+    };
+
+    if let Err(e) = result {
+        eprintln!("{e}");
+        std::process::exit(1);
     }
 }
diff --git a/sshdconfig/src/metadata.rs b/sshdconfig/src/metadata.rs
index d1f56311d..e3d7a37f6 100644
--- a/sshdconfig/src/metadata.rs
+++ b/sshdconfig/src/metadata.rs
@@ -1,6 +1,8 @@
 // Copyright (c) Microsoft Corporation.
 // Licensed under the MIT License.
 
+use clap::ValueEnum;
+
 // TODO: ensure lists are complete
 
 // keywords that can be repeated over multiple lines and should be represented as arrays
@@ -13,6 +15,16 @@ pub const REPEATABLE_KEYWORDS: [&str; 6] = [
     "subsystem"
 ];
 
+#[derive(Clone, Debug, Eq, PartialEq, ValueEnum)]
+pub enum RepeatableKeyword {
+    HostKey,
+    Include,
+    ListenAddress,
+    Port,
+    SetEnv,
+    Subsystem,
+}
+
 // keywords that can have multiple argments per line and should be represented as arrays
 // but cannot be repeated over multiple lines, as subsequent entries are ignored
 pub const MULTI_ARG_KEYWORDS: [&str; 7] = [
@@ -24,3 +36,11 @@ pub const MULTI_ARG_KEYWORDS: [&str; 7] = [
     "macs",
     "pubkeyacceptedalgorithms"
 ];
+
+#[cfg(windows)]
+pub mod windows {
+    pub const REGISTRY_PATH: &str = "HKLM\\SOFTWARE\\OpenSSH";
+    pub const DEFAULT_SHELL: &str = "DefaultShell";
+    pub const DEFAULT_SHELL_CMD_OPTION: &str = "DefaultShellCommandOption";
+    pub const DEFAULT_SHELL_ESCAPE_ARGS: &str = "DefaultShellEscapeArguments";
+}
diff --git a/sshdconfig/src/parser.rs b/sshdconfig/src/parser.rs
index f6e3cad0f..42aead483 100644
--- a/sshdconfig/src/parser.rs
+++ b/sshdconfig/src/parser.rs
@@ -7,6 +7,7 @@ use tree_sitter::Parser;
 
 use crate::error::SshdConfigError;
 use crate::metadata::{MULTI_ARG_KEYWORDS, REPEATABLE_KEYWORDS};
+use rust_i18n::t;
 
 #[derive(Debug, JsonSchema)]
 pub struct SshdConfigParser {
@@ -35,14 +36,14 @@ impl SshdConfigParser {
         parser.set_language(&tree_sitter_ssh_server_config::LANGUAGE.into())?;
 
         let Some(tree) = &mut parser.parse(input, None) else {
-            return Err(SshdConfigError::ParserError(format!("failed to parse: {input}")));
+            return Err(SshdConfigError::ParserError(t!("parser.failedToParse", input = input).to_string()));
         };
         let root_node = tree.root_node();
         if root_node.is_error() {
-            return Err(SshdConfigError::ParserError(format!("failed to parse root: {input}")));
+            return Err(SshdConfigError::ParserError(t!("parser.failedToParseRoot", input = input).to_string()));
         }
         if root_node.kind() != "server_config" {
-            return Err(SshdConfigError::ParserError(format!("invalid config: {input}")));
+            return Err(SshdConfigError::ParserError(t!("parser.invalidConfig", input = input).to_string()));
         }
         let input_bytes = input.as_bytes();
         let mut cursor = root_node.walk();
@@ -54,12 +55,12 @@ impl SshdConfigParser {
 
     fn parse_child_node(&mut self, node: tree_sitter::Node, input: &str, input_bytes: &[u8]) -> Result<(), SshdConfigError> {
         if node.is_error() {
-            return Err(SshdConfigError::ParserError(format!("failed to parse: {input}")));
+            return Err(SshdConfigError::ParserError(t!("parser.failedToParse", input = input).to_string()));
         }
         match node.kind() {
             "keyword" => self.parse_keyword_node(node, input, input_bytes),
             "comment" | "empty_line" => Ok(()),
-            _ => Err(SshdConfigError::ParserError(format!("unknown node type: {}", node.kind()))),
+            _ => Err(SshdConfigError::ParserError(t!("parser.unknownNodeType", node = node.kind()).to_string())),
         }
     }
 
@@ -72,9 +73,9 @@ impl SshdConfigParser {
 
         if let Some(keyword) = keyword_node.child_by_field_name("keyword") {
             let Ok(text) = keyword.utf8_text(input_bytes) else {
-                return Err(SshdConfigError::ParserError(format!(
-                    "failed to parse keyword node: {input}"
-                )));
+                return Err(SshdConfigError::ParserError(
+                    t!("parser.failedToParseChildNode", input = input).to_string()
+                ));
             };
             if REPEATABLE_KEYWORDS.contains(&text) {
                 is_repeatable = true;
@@ -87,7 +88,7 @@ impl SshdConfigParser {
 
         for node in keyword_node.named_children(&mut cursor) {
             if node.is_error() {
-                return Err(SshdConfigError::ParserError(format!("failed to parse child node: {input}")));
+                return Err(SshdConfigError::ParserError(t!("parser.failedToParseChildNode", input = input).to_string()));
             }
             if node.kind() == "arguments" {
                 value = parse_arguments_node(node, input, input_bytes, is_vec)?;
@@ -95,11 +96,11 @@ impl SshdConfigParser {
         }
         if let Some(key) = key {
             if value.is_null() {
-                return Err(SshdConfigError::ParserError(format!("missing value in child node: {input}")));
+                return Err(SshdConfigError::ParserError(t!("parser.missingValueInChildNode", input = input).to_string()));
             }
             return self.update_map(&key, value, is_repeatable);
         }
-        Err(SshdConfigError::ParserError(format!("missing key in child node: {input}")))
+        Err(SshdConfigError::ParserError(t!("parser.missingKeyInChildNode", input = input).to_string()))
     }
 
     fn update_map(&mut self, key: &str, value: Value, is_repeatable: bool) -> Result<(), SshdConfigError> {
@@ -114,19 +115,19 @@ impl SshdConfigParser {
                             }
                         } else {
                             return Err(SshdConfigError::ParserError(
-                                "value is not an array".to_string(),
+                                t!("parser.failedToParseAsArray").to_string()
                             ));
                         }
                     } else {
                         return Err(SshdConfigError::ParserError(
-                            "value is not an array".to_string(),
+                            t!("parser.failedToParseAsArray").to_string()
                         ));
                     }
                 } else {
-                    return Err(SshdConfigError::ParserError(format!("key {key} not found")));
+                    return Err(SshdConfigError::ParserError(t!("parser.keyNotFound", key = key).to_string()));
                 }
             } else {
-                return Err(SshdConfigError::ParserError(format!("key {key} is not repeatable")));
+                return Err(SshdConfigError::ParserError(t!("parser.keyNotRepeatable", key = key).to_string()));
             }
         } else {
             self.map.insert(key.to_string(), value);
@@ -142,32 +143,32 @@ fn parse_arguments_node(arg_node: tree_sitter::Node, input: &str, input_bytes: &
     for node in arg_node.named_children(&mut cursor) {
 
         if node.is_error() {
-            return Err(SshdConfigError::ParserError(format!("failed to parse child node: {input}")));
+            return Err(SshdConfigError::ParserError(t!("parser.failedToParseChildNode", input = input).to_string()));
         }
         let argument: Value = match node.kind() {
             "boolean" | "string" => {
                 let Ok(arg) = node.utf8_text(input_bytes) else {
-                    return Err(SshdConfigError::ParserError(format!(
-                        "failed to parse string node: {input}"
-                    )));
+                    return Err(SshdConfigError::ParserError(
+                        t!("parser.failedToParseNode", input = input).to_string()
+                    ));
                 };
                 Value::String(arg.to_string())
             }
             "number" => {
                 let Ok(arg) = node.utf8_text(input_bytes) else {
-                    return Err(SshdConfigError::ParserError(format!(
-                        "failed to parse string node: {input}"
-                    )));
+                    return Err(SshdConfigError::ParserError(
+                        t!("parser.failedToParseNode", input = input).to_string()
+                    ));
                 };
                 Value::Number(arg.parse::<u64>()?.into())
             }
             "operator" => {
                 // TODO: handle operator if not parsing from SSHD -T
-                return Err(SshdConfigError::ParserError(format!(
-                    "todo - unsuported node: {}", node.kind()
-                )));
+                return Err(SshdConfigError::ParserError(
+                    t!("parser.invalidValue").to_string()
+                ));
             }
-            _ => return Err(SshdConfigError::ParserError(format!("unknown node: {}", node.kind())))
+            _ => return Err(SshdConfigError::ParserError(t!("parser.unknownNode", kind = node.kind()).to_string()))
         };
         if is_vec {
             vec.push(argument);
diff --git a/sshdconfig/src/set.rs b/sshdconfig/src/set.rs
new file mode 100644
index 000000000..349e36cf3
--- /dev/null
+++ b/sshdconfig/src/set.rs
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#[cfg(windows)]
+use {
+    std::path::Path,
+    registry_lib::{config::RegistryValueData, RegistryHelper},
+    crate::metadata::windows::{DEFAULT_SHELL, DEFAULT_SHELL_CMD_OPTION, DEFAULT_SHELL_ESCAPE_ARGS, REGISTRY_PATH},
+};
+
+use crate::args::DefaultShell;
+use crate::error::SshdConfigError;
+use rust_i18n::t;
+
+/// Invoke the set command.
+///
+/// # Errors
+///
+/// This function will return an error if the desired settings cannot be applied.
+pub fn invoke_set(input: &str) -> Result<(), SshdConfigError> {
+    match serde_json::from_str::<DefaultShell>(input) {
+        Ok(default_shell) => {
+            set_default_shell(default_shell.shell, default_shell.cmd_option, default_shell.escape_arguments)
+        },
+        Err(e) => {
+            Err(SshdConfigError::InvalidInput(t!("set.failedToParseInput", error = e).to_string()))
+        }
+    }
+}
+
+#[cfg(windows)]
+fn set_default_shell(shell: Option<String>, cmd_option: Option<String>, escape_arguments: Option<bool>) -> Result<(), SshdConfigError> {
+    if let Some(shell) = shell {
+        // TODO: if shell contains quotes, we need to remove them
+        let shell_path = Path::new(&shell);
+        if shell_path.is_relative() && shell_path.components().any(|c| c == std::path::Component::ParentDir) {
+            return Err(SshdConfigError::InvalidInput(t!("set.shellPathMustNotBeRelative").to_string()));
+        }
+        if !shell_path.exists() {
+            return Err(SshdConfigError::InvalidInput(t!("set.shellPathDoesNotExist", shell = shell).to_string()));
+        }
+
+        set_registry(DEFAULT_SHELL, RegistryValueData::String(shell))?;
+    } else {
+        remove_registry(DEFAULT_SHELL)?;
+    }
+
+
+    if let Some(cmd_option) = cmd_option {
+        set_registry(DEFAULT_SHELL_CMD_OPTION, RegistryValueData::String(cmd_option.clone()))?;
+    } else {
+        remove_registry(DEFAULT_SHELL_CMD_OPTION)?;
+    }
+
+    if let Some(escape_args) = escape_arguments {
+        let mut escape_data = 0;
+        if escape_args {
+            escape_data = 1;
+        }
+        set_registry(DEFAULT_SHELL_ESCAPE_ARGS, RegistryValueData::DWord(escape_data))?;
+    } else {
+        remove_registry(DEFAULT_SHELL_ESCAPE_ARGS)?;
+    }
+
+    Ok(())
+}
+
+#[cfg(not(windows))]
+fn set_default_shell(_shell: Option<String>, _cmd_option: Option<String>, _escape_arguments: Option<bool>) -> Result<(), SshdConfigError> {
+    Err(SshdConfigError::InvalidInput(t!("get.windowsOnly").to_string()))
+}
+
+#[cfg(windows)]
+fn set_registry(name: &str, data: RegistryValueData) -> Result<(), SshdConfigError> {
+    let registry_helper = RegistryHelper::new(REGISTRY_PATH, Some(name.to_string()), Some(data))?;
+    registry_helper.set()?;
+    Ok(())
+}
+
+#[cfg(windows)]
+fn remove_registry(name: &str) -> Result<(), SshdConfigError> {
+    let registry_helper = RegistryHelper::new(REGISTRY_PATH, Some(name.to_string()), None)?;
+    registry_helper.remove()?;
+    Ok(())
+}
diff --git a/sshdconfig/src/util.rs b/sshdconfig/src/util.rs
index 1e1235784..cc3ca84b5 100644
--- a/sshdconfig/src/util.rs
+++ b/sshdconfig/src/util.rs
@@ -4,6 +4,7 @@
 use std::process::Command;
 
 use crate::error::SshdConfigError;
+use rust_i18n::t;
 
 /// Invoke sshd -T.
 ///
@@ -29,9 +30,9 @@ pub fn invoke_sshd_config_validation() -> Result<String, SshdConfigError> {
     } else {
         let stderr = String::from_utf8(output.stderr)
             .map_err(|e| SshdConfigError::CommandError(e.to_string()))?;
-        if stderr.contains("sshd: no hostkeys available") {
+        if stderr.contains("sshd: no hostkeys available") || stderr.contains("Permission denied") {
             return Err(SshdConfigError::CommandError(
-                "sshd: no hostkeys available, please run as admin".to_string(),
+                t!("util.sshdElevation").to_string()
             ));
         }
         Err(SshdConfigError::CommandError(stderr))
diff --git a/sshdconfig/sshd-windows.dsc.resource.json b/sshdconfig/sshd-windows.dsc.resource.json
new file mode 100644
index 000000000..574dc28c6
--- /dev/null
+++ b/sshdconfig/sshd-windows.dsc.resource.json
@@ -0,0 +1,37 @@
+{
+    "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
+    "type": "Microsoft.OpenSSH.SSHD/Windows",
+    "description": "Manage SSH Server Configuration Global Settings",
+    "tags": [
+        "Windows"
+    ],
+    "version": "0.1.0",
+    "get": {
+        "executable": "sshdconfig",
+        "args": [
+            "get",
+            "-s",
+            "windows-global"
+        ]
+    },
+    "set": {
+        "executable": "sshdconfig",
+        "args": [
+            "set",
+            {
+                "jsonInputArg": "--input",
+                "mandatory": true
+            }
+        ]
+    },
+    "schema": {
+        "command": {
+            "executable": "sshdconfig",
+            "args": [
+                "schema",
+                "-s",
+                "windows-global"
+            ]
+        }
+    }
+}
diff --git a/sshdconfig/sshdconfig.dsc.resource.json b/sshdconfig/sshd_config.dsc.resource.json
similarity index 85%
rename from sshdconfig/sshdconfig.dsc.resource.json
rename to sshdconfig/sshd_config.dsc.resource.json
index fa97f9be4..c18dd7d9a 100644
--- a/sshdconfig/sshdconfig.dsc.resource.json
+++ b/sshdconfig/sshd_config.dsc.resource.json
@@ -13,7 +13,9 @@
         "command": {
             "executable": "sshdconfig",
             "args": [
-                "schema"
+                "schema",
+                "-s",
+                "sshd-config"
             ]
         }
     }
diff --git a/sshdconfig/tests/defaultshell.tests.ps1 b/sshdconfig/tests/defaultshell.tests.ps1
new file mode 100644
index 000000000..baa97524b
--- /dev/null
+++ b/sshdconfig/tests/defaultshell.tests.ps1
@@ -0,0 +1,209 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+
+Describe 'Default Shell Configuration Tests' -Skip:(!$IsWindows) {
+    BeforeAll {
+        # Store original registry values to restore later
+        $OriginalValues = @{}
+        $RegistryPath = "HKLM:\SOFTWARE\OpenSSH"
+        $ValueNames = @("DefaultShell", "DefaultShellCommandOption", "DefaultShellEscapeArguments")
+        $CreatedOpenSSHKey = $false
+
+        # Create OpenSSH registry key if it doesn't exist
+        if (-not (Test-Path $RegistryPath)) {
+            $CreatedOpenSSHKey = $true
+            New-Item -Path $RegistryPath -Force | Out-Null
+        }
+        else {
+            # Store existing values
+            foreach ($valueName in $ValueNames) {
+                try {
+                    $value = Get-ItemProperty -Path $RegistryPath -Name $valueName -ErrorAction SilentlyContinue
+                    if ($value) {
+                        $OriginalValues[$valueName] = $value.$valueName
+                        Remove-ItemProperty -Path $RegistryPath -Name $valueName -ErrorAction SilentlyContinue
+                    }
+                }
+                catch {
+                    # Value doesn't currently exist, nothing to store
+                }
+            }
+        }
+    }
+
+    AfterAll {
+        # Restore original registry values
+        if ($CreatedOpenSSHKey) {
+            # Remove the OpenSSH key if it was created for the tests
+            Remove-Item -Path $RegistryPath -Force -ErrorAction SilentlyContinue
+        } else {
+            foreach ($valueName in $ValueNames) {
+                if ($OriginalValues.ContainsKey($valueName)) {
+                    New-ItemProperty -Path $RegistryPath -Name $valueName -Value $OriginalValues[$valueName]
+                }
+            }
+        }
+    }
+
+    AfterEach {
+        # Clean up any properties set during the tests
+        foreach ($valueName in $ValueNames) {
+            try {
+                Remove-ItemProperty -Path $RegistryPath -Name $valueName -ErrorAction SilentlyContinue
+            }
+            catch {
+                # Ignore if value doesn't exist
+            }
+        }
+    }
+
+    Context 'Get Default Shell' {
+        It 'Should get default shell without args when registry value exists' {
+            $testShell = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+            New-ItemProperty -Path $RegistryPath -Name "DefaultShell" -Value $testShell
+
+            $output = sshdconfig get -s windows-global
+            $LASTEXITCODE | Should -Be 0
+
+            $result = $output | ConvertFrom-Json
+            $result.shell | Should -Be $testShell
+            $result.cmdOption | Should -BeNullOrEmpty
+            $result.escapeArguments | Should -BeNullOrEmpty
+        }
+
+        It 'Should get default shell with args when registry value exists' {
+            $testShell = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+            $testShellWithArgs = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+            New-ItemProperty -Path $RegistryPath -Name "DefaultShell" -Value $testShellWithArgs
+            New-ItemProperty -Path $RegistryPath -Name "DefaultShellCommandOption" -Value "/c"
+            New-ItemProperty -Path $RegistryPath -Name "DefaultShellEscapeArguments" -Value 0 -Type DWord
+
+            $output = sshdconfig get -s windows-global
+            $LASTEXITCODE | Should -Be 0
+
+            $result = $output | ConvertFrom-Json
+            $result.shell | Should -Be $testShell
+            $result.cmdOption | Should -Be "/c"
+            $result.escapeArguments | Should -Be $false
+        }
+
+        It 'Should handle empty default shell registry values' -Skip:(!$IsWindows) {
+            $output = sshdconfig get -s windows-global
+            $LASTEXITCODE | Should -Be 0
+
+            $result = $output | ConvertFrom-Json
+            $result.shell | Should -BeNullOrEmpty
+            $result.cmdOption | Should -BeNullOrEmpty
+            $result.escapeArguments | Should -BeNullOrEmpty
+        }
+    }
+
+    Context 'Set Default Shell' {
+        It 'Should set default shell with valid configuration' {
+            $testShell = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+
+            $inputConfig = @{
+                shell = $testShell
+                cmdOption = "/c"
+                escapeArguments = $false
+            } | ConvertTo-Json
+
+            sshdconfig set --input $inputConfig
+            $LASTEXITCODE | Should -Be 0
+
+            $defaultShell = Get-ItemProperty -Path $RegistryPath -Name "DefaultShell" -ErrorAction SilentlyContinue
+            $defaultShell.DefaultShell | Should -Be $testShell
+
+            $cmdOption = Get-ItemProperty -Path $RegistryPath -Name "DefaultShellCommandOption" -ErrorAction SilentlyContinue
+            $cmdOption.DefaultShellCommandOption | Should -Be "/c"
+
+            $escapeArgs = Get-ItemProperty -Path $RegistryPath -Name "DefaultShellEscapeArguments" -ErrorAction SilentlyContinue
+            $escapeArgs.DefaultShellEscapeArguments | Should -Be 0
+        }
+
+        It 'Should set default shell with minimal configuration' {
+            $inputConfig = @{
+                shell = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+            } | ConvertTo-Json
+
+            sshdconfig set --input $inputConfig
+            $LASTEXITCODE | Should -Be 0
+
+            $defaultShell = Get-ItemProperty -Path $RegistryPath -Name "DefaultShell" -ErrorAction SilentlyContinue
+            $defaultShell.DefaultShell | Should -Be "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+        }
+
+        It 'Should handle invalid JSON input gracefully' {
+            $invalidJson = "{ invalid json }"
+
+            sshdconfig set --input $invalidJson
+            $LASTEXITCODE | Should -Not -Be 0
+        }
+
+        It 'Should clear default shell when set to null' {
+            Set-ItemProperty -Path $RegistryPath -Name "DefaultShell" -Value "C:\Windows\System32\cmd.exe"
+
+            $inputConfig = @{ shell = $null } | ConvertTo-Json
+
+            sshdconfig set --input $inputConfig
+            $LASTEXITCODE | Should -Be 0
+
+            $result = Get-ItemProperty -Path $RegistryPath -Name "DefaultShell" -ErrorAction SilentlyContinue
+            $result | Should -BeNullOrEmpty
+        }
+    }
+
+    Context 'Set then get default shell' {
+        It 'Should maintain configuration consistency between set and get' {
+            $originalConfig = @{
+                shell = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+                cmdOption = "/c"
+                escapeArguments = $true
+            }
+            $inputJson = $originalConfig | ConvertTo-Json
+
+            sshdconfig set --input $inputJson
+            $LASTEXITCODE | Should -Be 0
+
+            $getOutput = sshdconfig get -s windows-global
+            $LASTEXITCODE | Should -Be 0
+
+            $retrievedConfig = $getOutput | ConvertFrom-Json
+
+            $retrievedConfig.shell | Should -Be $originalConfig.shell
+            $retrievedConfig.cmdOption | Should -Be $originalConfig.cmdOption
+            $retrievedConfig.escapeArguments | Should -Be $originalConfig.escapeArguments
+        }
+    }
+
+    Context 'Set default shell with null value' {
+        It 'Should clear existing default shell when set to null' {
+            $testShell = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
+            New-ItemProperty -Path $RegistryPath -Name "DefaultShell" -Value $testShell
+
+            $inputConfig = @{ shell = $null } | ConvertTo-Json
+
+            sshdconfig set --input $inputConfig
+            $LASTEXITCODE | Should -Be 0
+
+            $result = Get-ItemProperty -Path $RegistryPath -Name "DefaultShell" -ErrorAction SilentlyContinue
+            $result | Should -BeNullOrEmpty
+        }
+    }
+}
+
+Describe 'Default Shell Configuration Error Handling on Non-Windows Platforms' -Skip:($IsWindows) {
+    It 'Should return error for set command' {
+        $inputConfig = @{ shell = $null } | ConvertTo-Json
+
+        $out = sshdconfig set --input $inputConfig 2>&1
+        $LASTEXITCODE | Should -Not -Be 0
+        $out | Should -BeLike '*is only applicable to Windows*'
+    }
+
+    It 'Should return error for get command' {
+        $out = sshdconfig get -s windows-global 2>&1
+        $LASTEXITCODE | Should -Not -Be 0
+        $out | Should -BeLike '*is only applicable to Windows*'
+    }
+}