Skip to content

fix(presets): preserve argument-hint in preset SKILL.md generation#2978

Open
jawwad-ali wants to merge 1 commit into
github:mainfrom
jawwad-ali:fix/preset-argument-hint
Open

fix(presets): preserve argument-hint in preset SKILL.md generation#2978
jawwad-ali wants to merge 1 commit into
github:mainfrom
jawwad-ali:fix/preset-argument-hint

Conversation

@jawwad-ali

Copy link
Copy Markdown
Contributor

Description

Follow-up to #2903 / #2916. That fix preserved argument-hint for extension commands when generating Claude SKILL.md; the same field is still dropped by the preset skill generators.

When a preset-provided command (or a preset override of an extension command) declares argument-hint: in its frontmatter, the generated .claude/skills/<name>/SKILL.md loses it, because the preset generators build the skill frontmatter via the shared CommandRegistrar.build_skill_frontmatter() (which only emits name / description / compatibility / metadata) and never forward argument-hint. It is also re-dropped on preset removal, when an overridden skill is restored from its source command — which silently undoes the #2916 extension fix in a real workflow (override an extension skill via a preset, then remove the preset).

Change

Rather than copy the #2916 inline block to each site, this factors the carry-over into one helper and reuses it:

Why it's safe (no behavior change for non-Claude agents or the core path)

  • inject_argument_hint is defined only on ClaudeIntegration (not inherited), so the hasattr gate adds the key for Claude only — build_skill_frontmatter's shared shape is byte-identical for every other agent (codex, kimi, …).
  • Core command templates carry no argument-hint (0 of 9 templates/commands/*.md), so the core-template restore site is a deliberate no-op.
  • The helper no-ops on a missing hint or a non-dict frontmatter.
  • The one structural tweak — at the override-restore site, the existing get_integration(...) lookup is hoisted a few lines above build_skill_frontmatter so the hint can be applied pre-serialization — is a pure reorder: get_integration is a side-effect-free registry lookup, the same value still feeds post_process_skill_content, and there is no import cycle (it was already a method-local import).

Scope

Kept focused per CONTRIBUTING. The init-time agents.py::render_skill_command generator also omits argument-hint, but it takes an agent_name (no integration object) and so needs separate plumbing — deferred to a follow-up rather than widening this PR.

Heads-up on overlapping PRs

Open PRs #2917 ("preserve non-ASCII characters in skill frontmatter") and #2103 touch the same presets.py skill-generation lines. The concerns are orthogonal — apply_argument_hint mutates the frontmatter dict before whatever dump function runs, so it composes cleanly with #2917's dump_frontmatter() swap. Happy to rebase whichever lands first.

Testing

  • Tested locally with uv run specify --help (exit 0)
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (N/A — generation-only frontmatter change; covered by the unit tests below)

Details (Windows 11, Python 3.12.12):

  • uvx ruff check src/ — All checks passed
  • uv run pytest tests/test_presets.py tests/test_extension_skills.py tests/integrations/test_integration_claude.py -q397 passed, 2 skipped (the fix(extensions): preserve argument-hint in extension Claude SKILL.md (#2903) #2916 extension tests pass unchanged, confirming the refactor is behavior-preserving)
  • Full suite uv run pytest3610 passed, 148 skipped, 14 failed; the 14 failures are pre-existing and environment-only (os.symlinkWinError 1314; creating symlinks needs elevation/Developer Mode on Windows), identical to clean main on this host and unrelated to this change.

New tests in tests/test_presets.py:

  • test_argument_hint_preserved_for_preset_command — installs a preset command with argument-hint and a long, folding description; asserts the generated SKILL.md frontmatter parses and retains both argument-hint and the full description. (Fails on main with KeyError: 'argument-hint'.)
  • test_argument_hint_not_added_for_non_claude_preset_command — same under a non-Claude skills agent (codex); asserts argument-hint is not present, proving the Claude-only gate.

Manual sanity: this changes only the emitted SKILL.md frontmatter — no slash command's behavior changes; generated files parse as valid YAML and surface the hint in Claude Code.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Developed with Claude Code (Claude Opus 4.8) under my direction — identifying the parallel preset drop sites, factoring the shared helper, writing the regression tests, and running the verification above. I personally confirmed the no-op behavior for non-Claude agents and the core path, verified the override-restore reorder is behavior-preserving, and reviewed the full diff before submitting. I'll disclose if any review responses are AI-assisted as well.

Preset-provided and extension-override commands that declare
`argument-hint:` in their frontmatter had it dropped from the generated
Claude SKILL.md, and it was re-dropped when a preset was removed and its
overridden skill restored. This is the preset-side analog of the
extension fix in github#2903 / github#2916.

Factor the argument-hint carry-over into a shared
CommandRegistrar.apply_argument_hint() helper and apply it at the four
preset skill-generation sites (register, reconcile override-restore, and
the core/extension unregister-restore paths). The extension path from
github#2916 now uses the same helper.

The helper writes argument-hint into the frontmatter dict before
serialization (so a folded multi-line description cannot be split into
invalid YAML) and only for integrations that support it (those exposing
inject_argument_hint -- currently Claude), leaving build_skill_frontmatter's
shared shape unchanged for every other agent. Core templates carry no
argument-hint, so the core-restore path is a no-op. No behavior change for
non-Claude agents or the core path.

Add regression tests covering a folding description (Claude) and the
non-Claude gate (codex).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jawwad-ali jawwad-ali requested a review from mnriem as a code owner June 14, 2026 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant