compound-engineering-pi 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +124 -0
- package/bin/compound-engineering-pi +12 -0
- package/bin/compound-plugin +12 -0
- package/compound-engineering-pi +12 -0
- package/compound-plugin +5 -0
- package/docs/pi.md +152 -0
- package/extensions/compound-engineering-compat.ts +452 -0
- package/package.json +84 -0
- package/pi-resources/compound-engineering/mcporter.json +7 -0
- package/plugins/coding-tutor/.claude-plugin/plugin.json +9 -0
- package/plugins/coding-tutor/README.md +37 -0
- package/plugins/coding-tutor/commands/quiz-me.md +1 -0
- package/plugins/coding-tutor/commands/sync-tutorials.md +25 -0
- package/plugins/coding-tutor/commands/teach-me.md +1 -0
- package/plugins/coding-tutor/skills/coding-tutor/SKILL.md +214 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/create_tutorial.py +207 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/index_tutorials.py +193 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/quiz_priority.py +190 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/setup_tutorials.py +118 -0
- package/plugins/compound-engineering/.claude-plugin/plugin.json +33 -0
- package/plugins/compound-engineering/CHANGELOG.md +457 -0
- package/plugins/compound-engineering/CLAUDE.md +89 -0
- package/plugins/compound-engineering/LICENSE +21 -0
- package/plugins/compound-engineering/README.md +232 -0
- package/plugins/compound-engineering/agents/design/design-implementation-reviewer.md +109 -0
- package/plugins/compound-engineering/agents/design/design-iterator.md +224 -0
- package/plugins/compound-engineering/agents/design/figma-design-sync.md +190 -0
- package/plugins/compound-engineering/agents/docs/ankane-readme-writer.md +65 -0
- package/plugins/compound-engineering/agents/research/best-practices-researcher.md +126 -0
- package/plugins/compound-engineering/agents/research/framework-docs-researcher.md +106 -0
- package/plugins/compound-engineering/agents/research/git-history-analyzer.md +59 -0
- package/plugins/compound-engineering/agents/research/learnings-researcher.md +264 -0
- package/plugins/compound-engineering/agents/research/repo-research-analyst.md +135 -0
- package/plugins/compound-engineering/agents/review/agent-native-reviewer.md +261 -0
- package/plugins/compound-engineering/agents/review/architecture-strategist.md +67 -0
- package/plugins/compound-engineering/agents/review/code-simplicity-reviewer.md +101 -0
- package/plugins/compound-engineering/agents/review/data-integrity-guardian.md +85 -0
- package/plugins/compound-engineering/agents/review/data-migration-expert.md +112 -0
- package/plugins/compound-engineering/agents/review/deployment-verification-agent.md +174 -0
- package/plugins/compound-engineering/agents/review/dhh-rails-reviewer.md +66 -0
- package/plugins/compound-engineering/agents/review/julik-frontend-races-reviewer.md +221 -0
- package/plugins/compound-engineering/agents/review/kieran-python-reviewer.md +133 -0
- package/plugins/compound-engineering/agents/review/kieran-rails-reviewer.md +115 -0
- package/plugins/compound-engineering/agents/review/kieran-typescript-reviewer.md +124 -0
- package/plugins/compound-engineering/agents/review/pattern-recognition-specialist.md +72 -0
- package/plugins/compound-engineering/agents/review/performance-oracle.md +137 -0
- package/plugins/compound-engineering/agents/review/schema-drift-detector.md +154 -0
- package/plugins/compound-engineering/agents/review/security-sentinel.md +114 -0
- package/plugins/compound-engineering/agents/workflow/bug-reproduction-validator.md +82 -0
- package/plugins/compound-engineering/agents/workflow/every-style-editor.md +64 -0
- package/plugins/compound-engineering/agents/workflow/lint.md +16 -0
- package/plugins/compound-engineering/agents/workflow/pr-comment-resolver.md +84 -0
- package/plugins/compound-engineering/agents/workflow/spec-flow-analyzer.md +134 -0
- package/plugins/compound-engineering/commands/agent-native-audit.md +278 -0
- package/plugins/compound-engineering/commands/changelog.md +138 -0
- package/plugins/compound-engineering/commands/create-agent-skill.md +9 -0
- package/plugins/compound-engineering/commands/deepen-plan.md +546 -0
- package/plugins/compound-engineering/commands/deploy-docs.md +113 -0
- package/plugins/compound-engineering/commands/feature-video.md +342 -0
- package/plugins/compound-engineering/commands/generate_command.md +163 -0
- package/plugins/compound-engineering/commands/heal-skill.md +143 -0
- package/plugins/compound-engineering/commands/lfg.md +20 -0
- package/plugins/compound-engineering/commands/release-docs.md +212 -0
- package/plugins/compound-engineering/commands/report-bug.md +151 -0
- package/plugins/compound-engineering/commands/reproduce-bug.md +100 -0
- package/plugins/compound-engineering/commands/resolve_parallel.md +35 -0
- package/plugins/compound-engineering/commands/resolve_todo_parallel.md +37 -0
- package/plugins/compound-engineering/commands/slfg.md +32 -0
- package/plugins/compound-engineering/commands/technical_review.md +8 -0
- package/plugins/compound-engineering/commands/test-browser.md +339 -0
- package/plugins/compound-engineering/commands/test-xcode.md +332 -0
- package/plugins/compound-engineering/commands/triage.md +311 -0
- package/plugins/compound-engineering/commands/workflows/brainstorm.md +124 -0
- package/plugins/compound-engineering/commands/workflows/compound.md +239 -0
- package/plugins/compound-engineering/commands/workflows/plan.md +551 -0
- package/plugins/compound-engineering/commands/workflows/review.md +526 -0
- package/plugins/compound-engineering/commands/workflows/work.md +433 -0
- package/plugins/compound-engineering/skills/agent-browser/SKILL.md +223 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/SKILL.md +435 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/action-parity-discipline.md +409 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/agent-execution-patterns.md +467 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/agent-native-testing.md +582 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/architecture-patterns.md +478 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/dynamic-context-injection.md +338 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/files-universal-interface.md +301 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +359 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/mcp-tool-design.md +506 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/mobile-patterns.md +871 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/product-implications.md +443 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +317 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/self-modification.md +269 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/shared-workspace-architecture.md +680 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/system-prompt-design.md +250 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/SKILL.md +184 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/resources.md +119 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/plugins/compound-engineering/skills/brainstorming/SKILL.md +190 -0
- package/plugins/compound-engineering/skills/compound-docs/SKILL.md +511 -0
- package/plugins/compound-engineering/skills/compound-docs/assets/critical-pattern-template.md +34 -0
- package/plugins/compound-engineering/skills/compound-docs/assets/resolution-template.md +93 -0
- package/plugins/compound-engineering/skills/compound-docs/references/yaml-schema.md +65 -0
- package/plugins/compound-engineering/skills/compound-docs/schema.yaml +176 -0
- package/plugins/compound-engineering/skills/create-agent-skills/SKILL.md +275 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/api-security.md +226 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/be-clear-and-direct.md +531 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/best-practices.md +404 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/common-patterns.md +595 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/core-principles.md +437 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/executable-code.md +175 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/iteration-and-testing.md +474 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/official-spec.md +134 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/recommended-structure.md +168 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/skill-structure.md +152 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/using-scripts.md +113 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/using-templates.md +112 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/workflows-and-validation.md +510 -0
- package/plugins/compound-engineering/skills/create-agent-skills/templates/router-skill.md +73 -0
- package/plugins/compound-engineering/skills/create-agent-skills/templates/simple-skill.md +33 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-reference.md +96 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-script.md +93 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-template.md +74 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-workflow.md +120 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/audit-skill.md +138 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/create-domain-expertise-skill.md +605 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/create-new-skill.md +191 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/get-guidance.md +121 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/upgrade-to-router.md +161 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/verify-skill.md +204 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/SKILL.md +185 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/architecture.md +653 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/controllers.md +303 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/frontend.md +510 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/gems.md +266 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/models.md +359 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/testing.md +338 -0
- package/plugins/compound-engineering/skills/document-review/SKILL.md +87 -0
- package/plugins/compound-engineering/skills/dspy-ruby/SKILL.md +737 -0
- package/plugins/compound-engineering/skills/dspy-ruby/assets/config-template.rb +187 -0
- package/plugins/compound-engineering/skills/dspy-ruby/assets/module-template.rb +300 -0
- package/plugins/compound-engineering/skills/dspy-ruby/assets/signature-template.rb +221 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/core-concepts.md +674 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/observability.md +366 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/optimization.md +603 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/providers.md +418 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/toolsets.md +502 -0
- package/plugins/compound-engineering/skills/every-style-editor/SKILL.md +134 -0
- package/plugins/compound-engineering/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/plugins/compound-engineering/skills/file-todos/SKILL.md +252 -0
- package/plugins/compound-engineering/skills/file-todos/assets/todo-template.md +155 -0
- package/plugins/compound-engineering/skills/frontend-design/SKILL.md +42 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/SKILL.md +237 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/requirements.txt +2 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/compose_images.py +157 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/edit_image.py +144 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/gemini_images.py +263 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/generate_image.py +133 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/multi_turn_chat.py +216 -0
- package/plugins/compound-engineering/skills/git-worktree/SKILL.md +302 -0
- package/plugins/compound-engineering/skills/git-worktree/scripts/worktree-manager.sh +337 -0
- package/plugins/compound-engineering/skills/orchestrating-swarms/SKILL.md +1718 -0
- package/plugins/compound-engineering/skills/rclone/SKILL.md +150 -0
- package/plugins/compound-engineering/skills/rclone/scripts/check_setup.sh +60 -0
- package/plugins/compound-engineering/skills/resolve-pr-parallel/SKILL.md +89 -0
- package/plugins/compound-engineering/skills/resolve-pr-parallel/scripts/get-pr-comments +68 -0
- package/plugins/compound-engineering/skills/resolve-pr-parallel/scripts/resolve-pr-thread +23 -0
- package/plugins/compound-engineering/skills/skill-creator/SKILL.md +210 -0
- package/plugins/compound-engineering/skills/skill-creator/scripts/init_skill.py +303 -0
- package/plugins/compound-engineering/skills/skill-creator/scripts/package_skill.py +110 -0
- package/plugins/compound-engineering/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/prompts/deepen-plan.md +549 -0
- package/prompts/feature-video.md +341 -0
- package/prompts/resolve_todo_parallel.md +36 -0
- package/prompts/test-browser.md +342 -0
- package/prompts/workflows-brainstorm.md +123 -0
- package/prompts/workflows-compound.md +238 -0
- package/prompts/workflows-plan.md +550 -0
- package/prompts/workflows-review.md +529 -0
- package/prompts/workflows-work.md +432 -0
- package/skills/agent-browser/SKILL.md +223 -0
- package/skills/agent-native-architecture/SKILL.md +435 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +409 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +467 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +582 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +478 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +338 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +301 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +359 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +506 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +871 -0
- package/skills/agent-native-architecture/references/product-implications.md +443 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +317 -0
- package/skills/agent-native-architecture/references/self-modification.md +269 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +680 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +250 -0
- package/skills/agent-native-reviewer/SKILL.md +260 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +184 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +119 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/ankane-readme-writer/SKILL.md +63 -0
- package/skills/architecture-strategist/SKILL.md +66 -0
- package/skills/best-practices-researcher/SKILL.md +125 -0
- package/skills/brainstorming/SKILL.md +190 -0
- package/skills/bug-reproduction-validator/SKILL.md +81 -0
- package/skills/code-simplicity-reviewer/SKILL.md +100 -0
- package/skills/compound-docs/SKILL.md +511 -0
- package/skills/compound-docs/assets/critical-pattern-template.md +34 -0
- package/skills/compound-docs/assets/resolution-template.md +93 -0
- package/skills/compound-docs/references/yaml-schema.md +65 -0
- package/skills/compound-docs/schema.yaml +176 -0
- package/skills/create-agent-skills/SKILL.md +275 -0
- package/skills/create-agent-skills/references/api-security.md +226 -0
- package/skills/create-agent-skills/references/be-clear-and-direct.md +531 -0
- package/skills/create-agent-skills/references/best-practices.md +404 -0
- package/skills/create-agent-skills/references/common-patterns.md +595 -0
- package/skills/create-agent-skills/references/core-principles.md +437 -0
- package/skills/create-agent-skills/references/executable-code.md +175 -0
- package/skills/create-agent-skills/references/iteration-and-testing.md +474 -0
- package/skills/create-agent-skills/references/official-spec.md +134 -0
- package/skills/create-agent-skills/references/recommended-structure.md +168 -0
- package/skills/create-agent-skills/references/skill-structure.md +152 -0
- package/skills/create-agent-skills/references/using-scripts.md +113 -0
- package/skills/create-agent-skills/references/using-templates.md +112 -0
- package/skills/create-agent-skills/references/workflows-and-validation.md +510 -0
- package/skills/create-agent-skills/templates/router-skill.md +73 -0
- package/skills/create-agent-skills/templates/simple-skill.md +33 -0
- package/skills/create-agent-skills/workflows/add-reference.md +96 -0
- package/skills/create-agent-skills/workflows/add-script.md +93 -0
- package/skills/create-agent-skills/workflows/add-template.md +74 -0
- package/skills/create-agent-skills/workflows/add-workflow.md +120 -0
- package/skills/create-agent-skills/workflows/audit-skill.md +138 -0
- package/skills/create-agent-skills/workflows/create-domain-expertise-skill.md +605 -0
- package/skills/create-agent-skills/workflows/create-new-skill.md +191 -0
- package/skills/create-agent-skills/workflows/get-guidance.md +121 -0
- package/skills/create-agent-skills/workflows/upgrade-to-router.md +161 -0
- package/skills/create-agent-skills/workflows/verify-skill.md +204 -0
- package/skills/data-integrity-guardian/SKILL.md +84 -0
- package/skills/data-migration-expert/SKILL.md +111 -0
- package/skills/deployment-verification-agent/SKILL.md +173 -0
- package/skills/design-implementation-reviewer/SKILL.md +107 -0
- package/skills/design-iterator/SKILL.md +222 -0
- package/skills/dhh-rails-reviewer/SKILL.md +65 -0
- package/skills/dhh-rails-style/SKILL.md +185 -0
- package/skills/dhh-rails-style/references/architecture.md +653 -0
- package/skills/dhh-rails-style/references/controllers.md +303 -0
- package/skills/dhh-rails-style/references/frontend.md +510 -0
- package/skills/dhh-rails-style/references/gems.md +266 -0
- package/skills/dhh-rails-style/references/models.md +359 -0
- package/skills/dhh-rails-style/references/testing.md +338 -0
- package/skills/document-review/SKILL.md +87 -0
- package/skills/dspy-ruby/SKILL.md +737 -0
- package/skills/dspy-ruby/assets/config-template.rb +187 -0
- package/skills/dspy-ruby/assets/module-template.rb +300 -0
- package/skills/dspy-ruby/assets/signature-template.rb +221 -0
- package/skills/dspy-ruby/references/core-concepts.md +674 -0
- package/skills/dspy-ruby/references/observability.md +366 -0
- package/skills/dspy-ruby/references/optimization.md +603 -0
- package/skills/dspy-ruby/references/providers.md +418 -0
- package/skills/dspy-ruby/references/toolsets.md +502 -0
- package/skills/every-style-editor/SKILL.md +134 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/every-style-editor-2/SKILL.md +62 -0
- package/skills/figma-design-sync/SKILL.md +188 -0
- package/skills/file-todos/SKILL.md +252 -0
- package/skills/file-todos/assets/todo-template.md +155 -0
- package/skills/framework-docs-researcher/SKILL.md +105 -0
- package/skills/frontend-design/SKILL.md +42 -0
- package/skills/gemini-imagegen/SKILL.md +237 -0
- package/skills/gemini-imagegen/requirements.txt +2 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +157 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +144 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +263 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +133 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +216 -0
- package/skills/git-history-analyzer/SKILL.md +58 -0
- package/skills/git-worktree/SKILL.md +302 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +337 -0
- package/skills/julik-frontend-races-reviewer/SKILL.md +220 -0
- package/skills/kieran-python-reviewer/SKILL.md +132 -0
- package/skills/kieran-rails-reviewer/SKILL.md +114 -0
- package/skills/kieran-typescript-reviewer/SKILL.md +123 -0
- package/skills/learnings-researcher/SKILL.md +263 -0
- package/skills/lint/SKILL.md +14 -0
- package/skills/orchestrating-swarms/SKILL.md +1718 -0
- package/skills/pattern-recognition-specialist/SKILL.md +71 -0
- package/skills/performance-oracle/SKILL.md +136 -0
- package/skills/pr-comment-resolver/SKILL.md +82 -0
- package/skills/rclone/SKILL.md +150 -0
- package/skills/rclone/scripts/check_setup.sh +60 -0
- package/skills/repo-research-analyst/SKILL.md +134 -0
- package/skills/resolve_pr_parallel/SKILL.md +89 -0
- package/skills/resolve_pr_parallel/scripts/get-pr-comments +68 -0
- package/skills/resolve_pr_parallel/scripts/resolve-pr-thread +23 -0
- package/skills/schema-drift-detector/SKILL.md +153 -0
- package/skills/security-sentinel/SKILL.md +113 -0
- package/skills/skill-creator/SKILL.md +210 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/skills/spec-flow-analyzer/SKILL.md +133 -0
- package/src/commands/convert.ts +183 -0
- package/src/commands/install.ts +273 -0
- package/src/commands/list.ts +37 -0
- package/src/commands/sync.ts +89 -0
- package/src/converters/claude-to-codex.ts +182 -0
- package/src/converters/claude-to-opencode.ts +395 -0
- package/src/converters/claude-to-pi.ts +205 -0
- package/src/index.ts +22 -0
- package/src/parsers/claude-home.ts +65 -0
- package/src/parsers/claude.ts +252 -0
- package/src/sync/codex.ts +92 -0
- package/src/sync/opencode.ts +75 -0
- package/src/sync/pi.ts +88 -0
- package/src/targets/codex.ts +96 -0
- package/src/targets/index.ts +38 -0
- package/src/targets/opencode.ts +57 -0
- package/src/targets/pi.ts +131 -0
- package/src/templates/pi/compat-extension.ts +452 -0
- package/src/types/claude.ts +90 -0
- package/src/types/codex.ts +23 -0
- package/src/types/opencode.ts +54 -0
- package/src/types/pi.ts +40 -0
- package/src/utils/codex-agents.ts +64 -0
- package/src/utils/files.ts +77 -0
- package/src/utils/frontmatter.ts +65 -0
- package/src/utils/symlink.ts +43 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { defineCommand } from "citty"
|
|
2
|
+
import os from "os"
|
|
3
|
+
import path from "path"
|
|
4
|
+
import { loadClaudePlugin } from "../parsers/claude"
|
|
5
|
+
import { targets } from "../targets"
|
|
6
|
+
import type { PermissionMode } from "../converters/claude-to-opencode"
|
|
7
|
+
import { ensureCodexAgentsFile } from "../utils/codex-agents"
|
|
8
|
+
|
|
9
|
+
const permissionModes: PermissionMode[] = ["none", "broad", "from-commands"]
|
|
10
|
+
|
|
11
|
+
export default defineCommand({
|
|
12
|
+
meta: {
|
|
13
|
+
name: "convert",
|
|
14
|
+
description: "Convert a Claude Code plugin into another format",
|
|
15
|
+
},
|
|
16
|
+
args: {
|
|
17
|
+
source: {
|
|
18
|
+
type: "positional",
|
|
19
|
+
required: true,
|
|
20
|
+
description: "Path to the Claude plugin directory",
|
|
21
|
+
},
|
|
22
|
+
to: {
|
|
23
|
+
type: "string",
|
|
24
|
+
default: "opencode",
|
|
25
|
+
description: "Target format (opencode | codex | pi)",
|
|
26
|
+
},
|
|
27
|
+
output: {
|
|
28
|
+
type: "string",
|
|
29
|
+
alias: "o",
|
|
30
|
+
description: "Output directory (project root)",
|
|
31
|
+
},
|
|
32
|
+
codexHome: {
|
|
33
|
+
type: "string",
|
|
34
|
+
alias: "codex-home",
|
|
35
|
+
description: "Write Codex output to this .codex root (ex: ~/.codex)",
|
|
36
|
+
},
|
|
37
|
+
piHome: {
|
|
38
|
+
type: "string",
|
|
39
|
+
alias: "pi-home",
|
|
40
|
+
description: "Write Pi output to this Pi root (ex: ~/.pi/agent or ./.pi)",
|
|
41
|
+
},
|
|
42
|
+
also: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "Comma-separated extra targets to generate (ex: codex)",
|
|
45
|
+
},
|
|
46
|
+
permissions: {
|
|
47
|
+
type: "string",
|
|
48
|
+
default: "broad",
|
|
49
|
+
description: "Permission mapping: none | broad | from-commands",
|
|
50
|
+
},
|
|
51
|
+
agentMode: {
|
|
52
|
+
type: "string",
|
|
53
|
+
default: "subagent",
|
|
54
|
+
description: "Default agent mode: primary | subagent",
|
|
55
|
+
},
|
|
56
|
+
inferTemperature: {
|
|
57
|
+
type: "boolean",
|
|
58
|
+
default: true,
|
|
59
|
+
description: "Infer agent temperature from name/description",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
async run({ args }) {
|
|
63
|
+
const targetName = String(args.to)
|
|
64
|
+
const target = targets[targetName]
|
|
65
|
+
if (!target) {
|
|
66
|
+
throw new Error(`Unknown target: ${targetName}`)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!target.implemented) {
|
|
70
|
+
throw new Error(`Target ${targetName} is registered but not implemented yet.`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const permissions = String(args.permissions)
|
|
74
|
+
if (!permissionModes.includes(permissions as PermissionMode)) {
|
|
75
|
+
throw new Error(`Unknown permissions mode: ${permissions}`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const plugin = await loadClaudePlugin(String(args.source))
|
|
79
|
+
const outputRoot = resolveOutputRoot(args.output)
|
|
80
|
+
const codexHome = resolveCodexRoot(args.codexHome)
|
|
81
|
+
const piHome = resolvePiRoot(args.piHome)
|
|
82
|
+
|
|
83
|
+
const agentMode = String(args.agentMode) === "primary" ? "primary" : "subagent"
|
|
84
|
+
const options = {
|
|
85
|
+
agentMode,
|
|
86
|
+
inferTemperature: Boolean(args.inferTemperature),
|
|
87
|
+
permissions: permissions as PermissionMode,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const primaryOutputRoot =
|
|
91
|
+
targetName === "codex"
|
|
92
|
+
? codexHome
|
|
93
|
+
: targetName === "pi"
|
|
94
|
+
? piHome
|
|
95
|
+
: outputRoot
|
|
96
|
+
const bundle = target.convert(plugin, options)
|
|
97
|
+
if (!bundle) {
|
|
98
|
+
throw new Error(`Target ${targetName} did not return a bundle.`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await target.write(primaryOutputRoot, bundle)
|
|
102
|
+
console.log(`Converted ${plugin.manifest.name} to ${targetName} at ${primaryOutputRoot}`)
|
|
103
|
+
|
|
104
|
+
const extraTargets = parseExtraTargets(args.also)
|
|
105
|
+
const allTargets = [targetName, ...extraTargets]
|
|
106
|
+
for (const extra of extraTargets) {
|
|
107
|
+
const handler = targets[extra]
|
|
108
|
+
if (!handler) {
|
|
109
|
+
console.warn(`Skipping unknown target: ${extra}`)
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
if (!handler.implemented) {
|
|
113
|
+
console.warn(`Skipping ${extra}: not implemented yet.`)
|
|
114
|
+
continue
|
|
115
|
+
}
|
|
116
|
+
const extraBundle = handler.convert(plugin, options)
|
|
117
|
+
if (!extraBundle) {
|
|
118
|
+
console.warn(`Skipping ${extra}: no output returned.`)
|
|
119
|
+
continue
|
|
120
|
+
}
|
|
121
|
+
const extraRoot =
|
|
122
|
+
extra === "codex"
|
|
123
|
+
? codexHome
|
|
124
|
+
: extra === "pi"
|
|
125
|
+
? piHome
|
|
126
|
+
: path.join(outputRoot, extra)
|
|
127
|
+
await handler.write(extraRoot, extraBundle)
|
|
128
|
+
console.log(`Converted ${plugin.manifest.name} to ${extra} at ${extraRoot}`)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (allTargets.includes("codex")) {
|
|
132
|
+
await ensureCodexAgentsFile(codexHome)
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
function parseExtraTargets(value: unknown): string[] {
|
|
138
|
+
if (!value) return []
|
|
139
|
+
return String(value)
|
|
140
|
+
.split(",")
|
|
141
|
+
.map((entry) => entry.trim())
|
|
142
|
+
.filter(Boolean)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function resolveCodexHome(value: unknown): string | null {
|
|
146
|
+
if (!value) return null
|
|
147
|
+
const raw = String(value).trim()
|
|
148
|
+
if (!raw) return null
|
|
149
|
+
const expanded = expandHome(raw)
|
|
150
|
+
return path.resolve(expanded)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function resolveCodexRoot(value: unknown): string {
|
|
154
|
+
return resolveCodexHome(value) ?? path.join(os.homedir(), ".codex")
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function resolvePiHome(value: unknown): string | null {
|
|
158
|
+
if (!value) return null
|
|
159
|
+
const raw = String(value).trim()
|
|
160
|
+
if (!raw) return null
|
|
161
|
+
const expanded = expandHome(raw)
|
|
162
|
+
return path.resolve(expanded)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function resolvePiRoot(value: unknown): string {
|
|
166
|
+
return resolvePiHome(value) ?? path.join(os.homedir(), ".pi", "agent")
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function expandHome(value: string): string {
|
|
170
|
+
if (value === "~") return os.homedir()
|
|
171
|
+
if (value.startsWith(`~${path.sep}`)) {
|
|
172
|
+
return path.join(os.homedir(), value.slice(2))
|
|
173
|
+
}
|
|
174
|
+
return value
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function resolveOutputRoot(value: unknown): string {
|
|
178
|
+
if (value && String(value).trim()) {
|
|
179
|
+
const expanded = expandHome(String(value).trim())
|
|
180
|
+
return path.resolve(expanded)
|
|
181
|
+
}
|
|
182
|
+
return process.cwd()
|
|
183
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { defineCommand } from "citty"
|
|
2
|
+
import { promises as fs } from "fs"
|
|
3
|
+
import os from "os"
|
|
4
|
+
import path from "path"
|
|
5
|
+
import { loadClaudePlugin } from "../parsers/claude"
|
|
6
|
+
import { targets } from "../targets"
|
|
7
|
+
import { pathExists } from "../utils/files"
|
|
8
|
+
import type { PermissionMode } from "../converters/claude-to-opencode"
|
|
9
|
+
import { ensureCodexAgentsFile } from "../utils/codex-agents"
|
|
10
|
+
|
|
11
|
+
const permissionModes: PermissionMode[] = ["none", "broad", "from-commands"]
|
|
12
|
+
|
|
13
|
+
export default defineCommand({
|
|
14
|
+
meta: {
|
|
15
|
+
name: "install",
|
|
16
|
+
description: "Install and convert a Claude plugin",
|
|
17
|
+
},
|
|
18
|
+
args: {
|
|
19
|
+
plugin: {
|
|
20
|
+
type: "positional",
|
|
21
|
+
required: true,
|
|
22
|
+
description: "Plugin name or path",
|
|
23
|
+
},
|
|
24
|
+
to: {
|
|
25
|
+
type: "string",
|
|
26
|
+
default: "opencode",
|
|
27
|
+
description: "Target format (opencode | codex | pi)",
|
|
28
|
+
},
|
|
29
|
+
output: {
|
|
30
|
+
type: "string",
|
|
31
|
+
alias: "o",
|
|
32
|
+
description: "Output directory (project root)",
|
|
33
|
+
},
|
|
34
|
+
codexHome: {
|
|
35
|
+
type: "string",
|
|
36
|
+
alias: "codex-home",
|
|
37
|
+
description: "Write Codex output to this .codex root (ex: ~/.codex)",
|
|
38
|
+
},
|
|
39
|
+
piHome: {
|
|
40
|
+
type: "string",
|
|
41
|
+
alias: "pi-home",
|
|
42
|
+
description: "Write Pi output to this Pi root (ex: ~/.pi/agent or ./.pi)",
|
|
43
|
+
},
|
|
44
|
+
also: {
|
|
45
|
+
type: "string",
|
|
46
|
+
description: "Comma-separated extra targets to generate (ex: codex)",
|
|
47
|
+
},
|
|
48
|
+
permissions: {
|
|
49
|
+
type: "string",
|
|
50
|
+
default: "broad",
|
|
51
|
+
description: "Permission mapping: none | broad | from-commands",
|
|
52
|
+
},
|
|
53
|
+
agentMode: {
|
|
54
|
+
type: "string",
|
|
55
|
+
default: "subagent",
|
|
56
|
+
description: "Default agent mode: primary | subagent",
|
|
57
|
+
},
|
|
58
|
+
inferTemperature: {
|
|
59
|
+
type: "boolean",
|
|
60
|
+
default: true,
|
|
61
|
+
description: "Infer agent temperature from name/description",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
async run({ args }) {
|
|
65
|
+
const targetName = String(args.to)
|
|
66
|
+
const target = targets[targetName]
|
|
67
|
+
if (!target) {
|
|
68
|
+
throw new Error(`Unknown target: ${targetName}`)
|
|
69
|
+
}
|
|
70
|
+
if (!target.implemented) {
|
|
71
|
+
throw new Error(`Target ${targetName} is registered but not implemented yet.`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const permissions = String(args.permissions)
|
|
75
|
+
if (!permissionModes.includes(permissions as PermissionMode)) {
|
|
76
|
+
throw new Error(`Unknown permissions mode: ${permissions}`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const resolvedPlugin = await resolvePluginPath(String(args.plugin))
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const plugin = await loadClaudePlugin(resolvedPlugin.path)
|
|
83
|
+
const outputRoot = resolveOutputRoot(args.output)
|
|
84
|
+
const codexHome = resolveCodexRoot(args.codexHome)
|
|
85
|
+
const piHome = resolvePiRoot(args.piHome)
|
|
86
|
+
|
|
87
|
+
const agentMode = String(args.agentMode) === "primary" ? "primary" : "subagent"
|
|
88
|
+
const options = {
|
|
89
|
+
agentMode,
|
|
90
|
+
inferTemperature: Boolean(args.inferTemperature),
|
|
91
|
+
permissions: permissions as PermissionMode,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const bundle = target.convert(plugin, options)
|
|
95
|
+
if (!bundle) {
|
|
96
|
+
throw new Error(`Target ${targetName} did not return a bundle.`)
|
|
97
|
+
}
|
|
98
|
+
const primaryOutputRoot =
|
|
99
|
+
targetName === "codex"
|
|
100
|
+
? codexHome
|
|
101
|
+
: targetName === "pi"
|
|
102
|
+
? piHome
|
|
103
|
+
: outputRoot
|
|
104
|
+
await target.write(primaryOutputRoot, bundle)
|
|
105
|
+
console.log(`Installed ${plugin.manifest.name} to ${primaryOutputRoot}`)
|
|
106
|
+
|
|
107
|
+
const extraTargets = parseExtraTargets(args.also)
|
|
108
|
+
const allTargets = [targetName, ...extraTargets]
|
|
109
|
+
for (const extra of extraTargets) {
|
|
110
|
+
const handler = targets[extra]
|
|
111
|
+
if (!handler) {
|
|
112
|
+
console.warn(`Skipping unknown target: ${extra}`)
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
if (!handler.implemented) {
|
|
116
|
+
console.warn(`Skipping ${extra}: not implemented yet.`)
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
119
|
+
const extraBundle = handler.convert(plugin, options)
|
|
120
|
+
if (!extraBundle) {
|
|
121
|
+
console.warn(`Skipping ${extra}: no output returned.`)
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
const extraRoot =
|
|
125
|
+
extra === "codex"
|
|
126
|
+
? codexHome
|
|
127
|
+
: extra === "pi"
|
|
128
|
+
? piHome
|
|
129
|
+
: path.join(outputRoot, extra)
|
|
130
|
+
await handler.write(extraRoot, extraBundle)
|
|
131
|
+
console.log(`Installed ${plugin.manifest.name} to ${extraRoot}`)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (allTargets.includes("codex")) {
|
|
135
|
+
await ensureCodexAgentsFile(codexHome)
|
|
136
|
+
}
|
|
137
|
+
} finally {
|
|
138
|
+
if (resolvedPlugin.cleanup) {
|
|
139
|
+
await resolvedPlugin.cleanup()
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
type ResolvedPluginPath = {
|
|
146
|
+
path: string
|
|
147
|
+
cleanup?: () => Promise<void>
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function resolvePluginPath(input: string): Promise<ResolvedPluginPath> {
|
|
151
|
+
const raw = input.trim()
|
|
152
|
+
if (!raw) {
|
|
153
|
+
throw new Error("Plugin name or path is required.")
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const likelyPath =
|
|
157
|
+
raw.startsWith(".") ||
|
|
158
|
+
raw.startsWith("/") ||
|
|
159
|
+
raw.startsWith("~") ||
|
|
160
|
+
raw.includes(path.sep)
|
|
161
|
+
|
|
162
|
+
const directPath = path.resolve(expandHome(raw))
|
|
163
|
+
const pluginsPath = path.join(process.cwd(), "plugins", raw)
|
|
164
|
+
|
|
165
|
+
// If user passed an explicit path, honor it first.
|
|
166
|
+
if (likelyPath && (await pathExists(directPath))) {
|
|
167
|
+
return { path: directPath }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// For named installs, prefer bundled ./plugins/<name> to avoid collisions
|
|
171
|
+
// with similarly named directories in the repo root.
|
|
172
|
+
if (await pathExists(pluginsPath)) {
|
|
173
|
+
return { path: pluginsPath }
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!likelyPath && (await pathExists(directPath))) {
|
|
177
|
+
return { path: directPath }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return await resolveGitHubPluginPath(raw)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function parseExtraTargets(value: unknown): string[] {
|
|
184
|
+
if (!value) return []
|
|
185
|
+
return String(value)
|
|
186
|
+
.split(",")
|
|
187
|
+
.map((entry) => entry.trim())
|
|
188
|
+
.filter(Boolean)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function resolveCodexHome(value: unknown): string | null {
|
|
192
|
+
if (!value) return null
|
|
193
|
+
const raw = String(value).trim()
|
|
194
|
+
if (!raw) return null
|
|
195
|
+
const expanded = expandHome(raw)
|
|
196
|
+
return path.resolve(expanded)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function resolveCodexRoot(value: unknown): string {
|
|
200
|
+
return resolveCodexHome(value) ?? path.join(os.homedir(), ".codex")
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function resolvePiHome(value: unknown): string | null {
|
|
204
|
+
if (!value) return null
|
|
205
|
+
const raw = String(value).trim()
|
|
206
|
+
if (!raw) return null
|
|
207
|
+
const expanded = expandHome(raw)
|
|
208
|
+
return path.resolve(expanded)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function resolvePiRoot(value: unknown): string {
|
|
212
|
+
return resolvePiHome(value) ?? path.join(os.homedir(), ".pi", "agent")
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function expandHome(value: string): string {
|
|
216
|
+
if (value === "~") return os.homedir()
|
|
217
|
+
if (value.startsWith(`~${path.sep}`)) {
|
|
218
|
+
return path.join(os.homedir(), value.slice(2))
|
|
219
|
+
}
|
|
220
|
+
return value
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function resolveOutputRoot(value: unknown): string {
|
|
224
|
+
if (value && String(value).trim()) {
|
|
225
|
+
const expanded = expandHome(String(value).trim())
|
|
226
|
+
return path.resolve(expanded)
|
|
227
|
+
}
|
|
228
|
+
// OpenCode global config lives at ~/.config/opencode per XDG spec
|
|
229
|
+
// See: https://opencode.ai/docs/config/
|
|
230
|
+
return path.join(os.homedir(), ".config", "opencode")
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function resolveGitHubPluginPath(pluginName: string): Promise<ResolvedPluginPath> {
|
|
234
|
+
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "compound-plugin-"))
|
|
235
|
+
const source = resolveGitHubSource()
|
|
236
|
+
try {
|
|
237
|
+
await cloneGitHubRepo(source, tempRoot)
|
|
238
|
+
} catch (error) {
|
|
239
|
+
await fs.rm(tempRoot, { recursive: true, force: true })
|
|
240
|
+
throw error
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const pluginPath = path.join(tempRoot, "plugins", pluginName)
|
|
244
|
+
if (!(await pathExists(pluginPath))) {
|
|
245
|
+
await fs.rm(tempRoot, { recursive: true, force: true })
|
|
246
|
+
throw new Error(`Could not find plugin ${pluginName} in ${source}.`)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
path: pluginPath,
|
|
251
|
+
cleanup: async () => {
|
|
252
|
+
await fs.rm(tempRoot, { recursive: true, force: true })
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function resolveGitHubSource(): string {
|
|
258
|
+
const override = process.env.COMPOUND_PLUGIN_GITHUB_SOURCE
|
|
259
|
+
if (override && override.trim()) return override.trim()
|
|
260
|
+
return "https://github.com/EveryInc/compound-engineering-plugin"
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function cloneGitHubRepo(source: string, destination: string): Promise<void> {
|
|
264
|
+
const proc = Bun.spawn(["git", "clone", "--depth", "1", source, destination], {
|
|
265
|
+
stdout: "pipe",
|
|
266
|
+
stderr: "pipe",
|
|
267
|
+
})
|
|
268
|
+
const exitCode = await proc.exited
|
|
269
|
+
const stderr = await new Response(proc.stderr).text()
|
|
270
|
+
if (exitCode !== 0) {
|
|
271
|
+
throw new Error(`Failed to clone ${source}. ${stderr.trim()}`)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import path from "path"
|
|
2
|
+
import { promises as fs } from "fs"
|
|
3
|
+
import { defineCommand } from "citty"
|
|
4
|
+
import { pathExists } from "../utils/files"
|
|
5
|
+
|
|
6
|
+
export default defineCommand({
|
|
7
|
+
meta: {
|
|
8
|
+
name: "list",
|
|
9
|
+
description: "List available Claude plugins under plugins/",
|
|
10
|
+
},
|
|
11
|
+
async run() {
|
|
12
|
+
const root = process.cwd()
|
|
13
|
+
const pluginsDir = path.join(root, "plugins")
|
|
14
|
+
if (!(await pathExists(pluginsDir))) {
|
|
15
|
+
console.log("No plugins directory found.")
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const entries = await fs.readdir(pluginsDir, { withFileTypes: true })
|
|
20
|
+
const plugins: string[] = []
|
|
21
|
+
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
if (!entry.isDirectory()) continue
|
|
24
|
+
const manifestPath = path.join(pluginsDir, entry.name, ".claude-plugin", "plugin.json")
|
|
25
|
+
if (await pathExists(manifestPath)) {
|
|
26
|
+
plugins.push(entry.name)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (plugins.length === 0) {
|
|
31
|
+
console.log("No Claude plugins found under plugins/.")
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(plugins.sort().join("\n"))
|
|
36
|
+
},
|
|
37
|
+
})
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { defineCommand } from "citty"
|
|
2
|
+
import os from "os"
|
|
3
|
+
import path from "path"
|
|
4
|
+
import { loadClaudeHome } from "../parsers/claude-home"
|
|
5
|
+
import { syncToOpenCode } from "../sync/opencode"
|
|
6
|
+
import { syncToCodex } from "../sync/codex"
|
|
7
|
+
import { syncToPi } from "../sync/pi"
|
|
8
|
+
|
|
9
|
+
function isValidTarget(value: string): value is "opencode" | "codex" | "pi" {
|
|
10
|
+
return value === "opencode" || value === "codex" || value === "pi"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Check if any MCP servers have env vars that might contain secrets */
|
|
14
|
+
function hasPotentialSecrets(mcpServers: Record<string, unknown>): boolean {
|
|
15
|
+
const sensitivePatterns = /key|token|secret|password|credential|api_key/i
|
|
16
|
+
for (const server of Object.values(mcpServers)) {
|
|
17
|
+
const env = (server as { env?: Record<string, string> }).env
|
|
18
|
+
if (env) {
|
|
19
|
+
for (const key of Object.keys(env)) {
|
|
20
|
+
if (sensitivePatterns.test(key)) return true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default defineCommand({
|
|
28
|
+
meta: {
|
|
29
|
+
name: "sync",
|
|
30
|
+
description: "Sync Claude Code config (~/.claude/) to OpenCode, Codex, or Pi",
|
|
31
|
+
},
|
|
32
|
+
args: {
|
|
33
|
+
target: {
|
|
34
|
+
type: "string",
|
|
35
|
+
required: true,
|
|
36
|
+
description: "Target: opencode | codex | pi",
|
|
37
|
+
},
|
|
38
|
+
claudeHome: {
|
|
39
|
+
type: "string",
|
|
40
|
+
alias: "claude-home",
|
|
41
|
+
description: "Path to Claude home (default: ~/.claude)",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
async run({ args }) {
|
|
45
|
+
if (!isValidTarget(args.target)) {
|
|
46
|
+
throw new Error(`Unknown target: ${args.target}. Use 'opencode', 'codex', or 'pi'.`)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const claudeHome = expandHome(args.claudeHome ?? path.join(os.homedir(), ".claude"))
|
|
50
|
+
const config = await loadClaudeHome(claudeHome)
|
|
51
|
+
|
|
52
|
+
// Warn about potential secrets in MCP env vars
|
|
53
|
+
if (hasPotentialSecrets(config.mcpServers)) {
|
|
54
|
+
console.warn(
|
|
55
|
+
"⚠️ Warning: MCP servers contain env vars that may include secrets (API keys, tokens).\n" +
|
|
56
|
+
" These will be copied to the target config. Review before sharing the config file.",
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(
|
|
61
|
+
`Syncing ${config.skills.length} skills, ${Object.keys(config.mcpServers).length} MCP servers...`,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
const outputRoot =
|
|
65
|
+
args.target === "opencode"
|
|
66
|
+
? path.join(os.homedir(), ".config", "opencode")
|
|
67
|
+
: args.target === "codex"
|
|
68
|
+
? path.join(os.homedir(), ".codex")
|
|
69
|
+
: path.join(os.homedir(), ".pi", "agent")
|
|
70
|
+
|
|
71
|
+
if (args.target === "opencode") {
|
|
72
|
+
await syncToOpenCode(config, outputRoot)
|
|
73
|
+
} else if (args.target === "codex") {
|
|
74
|
+
await syncToCodex(config, outputRoot)
|
|
75
|
+
} else {
|
|
76
|
+
await syncToPi(config, outputRoot)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log(`✓ Synced to ${args.target}: ${outputRoot}`)
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
function expandHome(value: string): string {
|
|
84
|
+
if (value === "~") return os.homedir()
|
|
85
|
+
if (value.startsWith(`~${path.sep}`)) {
|
|
86
|
+
return path.join(os.homedir(), value.slice(2))
|
|
87
|
+
}
|
|
88
|
+
return value
|
|
89
|
+
}
|