DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

QDchuan /

QDchuan/dsh-github-toolkit

Verified

GitHub tools for DeepSeek Harness: 18 agent-facing github_* tools plus a Web settings page that keeps the PAT in the DSH credential store.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@52604c18

dsh-github-toolkit

English | 中文

GitHub for DeepSeek Harness: 18 agent-facing github_* tools, plus a GitHub page in Web Settings that stores your PAT in the DSH credential store and takes effect without a restart.

No build step, no runtime dependencies — the host half uses Node's built-in fetch, the browser half requires only react and the shell's static UI primitives.

  • The token never lives in configuration. It is resolved from the DSH credential store by reference (default GITHUB_TOKEN) on every request, so rotating the PAT applies to the next call and cordis.patch.yml never contains a secret.
  • Configured in the GUI, not the terminal. Paste the PAT, test it against api.github.com from the page before saving, bind a default repository, and switch the write tools on or off.
  • Failures name the fix. 401 → rotate the token; 403 with zero quota → when it resets; 403 otherwise → scopes or SAML SSO; 404 → missing or unauthorized; 422 → GitHub's own field-level errors.

Requirements

  • DeepSeek Harness 0.1.5-rc.1 or newer (@deepseek-ai/dsh-tools and @deepseek-ai/dsh-credentials are peers the harness provides).
  • Node.js 22+ (the host half uses AbortSignal.any).
  • A GitHub personal access token; fine-grained tokens are recommended.

Install

dsh plugin --profile web add dsh-github-toolkit

The package declares dsh.bundle, so the installer adds it to the profile's bundle list and the row in cordis.patch.yml mounts the host half. Then refresh the Web UI and open Settings → GitHub.

Without npm:

dsh plugin --profile web add github:<owner>/dsh-github-toolkit

No build scripts are involved, so this installs straight from the repository.

Set it up in the GUI

Open Settings from the bottom-left of the Web UI, then pick GitHub:

The GitHub page in Web Settings: token status and source, Test connection / Save / Clear, default owner and repository, API base, timeout, page size, and the write-access switch

  1. Refresh the Web UI and open Settings → GitHub.
  2. Paste the PAT → Test connection (the page calls api.github.com directly, so you see the account, scopes, and remaining quota before anything is stored) → Save token.
  3. Optionally set default owner / default repository and save the configuration.
Section What it does
Access token Shows whether a token is configured and where it comes from (credential store / launch environment); password field to paste one; Test connection; Save; Clear
Defaults & behaviour Default owner, default repository, credential reference name, API base (GitHub Enterprise Server), request timeout, page size, write access switch; Save configuration; Reset to defaults

Interaction decisions worth knowing:

  • Testing happens in the browser. GitHub's REST API answers CORS preflights (Access-Control-Allow-Origin: *, and X-OAuth-Scopes / X-RateLimit-* are exposed), so a candidate token can be validated without handing it to the host first.
  • Stored tokens are never read back. The credential store reports only whether a value is configured, its source, and whether it accepts writes; the page cannot display the secret. Re-paste to re-test, or ask the model to call github_auth_status.
  • Saving applies immediately. Turning write access off unregisters the mutating tools and narrows github_api to GET; turning it on registers them again — no restart.
  • Empty means default. Clearing a text field and saving removes your override, so the value falls back to the composition default.

Tools

Tool Purpose Read-only
github_auth_status Token identity, scopes, remaining quota — the credential diagnostic entry point yes
github_get_repository Repository metadata yes
github_read_file Read a file at a ref, or list a directory yes
github_search Search repositories / code / issues / commits / users yes
github_list_issues List issues (state, labels, assignee, since) yes
github_get_issue One issue or PR, optionally with its comments yes
github_list_pull_requests List pull requests yes
github_get_pull_request One PR with changed files and an optional full diff yes
github_list_commits List commits, optionally filtered by path or author yes
github_list_branches List branches yes
github_get_checks CI status and check runs for a ref yes
github_api Raw REST escape hatch (GET-only when write access is off) depends
github_create_issue Create an issue no
github_comment Comment on an issue or PR no
github_update_issue Change title, body, state, labels, assignees no
github_create_pull_request Create a pull request no
github_create_review Submit a review, with optional inline comments no
github_write_file Commit a file through the contents API (resolves the current sha) no

Read and write tools are modelled separately so permission presets can keep the mutating ones on ask, and one switch turns the plugin read-only.

Returned payloads are curated before they reach the model: GitHub objects carry far more than a model needs, so bodies, patches, and diffs are clipped to configured budgets and marked as truncated.

Configuration

The settings page writes the tool-github namespace in settings.yaml; the composition row only carries defaults:

Field Default Meaning
tokenRef GITHUB_TOKEN Credential reference name
apiBase https://api.github.com Change for GitHub Enterprise Server
defaultOwner / defaultRepo — Without them the model must pass owner/repo
timeoutMs 30000 Per-request timeout
perPage 30 Default page size (max 100)
maxTextChars 6000 Clip budget for bodies and ordinary responses
maxPatchChars 3000 Clip budget per file patch
maxDiffChars 20000 Clip budget for a full diff
maxFileBytes 400000 Larger files return metadata only
enableWrite true Whether the mutating tools are registered
userAgent dsh-github-toolkit/0.3.0 Request User-Agent

Credentials

The PAT lives in $DSH_HOME/.credentials.yaml:

refs:
  GITHUB_TOKEN: ghp_xxxxxxxx

Lookup precedence (owned by dsh-credentials-local): launch environment > credential file > project .env > $DSH_HOME/.env. A GITHUB_TOKEN exported before dsh starts therefore shadows the stored value, and the settings page reports that source.

Suggested fine-grained PAT permissions:

  • Read-only use: Contents: read, Issues: read, Pull requests: read, Metadata: read
  • Write tools as well: Contents: write, Issues: write, Pull requests: write
  • CI status: Actions: read, Checks: read
  • Organization repositories with SAML SSO need the token authorized for that organization, otherwise the API answers 403.

Troubleshooting

Symptom Cause and fix
Test connection returns 401 The token itself is invalid — truncated paste, expired or deleted, or an app secret instead of a PAT. Generate a new one
"No GitHub token was found" Neither the credential store, a .env, nor the process environment has a value. Save one in Settings → GitHub, or launch dsh with GITHUB_TOKEN=…
Reads work, writes or repo creation fail with 403 Resource not accessible by personal access token The token lacks the permission (common with fine-grained tokens). Add it, or switch to a classic token
403 reporting a rate limit Quota exhausted; the message states when it resets
403 otherwise Usually a missing scope, or an organization behind SAML SSO where the token is not authorized
404 The resource does not exist, or the token cannot see private resources (needs repo / Contents: read)
422 GitHub rejected the fields: missing branch, head equal to base, a label or assignee that is not a collaborator — the error carries GitHub's field-level detail
No GitHub page in Settings Refresh the page first. If it is still absent, the running host has not published the new client-plugin graph yet (observed once); restart dsh
A saved token seems to have no effect Check whether the launching shell already exports GITHUB_TOKEN (it shadows the stored value; the page reports which source is in use)
You installed someone else's plugin dsh-tool-github on npm is a different project; this package is dsh-github-toolkit
git over HTTPS: schannel: AcquireCredentialsHandle failed: SEC_E_NO_CREDENTIALS Windows Schannel cannot acquire credentials in that environment (common inside sandboxes). git config --global http.sslBackend openssl switches git to OpenSSL; Node and pnpm are unaffected

Security notes

  • The token is resolved through ctx.credentials per request; the plugin never caches it, never logs it, and has no code path that writes it into configuration.
  • Test connection sends the typed value straight to api.github.com (not to the host); it stays in page memory and the field is cleared after a successful save.
  • github_api bypasses the purpose-built tools' field validation; with write access off it is restricted to GET.
  • The credential file is protected by file permissions, but the agent's tool processes run as the same OS user and can read it — keeping the location unadvertised is discretion, not isolation. A deployment that must keep keys away from its own agent needs a different store.

Development

npm install          # brings the @deepseek-ai peers the tests import
npm test             # host contracts + the browser bundle, offline (plus one live 401 check)
npm run test:installed
  • test/smoke.mjs needs no PAT: it drives the plugin the way the loader does, renders the settings section against a minimal React runtime, and asserts the error mapping against stubbed responses. With a network it also checks that a deliberately invalid token comes back as a mapped 401, and skips that part offline.
  • test/installed.mjs checks what the harness actually loads: node test/installed.mjs [profile] [pluginDir].

For a local checkout you can point a profile at this folder instead of publishing:

./install.ps1 -DryRun     # show what would be copied and written
./install.ps1             # copy into the web profile and add a manual row
./install.ps1 -Uninstall  # remove the copy and that row

Do not combine that with a dsh plugin add install: both resolve to the same package, and two active loader sources for one package are a composition error.

Layout

File Role
cordis.patch.yml Bundle layer: the one row that mounts the host half
lib/index.js Host half and package root: config, credential resolution, tool registration, settings namespace
lib/client.js Browser half: the Settings → GitHub page (hand-written client bundle, no build)
lib/rest.js GitHub REST client: timeouts, pagination, error mapping
lib/tools-read.js, lib/tools-write.js Tool definitions
lib/format.js, lib/shared.js Payload curation/rendering and parameter helpers
test/smoke.mjs, test/installed.mjs Contract tests and an installed-copy check
screenshots.json, assets/ Screenshots a storefront may show, declared inside the repository

Known limitations

  • The tools cover the REST surface this plugin models; anything else goes through github_api, which returns bounded JSON rather than a typed result.
  • GitHub Search's total_count is approximate for large result sets, and the plugin reports it as-is.
  • The browser half is a plain client bundle, so it renders its own controls rather than a schema-driven form; new options are added in lib/client.js and lib/index.js together.
  • A profile that has already loaded a client bundle needs a page refresh to pick up a new version of it.

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 52604c18bb90

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout