Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .trellis/scripts/common/active_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"kimi",
"zcode",
"snow",
"dsh",
}

# Every name below records how it was checked. Do NOT add a name by analogy
Expand All @@ -64,6 +65,15 @@
# only "evidence" behind them. A platform with no verified name belongs in no
# table; it resolves through TRELLIS_CONTEXT_ID or its hook/plugin bridge.
_ENV_SESSION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
# REAL (reported 2026-08-13 against DSH 0.1.0-rc.6 by @SajoLuo, from a live
# run: DSH exports DSH_SESSION_ID plus DSH_SHELL=1 into its managed shell).
# MUST STAY FIRST. A DSH session can inherit an outer host's identity — a
# DSH launched from Codex still carries CODEX_THREAD_ID — and the untargeted
# lookup below walks this table in order, so any earlier entry would claim
# the session and write a foreign `codex_<thread>` pointer for DSH work.
# DSH_SESSION_ID is the only name here no other vendor sets, so first place
# is safe: it cannot mis-claim a non-DSH session.
("dsh", ("DSH_SESSION_ID",)),
# REAL, undocumented (verified 2026-08-05 in a live Claude Code 2.1.221 bash
# child; absent from code.claude.com/docs/en/env-vars). CLAUDE_SESSION_ID
# was removed here — verified absent from that same live environment.
Expand Down
20 changes: 10 additions & 10 deletions .trellis/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,13 @@ When a user request matches one of these intents inside an active task, route fi

[/Claude Code, Cursor, OpenCode, codex-sub-agent, Kiro, Gemini, Qoder, CodeBuddy, Copilot, Droid, Pi, Oh My Pi, ZCode, Snow, Reasonix, Trae, Grok, Kimi Code]

[codex-inline, Kilo, Antigravity, Devin]
[codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

- Planning or unclear requirements -> `trellis-brainstorm`.
- Before editing -> `trellis-before-dev`; after editing -> `trellis-check`.
- Repeated debugging -> `trellis-break-loop`; spec updates -> `trellis-update-spec`.

[/codex-inline, Kilo, Antigravity, Devin]
[/codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

### Guardrails

Expand Down Expand Up @@ -363,11 +363,11 @@ Spawn the research sub-agent:

[/Claude Code, Cursor, OpenCode, codex-sub-agent, Kiro, Gemini, Qoder, CodeBuddy, Copilot, Droid, Pi, Oh My Pi, ZCode, Snow, Reasonix, Trae, Grok, Kimi Code]

[codex-inline, Kilo, Antigravity, Devin]
[codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

Do the research in the main session directly and write findings into `{TASK_DIR}/research/`. `codex-inline` is the explicit mode that keeps work in the main session.

[/codex-inline, Kilo, Antigravity, Devin]
[/codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

**Research artifact conventions**:
- One file per research topic (e.g. `research/auth-library-comparison.md`)
Expand Down Expand Up @@ -427,11 +427,11 @@ Skip this step only when both files already have real curated entries.

[/Claude Code, Cursor, OpenCode, codex-sub-agent, Kiro, Gemini, Qoder, CodeBuddy, Copilot, Droid, Pi, Oh My Pi, ZCode, Snow, Reasonix, Trae, Grok, Kimi Code]

[codex-inline, Kilo, Antigravity, Devin]
[codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

Skip this step. Context is loaded directly by the `trellis-before-dev` skill in Phase 2.

[/codex-inline, Kilo, Antigravity, Devin]
[/codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

#### 1.4 Activate task `[required · once]`

Expand Down Expand Up @@ -515,15 +515,15 @@ The platform prelude auto-handles the context load requirement:

[/Kiro]

[codex-inline, Kilo, Antigravity, Devin]
[codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

1. Load the `trellis-before-dev` skill to read project guidelines
2. Read `{TASK_DIR}/prd.md`, then `design.md` if present, then `implement.md` if present
3. Consult materials under `{TASK_DIR}/research/`
4. Implement the code per reviewed artifacts
5. Run project lint and type-check

[/codex-inline, Kilo, Antigravity, Devin]
[/codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

#### 2.2 Quality check `[required · repeatable]`

Expand All @@ -543,7 +543,7 @@ The check agent's job:

[/Claude Code, Cursor, OpenCode, codex-sub-agent, Kiro, Gemini, Qoder, CodeBuddy, Copilot, Droid, Pi, Oh My Pi, ZCode, Snow, Reasonix, Trae, Grok, Kimi Code]

[codex-inline, Kilo, Antigravity, Devin]
[codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

Load the `trellis-check` skill and verify the code per its guidance:
- Spec compliance
Expand All @@ -552,7 +552,7 @@ Load the `trellis-check` skill and verify the code per its guidance:

If issues are found → fix → re-check, until green.

[/codex-inline, Kilo, Antigravity, Devin]
[/codex-inline, Kilo, Antigravity, Devin, DeepSeek Harness]

**Final pass (before Phase 3.4 commit)**: the last 2.2 of a task must run full-scope, not just on the latest implement chunk. List all affected packages with `python3 ./.trellis/scripts/get_context.py --mode packages`, then load each package's spec index Quality Check section. This catches cross-layer / multi-package issues a mid-iteration local 2.2 cannot.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
| **Task-centered workflow** | Keep PRDs, implementation context, review context, and task status in `.trellis/tasks/` so AI work stays structured. |
| **Project memory** | Journals in `.trellis/workspace/` preserve what happened last time, so each new session starts with real context. |
| **Team-shared standards** | Specs live in the repo, so one person's hard-won workflow or rule can benefit the whole team. |
| **Multi-platform setup** | Bring the same Trellis structure to 21 AI coding platforms instead of rebuilding your workflow per tool. |
| **Multi-platform setup** | Bring the same Trellis structure to 22 AI coding platforms instead of rebuilding your workflow per tool. |

## Prerequisites:

Expand Down
2 changes: 1 addition & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
| **任务驱动工作流** | PRD、实现上下文、审查上下文与任务状态统一存放于 `.trellis/tasks/`,AI 开发过程保持结构化、可追溯。 |
| **项目记忆** | `.trellis/workspace/` 中的工作日志(journal)会保留上一次会话的脉络,因此每次新会话都能基于真实上下文开始。 |
| **团队共享标准** | Spec 随仓库一同版本化,个人总结出的规则与流程可以直接成为整个团队的基础设施。 |
| **多平台复用** | 同一套 Trellis 结构覆盖 21 个 AI coding 平台,无需为每个工具单独搭建工作流。 |
| **多平台复用** | 同一套 Trellis 结构覆盖 22 个 AI coding 平台,无需为每个工具单独搭建工作流。 |

## 前置要求

Expand Down
2 changes: 1 addition & 1 deletion marketplace
1 change: 1 addition & 0 deletions packages/cli/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ program
.option("--codebuddy", "Include CodeBuddy commands")
.option("--copilot", "Include GitHub Copilot hooks")
.option("--droid", "Include Factory Droid commands")
.option("--dsh", "Include DeepSeek Harness (dsh) skills")
.option("--pi", "Include Pi Agent extension assets")
.option("--reasonix", "Include Reasonix skills")
.option("--zcode", "Include ZCode commands")
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,7 @@ interface InitOptions {
codebuddy?: boolean;
copilot?: boolean;
droid?: boolean;
dsh?: boolean;
pi?: boolean;
reasonix?: boolean;
zcode?: boolean;
Expand Down
85 changes: 85 additions & 0 deletions packages/cli/src/configurators/dsh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* DeepSeek Harness (dsh) configurator.
*
* dsh is a class-2 pull-based platform (agentCapable, no shipped
* session-start hook, no project-level hooks/settings Trellis may write).
* The dsh agent loads skills by name through its skill-loader tool and
* discovers them from the project roots `<projectRoot>/.dsh/skills`
* (rank 100) and `<projectRoot>/.agents/skills` (rank 200). Two output
* paths:
* - `.agents/skills/` — workflow + bundled skills, written via the NEUTRAL
* resolver so the files stay byte-identical to Codex/Gemini/Pi/Kimi
* writes into the same shared root.
* - `.dsh/skills/` — dsh-private user-invocable entry skills
* (`trellis-start` / `trellis-continue` / `trellis-finish-work`),
* platform-resolved (`--platform dsh`, `trellis-<name>` skill refs), in
* dsh's own highest-rank project skill root.
* - `.dsh/DSH.md` — operator guide; also gives the platform a
* configDir-owned tracked file so `trellis platforms` / `uninstall`
* can detect and scope dsh.
*
* dsh ships no project-level sub-agent definition surface, so no
* trellis-implement / trellis-check / trellis-research agent prompts are
* written; implement/check/research run inline through the workflow skills.
*/

import { AI_TOOLS } from "../types/ai-tools.js";
import { getDshGuide } from "../templates/dsh/index.js";
import {
collectSkillTemplates,
resolveAllAsSkills,
resolveBundledSkills,
resolveSkillsNeutral,
} from "./shared.js";

/**
* Command templates that become user-invocable dsh skills
* (`trellis-start` / `trellis-continue` / `trellis-finish-work`). dsh has
* no slash-command palette, so the session-boundary commands are delivered
* as SKILL.md files in `.dsh/skills/`.
*/
const DSH_COMMAND_SKILL_NAMES = new Set([
"trellis-start",
"trellis-continue",
"trellis-finish-work",
]);

/** Session-boundary commands resolved as dsh skills (dsh-private root, so
* platform-specific `{{CLI_FLAG}}` / `{{CMD_REF}}` resolution is correct). */
function resolveDshCommandSkills(): ReturnType<typeof resolveAllAsSkills> {
const ctx = AI_TOOLS.dsh.templateContext;
return resolveAllAsSkills(ctx).filter((skill) =>
DSH_COMMAND_SKILL_NAMES.has(skill.name),
);
}

/**
* The dsh file set — written at init and diffed by `trellis update`.
*/
export function collectDshTemplates(): Map<string, string> {
const ctx = AI_TOOLS.dsh.templateContext;
const files = new Map<string, string>();

// 1. Workflow + bundled skills → shared `.agents/skills/` (neutral
// rendering, byte-identical to Codex/Gemini/Pi/Kimi writes).
for (const [filePath, content] of collectSkillTemplates(
".agents/skills",
resolveSkillsNeutral(ctx),
resolveBundledSkills(ctx),
)) {
files.set(filePath, content);
}

// 2. Commands-as-skills → `.dsh/skills/` (dsh-native project root).
for (const [filePath, content] of collectSkillTemplates(
".dsh/skills",
resolveDshCommandSkills(),
)) {
files.set(filePath, content);
}

// 3. Operator guide → `.dsh/DSH.md`.
files.set(".dsh/DSH.md", getDshGuide());

return files;
}
2 changes: 2 additions & 0 deletions packages/cli/src/configurators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { collectQoderTemplates } from "./qoder.js";
import { collectCodebuddyTemplates } from "./codebuddy.js";
import { collectCopilotTemplates } from "./copilot.js";
import { collectDroidTemplates } from "./droid.js";
import { collectDshTemplates } from "./dsh.js";
import { collectPiTemplates } from "./pi.js";
import { collectReasonixTemplates } from "./reasonix.js";
import { collectZcodeTemplates, configureZcode } from "./zcode.js";
Expand Down Expand Up @@ -98,6 +99,7 @@ const PLATFORM_FUNCTIONS: Record<AITool, PlatformFunctions> = {
codebuddy: fromTemplates(collectCodebuddyTemplates),
copilot: fromTemplates(collectCopilotTemplates),
droid: fromTemplates(collectDroidTemplates),
dsh: fromTemplates(collectDshTemplates),
pi: fromTemplates(collectPiTemplates),
reasonix: fromTemplates(collectReasonixTemplates),
zcode: { configure: configureZcode, collectTemplates: collectZcodeTemplates },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This page lists common Trellis file locations in a user project by platform. Whe
| CodeBuddy | `--codebuddy` | `.codebuddy/` | `.codebuddy/skills/` | `.codebuddy/agents/` | `.codebuddy/hooks/` + `.codebuddy/settings.json` |
| GitHub Copilot | `--copilot` | `.github/` | `.github/skills/` | `.github/agents/` | `.github/copilot/hooks/` + prompts |
| Factory Droid | `--droid` | `.factory/` | `.factory/skills/` | `.factory/droids/` | `.factory/hooks/` + settings |
| DeepSeek Harness (dsh) | `--dsh` | `.dsh/` | `.agents/skills/` (shared) + `.dsh/skills/` (entry skills) | None (workflow skills run implement/check inline) | None (class-2 pull-based; no project hooks/settings) |
| Pi Agent | `--pi` | `.pi/` | `.agents/skills/` | `.pi/agents/` | `.pi/extensions/trellis/` (native `trellis_subagent` tool) + `.pi/settings.json` |
| Trae IDE | `--trae` | `.trae/` | `.trae/skills/` | `.trae/agents/` | `.trae/hooks/` + `.trae/hooks.json` |
| Reasonix | `--reasonix` | `.reasonix/` | `.reasonix/skills/` | None — sub-agents are skills with `runAs: subagent` frontmatter | None |
Expand Down Expand Up @@ -73,7 +74,7 @@ When changing behavior, inspect workflows and skills first. Do not assume Trelli

### Shared `.agents/skills/`

Codex, Gemini CLI, Pi Agent, and Kimi Code write the shared `.agents/skills/` layer. Some tools that support agentskills.io can also read this directory. If the user wants multiple compatible tools to share one skill, consider `.agents/skills/` first, but do not assume every platform reads it. ZCode keeps Trellis-managed skills under `.zcode/skills/`.
Codex, Gemini CLI, Pi Agent, Kimi Code, and DeepSeek Harness (dsh) write the shared `.agents/skills/` layer. Some tools that support agentskills.io can also read this directory. If the user wants multiple compatible tools to share one skill, consider `.agents/skills/` first, but do not assume every platform reads it. ZCode keeps Trellis-managed skills under `.zcode/skills/`.

## Decision Rules When Modifying Platform Files

Expand Down
56 changes: 56 additions & 0 deletions packages/cli/src/templates/dsh/DSH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Trellis on DeepSeek Harness (dsh)

dsh is a **class-2 pull-based** Trellis host: no session-start hook auto-injects
workflow context, so the agent loads the Trellis skills on demand through its
skill-loader tool.

| Capability | Status |
| --- | --- |
| Skills (`.agents/skills/trellis-*/SKILL.md`) | Works — dsh discovers this shared root natively |
| Entry skills (`.dsh/skills/trellis-*/SKILL.md`) | Works — dsh's own project skill root (highest rank) |
| Context hooks | None — pull-based: skills read `.trellis/` files directly |
| Sub-agents | None shipped — implement/check/research run inline via the workflow skills |

## Quick start

```bash
trellis init --dsh -u your-name
dsh web # or: dsh --profile headless "start a Trellis task for ..."
```

In dsh:

1. Open a session in the project root and describe the work in natural
language. For a new task the agent should load the `trellis-start` skill,
which reads the current task state from `.trellis/` and routes to
`trellis-brainstorm` (unclear requirements), `trellis-before-dev` (about to
write code), `trellis-check` (done coding), or `trellis-update-spec`
(learned something worth capturing).
2. Entry skills are `trellis-start` / `trellis-continue` / `trellis-finish-work`
in `.dsh/skills/`. You can also ask for them by name at any time.
3. Type `/trellis:finish-work` is a slash-command convention from other hosts —
dsh has no slash palette, so say "finish the trellis task" instead, and the
agent loads `trellis-finish-work`.

## File map

- `.agents/skills/` — auto-triggered workflow skills (`trellis-before-dev`,
`trellis-brainstorm`, `trellis-check`, `trellis-break-loop`,
`trellis-update-spec`) plus the bundled `trellis-meta` /
`trellis-spec-bootstrap` / `trellis-session-insight` skills. Byte-identical
to Codex / Gemini CLI / Pi / Kimi writes into the same shared root.
- `.dsh/skills/` — dsh-private entry skills (`trellis-start` /
`trellis-continue` / `trellis-finish-work`).
- `.trellis/` — specs, tasks, workspace memory, and the shared scripts the
skills invoke (`get_context.py`, `task.py`, ...).

## Notes

- Skill scripts pass `--platform dsh` to `get_context.py`; the value is used
as a platform-scoped context key.
- The shipped `minimal` agent preset composes only `bash` +
`str_replace_editor`; the default presets include `web_search` and the
filesystem/terminal tools the skills assume.
- dsh has no project-level sub-agent definition surface, so Trellis ships no
`trellis-implement` / `trellis-check` / `trellis-research` agent prompts
here — the workflow skills run those phases inline in the main session.
27 changes: 27 additions & 0 deletions packages/cli/src/templates/dsh/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* DeepSeek Harness (dsh) template module.
*
* dsh is a class-2 pull-based, skills-only platform:
* - Workflow + bundled skills go to the shared `.agents/skills/` root via
* the neutral resolver (byte-identical to Codex/Gemini/Pi/Kimi writes).
* - User-invocable entry points (`trellis-start` / `trellis-continue` /
* `trellis-finish-work`, loaded by the dsh agent through its skill-loader
* tool) live under `.dsh/skills/<name>/SKILL.md` — dsh's own highest-rank
* project skill root.
* - Operator guide `.dsh/DSH.md`.
*
* dsh has no shipped session-start hook, so `trellis-start` is kept as a
* user-invocable skill. dsh ships no project-level sub-agent definition
* surface, so no trellis-implement / trellis-check / trellis-research agent
* prompts are written; implement/check/research run inline through the
* workflow skills.
*/

import { createTemplateReader } from "../template-utils.js";

const { readTemplate } = createTemplateReader(import.meta.url);

/** Operator guide copied to `.dsh/DSH.md`. */
export function getDshGuide(): string {
return readTemplate("DSH.md");
}
10 changes: 10 additions & 0 deletions packages/cli/src/templates/trellis/scripts/common/active_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"kimi",
"zcode",
"snow",
"dsh",
}

# Every name below records how it was checked. Do NOT add a name by analogy
Expand All @@ -64,6 +65,15 @@
# only "evidence" behind them. A platform with no verified name belongs in no
# table; it resolves through TRELLIS_CONTEXT_ID or its hook/plugin bridge.
_ENV_SESSION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
# REAL (reported 2026-08-13 against DSH 0.1.0-rc.6 by @SajoLuo, from a live
# run: DSH exports DSH_SESSION_ID plus DSH_SHELL=1 into its managed shell).
# MUST STAY FIRST. A DSH session can inherit an outer host's identity — a
# DSH launched from Codex still carries CODEX_THREAD_ID — and the untargeted
# lookup below walks this table in order, so any earlier entry would claim
# the session and write a foreign `codex_<thread>` pointer for DSH work.
# DSH_SESSION_ID is the only name here no other vendor sets, so first place
# is safe: it cannot mis-claim a non-DSH session.
("dsh", ("DSH_SESSION_ID",)),
# REAL, undocumented (verified 2026-08-05 in a live Claude Code 2.1.221 bash
# child; absent from code.claude.com/docs/en/env-vars). CLAUDE_SESSION_ID
# was removed here — verified absent from that same live environment.
Expand Down
Loading
Loading