feat(windsurf): add Windsurf as converter target with global scope support
Add `--to windsurf` target for the converter CLI with full spec compliance
per docs/specs/windsurf.md:
- Claude agents → Windsurf skills (skills/{name}/SKILL.md)
- Claude commands → Windsurf workflows (workflows/{name}.md, flat)
- Pass-through skills copy unchanged
- MCP servers → mcp_config.json (merged with existing, 0o600 permissions)
- Hooks skipped with warning, CLAUDE.md skipped
Global scope support via generic --scope flag (Windsurf as first adopter):
- --to windsurf defaults to global (~/.codeium/windsurf/)
- --scope workspace for project-level .windsurf/ output
- --output overrides scope-derived paths
Shared utilities extracted (resolveTargetOutputRoot, hasPotentialSecrets)
to eliminate duplication across CLI commands.
68 new tests (converter, writer, scope resolution).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { syncToPi } from "../sync/pi"
|
||||
import { syncToDroid } from "../sync/droid"
|
||||
import { syncToCopilot } from "../sync/copilot"
|
||||
import { expandHome } from "../utils/resolve-home"
|
||||
import { hasPotentialSecrets } from "../utils/secrets"
|
||||
|
||||
const validTargets = ["opencode", "codex", "pi", "droid", "copilot"] as const
|
||||
type SyncTarget = (typeof validTargets)[number]
|
||||
@@ -16,20 +17,6 @@ function isValidTarget(value: string): value is SyncTarget {
|
||||
return (validTargets as readonly string[]).includes(value)
|
||||
}
|
||||
|
||||
/** Check if any MCP servers have env vars that might contain secrets */
|
||||
function hasPotentialSecrets(mcpServers: Record<string, unknown>): boolean {
|
||||
const sensitivePatterns = /key|token|secret|password|credential|api_key/i
|
||||
for (const server of Object.values(mcpServers)) {
|
||||
const env = (server as { env?: Record<string, string> }).env
|
||||
if (env) {
|
||||
for (const key of Object.keys(env)) {
|
||||
if (sensitivePatterns.test(key)) return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function resolveOutputRoot(target: SyncTarget): string {
|
||||
switch (target) {
|
||||
case "opencode":
|
||||
|
||||
Reference in New Issue
Block a user