GitHub PRs, reviews, issues, and CI for DeepSeek Harness — every write gated by human approval, token never logged.
Create, review, merge, and search GitHub from the agent, with a CI composite action, polling review bot, and status-check gate.
Official repository. This is the only official repository of dsh-github, maintained by PerryLink. Same-name repositories under other accounts are not affiliated.
- 1024 store channel:
npm i -g dsh1024once, thendsh1024 plugin --profile web add @perrylink/dsh-github(counts toward the deepseek1024.com install ranking).
- Compatibility
- What you get
- Quick start
- Install & uninstall
- Configuration
- Tools & surfaces
- Architecture
- Permissions & data
- Security boundaries
- Known limitations
- Development
- Repository layout
- Interoperability with other DSH plugins
- Topics
- Contributors
- PerryLink DSH Plugin Family
- License
| Surface | Status |
|---|---|
| Harness | DeepSeek Harness dsh-v0.2.1-alpha.1 (compat declared for >=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0; 0.1.2-rc.1 adapted 2026-09-09): the review job is owned by a bare SessionId and a notice source is the plugin-owned kind dsh-github (the host's Agent | SessionId union and its catch-all kind: 'plugin' are both gone); the settings card registers on the Plugins page (Official group, plugins.item slot) and renders from the owner form dsh-client-ui-plugin-manager supplies, instead of binding the removed ctx.settingsScope; the CI driver auto-approves through the official ctx.approval.setPolicy policy seam; the review bot polls as a ctx.jobs background job with a timer fallback. Upgraded 2026-09-24 to 0.1.7-rc.2 (typecheck + typecheck:ci + 185 unit tests green). |
| Node | ^22.19.0 || >=24.0.0 |
| Platforms | All (host plugin; outbound network to GitHub) |
| Model | Any (static review is deterministic; reviewMode: "model" is optional) |
dsh-github fills the GitHub gap between dsh and tools like Claude Code and Codex: your agent can read, review, open, update, and merge pull requests, read repository metadata and files, comment on and close issues, and search — while a human approves every write and the token stays secret.
- 15 tools —
pr_create,pr_merge,pr_update,gh_review,review_post,gh_issue,issue_open,issue_comment,issue_close,gh_search,gh_repo,gh_file,gh_repo_search,gh_checks, all canonical JSON viadefineTool, plus the one-shotci_runwhenci.enabledis on. - 4 command families —
/pr create,/review(start/stop/post),/issue open, and/ci(scan/status/start/stop/run <pr>, registered underci.enabled). - Full PR lifecycle — create → review → update (title/body/state/base) → merge (merge/squash/rebase, optional head-branch delete).
- Inline reviews —
review_postposts one summary comment or line-anchored review comments against the PR head commit. - Approval-gated writes — every GitHub write goes through
ctx.approval(defaultask, fail-closed); approval reasons preview titles, body sizes, and comment overrides. - Token secrecy — credentials seam → environment →
ghCLI, resolved per operation, never in logs, events, renders, or errors. - Background review jobs —
/reviewruns onctx.jobswith the host's ownjob_list/job_output/job_killsurface. - Resilience — 429 retry with
Retry-After/x-ratelimit-resetbackoff; read tools are concurrency-safe; all calls honor cancellation. - CI surface — the one-shot
ci_runtool, a polling review bot, and a status-check gate (composite actionaction.yml).
# 1. install the bundle into your profile
dsh plugin --profile web add "github:PerryLink/dsh-github#main"
# or from npm (published releases)
dsh plugin --profile web add @perrylink/dsh-github
# 2. restart and verify the row
dsh --profile web --dump-config | grep -A3 'id: dsh-github'- git channel (latest
main):dsh plugin --profile web add "github:PerryLink/dsh-github#main"— thepreparescript builds with production dependencies only. - npm channel (published releases):
dsh plugin --profile web add @perrylink/dsh-github. - tarball channel:
pnpm packin this repo, thendsh plugin --profile web add ./perrylink-dsh-github-<version>.tgz. - uninstall:
dsh plugin --profile web remove @perrylink/dsh-github(or remove the row from the profile patch).
All tunables are Schemastery Config fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. cordis.patch.yml documents each key inline. In the GUI, the Plugins page settings card (Official group) reads tokenRef from the entry's own configuration form — the 0.1.7-alpha.1 host removed the ctx.settingsScope binding and the namespace-registration seam behind it, so the card no longer owns a settings namespace. The GitHub token is not a configuration field at all: the card reports whether the referenced credential is set and writes it through the credentials file, which is where the host half resolves it.
| Key | Default | Meaning |
|---|---|---|
tokenSource |
auto |
auto (credentials → env → gh) or one of credentials / env / gh |
tokenRef |
GITHUB_TOKEN |
Credential-seam reference / environment-variable name |
defaultOwnerRepo |
— | Fallback owner/repo when a call names none and git has no origin |
autoCommit |
false |
Whether /pr create may instruct the model to commit+push first |
maxDiffChars |
8000 |
Character cap for PR diffs read into reviews |
renderExcerptChars |
2000 |
Character cap for the diff excerpt rendered into tool output |
maxComments |
20 |
Cap for PR comments listed by gh_review |
reviewJobTimeoutMs |
600000 |
Deadline for one background review job (fails with timeout) |
maxReviewRecords |
50 |
Cap for in-memory review-job records; oldest settled records evict first |
maxFileChars |
12000 |
Character cap for file contents read by gh_file |
maxFindings |
50 |
Cap for analyzer findings per review |
maxLineLength |
300 |
Line length beyond which the analyzer flags a long-line finding |
reviewMode |
static |
Review engine: static (deterministic analyzer) or model (one-shot subagent through the host's subagents seam; fails loud when the seam is absent) |
modelReviewProvider |
— | Subagent provider name for reviewMode: "model"; defaults to the first registered provider |
maxRetries |
3 |
429 retry attempts per request |
retryBaseMs |
500 |
Retry backoff base (doubles per attempt) |
retryMaxWaitMs |
60000 |
Retry backoff ceiling |
requestTimeoutMs |
30000 |
Hard per-request timeout; aborts the fetch when exceeded |
apiBaseUrl |
https://api.github.com |
GitHub REST base URL (GitHub Enterprise) |
allowedActions |
['pr.create','pr.merge','pr.update','review.post','issue.create','issue.comment','issue.close','ci.run'] |
Write-action whitelist; anything else is denied before approval |
workspaceDir |
unset (explicit override wins) | Working directory for read-only git inspection: explicit config.workspaceDir when set, else the session creation cwd (agent.session.header.cwd), else the process cwd — required for a dsh web service, whose process cwd is not the session's workspace (see "Repository resolution" below) |
ci |
{ enabled: false, … } |
CI integration section: polling review bot, status-check gate, and the one-shot ci_run tool (all ci.* keys live inside it) |
| Surface | Kind | Notes |
|---|---|---|
pr_create |
tool | Create a pull request (write; approval-gated) |
pr_merge |
tool | Merge a PR (merge/squash/rebase, optional head-branch delete) |
pr_update |
tool | Update a PR (title/body/state/base) |
gh_review |
tool | Read a PR: metadata, capped diff, comments, CI, static findings |
review_post |
tool | Publish a review comment (summary or line-anchored inline) |
gh_issue |
tool | List / get / comment on issues (PRs marked kind: "pr") |
issue_open |
tool | Create an issue |
issue_comment |
tool | Comment on an issue or PR |
issue_close |
tool | Close an issue (optional state reason) |
gh_search |
tool | Search issues and PRs (separate search quota) |
gh_repo |
tool | Read repository metadata |
gh_file |
tool | Read one file at a branch/tag/commit |
gh_repo_search |
tool | GraphQL repository search (separate search quota) |
gh_checks |
tool | GraphQL PR status checks (check runs + commit statuses) |
/pr create |
command | Read git state and queue a pr_create instruction |
/review |
command | Start / stop / post a background review job |
/issue open |
command | Queue an issue_open instruction |
ci_run |
tool | One-shot CI review run by the composite action / CI driver |
| review bot | surface | Polling review bot with idempotent inline comments (ci.*) |
| status-check gate | surface | Publishes the success / needs-changes verdict per PR head commit (action.yml) |
- Credential seam.
tokenSource: autoresolves per operation in the order credentials seam (GITHUB_TOKENreference) → environment variable →ghCLI token. The value is a local variable handed to the REST client; it never enters canonical values, renders, cards, command outputs, injected notices, job output, approval reasons, or error messages. - Approval gate. All writes flow through model tools. A
tools/pre-executewaterfall listener returnsaskfor the write tools, so the registry asks the human throughctx.approval(the host logs theapproval/asked+approval/decidedaudit pair) and fails closed without an answerer. Commands never write directly: a write command gathers read-only context, then wakes the agent so the model runs the gated tool inside a turn. - Background review job.
/review <pr>starts agithub-reviewjob onctx.jobs; the job fetches metadata (capturing the head-commit SHA for inline posting), the capped diff, CI checks, and existing comments, then runs the deterministic multi-file analyzer (src/review.ts). The job is owned by the calling agent's bareSessionId—0.1.7-alpha.1fences the registry onSessionIdwith noAgentunion — sodsh-tool-jobsmust be composed orstartrefuses. WithreviewMode: "model", the job hands the capped diff to a one-shot subagent through the host'ssubagentsseam. Completion reaches the session through the host'sdsh-tool-jobsconsumer; the model reads it withjob_outputand publishes it withreview_post. - CI composite action / review bot / status-check gate. The repo ships a composite action (
action.yml) that reviews PRs, fixes CI, and writes the report; a polling review bot posts idempotent inline comments; and a status-check gate publishes the verdict per PR head commit. The one-shotci_runtool drives the headless run. Every write stays approval-gated. - Repository resolution. A
gh_*call resolves its target repo from, in order: an explicitownerRepo;defaultOwnerRepo; then theoriginremote of the working directory chosen byworkspaceDirFor— the explicitconfig.workspaceDir(when set), else the session's creation cwd (agent.session.header.cwd), else the process cwd. The git-origin step needs both a real checkout and a matching host: public GitHub's REST base isapi.github.comwhile its origins aregithub.com, so the host check accepts the provider host under either form (GitHub Enterprise's single host is unaffected). Without the session cwd adsh webdeployment — a service whose process cwd is not the session's workspace — could never resolve a repo, so everyownerRepo-less call failed (#3).
- Permissions: writes ride the official approval seam; nothing is re-implemented or bypassed. The plugin declares
network:outboundandfilesystem:writein its workshop manifest. - Data: the review report lives in process memory keyed by job id; nothing durable is written to disk.
- Session log: the plugin adds no custom session event types; all model-visible content flows through host-logged surfaces (
tool/result,user/message,command/run,approval/asked…). The notices commands queue carry the plugin's own merge-extensible source kind,{ kind: 'dsh-github', form: 'notice', summary }— the host has no catch-allpluginkind, and its session-format admission path refuses one outright.
- Approval, not enforcement. Writes only produce
ask/deny decisions on the official seam; the sandbox and approval systems remain the enforcement authorities. - Fail closed. Missing approval answerer degrades to the strictest decision — never to silent pass-through.
- The token never leaves the process. It is read per operation and sent only in the Authorization header; never logged, rendered, injected, or surfaced in errors.
- No writes outside approval.
/pr createnever commits or pushes by itself; withautoCommit: true, the model performs those writes through the bash tool's own approval gate. The review job performs no writes; onlyreview_postpublishes, after approval. - Untrusted content is escaped and marked.
formatPostBodybacktick- and HTML-escapes diff-derived file names, and external GitHub content (files, bodies, comments, search results) is marked as external in renders. - Bounded work and rate limits. 429s are retried with backoff; the remaining quota is surfaced on every result, including failures.
- No custom session events — deliberate (see Architecture); audit trails rely on the host's own event vocabulary.
- Static analyzer by default — deterministic rules (
src/review.ts), zero tokens, reproducible.reviewMode: "model"costs tokens and requires thesubagentsseam and a registered provider. - Jobs and records are process-local — the review report lives in plugin memory keyed by job id; the record map is capped by
maxReviewRecords(oldest settled records evict first). - npm
latestdist-tags are stale — install through the profile closuredsh-baseprovides; never barenpm i @deepseek-ai/dsh-tools.
pnpm install # node ^22.19 || >=24
pnpm run build # tsc --noEmitOnError → lib/
pnpm run prepare # self-contained git-install build (scripts/prepare.mjs)
pnpm run prepublishOnly # build + test before publishing
pnpm test # vitest run
pnpm run typecheck # tsc --noEmit
pnpm run check:readmes # cross-checks TOC anchors, tools, and config keys in all 5 READMEssrc/index.ts plugin entry (name/inject/apply, applyWithDeps for tests)
src/config.ts Schemastery Config
src/types.ts local structural views of host services + Context merging
src/credential.ts token resolution (seam → env → gh), per operation
src/github.ts REST client: 429 retry, rate limits, diff media type
src/git.ts read-only git inspection + origin parsing for any API host
src/review.ts deterministic diff analyzer + sanitized comment drafting
src/jobs.ts github-review background job producer (metadata + diff + CI + comments)
src/approval-gate.ts tools/pre-execute ask/deny gate with write previews
src/tools.ts the fourteen model-facing tools (plus `ci_run` under src/ci/)
src/commands.ts /pr, /review, /issue
src/present.ts pure UI-card presenters
test/ vitest suite + mock host scaffolding + opt-in e2e smoke
cordis.patch.yml bundle patch (one insert row)
scripts/prepare.mjs self-contained git-install build
Verified against DSH 0.2.0-rc.2 (the runtime this README ships for) and the high-star plugin set surveyed on 2026-10-05.
This plugin does not interfere with other plugins, including the widely installed high-star ones:
- No tool-name collision. Every tool is namespaced; no bare name owned by a shipped tool or another plugin is registered.
- No service-key collision. It provides no service key at all, so it cannot collide on one.
- No slot collision. It registers no client slot key, so it cannot contend for a
shadows-shipped-uiseat. - No HTTP route collision. It registers no
webServerprefix. - No patch-layer collision. The bundle patch only
inserts its own row; it never overrides a built-in row'sconfig. - No global mutation. It does not patch prototypes, rewrite
process.env, or replace the global fetch dispatcher.
Shared event listeners are non-interfering by construction. It observes the ordering-sensitive event tools/pre-execute with ctx.on() — Cordis's broadcast registration, where every listener runs and none can starve another. Every listener here delegates through next(), so the chain is never short-circuited, and a mutation is applied to the value next() produced rather than returned in its place:
tools/pre-execute— also used bycc-safety-net(1576★).
Static evidence: dsh-plugin-doctor K10–K13 report pass for every check on this repository.
dsh · dsh-plugin · deepseek-harness · github · pull-request · code-review · issue-tracker
- @PerryLink — creator and maintainer: the GitHub tool surface, approval gate, background review jobs, CI composite action, review bot, status-check gate, and the five-language docs.
- @AraragiEro — the GitHub token settings card in the Plugins settings page (#6).
- @alexchenzl — invited the plugin onto the DSH Directory (#5).
This project is one of the 33 actively maintained DeepSeek Harness plugins from PerryLink — the roster is 42, of which 6 are frozen and 3 retired; every one keeps its row below, with the reason in the Status column. If this one helps you, the others likely will too:
| Plugin | One-liner | Status |
|---|---|---|
| dsh-auto-review | Second-model auto-review on the approval chain, fail-closed by default | |
| dsh-autotier | Automatic strong/cheap model-tier routing with deterministic risk guards and a /tier command |
|
| dsh-background-agents | Durable background child agents with a Web UI sidebar, messaging and interrupt | 🚫 RETIRED — see the note above |
| dsh-budget | Cost governance for DeepSeek Harness: budgets, carbon, and latency in one panel. | 🧊 FROZEN — see the repo README |
| dsh-catalog | DSH Desktop Market standard catalog source for the PerryLink family | |
| dsh-cert-mcp | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
| dsh-checkpoint-rewind | Claude Code /rewind-equivalent: snapshots, session forks, one-shot restore | |
| dsh-claude-move | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH | 🧊 FROZEN — see the repo README |
| dsh-click | Cross-platform native desktop control for DeepSeek Harness — Windows first. | |
| dsh-composer-history | Terminal-style input history for the web composer: arrows, Ctrl+R search | |
| dsh-data-quality | Dataset quality checks and citation cross-checks (the optional numeric bridge consumed here) | |
| dsh-defend | Prompt-injection, jailbreak, and secret-leak defense for DeepSeek Harness. | 🧊 FROZEN — see the repo README |
| dsh-doublecheck | Engineering-discipline guard: requirements grill, test gates, adversary review | |
| dsh-draw | Unified static-image generation routing for DeepSeek Harness. | 🧊 FROZEN — see the repo README |
| dsh-fast | Read-only performance diagnostics for DeepSeek Harness. | |
| dsh-fund-research | Deterministic research reports for Chinese public mutual funds | |
| dsh-github | GitHub PR/issues integration for DSH, every write gated by approval | |
| dsh-industry-research | Industry research orchestration that seals its deliverables through this plugin's ctx.researchReport.assemble |
|
| dsh-laya | Laya typed decisions (noul/choice/score) as a first-class Cordis service and model-visible tools |
|
| dsh-library | Local document knowledge base for DeepSeek Harness. | |
| dsh-local-ai | Local-model (Ollama) integration for DeepSeek Harness. | |
| dsh-lsp-actions | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
| dsh-mask | PII masking middleware: anonymize at the model boundary, restore at the display layer | |
| dsh-mcp-panel | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors | |
| dsh-memento | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | 🧊 FROZEN — see the repo README |
| dsh-observe | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
| dsh-output-styles | Claude Code outputStyles-equivalent runtime style switching | |
| dsh-permission-rules | Claude Code-style declarative allow/deny/ask permission rules with audit | |
| dsh-plugin-certification | Community certification registry with repro-checkable grades and badges | |
| dsh-plugin-doctor | Zero-dependency static + sandbox smoke detector for DSH plugins | |
| dsh-plugin-guide | Plugin-development knowledge base as an on-demand agent skill | |
| dsh-plugin-kit | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
| dsh-plugin-upgrade | One-package, one-corridor-index plugin upgrade skill: routes a repository to the matching closed corridor card | |
| dsh-plugin-upgrade-015 | Merged 0.1.3-alpha.1 → 0.1.5-rc.1 upgrade corridor card plus a zero-dependency seam scanner |
🚫 RETIRED — corridors carried by dsh-plugin-upgrade |
| dsh-reach | Multi-channel approval/question bridge: WeChat/Telegram/Feishu, session console | 🧊 FROZEN — see the repo README |
| dsh-research-report | Verifiable research-report engine: content-addressed evidence ledger and sealed versions | |
| dsh-score | Multi-dimensional quality scoring for DeepSeek Harness plugins. | |
| dsh-session-pin | Pin sessions in the Web sidebar with durable ordering | 🚫 RETIRED — see the note above |
| dsh-session-sync | Cross-device session sync for DeepSeek Harness — a dedicated git mirror of your session store. | |
| dsh-skill-pack-security | Security-audit skill pack: secret scan, dependency and supply-chain review | |
| dsh-talk | Voice-first session loop for DeepSeek Harness: talk to it, hear it answer. | |
| dsh-team-rooms | Cross-session team rooms: shared message bus, task board and timeline | 🚫 RETIRED — see the note above |
| dsh-test-drive | Isolated install-and-smoke test drives for DeepSeek Harness plugins. | |
| dsh-ticktick | TickTick/Dida365 task bridge: session-header panel + 11 tools | |
| dsh-translate | Vendor parameter translation and deterministic JSON repair for DeepSeek Harness. |
All PerryLink plugins are browsable in the built-in DSH Desktop Market: Market → Sources → add source → paste https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json → select it. Installation still goes through the Market's npm-identity verification and your confirmation.
Apache License 2.0 © 2026 dsh-github contributors