diff --git a/pkgs/build-support/build-bazel-package/default.nix b/pkgs/build-support/build-bazel-package/default.nix
index 07d37451ddf..28247bac102 100644
--- a/pkgs/build-support/build-bazel-package/default.nix
+++ b/pkgs/build-support/build-bazel-package/default.nix
@@ -25,7 +25,13 @@ in stdenv.mkDerivation (fBuildAttrs // {
     buildPhase = fFetchAttrs.buildPhase or ''
       runHook preBuild
 
-      bazel --output_base="$bazelOut" --output_user_root="$bazelUserRoot" fetch $bazelFlags $bazelTarget
+      # Bazel computes the default value of output_user_root before parsing the
+      # flag. The computation of the default value involves getting the $USER
+      # from the environment. I don't have that variable when building with
+      # sandbox enabled. Code here
+      # https://github.com/bazelbuild/bazel/blob/9323c57607d37f9c949b60e293b573584906da46/src/main/cpp/startup_options.cc#L123-L124
+      #
+      USER=homeless-shelter bazel --output_base="$bazelOut" --output_user_root="$bazelUserRoot" fetch $bazelFlags $bazelTarget
 
       runHook postBuild
     '';
@@ -33,10 +39,19 @@ in stdenv.mkDerivation (fBuildAttrs // {
     installPhase = fFetchAttrs.installPhase or ''
       runHook preInstall
 
+      # Remove all built in external workspaces, Bazel will recreate them when building
+      rm -rf $bazelOut/external/{bazel_tools,\@bazel_tools.marker}
+      rm -rf $bazelOut/external/{embedded_jdk,\@embedded_jdk.marker}
+      rm -rf $bazelOut/external/{local_*,\@local_*}
+
       # Patching markers to make them deterministic
-      for i in $bazelOut/external/\@*.marker; do
-        sed -i 's, -\?[0-9][0-9]*$, 1,' "$i"
-      done
+      sed -i 's, -\?[0-9][0-9]*$, 1,' $bazelOut/external/\@*.marker
+
+      # Remove all vcs files
+      rm -rf $(find $bazelOut/external -type d -name .git)
+      rm -rf $(find $bazelOut/external -type d -name .svn)
+      rm -rf $(find $bazelOut/external -type d -name .hg)
+
       # Patching symlinks to remove build directory reference
       find $bazelOut/external -type l | while read symlink; do
         ln -sf $(readlink "$symlink" | sed "s,$NIX_BUILD_TOP,NIX_BUILD_TOP,") "$symlink"
diff --git a/pkgs/development/tools/bazel-watcher/default.nix b/pkgs/development/tools/bazel-watcher/default.nix
new file mode 100644
index 00000000000..bedb55ec374
--- /dev/null
+++ b/pkgs/development/tools/bazel-watcher/default.nix
@@ -0,0 +1,80 @@
+{ buildBazelPackage
+, cacert
+, fetchFromGitHub
+, fetchpatch
+, git
+, go
+, stdenv
+}:
+
+buildBazelPackage rec {
+  name = "bazel-watcher-${version}";
+  version = "0.5.0";
+
+  src = fetchFromGitHub {
+    owner = "bazelbuild";
+    repo = "bazel-watcher";
+    rev = "v${version}";
+    sha256 = "1sis723hwax4dg0c28x20yj0hjli66q1ykcvjirgy57znz4iwlq9";
+  };
+
+  patches = [
+    (fetchpatch {
+      url = "https://github.com/bazelbuild/bazel-watcher/commit/4d5928eee3dd5843a1b55136d914b78fef7f25d0.patch";
+      sha256 = "0gxzcdqgifrmvznfy0p5nd11b39n2pwxcvpmhc6hxf85mwlxz7dg";
+    })
+
+    ./update-gazelle-fix-ssl.patch
+  ];
+
+  nativeBuildInputs = [ go git ];
+
+  bazelTarget = "//ibazel";
+
+  fetchAttrs = {
+    preBuild = ''
+      patchShebangs .
+
+      # tell rules_go to use the Go binary found in the PATH
+      sed -e 's:go_register_toolchains():go_register_toolchains(go_version = "host"):g' -i WORKSPACE
+
+      # tell rules_go to invoke GIT with custom CAINFO path
+      export GIT_SSL_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt"
+    '';
+
+    preInstall = ''
+      # Remove the go_sdk (it's just a copy of the go derivation) and all
+      # references to it from the marker files. Bazel does not need to download
+      # this sdk because we have patched the WORKSPACE file to point to the one
+      # currently present in PATH. Without removing the go_sdk from the marker
+      # file, the hash of it will change anytime the Go derivation changes and
+      # that would lead to impurities in the marker files which would result in
+      # a different sha256 for the fetch phase.
+      rm -rf $bazelOut/external/{go_sdk,\@go_sdk.marker}
+      sed -e '/^FILE:@go_sdk.*/d' -i $bazelOut/external/\@*.marker
+    '';
+
+    sha256 = "1iyjvibvlwg980p7nizr6x5v31dyp4a344f0xn839x393583k59d";
+  };
+
+  buildAttrs = {
+    preBuild = ''
+      patchShebangs .
+
+      # tell rules_go to use the Go binary found in the PATH
+      sed -e 's:go_register_toolchains():go_register_toolchains(go_version = "host"):g' -i WORKSPACE
+    '';
+
+    installPhase = ''
+      install -Dm755 bazel-bin/ibazel/*_pure_stripped/ibazel $out/bin/ibazel
+    '';
+  };
+
+  meta = with stdenv.lib; {
+    homepage = https://github.com/bazelbuild/bazel-watcher;
+    description = "Tools for building Bazel targets when source files change.";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ kalbasit ];
+    platforms = platforms.all;
+  };
+}
diff --git a/pkgs/development/tools/bazel-watcher/update-gazelle-fix-ssl.patch b/pkgs/development/tools/bazel-watcher/update-gazelle-fix-ssl.patch
new file mode 100644
index 00000000000..4cf69e9d172
--- /dev/null
+++ b/pkgs/development/tools/bazel-watcher/update-gazelle-fix-ssl.patch
@@ -0,0 +1,19 @@
+diff --git a/WORKSPACE b/WORKSPACE
+index 4011d9b..d085ae8 100644
+--- a/WORKSPACE
++++ b/WORKSPACE
+@@ -52,11 +52,9 @@ http_archive(
+
+ http_archive(
+     name = "bazel_gazelle",
+-    sha256 = "c0a5739d12c6d05b6c1ad56f2200cb0b57c5a70e03ebd2f7b87ce88cabf09c7b",
+-    urls = [
+-        "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/0.14.0/bazel-gazelle-0.14.0.tar.gz",
+-        "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.14.0/bazel-gazelle-0.14.0.tar.gz",
+-    ],
++    sha256 = "0600ea2daf98170211dc561fd348a8a9328c91eb6df66a381eaaf0bcd122e80b",
++    strip_prefix = "bazel-gazelle-b34f46af2f31ee0470e7364352c2376bcc10d079",
++    url = "https://github.com/bazelbuild/bazel-gazelle/archive/b34f46af2f31ee0470e7364352c2376bcc10d079.tar.gz",
+ )
+
+ load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index ba0bbdb2a14..827e430a728 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -8058,6 +8058,8 @@ with pkgs;
     buildBazelPackage = buildBazelPackage.override { enableNixHacks = false; };
   };
 
+  bazel-watcher = callPackage ../development/tools/bazel-watcher { };
+
   buildBazelPackage = callPackage ../build-support/build-bazel-package { };
 
   bear = callPackage ../development/tools/build-managers/bear { };