Files
pbakaus_impeccable/scripts/lib/transformers/providers.js
T
Forgeandplamb 5ce4a5c6b5 Add Hermes Agent as a supported provider
Impeccable now ships a Hermes-compatible bundle under dist/hermes/.hermes/skills/.
Hermes reads the Agent Skills spec as-is, so the bundle uses the four spec
frontmatter fields (name, description, version, license) plus metadata/compatibility
and drops the Claude/Codex-specific extensions Hermes would silently ignore.

The .hermes/skills/ tracked root and the regenerated pin.mjs mirrors will be
produced by .github/workflows/sync-generated-output.yml after this lands; per
AGENTS.md, generated harness churn stays out of feature PRs.

What a Hermes user gets:
- npx impeccable install --providers=hermes --scope=project writes
  .hermes/skills/impeccable/ into the cwd.
- npx impeccable install --providers=hermes --scope=user honors $HERMES_HOME,
  so a profile-scoped install (HERMES_HOME=~/.hermes/profiles/forge) lands in
  the active profile's skills dir, not the default ~/.hermes/. Cross-home
  HERMES_HOME inheritance is ignored so test isolation holds.
- /impeccable registers as a Hermes slash command and routes sub-commands via
  the Commands table in the skill body, since user-invocable / argument-hint
  are not honored by Hermes' skill loader.

What a Hermes user does NOT get, and why:
- No hook surface. Impeccable's PostToolUse/Stop anti-pattern detector on
  Claude/Codex/Cursor/Grok/GitHub does not translate to Hermes, which has no
  equivalent tool event lifecycle. The skill body still ships.
- No writeOpenAIMetadata, agentFormat, or emitHooks. Hermes has no per-skill
  tool ACL, no subagent on-disk format, and no hooks.json equivalent.

Verified end-to-end with hermes-agent v0.18.2: /impeccable polish and
/impeccable critique both load reference/<command>.md and return the
documented first step. parse_frontmatter accepts the generated SKILL.md,
scan_skill_commands registers /impeccable, and the full default test suite
passes (267/267 in the critical files; 0 fail across all suites).
2026-08-06 00:03:12 -07:00

180 lines
6.7 KiB
JavaScript

/**
* Provider configurations for the transformer factory.
*
* Each config specifies:
* - provider: key into PROVIDER_PLACEHOLDERS (e.g. 'claude-code')
* - configDir: dot-directory name (e.g. '.claude')
* - displayName: human-readable name for log output (e.g. 'Claude Code')
* - providerTags: markdown block tags kept for this target (e.g. <codex>...</codex>)
* - frontmatterFields: which optional fields to emit beyond name + description
* - bodyTransform: optional function (body, skill) => transformed body
*/
export const PROVIDERS = {
cursor: {
provider: 'cursor',
providerTags: ['cursor'],
configDir: '.cursor',
displayName: 'Cursor',
frontmatterFields: ['license', 'compatibility', 'metadata'],
// Cursor subagents: `.cursor/agents/<name>.md` at repo level,
// `~/.cursor/agents/` at user level. Project agents take precedence over
// user ones, so installs simply overwrite on update.
agentFormat: 'cursor-md',
emitHooks: 'cursor',
// Cursor reads `.cursor/hooks.json`, not `.cursor/hooks/hooks.json`.
hooksManifestRel: 'hooks.json',
},
'claude-code': {
provider: 'claude-code',
providerTags: ['claude-code', 'claude'],
configDir: '.claude',
displayName: 'Claude Code',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
agentFormat: 'claude-md',
emitHooks: 'claude',
// Project-local Claude Code hooks live in `.claude/settings.json`.
hooksManifestRel: 'settings.json',
},
gemini: {
provider: 'gemini',
providerTags: ['gemini'],
configDir: '.gemini',
displayName: 'Gemini',
frontmatterFields: [],
},
codex: {
provider: 'codex',
providerTags: ['codex'],
configDir: '.codex',
displayName: 'Codex',
frontmatterFields: [],
writeOpenAIMetadata: true,
// No agentFormat: the Codex subagent ships nested inside the skill's own
// agents/ folder (see CODEX_SKILL_PROVIDERS in factory.js), which Codex
// auto-discovers on install. No top-level .codex/agents/ sidecar is emitted.
emitHooks: 'codex',
// Codex discovers project-local hooks at `.codex/hooks.json`.
hooksManifestRel: 'hooks.json',
},
agents: {
provider: 'agents',
providerTags: ['agents', 'codex'],
configDir: '.agents',
displayName: 'Codex Repo Skills',
placeholderProvider: 'codex',
frontmatterFields: [],
writeOpenAIMetadata: true,
},
github: {
provider: 'github',
providerTags: ['github'],
configDir: '.github',
displayName: 'GitHub Copilot',
placeholderProvider: 'agents',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata'],
// Copilot custom agents: `.github/agents/<name>.agent.md` at repo level,
// `~/.copilot/agents/` at user level (the CLI installer handles placement).
// The degraded/ fallbacks still ship for Copilot surfaces where the model
// fails to delegate; the .agent.md files are the real subagent path.
agentFormat: 'copilot-agent-md',
emitHooks: 'github',
// GitHub Copilot discovers repo-level hooks under `.github/hooks/*.json`.
hooksManifestRel: 'hooks/impeccable.json',
},
kiro: {
provider: 'kiro',
providerTags: ['kiro'],
configDir: '.kiro',
displayName: 'Kiro',
frontmatterFields: ['license', 'compatibility', 'metadata'],
},
opencode: {
provider: 'opencode',
providerTags: ['opencode'],
configDir: '.opencode',
displayName: 'OpenCode',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
},
pi: {
provider: 'pi',
providerTags: ['pi'],
configDir: '.pi',
displayName: 'Pi',
frontmatterFields: ['license', 'compatibility', 'metadata', 'allowed-tools'],
},
qoder: {
provider: 'qoder',
providerTags: ['qoder'],
configDir: '.qoder',
displayName: 'Qoder',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
},
'trae-cn': {
provider: 'trae-cn',
providerTags: ['trae-cn', 'trae'],
configDir: '.trae-cn',
displayName: 'Trae China',
placeholderProvider: 'trae',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata'],
},
trae: {
provider: 'trae',
providerTags: ['trae'],
configDir: '.trae',
displayName: 'Trae',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata'],
},
'rovo-dev': {
provider: 'rovo-dev',
providerTags: ['rovo-dev'],
configDir: '.rovodev',
displayName: 'Rovo Dev',
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
},
vibe: {
provider: 'vibe',
providerTags: ['vibe'],
configDir: '.vibe',
displayName: 'Mistral Vibe',
frontmatterFields: ['user-invocable', 'license', 'compatibility', 'metadata', 'allowed-tools'],
},
grok: {
provider: 'grok',
providerTags: ['grok'],
configDir: '.grok',
displayName: 'Grok Build',
// Grok's skill frontmatter matches the Agent Skills spec plus Claude-style
// extensions (user-invocable, argument-hint, allowed-tools, model, effort).
// See https://docs.x.ai/build/features/skills-plugins-marketplaces and
// ~/.grok/docs/user-guide/08-skills.md.
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
// Project/user agents are markdown with YAML frontmatter (Claude-compatible).
agentFormat: 'claude-md',
emitHooks: 'grok',
// Grok discovers project hooks from `.grok/hooks/*.json` (not a single
// settings.json). Claude tool-name matchers alias to Grok tools.
hooksManifestRel: 'hooks/impeccable.json',
},
antigravity: {
provider: 'antigravity',
providerTags: ['antigravity'],
configDir: '.agent',
displayName: 'Antigravity',
frontmatterFields: ['license', 'compatibility', 'metadata', 'allowed-tools'],
},
hermes: {
provider: 'hermes',
providerTags: ['hermes'],
configDir: '.hermes',
displayName: 'Hermes Agent',
// Hermes ships the Agent Skills spec as-is. The optional fields below
// (license, compatibility, metadata) are spec-defined; harness-specific
// extensions (user-invocable, argument-hint, allowed-tools) are NOT
// recognized by the Hermes skill loader and would be silently ignored.
// Hermes also has no hook surface, no equivalent of Claude's slash
// commands, and no per-skill tool ACL -- so no emitHooks, no agentFormat,
// no writeOpenAIMetadata. See hermes-agent/SKILL.md "Skills" section.
frontmatterFields: ['license', 'compatibility', 'metadata'],
},
};