diff --git a/.goreleaser.yml b/.goreleaser.yml
index e3c75049dba41a7621c2017b40db5f8183f8eb17..d41eae7806ad5185a3fc91f2dc5144a1a4092cf0 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -57,6 +57,19 @@ builds:
     goarch: [arm64]
     # No "upx", since it causes random core dumps, see
     # https://github.com/binwiederhier/ntfy/issues/191#issuecomment-1083406546
+  -
+    id: ntfy_windows_amd64
+    binary: ntfy
+    env:
+      - CGO_ENABLED=0 # explicitly disable, since we don't need go-sqlite3
+    tags: []
+    ldflags:
+      - "-X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
+    goos: [windows]
+    goarch: [amd64]
+    hooks:
+      post:
+        - upx "{{ .Path }}" # apt install upx
 nfpms:
   -
     package_name: ntfy
diff --git a/cmd/access.go b/cmd/access_linux.go
similarity index 99%
rename from cmd/access.go
rename to cmd/access_linux.go
index b3cacfa54664d4217de6f6bbb539a135af5133bd..2334a04d2a0c8bb2f2986ed622f757bc4be55e97 100644
--- a/cmd/access.go
+++ b/cmd/access_linux.go
@@ -8,6 +8,10 @@ import (
 	"heckel.io/ntfy/util"
 )
 
+func init() {
+	commands = append(commands, cmdAccess)
+}
+
 const (
 	userEveryone = "everyone"
 )
diff --git a/cmd/access_test.go b/cmd/access_linux_test.go
similarity index 100%
rename from cmd/access_test.go
rename to cmd/access_linux_test.go
diff --git a/cmd/app.go b/cmd/app.go
index 85540ceed454a5032e62877f3d65c7d31c49a0fb..504bde5fcf275efb70765e15faf4f5dd3d24fc37 100644
--- a/cmd/app.go
+++ b/cmd/app.go
@@ -19,6 +19,8 @@ const (
 	categoryServer = "Server commands"
 )
 
+var commands = make([]*cli.Command, 0)
+
 // New creates a new CLI application
 func New() *cli.App {
 	return &cli.App{
@@ -30,16 +32,7 @@ func New() *cli.App {
 		Reader:                 os.Stdin,
 		Writer:                 os.Stdout,
 		ErrWriter:              os.Stderr,
-		Commands: []*cli.Command{
-			// Server commands
-			cmdServe,
-			cmdUser,
-			cmdAccess,
-
-			// Client commands
-			cmdPublish,
-			cmdSubscribe,
-		},
+		Commands:               commands,
 	}
 }
 
diff --git a/cmd/publish.go b/cmd/publish.go
index e210308a67d75cda9ec2c6128b71036f946b89d6..34d7bf70df2d7c3e016a6fba2b6adfbbfcfc1226 100644
--- a/cmd/publish.go
+++ b/cmd/publish.go
@@ -12,6 +12,10 @@ import (
 	"strings"
 )
 
+func init() {
+	commands = append(commands, cmdPublish)
+}
+
 var cmdPublish = &cli.Command{
 	Name:      "publish",
 	Aliases:   []string{"pub", "send", "trigger"},
diff --git a/cmd/serve.go b/cmd/serve_linux.go
similarity index 99%
rename from cmd/serve.go
rename to cmd/serve_linux.go
index 2fd878d5b3940d7c8b4afaccb453bc710e6e280a..b56268b499ee56239dfde904f748ebcc5f72ecf9 100644
--- a/cmd/serve.go
+++ b/cmd/serve_linux.go
@@ -14,6 +14,10 @@ import (
 	"time"
 )
 
+func init() {
+	commands = append(commands, cmdServe)
+}
+
 var flagsServe = []cli.Flag{
 	&cli.StringFlag{Name: "config", Aliases: []string{"c"}, EnvVars: []string{"NTFY_CONFIG_FILE"}, Value: "/etc/ntfy/server.yml", DefaultText: "/etc/ntfy/server.yml", Usage: "config file"},
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "base-url", Aliases: []string{"B"}, EnvVars: []string{"NTFY_BASE_URL"}, Usage: "externally visible base URL for this host (e.g. https://ntfy.sh)"}),
diff --git a/cmd/serve_test.go b/cmd/serve_linux_test.go
similarity index 100%
rename from cmd/serve_test.go
rename to cmd/serve_linux_test.go
diff --git a/cmd/subscribe.go b/cmd/subscribe.go
index 9000a163497b58faebd746b1e68ba552f490be4b..95ad02a4478365eb2238d96e14a7d569cb4ed13e 100644
--- a/cmd/subscribe.go
+++ b/cmd/subscribe.go
@@ -13,6 +13,10 @@ import (
 	"strings"
 )
 
+func init() {
+	commands = append(commands, cmdSubscribe)
+}
+
 var cmdSubscribe = &cli.Command{
 	Name:      "subscribe",
 	Aliases:   []string{"sub"},
diff --git a/cmd/user.go b/cmd/user_linux.go
similarity index 99%
rename from cmd/user.go
rename to cmd/user_linux.go
index 1057ba48b4fcdda596a234a78fe8cec6d3287995..3fc3a5b7bc1805e7fdac37f37924aeb66218a9f7 100644
--- a/cmd/user.go
+++ b/cmd/user_linux.go
@@ -11,7 +11,12 @@ import (
 	"strings"
 )
 
+func init() {
+	commands = append(commands, cmdUser)
+}
+
 var flagsUser = userCommandFlags()
+
 var cmdUser = &cli.Command{
 	Name:      "user",
 	Usage:     "Manage/show users",
diff --git a/cmd/user_test.go b/cmd/user_linux_test.go
similarity index 100%
rename from cmd/user_test.go
rename to cmd/user_linux_test.go