From 9a800763b4ed18088e298db6cecc42c27786425b Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 8 Jun 2026 17:48:42 +0000 Subject: [PATCH 1/2] Fix colon in command filenames for Windows compatibility Replace colons with dashes in generated command filenames to avoid Windows filesystem restrictions (colon is reserved character). Also rename existing colon-named files: - automation:create.md -> automation-create.md - slack-monitor:poll.md -> slack-monitor-poll.md - github-monitor:poll.md -> github-monitor-poll.md - And 5 more similar renames Closes #230 --- scripts/sync_extensions.py | 3 ++- .../commands/{pr-reviewer:setup.md => pr-reviewer-setup.md} | 0 .../{github-monitor:poll.md => github-monitor-poll.md} | 0 .../{incident-retro:setup.md => incident-retro-setup.md} | 0 .../{linear-triage:setup.md => linear-triage-setup.md} | 0 .../commands/{automation:create.md => automation-create.md} | 0 .../{research-brief:setup.md => research-brief-setup.md} | 0 .../commands/{slack-monitor:poll.md => slack-monitor-poll.md} | 0 .../{standup-digest:setup.md => standup-digest-setup.md} | 0 9 files changed, 2 insertions(+), 1 deletion(-) rename skills/github-pr-reviewer/commands/{pr-reviewer:setup.md => pr-reviewer-setup.md} (100%) rename skills/github-repo-monitor/commands/{github-monitor:poll.md => github-monitor-poll.md} (100%) rename skills/incident-retrospective/commands/{incident-retro:setup.md => incident-retro-setup.md} (100%) rename skills/linear-triage/commands/{linear-triage:setup.md => linear-triage-setup.md} (100%) rename skills/openhands-automation/commands/{automation:create.md => automation-create.md} (100%) rename skills/research-brief/commands/{research-brief:setup.md => research-brief-setup.md} (100%) rename skills/slack-channel-monitor/commands/{slack-monitor:poll.md => slack-monitor-poll.md} (100%) rename skills/slack-standup-digest/commands/{standup-digest:setup.md => standup-digest-setup.md} (100%) diff --git a/scripts/sync_extensions.py b/scripts/sync_extensions.py index 0a6ccacc..040ff241 100644 --- a/scripts/sync_extensions.py +++ b/scripts/sync_extensions.py @@ -143,7 +143,8 @@ def collect_needed_commands() -> list[CommandSpec]: meta = parse_frontmatter(skill_md.read_text()) desc = str(meta.get("description", "")) for trigger in slash_triggers(meta): - cmd_name = trigger.lstrip("/") + # Replace colons with dashes for cross-platform filename compatibility + cmd_name = trigger.lstrip("/").replace(":", "-") cmd_path = skill_dir / "commands" / f"{cmd_name}.md" needed.append(CommandSpec(path=cmd_path, trigger=trigger, description=desc)) return needed diff --git a/skills/github-pr-reviewer/commands/pr-reviewer:setup.md b/skills/github-pr-reviewer/commands/pr-reviewer-setup.md similarity index 100% rename from skills/github-pr-reviewer/commands/pr-reviewer:setup.md rename to skills/github-pr-reviewer/commands/pr-reviewer-setup.md diff --git a/skills/github-repo-monitor/commands/github-monitor:poll.md b/skills/github-repo-monitor/commands/github-monitor-poll.md similarity index 100% rename from skills/github-repo-monitor/commands/github-monitor:poll.md rename to skills/github-repo-monitor/commands/github-monitor-poll.md diff --git a/skills/incident-retrospective/commands/incident-retro:setup.md b/skills/incident-retrospective/commands/incident-retro-setup.md similarity index 100% rename from skills/incident-retrospective/commands/incident-retro:setup.md rename to skills/incident-retrospective/commands/incident-retro-setup.md diff --git a/skills/linear-triage/commands/linear-triage:setup.md b/skills/linear-triage/commands/linear-triage-setup.md similarity index 100% rename from skills/linear-triage/commands/linear-triage:setup.md rename to skills/linear-triage/commands/linear-triage-setup.md diff --git a/skills/openhands-automation/commands/automation:create.md b/skills/openhands-automation/commands/automation-create.md similarity index 100% rename from skills/openhands-automation/commands/automation:create.md rename to skills/openhands-automation/commands/automation-create.md diff --git a/skills/research-brief/commands/research-brief:setup.md b/skills/research-brief/commands/research-brief-setup.md similarity index 100% rename from skills/research-brief/commands/research-brief:setup.md rename to skills/research-brief/commands/research-brief-setup.md diff --git a/skills/slack-channel-monitor/commands/slack-monitor:poll.md b/skills/slack-channel-monitor/commands/slack-monitor-poll.md similarity index 100% rename from skills/slack-channel-monitor/commands/slack-monitor:poll.md rename to skills/slack-channel-monitor/commands/slack-monitor-poll.md diff --git a/skills/slack-standup-digest/commands/standup-digest:setup.md b/skills/slack-standup-digest/commands/standup-digest-setup.md similarity index 100% rename from skills/slack-standup-digest/commands/standup-digest:setup.md rename to skills/slack-standup-digest/commands/standup-digest-setup.md From 84a2f6c34eb86bc189415b556274196a1b3236bb Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 8 Jun 2026 17:56:25 +0000 Subject: [PATCH 2/2] test: cover colon command filename normalization Co-authored-by: openhands --- tests/test_sync_extensions.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_sync_extensions.py b/tests/test_sync_extensions.py index 6c7b5e67..8dfb703d 100644 --- a/tests/test_sync_extensions.py +++ b/tests/test_sync_extensions.py @@ -198,6 +198,20 @@ def test_paths_are_under_commands_dir(self): assert spec.path.parent.name == "commands" assert spec.path.suffix == ".md" + def test_colon_triggers_are_normalized_for_filenames(self, tmp_path, monkeypatch): + skill_dir = tmp_path / "skills" / "test-skill" + skill_dir.mkdir(parents=True) + (skill_dir / "SKILL.md").write_text( + "---\nname: test-skill\ndescription: Test\ntriggers:\n - /test:command\n---\nBody\n" + ) + + monkeypatch.setattr("sync_extensions.SKILL_DIRS", [tmp_path / "skills"]) + + specs = collect_needed_commands() + assert [spec.path.relative_to(tmp_path).as_posix() for spec in specs] == [ + "skills/test-skill/commands/test-command.md" + ] + # ── load_marketplaces ────────────────────────────────────────────────