@paradigma-inc/flywheel 0.1.53 → 0.1.72
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/README.md +149 -17
- package/package.json +4 -2
- package/skills/flywheel/SKILL.md +4 -3
- package/skills/flywheel/getting-started/flywheel-quickstart.md +4 -4
- package/skills/flywheel/references/flywheel-cli-tool-map.md +47 -35
- package/skills/flywheel/references/flywheel-mcp-tool-map.md +16 -5
- package/skills/flywheel/setting-up-flywheel/claude-code-cli-installation.md +3 -3
- package/skills/flywheel/setting-up-flywheel/codex-cli-installation.md +3 -3
- package/skills/flywheel/setting-up-flywheel/installation-overview.md +9 -8
- package/skills/flywheel/setting-up-flywheel/other-hosts-installation.md +1 -1
- package/skills/flywheel/setting-up-flywheel/updating-flywheel-mcp.md +4 -4
- package/skills/flywheel-auto/SKILL.md +4 -3
- package/skills/flywheel-auto/references/flywheel-cli-tool-map.md +37 -35
- package/skills/flywheel-auto/references/flywheel-mcp-tool-map.md +4 -4
- package/skills/flywheel-lookahead/SKILL.md +1 -1
- package/skills/flywheel-lookahead/references/flywheel-cli-tool-map.md +37 -35
- package/skills/flywheel-lookahead/references/flywheel-mcp-tool-map.md +4 -4
- package/skills/flywheel-prove/SKILL.md +1 -1
- package/skills/flywheel-reproduce/SKILL.md +4 -3
- package/skills/flywheel-reproduce/references/flywheel-cli-tool-map.md +37 -35
- package/skills/flywheel-reproduce/references/flywheel-mcp-tool-map.md +4 -4
- package/skills/flywheel-to-graph/SKILL.md +1 -1
- package/skills/flywheel-to-graph/references/flywheel-cli-tool-map.md +37 -35
- package/skills/flywheel-to-graph/references/flywheel-mcp-tool-map.md +4 -4
- package/skills/flywheel-tree/SKILL.md +1 -1
- package/src/agents.mjs +114 -48
- package/src/cli.mjs +373 -56
- package/src/mcp-writer.mjs +190 -17
- package/src/runtime/required-runtime-commands.json +19 -4
- package/src/runtime/vendor/flywheel-cli-dist/auth/login.d.ts +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/auth/login.js +3 -6
- package/src/runtime/vendor/flywheel-cli-dist/auth/login.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/auth/profiles.d.ts +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/auth/profiles.js +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/auth/profiles.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/_admin-auth.d.ts +27 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_admin-auth.js +54 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_admin-auth.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_artifacts-upload-helpers.d.ts +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/_artifacts-upload-helpers.js +6 -5
- package/src/runtime/vendor/flywheel-cli-dist/commands/_artifacts-upload-helpers.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/_browser-handoff.d.ts +21 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_browser-handoff.js +51 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_browser-handoff.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_open-url.d.ts +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/_open-url.js +6 -3
- package/src/runtime/vendor/flywheel-cli-dist/commands/_open-url.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/_secret-param.d.ts +7 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_secret-param.js +18 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_secret-param.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_stream-file-out.d.ts +39 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_stream-file-out.js +72 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/_stream-file-out.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-detach.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-detach.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-add.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-add.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-remove.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-remove.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-set-primary.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-set-primary.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-get.d.ts +2 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-get.js +6 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-get.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge-preview.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge-preview.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge-proof.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge-proof.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-get.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-get.js +11 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-get.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-set.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-set.js +60 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-set.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export-stream.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export-stream.js +115 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export-stream.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export.js +12 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-list.d.ts +4 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-list.js +39 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-list.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-nodes-audit-list.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-nodes-audit-list.js +15 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/admin-nodes-audit-list.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/api-keys-list.d.ts +18 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/api-keys-list.js +38 -5
- package/src/runtime/vendor/flywheel-cli-dist/commands/api-keys-list.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete.js +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/auth-mode.d.ts +4 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/auth-mode.js +42 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/auth-mode.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/auth-status.js +15 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/auth-status.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-grants-list.js +8 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-grants-list.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-grants-request-approval.js +6 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-grants-request-approval.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-release-all.js +18 -7
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-release-all.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/credits-billing-portal.js +8 -4
- package/src/runtime/vendor/flywheel-cli-dist/commands/credits-billing-portal.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/credits-purchase.js +8 -4
- package/src/runtime/vendor/flywheel-cli-dist/commands/credits-purchase.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/credits-subscribe.js +8 -4
- package/src/runtime/vendor/flywheel-cli-dist/commands/credits-subscribe.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/destructive-confirmation.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/destructive-confirmation.js +7 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/destructive-confirmation.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/enums.d.ts +8 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/enums.js +4 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/enums.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/env.d.ts +0 -4
- package/src/runtime/vendor/flywheel-cli-dist/commands/env.js +7 -12
- package/src/runtime/vendor/flywheel-cli-dist/commands/env.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/export-history.js +42 -30
- package/src/runtime/vendor/flywheel-cli-dist/commands/export-history.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/export-subgraph.js +12 -4
- package/src/runtime/vendor/flywheel-cli-dist/commands/export-subgraph.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/github-link.js +9 -14
- package/src/runtime/vendor/flywheel-cli-dist/commands/github-link.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/help-format.d.ts +31 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/help-format.js +69 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/help-format.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/help.d.ts +6 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/help.js +226 -124
- package/src/runtime/vendor/flywheel-cli-dist/commands/help.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-create.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-create.js +25 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-create.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-delete.d.ts +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-delete.js +6 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-delete.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-list.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-list.js +10 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-list.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-runs-list.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-runs-list.js +15 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-runs-list.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-create.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-create.js +8 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-create.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-delete.d.ts +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-delete.js +6 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-delete.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-list.d.ts +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-list.js +6 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-list.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-update.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-update.js +8 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-update.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-set-enabled.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-set-enabled.js +8 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-set-enabled.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-update.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-update.js +29 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-update.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/index.js +36 -6
- package/src/runtime/vendor/flywheel-cli-dist/commands/index.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-huggingface-set.js +7 -3
- package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-huggingface-set.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-wandb-set.js +6 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-wandb-set.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-add-parent.js +6 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-add-parent.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete-bulk.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete-bulk.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete.js +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-remove-parent.js +8 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-remove-parent.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-resolve-slug.js +55 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-resolve-slug.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/profile-list.js +13 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/profile-list.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/profile-set.js +4 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/profile-set.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/profile-show.js +16 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/profile-show.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/account.js +8 -7
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/account.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/admin.d.ts +8 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/admin.js +131 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/admin.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/api-keys.js +8 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/api-keys.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/approval.js +29 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/approval.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/artifacts.js +13 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/artifacts.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/auth.js +2 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/auth.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/budgets.js +11 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/budgets.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/compute.js +2 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/compute.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/credits.js +8 -6
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/credits.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/env.js +7 -5
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/env.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/github.js +6 -14
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/github.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hooks.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hooks.js +312 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hooks.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/integrations.js +22 -8
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/integrations.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/lifecycle.js +122 -25
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/lifecycle.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/profile.js +2 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/profile.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/resources.js +1 -31
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/resources.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/sharing.js +12 -4
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry/sharing.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry.d.ts +2 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry.js +46 -9
- package/src/runtime/vendor/flywheel-cli-dist/commands/registry.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-refresh.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-refresh.js +20 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-refresh.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-resolve.d.ts +2 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-resolve.js +23 -0
- package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-resolve.js.map +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/errors.d.ts +15 -0
- package/src/runtime/vendor/flywheel-cli-dist/errors.js +16 -1
- package/src/runtime/vendor/flywheel-cli-dist/errors.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/http/client.d.ts +1 -0
- package/src/runtime/vendor/flywheel-cli-dist/http/client.js +75 -19
- package/src/runtime/vendor/flywheel-cli-dist/http/client.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/http/debug.d.ts +3 -0
- package/src/runtime/vendor/flywheel-cli-dist/http/debug.js +21 -2
- package/src/runtime/vendor/flywheel-cli-dist/http/debug.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/main.js +119 -10
- package/src/runtime/vendor/flywheel-cli-dist/main.js.map +1 -1
- package/src/runtime/vendor/flywheel-cli-dist/output/format.js +44 -6
- package/src/runtime/vendor/flywheel-cli-dist/output/format.js.map +1 -1
- package/src/runtime/vendor/manifest.json +82 -10
- package/src/setup/base-url.mjs +43 -0
- package/src/setup/command.mjs +2 -0
- package/src/setup/io/patchers/json.mjs +2 -0
- package/src/setup/io/patchers/toml.mjs +7 -1
- package/src/setup/io/patchers/yaml.mjs +2 -0
- package/src/setup/modes/cli.mjs +72 -24
- package/src/setup/modes/mcp-command.mjs +146 -38
- package/src/setup/modes/mcp.mjs +26 -1
- package/src/setup/resolved-selection-record.mjs +25 -0
- package/src/setup/shared/prior-mode-detect.mjs +133 -14
- package/src/setup-auth.mjs +3 -2
- package/src/skill-installer.mjs +179 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-policy-get.d.ts +0 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-policy-get.js +0 -6
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-policy-get.js.map +0 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-policy-set.d.ts +0 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-policy-set.js +0 -19
- package/src/runtime/vendor/flywheel-cli-dist/commands/compute-policy-set.js.map +0 -1
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-audit-list.d.ts +0 -2
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-audit-list.js +0 -7
- package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-audit-list.js.map +0 -1
package/src/cli.mjs
CHANGED
|
@@ -2,18 +2,21 @@ import { Command } from "commander";
|
|
|
2
2
|
import { checkbox, select } from "@inquirer/prompts";
|
|
3
3
|
import ora from "ora";
|
|
4
4
|
import pc from "picocolors";
|
|
5
|
-
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { access, readFile, rm } from "node:fs/promises";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
ALL_HOST_NAMES,
|
|
10
10
|
SERVER_NAME,
|
|
11
11
|
SETUP_HOST_NAMES,
|
|
12
|
+
SKILL_ONLY_HOST_NAMES,
|
|
12
13
|
detectHosts,
|
|
13
14
|
getHost,
|
|
15
|
+
isSkillOnlyHost,
|
|
14
16
|
normalizeHosts,
|
|
15
17
|
} from "./agents.mjs";
|
|
16
18
|
import {
|
|
19
|
+
readEntryServerUrl,
|
|
17
20
|
readNamedConfigEntry,
|
|
18
21
|
readJsonConfig,
|
|
19
22
|
readTomlServerEntry,
|
|
@@ -28,10 +31,13 @@ import {
|
|
|
28
31
|
listBundledSkills,
|
|
29
32
|
partitionInstallSkillHosts,
|
|
30
33
|
removeInstalledSkillsForHosts,
|
|
34
|
+
resolveInstalledSkillDir,
|
|
35
|
+
resolveFlywheelInstalledMarkerPath,
|
|
31
36
|
SUPPORTED_INSTALL_SKILL_HOSTS,
|
|
32
37
|
resolvePackageRoot,
|
|
33
38
|
} from "./skill-installer.mjs";
|
|
34
39
|
import { normalizeSetupAuthMode } from "./setup-auth.mjs";
|
|
40
|
+
import { resolveSetupBaseUrl } from "./setup/base-url.mjs";
|
|
35
41
|
import { runSetupRouter } from "./setup/command.mjs";
|
|
36
42
|
import { SetupModeUsageError } from "./setup/mode.mjs";
|
|
37
43
|
import { runCliSetupMode } from "./setup/modes/cli.mjs";
|
|
@@ -42,11 +48,17 @@ import {
|
|
|
42
48
|
import { findFlywheelMcpEntryNames } from "./setup/shared/prior-mode-detect.mjs";
|
|
43
49
|
import { renderSetupSummary } from "./setup/shared/summary.mjs";
|
|
44
50
|
|
|
51
|
+
async function pathExists(targetPath) {
|
|
52
|
+
try {
|
|
53
|
+
await access(targetPath);
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
45
60
|
export { buildGuidedSkillInstallPrompt };
|
|
46
61
|
|
|
47
|
-
const INSTALL_SKILL_BASE_URL = "https://flywheel.paradigma.inc";
|
|
48
|
-
const DEFAULT_BASE_URL =
|
|
49
|
-
process.env.FLYWHEEL_PUBLIC_BASE_URL || INSTALL_SKILL_BASE_URL;
|
|
50
62
|
const log = {
|
|
51
63
|
info: (message) => console.log(pc.cyan(message)),
|
|
52
64
|
warn: (message) => console.log(pc.yellow(`⚠ ${message}`)),
|
|
@@ -62,6 +74,12 @@ const CHECKBOX_THEME = {
|
|
|
62
74
|
},
|
|
63
75
|
};
|
|
64
76
|
|
|
77
|
+
function hostChoiceDescription({ detected = false, configured = false } = {}) {
|
|
78
|
+
if (configured) return "Already has a Flywheel entry for this scope.";
|
|
79
|
+
if (detected) return "Detected on this machine.";
|
|
80
|
+
return "Supported host; select it if you use it here.";
|
|
81
|
+
}
|
|
82
|
+
|
|
65
83
|
function normalizeBaseUrl(value) {
|
|
66
84
|
const normalized = String(value || "").trim();
|
|
67
85
|
let parsedUrl;
|
|
@@ -95,9 +113,12 @@ function normalizeAuthMode(value) {
|
|
|
95
113
|
function selectedHostsFromOptions(options) {
|
|
96
114
|
const hosts = [];
|
|
97
115
|
if (options.claude) hosts.push("claude");
|
|
116
|
+
if (options.cursor) hosts.push("cursor");
|
|
117
|
+
if (options.universal) hosts.push("universal");
|
|
118
|
+
if (options.antigravity) hosts.push("antigravity");
|
|
98
119
|
if (options.opencode) hosts.push("opencode");
|
|
99
120
|
if (options.codex) hosts.push("codex");
|
|
100
|
-
if (options.
|
|
121
|
+
if (options.gemini) hosts.push("gemini");
|
|
101
122
|
if (options.piMono) hosts.push("pi-mono");
|
|
102
123
|
if (options.hermesAgent) hosts.push("hermes-agent");
|
|
103
124
|
if (options.openclaw) hosts.push("openclaw");
|
|
@@ -109,6 +130,9 @@ const UNINSTALL_OPTION_KEY_BY_HOST = Object.freeze({
|
|
|
109
130
|
codex: "codex",
|
|
110
131
|
opencode: "opencode",
|
|
111
132
|
cursor: "cursor",
|
|
133
|
+
gemini: "gemini",
|
|
134
|
+
universal: "universal",
|
|
135
|
+
antigravity: "antigravity",
|
|
112
136
|
"pi-mono": "piMono",
|
|
113
137
|
"hermes-agent": "hermesAgent",
|
|
114
138
|
openclaw: "openclaw",
|
|
@@ -167,6 +191,9 @@ async function isAlreadyConfigured(hostName, scope, serverName) {
|
|
|
167
191
|
|
|
168
192
|
async function readExistingServerState(hostName, scope, serverName) {
|
|
169
193
|
const host = getHost(hostName);
|
|
194
|
+
if (isSkillOnlyHost(host)) {
|
|
195
|
+
return { exists: false, url: null, mcpPath: null };
|
|
196
|
+
}
|
|
170
197
|
const mcpPath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
|
|
171
198
|
|
|
172
199
|
if (host.mcp.configType === "toml") {
|
|
@@ -181,7 +208,7 @@ async function readExistingServerState(hostName, scope, serverName) {
|
|
|
181
208
|
const entry = readNamedConfigEntry(existing, host.mcp.configKey, serverName);
|
|
182
209
|
return {
|
|
183
210
|
exists: entry !== null,
|
|
184
|
-
url:
|
|
211
|
+
url: readEntryServerUrl(entry),
|
|
185
212
|
mcpPath,
|
|
186
213
|
};
|
|
187
214
|
}
|
|
@@ -202,6 +229,11 @@ async function promptHosts(
|
|
|
202
229
|
return {
|
|
203
230
|
name: SETUP_HOST_NAMES[hostName],
|
|
204
231
|
value: hostName,
|
|
232
|
+
short: SETUP_HOST_NAMES[hostName],
|
|
233
|
+
description: hostChoiceDescription({
|
|
234
|
+
detected: detected.includes(hostName),
|
|
235
|
+
configured,
|
|
236
|
+
}),
|
|
205
237
|
checked: detected.includes(hostName),
|
|
206
238
|
disabled:
|
|
207
239
|
disableAlreadyConfigured && configured
|
|
@@ -272,15 +304,23 @@ export function buildSetupModePromptConfig() {
|
|
|
272
304
|
message: "How should your agent access Flywheel?",
|
|
273
305
|
choices: [
|
|
274
306
|
{
|
|
275
|
-
name:
|
|
307
|
+
name: "MCP + bundled skills",
|
|
276
308
|
value: "mcp",
|
|
309
|
+
short: "MCP + skills",
|
|
310
|
+
description:
|
|
311
|
+
"Configure MCP tools plus bundled skills for supported AI hosts.",
|
|
277
312
|
},
|
|
278
313
|
{
|
|
279
|
-
name:
|
|
314
|
+
name: "CLI + bundled skills",
|
|
280
315
|
value: "cli",
|
|
316
|
+
short: "CLI + skills",
|
|
317
|
+
description:
|
|
318
|
+
"Install bundled skills for agents that call the flywheel binary.",
|
|
281
319
|
},
|
|
282
320
|
],
|
|
283
321
|
default: "mcp",
|
|
322
|
+
loop: false,
|
|
323
|
+
pageSize: 4,
|
|
284
324
|
theme: CHECKBOX_THEME,
|
|
285
325
|
};
|
|
286
326
|
}
|
|
@@ -289,7 +329,19 @@ async function promptSetupMode() {
|
|
|
289
329
|
return await select(buildSetupModePromptConfig());
|
|
290
330
|
}
|
|
291
331
|
|
|
292
|
-
|
|
332
|
+
/**
|
|
333
|
+
* Validate the flag combination for --mode cli. Rejections raise
|
|
334
|
+
* `SetupModeUsageError` so the top-level handler reports them as usage
|
|
335
|
+
* errors (exit code 2) and not as operational failures.
|
|
336
|
+
*
|
|
337
|
+
* `--oauth` controls the MCP config written in --mode mcp (it omits the
|
|
338
|
+
* Authorization header so the IDE can discover MCP 2.0 OAuth instead).
|
|
339
|
+
* --mode cli writes no MCP config at all, so there is nothing for --oauth
|
|
340
|
+
* to modify. Silently accepting it would look successful but still fall
|
|
341
|
+
* back to API-key auth in the runtime config — a misconfiguration. Reject
|
|
342
|
+
* it up front with guidance toward the correct invocation.
|
|
343
|
+
*/
|
|
344
|
+
function validateCliModeFlags(options) {
|
|
293
345
|
if (options.installSkill && options.skipSkill) {
|
|
294
346
|
throw new SetupModeUsageError(
|
|
295
347
|
"--install-skill and --skip-skill cannot be used together.",
|
|
@@ -302,12 +354,19 @@ function validateCliModeSkillFlags(options) {
|
|
|
302
354
|
"--skip-skill is not supported with --mode cli; use --mode mcp --skip-skill for MCP-only setup.",
|
|
303
355
|
);
|
|
304
356
|
}
|
|
357
|
+
if (options.oauth === true) {
|
|
358
|
+
throw new SetupModeUsageError(
|
|
359
|
+
"--oauth is not supported with --mode cli. --oauth only affects the MCP config written by --mode mcp; re-run with --mode mcp --oauth, or drop --oauth for a CLI-mode setup.",
|
|
360
|
+
);
|
|
361
|
+
}
|
|
305
362
|
}
|
|
306
363
|
|
|
307
364
|
async function runCliModeCommand(options) {
|
|
308
|
-
|
|
365
|
+
validateCliModeFlags(options);
|
|
309
366
|
const scope = options.project ? "project" : "global";
|
|
310
|
-
const baseUrl = normalizeBaseUrl(
|
|
367
|
+
const baseUrl = normalizeBaseUrl(
|
|
368
|
+
resolveSetupBaseUrl({ explicitBaseUrl: options.baseUrl }),
|
|
369
|
+
);
|
|
311
370
|
const serverUrl = `${baseUrl}/mcp-server`;
|
|
312
371
|
const serverName = normalizeServerName(options.name || SERVER_NAME);
|
|
313
372
|
const hosts = await resolveHosts(options, scope, serverName, {
|
|
@@ -380,7 +439,8 @@ async function runCliModeCommand(options) {
|
|
|
380
439
|
|
|
381
440
|
async function runSetupCommandViaRouter(options) {
|
|
382
441
|
return await runSetupRouter(options, {
|
|
383
|
-
isInteractive:
|
|
442
|
+
isInteractive:
|
|
443
|
+
process.stdin.isTTY === true && process.stdout.isTTY === true,
|
|
384
444
|
promptMode: promptSetupMode,
|
|
385
445
|
runMcpMode: async () =>
|
|
386
446
|
await runMcpModeCommand(options, {
|
|
@@ -460,8 +520,12 @@ function readConfigSection(config, configKey) {
|
|
|
460
520
|
|
|
461
521
|
function parseTomlServerNames(tomlText) {
|
|
462
522
|
const serverNames = new Set();
|
|
463
|
-
for (const line of String(tomlText || "")
|
|
464
|
-
|
|
523
|
+
for (const line of String(tomlText || "")
|
|
524
|
+
.replace(/\r\n/g, "\n")
|
|
525
|
+
.split("\n")) {
|
|
526
|
+
const match = line
|
|
527
|
+
.trim()
|
|
528
|
+
.match(/^\[mcp_servers\.([A-Za-z0-9_-]+)\](?:\s*#.*)?$/);
|
|
465
529
|
if (!match) {
|
|
466
530
|
continue;
|
|
467
531
|
}
|
|
@@ -484,6 +548,9 @@ function isLikelyFlywheelMcpUrl(url) {
|
|
|
484
548
|
|
|
485
549
|
async function listHostMcpEntries(hostName, scope) {
|
|
486
550
|
const host = getHost(hostName);
|
|
551
|
+
if (isSkillOnlyHost(host)) {
|
|
552
|
+
return [];
|
|
553
|
+
}
|
|
487
554
|
const filePath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
|
|
488
555
|
|
|
489
556
|
if (host.mcp.configType === "toml") {
|
|
@@ -514,10 +581,13 @@ async function listHostMcpEntries(hostName, scope) {
|
|
|
514
581
|
: await readJsonConfig(filePath);
|
|
515
582
|
const section = readConfigSection(config, host.mcp.configKey);
|
|
516
583
|
return Object.entries(section)
|
|
517
|
-
.filter(
|
|
584
|
+
.filter(
|
|
585
|
+
([, entry]) =>
|
|
586
|
+
entry && typeof entry === "object" && !Array.isArray(entry),
|
|
587
|
+
)
|
|
518
588
|
.map(([serverName, entry]) => ({
|
|
519
589
|
serverName,
|
|
520
|
-
url:
|
|
590
|
+
url: readEntryServerUrl(entry),
|
|
521
591
|
}));
|
|
522
592
|
}
|
|
523
593
|
|
|
@@ -525,7 +595,9 @@ async function resolveHostsWithRemainingFlywheelMcpEntries({ scope }) {
|
|
|
525
595
|
const remainingHosts = [];
|
|
526
596
|
for (const hostName of SUPPORTED_INSTALL_SKILL_HOSTS) {
|
|
527
597
|
// eslint-disable-next-line no-await-in-loop
|
|
528
|
-
const hostEntries = await listHostMcpEntries(hostName, scope).catch(
|
|
598
|
+
const hostEntries = await listHostMcpEntries(hostName, scope).catch(
|
|
599
|
+
() => [],
|
|
600
|
+
);
|
|
529
601
|
if (hostEntries.some((entry) => isLikelyFlywheelMcpUrl(entry.url))) {
|
|
530
602
|
remainingHosts.push(hostName);
|
|
531
603
|
}
|
|
@@ -533,14 +605,68 @@ async function resolveHostsWithRemainingFlywheelMcpEntries({ scope }) {
|
|
|
533
605
|
return remainingHosts;
|
|
534
606
|
}
|
|
535
607
|
|
|
608
|
+
/**
|
|
609
|
+
* Determine which non-uninstalled hosts still claim bundled skill artifacts
|
|
610
|
+
* via their install marker, and therefore must keep their (possibly shared)
|
|
611
|
+
* skill directories intact.
|
|
612
|
+
*
|
|
613
|
+
* The install marker (`.flywheel-installed-by-<host>`) is written by
|
|
614
|
+
* `installBundledSkillForHosts` for any host whose install path produces no
|
|
615
|
+
* MCP entry:
|
|
616
|
+
*
|
|
617
|
+
* - skill-only hosts (universal, antigravity): marker always written.
|
|
618
|
+
* - MCP-capable hosts (codex, opencode, cursor, claude, pi-mono, openclaw,
|
|
619
|
+
* gemini): marker written ONLY when the host was installed via
|
|
620
|
+
* `--mode cli`, because CLI-mode installs write no MCP entry.
|
|
621
|
+
*
|
|
622
|
+
* A marker at a skill-root is therefore the unambiguous "this host still
|
|
623
|
+
* owns these skills" signal for both categories. Narrowing the retain pass
|
|
624
|
+
* to skill-only hosts would let `uninstall --universal` silently wipe the
|
|
625
|
+
* shared `.agents/skills/` dir out from under a still-installed CLI-mode
|
|
626
|
+
* codex. Using dir existence alone would over-retain for hosts that never
|
|
627
|
+
* installed anything. The per-host marker resolves both.
|
|
628
|
+
*
|
|
629
|
+
* `excludedHostNames` is the list of hosts currently being uninstalled;
|
|
630
|
+
* their markers will be removed and their artifacts are expected to go, so
|
|
631
|
+
* they are excluded from retention here.
|
|
632
|
+
*/
|
|
633
|
+
async function resolveSkillOnlyHostsRetainingArtifacts({
|
|
634
|
+
scope,
|
|
635
|
+
excludedHostNames = [],
|
|
636
|
+
}) {
|
|
637
|
+
const excluded = new Set(excludedHostNames);
|
|
638
|
+
const retained = [];
|
|
639
|
+
for (const hostName of SUPPORTED_INSTALL_SKILL_HOSTS) {
|
|
640
|
+
if (excluded.has(hostName)) continue;
|
|
641
|
+
let markerPath;
|
|
642
|
+
try {
|
|
643
|
+
markerPath = resolveFlywheelInstalledMarkerPath(
|
|
644
|
+
process.cwd(),
|
|
645
|
+
hostName,
|
|
646
|
+
scope,
|
|
647
|
+
);
|
|
648
|
+
} catch {
|
|
649
|
+
// Host isn't registered with the flywheel skill installer; no marker
|
|
650
|
+
// to consult, nothing to retain.
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
// eslint-disable-next-line no-await-in-loop
|
|
654
|
+
const markerExists = await pathExists(markerPath);
|
|
655
|
+
if (markerExists) {
|
|
656
|
+
retained.push(hostName);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return retained;
|
|
660
|
+
}
|
|
661
|
+
|
|
536
662
|
async function findFlywheelServerNamesOnHost(hostName, scope) {
|
|
537
663
|
// Mirror setup's prior-mode detector: walk every MCP entry on the host and
|
|
538
664
|
// keep those whose URL is Flywheel-identifying (hostname contains "flywheel"
|
|
539
665
|
// or path === /mcp-server with a matching target origin). Uninstall must
|
|
540
|
-
// catch renamed
|
|
541
|
-
// setup already detects; otherwise a user
|
|
542
|
-
// name is stuck between setup ("already
|
|
543
|
-
// configured").
|
|
666
|
+
// catch renamed or drifted entries (e.g. a non-default TOML section name
|
|
667
|
+
// under `[mcp_servers.*]`) that setup already detects; otherwise a user
|
|
668
|
+
// whose host has a non-default entry name is stuck between setup ("already
|
|
669
|
+
// installed") and uninstall ("not configured").
|
|
544
670
|
return await findFlywheelMcpEntryNames({ hostName, scope }).catch(() => []);
|
|
545
671
|
}
|
|
546
672
|
|
|
@@ -574,10 +700,92 @@ async function isConfiguredForUninstallScope(
|
|
|
574
700
|
{ explicitServerName },
|
|
575
701
|
);
|
|
576
702
|
if (targets.length > 0) return true;
|
|
703
|
+
// Skill-only hosts and CLI-mode MCP-capable hosts never write an MCP
|
|
704
|
+
// entry, so the sweep above finds nothing for them. Fall back to the
|
|
705
|
+
// install marker: if this host wrote its own ownership marker in the
|
|
706
|
+
// selected scope, it IS configured for the purposes of the uninstall
|
|
707
|
+
// prompt.
|
|
708
|
+
if (SUPPORTED_INSTALL_SKILL_HOSTS.includes(hostName)) {
|
|
709
|
+
try {
|
|
710
|
+
const markerPath = resolveFlywheelInstalledMarkerPath(
|
|
711
|
+
process.cwd(),
|
|
712
|
+
hostName,
|
|
713
|
+
singleScope,
|
|
714
|
+
);
|
|
715
|
+
// eslint-disable-next-line no-await-in-loop
|
|
716
|
+
if (await pathExists(markerPath)) return true;
|
|
717
|
+
} catch {
|
|
718
|
+
// Host isn't registered with the skill installer; nothing to check.
|
|
719
|
+
}
|
|
720
|
+
}
|
|
577
721
|
}
|
|
578
722
|
return false;
|
|
579
723
|
}
|
|
580
724
|
|
|
725
|
+
/**
|
|
726
|
+
* Public wrapper exposing the uninstall-eligibility check used by the
|
|
727
|
+
* interactive prompt. Returns true when the host has either a Flywheel MCP
|
|
728
|
+
* entry OR a Flywheel install marker in the requested scope. Exported so
|
|
729
|
+
* tests can verify that skill-only hosts surface as configurable in the
|
|
730
|
+
* prompt even though they write no MCP entry.
|
|
731
|
+
*/
|
|
732
|
+
export async function isHostConfiguredForUninstall({
|
|
733
|
+
hostName,
|
|
734
|
+
scope = "project",
|
|
735
|
+
serverName = SERVER_NAME,
|
|
736
|
+
} = {}) {
|
|
737
|
+
// Mirror `runUninstallCommand`'s derivation: only treat the caller's
|
|
738
|
+
// `serverName` as "explicit" when it differs from the package default.
|
|
739
|
+
// An explicit name short-circuits the Flywheel-identifying sweep in
|
|
740
|
+
// `resolveUninstallServerNamesForHost`, which the default-named case
|
|
741
|
+
// needs to run so drifted entries (and the marker fallback for
|
|
742
|
+
// skill-only / CLI-mode hosts) are reachable.
|
|
743
|
+
const explicitServerName =
|
|
744
|
+
typeof serverName === "string" &&
|
|
745
|
+
serverName.length > 0 &&
|
|
746
|
+
serverName !== SERVER_NAME
|
|
747
|
+
? serverName
|
|
748
|
+
: null;
|
|
749
|
+
return isConfiguredForUninstallScope(hostName, scope, { explicitServerName });
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Remove every Flywheel install marker for the requested hosts across the
|
|
754
|
+
* requested scopes. Exported and implemented as a standalone helper so it
|
|
755
|
+
* can run independently of bundled-skill discovery: a package with a
|
|
756
|
+
* missing or trimmed `skills/` directory must still be able to uninstall
|
|
757
|
+
* cleanly, otherwise stale markers leak into later prompt-eligibility,
|
|
758
|
+
* retention, and prior-mode-detection logic. `rm ..., { force: true }`
|
|
759
|
+
* makes the operation idempotent — hosts that never wrote a marker (e.g.
|
|
760
|
+
* MCP-capable hosts installed only via `--mode mcp`) are silent no-ops.
|
|
761
|
+
*
|
|
762
|
+
* Hosts not registered with the Flywheel skill installer are skipped
|
|
763
|
+
* rather than throwing, so callers can pass the full uninstall host list
|
|
764
|
+
* without pre-filtering.
|
|
765
|
+
*/
|
|
766
|
+
export async function cleanupHostInstallMarkers({
|
|
767
|
+
cwd = process.cwd(),
|
|
768
|
+
scopes = ["project"],
|
|
769
|
+
hostNames = [],
|
|
770
|
+
} = {}) {
|
|
771
|
+
for (const singleScope of scopes) {
|
|
772
|
+
for (const hostName of hostNames) {
|
|
773
|
+
let markerPath;
|
|
774
|
+
try {
|
|
775
|
+
markerPath = resolveFlywheelInstalledMarkerPath(
|
|
776
|
+
cwd,
|
|
777
|
+
hostName,
|
|
778
|
+
singleScope,
|
|
779
|
+
);
|
|
780
|
+
} catch {
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
// eslint-disable-next-line no-await-in-loop
|
|
784
|
+
await rm(markerPath, { force: true });
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
581
789
|
async function promptUninstallScope(defaultScope) {
|
|
582
790
|
try {
|
|
583
791
|
return await select({
|
|
@@ -674,6 +882,14 @@ async function resolveUninstallTargets(options, { explicitServerName }) {
|
|
|
674
882
|
|
|
675
883
|
async function removeHostConfig(hostName, scope, serverName) {
|
|
676
884
|
const host = getHost(hostName);
|
|
885
|
+
if (isSkillOnlyHost(host)) {
|
|
886
|
+
return {
|
|
887
|
+
host: host.displayName,
|
|
888
|
+
scope,
|
|
889
|
+
filePath: null,
|
|
890
|
+
status: "not present",
|
|
891
|
+
};
|
|
892
|
+
}
|
|
677
893
|
const filePath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
|
|
678
894
|
|
|
679
895
|
if (host.mcp.configType === "toml") {
|
|
@@ -733,7 +949,8 @@ async function runUninstallCommand(options) {
|
|
|
733
949
|
// Resolve the concrete server name(s) to remove at the host/scope level.
|
|
734
950
|
// When --name was not given, this iterates every Flywheel-identifying
|
|
735
951
|
// entry (matching setup's prior-mode detector) so renamed or drifted
|
|
736
|
-
// entries (
|
|
952
|
+
// entries (non-default TOML section names under `[mcp_servers.*]`) are
|
|
953
|
+
// actually cleared.
|
|
737
954
|
// eslint-disable-next-line no-await-in-loop
|
|
738
955
|
const targetNames = await resolveUninstallServerNamesForHost(
|
|
739
956
|
host,
|
|
@@ -743,10 +960,16 @@ async function runUninstallCommand(options) {
|
|
|
743
960
|
if (targetNames.length === 0) {
|
|
744
961
|
// eslint-disable-next-line no-await-in-loop
|
|
745
962
|
const hostForDisplay = getHost(host);
|
|
746
|
-
//
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
963
|
+
// Skill-only hosts (universal, antigravity) have no MCP surface
|
|
964
|
+
// at all — `host.mcp` is null, so dereferencing `projectPaths` via
|
|
965
|
+
// `mcpCandidatesForScope` throws. Report the absence without
|
|
966
|
+
// consulting a path that doesn't exist for them.
|
|
967
|
+
const filePath = isSkillOnlyHost(hostForDisplay)
|
|
968
|
+
? null
|
|
969
|
+
: // eslint-disable-next-line no-await-in-loop
|
|
970
|
+
await resolveMcpPath(
|
|
971
|
+
mcpCandidatesForScope(hostForDisplay, singleScope),
|
|
972
|
+
);
|
|
750
973
|
mcpResults.push({
|
|
751
974
|
host: hostForDisplay.displayName,
|
|
752
975
|
scope: singleScope,
|
|
@@ -774,12 +997,28 @@ async function runUninstallCommand(options) {
|
|
|
774
997
|
if (bundledSkillNames.length > 0) {
|
|
775
998
|
const skillSpinner = ora("Removing Flywheel bundled skills...").start();
|
|
776
999
|
for (const singleScope of scopes) {
|
|
777
|
-
//
|
|
778
|
-
//
|
|
1000
|
+
// Retain any skill directory still claimed by a non-uninstalled host.
|
|
1001
|
+
// Two signals combine: (a) MCP-backed hosts whose Flywheel entries
|
|
1002
|
+
// survived the MCP-removal pass above, and (b) any host with bundled
|
|
1003
|
+
// skill artifacts still on disk (including skill-only hosts like
|
|
1004
|
+
// universal/antigravity, which never advertise themselves via MCP
|
|
1005
|
+
// entries). Without (b), uninstalling one MCP host would silently
|
|
1006
|
+
// wipe a shared `.agents/skills/<skill>/` that another host still
|
|
1007
|
+
// relies on.
|
|
779
1008
|
// eslint-disable-next-line no-await-in-loop
|
|
780
|
-
const
|
|
1009
|
+
const mcpRetained = await resolveHostsWithRemainingFlywheelMcpEntries({
|
|
781
1010
|
scope: singleScope,
|
|
782
1011
|
});
|
|
1012
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1013
|
+
const skillOnlyRetained = await resolveSkillOnlyHostsRetainingArtifacts(
|
|
1014
|
+
{
|
|
1015
|
+
scope: singleScope,
|
|
1016
|
+
excludedHostNames: supportedHosts,
|
|
1017
|
+
},
|
|
1018
|
+
);
|
|
1019
|
+
const configuredRetainHostNames = [
|
|
1020
|
+
...new Set([...mcpRetained, ...skillOnlyRetained]),
|
|
1021
|
+
];
|
|
783
1022
|
skillSpinner.text = `Removing bundled skills from ${supportedHosts.length} host(s) (${singleScope})...`;
|
|
784
1023
|
// eslint-disable-next-line no-await-in-loop
|
|
785
1024
|
bundledSkillResults.push(
|
|
@@ -794,10 +1033,25 @@ async function runUninstallCommand(options) {
|
|
|
794
1033
|
}
|
|
795
1034
|
skillSpinner.succeed("Bundled skill uninstall complete");
|
|
796
1035
|
}
|
|
1036
|
+
|
|
1037
|
+
// Install-marker cleanup runs independently of bundled-skill discovery.
|
|
1038
|
+
// A broken or trimmed package (missing `skills/`) can leave
|
|
1039
|
+
// `bundledSkillNames` empty — the skill-removal pass above legitimately
|
|
1040
|
+
// no-ops in that case, but the ownership markers must still be cleared,
|
|
1041
|
+
// otherwise a later `uninstall`/`setup` would treat the uninstalled
|
|
1042
|
+
// host as still owning shared skill dirs (wrong retention) or as a
|
|
1043
|
+
// prior CLI install (false cross-mode conflict).
|
|
1044
|
+
await cleanupHostInstallMarkers({
|
|
1045
|
+
cwd: process.cwd(),
|
|
1046
|
+
scopes,
|
|
1047
|
+
hostNames: supportedHosts,
|
|
1048
|
+
});
|
|
797
1049
|
}
|
|
798
1050
|
|
|
799
1051
|
log.blank();
|
|
800
|
-
log.plain(
|
|
1052
|
+
log.plain(
|
|
1053
|
+
pc.green("✔ Flywheel uninstall complete (MCP entries and bundled skills)"),
|
|
1054
|
+
);
|
|
801
1055
|
log.blank();
|
|
802
1056
|
for (const result of mcpResults) {
|
|
803
1057
|
const icon = result.status === "removed" ? pc.green("-") : pc.dim("~");
|
|
@@ -830,11 +1084,13 @@ async function runUninstallCommand(options) {
|
|
|
830
1084
|
}
|
|
831
1085
|
}
|
|
832
1086
|
|
|
833
|
-
const sortedGroups = [...groupedSkillResults.values()].sort(
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
1087
|
+
const sortedGroups = [...groupedSkillResults.values()].sort(
|
|
1088
|
+
(left, right) => {
|
|
1089
|
+
const leftKey = `${left.hostName}:${left.scope}`;
|
|
1090
|
+
const rightKey = `${right.hostName}:${right.scope}`;
|
|
1091
|
+
return leftKey.localeCompare(rightKey);
|
|
1092
|
+
},
|
|
1093
|
+
);
|
|
838
1094
|
for (const groupedResult of sortedGroups) {
|
|
839
1095
|
log.plain(
|
|
840
1096
|
` ${pc.bold(getHost(groupedResult.hostName).displayName)} ${pc.dim(`(${groupedResult.scope})`)}`,
|
|
@@ -850,7 +1106,9 @@ async function runUninstallCommand(options) {
|
|
|
850
1106
|
entry.status === "retained" && Array.isArray(entry.retainedHostNames)
|
|
851
1107
|
? ` (shared with configured host(s): ${entry.retainedHostNames.join(", ")})`
|
|
852
1108
|
: "";
|
|
853
|
-
log.plain(
|
|
1109
|
+
log.plain(
|
|
1110
|
+
` ${icon} ${entry.status}${retainedSuffix}: ${entry.skillNames.join(", ")}`,
|
|
1111
|
+
);
|
|
854
1112
|
log.plain(` ${pc.dim(entry.installedSkillDir)}`);
|
|
855
1113
|
}
|
|
856
1114
|
}
|
|
@@ -861,7 +1119,9 @@ async function runUninstallCommand(options) {
|
|
|
861
1119
|
log.plain(
|
|
862
1120
|
` ${pc.bold(getHost(unsupportedHostName).displayName)} ${pc.dim(`(${singleScope})`)}`,
|
|
863
1121
|
);
|
|
864
|
-
log.plain(
|
|
1122
|
+
log.plain(
|
|
1123
|
+
` ${pc.dim("~")} skill uninstall not supported (MCP-only host)`,
|
|
1124
|
+
);
|
|
865
1125
|
}
|
|
866
1126
|
}
|
|
867
1127
|
log.blank();
|
|
@@ -882,15 +1142,32 @@ Examples:
|
|
|
882
1142
|
${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --auth-mode device --codex --project")}
|
|
883
1143
|
${pc.green("npx --yes @paradigma-inc/flywheel setup --mode cli --codex --project")}
|
|
884
1144
|
${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --yes --codex --claude --cursor")}
|
|
885
|
-
${pc.green(
|
|
886
|
-
"npx --yes @paradigma-inc/flywheel uninstall --scope all --hosts codex,claude,opencode,cursor,pi-mono,hermes-agent,openclaw",
|
|
887
|
-
)}
|
|
1145
|
+
${pc.green("npx --yes @paradigma-inc/flywheel uninstall --yes --scope all")}
|
|
888
1146
|
`,
|
|
889
1147
|
);
|
|
890
1148
|
|
|
891
1149
|
program
|
|
892
1150
|
.command("setup")
|
|
893
1151
|
.description("Set up Flywheel for your AI coding host")
|
|
1152
|
+
.addHelpText(
|
|
1153
|
+
"before",
|
|
1154
|
+
`${pc.bold(pc.cyan("✻ Flywheel Setup"))}
|
|
1155
|
+
|
|
1156
|
+
Configure the Flywheel CLI, MCP host entries, and bundled skills without changing command names or setup modes.
|
|
1157
|
+
`,
|
|
1158
|
+
)
|
|
1159
|
+
.optionsGroup("Hosts:")
|
|
1160
|
+
.option("--claude", "Set up for Claude Code")
|
|
1161
|
+
.option("--cursor", "Set up for Cursor")
|
|
1162
|
+
.option("--universal", "Set up for Universal (.agents/skills)")
|
|
1163
|
+
.option("--antigravity", "Set up for Antigravity (.agent/skills)")
|
|
1164
|
+
.option("--opencode", "Set up for OpenCode")
|
|
1165
|
+
.option("--codex", "Set up for Codex")
|
|
1166
|
+
.option("--gemini", "Set up for Gemini CLI")
|
|
1167
|
+
.option("--pi-mono", "Set up for Pi (pi-mono)")
|
|
1168
|
+
.option("--hermes-agent", "Set up for Hermes Agent")
|
|
1169
|
+
.option("--openclaw", "Set up for OpenClaw")
|
|
1170
|
+
.optionsGroup("Mode:")
|
|
894
1171
|
.option(
|
|
895
1172
|
"--mode <mode>",
|
|
896
1173
|
"Install mode: mcp | cli (required in non-interactive; prompted in TTY, default: mcp)",
|
|
@@ -899,50 +1176,78 @@ Examples:
|
|
|
899
1176
|
)
|
|
900
1177
|
.option("--mcp", "Alias for --mode mcp")
|
|
901
1178
|
.option("--cli", "Alias for --mode cli")
|
|
902
|
-
.
|
|
903
|
-
.option("--opencode", "Set up for OpenCode")
|
|
904
|
-
.option("--codex", "Set up for Codex")
|
|
905
|
-
.option("--cursor", "Set up for Cursor")
|
|
906
|
-
.option("--pi-mono", "Set up for Pi (pi-mono)")
|
|
907
|
-
.option("--hermes-agent", "Set up for Hermes Agent")
|
|
908
|
-
.option("--openclaw", "Set up for OpenClaw")
|
|
1179
|
+
.optionsGroup("Scope:")
|
|
909
1180
|
.option(
|
|
910
1181
|
"-p, --project",
|
|
911
1182
|
"Configure for current project instead of globally",
|
|
912
1183
|
)
|
|
913
|
-
.option("-y, --yes", "Skip
|
|
914
|
-
.
|
|
1184
|
+
.option("-y, --yes", "Skip confirmation prompts")
|
|
1185
|
+
.optionsGroup("Authentication:")
|
|
915
1186
|
.option("--api-key <key>", "Use API key authentication")
|
|
1187
|
+
.option("--oauth", "Use OAuth endpoint (IDE handles auth flow)")
|
|
1188
|
+
.optionsGroup("Skills:")
|
|
1189
|
+
.option("--install-skill", "Install or refresh the bundled Flywheel skills")
|
|
1190
|
+
.option("--skip-skill", "Skip bundled skill installation (MCP-only setup)")
|
|
1191
|
+
.optionsGroup("Advanced:")
|
|
916
1192
|
.option(
|
|
917
1193
|
"--auth-mode <mode>",
|
|
918
|
-
"
|
|
1194
|
+
"API-key mint flow: auto | loopback | device (default: auto)",
|
|
919
1195
|
normalizeAuthMode,
|
|
920
1196
|
"auto",
|
|
921
1197
|
)
|
|
922
|
-
.option("--install-skill", "Install or refresh the bundled Flywheel skills")
|
|
923
|
-
.option("--skip-skill", "Skip bundled skill installation (MCP-only setup)")
|
|
924
1198
|
.option(
|
|
925
1199
|
"--base-url <url>",
|
|
926
|
-
`Public Flywheel origin used for setup and MCP config (default: ${
|
|
1200
|
+
`Public Flywheel origin used for setup and MCP config (default: ${resolveSetupBaseUrl()})`,
|
|
927
1201
|
)
|
|
928
1202
|
.option("--name <name>", `MCP server name (default: ${SERVER_NAME})`)
|
|
1203
|
+
.option(
|
|
1204
|
+
"--force",
|
|
1205
|
+
"Reconcile prior install mode automatically via uninstall",
|
|
1206
|
+
)
|
|
1207
|
+
.addHelpText(
|
|
1208
|
+
"after",
|
|
1209
|
+
`
|
|
1210
|
+
Examples:
|
|
1211
|
+
${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --install-skill")}
|
|
1212
|
+
${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --skip-skill --codex --project")}
|
|
1213
|
+
${pc.green("npx --yes @paradigma-inc/flywheel setup --mode cli --codex --project")}
|
|
1214
|
+
|
|
1215
|
+
Next steps:
|
|
1216
|
+
${pc.green("flywheel help")}
|
|
1217
|
+
${pc.green("flywheel auth:status")}
|
|
1218
|
+
`,
|
|
1219
|
+
)
|
|
929
1220
|
.action(async (options) => {
|
|
930
1221
|
await runSetupCommandViaRouter(options);
|
|
931
1222
|
});
|
|
932
1223
|
|
|
933
1224
|
program
|
|
934
1225
|
.command("uninstall")
|
|
935
|
-
.description(
|
|
1226
|
+
.description(
|
|
1227
|
+
"Remove Flywheel MCP entries and bundled skills from selected hosts",
|
|
1228
|
+
)
|
|
1229
|
+
.addHelpText(
|
|
1230
|
+
"before",
|
|
1231
|
+
`${pc.bold(pc.cyan("✻ Flywheel Uninstall"))}
|
|
1232
|
+
|
|
1233
|
+
Remove Flywheel MCP entries and bundled skills from selected hosts without changing command names or uninstall scopes.
|
|
1234
|
+
`,
|
|
1235
|
+
)
|
|
1236
|
+
.optionsGroup("Hosts:")
|
|
936
1237
|
.option("--claude", "Uninstall for Claude Code")
|
|
1238
|
+
.option("--cursor", "Uninstall for Cursor")
|
|
1239
|
+
.option("--universal", "Uninstall bundled skills from .agents/skills")
|
|
1240
|
+
.option("--antigravity", "Uninstall bundled skills from .agent/skills")
|
|
937
1241
|
.option("--opencode", "Uninstall for OpenCode")
|
|
938
1242
|
.option("--codex", "Uninstall for Codex")
|
|
939
|
-
.option("--
|
|
1243
|
+
.option("--gemini", "Uninstall for Gemini CLI")
|
|
940
1244
|
.option("--pi-mono", "Uninstall for Pi (pi-mono)")
|
|
941
1245
|
.option("--hermes-agent", "Uninstall for Hermes Agent")
|
|
942
1246
|
.option("--openclaw", "Uninstall for OpenClaw")
|
|
1247
|
+
.optionsGroup("Selection:")
|
|
943
1248
|
.option(
|
|
944
1249
|
"--hosts <list>",
|
|
945
|
-
"Comma-separated:
|
|
1250
|
+
"Comma-separated: claude,cursor,universal,antigravity,opencode,codex,gemini,pi-mono,hermes-agent,openclaw",
|
|
946
1251
|
)
|
|
947
1252
|
.option("--scope <scope>", "all | global | project")
|
|
948
1253
|
.option(
|
|
@@ -950,6 +1255,18 @@ Examples:
|
|
|
950
1255
|
`MCP server name to remove (default: ${SERVER_NAME})`,
|
|
951
1256
|
)
|
|
952
1257
|
.option("-y, --yes", "Skip uninstall selection prompts")
|
|
1258
|
+
.addHelpText(
|
|
1259
|
+
"after",
|
|
1260
|
+
`
|
|
1261
|
+
Examples:
|
|
1262
|
+
${pc.green("npx --yes @paradigma-inc/flywheel uninstall --codex --scope project")}
|
|
1263
|
+
${pc.green("npx --yes @paradigma-inc/flywheel uninstall --hosts claude,codex --scope all --yes")}
|
|
1264
|
+
|
|
1265
|
+
Next steps:
|
|
1266
|
+
${pc.green("flywheel help setup")}
|
|
1267
|
+
${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp")}
|
|
1268
|
+
`,
|
|
1269
|
+
)
|
|
953
1270
|
.action(async (options) => {
|
|
954
1271
|
await runUninstallCommand(options);
|
|
955
1272
|
});
|