(
value: string,
plugin: { path: string; source?: string },
)
| 324 | * Used in MCP/LSP server command/args/env, hook commands, skill/agent content. |
| 325 | */ |
| 326 | export function substitutePluginVariables( |
| 327 | value: string, |
| 328 | plugin: { path: string; source?: string }, |
| 329 | ): string { |
| 330 | const normalize = (p: string) => |
| 331 | process.platform === 'win32' ? p.replace(/\\/g, '/') : p |
| 332 | let out = value.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, () => |
| 333 | normalize(plugin.path), |
| 334 | ) |
| 335 | // source can be absent (e.g. hooks where pluginRoot is a skill root without |
| 336 | // a plugin context). In that case ${CLAUDE_PLUGIN_DATA} is left literal. |
| 337 | if (plugin.source) { |
| 338 | const source = plugin.source |
| 339 | out = out.replace(/\$\{CLAUDE_PLUGIN_DATA\}/g, () => |
| 340 | normalize(getPluginDataDir(source)), |
| 341 | ) |
| 342 | } |
| 343 | return out |
| 344 | } |
| 345 | |
| 346 | /** |
| 347 | * Substitute ${user_config.KEY} with saved option values. |
no test coverage detected