@open-mercato/cli 0.6.7-develop.6863.1.61001cf9a8 → 0.6.7
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/.turbo/turbo-build.log +4 -4
- package/build.mjs +7 -24
- package/dist/agentic/claude-code/hooks/entity-migration-check.ts +88 -32
- package/dist/agentic/codex/enforcement-rules.md +16 -2
- package/dist/agentic/cursor/hooks/entity-migration-check.mjs +50 -19
- package/dist/agentic/cursor/rules/entity-guard.mdc +21 -9
- package/dist/agentic/cursor/rules/generated-guard.mdc +5 -3
- package/dist/agentic/cursor/rules/open-mercato.mdc +29 -3
- package/dist/agentic/guides/cache.md +45 -0
- package/dist/agentic/guides/core.md +453 -0
- package/dist/agentic/guides/events.md +117 -0
- package/dist/agentic/guides/module-facts.json +3833 -115419
- package/dist/agentic/guides/module-system.md +127 -12
- package/dist/agentic/guides/modules/ai_assistant.md +28 -227
- package/dist/agentic/guides/modules/api_docs.md +2 -58
- package/dist/agentic/guides/modules/api_keys.md +7 -92
- package/dist/agentic/guides/modules/attachments.md +14 -119
- package/dist/agentic/guides/modules/audit_logs.md +10 -131
- package/dist/agentic/guides/modules/auth.md +33 -276
- package/dist/agentic/guides/modules/business_rules.md +14 -149
- package/dist/agentic/guides/modules/catalog.md +43 -475
- package/dist/agentic/guides/modules/channel_gmail.md +3 -82
- package/dist/agentic/guides/modules/channel_imap.md +3 -82
- package/dist/agentic/guides/modules/checkout.md +27 -299
- package/dist/agentic/guides/modules/communication_channels.md +33 -315
- package/dist/agentic/guides/modules/configs.md +8 -104
- package/dist/agentic/guides/modules/content.md +2 -57
- package/dist/agentic/guides/modules/currencies.md +17 -152
- package/dist/agentic/guides/modules/customer_accounts.md +45 -387
- package/dist/agentic/guides/modules/customers.md +85 -746
- package/dist/agentic/guides/modules/dashboards.md +10 -155
- package/dist/agentic/guides/modules/data_sync.md +16 -149
- package/dist/agentic/guides/modules/dictionaries.md +12 -107
- package/dist/agentic/guides/modules/directory.md +15 -148
- package/dist/agentic/guides/modules/entities.md +13 -145
- package/dist/agentic/guides/modules/events.md +2 -59
- package/dist/agentic/guides/modules/feature_toggles.md +9 -119
- package/dist/agentic/guides/modules/gateway_stripe.md +4 -92
- package/dist/agentic/guides/modules/generators.md +2 -45
- package/dist/agentic/guides/modules/inbox_ops.md +27 -207
- package/dist/agentic/guides/modules/integrations.md +16 -146
- package/dist/agentic/guides/modules/messages.md +24 -223
- package/dist/agentic/guides/modules/notifications.md +8 -96
- package/dist/agentic/guides/modules/onboarding.md +6 -77
- package/dist/agentic/guides/modules/payment_gateways.md +21 -164
- package/dist/agentic/guides/modules/perspectives.md +7 -77
- package/dist/agentic/guides/modules/planner.md +18 -136
- package/dist/agentic/guides/modules/portal.md +2 -93
- package/dist/agentic/guides/modules/progress.md +14 -104
- package/dist/agentic/guides/modules/query_index.md +15 -154
- package/dist/agentic/guides/modules/record_locks.md +21 -206
- package/dist/agentic/guides/modules/resources.md +30 -197
- package/dist/agentic/guides/modules/sales.md +84 -678
- package/dist/agentic/guides/modules/scheduler.md +14 -133
- package/dist/agentic/guides/modules/search.md +6 -170
- package/dist/agentic/guides/modules/security.md +35 -294
- package/dist/agentic/guides/modules/shipping_carriers.md +18 -134
- package/dist/agentic/guides/modules/sso.md +26 -151
- package/dist/agentic/guides/modules/staff.md +57 -369
- package/dist/agentic/guides/modules/storage_s3.md +5 -95
- package/dist/agentic/guides/modules/sync_akeneo.md +3 -85
- package/dist/agentic/guides/modules/sync_excel.md +6 -75
- package/dist/agentic/guides/modules/system_status_overlays.md +2 -60
- package/dist/agentic/guides/modules/translations.md +10 -104
- package/dist/agentic/guides/modules/webhooks.md +24 -203
- package/dist/agentic/guides/modules/wms.md +46 -441
- package/dist/agentic/guides/modules/workflows.md +43 -302
- package/dist/agentic/guides/queue.md +53 -0
- package/dist/agentic/guides/search.md +115 -0
- package/dist/agentic/guides/shared.md +108 -0
- package/dist/agentic/guides/ui.md +347 -0
- package/dist/agentic/shared/AGENTS.md.template +311 -124
- package/dist/agentic/shared/ai/agentic.config.json +0 -2
- package/dist/agentic/shared/ai/lessons.md +3 -26
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +0 -4
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +241 -20
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +260 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +601 -16
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +146 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +310 -14
- package/dist/agentic/shared/ai/skills/om-help/SKILL.md +97 -15
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +84 -0
- package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +193 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +152 -33
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +708 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +34 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +762 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +820 -20
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +50 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +97 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +843 -19
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +271 -0
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +63 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +467 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +101 -0
- package/dist/agentic/shared/ai/skills/tiers.json +21 -143
- package/dist/agentic/shared/ai/skills/tiers.schema.json +40 -52
- package/dist/agentic/shared/ai/specs/README.md +3 -4
- package/dist/agentic/shared/ai/specs/SPEC-000-template.md +10 -226
- package/dist/agentic/shared/ai/trackers/github.md +4 -108
- package/dist/agentic/shared/scripts/install-skills.sh +694 -4
- package/dist/bin.js +1 -13
- package/dist/bin.js.map +2 -2
- package/dist/lib/__integration__/TC-INT-008.spec.js +8 -88
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-init.js +3 -13
- package/dist/lib/agentic-init.js.map +2 -2
- package/dist/lib/agentic-setup.js +186 -418
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/extensions/injection-widgets.js +0 -20
- package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
- package/dist/lib/generators/module-facts-discovery.js +7 -41
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +45 -1387
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-registry.js +5 -11
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/resolver.js +0 -2
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/testing/integration.js +0 -5
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +1 -23
- package/dist/mercato.js.map +2 -2
- package/package.json +11 -13
- package/src/bin.ts +1 -33
- package/src/lib/__integration__/TC-INT-008.spec.ts +9 -107
- package/src/lib/__tests__/agentic-init.test.ts +5 -41
- package/src/lib/agentic-init.ts +3 -15
- package/src/lib/agentic-setup.ts +224 -530
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +2 -88
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +0 -1
- package/src/lib/generators/__tests__/module-facts.discovery.test.ts +10 -54
- package/src/lib/generators/__tests__/module-subset.test.ts +0 -18
- package/src/lib/generators/extensions/injection-widgets.ts +0 -51
- package/src/lib/generators/module-facts-discovery.ts +7 -58
- package/src/lib/generators/module-facts.ts +46 -1851
- package/src/lib/generators/module-registry.ts +6 -16
- package/src/lib/resolver.ts +0 -3
- package/src/lib/testing/__tests__/integration.test.ts +0 -4
- package/src/lib/testing/integration.ts +0 -5
- package/src/mercato.ts +1 -26
- package/dist/agentic/guides/ai-workflows.md +0 -76
- package/dist/agentic/guides/architecture.md +0 -107
- package/dist/agentic/guides/backend-ui.md +0 -80
- package/dist/agentic/guides/contracts.md +0 -92
- package/dist/agentic/guides/extensions.md +0 -121
- package/dist/agentic/guides/framework-extension-points.md +0 -36
- package/dist/agentic/guides/integrations.md +0 -81
- package/dist/agentic/guides/modules/design_system.md +0 -102
- package/dist/agentic/guides/spec-delivery.md +0 -22
- package/dist/agentic/guides/testing-debugging.md +0 -80
- package/dist/agentic/guides/upstream/AGENTS.md +0 -298
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +0 -316
- package/dist/agentic/guides/upstream/manifest.json +0 -8
- package/dist/agentic/shared/ai/harness/README.md +0 -50
- package/dist/agentic/shared/ai/harness/RELEASE.md +0 -57
- package/dist/agentic/shared/ai/harness/cases.json +0 -13680
- package/dist/agentic/shared/ai/harness/cases.schema.json +0 -133
- package/dist/agentic/shared/ai/harness/fixtures/index.json +0 -49
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +0 -162
- package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +0 -21
- package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +0 -96
- package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +0 -172
- package/dist/agentic/shared/ai/harness/release-matrix.json +0 -158
- package/dist/agentic/shared/ai/harness/release-result.schema.json +0 -219
- package/dist/agentic/shared/ai/harness/result.schema.json +0 -76
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +0 -12
- package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +0 -73
- package/dist/agentic/shared/ai/harness/validators.json +0 -78
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +0 -2121
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +0 -1096
- package/dist/agentic/shared/ai/lessons/_template.md +0 -16
- package/dist/agentic/shared/ai/review-checklist.md +0 -36
- package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +0 -21
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +0 -98
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +0 -16
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +0 -53
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +0 -11
- package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +0 -30
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +0 -12
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +0 -13
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +0 -28
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +0 -22
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +0 -13
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +0 -10
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +0 -17
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +0 -29
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +0 -100
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +0 -16
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +0 -17
- package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +0 -25
- package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +0 -11
- package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +0 -18
- package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +0 -20
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +0 -33
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +0 -40
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +0 -27
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +0 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +0 -16
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +0 -14
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +0 -15
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +0 -12
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +0 -34
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +0 -4
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +0 -11
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +0 -31
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +0 -39
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +0 -43
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +0 -19
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +0 -172
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +0 -12
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +0 -83
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +0 -21
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +0 -22
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +0 -13
- package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +0 -41
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +0 -19
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +0 -44
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +0 -39
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +0 -20
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +0 -57
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +0 -486
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +0 -18
- package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +0 -27
- package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +0 -13
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +0 -41
- package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +0 -11
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +0 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +0 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +0 -14
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +0 -187
- package/dist/agentic/shared/scripts/check-lessons.mjs +0 -178
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +0 -2958
- package/dist/agentic/shared/scripts/execution-sandbox.mjs +0 -329
- package/dist/agentic/shared/scripts/framework-context.mjs +0 -888
- package/dist/agentic/shared/scripts/install-skills.mjs +0 -1029
- package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +0 -222
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +0 -1774
- package/dist/lib/generators/module-extension-facts.js +0 -1840
- package/dist/lib/generators/module-extension-facts.js.map +0 -7
- package/dist/lib/generators/module-fact-sources.js +0 -70
- package/dist/lib/generators/module-fact-sources.js.map +0 -7
- package/dist/lib/generators/module-override-targets.js +0 -688
- package/dist/lib/generators/module-override-targets.js.map +0 -7
- package/dist/lib/load-env.js +0 -24
- package/dist/lib/load-env.js.map +0 -7
- package/dist/lib/telemetry-init.js +0 -358
- package/dist/lib/telemetry-init.js.map +0 -7
- package/src/lib/__tests__/agentic-setup.ownership.test.ts +0 -386
- package/src/lib/__tests__/injection-widget-id-validation.test.ts +0 -184
- package/src/lib/__tests__/load-env.test.ts +0 -65
- package/src/lib/__tests__/telemetry-init.test.ts +0 -298
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +0 -92
- package/src/lib/generators/__tests__/module-extension-activations.test.ts +0 -762
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +0 -404
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +0 -108
- package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +0 -561
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +0 -119
- package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +0 -149
- package/src/lib/generators/__tests__/module-override-targets.test.ts +0 -304
- package/src/lib/generators/module-extension-facts.ts +0 -2365
- package/src/lib/generators/module-fact-sources.ts +0 -108
- package/src/lib/generators/module-override-targets.ts +0 -863
- package/src/lib/load-env.ts +0 -30
- package/src/lib/telemetry-init.ts +0 -461
|
@@ -1,5 +1,695 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
# Skill installer for a standalone Open Mercato app. Skills live in ONE
|
|
5
|
+
# canonical place — the cross-agent directory .agents/skills/ — and two sources
|
|
6
|
+
# are mixed into it:
|
|
7
|
+
#
|
|
8
|
+
# 1. Local tiered skills: reads .ai/skills/tiers.json and symlinks each
|
|
9
|
+
# selected skill into .agents/skills/<name> -> ../../.ai/skills/<name>.
|
|
10
|
+
# Legacy directory-level symlinks (e.g. .claude/skills -> ../.ai/skills)
|
|
11
|
+
# left by an older scaffold are cleaned up.
|
|
12
|
+
# 2. External shared skills: installs the subset this app ships from the
|
|
13
|
+
# open-mercato/skills collection via `npx skills add` into the same
|
|
14
|
+
# .agents/skills/ directory, then `npx skills update` so a re-run refreshes
|
|
15
|
+
# them to the latest published versions. The external source + explicit
|
|
16
|
+
# skill list live under `external` in tiers.json. A folder under .ai/skills/
|
|
17
|
+
# matching an external skill name is a repo-local override the external
|
|
18
|
+
# skill reads in place; it is never symlinked into the canonical or
|
|
19
|
+
# per-agent directories.
|
|
20
|
+
#
|
|
21
|
+
# Agent support matrix. Per-agent symlinks are created ONLY for agents that
|
|
22
|
+
# cannot read the canonical project-level .agents/skills/ directory:
|
|
23
|
+
#
|
|
24
|
+
# agent id project directory reads .agents/skills/ per-agent symlinks
|
|
25
|
+
# claude-code .claude/skills no yes (written by this script)
|
|
26
|
+
# codex .codex/skills yes no
|
|
27
|
+
# cursor .cursor/skills yes no
|
|
28
|
+
#
|
|
29
|
+
# The "reads .agents/skills/" column follows the universal-agent list of the
|
|
30
|
+
# `skills` CLI (vercel-labs/skills). An agent that cannot read the canonical
|
|
31
|
+
# directory MUST keep its symlinks, or its skills silently disappear.
|
|
32
|
+
#
|
|
33
|
+
# The scaffold is offline: `npx skills add`/`update` only run when you invoke
|
|
34
|
+
# this script (yarn install-skills). Pass --no-external (or set
|
|
35
|
+
# OM_SKIP_EXTERNAL_SKILLS=1) to skip the network step entirely.
|
|
36
|
+
#
|
|
37
|
+
# Usage:
|
|
38
|
+
# install-skills.sh # default tier set (core) + install/update external skills
|
|
39
|
+
# install-skills.sh --with <csv> # default + extra tiers (additive)
|
|
40
|
+
# install-skills.sh --tiers <csv> # exactly the listed tiers (replaces default)
|
|
41
|
+
# install-skills.sh --all # every tier
|
|
42
|
+
# install-skills.sh --legacy-links # also symlink every skill into .claude/skills/ and .codex/skills/
|
|
43
|
+
# install-skills.sh --ignore-agents <csv> # never write these agents' directories
|
|
44
|
+
# install-skills.sh --no-external # skip the npx external-skills install/update step (offline)
|
|
45
|
+
# install-skills.sh --list # print tier table and exit
|
|
46
|
+
# install-skills.sh --clean # remove all skill symlinks and exit
|
|
47
|
+
# install-skills.sh --help | -h # show usage and exit
|
|
48
|
+
|
|
49
|
+
usage() {
|
|
50
|
+
cat <<'EOF'
|
|
51
|
+
Usage: install-skills.sh [options]
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
(no options) Install the default tier set from .ai/skills/tiers.json
|
|
55
|
+
plus the external open-mercato/skills subset this app ships
|
|
56
|
+
into the canonical .agents/skills/ directory. Agents that
|
|
57
|
+
cannot read it (Claude Code) also get per-skill symlinks.
|
|
58
|
+
--with <csv> Install default tiers plus the given tier names (additive).
|
|
59
|
+
--tiers <csv> Install exactly the given tier names (replaces default).
|
|
60
|
+
--all Install every tier defined in tiers.json.
|
|
61
|
+
--legacy-links Restore the pre-canonical layout: symlink every skill into
|
|
62
|
+
.claude/skills/ AND .codex/skills/, even for agents that
|
|
63
|
+
read .agents/skills/ natively.
|
|
64
|
+
--ignore-agents <csv>
|
|
65
|
+
Never write these agents' directories (claude-code, codex,
|
|
66
|
+
cursor). Defaults to `agents.ignore` in tiers.json; this
|
|
67
|
+
flag overrides it.
|
|
68
|
+
--no-external Skip the external-collection step — `npx skills add` on
|
|
69
|
+
first run and `npx skills update` on re-runs (also:
|
|
70
|
+
OM_SKIP_EXTERNAL_SKILLS=1). Use when offline.
|
|
71
|
+
--list Print the tier table and exit without installing.
|
|
72
|
+
--clean Remove all skill symlinks (local and external) and exit.
|
|
73
|
+
--help, -h Show this message.
|
|
74
|
+
|
|
75
|
+
--with, --tiers, and --all are mutually exclusive.
|
|
76
|
+
EOF
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
80
|
+
echo "install-skills: jq is required but not installed." >&2
|
|
81
|
+
echo "Install jq (e.g. 'sudo apt-get install jq' or 'brew install jq') and re-run." >&2
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Resolve the app root from this script's own location (scripts/install-skills.sh),
|
|
86
|
+
# falling back to git and finally the current directory. A freshly scaffolded app
|
|
87
|
+
# may not be a git checkout yet, so git is optional here.
|
|
88
|
+
script_path="$0"
|
|
89
|
+
case "${script_path}" in
|
|
90
|
+
/*) : ;;
|
|
91
|
+
*) script_path="$(pwd)/${script_path}" ;;
|
|
92
|
+
esac
|
|
93
|
+
script_dir=$(CDPATH= cd -- "$(dirname -- "${script_path}")" && pwd)
|
|
94
|
+
repo_root=$(CDPATH= cd -- "${script_dir}/.." && pwd)
|
|
95
|
+
if [ ! -f "${repo_root}/.ai/skills/tiers.json" ]; then
|
|
96
|
+
git_root=$(git rev-parse --show-toplevel 2>/dev/null || true)
|
|
97
|
+
if [ -n "${git_root}" ] && [ -f "${git_root}/.ai/skills/tiers.json" ]; then
|
|
98
|
+
repo_root="${git_root}"
|
|
99
|
+
elif [ -f "$(pwd)/.ai/skills/tiers.json" ]; then
|
|
100
|
+
repo_root="$(pwd)"
|
|
101
|
+
fi
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
manifest="${repo_root}/.ai/skills/tiers.json"
|
|
105
|
+
skills_dir="${repo_root}/.ai/skills"
|
|
106
|
+
|
|
107
|
+
if [ ! -f "${manifest}" ]; then
|
|
108
|
+
echo "install-skills: missing manifest ${manifest}" >&2
|
|
109
|
+
echo " Run this from your app root (yarn install-skills)." >&2
|
|
110
|
+
exit 1
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
mode=""
|
|
114
|
+
with_csv=""
|
|
115
|
+
tiers_csv=""
|
|
116
|
+
list_only=0
|
|
117
|
+
clean_only=0
|
|
118
|
+
legacy_links=0
|
|
119
|
+
ignore_agents_csv=""
|
|
120
|
+
ignore_agents_set=0
|
|
121
|
+
# Any non-empty value other than "0" skips the external npx step.
|
|
122
|
+
case "${OM_SKIP_EXTERNAL_SKILLS:-0}" in
|
|
123
|
+
""|0) no_external=0 ;;
|
|
124
|
+
*) no_external=1 ;;
|
|
125
|
+
esac
|
|
126
|
+
|
|
127
|
+
set_mode() {
|
|
128
|
+
new_mode="$1"
|
|
129
|
+
if [ -n "${mode}" ] && [ "${mode}" != "${new_mode}" ]; then
|
|
130
|
+
echo "install-skills: --with, --tiers, and --all are mutually exclusive." >&2
|
|
131
|
+
usage >&2
|
|
132
|
+
exit 1
|
|
133
|
+
fi
|
|
134
|
+
mode="${new_mode}"
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
while [ $# -gt 0 ]; do
|
|
138
|
+
case "$1" in
|
|
139
|
+
--help|-h)
|
|
140
|
+
usage
|
|
141
|
+
exit 0
|
|
142
|
+
;;
|
|
143
|
+
--list)
|
|
144
|
+
list_only=1
|
|
145
|
+
shift
|
|
146
|
+
;;
|
|
147
|
+
--clean)
|
|
148
|
+
clean_only=1
|
|
149
|
+
shift
|
|
150
|
+
;;
|
|
151
|
+
--no-external)
|
|
152
|
+
no_external=1
|
|
153
|
+
shift
|
|
154
|
+
;;
|
|
155
|
+
--legacy-links)
|
|
156
|
+
legacy_links=1
|
|
157
|
+
shift
|
|
158
|
+
;;
|
|
159
|
+
--ignore-agents)
|
|
160
|
+
if [ $# -lt 2 ]; then
|
|
161
|
+
echo "install-skills: --ignore-agents requires a comma-separated list of agent ids." >&2
|
|
162
|
+
exit 1
|
|
163
|
+
fi
|
|
164
|
+
ignore_agents_csv="$2"
|
|
165
|
+
ignore_agents_set=1
|
|
166
|
+
shift 2
|
|
167
|
+
;;
|
|
168
|
+
--ignore-agents=*)
|
|
169
|
+
ignore_agents_csv="${1#--ignore-agents=}"
|
|
170
|
+
ignore_agents_set=1
|
|
171
|
+
shift
|
|
172
|
+
;;
|
|
173
|
+
--all)
|
|
174
|
+
set_mode all
|
|
175
|
+
shift
|
|
176
|
+
;;
|
|
177
|
+
--with)
|
|
178
|
+
set_mode with
|
|
179
|
+
if [ $# -lt 2 ]; then
|
|
180
|
+
echo "install-skills: --with requires a comma-separated list of tier names." >&2
|
|
181
|
+
exit 1
|
|
182
|
+
fi
|
|
183
|
+
with_csv="$2"
|
|
184
|
+
shift 2
|
|
185
|
+
;;
|
|
186
|
+
--with=*)
|
|
187
|
+
set_mode with
|
|
188
|
+
with_csv="${1#--with=}"
|
|
189
|
+
shift
|
|
190
|
+
;;
|
|
191
|
+
--tiers)
|
|
192
|
+
set_mode tiers
|
|
193
|
+
if [ $# -lt 2 ]; then
|
|
194
|
+
echo "install-skills: --tiers requires a comma-separated list of tier names." >&2
|
|
195
|
+
exit 1
|
|
196
|
+
fi
|
|
197
|
+
tiers_csv="$2"
|
|
198
|
+
shift 2
|
|
199
|
+
;;
|
|
200
|
+
--tiers=*)
|
|
201
|
+
set_mode tiers
|
|
202
|
+
tiers_csv="${1#--tiers=}"
|
|
203
|
+
shift
|
|
204
|
+
;;
|
|
205
|
+
*)
|
|
206
|
+
echo "install-skills: unknown option '$1'" >&2
|
|
207
|
+
usage >&2
|
|
208
|
+
exit 1
|
|
209
|
+
;;
|
|
210
|
+
esac
|
|
211
|
+
done
|
|
212
|
+
|
|
213
|
+
split_csv() {
|
|
214
|
+
printf '%s' "$1" | tr ',' '\n' | sed 's/^ *//; s/ *$//' | grep -v '^$' || true
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
all_tier_names=$(jq -r '.tiers | keys[]' "${manifest}")
|
|
218
|
+
default_tier_names=$(jq -r '.default[]' "${manifest}")
|
|
219
|
+
|
|
220
|
+
tier_defined() {
|
|
221
|
+
needle="$1"
|
|
222
|
+
for candidate in ${all_tier_names}; do
|
|
223
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
224
|
+
return 0
|
|
225
|
+
fi
|
|
226
|
+
done
|
|
227
|
+
return 1
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
tier_skills() {
|
|
231
|
+
jq -r --arg t "$1" '.tiers[$t].skills[]' "${manifest}"
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
tier_skill_count() {
|
|
235
|
+
jq -r --arg t "$1" '.tiers[$t].skills | length' "${manifest}"
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
is_default_tier() {
|
|
239
|
+
needle="$1"
|
|
240
|
+
for candidate in ${default_tier_names}; do
|
|
241
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
242
|
+
return 0
|
|
243
|
+
fi
|
|
244
|
+
done
|
|
245
|
+
return 1
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
dedup_lines() {
|
|
249
|
+
awk 'NF && !seen[$0]++'
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
agents_dir="${repo_root}/.agents/skills"
|
|
253
|
+
|
|
254
|
+
# See the agent support matrix in the header comment.
|
|
255
|
+
known_agents="claude-code codex cursor"
|
|
256
|
+
legacy_agents="claude-code codex"
|
|
257
|
+
|
|
258
|
+
agent_dir() {
|
|
259
|
+
case "$1" in
|
|
260
|
+
claude-code) printf '%s' "${repo_root}/.claude/skills" ;;
|
|
261
|
+
codex) printf '%s' "${repo_root}/.codex/skills" ;;
|
|
262
|
+
cursor) printf '%s' "${repo_root}/.cursor/skills" ;;
|
|
263
|
+
esac
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
agent_reads_canonical() {
|
|
267
|
+
case "$1" in
|
|
268
|
+
codex|cursor) return 0 ;;
|
|
269
|
+
*) return 1 ;;
|
|
270
|
+
esac
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
agent_known() {
|
|
274
|
+
needle="$1"
|
|
275
|
+
for candidate in ${known_agents}; do
|
|
276
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
277
|
+
return 0
|
|
278
|
+
fi
|
|
279
|
+
done
|
|
280
|
+
return 1
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
is_legacy_agent() {
|
|
284
|
+
needle="$1"
|
|
285
|
+
for candidate in ${legacy_agents}; do
|
|
286
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
287
|
+
return 0
|
|
288
|
+
fi
|
|
289
|
+
done
|
|
290
|
+
return 1
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
# The CLI flag overrides `agents.ignore` in tiers.json.
|
|
294
|
+
if [ "${ignore_agents_set}" -eq 1 ]; then
|
|
295
|
+
ignored_agents=$(split_csv "${ignore_agents_csv}")
|
|
296
|
+
else
|
|
297
|
+
ignored_agents=$(jq -r '.agents.ignore[]?' "${manifest}")
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
for agent in ${ignored_agents}; do
|
|
301
|
+
if ! agent_known "${agent}"; then
|
|
302
|
+
echo "install-skills: unknown agent '${agent}'." >&2
|
|
303
|
+
echo " Valid agents: $(printf '%s' "${known_agents}")" >&2
|
|
304
|
+
exit 1
|
|
305
|
+
fi
|
|
306
|
+
done
|
|
307
|
+
|
|
308
|
+
is_ignored_agent() {
|
|
309
|
+
needle="$1"
|
|
310
|
+
for candidate in ${ignored_agents}; do
|
|
311
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
312
|
+
return 0
|
|
313
|
+
fi
|
|
314
|
+
done
|
|
315
|
+
return 1
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
# Agents that get their own per-skill symlinks: in the default layout only the
|
|
319
|
+
# ones that cannot read .agents/skills/; with --legacy-links the historical pair.
|
|
320
|
+
link_agents=""
|
|
321
|
+
for agent in ${known_agents}; do
|
|
322
|
+
if is_ignored_agent "${agent}"; then
|
|
323
|
+
continue
|
|
324
|
+
fi
|
|
325
|
+
if [ "${legacy_links}" -eq 1 ]; then
|
|
326
|
+
if is_legacy_agent "${agent}"; then
|
|
327
|
+
link_agents="${link_agents} ${agent}"
|
|
328
|
+
fi
|
|
329
|
+
elif ! agent_reads_canonical "${agent}"; then
|
|
330
|
+
link_agents="${link_agents} ${agent}"
|
|
331
|
+
fi
|
|
332
|
+
done
|
|
333
|
+
|
|
334
|
+
is_link_agent() {
|
|
335
|
+
needle="$1"
|
|
336
|
+
for candidate in ${link_agents}; do
|
|
337
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
338
|
+
return 0
|
|
339
|
+
fi
|
|
340
|
+
done
|
|
341
|
+
return 1
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
resolves_into_skills_dir() {
|
|
345
|
+
link_path="$1"
|
|
346
|
+
resolved=$(readlink -f -- "${link_path}" 2>/dev/null || true)
|
|
347
|
+
if [ -z "${resolved}" ]; then
|
|
348
|
+
return 1
|
|
349
|
+
fi
|
|
350
|
+
case "${resolved}" in
|
|
351
|
+
"${skills_dir}"/*)
|
|
352
|
+
return 0
|
|
353
|
+
;;
|
|
354
|
+
esac
|
|
355
|
+
return 1
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
resolves_into_agents_dir() {
|
|
359
|
+
link_path="$1"
|
|
360
|
+
resolved=$(readlink -f -- "${link_path}" 2>/dev/null || true)
|
|
361
|
+
if [ -z "${resolved}" ]; then
|
|
362
|
+
return 1
|
|
363
|
+
fi
|
|
364
|
+
case "${resolved}" in
|
|
365
|
+
"${agents_dir}"/*)
|
|
366
|
+
return 0
|
|
367
|
+
;;
|
|
368
|
+
esac
|
|
369
|
+
return 1
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
clean_harness() {
|
|
373
|
+
harness_dir="$1"
|
|
374
|
+
if [ ! -d "${harness_dir}" ] && [ ! -L "${harness_dir}" ]; then
|
|
375
|
+
return 0
|
|
376
|
+
fi
|
|
377
|
+
if [ -L "${harness_dir}" ]; then
|
|
378
|
+
rm -f "${harness_dir}"
|
|
379
|
+
return 0
|
|
380
|
+
fi
|
|
381
|
+
for entry in "${harness_dir}"/* "${harness_dir}"/.[!.]* "${harness_dir}"/..?*; do
|
|
382
|
+
[ -e "${entry}" ] || [ -L "${entry}" ] || continue
|
|
383
|
+
if [ -L "${entry}" ] && { resolves_into_skills_dir "${entry}" || resolves_into_agents_dir "${entry}"; }; then
|
|
384
|
+
rm -f "${entry}"
|
|
385
|
+
fi
|
|
386
|
+
done
|
|
387
|
+
if [ -d "${harness_dir}" ]; then
|
|
388
|
+
rmdir "${harness_dir}" 2>/dev/null || true
|
|
389
|
+
fi
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
# Replace any legacy directory-level symlink (.claude/skills -> ../.ai/skills)
|
|
393
|
+
# with a real directory holding per-skill symlinks.
|
|
394
|
+
prepare_harness_dir() {
|
|
395
|
+
harness_dir="$1"
|
|
396
|
+
parent_dir=$(dirname "${harness_dir}")
|
|
397
|
+
mkdir -p "${parent_dir}"
|
|
398
|
+
if [ -L "${harness_dir}" ]; then
|
|
399
|
+
rm -f "${harness_dir}"
|
|
400
|
+
fi
|
|
401
|
+
if [ ! -d "${harness_dir}" ]; then
|
|
402
|
+
mkdir -p "${harness_dir}"
|
|
403
|
+
fi
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
sweep_harness() {
|
|
407
|
+
harness_dir="$1"
|
|
408
|
+
selected_list="$2"
|
|
409
|
+
[ -d "${harness_dir}" ] || return 0
|
|
410
|
+
for entry in "${harness_dir}"/*; do
|
|
411
|
+
[ -L "${entry}" ] || continue
|
|
412
|
+
base=$(basename "${entry}")
|
|
413
|
+
keep=0
|
|
414
|
+
for skill in ${selected_list}; do
|
|
415
|
+
if [ "${skill}" = "${base}" ]; then
|
|
416
|
+
keep=1
|
|
417
|
+
break
|
|
418
|
+
fi
|
|
419
|
+
done
|
|
420
|
+
if [ "${keep}" -eq 0 ] && resolves_into_skills_dir "${entry}"; then
|
|
421
|
+
rm -f "${entry}"
|
|
422
|
+
fi
|
|
423
|
+
done
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
# Drop links to skills the external collection no longer ships: their target
|
|
427
|
+
# under .agents/skills/ is gone, so the link dangles.
|
|
428
|
+
prune_broken_links() {
|
|
429
|
+
harness_dir="$1"
|
|
430
|
+
[ -d "${harness_dir}" ] || return 0
|
|
431
|
+
for entry in "${harness_dir}"/*; do
|
|
432
|
+
[ -L "${entry}" ] || continue
|
|
433
|
+
[ -e "${entry}" ] && continue
|
|
434
|
+
rm -f "${entry}"
|
|
435
|
+
done
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
print_list() {
|
|
439
|
+
for tier in ${all_tier_names}; do
|
|
440
|
+
count=$(tier_skill_count "${tier}")
|
|
441
|
+
if is_default_tier "${tier}"; then
|
|
442
|
+
label="default"
|
|
443
|
+
else
|
|
444
|
+
label="opt-in"
|
|
445
|
+
fi
|
|
446
|
+
printf '%-12s (%s skills, %s):\n' "${tier}" "${count}" "${label}"
|
|
447
|
+
skills=$(tier_skills "${tier}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
|
|
448
|
+
printf ' %s\n' "${skills}"
|
|
449
|
+
done
|
|
450
|
+
|
|
451
|
+
external_source=$(jq -r '.external.source // empty' "${manifest}")
|
|
452
|
+
if [ -n "${external_source}" ]; then
|
|
453
|
+
printf '\n'
|
|
454
|
+
printf 'external (from %s):\n' "${external_source}"
|
|
455
|
+
ext=$(jq -r '.external.skills[]?' "${manifest}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
|
|
456
|
+
printf ' %s\n' "${ext}"
|
|
457
|
+
fi
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if [ "${list_only}" -eq 1 ]; then
|
|
461
|
+
print_list
|
|
462
|
+
exit 0
|
|
463
|
+
fi
|
|
464
|
+
|
|
465
|
+
if [ "${clean_only}" -eq 1 ]; then
|
|
466
|
+
# Sweep every known agent directory (both the canonical link layer and any
|
|
467
|
+
# leftovers from the legacy per-agent layout), then the canonical directory.
|
|
468
|
+
for agent in ${known_agents}; do
|
|
469
|
+
clean_harness "$(agent_dir "${agent}")"
|
|
470
|
+
done
|
|
471
|
+
if [ -d "${agents_dir}" ]; then
|
|
472
|
+
rm -rf "${agents_dir}"
|
|
473
|
+
echo "info: removed skills under .agents/skills/."
|
|
474
|
+
fi
|
|
475
|
+
echo "info: removed all skill symlinks under .claude/skills/, .codex/skills/ and .cursor/skills/."
|
|
476
|
+
exit 0
|
|
477
|
+
fi
|
|
478
|
+
|
|
479
|
+
selected_tiers=""
|
|
480
|
+
|
|
481
|
+
case "${mode}" in
|
|
482
|
+
""|"with")
|
|
483
|
+
for tier in ${default_tier_names}; do
|
|
484
|
+
selected_tiers="${selected_tiers}
|
|
485
|
+
${tier}"
|
|
486
|
+
done
|
|
487
|
+
if [ "${mode}" = "with" ]; then
|
|
488
|
+
extra_tiers=$(split_csv "${with_csv}")
|
|
489
|
+
if [ -z "${extra_tiers}" ]; then
|
|
490
|
+
echo "install-skills: --with requires at least one tier name." >&2
|
|
491
|
+
exit 1
|
|
492
|
+
fi
|
|
493
|
+
for tier in ${extra_tiers}; do
|
|
494
|
+
if ! tier_defined "${tier}"; then
|
|
495
|
+
echo "install-skills: unknown tier '${tier}'." >&2
|
|
496
|
+
echo " Valid tiers: $(printf '%s\n' ${all_tier_names} | tr '\n' ' ' | sed 's/ $//')" >&2
|
|
497
|
+
exit 1
|
|
498
|
+
fi
|
|
499
|
+
selected_tiers="${selected_tiers}
|
|
500
|
+
${tier}"
|
|
501
|
+
done
|
|
502
|
+
fi
|
|
503
|
+
;;
|
|
504
|
+
"tiers")
|
|
505
|
+
requested_tiers=$(split_csv "${tiers_csv}")
|
|
506
|
+
if [ -z "${requested_tiers}" ]; then
|
|
507
|
+
echo "install-skills: --tiers requires at least one tier name." >&2
|
|
508
|
+
exit 1
|
|
509
|
+
fi
|
|
510
|
+
for tier in ${requested_tiers}; do
|
|
511
|
+
if ! tier_defined "${tier}"; then
|
|
512
|
+
echo "install-skills: unknown tier '${tier}'." >&2
|
|
513
|
+
echo " Valid tiers: $(printf '%s\n' ${all_tier_names} | tr '\n' ' ' | sed 's/ $//')" >&2
|
|
514
|
+
exit 1
|
|
515
|
+
fi
|
|
516
|
+
selected_tiers="${selected_tiers}
|
|
517
|
+
${tier}"
|
|
518
|
+
done
|
|
519
|
+
;;
|
|
520
|
+
"all")
|
|
521
|
+
for tier in ${all_tier_names}; do
|
|
522
|
+
selected_tiers="${selected_tiers}
|
|
523
|
+
${tier}"
|
|
524
|
+
done
|
|
525
|
+
;;
|
|
526
|
+
esac
|
|
527
|
+
|
|
528
|
+
selected_tiers=$(printf '%s\n' "${selected_tiers}" | dedup_lines)
|
|
529
|
+
|
|
530
|
+
selected_skills=""
|
|
531
|
+
for tier in ${selected_tiers}; do
|
|
532
|
+
for skill in $(tier_skills "${tier}"); do
|
|
533
|
+
selected_skills="${selected_skills}
|
|
534
|
+
${skill}"
|
|
535
|
+
done
|
|
536
|
+
done
|
|
537
|
+
selected_skills=$(printf '%s\n' "${selected_skills}" | dedup_lines)
|
|
538
|
+
|
|
539
|
+
if [ -z "${selected_skills}" ]; then
|
|
540
|
+
echo "install-skills: no skills selected for installation." >&2
|
|
541
|
+
exit 1
|
|
542
|
+
fi
|
|
543
|
+
|
|
544
|
+
external_skills_list=$(jq -r '.external.skills[]?' "${manifest}")
|
|
545
|
+
|
|
546
|
+
is_external_skill() {
|
|
547
|
+
needle="$1"
|
|
548
|
+
for candidate in ${external_skills_list}; do
|
|
549
|
+
if [ "${candidate}" = "${needle}" ]; then
|
|
550
|
+
return 0
|
|
551
|
+
fi
|
|
552
|
+
done
|
|
553
|
+
return 1
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
# Local tier skills live once, in the canonical cross-agent directory.
|
|
557
|
+
install_canonical() {
|
|
558
|
+
prepare_harness_dir "${agents_dir}"
|
|
559
|
+
for skill in ${selected_skills}; do
|
|
560
|
+
if is_external_skill "${skill}"; then
|
|
561
|
+
# Owned by the external collection; a same-named .ai/skills/ folder is a
|
|
562
|
+
# repo-local override and must not shadow the npx-installed skill.
|
|
563
|
+
echo "install-skills: warning: '${skill}' is an external skill; skipping local symlink." >&2
|
|
564
|
+
continue
|
|
565
|
+
fi
|
|
566
|
+
skill_target="${skills_dir}/${skill}"
|
|
567
|
+
if [ ! -d "${skill_target}" ]; then
|
|
568
|
+
echo "install-skills: skill folder '${skill_target}' is missing on disk." >&2
|
|
569
|
+
exit 1
|
|
570
|
+
fi
|
|
571
|
+
ln -sfn "../../.ai/skills/${skill}" "${agents_dir}/${skill}"
|
|
572
|
+
done
|
|
573
|
+
sweep_harness "${agents_dir}" "${selected_skills}"
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
# Link layer for agents that cannot read the canonical directory. External
|
|
577
|
+
# skills are linked by the skills CLI itself (via the --agent args below), so
|
|
578
|
+
# only the local tier skills are linked here.
|
|
579
|
+
install_agent_links() {
|
|
580
|
+
agent="$1"
|
|
581
|
+
harness_dir=$(agent_dir "${agent}")
|
|
582
|
+
prepare_harness_dir "${harness_dir}"
|
|
583
|
+
for skill in ${selected_skills}; do
|
|
584
|
+
if is_external_skill "${skill}"; then
|
|
585
|
+
continue
|
|
586
|
+
fi
|
|
587
|
+
if [ "${legacy_links}" -eq 1 ]; then
|
|
588
|
+
ln -sfn "../../.ai/skills/${skill}" "${harness_dir}/${skill}"
|
|
589
|
+
else
|
|
590
|
+
ln -sfn "../../.agents/skills/${skill}" "${harness_dir}/${skill}"
|
|
591
|
+
fi
|
|
592
|
+
done
|
|
593
|
+
link_external_skills "${harness_dir}"
|
|
594
|
+
sweep_harness "${harness_dir}" "${selected_skills}"
|
|
595
|
+
prune_broken_links "${harness_dir}"
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
# Mirror every external skill (a real directory under the canonical dir) into an
|
|
599
|
+
# agent's own directory. Local tier skills are symlinks and are skipped here.
|
|
600
|
+
#
|
|
601
|
+
# `npx skills add --agent <id>` is supposed to write these links itself, but it
|
|
602
|
+
# only does so reliably for an agent directory that already exists (see
|
|
603
|
+
# vercel-labs/skills#744) and the canonical layout no longer pre-creates one. So
|
|
604
|
+
# the script owns this layer end to end: an agent that cannot read
|
|
605
|
+
# .agents/skills/ would otherwise silently lose the whole shared collection.
|
|
606
|
+
link_external_skills() {
|
|
607
|
+
harness_dir="$1"
|
|
608
|
+
[ -d "${agents_dir}" ] || return 0
|
|
609
|
+
for entry in "${agents_dir}"/*; do
|
|
610
|
+
[ -L "${entry}" ] && continue
|
|
611
|
+
[ -d "${entry}" ] || continue
|
|
612
|
+
external_name=$(basename "${entry}")
|
|
613
|
+
ln -sfn "../../.agents/skills/${external_name}" "${harness_dir}/${external_name}"
|
|
614
|
+
done
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
# Mix in the external shared collection (open-mercato/skills). Only the explicit
|
|
618
|
+
# subset this app ships (external.skills) is installed — never the whole
|
|
619
|
+
# collection. The npx CLI copies each skill into .agents/skills/. This runs BEFORE
|
|
620
|
+
# the link layer is written: `skills update --project` owns .agents/skills/ and
|
|
621
|
+
# would otherwise prune entries it does not know about. The agent directories are
|
|
622
|
+
# written afterwards by install_agent_links, which does not rely on the CLI's own
|
|
623
|
+
# symlinking.
|
|
624
|
+
external_source=$(jq -r '.external.source // empty' "${manifest}")
|
|
625
|
+
external_status="none"
|
|
626
|
+
# The skills CLI matches each --skill value against skill names verbatim (no
|
|
627
|
+
# comma splitting), so the subset must be passed as repeated --skill flags.
|
|
628
|
+
external_skill_args=""
|
|
629
|
+
for external_skill in $(printf '%s\n' "${external_skills_list}" | dedup_lines); do
|
|
630
|
+
external_skill_args="${external_skill_args} --skill ${external_skill}"
|
|
631
|
+
done
|
|
632
|
+
external_agent_args=""
|
|
633
|
+
for agent in ${link_agents}; do
|
|
634
|
+
external_agent_args="${external_agent_args} --agent ${agent}"
|
|
635
|
+
done
|
|
636
|
+
if [ -z "${external_agent_args}" ]; then
|
|
637
|
+
# No agent needs its own directory — install into .agents/skills/ only.
|
|
638
|
+
external_agent_args=" --agent universal"
|
|
639
|
+
fi
|
|
640
|
+
if [ -n "${external_source}" ] && [ -n "${external_skill_args}" ]; then
|
|
641
|
+
if [ "${no_external}" = "1" ]; then
|
|
642
|
+
external_status="skipped (--no-external)"
|
|
643
|
+
elif ! command -v npx >/dev/null 2>&1; then
|
|
644
|
+
external_status="skipped (npx not found)"
|
|
645
|
+
echo "install-skills: warning: npx not found; skipping external skills from ${external_source}." >&2
|
|
646
|
+
elif (cd "${repo_root}" && npx -y skills add "${external_source}" ${external_skill_args} ${external_agent_args} -y); then
|
|
647
|
+
external_status="installed from ${external_source}"
|
|
648
|
+
# `add` seeds the subset; a follow-up `update` bumps already-installed skills
|
|
649
|
+
# to the latest published versions on a re-run. Non-fatal when offline mid-run.
|
|
650
|
+
if (cd "${repo_root}" && npx -y skills update --project -y); then
|
|
651
|
+
external_status="updated to latest from ${external_source}"
|
|
652
|
+
else
|
|
653
|
+
echo "install-skills: warning: could not update external skills to latest;" >&2
|
|
654
|
+
echo " the installed versions are kept. Re-run when online to refresh." >&2
|
|
655
|
+
fi
|
|
656
|
+
else
|
|
657
|
+
external_status="FAILED"
|
|
658
|
+
echo "install-skills: warning: installing external skills from ${external_source} failed;" >&2
|
|
659
|
+
echo " local tier skills are installed. Re-run when online, or pass --no-external to silence this." >&2
|
|
660
|
+
fi
|
|
661
|
+
fi
|
|
662
|
+
|
|
663
|
+
install_canonical
|
|
664
|
+
|
|
665
|
+
for agent in ${known_agents}; do
|
|
666
|
+
if is_link_agent "${agent}"; then
|
|
667
|
+
install_agent_links "${agent}"
|
|
668
|
+
else
|
|
669
|
+
# Not a link target (reads the canonical directory, or ignored): drop any
|
|
670
|
+
# stale symlinks left behind by the legacy per-agent layout.
|
|
671
|
+
clean_harness "$(agent_dir "${agent}")"
|
|
672
|
+
fi
|
|
673
|
+
done
|
|
674
|
+
|
|
675
|
+
skill_count=$(printf '%s\n' "${selected_skills}" | grep -c '.' || true)
|
|
676
|
+
tier_count=$(printf '%s\n' "${selected_tiers}" | grep -c '.' || true)
|
|
677
|
+
tier_summary=$(printf '%s\n' "${selected_tiers}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
|
|
678
|
+
|
|
679
|
+
printf 'Installed %s local skills across %s tiers: %s.\n' "${skill_count}" "${tier_count}" "${tier_summary}"
|
|
680
|
+
if [ "${external_status}" != "none" ]; then
|
|
681
|
+
printf 'External skills: %s.\n' "${external_status}"
|
|
682
|
+
fi
|
|
683
|
+
link_summary=$(printf '%s' "${link_agents}" | sed 's/^ *//; s/ /, /g')
|
|
684
|
+
if [ -z "${link_summary}" ]; then
|
|
685
|
+
printf 'Layout: .agents/skills/ (canonical); no per-agent symlinks.\n'
|
|
686
|
+
else
|
|
687
|
+
printf 'Layout: .agents/skills/ (canonical); per-agent symlinks: %s.\n' "${link_summary}"
|
|
688
|
+
fi
|
|
689
|
+
|
|
690
|
+
if [ -z "${mode}" ]; then
|
|
691
|
+
cat <<'EOF'
|
|
692
|
+
Tip: opt into more skills with `yarn install-skills --with automation` or `--all`.
|
|
693
|
+
See `yarn install-skills --list` for the full catalog.
|
|
694
|
+
EOF
|
|
695
|
+
fi
|