Skip to content

Commit 90e6436

Browse files
fuyongdeclaude
andcommitted
fix: migrate Qwen Code CLI from TOML to Markdown format (#1589)
Qwen Code CLI v0.10.0 deprecated TOML format and fully switched to Markdown as the core format for configuration and interaction files. - Update create-release-packages.sh: generate .md files with $ARGUMENTS instead of .toml files with {{args}} for qwen agent - Update create-release-packages.ps1: same change for PowerShell script - Update AGENTS.md: reflect Qwen's new Markdown format in docs and remove Qwen from TOML format section - Update tests/test_ai_skills.py: add commands_dir_qwen fixture and tests covering Markdown-format skills installation for Qwen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5c0bedb commit 90e6436

File tree

4 files changed

+47
-6
lines changed

4 files changed

+47
-6
lines changed

.github/workflows/scripts/create-release-packages.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ function Build-Variant {
298298
}
299299
'qwen' {
300300
$cmdDir = Join-Path $baseDir ".qwen/commands"
301-
Generate-Commands -Agent 'qwen' -Extension 'toml' -ArgFormat '{{args}}' -OutputDir $cmdDir -ScriptVariant $Script
301+
Generate-Commands -Agent 'qwen' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
302302
if (Test-Path "agent_templates/qwen/QWEN.md") {
303303
Copy-Item -Path "agent_templates/qwen/QWEN.md" -Destination (Join-Path $baseDir "QWEN.md")
304304
}

.github/workflows/scripts/create-release-packages.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ build_variant() {
154154
[[ -d templates ]] && { mkdir -p "$SPEC_DIR/templates"; find templates -type f -not -path "templates/commands/*" -not -name "vscode-settings.json" -exec cp --parents {} "$SPEC_DIR"/ \; ; echo "Copied templates -> .specify/templates"; }
155155

156156
# NOTE: We substitute {ARGS} internally. Outward tokens differ intentionally:
157-
# * Markdown/prompt (claude, copilot, cursor-agent, opencode): $ARGUMENTS
158-
# * TOML (gemini, qwen, tabnine): {{args}}
157+
# * Markdown/prompt (claude, copilot, cursor-agent, opencode, qwen): $ARGUMENTS
158+
# * TOML (gemini, tabnine): {{args}}
159159
# This keeps formats readable without extra abstraction.
160160

161161
case $agent in
@@ -180,7 +180,7 @@ build_variant() {
180180
generate_commands cursor-agent md "\$ARGUMENTS" "$base_dir/.cursor/commands" "$script" ;;
181181
qwen)
182182
mkdir -p "$base_dir/.qwen/commands"
183-
generate_commands qwen toml "{{args}}" "$base_dir/.qwen/commands" "$script"
183+
generate_commands qwen md "\$ARGUMENTS" "$base_dir/.qwen/commands" "$script"
184184
[[ -f agent_templates/qwen/QWEN.md ]] && cp agent_templates/qwen/QWEN.md "$base_dir/QWEN.md" ;;
185185
opencode)
186186
mkdir -p "$base_dir/.opencode/command"

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Specify supports multiple AI agents by generating agent-specific command files a
3535
| **Gemini CLI** | `.gemini/commands/` | TOML | `gemini` | Google's Gemini CLI |
3636
| **GitHub Copilot** | `.github/agents/` | Markdown | N/A (IDE-based) | GitHub Copilot in VS Code |
3737
| **Cursor** | `.cursor/commands/` | Markdown | `cursor-agent` | Cursor CLI |
38-
| **Qwen Code** | `.qwen/commands/` | TOML | `qwen` | Alibaba's Qwen Code CLI |
38+
| **Qwen Code** | `.qwen/commands/` | Markdown | `qwen` | Alibaba's Qwen Code CLI |
3939
| **opencode** | `.opencode/command/` | Markdown | `opencode` | opencode CLI |
4040
| **Codex CLI** | `.codex/commands/` | Markdown | `codex` | Codex CLI |
4141
| **Windsurf** | `.windsurf/workflows/` | Markdown | N/A (IDE-based) | Windsurf IDE workflows |
@@ -362,7 +362,7 @@ Command content with {SCRIPT} and $ARGUMENTS placeholders.
362362

363363
### TOML Format
364364

365-
Used by: Gemini, Qwen, Tabnine
365+
Used by: Gemini, Tabnine
366366

367367
```toml
368368
description = "Command description"

tests/test_ai_skills.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ def commands_dir_gemini(project_dir):
132132
return cmd_dir
133133

134134

135+
@pytest.fixture
136+
def commands_dir_qwen(project_dir):
137+
"""Create a populated .qwen/commands directory (Markdown format)."""
138+
cmd_dir = project_dir / ".qwen" / "commands"
139+
cmd_dir.mkdir(parents=True, exist_ok=True)
140+
for name in ["speckit.specify.md", "speckit.plan.md", "speckit.tasks.md"]:
141+
(cmd_dir / name).write_text(f"# {name}\nContent here\n")
142+
return cmd_dir
143+
144+
135145
# ===== _get_skills_dir Tests =====
136146

137147
class TestGetSkillsDir:
@@ -390,6 +400,28 @@ def test_non_md_commands_dir_falls_back(self, project_dir):
390400
# .toml commands should be untouched
391401
assert (cmds_dir / "speckit.specify.toml").exists()
392402

403+
def test_qwen_md_commands_dir_installs_skills(self, project_dir):
404+
"""Qwen now uses Markdown format; skills should install directly from .qwen/commands/."""
405+
cmds_dir = project_dir / ".qwen" / "commands"
406+
cmds_dir.mkdir(parents=True)
407+
(cmds_dir / "speckit.specify.md").write_text(
408+
"---\ndescription: Create or update the feature specification.\n---\n\n# Specify\n\nBody.\n"
409+
)
410+
(cmds_dir / "speckit.plan.md").write_text(
411+
"---\ndescription: Generate implementation plan.\n---\n\n# Plan\n\nBody.\n"
412+
)
413+
414+
result = install_ai_skills(project_dir, "qwen")
415+
416+
assert result is True
417+
skills_dir = project_dir / ".qwen" / "skills"
418+
assert skills_dir.exists()
419+
skill_dirs = [d.name for d in skills_dir.iterdir() if d.is_dir()]
420+
assert len(skill_dirs) >= 1
421+
# .md commands should be untouched
422+
assert (cmds_dir / "speckit.specify.md").exists()
423+
assert (cmds_dir / "speckit.plan.md").exists()
424+
393425
@pytest.mark.parametrize("agent_key", [k for k in AGENT_CONFIG.keys() if k != "generic"])
394426
def test_skills_install_for_all_agents(self, temp_dir, agent_key):
395427
"""install_ai_skills should produce skills for every configured agent."""
@@ -443,6 +475,15 @@ def test_existing_commands_preserved_gemini(self, project_dir, templates_dir, co
443475
remaining = list(commands_dir_gemini.glob("speckit.*"))
444476
assert len(remaining) == 3
445477

478+
def test_existing_commands_preserved_qwen(self, project_dir, templates_dir, commands_dir_qwen):
479+
"""install_ai_skills must NOT remove pre-existing .qwen/commands files."""
480+
assert len(list(commands_dir_qwen.glob("speckit.*"))) == 3
481+
482+
install_ai_skills(project_dir, "qwen")
483+
484+
remaining = list(commands_dir_qwen.glob("speckit.*"))
485+
assert len(remaining) == 3
486+
446487
def test_commands_dir_not_removed(self, project_dir, templates_dir, commands_dir_claude):
447488
"""install_ai_skills must not remove the commands directory."""
448489
install_ai_skills(project_dir, "claude")

0 commit comments

Comments
 (0)