mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-25 11:10:18 +00:00
93 lines
4.4 KiB
Markdown
93 lines
4.4 KiB
Markdown
# 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.
|