diff --git a/glfw/glow-extras/glfw/GlfwApp.cc b/glfw/glow-extras/glfw/GlfwApp.cc
index fb600f2ffef55f857332004fe5d7ccbaf345a0f1..d4f8123833028022d209fb937a6ac0876efe0e9a 100644
--- a/glfw/glow-extras/glfw/GlfwApp.cc
+++ b/glfw/glow-extras/glfw/GlfwApp.cc
@@ -244,7 +244,7 @@ void GlfwApp::init()
         if (mCacheWindowSize)
         {
             // Restore window size
-            std::ifstream file("glfwapp.ini");
+            std::ifstream file(mCacheWindowSizeFilename);
             if (file.good())
             {
                 int w, h, x, y;
@@ -755,7 +755,7 @@ void GlfwApp::internalCleanUp()
     if (mCacheWindowSize)
     {
         // Save window size to disk
-        std::ofstream file("glfwapp.ini");
+        std::ofstream file(mCacheWindowSizeFilename);
         if (file.good())
         {
             if (mInternalContext->isFullscreen())
diff --git a/glfw/glow-extras/glfw/GlfwApp.hh b/glfw/glow-extras/glfw/GlfwApp.hh
index b490db6adc94cc01334bf5a70253dd8a80781861..d9ec6b75e5e6863a3b9d52484841da850107009f 100644
--- a/glfw/glow-extras/glfw/GlfwApp.hh
+++ b/glfw/glow-extras/glfw/GlfwApp.hh
@@ -130,6 +130,8 @@ private:
     bool mUsePipelineConfigGui = false; ///< if true, enables the pipeline scen configuration gui (only if pipeline is used, requires ImGui)
 
     bool mCacheWindowSize = false; ///< if true, saves window size and position on close, and restores on next launch
+    std::string mCacheWindowSizeFilename = "glfwapp.ini";       /// Default -> cwd
+    std::string mCacheWindowSizeFilenameImGui = "imgui.ini";    /// Default -> cwd
 
     double mCurrentTime = 0.0;            ///< current frame time (starts with 0)
     double mCurrentRenderDeltaTime = 0.0; ///< current delta time for the render(dt) call
@@ -226,6 +228,8 @@ public:
     GLOW_PROPERTY(UseDefaultCameraHandlingRight);
 
     GLOW_PROPERTY(CacheWindowSize);
+    GLOW_PROPERTY(CacheWindowSizeFilename);
+    GLOW_PROPERTY(CacheWindowSizeFilenameImGui);
 
     void setTitle(std::string const& title);
 
diff --git a/viewer/glow-extras/viewer/ViewerApp.cc b/viewer/glow-extras/viewer/ViewerApp.cc
index 4593c5082669d6601ff580915895ee888a219daf..1d804954166d275e828c0dc216291fcb3d00a0f8 100644
--- a/viewer/glow-extras/viewer/ViewerApp.cc
+++ b/viewer/glow-extras/viewer/ViewerApp.cc
@@ -178,10 +178,35 @@ void ViewerApp::init()
     if (mSettings.headlessScreenshot)
         setStartInvisible(true);
 
+    // set where to read and write the window position
+    // (empty location -> don't read or write)
+    if (mSettings.cacheWindowSizeFolder.empty())
+    {
+        setCacheWindowSize(false);
+    }
+    else
+    {
+        setCacheWindowSize(true);
+        setCacheWindowSizeFilename(mSettings.cacheWindowSizeFolder + "glfwapp.ini");
+        setCacheWindowSizeFilenameImGui(mSettings.cacheWindowSizeFolder + "imgui.ini");
+    }
+
     sLastCloseInfo.closed_by_key = -1;
 
     GlfwApp::init();
 
+    // set where to read and write the window position; part 2
+    // (ImGui Context has to be initialized already)
+    if (getGui() == Gui::ImGui)
+    {
+        if (!getCacheWindowSize())
+            ImGui::GetIO().IniFilename = nullptr;
+        else
+        {
+            ImGui::GetIO().IniFilename = getCacheWindowSizeFilenameImGui().c_str();
+        }
+    }
+
     // create camera (before initial layout)
     // (or take preserved camera)
     bool newCamera;
diff --git a/viewer/glow-extras/viewer/configure.cc b/viewer/glow-extras/viewer/configure.cc
index b8ff0c10b257cac6741c887117ca4de01620e60e..856c72be61adbc68cff3de4c6cdff82e2049c389 100644
--- a/viewer/glow-extras/viewer/configure.cc
+++ b/viewer/glow-extras/viewer/configure.cc
@@ -258,6 +258,8 @@ void configure(GeometricRenderable& r, Picker p)
     r.setPicker(std::move(p));
 }
 
-void configure(Renderable&, const file_drop_handler& h) { detail::set_file_drop_handler(h.callback); }
+void configure(Renderable&, file_drop_handler const& h) { detail::set_file_drop_handler(h.callback); }
 
-}
+void configure(Renderable&, cache_window_size const& s) { detail::set_cache_window_size_folder(s.folder); }
+
+} // namespace glow::viewer
diff --git a/viewer/glow-extras/viewer/configure.hh b/viewer/glow-extras/viewer/configure.hh
index 06fd71b2187a71d4ec10bde30402b1763ccee89e..e52660de8b0c8c49aef4a1bf39f29b36f5f2eade 100644
--- a/viewer/glow-extras/viewer/configure.hh
+++ b/viewer/glow-extras/viewer/configure.hh
@@ -156,6 +156,16 @@ struct file_drop_handler
     explicit file_drop_handler(std::function<void(std::vector<std::string> const&)> f) : callback(f) {}
 };
 
+struct cache_window_size
+{
+    std::string_view folder;
+
+    constexpr explicit cache_window_size(std::string_view folder)
+        : folder(folder)
+    {
+    }
+};
+
 // Config tags
 inline auto constexpr no_grid = no_grid_t{};
 inline auto constexpr no_left_mouse_control = no_left_mouse_control_t{};
@@ -180,6 +190,7 @@ inline auto constexpr tonemap_exposure = tonemap_exposure_t{};
 inline auto constexpr backface_culling = backface_culling_t{};
 inline auto constexpr preserve_camera = preserve_camera_t{};
 inline auto constexpr reuse_camera = reuse_camera_t{};
+inline auto constexpr no_cache_window_size = cache_window_size("");
 
 // passthrough configures for scene modification commands
 void configure(Renderable&, no_grid_t b);
@@ -217,6 +228,7 @@ void configure(Renderable&, close_keys const& k);
 void configure(Renderable&, preserve_camera_t b);
 void configure(Renderable&, reuse_camera_t b);
 void configure(Renderable&, file_drop_handler const& h);
+void configure(Renderable&, cache_window_size const& h);
 
 /// custom scene configuration
 void configure(Renderable&, std::function<void(SceneConfig&)> f);
diff --git a/viewer/glow-extras/viewer/detail/command_queue.cc b/viewer/glow-extras/viewer/detail/command_queue.cc
index db9333da9bc0d5604f787694051dc23e79652089..7391eb3c9aff3864f412332801e295ee337403a7 100644
--- a/viewer/glow-extras/viewer/detail/command_queue.cc
+++ b/viewer/glow-extras/viewer/detail/command_queue.cc
@@ -1,5 +1,6 @@
 #include "command_queue.hh"
 
+#include <filesystem>
 #include <variant>
 
 #include <glow-extras/viewer/ViewerApp.hh>
@@ -97,7 +98,7 @@ void glow::viewer::detail::on_last_command()
     }
 }
 
-bool glow::viewer::detail::is_interactive(const glow::viewer::detail::command_queue& commands)
+bool glow::viewer::detail::is_interactive(glow::viewer::detail::command_queue const& commands)
 {
     for (auto const& cmd : commands)
         if (cmd.instr == detail::command::instruction::InteractiveSubview)
@@ -106,7 +107,7 @@ bool glow::viewer::detail::is_interactive(const glow::viewer::detail::command_qu
     return false;
 }
 
-void glow::viewer::detail::create_layout_tree(glow::viewer::layout::tree_node& rootNode, const glow::viewer::detail::command_queue& commands, float deltaTime, bool allowInteractiveExecute)
+void glow::viewer::detail::create_layout_tree(glow::viewer::layout::tree_node& rootNode, glow::viewer::detail::command_queue const& commands, float deltaTime, bool allowInteractiveExecute)
 {
     using cmd_t = detail::command;
 
@@ -116,7 +117,7 @@ void glow::viewer::detail::create_layout_tree(glow::viewer::layout::tree_node& r
         if (cmd.instr == cmd_t::instruction::AddRenderjob)
         {
             TG_ASSERT(currentNode != nullptr);
-            const auto renderable = cmd.data_renderable;
+            auto const renderable = cmd.data_renderable;
             TG_ASSERT(renderable);
             renderable->runLazyInit();
             currentNode->scene.add(renderable);
@@ -124,7 +125,7 @@ void glow::viewer::detail::create_layout_tree(glow::viewer::layout::tree_node& r
         else if (cmd.instr == cmd_t::instruction::ModifyScene)
         {
             TG_ASSERT(currentNode != nullptr);
-            const auto funcp = cmd.data_scene;
+            auto const funcp = cmd.data_scene;
             TG_ASSERT(funcp);
             funcp(currentNode->scene);
         }
@@ -159,7 +160,7 @@ void glow::viewer::detail::create_layout_tree(glow::viewer::layout::tree_node& r
         else if (cmd.instr == cmd_t::instruction::ModifyLayout)
         {
             TG_ASSERT(currentNode != nullptr);
-            const auto layoutSettings = cmd.data_settings;
+            auto const layoutSettings = cmd.data_settings;
             currentNode->layoutSettings = layoutSettings;
         }
         else if (TG_LIKELY(cmd.instr == cmd_t::instruction::InteractiveSubview && allowInteractiveExecute))
@@ -173,7 +174,7 @@ void glow::viewer::detail::create_layout_tree(glow::viewer::layout::tree_node& r
             // Run the interactive lambda to fill innerCommandQueue
             {
                 sCommandQueueStack.push_back(innerCommandQueue);
-                const auto funcp = cmd.data_interactive;
+                auto const funcp = cmd.data_interactive;
                 TG_ASSERT(funcp);
                 funcp(deltaTime);
                 sCommandQueueStack.pop_back();
@@ -266,7 +267,6 @@ void glow::viewer::detail::reset_camera_to_scene(bool clip_cam)
         sCurrentViewerApp->resetCameraToSceneNextFrame(clip_cam);
 }
 
-
 bool glow::viewer::detail::is_fullscreen()
 {
     if (nullptr == sCurrentViewerApp)
@@ -288,7 +288,23 @@ void glow::viewer::detail::toggle_fullscreen()
         return sCurrentViewerApp->toggleFullscreen();
 }
 
-void glow::viewer::detail::set_file_drop_handler(std::function<void(const std::vector<std::string>&)> callback)
+void glow::viewer::detail::set_file_drop_handler(std::function<void(std::vector<std::string> const&)> callback)
 {
     sGlobalSettings.onDropFiles = std::move(callback);
 }
+
+void glow::viewer::detail::set_cache_window_size_folder(std::string_view s)
+{
+    auto& folder = sGlobalSettings.cacheWindowSizeFolder;
+    folder = s;
+    if (folder.empty())
+        return;
+
+    if (folder.back() != '/')
+        folder.append("/");
+    if (!std::filesystem::exists(folder))
+    {
+        glow::warning() << "Target folder for window size caching does not exist! Defaulting to working directory.";
+        folder = "./";
+    }
+}
diff --git a/viewer/glow-extras/viewer/detail/command_queue.hh b/viewer/glow-extras/viewer/detail/command_queue.hh
index 38cb4be3c11ce24717ea02417b9fc207c3853175..196ec9e69c31f9f72f77837e0d5a83a319324178 100644
--- a/viewer/glow-extras/viewer/detail/command_queue.hh
+++ b/viewer/glow-extras/viewer/detail/command_queue.hh
@@ -31,6 +31,7 @@ struct global_settings
     bool rightMouseControlEnabled = true;
     bool enableViewerUI = true;
 
+    std::string cacheWindowSizeFolder = "./";
     bool has3D = false; ///< True iff we have 3D content (this is set automatically)
 
     bool use_2d_controls() const { return controls2d_enabled || !has3D; }
@@ -274,6 +275,7 @@ void set_subview_margin(int margin);
 void set_subview_margin_color(tg::color3 color);
 void set_headless_screenshot(tg::ivec2 resolution, int accum, std::string const& filename, GLenum format);
 void set_file_drop_handler(std::function<void(std::vector<std::string> const&)> callback);
+void set_cache_window_size_folder(std::string_view s);
 
 // Returns true if the given command list contains one or more interactive instructions (and whose tree therefore must be rebuilt each frame)
 bool is_interactive(command_queue const& commands);