Cross-platform Git client with AI change audits and commit messages.
Pure Go · GPU Direct Rendering · Zero WebViews
English • 简体中文
When reviewing large pull requests or AI-generated diffs, the biggest bottleneck isn't looking at lines of code—it's understanding why each hunk was changed, what the author intended, and whether there are hidden pitfalls.
Gloss is a cross-platform Git client (macOS, Linux, Windows) crafted for swift code review and safe everyday Git operations:
- Catch risky changes early: One click scans the staged diff and lists suspicious spots—hardcoded secrets, injection risks, and the like—ranked by severity and anchored to file and line.
- Blazing native performance: Powered by mygo, rendered directly via GPU. Zero WebViews, zero JavaScript runtimes, single native binary. Instant startup, silky smooth 60fps scrolling, minimal memory footprint.
- ⚡ GPU Direct Rendering: Pure Go native interface built with
mygo, styled around GitHub's visual palette. - 🛡 Pre-flight Risk Scan: One click scans the staged diff for hardcoded secrets, injection risks, and other suspicious changes, grouped by severity and anchored to file and line.
- 🤖 AI Commit Messages & Branch Names: Generate Conventional Commits messages from the staged diff (optionally steered by an intent hint), and name new branches from a one-line description.
- 🌲 Fork-Style Layout & Topology Graph: Custom commit topology graph to visualize branching histories, with three built-in lane palettes (Classic / Vivid / Grayscale) and per-lane color overrides for dark and light; the review pane shows one file at a time with split / unified layouts, word-level inline highlighting and syntax highlighting.
- 🔍 Viewed Tracking: Mark files as reviewed to collapse them into clean headers; automatically resets when file contents change.
- 🛠 Full Git Workflow:
- Staging & Commits: Whole-file staging, per-hunk staging, persistent drafts, and Amend (
--amend). - Branches & Remotes: Switch/create/rename/delete branches, safe merge and rebase, push tags, and
--force-with-leaseprotected force push. - Stash Management: Modal stash dialog with message and untracked files (
-u); right-click to inspect diff, Apply, Pop, or Drop with confirmation.
- Staging & Commits: Whole-file staging, per-hunk staging, persistent drafts, and Amend (
- 🦺 Human-Friendly Error & Conflict Resolution:
- Plain-language explanations for hook rejections, lock contention, missing credentials, or detached HEAD states.
- Dedicated amber banner during active rebase/merge conflicts with two-way side picking and deletion handling.
- ⌨️ Keyboard-Driven & Command Palette: Press
⌘Kfor the command palette,J/Kto jump across diff hunks, and full macOS native menu shortcuts. - 🤖 Universal LLM Compatibility: Built-in presets for Anthropic Claude, DeepSeek, Kimi, Qwen, GLM, OpenRouter, Ollama, and any OpenAI-compatible API.
- Local Repositories: Open any working copy to inspect uncommitted changes. The sidebar organizes Branches, Remotes, Tags, and Stashes. Click a branch to focus on its commit history; click a stash to view its exact changes.
- Staging & Commits: Stage entire files or individual hunks via dedicated buttons on hunk headers. Work is cleanly divided between "Staged" and "Unstaged" areas. Draft messages are preserved per repository even when switching contexts (
⌘⏎to commit). - File Row Context Menu: Right-click any file row in the Changes, History, or Stash views — stage / unstage (conflict rows get "Use Ours / Use Theirs" plus "Mark Resolved" instead), discard changes… (untracked files say "Delete File…"; both ask first), open in editor, reveal in Finder, copy path / relative path / file name, view file history…, mark as reviewed, and add to
.gitignore. Rows in History and Stash views are read-only, so actions that would touch the working tree simply aren't there. - View File History…: Lists the commits that touched this file (
git log --follow, so it follows renames) and jumps straight to the selected commit in the History tab — no digging through the whole branch history to find which commits it appeared in. - Branch Switching, Checkout & Tags: Double-click branches or tags in the sidebar to check them out. Checking out remote branches automatically sets up local tracking branches. Detached HEAD states trigger warning badges in the toolbar.
- Branch Integration & Remote Management:
- Right-click local branches to merge or rebase onto target branches (with safety confirmations and conflict assistance).
- Deleting a branch is always two separate actions: Delete Branch removes the local branch (with a confirmation, and a second one if it isn't merged), Delete Remote Branch deletes the remote copy and leaves the local branch alone. Local branches that track an upstream offer both, right where you right-clicked.
- Right-click remote branches to checkout or safely delete them with confirmation.
- Push tags to
originwith a single click. - Protected force pushing via
--force-with-leaseprevents overwriting teammates' work.
- Stash Management & Amend:
- Save dirty working tree states with custom messages and untracked files (
-u). - Inspect stash diffs directly; apply, pop, or drop stashes with confirmation dialogs.
- Amend commits with pre-filled previous commit messages, supporting message-only adjustments or staged additions.
- Save dirty working tree states with custom messages and untracked files (
- Fetch, Pull & Push: Dedicated toolbar actions with intelligent disable states for detached HEAD or repos without remotes. Provides plain-language translations for push rejections, divergences, and authentication requirements.
- One File at a Time Diff View: The left pane navigates, the right pane renders the selected file with MyGo's diff viewer — red/green highlighting, dual-side line numbers, word-level inline changes, collapsible unchanged regions, and syntax highlighting. The unstaged side is editable (saving writes the working tree only, never the index).
- Built-in Editor Lists the Whole Workspace: The editor view's file pane lists every file in the working tree (
git ls-files), not just the ones you changed — files you did change keep their status letter, staging box and change markers, unchanged files open with a clean gutter. The tree opens fully collapsed, and changed files are tinted by their status the way VS Code does it (directories take the most urgent colour underneath) — so "has colour" is itself the signal. That pane has its own filter box and selection, so moving between views never carries one pane's filter into the other; its footer tells you how many files are dirty. - Pre-flight Risk Scan: The 🛡 Audit Changes button hands the full staged diff to your model and lists suspicious spots (hardcoded secrets, injection risks, …) grouped by severity—critical / high / medium / low—each anchored to a file and line. Provider failures are translated into plain language instead of raw HTTP errors.
- AI Commit Messages & Branch Names: The AI button in the commit box drafts a Conventional Commits message from the staged diff, treating your notes in the message box as an intent hint; a zh/EN toggle picks the language. The new-branch dialog can generate a branch name from a one-line description.
- Fork-Style Commit Graph: Top pane displays commits alongside a calculated topology graph; bottom pane displays the file tree on the left and the selected file's diff on the right.
- File Tree & Viewed Marks: Collapsible directory tree with single-child path flattening and fuzzy search (
⌘P). Marking a file asRevieweddims it in the file list and invalidates on content changes. - Find in Diff (
⌘F): The find bar belongs to the diff viewer —⌘Fwhile the diff has focus,⌘F/⇧⌘Gto walk matches. Finding content and finding files are separate:⌘Ffor content,⌘Pfor files. - Stage by Hunk: Hovering a change (or parking the caret on it) reveals
Stage/Unstagefor exactly that change — the blocks are the viewer's own, so one click stages that block only and leaves the other changes in the file alone. - Conflict Resolution Inline: Selecting a conflicted file shows the worktree text with its markers (the left side switches between current / theirs / merge base). Every conflict block has its own "keep X / keep Y / keep both / keep neither", the top bar resolves the whole file either way, and the right side is editable: "Save & Resolve" writes the file and runs
git addin one step. - Command Palette (
⌘K): Quick access to all application actions with keyboard-first workflows.
| Shortcut | Action |
|---|---|
⌘K |
Open Command Palette |
J / K |
Jump to Next / Previous hunk (Changes) or commit (History) |
↓ / ↑ |
Select Next / Previous commit (History) or file (Changes) |
⌘F |
Find in the diff (opens the viewer's own find bar when it has focus) |
↵ / ⇧↵ |
Next / previous match (in the find box) |
⌘G / ⌘⇧G |
Next / previous match |
Esc |
Close the find bar |
⌘P |
Focus file filter input |
⌘S |
Save the edited side of the diff / editor (a conflict also runs git add) |
⌘⏎ |
Commit staged changes |
⌘O |
Open repository |
⌘1 / ⌘2 |
Switch between Changes / History |
⌘⇧B |
Toggle Sidebar |
⌘R |
Refresh repository status |
⌘⇧F / ⌘⇧P / ⌘⇧U |
Fetch / Pull / Push |
⌘+ / ⌘− / ⌘0 |
Zoom in / Zoom out / Reset font size |
⌘, |
Settings (Preferences / Models / Prompts / Git config …) |
Esc |
Exit branch compare / PR review |
The table uses macOS notation. On Linux and Windows, ⌘ means Ctrl — the same key does the same thing, and the app displays Ctrl+… there (see keys_i18n.go). ⌥ becomes Alt, ⌫ becomes Backspace, ⏎ becomes Enter.
Menu items (
menu.go) share identical shortcut mappings withkeys.goto keep the native menu and the in-app shortcuts in sync.
Requires Go 1.27+ (enforced by mygo, pre-configured in mise.toml).
# 1. Install toolchain via mise
mise install # Installs Go 1.27.1
# 2. Local development with live reload
go tool mygo dev # Hot reload on code changes
# 3. Production release
go tool mygo build # Builds .app and .dmg into build/darwin-arm64/
# 4. Automated tests
go test ./... # Headless rendering tests, no display requiredMicrosoft Defender's ML heuristics — usually as Trojan:Script/Wacatac.C!ml — report Gloss.Setup.<version>.amd64.exe. It is a false positive: nothing here is packed, obfuscated, or downloaded at install time. An unsigned installer with a brand-new hash every release is simply the profile those heuristics score worst.
Two ways through while it is flagged:
- Install nothing. Download
gloss-<version>-windows-amd64-portable.zip, extract it, runGloss.exe. It is the same build as the archive the installer puts down (sameGloss.exeandghostty-vt.dll), needs no admin rights and writes nothing outside its own folder. - Allow it. Defender → Protection history → the detection → Actions → Allow on device, or add your download folder to the exclusions.
Report it. Detections are per file hash, so a fresh release starts flagged again — report the file once per release (takes a few hours): https://www.microsoft.com/en-us/wdsi/filesubmission → Software developer → upload the flagged Gloss.Setup.<version>.amd64.exe → Incorrectly detected as malware. Microsoft clears that hash and feeds the result back into the model.
The durable fix is code signing: a signed build carries a publisher, so the same bytes stop being scored as an anonymous binary.
Open Settings (⌘,) from the top right menu to configure your API provider and key. The configuration is securely stored at ~/Library/Application Support/Gloss/config.json (permissions 0600).
The provider column lists only the providers you've added; drag the handle at the start of a row to reorder them (the order is part of the draft — it lands on Save, and Cancel throws it away). New ones come from the Add Provider button's menu, which also shows built-in presets for Anthropic Claude, DeepSeek, Kimi, Qwen, GLM, OpenRouter and Ollama, plus custom OpenAI-compatible endpoints; providers already in the list are greyed out there.
Alternatively, Gloss falls back to standard environment variables:
export ANTHROPIC_API_KEY=sk-ant-...
# Optional: export ANTHROPIC_MODEL=claude-sonnet-5-5
# Optional: export ANTHROPIC_BASE_URL=https://...Settings → Git Config shows all three layers of git's own configuration in one page: global (~/.gitconfig, every repository on this machine), local (.git/config, this repository only), and system (/etc/gitconfig and vendor files, shown read-only).
The page covers one question — who git says you are when you commit — so it lists exactly user.name and user.email. Structural settings (branch.*, remote.*, core.*) are deliberately absent: they have proper homes in the branch and remote panes, and turning them into editable rows is how a repository gets broken by a typo. At the local layer you pick whether this repository inherits the global identity or sets its own; inheriting means the local keys are dropped on save so the global ones apply. Clearing a field means "this layer no longer sets it" (the key is removed rather than written as an empty value), and the placeholder shows the value that would apply instead.
Only the rows you changed are written. Comments, include ordering, and anything Gloss does not understand are left exactly as they are — no full rewrite. Reads and writes both go through the git CLI, so includeIf conditions and subsections behave here exactly as they do on the command line.
Needs git ≥ 2.26 (reading uses --show-scope). On older git the page shows git's own message instead of silently degrading — a half-read config is worse than a clear "your git is too old".
main.go / app.go Window, menus, app state, root frame layout
sidebar.go Sidebar: branches / remotes / tags / stashes tree
branchops.go Branch & remote operations: merge, rebase, delete, force push
renamebranchdialog.go Branch rename dialog with name validation
stashdialog.go Stash modal dialog (save dirty state with optional message)
stashops.go Stash actions: apply, pop, drop with confirmation
history.go Top pane: commit table and column headers
commitops.go Commit row actions: cherry-pick, revert, checkout, copy hash
resetdialog.go Branch reset dialog (soft / mixed / hard with warning)
newbranchdialog.go Create branch from selected commit
graph.go Topology graph: layout computation & line drawing
filepane.go Bottom pane left: file list & staging controls
workspace.go Editor view's file pane: the whole working tree, not just the changes
filemenu.go File row context menu: stage / discard / copy / history / ignore
filehist.go "View File History…" dialog: this file's own commits, jump to one
review.go Review pane: single-file diff viewer (both sides, hunk staging, conflict side picking)
conflict_region.go Parsing and rewriting conflict markers in the worktree text
files.go File list identity (fileKey / pathOf / displayPath)
commitbox.go Staging checkboxes, hunk staging buttons, commit box
checkout.go Checkout handlers, double-click, cleanup
tagdialog.go Tag creation dialog (lightweight & annotated)
remote.go Toolbar remote actions: fetch, pull, push
opbanner.go Operation feedback banners (error bar / success toast)
pendingbar.go Amber conflict status bar: continue / skip / abort
confirmdialog.go Destructive action confirmation dialogs
resolve.go Conflict resolution: two-way side picking & cards (menu lives in filemenu.go)
treeview.go Shared tree rows (indentation, arrows, selection capsules)
refs.go Git reference grouping & filtering
palette.go / keys.go Command palette & shortcut bindings
menu.go macOS native menu bar commands
settings.go Settings dialog (sidebar + Preferences / Models / Prompts / Updates / About)
gitconfig.go Settings → Git Config page: read, edit and save all three layers (writes live in internal/gitrepo/config.go)
theme.go GitHub-aligned theme palette (light / dark)
internal/
gitrepo/ Git CLI wrapper (status / diff / log / refs / write ops)
write.go Staging, hunk staging, commit, amend
stash.go Stash operations (push / apply / pop / drop)
commitops.go Cherry-pick, revert, reset (--soft / --mixed / --hard)
branch.go Create, rename, delete branch, merge, rebase
remote.go Fetch, pull, push (with --force-with-lease, tags, delete)
pending.go In-progress operation detection + continue / skip / abort
conflict.go Conflict side resolution (ours / theirs, delete-modify)
failure.go Plain-language git error translator
config.go git config read/write: all three layers in one call, writes scoped to --global/--local
diff/ Unified diff parser
slice.go Slice hunk patches for hunk-level staging
range.go Build a patch for a line range (context only where both sides agree)
explain/ Prompt construction for commit messages, branch names, PR review, and risk scans (pure functions)
llm/ Streaming client for Anthropic & OpenAI-compatible APIs
failure.go Plain-language provider error translator
store/ Config and state persistence
filetree/ Tree building, flattening, and fuzzy filtering
Threading Invariant (see top of
app.go): All app field mutations occur strictly on the main thread. Background goroutines receive value parameters and dispatch results back to the main thread.
- Staging + Commits (file-level + hunk-level)
- Branching / Checkout / Tags (double-click + context menu)
- Remotes: Fetch / Pull / Push
- Conflict management: Amber status bar + Continue / Skip / Abort
- Conflict side picking: Use ours / Use theirs / Mark resolved
- Commit context menu: Cherry-pick / Revert / Reset / Branch from here
- Local branch operations: New branch (
⌘⇧N), rename, safe deletion - Remote branch & integration: Delete remote branch, merge/rebase, force-with-lease push
- Draggable sidebar resizing
- Keyboard navigation for the file list:
J/Kand↑/↓move the selected commit on the history tab; on the changes tab↑/↓move the selection in the changed-files list whileJ/Kjump between hunks - AI commit message & branch generation
- GitHub PR: list open PRs and review PR diffs
- Pre-flight risk scan: Full-diff scan highlighting potential vulnerabilities
- File row context menu: stage / discard (delete for untracked) / reveal in Finder / copy path three ways / view file history / mark reviewed / add to
.gitignore - Drag-to-reorder providers, with presets moved into the Add Provider menu
- Native text selection in the diff: the review pane is a real editor, so drag-select,
⌘Cand undo are its own behavior
MIT — see LICENSE.