Introduction¶
When working in DSH (DeepSeek Harness) daily, finding repositories basically relies on opening new tabs and scrolling github.com/trending: when seeing a useful repo, copy the address, open a terminal to git clone, and casually throw the README into a translation tool. Direct browser connections to GitHub are blocked by CORS, so the plugin must make these network requests itself.
dsh-plugin-github-radar (1578361862-art/dsh-plugin-github-radar) incorporates this process into DSH’s own Web GUI: it adds a “GitHub Radar” panel to view repos trending today/this week/this month, favorites them, reads the README (can be one-click translated to Chinese), stars them, and shallow clones them to the local machine. It is not a standalone web page, but a full-screen panel within DSH, occupying the main slot, with an entry in the left column, and its style follows the theme.
Below is an introduction to the plugin’s structure, capabilities, installation methods, and actual pitfalls encountered during use.
What is it¶
A one-sentence positioning: A DSH client plugin that integrates GitHub trend browsing, favoriting, cloning, and README Chinese translation into the DSH panel.
- Maintainer: 1578361862-art
- Current Version: 0.2.0 (
package.json) - License: MIT
- Runtime Environment:
node >=20,dsh >=0.2.1-rc.5 - Directory Category: Networking Tools
- Principle: The host is responsible for scraping and cloning; the browser side only handles UI; both call
/github-radar/api/*via same-origin; no extra ports or second processes are started.
It solves the friction of the two steps “finding repositories” and “reading README”: The DSH under the user’s account already has a model mounted, and the plugin directly reuses it without requiring an extra key; cloning is shallow cloning, typically for scenarios where you just want to take a look at the code rather than pull the full history.
Overall Structure: Host + Browser¶
dsh-plugin-github-radar/
├── package.json # dsh.client.platform=web, exports ./client
├── lib/index.js # Host side: /github-radar/api/*, scraping, cloning, login, translation
├── lib/client.js # Browser side: __ModuleLoader__ bundle, registers main + sidebar entry
└── docs-panel.png
The division of labor is clear:
- The host does the dirty work: scrape
github.com/trending, get READMEs fromraw.githubusercontent.com,git clone --depth 1, call the model to translate. - The browser only handles UI, making same-origin calls via
fetch('/github-radar/api/...').
The reason for this is that direct browser connections to GitHub are blocked by CORS, so these actions cannot be placed in front-end code.
Core Features¶
Trending Dashboard & Filtering¶
The panel switches time ranges between Today / This Week / This Month. The language dropdown supports 18 languages, and the filter box can filter by repository name, description, or language. Trending data is cached in the host’s memory for 10 minutes.
Accessing github.com/trending while not logged in only yields 15 items; after logging in, it uses the GitHub API, increasing the quota from 60 times/hour to 5000 times/hour.
README Chinese Translation¶
The top-right corner of the README popup has “Original / Chinese”. When clicking “Chinese”, the host splits the README into two categories: code blocks and body paragraphs: code blocks are kept as-is and output directly, while body paragraphs are translated paragraph by paragraph, streamed back via SSE, allowing you to see the translation as it happens. The model used is the one already configured in DSH (ctx.llm, defaulting to deepseek-account / deepseek-flash), and no extra key is required. If a profile has no model mounted, it will directly report “No model service mounted”.
A few details worth noting:
- If a segment is empty, it returns to the original text and notes it, so the entire text won’t fail.
- Batch translation: Approximately 12,000 characters per batch. When reaching the end of a batch, “Continue translation (N chars left)” will appear at the bottom of both the body and the popup.
- It saves to disk after every paragraph is translated; closing the popup midway doesn’t waste the work. When opened next time, it first shows the translated parts and can resume from the breakpoint.
- Translations are cached in
~/Data/github-radar/translations/<owner>__<repo>__<engine>.json, stored separately by engine, not overwriting each other; “Re-translate” forces a re-run.
Engines are selectable (dropdown in the bottom-left of the popup):
| Engine | Description |
|---|---|
| Any configured model | Listed from ctx.llm, small models like flash / mini / lite / small are ranked first; this is used by default |
| Google Translate | Cloud Translation API v2, requires an API key; if no key is present, selecting it will pop up a configuration box |
| Free Machine Translation · MyMemory | Does not consume model quota, but limits are strict: 500 characters per request, about 1000 words per day, you might hit a 429 error after translating two READMEs. When rate limited, it automatically falls back to the model to continue |
Steps to integrate Google Translate:
1. Enable Cloud Translation API in the GCP Console
2. Create an API key (it is recommended to add restrictions: only allow Translation API)
3. Switch the engine in the panel to "Google Translate", paste the key, and it will verify by translating a word when saving
The key is stored in ~/Data/github-radar/google.json (permissions 600), and will be immediately deleted if verification fails. Billing is based on characters: 500,000 characters are free per month, exceeding that is about $20/million characters. It is one or two orders of magnitude more expensive than deepseek-flash for the same content; the reason for choosing it is usually “don’t want to touch model quota” or “have GCP quota on hand”.
GitHub Login¶
Click “Login GitHub” in the top right. There are two sources: paste a Personal Access Token directly, or leave it blank and run gh auth login in the terminal; the plugin will automatically reuse gh auth token. Classic tokens require the repo scope, while fine-grained tokens require repository read permissions.
Differences in capabilities before and after login:
| Capability | Not Logged In | Logged In |
|---|---|---|
| Trending list, README, Translation | ✅ | ✅ |
| Clone public repositories | ✅ | ✅ |
| Clone private repositories | ❌ | ✅ |
| Star/Unstar directly in panel | ❌ (will prompt to login if clicked) | ✅ |
| GitHub API quota | 60 times/hour | 5000 times/hour |
The token is stored in ~/Data/github-radar/auth.json, with chmod 600 after writing; when cloning, it passes the header via GIT_CONFIG_* environment variables; the token does not go into argv, nor is it written into .git/config.
Installation & Enablement¶
The plugin is released in DSH’s bundle format. One command (after npm publish):
dsh plugin --profile desktop add dsh-plugin-github-radar
If testing from a local directory:
dsh plugin --profile desktop add file:/absolute/path/github-radar-plugin
It writes to the profile’s dependencies and dsh.profile.bundles simultaneously. The entry is provided by cordis.patch.yml inside the package, so no manual configuration is needed. It should be noted that declaring dsh.bundle is a hard requirement for community directories; declaring only dsh.client packages makes them non-installable in one click; this package has both.
Uninstall:
dsh plugin --profile desktop remove dsh-plugin-github-radar
If installed from a local directory, delete the symlink ~/.dsh/profiles/desktop/node_modules/dsh-plugin-github-radar. ~/Data/github-radar and cloned repositories under ~/Code will not be deleted.
Typical Usage¶
A mapping of common actions in the panel is as follows:
| Action | Result |
|---|---|
| Today / This Week / This Month | Switch trending time range |
| Language dropdown | View only a specific language (18 types) |
| Filter box | Filter by repo name, description, or language |
| Clone | git clone --depth 1 to ~/Code/<owner>__<repo> |
| Favorite | Add to the favorites on the right, saved to ~/Data/github-radar/collection.json |
| README | Popup view, Markdown renders normally, can switch to Chinese (engine selectable) |
| ☆ | Star on GitHub (requires login) |
| ↗ | Go to GitHub |
Once cloned, it is a regular git repository. A shallow clone only has the current commit; if you need the full history, run inside the directory:
git fetch --unshallow
The browsing order is usually to look at trends, filter for the target, click clone, and then switch to Chinese in the README popup. Translating this kind of work doesn’t require a strong model; if you configure a local or free provider in DSH in the future, it will appear directly in the engine dropdown.
Where Data Lives¶
Divided into two places according to home directory rules:
~/Data/github-radar/ # Plugin's own state
├── auth.json # Login token (600)
├── collection.json # Favorites
└── translations/*.json # Translation cache
~/Code/<owner>__<repo>/ # Cloned repositories, all regular git repos
The clone directory uses owner__repo instead of the bare repository name because there might already be a directory with the same name under ~/Code; adding the prefix prevents treating someone else’s repository as “already present locally”. Both roots can be overridden by environment variables: GITHUB_RADAR_CODE, GITHUB_RADAR_HOME.
Interface Overview¶
The host side provides these HTTP interfaces, which are called by the browser side via same-origin:
GET /github-radar/api/trending?since=daily|weekly|monthly&lang=
GET /github-radar/api/state
POST /github-radar/api/collection {action:'add'|'remove', item}
POST /github-radar/api/clone {owner, repo}
GET /github-radar/api/readme?owner=&repo=
POST /github-radar/api/reveal {dir}
GET /github-radar/api/auth
POST /github-radar/api/auth {token}
DELETE /github-radar/api/auth
GET /github-radar/api/engines
POST /github-radar/api/engines {engine}
POST /github-radar/api/google {key}
DELETE /github-radar/api/google
GET /github-radar/api/stars?repos=a/b,c/d
POST /github-radar/api/star {owner, repo, star}
POST /github-radar/api/translate {owner, repo, force} → SSE
Among them, /github-radar/api/translate returns SSE, which is the channel for streaming translation back paragraph by paragraph.
Known Limitations¶
The limitations mentioned in the README are worth knowing before using:
- It parses the HTML of
github.com/trending; unlogged access only has 15 items; if GitHub changes the layout, it will stop working, and the page will display “didn’t catch anything this time”. - The leaderboard is cached in the host’s memory for 10 minutes.
- Cloning is shallow cloning; if you need full history, run
git fetch --unshallowin the directory. - Translation is at most about 12,000 characters per run; the latter half of long READMEs remains in the original text.
- README rendering uses a built-in lightweight parser (no third-party libraries): bare HTML is stripped leaving only text, and
<details>collapsible blocks are flattened. - The client
applyand translation both wrap try/catch: if the plugin itself errors, it only logs and won’t crash the Web startup.
Use Cases & Precautions¶
Who is it for: People who need to find open source repositories in DSH daily, read READMEs, and want to directly clone a shallow copy; and DSH users who want to open fewer tabs and put “Discover - Favorite - Clone - Understand” together. Those already using gh login or have configured a deepseek model profile require almost zero extra configuration.
Things to watch out for:
- The plugin runs with the permissions of the current dsh process, allowing it to read/write files, start processes, and access the network. Before installing, you should check the source code (
lib/index.js,lib/client.js) and the license (MIT) to see clearly which paths it touches. - Translations use the model already mounted in your DSH and will consume the corresponding model’s quota; if you don’t want to touch the quota, you can choose Google Translate or MyMemory, but the latter has a limit of 500 characters per request and about 1000 words per day.
- Whether accessing
github.comandraw.githubusercontent.comis unimpeded in a team/company proxy environment directly determines whether the plugin can be used; the easiest way to verify is to try the trending list in an unlogged state first.
Conclusion¶
The usage of dsh-plugin-github-radar is very centralized: adding a panel to DSH combines finding repositories, cloning, and reading README, while reusing the existing model configuration for translation. Login and keys are both optional. The functionality isn’t complex, but it consolidates several repetitive manual operations into one entry point.
For more information, see the directory page https://www.skillhub.cn/plugins/1578361862-art/dsh-plugin-github-radar and the repository https://github.com/1578361862-art/dsh-plugin-github-radar.