DeepSeek Harness Plugin

xbzbing/dsh-git-panel

Stars ★ 5 Downloads (30d) 2,727 Category Git & Code Review Added 2026-09-25 npm @xbzbing/dsh-git-panel

IDE-style Git panel in the DSH Web GUI: a resident tab with a three-column overview (branch/tag list, searchable commit-history graph, commit detail with changed-file tree and message) and a changes page (stats bar, uncommitted list with per-file stage/unstage/discard, commit box with amend); side-by-side diffs carry lazy highlight.js syntax highlighting, on-demand between-hunk context expansion and word-level intra-line emphasis, with image files shown as before/after panes; plus a zsh-style branch marker in the input bar. Every git command runs as an argv array through the host subprocess service, cwd locked to the repo root.

Install

# from npm (prebuilt)

dsh plugin --profile web add @xbzbing/dsh-git-panel

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:xbzbing/dsh-git-panel

Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).

README

English | 简体中文

dsh-git-panel

dsh-git-panel is a DSH Web GUI plugin that brings an IDE-style Git panel into the conversation workspace. It gathers the branch list, commit history graph, uncommitted-change commit & amend, and syntax-highlighted diffs into one resident tab, and puts a zsh-style branch marker at the left of the input bar — so you can check repo status and commit changes mid-conversation without switching to a terminal or a separate IDE.

The panel only reads the Git repository at the current session's working directory. Every git command runs through the host subprocess service as an argv array — no shell string concatenation — with the working directory locked to the repository root and per-command timeout and output caps. The plugin never touches your git config, and every write (commit, amend, stage, discard) has an explicit entry point.

Install

# npm (default)
dsh plugin --profile web add @xbzbing/dsh-git-panel@latest

# or from the GitHub repository (the built tree is committed, no local build needed)
dsh plugin --profile web add github:xbzbing/dsh-git-panel

After installing or updating, restart the dsh web service and refresh the page; the Git panel then appears in the workspace tab bar (after Chat and Trajectory). The plugin has a host half and a client half, and both the host mount and the client bundle manifest are fixed when the service starts, so code updates (installing, or an add that overwrites lib) usually need a service restart — a page refresh alone may not pick them up. In-panel settings (the input-bar marker toggle and the default diff view on the detail page) are hot-written and apply immediately without a restart.

Compatibility: verified on dsh@0.2.1-alpha.1 — installation, the Git panel, the input-bar marker, and the host RPC all work normally.

Features

  • Overview — three columns. The left column is the branch / tag list; clicking a ref filters history by it. The middle column is the commit history graph, searchable by commit message, commit hash, author, or date; hovering a commit shows a card with its full commit message (comment). The right column is the selected commit's changed-file tree and commit message; click a file to see its diff within that commit in a modal.
  • Changes — the local working tree. The left column has a statistics bar (file count / added·deleted lines / last-change time), the uncommitted change list with per-file checkboxes, and a commit box with an Amend checkbox; per-file stage / unstage / discard and manual commit are supported. The right column is the selected file's diff.
  • AI commit-message suggestion — the "AI suggest" button beside the commit box writes a commit message from the current uncommitted changes (restricted to your checked files when any are selected) in the style of the latest commit, using the model you have configured in DSH; the result lands in the commit box for you to edit before committing. No changes to summarize, a missing model service, and generation failures all report a clear message. Privacy note: the generation request sends your diff content to the provider of the model you configured in DSH. The button can be turned off on the plugin detail page.
  • Tag management — the commit-detail header in the Overview right column creates a tag at the selected commit (lightweight, or annotated with a message); tags already on that commit show as deletable chips, and deletion asks for confirmation.
  • Stash — the Changes page stashes the current uncommitted changes (with an optional message); the stash list below supports apply / pop / drop. A pop or apply that conflicts keeps the stash entry and reports it, so nothing is lost halfway. Drop asks for confirmation.
  • Commit undo — the same commit-action area can "Revert this commit" (appends a reverse commit, leaving the work tree untouched) or "Reset to here" (reset in soft / mixed / hard modes). Hard reset lists the uncommitted changes it will permanently discard and requires an extra acknowledgement; it is never the default, and whenever uncommitted changes are present a note warns they may be work the dsh AI is doing.
  • Shared-worktree guards — tag / stash / revert / reset and other write actions share the repository with the dsh AI, so every dialog footer suggests letting the AI run Git for you; a .git/index.lock clash (another process is working) retries once and surfaces a friendly "Git is busy" message instead of the raw error.
  • File browser — opening the workspace Git tab selects Files outside a Git repository, Overview in a clean repository, or Changes when there are uncommitted changes. Non-Git directories use the current directory as the browse root. The resizable tree loads one directory at a time and hides .git, shows dsh's official type icons per file, and dims entries excluded by .gitignore; the preview shows code/text or images, with a button to copy the file's relative path and placeholders for oversized or binary files. Markdown defaults to source; choose Rendered to use dsh's built-in Markdown view. HTML also defaults to source; choose Rendered to preview the page inside a locked-down sandbox (allow-scripts, no same-origin) — it never auto-runs. The source view is row-virtualized for large files (only the visible rows render); very large files disable highlighting and over-long lines are truncated, keeping it responsive.
  • In-code find — the file source preview and the diff views support Ctrl/⌘+F to find in place: every match is highlighted preserving syntax colors, with an active/total count, Enter / Shift+Enter or ‹ › to walk matches, a case-sensitivity toggle (insensitive by default), and Esc to close. Match counting scans the whole content, so matches outside the viewport are counted and reachable too.
  • Syntax-highlighted diffs — the overview modal, changes page, and file browser share dsh's built-in highlighter. Languages are selected by file extension and grammars load on demand; word-level change emphasis remains available in the diff views.
  • Diff modes — unified / split / before / after views. Unified is a single inline column (each change shown as adjacent -/+ lines, saving horizontal space); split is side-by-side. Both carry on-demand expansion of hidden between-hunk context and word-level emphasis on changed lines. The default view is selectable on the plugin detail page (unified / split) and can be switched per diff from the toolbar.
  • Mobile / narrow-panel layout — at 620px wide or below (a phone in portrait, or a sidebar squeezing the panel) the UI switches to a single-column drill-in: the three columns collapse to one, and you tap from a list into its detail / diff / preview and come back with a Back button. The Overview branch filter becomes a bottom sheet, commit rows go two-line for easier tapping, the tab-bar controls wrap onto a second row instead of hiding, and the side-by-side diff mode is dropped on narrow screens. Widening the panel restores the three-column layout, so the desktop experience is unchanged. On touch devices (e.g. tablets) the per-file row actions stay visible and hit targets grow.
  • Show input-bar marker toggle — the plugin detail page can toggle the input-bar marker; when off, the input bar stays clean and the Git tab shows a status dot instead (green = synced, orange = dirty). The two are mutually exclusive and changes apply immediately. The same config section also sets the default diff view (unified / split) and whether the commit box shows the "AI suggest" button.
  • Input-bar Git marker — a zsh-theme <repo> (<branch>) marker: the repo name is cyan, (branch) is green when in sync and orange when there are uncommitted changes; hover shows the full repository path, and clicking jumps to the panel (to Changes when dirty, otherwise to Overview); in non-Git directories the input-bar marker is hidden, while the workspace Git tab still opens the file browser.
  • The UI follows the DSH system language, in Simplified Chinese and English.

Screenshots

Overview File-diff modal
Overview: branches, commit graph, commit detail, hover card File-diff modal: syntax-highlighted unified / split diff with on-demand gap expansion and word-level emphasis
Changes File browser
Changes: stats bar, uncommitted list, commit box, diff File browser: lazy directory tree, official type icons, dimmed ignored entries, and file preview

Architecture

Two halves communicating over the typert Remote gateway.

  • Host (lib/host/) — a Cordis + typert GitPanelService on the gitPanel namespace, exposing snapshot / run / query / suggest / version and doing only endpoint delegation and lifecycle wiring; git runs through the host subprocess service (argv arrays, no shell, cwd locked to the repository root, timeout + output caps); the suggest endpoint makes a one-shot commit-message call through the host llm service with your configured model.
  • Client (lib/client.js) — a React bundle that registers the conversation.view panel and the conversation.input.left marker. One snapshot controller per session (polling + a refresh after each turn + a reload on connection reset) feeds the marker, the changes page, and the stats bar from a single snapshot, avoiding duplicate git commands.

Development

node build.mjs      # tsc (host d.ts) + esbuild (host bundle + client bundle + testkit)
npm run typecheck   # type check
npm run test:unit   # pure-algorithm and host-endpoint unit tests (node --test)
npm run test:e2e    # isolated file:// headless-browser e2e (never touches a running instance)
npm test            # unit + e2e

The host bundle is not minified: the typert gateway validates arguments by method parameter name, and minification would rename them and break the wire contract. Client changes are not hot-reloaded — rebuild and refresh the page. lib/ is committed as a build artifact so dsh plugin add github:… installs the built tree directly; after editing src/ you must rebuild and commit, or a GitHub install loads a stale entry. The test-time lib/testkit.mjs is not committed. For local development, add the plugin to a dsh web profile's dsh.profile.bundles with a file: dependency pointing at this directory; a rebuild makes it effective.

Project structure

src/
  host/
    types.ts        the single source of truth for the wire data model (reused by the client)
    index.ts        GitPanelService: endpoint delegation + lifecycle wiring
    git.ts          subprocess → a GitRunner with timeouts
    core.ts         workspace resolution + snapshotForSession
    actions.ts      GitAction → git command sequences (commit / amend / stage …)
    queries.ts      history / diff / file-lines / image-diff / dir-list / file-content / show / branches / tags / worktree-stats
    suggest.ts      AI commit-message suggestion (diff collection + one ctx.llm call)
    parser.ts       git output parsed into structured data
    version.ts      package version + GitHub release update check
  client/
    rpc.ts          the client face of the gitPanel endpoints
    controller.ts   per-session snapshot controller
    Panel.tsx       panel shell: sub-tab routing + version bar
    OverviewTab.tsx Overview three columns + hover card
    ChangesTab.tsx  changes page
    FilesTab.tsx    file browser (lazy directory tree + file preview)
    DiffView.tsx    diff view (unified / split / before / after)
    GitPill.tsx     input-bar marker
    code-spans.ts   split syntax tokens at word-level change ranges
    git-graph.ts    commit-graph lane layout
    file-tree.ts    file paths folded into a tree
    diff.ts         unified diff → side-by-side rows + inline rows + stats

License

MIT License.

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →

Community comments

Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.