# Workspace Git controls Workspace Git controls let the browser inspect Git state for the active session workspace. By default, WebUI can read status, list branches, show diffs, fetch remote refs, and generate commit-message suggestions. Actions that modify the repository, index, or worktree are disabled unless the WebUI process is started with `HERMES_WEBUI_WORKSPACE_GIT_DESTRUCTIVE=1`. > **Trust model - read this first.** Once mutating Git actions are enabled, a browser action can run > Git commands inside a mounted workspace. Some Git commands can also run repository hook code from > `.git/hooks/` or a configured `core.hooksPath`. That hook code runs as the WebUI process user, with > the WebUI process permissions and environment. Treat hooks that download or execute code as code > execution by the WebUI process user. ## What works by default Without `HERMES_WEBUI_WORKSPACE_GIT_DESTRUCTIVE=1`, WebUI can: - show repository status - list branches - show file diffs - fetch from the configured remote - generate commit-message suggestions Fetch may update remote-tracking refs, but it does not change the worktree, merge branches, create commits, or push changes. Commit-message generation may send staged or selected diff context to the configured model provider. The UI labels this before generation. Diffs for untracked files are size checked before WebUI reads file contents. Large or binary files return metadata instead of inline diff text. ## What requires explicit enablement These actions are blocked unless `HERMES_WEBUI_WORKSPACE_GIT_DESTRUCTIVE=1` is set: - stage and unstage - discard changes - commit and selected-file commit - pull and push - checkout - branch switching that parks and restores local changes Leave the flag unset for deployments where WebUI should only inspect mounted workspaces. Set it only when browser users are trusted to modify those repositories from WebUI. When the flag is enabled, branch switching parks and restores local changes automatically. If the branch being left has local changes, WebUI parks those changes in a WebUI-owned Git stash, switches branches, and then restores any WebUI-owned stash for the branch being entered. If Git cannot restore the stash cleanly, WebUI leaves the stash in place and reports the restore failure instead of dropping it. ## Workspace and path scope The browser does not send an arbitrary repository path. Git requests carry a session id and, when needed, workspace-relative file paths. The server resolves the session workspace, checks each path against that workspace, and then builds Git pathspecs from the checked paths. Git commands run through `subprocess.run` with `shell=False`. Local status and diff commands use a 5 second timeout. Remote operations such as fetch, pull, and push use a 60 second timeout. Before any Git subprocess starts, WebUI removes inherited `GIT_DIR`, `GIT_WORK_TREE`, `GIT_CONFIG_GLOBAL`, `GIT_CONFIG_SYSTEM`, `GIT_CONFIG_COUNT`, `GIT_CONFIG_PARAMETERS`, and injected `GIT_CONFIG_KEY_*` / `GIT_CONFIG_VALUE_*` values from the environment. Those variables can redirect Git to a different repository or inject config, so WebUI does not trust them from the parent process. `GIT_INDEX_FILE` is the intentional exception. Selected-file commits use a temporary index so WebUI can commit only the requested files, then remove the temporary index afterward. ## Coordination with active runs Mutating Git actions are rejected while the same session has a live stream. The API returns `active_stream` instead of racing a running agent that may be writing files in the same workspace. Mutating Git actions also take a per-repository lock. If another Git mutation is already running for that repository, the API returns `operation_in_progress`. ## Hook and remote behavior WebUI does not bypass Git hooks. Hook code may come from `.git/hooks/` or from a configured `core.hooksPath`. Commit actions run normal commit hooks such as `pre-commit`, `commit-msg`, and `post-commit`. Push can run `pre-push`. Pull uses `--ff-only`, so it does not create a merge commit, but it is still a Git operation running under the WebUI process. Push keeps Git's normal non-fast-forward protection and reports non-fast-forward rejection separately from general Git failures. If a hook fails, the API returns a structured Git error instead of hiding the failure. Other classified failures include authentication errors, missing upstream branches, conflicts, dirty worktrees, invalid refs, missing Git binaries, and timeouts.