Skip to content

Commit ea5b856

Browse files
AnIntegersunxing
andauthored
Add DeepSeek Harness (DSH) integration (#4336)
* feat: add DeepSeek Harness (DSH) integration Add a skills-based integration for DeepSeek Harness (DSH), the agent runtime behind the dsh CLI and Web GUI. DSH discovers project skills one level deep from .dsh/skills (its native root, provider rank 100) and .agents/skills (rank 200), using speckit-<name>/SKILL.md directory bundles with name/description frontmatter — the same agentskills.io layout SkillsIntegration already scaffolds. Users invoke skills via the '/'-trigger input in the DSH Web GUI (/speckit-specify <description>); the harness injects the rendered <skill_content> into the turn. Project AGENTS.md guidance is loaded natively by DSH, so no context-file handling is needed. - Install skills to .dsh/skills/speckit-<name>/SKILL.md (isolated static root; multi-install safe alongside other agents) - CLI dispatch via 'dsh --profile headless "<prompt>"' one-shot mode - Register 'dsh' in ALWAYS_SLASH_AGENTS so init output and hook messages render /speckit-<command> invocations - Add init next-steps hint, catalog entry, issue-template lists, devcontainer install step, docs table row - Verify with the real dsh-skill-filesystem provider: all 10 skills discovered as user- and model-invocable, bodies loadable Assisted-by: DeepSeek Harness (model: glm-5.3, supervised) * Address review: bump catalog updated_at, assert DSH next-steps output - Refresh integrations/catalog.json updated_at to the date of this catalog change (matches the bump convention in prior catalog PRs). - Add TestDshNextSteps asserting the init next-steps panel shows the 'Start DSH (dsh web)' guidance and .dsh/skills install path, and renders /speckit-<command> rather than dotted invocations — modeled on TestGrokNextSteps so a regression in the hint or path fails CI. Assisted-by: DeepSeek Harness (model: glm-5.3, supervised) * Address DSH review feedback Place launcher extra arguments before the headless task positional and keep the discovery-depth test compatible with valid skill resource directories. Assisted-by: OpenAI Codex (model: GPT-5, autonomous) --------- Co-authored-by: sunxing <sunxing@qianxin.com>
1 parent c1b01dd commit ea5b856

12 files changed

Lines changed: 404 additions & 4 deletions

File tree

‎.github/ISSUE_TEMPLATE/agent_request.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ body:
88
value: |
99
Thanks for requesting a new agent! Before submitting, please check if the agent is already supported.
1010
11-
**Currently supported agents**: Alquimia AI, Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Command Code, Cursor, Devin for Terminal, Docker Agent, Factory Droid, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Grok Build, Hermes Agent, IBM Bob, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed
11+
**Currently supported agents**: Alquimia AI, Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Command Code, Cursor, Devin for Terminal, Docker Agent, Factory Droid, DeepSeek Harness, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Grok Build, Hermes Agent, IBM Bob, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed
1212
1313
- type: input
1414
id: agent-name

‎.github/ISSUE_TEMPLATE/bug_report.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ body:
7575
- Devin for Terminal
7676
- Docker Agent
7777
- Factory Droid
78+
- DeepSeek Harness
7879
- Firebender
7980
- Forge
8081
- Gemini CLI

‎.github/ISSUE_TEMPLATE/feature_request.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ body:
6969
- Devin for Terminal
7070
- Docker Agent
7171
- Factory Droid
72+
- DeepSeek Harness
7273
- Firebender
7374
- Forge
7475
- Gemini CLI

‎docs/reference/integrations.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify
1616
| [Codex CLI](https://github.com/openai/codex) | `codex` | Skills-based integration; installs skills into `.agents/skills` and invokes them as `$speckit-<command>` |
1717
| [Command Code](https://commandcode.ai/docs) | `command-code` | Skills-based integration; installs skills into `.commandcode/skills/` and invokes them as `$speckit-<command>` |
1818
| [Cursor](https://cursor.sh/) | `cursor-agent` | |
19+
| [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) | `dsh` | Skills-based integration; installs skills into `.dsh/skills` and invokes them as `/speckit-<command>` |
1920
| [Devin for Terminal](https://cli.devin.ai/docs) | `devin` | Skills-based integration; installs skills into `.devin/skills/` and invokes them as `/speckit-<command>` |
2021
| [Docker Agent](https://docs.docker.com/ai/docker-agent/) | `docker-agent` | Skills-based integration; installs skills into `.agents/skills/` (the same directory used by Codex and Zed). In the selected agent YAML, enable local skills with `skills: true` and provide filesystem read access. Detects either the standalone `docker-agent` binary or the Docker CLI plugin (`docker agent`). Configure workflow dispatch with `SPECKIT_INTEGRATION_DOCKER_AGENT_EXTRA_ARGS=./agent.yaml`; the Spec Kit prompt is appended after these arguments. Not multi-install safe by default because the skills directory is shared. |
2122
| [Factory Droid](https://docs.factory.ai/cli/getting-started/overview) | `droid` | Skills-based integration; installs skills into `.factory/skills/` and invokes them as `/speckit-<command>` |

‎integrations/catalog.json‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schema_version": "1.0",
3-
"updated_at": "2026-08-26T00:00:00Z",
3+
"updated_at": "2026-08-31T00:00:00Z",
44
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.json",
55
"integrations": {
66
"alquimia": {
@@ -66,6 +66,15 @@
6666
"repository": "https://github.com/github/spec-kit",
6767
"tags": ["cli", "skills", "factory"]
6868
},
69+
"dsh": {
70+
"id": "dsh",
71+
"name": "DeepSeek Harness",
72+
"version": "1.0.0",
73+
"description": "DeepSeek Harness (DSH) CLI skills-based integration",
74+
"author": "spec-kit-core",
75+
"repository": "https://github.com/github/spec-kit",
76+
"tags": ["cli", "skills"]
77+
},
6978
"amp": {
7079
"id": "amp",
7180
"name": "Amp",

‎src/specify_cli/_invocation_style.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
# Agents that always render /speckit-<name>, regardless of ai_skills.
1515
ALWAYS_SLASH_AGENTS: frozenset[str] = frozenset(
16-
{"devin", "droid", "grok", "qodercli", "trae", "zed"}
16+
{"devin", "droid", "dsh", "grok", "qodercli", "trae", "zed"}
1717
)
1818

1919
# Agents that render /speckit-<name> only when ai_skills is enabled.

‎src/specify_cli/commands/init.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ def init(
10131013
devin_skill_mode = selected_ai == "devin"
10141014
zed_skill_mode = selected_ai == "zed" and _is_skills_integration
10151015
grok_skill_mode = selected_ai == "grok" and _is_skills_integration
1016+
dsh_skill_mode = selected_ai == "dsh" and _is_skills_integration
10161017
cline_skill_mode = selected_ai == "cline"
10171018
forge_skill_mode = selected_ai == "forge"
10181019
bob_skill_mode = selected_ai == "bob" and _is_skills_integration
@@ -1028,6 +1029,7 @@ def init(
10281029
or devin_skill_mode
10291030
or zed_skill_mode
10301031
or grok_skill_mode
1032+
or dsh_skill_mode
10311033
or bob_skill_mode
10321034
)
10331035

@@ -1066,6 +1068,11 @@ def init(
10661068
f"{step_num}. Start Grok Build in this project directory; spec-kit skills were installed to [cyan].grok/skills[/cyan]"
10671069
)
10681070
step_num += 1
1071+
if dsh_skill_mode:
1072+
steps_lines.append(
1073+
f"{step_num}. Start DSH ([cyan]dsh web[/cyan]) in this project directory; spec-kit skills were installed to [cyan].dsh/skills[/cyan]"
1074+
)
1075+
step_num += 1
10691076
if bob_skill_mode:
10701077
steps_lines.append(
10711078
f"{step_num}. Start Bob in this project directory; spec-kit skills were installed to [cyan].bob/skills[/cyan]"

‎src/specify_cli/integrations/__init__.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def _register_builtins() -> None:
6262
from .devin import DevinIntegration
6363
from .docker_agent import DockerAgentIntegration
6464
from .droid import DroidIntegration
65+
from .dsh import DshIntegration
6566
from .firebender import FirebenderIntegration
6667
from .forge import ForgeIntegration
6768
from .gemini import GeminiIntegration
@@ -103,6 +104,7 @@ def _register_builtins() -> None:
103104
_register(DevinIntegration())
104105
_register(DockerAgentIntegration())
105106
_register(DroidIntegration())
107+
_register(DshIntegration())
106108
_register(FirebenderIntegration())
107109
_register(ForgeIntegration())
108110
_register(GeminiIntegration())
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""DeepSeek Harness (DSH) integration — skills-based agent.
2+
3+
DSH discovers project skills from ``.dsh/skills`` (its native root, highest
4+
provider rank) and from the shared ``.agents/skills`` root, one level deep,
5+
using ``<name>/SKILL.md`` directory bundles with ``name``/``description``
6+
frontmatter — the same agentskills.io layout Spec Kit scaffolds for other
7+
skills-based agents. Skills are user-invocable through the ``/``-trigger
8+
input in the DSH Web GUI (and any TUI/ACP front end): typing
9+
``/speckit-specify <feature description>`` ships the literal token plus the
10+
user text, and the harness injects the skill's ``<skill_content>`` into the
11+
turn. Project guidance in ``AGENTS.md`` at the repo root is loaded
12+
automatically by DSH, so no context-file handling is needed here.
13+
14+
See: https://github.com/deepseek-ai/deepseek-harness
15+
"""
16+
17+
from __future__ import annotations
18+
19+
from ..base import SkillsIntegration
20+
21+
22+
class DshIntegration(SkillsIntegration):
23+
"""Integration for the DeepSeek Harness (DSH) agent."""
24+
25+
key = "dsh"
26+
config = {
27+
"name": "DeepSeek Harness",
28+
"folder": ".dsh/",
29+
"commands_subdir": "skills",
30+
"install_url": "https://github.com/deepseek-ai/deepseek-harness",
31+
"requires_cli": True,
32+
}
33+
registrar_config = {
34+
"dir": ".dsh/skills",
35+
"format": "markdown",
36+
"args": "$ARGUMENTS",
37+
"extension": "/SKILL.md",
38+
}
39+
# ``.dsh/`` is a static, unique agent root that no other integration
40+
# writes into, so co-installing DSH alongside other agents is safe.
41+
multi_install_safe = True
42+
43+
def build_exec_args(
44+
self,
45+
prompt: str,
46+
*,
47+
model: str | None = None,
48+
output_json: bool = True,
49+
) -> list[str] | None:
50+
"""Build non-interactive CLI args for DSH.
51+
52+
DSH's one-shot mode is ``dsh --profile headless "<task>"``: the
53+
runner submits the task as an ordinary user message, waits for
54+
quiescence, and prints the last assistant message to stdout. The
55+
headless profile recognizes whitespace-bounded ``/name`` tokens
56+
naming user-invocable skills, so a slash-command prompt such as
57+
``/speckit-specify build photo albums`` loads the skill exactly as
58+
an interactive session would. The CLI has no structured-JSON output
59+
flag, so ``output_json`` and ``model`` are ignored.
60+
"""
61+
args = [self._resolve_executable(), "--profile", "headless"]
62+
self._apply_extra_args_env_var(args)
63+
args.append(prompt)
64+
return args

0 commit comments

Comments
 (0)