diff --git a/.github/workflows/build-wrapper.yaml b/.github/workflows/build-wrapper.yaml
index 569edf5c9c7b..7c3ab9b9841e 100644
--- a/.github/workflows/build-wrapper.yaml
+++ b/.github/workflows/build-wrapper.yaml
@@ -6,10 +6,11 @@ on:
 
 permissions:
   actions: read
-  contents: read
+  contents: write
   pages: write
   id-token: write
   packages: write
+  pull-requests: write
 
 jobs:
   static-checks:
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 3d654358041b..4334f67bca66 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -27,6 +27,17 @@ jobs:
     runs-on: ${{ matrix.build.runs-on }}
     name: ${{ matrix.build.type }} ${{ matrix.build.cxx_compiler }} ${{ matrix.arch }} ${{ matrix.build.os }}
     steps:
+      - name: Verify ccache availability
+        shell: bash
+        run: |
+          if [ ! -d "/mnt/MLPerf/ccache" ]; then
+            echo "::error title=ccache-mlperf-not-mounted::NFS drive is not mounted; build machine not properly provisioned."
+            exit 1
+          fi
+          if [ ! -d "$HOME/.ccache-ci" ]; then
+            echo "::error title=ccache-not-provisioned::Ccache is not properly provisioned."
+            exit 1
+          fi
       - uses: tenstorrent-metal/metal-workflows/.github/actions/checkout-with-submodule-lfs@v2.0.0
       - name: Set up dynamic env vars for build
         run: |
@@ -41,10 +52,39 @@ jobs:
           docker_image_arch: ${{ inputs.arch }}
           docker_opts: |
             -e ARCH_NAME=${{ matrix.arch }}
+            --group-add 1457
+            -v /home/ubuntu/.ccache-ci:/home/ubuntu/.ccache
+            -e CCACHE_DIR=/home/ubuntu/.ccache
+            -v /mnt/MLPerf/ccache:/mnt/MLPerf/ccache
           docker_os_arch: ${{ matrix.build.os }}-amd64
           run_args: |
-            build_command="./build_metal.sh --build-type ${{ matrix.build.type }} --cxx-compiler-path ${{ matrix.build.cxx_compiler }} --c-compiler-path ${{ matrix.build.c_compiler }} --build-tests --build-programming-examples --disable-unity-builds"
+            set -eu # basic shell hygiene
+            set -x
+
+            # /tmp is a tmpfs; more efficient than persisted storage
+            mkdir -p /tmp/ccache
+            export CCACHE_TEMPDIR=/tmp/ccache
+
+            ccache --version
+            ccache --show-config
+
+            ls -al /mnt/MLPerf/ccache
+
+            # Zero out the stats so we can see how we did this build
+            # NOTE: may be inaccurate if we have >1 build runner on the same machine, using the same local cache
+            ccache -z
+
+            build_command="./build_metal.sh --build-type ${{ matrix.build.type }} --cxx-compiler-path ${{ matrix.build.cxx_compiler }} --c-compiler-path ${{ matrix.build.c_compiler }} --build-tests --build-programming-examples --disable-unity-builds --enable-ccache"
             nice -n 19 $build_command
+
+            mkdir out
+            ccache -s > out/ccache.stats
+      - name: Publish Ccache summary
+        run: |
+          echo '## CCache Summary' >> $GITHUB_STEP_SUMMARY
+          echo '```' >> $GITHUB_STEP_SUMMARY
+          cat out/ccache.stats >> $GITHUB_STEP_SUMMARY
+          echo '```' >> $GITHUB_STEP_SUMMARY
       - name: Check disk space
         run: |
           df -h