@pellux/goodvibes-agent 0.1.116 → 0.1.117

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.
Files changed (168) hide show
  1. package/CHANGELOG.md +41 -663
  2. package/README.md +38 -52
  3. package/dist/package/main.js +37826 -35924
  4. package/docs/README.md +5 -4
  5. package/docs/{connected-services.md → connected-host.md} +18 -10
  6. package/docs/getting-started.md +41 -44
  7. package/docs/release-and-publishing.md +6 -4
  8. package/package.json +3 -3
  9. package/src/agent/behavior-discovery-summary.ts +1 -3
  10. package/src/agent/persona-discovery.ts +1 -3
  11. package/src/agent/persona-registry.ts +5 -3
  12. package/src/agent/reminder-schedule-format.ts +6 -6
  13. package/src/agent/reminder-schedule.ts +1 -1
  14. package/src/agent/routine-registry.ts +43 -4
  15. package/src/agent/routine-schedule-format.ts +6 -6
  16. package/src/agent/routine-schedule-promotion.ts +1 -1
  17. package/src/agent/routine-schedule-receipts.ts +1 -1
  18. package/src/agent/runtime-profile-starters.ts +3 -3
  19. package/src/agent/runtime-profile.ts +78 -0
  20. package/src/agent/skill-registry.ts +190 -13
  21. package/src/cli/agent-knowledge-command.ts +2 -2
  22. package/src/cli/agent-knowledge-format.ts +2 -2
  23. package/src/cli/agent-knowledge-runtime.ts +1 -1
  24. package/src/cli/bundle-command.ts +1 -1
  25. package/src/cli/entrypoint.ts +16 -7
  26. package/src/cli/help.ts +26 -19
  27. package/src/cli/local-library-command.ts +75 -21
  28. package/src/cli/management-commands.ts +7 -6
  29. package/src/cli/management.ts +6 -51
  30. package/src/cli/parser.ts +23 -2
  31. package/src/cli/profiles-command.ts +119 -1
  32. package/src/cli/routines-command.ts +139 -11
  33. package/src/cli/service-posture.ts +11 -11
  34. package/src/cli/status.ts +21 -25
  35. package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
  36. package/src/input/agent-workspace-access-command-editors.ts +170 -0
  37. package/src/input/agent-workspace-activation.ts +2 -1
  38. package/src/input/agent-workspace-basic-command-editor-submission.ts +345 -92
  39. package/src/input/agent-workspace-basic-command-editors.ts +480 -7
  40. package/src/input/agent-workspace-categories.ts +175 -15
  41. package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
  42. package/src/input/agent-workspace-channel-command-editors.ts +47 -0
  43. package/src/input/agent-workspace-command-editor.ts +23 -1
  44. package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
  45. package/src/input/agent-workspace-editors.ts +27 -0
  46. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
  47. package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
  48. package/src/input/agent-workspace-learned-behavior.ts +67 -0
  49. package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
  50. package/src/input/agent-workspace-library-command-editors.ts +35 -0
  51. package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
  52. package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
  53. package/src/input/agent-workspace-memory-command-editors.ts +180 -0
  54. package/src/input/agent-workspace-navigation.ts +45 -0
  55. package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
  56. package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
  57. package/src/input/agent-workspace-operations-command-editors.ts +119 -0
  58. package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
  59. package/src/input/agent-workspace-provider-command-editors.ts +93 -0
  60. package/src/input/agent-workspace-requirements.ts +11 -0
  61. package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
  62. package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
  63. package/src/input/agent-workspace-session-command-editors.ts +249 -0
  64. package/src/input/agent-workspace-setup.ts +24 -14
  65. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
  66. package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
  67. package/src/input/agent-workspace-snapshot.ts +50 -8
  68. package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
  69. package/src/input/agent-workspace-task-command-editors.ts +47 -0
  70. package/src/input/agent-workspace-types.ts +120 -0
  71. package/src/input/agent-workspace-voice-media.ts +1 -1
  72. package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
  73. package/src/input/agent-workspace.ts +47 -37
  74. package/src/input/command-registry.ts +1 -1
  75. package/src/input/commands/agent-runtime-profile-runtime.ts +89 -4
  76. package/src/input/commands/agent-skills-runtime.ts +76 -12
  77. package/src/input/commands/agent-workspace-runtime.ts +4 -3
  78. package/src/input/commands/brief-runtime.ts +38 -9
  79. package/src/input/commands/channels-runtime.ts +3 -3
  80. package/src/input/commands/compat-runtime.ts +32 -0
  81. package/src/input/commands/health-runtime.ts +22 -24
  82. package/src/input/commands/knowledge.ts +26 -5
  83. package/src/input/commands/local-provider-runtime.ts +7 -3
  84. package/src/input/commands/local-setup-review.ts +4 -14
  85. package/src/input/commands/mcp-runtime.ts +8 -12
  86. package/src/input/commands/operator-runtime.ts +8 -67
  87. package/src/input/commands/personas-runtime.ts +1 -1
  88. package/src/input/commands/platform-access-runtime.ts +7 -70
  89. package/src/input/commands/policy-dispatch.ts +1 -1
  90. package/src/input/commands/policy.ts +1 -5
  91. package/src/input/commands/product-runtime.ts +2 -2
  92. package/src/input/commands/qrcode-runtime.ts +6 -4
  93. package/src/input/commands/routines-runtime.ts +44 -6
  94. package/src/input/commands/runtime-services.ts +1 -14
  95. package/src/input/commands/security-runtime.ts +3 -8
  96. package/src/input/commands/session-content.ts +1 -1
  97. package/src/input/commands/session-workflow.ts +5 -14
  98. package/src/input/commands/shell-core.ts +8 -2
  99. package/src/input/commands/subscription-runtime.ts +1 -6
  100. package/src/input/commands/support-bundle-runtime.ts +53 -0
  101. package/src/input/commands/tasks-runtime.ts +2 -2
  102. package/src/input/commands.ts +4 -0
  103. package/src/input/feed-context-factory.ts +0 -1
  104. package/src/input/handler-content-actions.ts +0 -25
  105. package/src/input/handler-feed.ts +0 -2
  106. package/src/input/handler-interactions.ts +2 -31
  107. package/src/input/handler-onboarding.ts +29 -12
  108. package/src/input/handler-shortcuts.ts +1 -3
  109. package/src/input/handler.ts +4 -7
  110. package/src/input/keybindings.ts +9 -9
  111. package/src/input/mcp-workspace.ts +90 -26
  112. package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
  113. package/src/input/onboarding/onboarding-wizard-apply.ts +49 -0
  114. package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
  115. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +81 -3
  116. package/src/input/onboarding/onboarding-wizard-steps.ts +14 -7
  117. package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
  118. package/src/input/onboarding/onboarding-wizard.ts +19 -2
  119. package/src/input/profile-picker-modal.ts +2 -2
  120. package/src/input/settings-modal-agent-policy.ts +6 -6
  121. package/src/input/settings-modal-subscriptions.ts +3 -3
  122. package/src/input/settings-modal.ts +14 -14
  123. package/src/main.ts +0 -2
  124. package/src/panels/automation-control-panel.ts +3 -3
  125. package/src/panels/builtin/agent.ts +1 -1
  126. package/src/panels/builtin/operations.ts +2 -2
  127. package/src/panels/builtin/session.ts +26 -18
  128. package/src/panels/builtin/shared.ts +6 -6
  129. package/src/panels/project-planning-panel.ts +1 -1
  130. package/src/panels/provider-health-domains.ts +3 -3
  131. package/src/panels/qr-panel.ts +44 -20
  132. package/src/panels/subscription-panel.ts +3 -3
  133. package/src/panels/system-messages-panel.ts +2 -2
  134. package/src/panels/tasks-panel.ts +4 -4
  135. package/src/planning/project-planning-coordinator.ts +2 -2
  136. package/src/renderer/agent-workspace.ts +26 -5
  137. package/src/renderer/block-actions.ts +1 -3
  138. package/src/renderer/help-overlay.ts +13 -8
  139. package/src/renderer/mcp-workspace.ts +32 -13
  140. package/src/renderer/model-picker-overlay.ts +0 -1
  141. package/src/renderer/model-workspace.ts +0 -2
  142. package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
  143. package/src/renderer/panel-picker-overlay.ts +1 -1
  144. package/src/renderer/profile-picker-modal.ts +2 -2
  145. package/src/renderer/settings-modal-helpers.ts +23 -23
  146. package/src/renderer/settings-modal.ts +18 -18
  147. package/src/renderer/system-message.ts +1 -1
  148. package/src/runtime/agent-runtime-events.ts +129 -0
  149. package/src/runtime/bootstrap-command-parts.ts +3 -2
  150. package/src/runtime/bootstrap-core.ts +4 -64
  151. package/src/runtime/bootstrap-shell.ts +42 -4
  152. package/src/runtime/bootstrap.ts +8 -27
  153. package/src/runtime/connected-host-auth.ts +42 -0
  154. package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
  155. package/src/runtime/index.ts +1 -5
  156. package/src/runtime/onboarding/apply.ts +213 -0
  157. package/src/runtime/onboarding/derivation.ts +5 -5
  158. package/src/runtime/onboarding/snapshot.ts +2 -2
  159. package/src/runtime/onboarding/types.ts +26 -1
  160. package/src/runtime/onboarding/verify.ts +81 -2
  161. package/src/runtime/operator-token-cleanup.ts +2 -2
  162. package/src/runtime/services.ts +27 -12
  163. package/src/shell/service-settings-sync.ts +7 -7
  164. package/src/shell/ui-openers.ts +27 -38
  165. package/src/tools/agent-local-registry-tool.ts +10 -4
  166. package/src/tools/agent-tool-policy-guard.ts +5 -7
  167. package/src/version.ts +1 -1
  168. package/src/cli/package-verification.ts +0 -274
package/src/cli/help.ts CHANGED
@@ -37,12 +37,12 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
37
37
  ' /setup Open setup/config flows',
38
38
  ' /model Choose provider and model',
39
39
  ' /knowledge Use isolated Agent Knowledge',
40
- ' /personas, /skills Tune local Agent behavior',
41
- ' /routines Run local routines in the main conversation',
42
- ' /schedule remind Create confirmed reminders or inspect schedules',
43
- ' /delegate Explicitly hand build/fix/review work to GoodVibes TUI',
40
+ ' /personas, /skills Tune local Agent behavior',
41
+ ' /routines Run local routines in the main conversation',
42
+ ' /schedule remind Create confirmed reminders or inspect schedules',
43
+ ' /delegate Explicitly hand build/fix/review work to GoodVibes TUI',
44
44
  '',
45
- 'Commands:',
45
+ 'Scriptable mirrors:',
46
46
  ' run|exec [prompt] Run non-interactively with text/json/stream-json output',
47
47
  ' status Print config, provider, auth, and setup posture',
48
48
  ' doctor Print status plus setup warnings',
@@ -55,7 +55,7 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
55
55
  ' memory Manage Agent-owned durable memory records',
56
56
  ' routines Inspect local routines and explicitly promote one to a connected schedule',
57
57
  ' auth Inspect Agent auth posture and connection token state',
58
- ' compat Inspect Agent SDK pin, connected service version, and Agent Knowledge route readiness',
58
+ ' compat Inspect Agent SDK pin, connected host version, and Agent Knowledge route readiness',
59
59
  ' knowledge Use isolated Agent Knowledge/Wiki routes',
60
60
  ' ask|search Shortcuts for isolated Agent Knowledge ask/search',
61
61
  ' delegate Explicitly delegate build/fix/review work to GoodVibes TUI',
@@ -106,7 +106,7 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
106
106
  ` ${binary} profiles create household --template household --yes`,
107
107
  ` ${binary} --agent-profile household`,
108
108
  ` ${binary} personas create --name "Travel Planner" --description "Plan trips" --body "Compare options before booking"`,
109
- ` ${binary} skills create --name "Daily Brief" --description "Summarize operator state" --procedure "Review Agent Knowledge, work plans, approvals, and routines" --enabled`,
109
+ ` ${binary} skills create --name "Daily Brief" --description "Summarize operator state" --procedure "Review Agent Knowledge, work plans, approvals, and routines" --requires-env GOODVIBES_AGENT_TOKEN --requires-command gh --enabled`,
110
110
  ` ${binary} memory add fact "Prefers concise morning briefings" --scope project --tags preference`,
111
111
  ` ${binary} memory search "morning briefings"`,
112
112
  ` ${binary} routines promote daily-operations-sweep --cron "0 9 * * *" --timezone America/Chicago --yes`,
@@ -138,12 +138,12 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
138
138
  },
139
139
  setup: {
140
140
  usage: ['setup', 'setup status', 'onboarding', 'onboarding status'],
141
- summary: 'Open Agent setup, or inspect whether setup has already been shown for this user.',
141
+ summary: 'Open Agent setup, or inspect whether setup has already been applied for this user.',
142
142
  examples: ['setup', 'setup status', 'onboarding status'],
143
143
  },
144
144
  status: {
145
145
  usage: ['status', 'status --json', '--runtime-url http://127.0.0.1:3421 status'],
146
- summary: 'Print Agent config, provider, auth, connected-service state, and setup posture.',
146
+ summary: 'Print Agent config, provider, auth, connected-host state, and setup posture.',
147
147
  examples: ['status', 'status --json', '--runtime-url http://127.0.0.1:3421 status'],
148
148
  },
149
149
  doctor: {
@@ -157,9 +157,9 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
157
157
  examples: ['providers', 'providers inspect openai-subscriber', 'providers use openai openai:gpt-5.4'],
158
158
  },
159
159
  profiles: {
160
- usage: ['profiles list', 'profiles templates', 'profiles templates from-discovered <id> --yes', 'profiles create-from-discovered <name> --yes', 'profiles templates export <id> <path> --yes', 'profiles templates import <path> --yes', 'profiles show <name>', 'profiles create <name> [--template <id>] --yes', 'profiles delete <name> --yes', '--agent-profile <name>'],
161
- summary: 'Create and inspect isolated Agent profile homes, with starter templates for household, research, travel, operations, personal productivity, and local imported starters. A profile changes Agent-local config, sessions, memory, personas, skills, routines, and setup paths without changing connected GoodVibes services.',
162
- examples: ['profiles templates', 'profiles create-from-discovered research-desk --yes', 'profiles templates from-discovered research-desk --yes', 'profiles templates export research ./research-starter.json --yes', 'profiles templates import ./research-starter.json --yes', 'profiles create household --template household --yes', '--agent-profile household status'],
160
+ usage: ['profiles list', 'profiles default', 'profiles use <name> --yes', 'profiles default clear --yes', 'profiles templates', 'profiles templates from-discovered <id> --yes', 'profiles create-from-discovered <name> --yes', 'profiles templates export <id> <path> --yes', 'profiles templates import <path> --yes', 'profiles show <name>', 'profiles create <name> [--template <id>] --yes', 'profiles delete <name> --yes', '--agent-profile <name>'],
161
+ summary: 'Create and inspect isolated Agent profile homes, with starter templates for household, research, travel, operations, personal productivity, and local imported starters. A profile changes Agent-local config, sessions, memory, personas, skills, routines, and setup paths without changing the connected GoodVibes host.',
162
+ examples: ['profiles templates', 'profiles create household --template household --yes', 'profiles use household --yes', 'profiles default', 'profiles create-from-discovered research-desk --yes', 'profiles templates from-discovered research-desk --yes', 'profiles templates export research ./research-starter.json --yes', 'profiles templates import ./research-starter.json --yes', '--agent-profile household status'],
163
163
  },
164
164
  personas: {
165
165
  usage: [
@@ -192,25 +192,28 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
192
192
  'skills list',
193
193
  'skills enabled',
194
194
  'skills active',
195
+ 'skills attention',
195
196
  'skills discover',
196
197
  'skills import-discovered <name> [--enabled] --yes',
197
198
  'skills search <query>',
198
199
  'skills show <id>',
199
- 'skills create --name <name> --description <summary> --procedure <steps> [--tags a,b] [--triggers a,b] [--enabled]',
200
- 'skills update <id> [--name <name>] [--description <summary>] [--procedure <steps>] [--tags a,b] [--triggers a,b]',
200
+ 'skills create --name <name> --description <summary> --procedure <steps> [--tags a,b] [--triggers a,b] [--requires-env A,B] [--requires-command gh,jq] [--enabled]',
201
+ 'skills update <id> [--name <name>] [--description <summary>] [--procedure <steps>] [--tags a,b] [--triggers a,b] [--requires-env A,B] [--requires-command gh,jq]',
201
202
  'skills enable <id>',
202
203
  'skills disable <id>',
203
204
  'skills review <id>',
204
205
  'skills stale <id> <reason>',
205
206
  'skills delete <id> --yes',
206
- 'skills bundle [list|enabled|show|create|update|enable|disable|review|stale|delete]',
207
+ 'skills bundle [list|enabled|attention|show|create|update|enable|disable|review|stale|delete]',
207
208
  ],
208
209
  summary: 'Manage reusable Agent-local procedures and skill bundles for the main conversation.',
209
210
  examples: [
210
211
  'skills list',
212
+ 'skills attention',
213
+ 'skills bundle attention',
211
214
  'skills discover',
212
215
  'skills import-discovered "Daily Brief" --enabled --yes',
213
- 'skills create --name "Daily Brief" --description "Summarize operator state" --procedure "Review Agent Knowledge, work plans, approvals, and routines" --enabled',
216
+ 'skills create --name "Daily Brief" --description "Summarize operator state" --procedure "Review Agent Knowledge, work plans, approvals, and routines" --requires-env GOODVIBES_AGENT_TOKEN --requires-command gh --enabled',
214
217
  'skills bundle create --name "Ops Pack" --description "Daily operations bundle" --skills daily-brief --enabled',
215
218
  'skills delete daily-brief --yes',
216
219
  ],
@@ -247,20 +250,24 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
247
250
  usage: [
248
251
  'routines list',
249
252
  'routines enabled',
253
+ 'routines attention',
250
254
  'routines discover',
251
255
  'routines import-discovered <name> [--enabled] --yes',
252
256
  'routines show <id>',
257
+ 'routines create --name <name> --description <summary> --steps <steps> [--tags a,b] [--triggers a,b] [--requires-env A,B] [--requires-command gh,jq] [--enabled]',
253
258
  'routines receipts',
254
259
  'routines reconcile',
255
260
  'routines receipt <receipt-id>',
256
261
  'routines promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--timezone <tz>] [--name <schedule-name>] [--provider <id>] [--model <model>] [--delivery-channel <channel[:route[:label]]>|--delivery-route <route[:label]>|--delivery-webhook <url>|--delivery-link <url>] [--disabled] --yes',
257
262
  ],
258
- summary: 'Inspect and import Agent-local routines, review local promotion receipts, reconcile receipts against live connected schedules, and explicitly promote a reviewed routine into a GoodVibes schedule. Without --yes, promote only prints the schedules.create preview.',
263
+ summary: 'Inspect, create, and import Agent-local routines with setup readiness. The same routine workflow is available in the TUI through /routines and the Agent workspace. GoodVibes schedule promotion is explicit. Without --yes, promotion only prints the preview.',
259
264
  examples: [
260
265
  'routines list',
266
+ 'routines attention',
261
267
  'routines discover',
262
268
  'routines import-discovered "Daily Brief" --enabled --yes',
263
269
  'routines show daily-operations-sweep',
270
+ 'routines create --name "Daily Sweep" --description "Review operator state" --steps "Check tasks, approvals, channels, and Agent Knowledge" --requires-env GOODVIBES_AGENT_TOKEN',
264
271
  'routines receipts',
265
272
  'routines reconcile',
266
273
  'routines promote daily-operations-sweep --cron "0 9 * * *" --timezone America/Chicago --delivery-channel slack --yes',
@@ -348,7 +355,7 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
348
355
  },
349
356
  tasks: {
350
357
  usage: ['tasks list', 'tasks show <taskId>'],
351
- summary: 'Inspect connected-service task summaries. Agent blocks service-owned task submission; use run for one-shot work or delegate for explicit build/fix/review handoff.',
358
+ summary: 'Inspect connected-host task summaries. Agent blocks host-owned task submission; use run for one-shot work or delegate for explicit build/fix/review handoff.',
352
359
  examples: ['tasks list', 'tasks show task-123', 'run "check provider readiness"', 'delegate "fix the failing tests"'],
353
360
  },
354
361
  bundle: {
@@ -402,7 +409,7 @@ export function renderGoodVibesCommandHelp(topic: string, binary = 'goodvibes-ag
402
409
  ].join('\n');
403
410
  }
404
411
  return [
405
- `GoodVibes ${normalized}`,
412
+ `GoodVibes Agent ${normalized}`,
406
413
  '',
407
414
  help.summary,
408
415
  '',
@@ -4,6 +4,10 @@ import { AgentPersonaRegistry, type AgentPersonaRecord } from '../agent/persona-
4
4
  import { discoverSkills, type SkillRecord } from '../agent/skill-discovery.ts';
5
5
  import {
6
6
  AgentSkillRegistry,
7
+ buildAgentSkillRequirements,
8
+ evaluateAgentSkillBundleReadiness,
9
+ evaluateAgentSkillReadiness,
10
+ formatAgentSkillRequirement,
7
11
  type AgentSkillBundleRecord,
8
12
  type AgentSkillRecord,
9
13
  } from '../agent/skill-registry.ts';
@@ -170,7 +174,7 @@ function renderDiscoveredPersonaList(personas: readonly DiscoveredPersonaRecord[
170
174
  return [
171
175
  'Discovered Agent persona files',
172
176
  ' No persona markdown files found in Agent persona folders.',
173
- ' Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents',
177
+ ' Search roots: .goodvibes/personas, .goodvibes/agent/personas, ~/.goodvibes/personas, ~/.goodvibes/agent/personas',
174
178
  ].join('\n');
175
179
  }
176
180
  return [
@@ -204,21 +208,29 @@ function discoveredPersonaFrontmatterList(persona: DiscoveredPersonaRecord, key:
204
208
  function summarizeSkill(skill: AgentSkillRecord): string {
205
209
  const enabled = skill.enabled ? 'enabled' : 'disabled';
206
210
  const tags = skill.tags.length > 0 ? ` tags=${skill.tags.join(',')}` : '';
207
- return ` ${skill.id} ${enabled} ${skill.reviewState} ${skill.name} - ${skill.description}${tags}`;
211
+ const readiness = evaluateAgentSkillReadiness(skill);
212
+ const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
213
+ return ` ${skill.id} ${enabled} ${skill.reviewState} ${ready} ${skill.name} - ${skill.description}${tags}`;
208
214
  }
209
215
 
210
- function summarizeBundle(bundle: AgentSkillBundleRecord): string {
216
+ function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
211
217
  const enabled = bundle.enabled ? 'enabled' : 'disabled';
212
- return ` ${bundle.id} ${enabled} ${bundle.reviewState} ${bundle.name} - ${bundle.description} skills=${bundle.skillIds.join(',')}`;
218
+ const readiness = evaluateAgentSkillBundleReadiness(bundle, skills);
219
+ const missing = [
220
+ ...readiness.missingRequirements.map(formatAgentSkillRequirement),
221
+ ...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
222
+ ];
223
+ const ready = readiness.ready ? 'ready' : `needs ${missing.join(',')}`;
224
+ return ` ${bundle.id} ${enabled} ${bundle.reviewState} ${ready} ${bundle.name} - ${bundle.description} skills=${bundle.skillIds.join(',')}`;
213
225
  }
214
226
 
215
- function renderSkillList(title: string, path: string, skills: readonly AgentSkillRecord[]): string {
227
+ function renderSkillList(title: string, path: string, skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
216
228
  if (skills.length === 0) {
217
229
  return [
218
230
  title,
219
- ' No local Agent skills yet.',
220
- ' Create one with: goodvibes-agent skills create --name <name> --description <summary> --procedure <steps>',
221
- ].join('\n');
231
+ ` ${emptyMessage ?? 'No local Agent skills yet.'}`,
232
+ emptyMessage ? '' : ' Create one with: goodvibes-agent skills create --name <name> --description <summary> --procedure <steps>',
233
+ ].filter(Boolean).join('\n');
222
234
  }
223
235
  return [
224
236
  `${title} (${skills.length})`,
@@ -273,26 +285,38 @@ function discoveredFrontmatterList(skill: SkillRecord, key: string): readonly st
273
285
  return value.split(',').map((entry) => entry.trim()).filter(Boolean);
274
286
  }
275
287
 
276
- function renderBundleList(title: string, path: string, bundles: readonly AgentSkillBundleRecord[]): string {
288
+ function discoveredFrontmatterAnyList(skill: SkillRecord, keys: readonly string[]): readonly string[] {
289
+ for (const key of keys) {
290
+ const values = discoveredFrontmatterList(skill, key);
291
+ if (values.length > 0) return values;
292
+ }
293
+ return [];
294
+ }
295
+
296
+ function renderBundleList(title: string, path: string, bundles: readonly AgentSkillBundleRecord[], skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
277
297
  if (bundles.length === 0) {
278
298
  return [
279
299
  title,
280
- ' No local Agent skill bundles yet.',
281
- ' Create one with: goodvibes-agent skills bundle create --name <name> --description <summary> --skills <id,id>',
282
- ].join('\n');
300
+ ` ${emptyMessage ?? 'No local Agent skill bundles yet.'}`,
301
+ emptyMessage ? '' : ' Create one with: goodvibes-agent skills bundle create --name <name> --description <summary> --skills <id,id>',
302
+ ].filter(Boolean).join('\n');
283
303
  }
284
304
  return [
285
305
  `${title} (${bundles.length})`,
286
306
  ` store: ${path}`,
287
- ...bundles.map(summarizeBundle),
307
+ ...bundles.map((bundle) => summarizeBundle(bundle, skills)),
288
308
  ].join('\n');
289
309
  }
290
310
 
291
311
  function renderSkill(skill: AgentSkillRecord): string {
312
+ const readiness = evaluateAgentSkillReadiness(skill);
292
313
  return [
293
314
  `Skill ${skill.name}`,
294
315
  ` id: ${skill.id}`,
295
316
  ` enabled: ${skill.enabled ? 'yes' : 'no'}`,
317
+ ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
318
+ ` requirements: ${skill.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
319
+ readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
296
320
  ` review: ${skill.reviewState}`,
297
321
  ` source: ${skill.source}`,
298
322
  ` provenance: ${skill.provenance}`,
@@ -308,11 +332,18 @@ function renderSkill(skill: AgentSkillRecord): string {
308
332
  ].filter((line): line is string => Boolean(line)).join('\n');
309
333
  }
310
334
 
311
- function renderBundle(bundle: AgentSkillBundleRecord): string {
335
+ function renderBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
336
+ const readiness = evaluateAgentSkillBundleReadiness(bundle, skills);
337
+ const missing = [
338
+ ...readiness.missingRequirements.map(formatAgentSkillRequirement),
339
+ ...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
340
+ ];
312
341
  return [
313
342
  `Skill bundle ${bundle.name}`,
314
343
  ` id: ${bundle.id}`,
315
344
  ` enabled: ${bundle.enabled ? 'yes' : 'no'}`,
345
+ ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
346
+ missing.length > 0 ? ` missing: ${missing.join(', ')}` : '',
316
347
  ` review: ${bundle.reviewState}`,
317
348
  ` source: ${bundle.source}`,
318
349
  ` provenance: ${bundle.provenance}`,
@@ -330,11 +361,11 @@ function usagePersonas(): string {
330
361
  }
331
362
 
332
363
  function usageSkills(): string {
333
- return 'Usage: goodvibes-agent skills [list|enabled|active|discover|import-discovered <name> --yes|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes|bundle ...]';
364
+ return 'Usage: goodvibes-agent skills [list|enabled|active|attention|discover|import-discovered <name> --yes|search <query>|show <id>|create [--requires-env A,B] [--requires-command gh,jq]|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes|bundle ...]';
334
365
  }
335
366
 
336
367
  function usageBundles(): string {
337
- return 'Usage: goodvibes-agent skills bundle [list|enabled|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes]';
368
+ return 'Usage: goodvibes-agent skills bundle [list|enabled|attention|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes]';
338
369
  }
339
370
 
340
371
  function errorOutput(runtime: CliCommandRuntime, error: unknown, kind: string): CliCommandOutput {
@@ -473,6 +504,7 @@ function skillPayloadFromOptions(options: ParsedOptions): {
473
504
  readonly procedure: string;
474
505
  readonly tags: readonly string[] | undefined;
475
506
  readonly triggers: readonly string[] | undefined;
507
+ readonly requirements: ReturnType<typeof buildAgentSkillRequirements>;
476
508
  readonly enabled: boolean | undefined;
477
509
  readonly provenance: string;
478
510
  } {
@@ -483,6 +515,10 @@ function skillPayloadFromOptions(options: ParsedOptions): {
483
515
  procedure: requiredOption(options, 'procedure', usage),
484
516
  tags: csvOption(options, 'tags'),
485
517
  triggers: csvOption(options, 'triggers'),
518
+ requirements: buildAgentSkillRequirements({
519
+ env: csvOption(options, 'requires-env'),
520
+ commands: csvOption(options, 'requires-command') ?? csvOption(options, 'requires-commands'),
521
+ }),
486
522
  enabled: hasFlag(options, 'enabled') ? true : undefined,
487
523
  provenance: optionValue(options, 'provenance') ?? 'cli',
488
524
  };
@@ -495,22 +531,26 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
495
531
  const registry = skillRegistry(runtime);
496
532
  const snapshot = registry.snapshot();
497
533
  if (normalized === 'list' || normalized === 'ls') {
498
- return success(runtime, 'agent.skills.bundles.list', { path: snapshot.path, bundles: snapshot.bundles }, renderBundleList('Agent skill bundles', snapshot.path, snapshot.bundles));
534
+ return success(runtime, 'agent.skills.bundles.list', { path: snapshot.path, bundles: snapshot.bundles }, renderBundleList('Agent skill bundles', snapshot.path, snapshot.bundles, snapshot.skills));
499
535
  }
500
536
  if (normalized === 'enabled') {
501
- return success(runtime, 'agent.skills.bundles.enabled', { path: snapshot.path, bundles: snapshot.enabledBundles }, renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles));
537
+ return success(runtime, 'agent.skills.bundles.enabled', { path: snapshot.path, bundles: snapshot.enabledBundles }, renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles, snapshot.skills));
538
+ }
539
+ if (normalized === 'attention' || normalized === 'needs-setup') {
540
+ const bundles = snapshot.bundles.filter((bundle) => !evaluateAgentSkillBundleReadiness(bundle, snapshot.skills).ready);
541
+ return success(runtime, 'agent.skills.bundles.attention', { path: snapshot.path, bundles }, renderBundleList('Agent skill bundles needing setup', snapshot.path, bundles, snapshot.skills, 'No local Agent skill bundles need setup.'));
502
542
  }
503
543
  if (normalized === 'search' || normalized === 'find') {
504
544
  const query = rest.join(' ').trim();
505
545
  const results = registry.searchBundles(query);
506
- return success(runtime, 'agent.skills.bundles.search', { query, results }, renderBundleList(`Agent skill bundles matching "${query}"`, snapshot.path, results));
546
+ return success(runtime, 'agent.skills.bundles.search', { query, results }, renderBundleList(`Agent skill bundles matching "${query}"`, snapshot.path, results, snapshot.skills));
507
547
  }
508
548
  if (normalized === 'show' || normalized === 'get') {
509
549
  const id = rest[0];
510
550
  if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle show <id>', 2);
511
551
  const bundle = registry.getBundle(id);
512
552
  if (!bundle) return failure(runtime, 'skill_bundle_not_found', `Unknown Agent skill bundle: ${id}`, 1);
513
- return success(runtime, 'agent.skills.bundles.show', bundle, renderBundle(bundle));
553
+ return success(runtime, 'agent.skills.bundles.show', bundle, renderBundle(bundle, snapshot.skills));
514
554
  }
515
555
  if (normalized === 'create') {
516
556
  const options = parseOptions(rest);
@@ -584,9 +624,13 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
584
624
  if (normalized === 'active') {
585
625
  return success(runtime, 'agent.skills.active', { path: snapshot.path, skills: snapshot.activeSkills, bundles: snapshot.enabledBundles }, [
586
626
  renderSkillList('Active Agent skills', snapshot.path, snapshot.activeSkills),
587
- snapshot.enabledBundles.length > 0 ? renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles) : '',
627
+ snapshot.enabledBundles.length > 0 ? renderBundleList('Enabled Agent skill bundles', snapshot.path, snapshot.enabledBundles, snapshot.skills) : '',
588
628
  ].filter(Boolean).join('\n\n'));
589
629
  }
630
+ if (normalized === 'attention' || normalized === 'needs-setup') {
631
+ const skills = snapshot.skills.filter((skill) => !evaluateAgentSkillReadiness(skill).ready);
632
+ return success(runtime, 'agent.skills.attention', { path: snapshot.path, skills }, renderSkillList('Agent skills needing setup', snapshot.path, skills, 'No local Agent skills need setup.'));
633
+ }
590
634
  if (normalized === 'discover') {
591
635
  const discovered = await discoverSkills(shellPaths(runtime));
592
636
  return success(runtime, 'agent.skills.discover', { skills: discovered }, renderDiscoveredSkillList(discovered));
@@ -616,6 +660,10 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
616
660
  procedure: discovered.body,
617
661
  tags: discoveredFrontmatterList(discovered, 'tags'),
618
662
  triggers: discoveredFrontmatterList(discovered, 'triggers'),
663
+ requirements: buildAgentSkillRequirements({
664
+ env: discoveredFrontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
665
+ commands: discoveredFrontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
666
+ }),
619
667
  enabled: hasFlag(options, 'enabled'),
620
668
  source: 'imported',
621
669
  provenance: `discovered:${discovered.origin}:${discovered.path}`,
@@ -648,6 +696,12 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
648
696
  procedure: optionValue(options, 'procedure'),
649
697
  tags: csvOption(options, 'tags'),
650
698
  triggers: csvOption(options, 'triggers'),
699
+ requirements: options.values.has('requires-env') || options.values.has('requires-command') || options.values.has('requires-commands')
700
+ ? buildAgentSkillRequirements({
701
+ env: csvOption(options, 'requires-env'),
702
+ commands: csvOption(options, 'requires-command') ?? csvOption(options, 'requires-commands'),
703
+ })
704
+ : undefined,
651
705
  provenance: optionValue(options, 'provenance'),
652
706
  });
653
707
  return success(runtime, 'agent.skills.update', skill, `Agent skill updated: ${skill.id}`);
@@ -1,16 +1,17 @@
1
1
  import { mkdirSync, writeFileSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
2
+ import { dirname } from 'node:path';
3
3
  import { SecretsManager } from '../config/secrets.ts';
4
4
  import { BUILTIN_SECRET_PROVIDER_SOURCES, describeSecretRef, isSecretRefInput, resolveSecretRef } from '@pellux/goodvibes-sdk/platform/config';
5
5
  import { getSubscriptionProviderConfig, listAvailableSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
6
6
  import { beginOpenAICodexLogin, exchangeOpenAICodexCode } from '@pellux/goodvibes-sdk/platform/config';
7
7
  import { inspectProviderAuth } from '@/runtime/index.ts';
8
- import { getOrCreateCompanionToken, buildCompanionConnectionInfo, encodeConnectionPayload, formatConnectionBlock } from '@pellux/goodvibes-sdk/platform/pairing';
8
+ import { buildCompanionConnectionInfo, encodeConnectionPayload, formatConnectionBlock } from '@pellux/goodvibes-sdk/platform/pairing';
9
9
  import { generateQrMatrix, renderQrToString } from '@pellux/goodvibes-sdk/platform/pairing';
10
10
  import { resolveRuntimeEndpointBinding } from './endpoints.ts';
11
11
  import type { CliCommandRuntime } from './management.ts';
12
12
  import { extractAuthorizationCode, formatJsonOrText, hasCommandFlag, openBrowser, urlHostForBindHost, withRuntimeServices, yesNo } from './management.ts';
13
13
  import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../config/surface.ts';
14
+ import { connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../runtime/connected-host-auth.ts';
14
15
 
15
16
  export async function renderSubscriptions(runtime: CliCommandRuntime): Promise<string> {
16
17
  return await withRuntimeServices(runtime, async (services) => {
@@ -279,7 +280,7 @@ export async function handleTasks(runtime: CliCommandRuntime): Promise<string> {
279
280
  const [sub = 'list', ...rest] = runtime.cli.commandArgs;
280
281
  if (sub === 'submit') {
281
282
  return [
282
- 'GoodVibes Agent blocks CLI task submission from the service-owned task workflow.',
283
+ 'GoodVibes Agent blocks CLI task submission from the host-owned task workflow.',
283
284
  ' policy: do normal assistant work in the main Agent conversation or use `goodvibes-agent run <prompt>` for an explicit one-shot run.',
284
285
  ' build/fix/review: use `goodvibes-agent delegate <task>` for explicit GoodVibes TUI handoff.',
285
286
  ' result: no local task was started.',
@@ -289,7 +290,7 @@ export async function handleTasks(runtime: CliCommandRuntime): Promise<string> {
289
290
  const tasks = [...services.runtimeStore.getState().tasks.tasks.values()];
290
291
  if (sub === 'list') {
291
292
  return tasks.length === 0
292
- ? 'GoodVibes tasks\n No connected-service tasks are currently recorded.'
293
+ ? 'GoodVibes tasks\n No connected-host tasks are currently recorded.'
293
294
  : ['GoodVibes tasks', ...tasks.map((task) => ` ${task.id} ${task.status} ${task.kind} ${task.title}`)].join('\n');
294
295
  }
295
296
  if (sub === 'show') {
@@ -302,8 +303,8 @@ export async function handleTasks(runtime: CliCommandRuntime): Promise<string> {
302
303
  }
303
304
 
304
305
  export async function renderPairing(runtime: CliCommandRuntime): Promise<string> {
305
- const daemonHomeDir = join(runtime.homeDirectory, '.goodvibes', 'daemon');
306
- const tokenRecord = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
306
+ const tokenRecord = readConnectedHostOperatorToken(runtime.homeDirectory);
307
+ if (!tokenRecord.token) return connectedHostTokenRequiredMessage(tokenRecord.path);
307
308
  const binding = resolveRuntimeEndpointBinding(runtime.configManager, 'controlPlane');
308
309
  const daemonUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
309
310
  const info = buildCompanionConnectionInfo({
@@ -19,14 +19,9 @@ import { BUILTIN_SECRET_PROVIDER_SOURCES, describeSecretRef, isSecretRefInput, r
19
19
  import { getSubscriptionProviderConfig, listAvailableSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
20
20
  import { beginOpenAICodexLogin, exchangeOpenAICodexCode } from '@pellux/goodvibes-sdk/platform/config';
21
21
  import { inspectProviderAuth } from '@/runtime/index.ts';
22
- import { getOrCreateCompanionToken, buildCompanionConnectionInfo, encodeConnectionPayload, formatConnectionBlock } from '@pellux/goodvibes-sdk/platform/pairing';
23
- import { generateQrMatrix, renderQrToString } from '@pellux/goodvibes-sdk/platform/pairing';
24
22
  import type { GoodVibesCliParseResult } from './types.ts';
25
23
  import { formatProviderAuthRoute, summarizeProviderAuthRoutes } from './provider-auth-routes.ts';
26
24
  import { classifyProviderSetup } from './provider-classification.ts';
27
- import { resolveRuntimeEndpointBinding } from './endpoints.ts';
28
- import { applyRuntimeEndpointFlagOverrides } from './config-overrides.ts';
29
- import type { RuntimeEndpointId } from './endpoints.ts';
30
25
  import { handleBundleCommand } from './bundle-command.ts';
31
26
  import { handleSecrets, handleSessions, handleTasks, renderPairing, renderSubscriptions } from './management-commands.ts';
32
27
  import { handleAgentKnowledgeCommand, handleAgentKnowledgeShortcutCommand, handleCompatCommand, handleDelegateCommand } from './agent-knowledge-command.ts';
@@ -132,46 +127,6 @@ export function urlHostForBindHost(host: string): string {
132
127
  return host || '127.0.0.1';
133
128
  }
134
129
 
135
- export function enableServicePosture(config: ConfigManager): void {
136
- config.setDynamic('service.enabled', true);
137
- config.setDynamic('service.autostart', true);
138
- config.setDynamic('service.restartOnFailure', true);
139
- }
140
-
141
- export function enableEndpointLanDefault(config: ConfigManager, endpoint: RuntimeEndpointId): void {
142
- const binding = resolveRuntimeEndpointBinding(config, endpoint);
143
- if (binding.hostMode === 'custom') return;
144
- if (endpoint === 'controlPlane') {
145
- config.setDynamic('controlPlane.hostMode', 'network');
146
- config.setDynamic('controlPlane.host', '0.0.0.0');
147
- config.setDynamic('controlPlane.allowRemote', true);
148
- return;
149
- }
150
- if (endpoint === 'httpListener') {
151
- config.setDynamic('httpListener.hostMode', 'network');
152
- config.setDynamic('httpListener.host', '0.0.0.0');
153
- return;
154
- }
155
- config.setDynamic('web.hostMode', 'network');
156
- config.setDynamic('web.host', '0.0.0.0');
157
- }
158
-
159
- export function applyTargetEndpointFlagsOrDefault(
160
- runtime: CliCommandRuntime,
161
- endpoint: RuntimeEndpointId,
162
- ): string | null {
163
- const errors = applyRuntimeEndpointFlagOverrides(runtime.configManager, endpoint, runtime.cli.flags);
164
- if (errors.length > 0) return errors.join('\n');
165
- if (runtime.cli.flags.hostname === undefined) {
166
- enableEndpointLanDefault(runtime.configManager, endpoint);
167
- }
168
- if (endpoint === 'controlPlane') {
169
- const binding = resolveRuntimeEndpointBinding(runtime.configManager, endpoint);
170
- runtime.configManager.setDynamic('controlPlane.allowRemote', binding.hostMode !== 'local');
171
- }
172
- return null;
173
- }
174
-
175
130
  export function openBrowser(url: string): string {
176
131
  const platform = process.platform;
177
132
  const command = platform === 'darwin' ? 'open' : platform === 'win32' ? 'cmd' : 'xdg-open';
@@ -544,8 +499,8 @@ async function renderAuth(runtime: CliCommandRuntime): Promise<string> {
544
499
  ]);
545
500
  if (blocked.has(sub)) {
546
501
  return [
547
- 'Unsupported: connected-service auth user/session administration is outside GoodVibes Agent.',
548
- 'GoodVibes Agent does not create, delete, rotate, revoke, or clear connected-service users, sessions, or bootstrap credentials.',
502
+ 'Unsupported: connected-host auth user/session administration is outside GoodVibes Agent.',
503
+ 'GoodVibes Agent does not create, delete, rotate, revoke, or clear connected-host users, sessions, or bootstrap credentials.',
549
504
  'Use the owning GoodVibes host for auth administration.',
550
505
  ].join('\n');
551
506
  }
@@ -566,21 +521,21 @@ async function renderAuth(runtime: CliCommandRuntime): Promise<string> {
566
521
  if (sub === 'users' || sub === 'sessions') {
567
522
  return formatJsonOrText(runtime.cli)(value, [
568
523
  `GoodVibes Agent auth ${sub}`,
569
- ' owner: connected GoodVibes services',
524
+ ' owner: connected GoodVibes host',
570
525
  ` operator token: ${paths.operatorTokenPresent ? 'present' : 'missing'}`,
571
526
  ` operator token path: ${paths.operatorTokenPath}`,
572
527
  ` ${sub}: managed outside Agent`,
573
- ' Agent does not enumerate or mutate connected-service users/sessions from the local CLI.',
528
+ ' Agent does not enumerate or mutate connected-host users/sessions from the local CLI.',
574
529
  ].join('\n'));
575
530
  }
576
531
  return formatJsonOrText(runtime.cli)(value, [
577
532
  'GoodVibes Agent auth',
578
- ' owner: connected GoodVibes services',
533
+ ' owner: connected GoodVibes host',
579
534
  ` permission mode: ${String(value.permissionMode)}`,
580
535
  ` operator token: ${paths.operatorTokenPresent ? 'present' : 'missing'} (${paths.operatorTokenPath})`,
581
536
  ` compatibility user store: ${paths.userStorePresent ? 'present' : 'missing'} (${paths.userStorePath})`,
582
537
  ` compatibility bootstrap credential: ${paths.bootstrapCredentialPresent ? 'present' : 'missing'} (${paths.bootstrapCredentialPath})`,
583
- ' connected-service user/session administration: outside Agent',
538
+ ' connected-host user/session administration: outside Agent',
584
539
  ' next: goodvibes-agent providers',
585
540
  ' next: goodvibes-agent subscription providers',
586
541
  ].join('\n'));
package/src/cli/parser.ts CHANGED
@@ -58,7 +58,28 @@ const COMMAND_ALIASES: Readonly<Record<string, GoodVibesCliCommand>> = {
58
58
  version: 'version',
59
59
  };
60
60
 
61
- const RETIRED_LAUNCHER_ALIASES = new Set(['app', 'launch', 'start', 'tui']);
61
+ const BLOCKED_PRODUCT_COMMANDS = new Set([
62
+ 'app',
63
+ 'bridge',
64
+ 'control-plane',
65
+ 'controlplane',
66
+ 'cp',
67
+ 'daemon',
68
+ 'http-listener',
69
+ 'launch',
70
+ 'listener',
71
+ 'remote',
72
+ 'serve',
73
+ 'server',
74
+ 'service',
75
+ 'services',
76
+ 'start',
77
+ 'surface',
78
+ 'surfaces',
79
+ 'tui',
80
+ 'web',
81
+ 'webhook',
82
+ ]);
62
83
 
63
84
  function createDefaultFlags(): GoodVibesCliFlags {
64
85
  return {
@@ -200,7 +221,7 @@ export function parseGoodVibesCli(
200
221
  if (!token.startsWith('-') || token === '-') {
201
222
  if (!sawCommand) {
202
223
  const commandToken = token.toLowerCase();
203
- if (RETIRED_LAUNCHER_ALIASES.has(commandToken)) {
224
+ if (BLOCKED_PRODUCT_COMMANDS.has(commandToken)) {
204
225
  command = 'unknown';
205
226
  rawCommand = token;
206
227
  sawCommand = true;