I'm building an extension (cc-spex, an SDD methodology toolkit on top of spec-kit) and ran into a portability challenge. Spec-kit's extension system handles format conversion and path routing across 28 agent harnesses well. But when my command content needs to reference agent-specific capabilities ("ask the user a question," "spawn a subagent"), I end up hardcoding tool names for one agent.
Before I work around this on my side, I wanted to ask: is there an existing mechanism for making extension command content portable across agents? If not, would it make sense to add one?
What I'm running into
Spec-kit solves the structural layer well (format conversion, path routing, argument placeholders). What I'm struggling with is the content layer. There are several categories of agent-specific behavior that don't seem to have a portable abstraction:
-
When a command needs to ask "which approach do you prefer?", it needs to know the right prompt tool: AskUserQuestion on Claude Code, question on OpenCode, or nothing on Codex. I haven't found a way to express "ask the user" generically.
-
Some workflows fan out to subagents for parallel work (code review across dimensions, research from multiple angles). On Claude Code that's the Agent tool, on OpenCode it's Task, and on many agents it simply doesn't exist. Ideally a command could say "if subagents are available, fan out; otherwise, run sequentially."
-
Workflow discipline (e.g., blocking implementation until a spec is reviewed) depends on hooks that vary widely: PreToolUse on Claude Code, tool.execute.before on OpenCode, or nothing at all. An extension currently can't discover what enforcement level the agent supports.
-
Extensions bundle helper scripts that commands invoke at runtime. The install location varies by agent (~/.claude/plugins/, ~/.opencode/plugins/, etc.), and there's no portable way for a command to reference its own script directory.
-
Some workflows benefit from clearing conversation context between phases. Claude Code has /clear for this, but most agents don't have an equivalent.
These come up in any extension that goes beyond "run a script and report." A code review extension that wants to ask "Fix all / Let me pick / Skip," a CI extension that parallelizes test runs, a workflow extension that enforces stage ordering. In my case, I audited cc-spex and found 46 agent-specific references across its commands, which effectively makes it single-agent despite spec-kit supporting 28.
Ideas (if this doesn't exist yet)
I looked at the source and noticed building blocks that could support this.
Each IntegrationBase subclass could declare what the agent supports, following the existing _feature_capabilities() pattern but at the integration level:
capabilities = {
"interactive_prompts": {"tool": "AskUserQuestion", "structured": True, "multi_select": True},
"subagents": {"tool": "Agent", "background": True, "worktree_isolation": True},
"process_enforcement": {"hooks": True, "pre_tool_gate": True},
"context_clearing": {"command": "/clear"},
}
With capability metadata in place, command templates could use conditional blocks that get resolved at install time, so each agent ends up with optimized instructions rather than generic placeholders:
{{#if interactive_prompts}}
Present findings using {{tool:interactive_prompts}} with these options:
- "Fix all"
- "Let me pick"
{{else}}
List findings and proceed with fixing all.
{{/if}}
post_process_skill_content() already does per-agent content transformation, but only for skills-format agents. Could this be extended to all format types via a post_process_command_content() on IntegrationBase?
For script discovery, something like __PLUGIN_ROOT__ in process_template() would let extensions write "__PLUGIN_ROOT__/scripts/script.sh" instead of hardcoding agent-specific search paths.
I also noticed the workflow expressions engine (expressions.py) already implements a safe Jinja2 subset with conditionals, though it's currently only used by the workflow YAML engine. Could that be reused here?
Questions
- Does something like this already exist that I'm overlooking?
- If not, would a capability system be a welcome addition, or is there a simpler approach?
- Would capability declarations fit better as a class attribute or in
registrar_config?
[edited, my agent was too quick 😬 ]
I'm building an extension (cc-spex, an SDD methodology toolkit on top of spec-kit) and ran into a portability challenge. Spec-kit's extension system handles format conversion and path routing across 28 agent harnesses well. But when my command content needs to reference agent-specific capabilities ("ask the user a question," "spawn a subagent"), I end up hardcoding tool names for one agent.
Before I work around this on my side, I wanted to ask: is there an existing mechanism for making extension command content portable across agents? If not, would it make sense to add one?
What I'm running into
Spec-kit solves the structural layer well (format conversion, path routing, argument placeholders). What I'm struggling with is the content layer. There are several categories of agent-specific behavior that don't seem to have a portable abstraction:
When a command needs to ask "which approach do you prefer?", it needs to know the right prompt tool:
AskUserQuestionon Claude Code,questionon OpenCode, or nothing on Codex. I haven't found a way to express "ask the user" generically.Some workflows fan out to subagents for parallel work (code review across dimensions, research from multiple angles). On Claude Code that's the
Agenttool, on OpenCode it'sTask, and on many agents it simply doesn't exist. Ideally a command could say "if subagents are available, fan out; otherwise, run sequentially."Workflow discipline (e.g., blocking implementation until a spec is reviewed) depends on hooks that vary widely:
PreToolUseon Claude Code,tool.execute.beforeon OpenCode, or nothing at all. An extension currently can't discover what enforcement level the agent supports.Extensions bundle helper scripts that commands invoke at runtime. The install location varies by agent (
~/.claude/plugins/,~/.opencode/plugins/, etc.), and there's no portable way for a command to reference its own script directory.Some workflows benefit from clearing conversation context between phases. Claude Code has
/clearfor this, but most agents don't have an equivalent.These come up in any extension that goes beyond "run a script and report." A code review extension that wants to ask "Fix all / Let me pick / Skip," a CI extension that parallelizes test runs, a workflow extension that enforces stage ordering. In my case, I audited cc-spex and found 46 agent-specific references across its commands, which effectively makes it single-agent despite spec-kit supporting 28.
Ideas (if this doesn't exist yet)
I looked at the source and noticed building blocks that could support this.
Each
IntegrationBasesubclass could declare what the agent supports, following the existing_feature_capabilities()pattern but at the integration level:With capability metadata in place, command templates could use conditional blocks that get resolved at install time, so each agent ends up with optimized instructions rather than generic placeholders:
{{#if interactive_prompts}} Present findings using {{tool:interactive_prompts}} with these options: - "Fix all" - "Let me pick" {{else}} List findings and proceed with fixing all. {{/if}}post_process_skill_content()already does per-agent content transformation, but only for skills-format agents. Could this be extended to all format types via apost_process_command_content()onIntegrationBase?For script discovery, something like
__PLUGIN_ROOT__inprocess_template()would let extensions write"__PLUGIN_ROOT__/scripts/script.sh"instead of hardcoding agent-specific search paths.I also noticed the workflow expressions engine (
expressions.py) already implements a safe Jinja2 subset with conditionals, though it's currently only used by the workflow YAML engine. Could that be reused here?Questions
registrar_config?[edited, my agent was too quick 😬 ]