dsh-repo-setup 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 gongyijie85
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # dsh-repo-setup
2
+
3
+ 仓库体检引导插件 —— Anthropic **claude-code-setup** 的 DeepSeek Harness 版。
4
+
5
+ 注册一个**只读**工具 `repo_setup_scan`:扫描项目目录的语言栈、测试设置、
6
+ 文档、git、Docker 与数据库线索,然后给出设置建议:该装哪些 DSH 技能插件、
7
+ 该挂哪些 MCP 服务器、该补哪些卫生文件。**绝不修改任何东西。**
8
+
9
+ ## 安装
10
+
11
+ ```sh
12
+ # npm
13
+ dsh plugin --profile web add dsh-repo-setup
14
+
15
+ # GitHub
16
+ dsh plugin --profile web add github:gongyijie85/dsh-repo-setup
17
+
18
+ # 本地开发
19
+ dsh plugin --profile web add D:\plugins\dsh-repo-setup
20
+ ```
21
+
22
+ 装完重启 profile(`dsh web`),模型会在进入新/陌生仓库时自动调用
23
+ `repo_setup_scan`(也可在对话里直接要求"扫描这个仓库怎么配置")。
24
+
25
+ ## 工具:repo_setup_scan
26
+
27
+ | 参数 | 说明 |
28
+ | --- | --- |
29
+ | `path` | 要扫描的项目目录;缺省为当前工作目录 |
30
+
31
+ 输出 Markdown 报告:
32
+
33
+ - **Detected stack** — package.json / pyproject.toml / Cargo.toml / go.mod /
34
+ Dockerfile 等标记识别的技术栈(含前端框架与测试运行器探测)
35
+ - **Repo hygiene** — AGENTS.md 缺失、git 未初始化、无测试、数据库线索
36
+ - **Recommended installs** — 一键命令:
37
+ - `mattpocock-skills-dsh`(grilling/to-spec/to-tickets/tdd/code-review 工作流)
38
+ - `superpowers-dsh`(规划→TDD→评审方法论)
39
+ - `dsh-ponytail`(防过度工程)
40
+ - MCP:context7(库文档)、playwright(前端)、postgres、github(按检测结果)
41
+
42
+ ## 工作原理
43
+
44
+ - **Bundle 层** —— `cordis.patch.yml` 在 dsh-base 层插入插件行。
45
+ - **工具** —— `lib/index.js` 用 `@deepseek-ai/dsh-tools` 的 `defineTool` 注册
46
+ `repo_setup_scan`,只读探测(读有限个已知文件 + 顶层目录列表),不做任何写入。
47
+ - **零运行时依赖** —— 除 harness 注入的 `@deepseek-ai/dsh-tools` peer 依赖外
48
+ 只用 Node 内置模块。
49
+
50
+ ## 开发验证
51
+
52
+ ```sh
53
+ node --check lib/index.js
54
+ # 功能冒烟(伪 ctx 注册 + 直接调 scanRepo 逻辑见 scripts/verify-tool.mjs)
55
+ node scripts/verify-tool.mjs
56
+ ```
57
+
58
+ ## 许可证
59
+
60
+ MIT。见 [LICENSE](LICENSE)。
@@ -0,0 +1,8 @@
1
+ # dsh-repo-setup bundle patch: register the read-only repo bootstrap scanner
2
+ # tool on the host tools registry.
3
+ #
4
+ # This patch is applied over the dsh-base layer; later layers (the profile's
5
+ # own cordis.patch.yml and --patch overlays) can still address this row by id.
6
+ - insert:
7
+ - id: dsh-repo-setup
8
+ name: 'dsh-repo-setup'
package/lib/index.js ADDED
@@ -0,0 +1,195 @@
1
+ // dsh-repo-setup: repo bootstrap guidance for the DeepSeek Harness.
2
+ //
3
+ // A Cordis plugin registering one read-only tool, `repo_setup_scan`, on the
4
+ // `ctx.tools` registry. The tool inspects a project directory (stack markers,
5
+ // test setup, docs, git, docker, db hints) and returns a curated setup
6
+ // recommendation: which DSH skill plugins to install, which MCP servers to
7
+ // mount, and which hygiene files to create. It never modifies anything.
8
+ //
9
+ // This is the DSH counterpart of Anthropic's claude-code-setup plugin.
10
+ //
11
+ // @module dsh-repo-setup
12
+ import { readFile, readdir } from 'node:fs/promises'
13
+ import { join } from 'node:path'
14
+ import { defineTool } from '@deepseek-ai/dsh-tools'
15
+
16
+ const name = 'dsh-repo-setup'
17
+ const inject = ['tools']
18
+
19
+ /** Marker files and the stack label they imply. */
20
+ const STACK_MARKERS = [
21
+ ['package.json', 'Node.js'],
22
+ ['pnpm-workspace.yaml', 'Node.js (pnpm workspace)'],
23
+ ['pyproject.toml', 'Python (pyproject)'],
24
+ ['requirements.txt', 'Python'],
25
+ ['Cargo.toml', 'Rust'],
26
+ ['go.mod', 'Go'],
27
+ ['pom.xml', 'Java (Maven)'],
28
+ ['build.gradle', 'Java (Gradle)'],
29
+ ['Gemfile', 'Ruby'],
30
+ ['composer.json', 'PHP'],
31
+ ['*.sln', 'dotnet'],
32
+ ['Makefile', 'Make (multi-lang)'],
33
+ ['CMakeLists.txt', 'C/C++ (CMake)'],
34
+ ['Dockerfile', 'Docker'],
35
+ ['docker-compose.yml', 'Docker Compose'],
36
+ ]
37
+
38
+ /** Files that indicate a test setup. */
39
+ const TEST_MARKERS = ['vitest.config.*', 'jest.config.*', 'pytest.ini', 'tox.ini', 'Cargo.toml', 'go.mod', '*.test.js', '*.spec.ts', 'tests/', 'test/']
40
+
41
+ /** Presence of a frontend framework among package.json dependencies. */
42
+ const FRONTEND_DEPS = ['react', 'vue', 'next', 'nuxt', 'svelte', 'angular', 'solid-js', 'vite', 'astro']
43
+
44
+ /** Presence of a database hint. */
45
+ const DB_HINTS = ['postgres', 'postgresql', 'DATABASE_URL', 'pg', 'mysql', 'mariadb', 'sqlite', 'mongodb', 'redis']
46
+
47
+ /**
48
+ * Read a small text file, tolerating absence.
49
+ * @param root - directory to look in.
50
+ * @param file - relative file name.
51
+ * @returns file contents or undefined.
52
+ */
53
+ async function tryRead(root, file) {
54
+ try {
55
+ return await readFile(join(root, file), 'utf8')
56
+ } catch {
57
+ return undefined
58
+ }
59
+ }
60
+
61
+ /**
62
+ * List top-level entries of a directory, tolerating absence.
63
+ * @param root - directory to scan.
64
+ * @returns entry names (files and dirs), or [].
65
+ */
66
+ async function listTop(root) {
67
+ try {
68
+ return await readdir(root, { withFileTypes: true })
69
+ } catch {
70
+ return []
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Run the read-only repo scan.
76
+ * @param root - the project directory to inspect.
77
+ * @returns a markdown report string.
78
+ */
79
+ async function scanRepo(root) {
80
+ const entries = await listTop(root)
81
+ const names = new Set(entries.map((e) => e.name))
82
+ const dirs = new Set(entries.filter((e) => e.isDirectory()).map((e) => e.name))
83
+ const files = new Set(entries.filter((e) => e.isFile()).map((e) => e.name))
84
+
85
+ const lines = []
86
+ lines.push(`# Repo setup scan: \`${root}\``)
87
+ lines.push('')
88
+
89
+ // --- stack ---
90
+ const stacks = STACK_MARKERS.filter(([m]) => names.has(m) || (m.includes('*') && [...names].some((n) => n.endsWith(m.slice(1)))))
91
+ .map(([, label]) => label)
92
+ const pkg = await tryRead(root, 'package.json')
93
+ let deps = {}
94
+ if (pkg) {
95
+ try {
96
+ const parsed = JSON.parse(pkg)
97
+ deps = { ...(parsed.dependencies ?? {}), ...(parsed.devDependencies ?? {}) }
98
+ } catch {
99
+ lines.push('- ⚠️ package.json exists but is not valid JSON.')
100
+ }
101
+ }
102
+ const depNames = Object.keys(deps)
103
+ if (depNames.some((d) => FRONTEND_DEPS.includes(d))) stacks.push('Frontend (web framework detected)')
104
+ if (depNames.includes('vitest') || depNames.includes('jest') || depNames.includes('playwright')) stacks.push('JS test runner detected')
105
+ lines.push(`**Detected stack:** ${stacks.length ? [...new Set(stacks)].join(', ') : 'unknown (no common marker found)'}`)
106
+
107
+ // --- hygiene ---
108
+ lines.push('')
109
+ lines.push('## Repo hygiene')
110
+ if (names.has('AGENTS.md') || names.has('CLAUDE.md')) {
111
+ lines.push('- ✅ `AGENTS.md` / `CLAUDE.md` present.')
112
+ } else {
113
+ lines.push('- ❌ No `AGENTS.md` / `CLAUDE.md` — agents start with zero repo conventions. Create one (writing-for-agents skill can draft it).')
114
+ }
115
+ if (names.has('.git')) {
116
+ lines.push('- ✅ Git repository initialized.')
117
+ } else {
118
+ lines.push('- ❌ Not a git repository — run `git init` before starting work.')
119
+ }
120
+ if (dirs.has('.github')) {
121
+ lines.push('- ✅ GitHub Actions directory present.')
122
+ }
123
+ const hasTests =
124
+ depNames.some((d) => ['vitest', 'jest', 'playwright', 'mocha', 'cypress', 'pytest', 'unittest'].includes(d)) ||
125
+ dirs.has('tests') || dirs.has('test') ||
126
+ [...names].some((n) => /\.(test|spec)\./.test(n))
127
+ lines.push(hasTests ? '- ✅ Test setup detected.' : '- ⚠️ No tests detected — consider test-first work (tdd skill).')
128
+ const dbHints = [...new Set([...depNames, (await tryRead(root, '.env.example')) ?? '', (await tryRead(root, '.env')) ?? ''].join('\n').match(/postgres|mysql|mariadb|sqlite|mongodb|redis|DATABASE_URL/g) ?? [])]
129
+ if (dbHints.length) {
130
+ lines.push(`- 🗄️ Database hints: ${dbHints.join(', ')}.`)
131
+ }
132
+
133
+ // --- recommendations ---
134
+ lines.push('')
135
+ lines.push('## Recommended installs')
136
+ const installs = []
137
+ installs.push('mattpocock-skills-dsh — grilling / to-spec / to-tickets / tdd / code-review workflow (25 skills)')
138
+ installs.push('superpowers-dsh — brainstorming → plans → TDD → review methodology')
139
+ installs.push('dsh-ponytail — lazy senior dev mode (anti-over-engineering)')
140
+ if (hasTests || stacks.some((s) => s.includes('test'))) installs.push('(tdd skill is included in both packs above)')
141
+ lines.push(`- \`dsh plugin --profile web add github:gongyijie85/mattpocock-skills-dsh\``)
142
+ lines.push(`- \`dsh plugin --profile web add github:LayneChai/superpowers-dsh\``)
143
+ lines.push(`- \`dsh plugin --profile web add github:gongyijie85/dsh-ponytail\``)
144
+ lines.push(`- \`dsh plugin --profile web add github:Bleed00/dsh-claude-mem\` (optional: cross-session memory)`)
145
+ lines.push(`- \`dsh plugin --profile web add github:Nichts0v0/dsh-mcp-manager\` (to mount the MCP servers below)`)
146
+ if (stacks.some((s) => s.includes('Node') || s.includes('Rust') || s.includes('Python') || s.includes('Go'))) {
147
+ lines.push('')
148
+ lines.push('**MCP servers to mount** (via the DSH MCP manager / Settings → MCP):')
149
+ lines.push('- `context7` (https://mcp.context7.com/mcp) — up-to-date library docs, kills hallucinated APIs')
150
+ }
151
+ if (stacks.some((s) => s.includes('Frontend'))) {
152
+ lines.push('- `playwright` (official Playwright MCP) — browser automation for the UI work')
153
+ }
154
+ if (dbHints.includes('postgres') || dbHints.includes('pg') || dbHints.includes('DATABASE_URL')) {
155
+ lines.push('- `postgres` (crystaldba/postgres-mcp) — schema/query help')
156
+ }
157
+ if (dirs.has('.github')) {
158
+ lines.push('- `github` (official GitHub MCP via GitRuozhi/dsh-github-mcp) — issues/PRs in context')
159
+ }
160
+
161
+ // --- summary ---
162
+ lines.push('')
163
+ lines.push('## Notes')
164
+ lines.push('- This scan is read-only: it never modified the repository.')
165
+ lines.push('- Re-run `repo_setup_scan` after the repo changes to refresh recommendations.')
166
+ lines.push('- Full plugin index: https://github.com/Dominic789654/awesome-deepseek-harness')
167
+ return lines.join('\n')
168
+ }
169
+
170
+ /** Register the read-only repo setup scanner. */
171
+ function apply(ctx) {
172
+ ctx.tools.register(defineTool({
173
+ name: 'repo_setup_scan',
174
+ description: 'Read-only bootstrap scan of a project directory: detects language stack, test setup, docs, git, docker and database hints, ' +
175
+ 'then recommends which DSH skill plugins to install (mattpocock-skills-dsh, superpowers-dsh, dsh-ponytail), which MCP servers to ' +
176
+ 'mount (context7, playwright, postgres, github), and which hygiene files to create. ' +
177
+ 'Use when starting work in a new or unfamiliar repository, or when the user asks what to install / how to set this repo up. ' +
178
+ 'Never modifies anything.',
179
+ parameters: {
180
+ path: {
181
+ type: 'string',
182
+ description: 'Project directory to scan. Defaults to the current working directory.',
183
+ },
184
+ },
185
+ output: {
186
+ schema: { type: 'string' },
187
+ render: (_args, value) => [{ type: 'text', text: value }],
188
+ },
189
+ execute: (args) => scanRepo(args.path ?? process.cwd()),
190
+ timeoutMs: 15000,
191
+ }))
192
+ }
193
+
194
+ export { apply, name, inject }
195
+ export default { apply, name, inject }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "dsh-repo-setup",
3
+ "description": "Repo bootstrap guidance for DeepSeek Harness: read-only repo_setup_scan tool that detects stack/tests/docs/git/db and recommends skill plugins, MCP servers and hygiene files to install (claude-code-setup counterpart)",
4
+ "version": "0.1.0",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "lib/index.js",
8
+ "exports": {
9
+ ".": "./lib/index.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "files": [
13
+ "lib",
14
+ "cordis.patch.yml",
15
+ "README.md",
16
+ "LICENSE"
17
+ ],
18
+ "license": "MIT",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/gongyijie85/dsh-repo-setup.git"
22
+ },
23
+ "homepage": "https://github.com/gongyijie85/dsh-repo-setup",
24
+ "bugs": {
25
+ "url": "https://github.com/gongyijie85/dsh-repo-setup/issues"
26
+ },
27
+ "keywords": [
28
+ "dsh",
29
+ "dsh-plugin",
30
+ "deepseek-harness",
31
+ "plugin",
32
+ "bootstrap",
33
+ "repo-setup",
34
+ "claude-code-setup"
35
+ ],
36
+ "peerDependencies": {
37
+ "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1 <0.2.0",
38
+ "@deepseek-ai/cordis": "^4.0.1"
39
+ },
40
+ "scripts": {
41
+ "verify": "node scripts/verify-tool.mjs",
42
+ "prepublishOnly": "node scripts/verify-tool.mjs"
43
+ },
44
+ "dsh": {
45
+ "bundle": {
46
+ "patch": "./cordis.patch.yml"
47
+ }
48
+ }
49
+ }