@pellux/goodvibes-agent 0.1.114 → 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 -650
  2. package/README.md +40 -50
  3. package/dist/package/main.js +38224 -35673
  4. package/docs/README.md +5 -4
  5. package/docs/{connected-services.md → connected-host.md} +18 -10
  6. package/docs/getting-started.md +43 -42
  7. package/docs/release-and-publishing.md +6 -4
  8. package/package.json +3 -3
  9. package/src/agent/behavior-discovery-summary.ts +165 -0
  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 +331 -0
  19. package/src/agent/runtime-profile.ts +228 -330
  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 +247 -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 +787 -0
  39. package/src/input/agent-workspace-basic-command-editors.ts +524 -459
  40. package/src/input/agent-workspace-categories.ts +177 -14
  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 +25 -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 +49 -19
  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 +56 -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 +124 -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 +160 -6
  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 +126 -11
  116. package/src/input/onboarding/onboarding-wizard-steps.ts +15 -8
  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 +52 -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 +25 -6
  158. package/src/runtime/onboarding/snapshot.ts +4 -2
  159. package/src/runtime/onboarding/types.ts +28 -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
@@ -174,8 +174,7 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
174
174
  + ' ~/.config/claude/claude_desktop_config.json (Claude Desktop)\n'
175
175
  + ' .mcp/mcp.json (project-local)\n'
176
176
  + ' .goodvibes/mcp.json (goodvibes project)\n'
177
- + '\nAdd one from inside Agent with explicit confirmation:\n'
178
- + ' /mcp add filesystem npx -y @modelcontextprotocol/server-filesystem . --scope project --role filesystem --yes'
177
+ + '\nOpen /mcp and choose Add or update server, or use Agent Workspace -> Tools & MCP -> Add MCP server.'
179
178
  );
180
179
  return;
181
180
  }
@@ -265,7 +264,7 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
265
264
  const mode = commandArgs[2] as 'constrained' | 'ask-on-risk' | 'allow-all' | 'blocked' | undefined;
266
265
  if (serverName && mode) {
267
266
  if (mode === 'allow-all') {
268
- ctx.print(`Use /settings → MCP to explicitly enable allow-all for ${serverName}. Direct CLI escalation is blocked.`);
267
+ ctx.print(`Use /settings → MCP to explicitly enable allow-all for ${serverName}. Direct command escalation is blocked.`);
269
268
  ctx.openSettingsModal?.();
270
269
  return;
271
270
  }
@@ -399,9 +398,9 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
399
398
  }),
400
399
  '',
401
400
  'Add or update from inside Agent with explicit confirmation:',
401
+ ' Open /mcp and choose Add or update server, or use Agent Workspace -> Tools & MCP -> Add MCP server.',
402
+ 'Automation equivalent:',
402
403
  ' /mcp add <name> <command> [args...] [--scope project|global] [--role <role>] [--trust <mode>] --yes',
403
- 'Example:',
404
- ' /mcp add filesystem npx -y @modelcontextprotocol/server-filesystem . --scope project --role filesystem --trust constrained --yes',
405
404
  ].join('\n'));
406
405
  } catch (error) {
407
406
  ctx.print(`MCP config read failed: ${summarizeError(error)}`);
@@ -446,8 +445,7 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
446
445
  + ' ~/.config/claude/claude_desktop_config.json (Claude Desktop)\n'
447
446
  + ' .mcp/mcp.json (project-local)\n'
448
447
  + ' .goodvibes/mcp.json (goodvibes project)\n'
449
- + '\nAdd one from inside Agent with explicit confirmation:\n'
450
- + ' /mcp add filesystem npx -y @modelcontextprotocol/server-filesystem . --scope project --role filesystem --yes\n'
448
+ + '\nOpen /mcp and choose Add or update server, or use Agent Workspace -> Tools & MCP -> Add MCP server.\n'
451
449
  + '\nFormat: { "servers": [{ "name": "my-server", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] }] }'
452
450
  );
453
451
  return;
@@ -473,11 +471,9 @@ function formatMcpServerList(servers: readonly McpSecurityServer[]): string {
473
471
  }
474
472
  if (connected.length > 0) {
475
473
  lines.push('');
476
- lines.push('Run "/mcp tools" to list all tools, or "/mcp tools <server>" for a specific server.');
477
- lines.push('Run "/mcp" to open the fullscreen MCP workspace, or "/mcp add <name> <command> [args...] [--scope project|global] --yes" to add/update.');
478
- lines.push('Run "/mcp reload --yes" after editing MCP config outside Agent.');
479
- lines.push('Run "/mcp trust <server> <mode> --yes" to change trust mode, or "/mcp role <server> <role> --yes" to change its coherence role.');
480
- lines.push('Run "/mcp quarantine <server> [detail] --yes" to block a server, or "/mcp quarantine <server> approve [operatorId] --yes" to approve a temporary override.');
474
+ lines.push('Open "/mcp" for the fullscreen MCP workspace with server status, tools, config paths, and confirmed add/remove/reload actions.');
475
+ lines.push('Use "/mcp tools" for a compact tool list, or "/mcp tools <server>" for one server.');
476
+ lines.push('Use Settings -> MCP for allow-all decisions; trust, role, and quarantine command actions still require explicit --yes confirmation.');
481
477
  lines.push('Use /settings -> MCP to explicitly enable allow-all for a server.');
482
478
  }
483
479
  if (disconnected.length > 0) {
@@ -1,7 +1,5 @@
1
1
  import type { CommandRegistry } from '../command-registry.ts';
2
- import type { ProfileData } from '@pellux/goodvibes-sdk/platform/profiles';
3
2
  import { logger } from '@pellux/goodvibes-sdk/platform/utils';
4
- import { requireProfileManager } from './runtime-services.ts';
5
3
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
6
4
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
7
5
 
@@ -63,71 +61,14 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
63
61
  registry.register({
64
62
  name: 'profiles',
65
63
  aliases: ['profile'],
66
- description: 'Browse, save, and delete config profiles',
67
- usage: '[list|open|save <name> --yes|delete <name> --yes]',
68
- argsHint: '[list|open|save --yes|delete --yes]',
69
- handler(args, ctx) {
70
- const parsed = stripYesFlag(args);
71
- const sub = parsed.rest[0] ?? 'open';
72
- const profileManager = requireProfileManager(ctx);
73
- if (sub === 'open') {
74
- if (ctx.openProfilePicker) {
75
- ctx.openProfilePicker();
76
- } else {
77
- const profiles = profileManager.list();
78
- if (profiles.length === 0) ctx.print('No profiles saved. Use /profiles save <name> --yes to save the current settings as a profile.');
79
- else ctx.print(['Saved profiles:', ...profiles.map(p => ` ${p.name}`)].join('\n'));
80
- }
81
- return;
82
- }
83
- if (sub === 'list') {
84
- const profiles = profileManager.list();
85
- if (profiles.length === 0) ctx.print('No profiles saved. Use /profiles save <name> --yes to save the current settings as a profile.');
86
- else ctx.print(['Saved profiles:', ...profiles.map(p => ` ${p.name}`)].join('\n'));
87
- return;
88
- }
89
- if (sub === 'save') {
90
- const name = parsed.rest[1];
91
- if (!name) {
92
- ctx.print('Usage: /profiles save <name> --yes');
93
- return;
94
- }
95
- if (!parsed.yes) {
96
- requireYesFlag(ctx, `save config profile ${name}`, '/profiles save <name> --yes');
97
- return;
98
- }
99
- const all = ctx.platform.configManager.getAll();
100
- const data: ProfileData = {
101
- display: { ...all.display },
102
- provider: {
103
- model: all.provider.model,
104
- reasoningEffort: all.provider.reasoningEffort,
105
- },
106
- behavior: { ...all.behavior },
107
- };
108
- profileManager.save(name, data);
109
- ctx.print(`Profile saved: ${name}`);
110
- return;
111
- }
112
- if (sub === 'delete' || sub === 'remove') {
113
- const name = parsed.rest[1];
114
- if (!name) {
115
- ctx.print('Usage: /profiles delete <name> --yes');
116
- return;
117
- }
118
- if (!parsed.yes) {
119
- requireYesFlag(ctx, `delete config profile ${name}`, '/profiles delete <name> --yes');
120
- return;
121
- }
122
- const deleted = profileManager.delete(name);
123
- ctx.print(deleted ? `Profile deleted: ${name}` : `Profile not found: ${name}`);
124
- return;
125
- }
126
- if (args.length === 0 && ctx.openProfilePicker) {
127
- ctx.openProfilePicker();
128
- return;
129
- }
130
- ctx.print('Usage: /profiles [list|open|save <name> --yes|delete <name> --yes]');
64
+ description: 'Blocked copied config-profile command; Agent uses isolated profile homes',
65
+ usage: 'disabled',
66
+ argsHint: 'disabled',
67
+ handler(_args, ctx) {
68
+ ctx.print([
69
+ 'Copied config profiles are disabled in GoodVibes Agent.',
70
+ 'Use /agent profiles or /agent-profile to create and manage isolated Agent profile homes.',
71
+ ].join('\n'));
131
72
  },
132
73
  });
133
74
 
@@ -93,7 +93,7 @@ function renderDiscoveredPersonas(personas: readonly DiscoveredPersonaRecord[]):
93
93
  return [
94
94
  'Discovered Agent persona files',
95
95
  ' No persona markdown files found in project/global Agent persona folders.',
96
- ' Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents',
96
+ ' Search roots: .goodvibes/personas, .goodvibes/agent/personas, ~/.goodvibes/personas, ~/.goodvibes/agent/personas',
97
97
  ].join('\n');
98
98
  }
99
99
  return [
@@ -27,69 +27,6 @@ function inspectAuthBundle(bundle: AuthReviewBundle): string {
27
27
  }
28
28
 
29
29
  export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry): void {
30
- registry.register({
31
- name: 'login',
32
- description: 'Front-door login flow for provider subscriptions',
33
- usage: 'provider <name> start|finish <code> --yes',
34
- async handler(args, ctx) {
35
- const parsed = stripYesFlag(args);
36
- const commandArgs = [...parsed.rest];
37
- const target = (commandArgs[0] ?? '').toLowerCase();
38
- if (target === 'provider') {
39
- const provider = commandArgs[1];
40
- const mode = commandArgs[2]?.toLowerCase();
41
- if (!provider || !mode) {
42
- ctx.print('Usage: /login provider <name> start|finish <code> --yes');
43
- return;
44
- }
45
- if (!parsed.yes) {
46
- requireYesFlag(ctx, `${mode} provider subscription login for ${provider}`, '/login provider <name> start|finish <code> --yes');
47
- return;
48
- }
49
- if (ctx.executeCommand) {
50
- await ctx.executeCommand('subscription', ['login', provider, mode, ...commandArgs.slice(3), '--yes']);
51
- return;
52
- }
53
- ctx.print(`Use /subscription login ${provider} ${mode}${commandArgs[3] ? ` ${commandArgs[3]}` : ''} --yes`);
54
- return;
55
- }
56
- if (target === 'service' || target === 'runtime' || target === 'listener' || target === 'daemon') {
57
- ctx.print([
58
- 'Connected-service login is outside GoodVibes Agent.',
59
- 'Agent does not create, exchange, store, rotate, revoke, or clear connected-service sessions.',
60
- 'Use the owning GoodVibes host for connected-service auth administration.',
61
- 'Agent login supports provider subscriptions only: /login provider <name> start|finish <code> --yes.',
62
- ].join('\n'));
63
- return;
64
- }
65
- ctx.print('Usage: /login provider <name> start|finish <code> --yes');
66
- },
67
- });
68
-
69
- registry.register({
70
- name: 'logout',
71
- description: 'Front-door logout flow for provider subscription sessions and supported overrides',
72
- usage: 'provider <name> --yes',
73
- async handler(args, ctx) {
74
- const parsed = stripYesFlag(args);
75
- const commandArgs = [...parsed.rest];
76
- const target = (commandArgs[0] ?? '').toLowerCase();
77
- if (target !== 'provider' || !commandArgs[1]) {
78
- ctx.print('Usage: /logout provider <name> --yes');
79
- return;
80
- }
81
- if (!parsed.yes) {
82
- requireYesFlag(ctx, `log out provider subscription ${commandArgs[1]}`, '/logout provider <name> --yes');
83
- return;
84
- }
85
- if (ctx.executeCommand) {
86
- await ctx.executeCommand('subscription', ['logout', commandArgs[1], '--yes']);
87
- return;
88
- }
89
- ctx.print(`Use /subscription logout ${commandArgs[1]} --yes`);
90
- },
91
- });
92
-
93
30
  registry.register({
94
31
  name: 'auth',
95
32
  description: 'Review provider auth posture and export redacted auth review bundles',
@@ -100,18 +37,18 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
100
37
  const sub = commandArgs[0] ?? 'review';
101
38
  if (sub === 'local') {
102
39
  ctx.print([
103
- 'Connected-service auth management is outside GoodVibes Agent.',
104
- 'Agent connects to GoodVibes services owned outside this package and does not create, delete, rotate, revoke, or clear connected-service auth users, sessions, or bootstrap credentials.',
105
- 'Use the owning GoodVibes host for connected-service auth administration.',
40
+ 'Connected-host auth management is outside GoodVibes Agent.',
41
+ 'Agent connects to a GoodVibes host owned outside this package and does not create, delete, rotate, revoke, or clear connected-host auth users, sessions, or bootstrap credentials.',
42
+ 'Use the owning GoodVibes host for connected-host auth administration.',
106
43
  'Agent auth commands available here: /auth review, /auth show <provider>, /auth repair <provider>, /auth bundle export <path> --yes, /auth bundle inspect <path>.',
107
44
  ].join('\n'));
108
45
  return;
109
46
  }
110
47
  if (sub === 'login') {
111
48
  ctx.print([
112
- 'Connected-service login is outside GoodVibes Agent.',
113
- 'Agent does not create, exchange, store, rotate, revoke, or clear connected-service sessions.',
114
- 'Use the owning GoodVibes host for connected-service auth administration.',
49
+ 'Connected-host login is outside GoodVibes Agent.',
50
+ 'Agent does not create, exchange, store, rotate, revoke, or clear connected-host sessions.',
51
+ 'Use the owning GoodVibes host for connected-host auth administration.',
115
52
  ].join('\n'));
116
53
  return;
117
54
  }
@@ -129,7 +66,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
129
66
  const builtinProviders = listBuiltinSubscriptionProviders().map((entry) => entry.provider);
130
67
  ctx.print([
131
68
  'Auth Review',
132
- ' connected-service auth: managed outside goodvibes-agent',
69
+ ' connected-host auth: managed outside goodvibes-agent',
133
70
  ` stored secrets: ${snapshot.secretKeyCount}`,
134
71
  ` built-in providers: ${builtinProviders.length}${builtinProviders.length > 0 ? ` (${builtinProviders.join(', ')})` : ''}`,
135
72
  ` active subscriptions: ${snapshot.activeSubscriptions}${snapshot.activeSubscriptions > 0 ? ` (${snapshot.providers.filter((provider) => provider.activeSubscription).map((provider) => provider.provider).join(', ')})` : ''}`,
@@ -289,7 +289,7 @@ async function handleStatus(_args: string[], context: CommandContext): Promise<v
289
289
  export function renderPolicyUsage(): string {
290
290
  return [
291
291
  'Usage: /policy <subcommand>',
292
- ' /policy open the policy/governance panel',
292
+ ' /policy status show current policy state',
293
293
  ' load <bundle-id> [rule-count] — Load a candidate bundle',
294
294
  ' simulate [mode] — Run simulation (silent|warn|enforce)',
295
295
  ' diff — Show rule diff (current vs candidate)',
@@ -4,14 +4,10 @@ import { dispatchPolicyCommand } from './policy-dispatch.ts';
4
4
  export const policyCommand: SlashCommand = {
5
5
  name: 'policy',
6
6
  aliases: ['pol'],
7
- description: 'Open the policy panel or manage versioned policy bundles (load, simulate, diff, promote, rollback).',
7
+ description: 'Review or manage versioned policy bundles (load, simulate, diff, promote, rollback).',
8
8
  usage: '<subcommand> [args]',
9
9
  argsHint: 'load|simulate|diff|lint|preflight|promote|rollback|status',
10
10
  handler: async (args: string[], context: CommandContext): Promise<void> => {
11
- if (args.length === 0 && context.openPolicyPanel) {
12
- context.openPolicyPanel();
13
- return;
14
- }
15
11
  await dispatchPolicyCommand(args, context);
16
12
  },
17
13
  };
@@ -68,7 +68,7 @@ function formatTrustReview(bundle: TrustReviewBundle): string {
68
68
  'Trust Review',
69
69
  ` permission mode: ${bundle.permissionMode}`,
70
70
  ` secrets stored: ${bundle.secretKeys.length}`,
71
- ` configured services: ${bundle.serviceNames.length}`,
71
+ ` configured integrations: ${bundle.serviceNames.length}`,
72
72
  ` plugins: ${bundle.pluginSummary.total} (trusted ${bundle.pluginSummary.trusted}, limited ${bundle.pluginSummary.limited}, untrusted ${bundle.pluginSummary.untrusted}, quarantined ${bundle.pluginSummary.quarantined})`,
73
73
  ` MCP servers: ${bundle.mcpSummary.total} (constrained ${bundle.mcpSummary.constrained}, ask-on-risk ${bundle.mcpSummary.askOnRisk}, allow-all ${bundle.mcpSummary.allowAll}, blocked ${bundle.mcpSummary.blocked}, quarantined ${bundle.mcpSummary.quarantined})`,
74
74
  ].join('\n');
@@ -81,7 +81,7 @@ function inspectTrustBundle(path: string): string {
81
81
  ` captured: ${new Date(parsed.capturedAt).toISOString()}`,
82
82
  ` permission mode: ${parsed.permissionMode}`,
83
83
  ` secrets stored: ${parsed.secretKeys.length}`,
84
- ` configured services: ${parsed.serviceNames.length}`,
84
+ ` configured integrations: ${parsed.serviceNames.length}`,
85
85
  ` plugins: ${parsed.pluginSummary.total}`,
86
86
  ` MCP servers: ${parsed.mcpSummary.total}`,
87
87
  ].join('\n');
@@ -1,16 +1,15 @@
1
1
  import type { CommandRegistry } from '../command-registry.ts';
2
- import { join } from 'node:path';
3
2
  import { networkInterfaces } from 'node:os';
4
3
  import {
5
4
  buildCompanionConnectionInfo,
6
5
  encodeConnectionPayload,
7
6
  formatConnectionBlock,
8
7
  generateQrMatrix,
9
- getOrCreateCompanionToken,
10
8
  renderQrToString,
11
9
  } from '@pellux/goodvibes-sdk/platform/pairing';
12
10
  import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../../config/surface.ts';
13
11
  import { resolveRuntimeEndpointBinding } from '../../cli/endpoints.ts';
12
+ import { connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../../runtime/connected-host-auth.ts';
14
13
  import { requirePlatform, requireShellPaths } from './runtime-services.ts';
15
14
 
16
15
  function getLocalNetworkIp(): string {
@@ -41,8 +40,11 @@ export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
41
40
  handler(_args, ctx) {
42
41
  const shellPaths = requireShellPaths(ctx);
43
42
  const configManager = requirePlatform(ctx).configManager;
44
- const daemonHomeDir = join(shellPaths.homeDirectory, '.goodvibes', 'daemon');
45
- const tokenRecord = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
43
+ const tokenRecord = readConnectedHostOperatorToken(shellPaths.homeDirectory);
44
+ if (!tokenRecord.token) {
45
+ ctx.print(connectedHostTokenRequiredMessage(tokenRecord.path));
46
+ return;
47
+ }
46
48
  const binding = resolveRuntimeEndpointBinding(configManager, 'controlPlane');
47
49
  const daemonUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
48
50
  const info = buildCompanionConnectionInfo({
@@ -1,5 +1,6 @@
1
1
  import { discoverRoutines, type DiscoveredRoutineRecord } from '../../agent/routine-discovery.ts';
2
- import { AgentRoutineRegistry, type AgentRoutineRecord } from '../../agent/routine-registry.ts';
2
+ import { AgentRoutineRegistry, evaluateAgentRoutineReadiness, type AgentRoutineRecord } from '../../agent/routine-registry.ts';
3
+ import { buildAgentSkillRequirements, formatAgentSkillRequirement } from '../../agent/skill-registry.ts';
3
4
  import {
4
5
  buildRoutineSchedulePreview,
5
6
  promoteRoutineToDaemonSchedule,
@@ -75,13 +76,17 @@ function requiredFlag(flags: ReadonlyMap<string, string>, key: string): string {
75
76
  function summarizeRoutine(routine: AgentRoutineRecord): string {
76
77
  const enabled = routine.enabled ? 'enabled' : 'disabled';
77
78
  const tags = routine.tags.length > 0 ? ` tags=${routine.tags.join(',')}` : '';
78
- return ` ${routine.id} ${enabled} ${routine.reviewState} starts=${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
79
+ const readiness = evaluateAgentRoutineReadiness(routine);
80
+ const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
81
+ return ` ${routine.id} ${enabled} ${routine.reviewState} ${ready} starts=${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
79
82
  }
80
83
 
81
- function renderList(title: string, registry: AgentRoutineRegistry, routines: readonly AgentRoutineRecord[]): string {
84
+ function renderList(title: string, registry: AgentRoutineRegistry, routines: readonly AgentRoutineRecord[], emptyMessage?: string): string {
82
85
  const snapshot = registry.snapshot();
83
86
  if (routines.length === 0) {
84
- return `${title}\n No local Agent routines yet. Create one with /routines create --name <name> --description <summary> --steps <steps>.`;
87
+ return emptyMessage
88
+ ? `${title}\n ${emptyMessage}`
89
+ : `${title}\n No local Agent routines yet. Create one with /routines create --name <name> --description <summary> --steps <steps>.`;
85
90
  }
86
91
  return [
87
92
  `${title} (${routines.length})`,
@@ -92,10 +97,14 @@ function renderList(title: string, registry: AgentRoutineRegistry, routines: rea
92
97
  }
93
98
 
94
99
  function renderRoutine(routine: AgentRoutineRecord): string {
100
+ const readiness = evaluateAgentRoutineReadiness(routine);
95
101
  return [
96
102
  `Routine ${routine.name}`,
97
103
  ` id: ${routine.id}`,
98
104
  ` enabled: ${routine.enabled ? 'yes' : 'no'}`,
105
+ ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
106
+ ` requirements: ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
107
+ readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
99
108
  ` review: ${routine.reviewState}`,
100
109
  ` source: ${routine.source}`,
101
110
  ` provenance: ${routine.provenance}`,
@@ -151,6 +160,14 @@ function frontmatterList(routine: DiscoveredRoutineRecord, key: string): readonl
151
160
  return splitList(value);
152
161
  }
153
162
 
163
+ function frontmatterAnyList(routine: DiscoveredRoutineRecord, keys: readonly string[]): readonly string[] {
164
+ for (const key of keys) {
165
+ const values = frontmatterList(routine, key);
166
+ if (values.length > 0) return values;
167
+ }
168
+ return [];
169
+ }
170
+
154
171
  function printError(ctx: CommandContext, error: unknown): void {
155
172
  ctx.print(`Error: ${error instanceof Error ? error.message : String(error)}`);
156
173
  }
@@ -185,6 +202,10 @@ async function importDiscoveredRoutine(args: readonly string[], ctx: CommandCont
185
202
  steps: discovered.steps,
186
203
  tags: frontmatterList(discovered, 'tags'),
187
204
  triggers: frontmatterList(discovered, 'triggers'),
205
+ requirements: buildAgentSkillRequirements({
206
+ env: frontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
207
+ commands: frontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
208
+ }),
188
209
  enabled: parsed.flags.get('enabled') === 'true',
189
210
  source: 'imported',
190
211
  provenance: `discovered:${discovered.origin}:${discovered.path}`,
@@ -231,6 +252,11 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
231
252
  ctx.print(renderList('Enabled Agent Routines', routineRegistry, snapshot.enabledRoutines));
232
253
  return;
233
254
  }
255
+ if (sub === 'attention' || sub === 'needs-setup') {
256
+ const routines = routineRegistry.list().filter((routine) => !evaluateAgentRoutineReadiness(routine).ready);
257
+ ctx.print(renderList('Agent Routines needing setup', routineRegistry, routines, 'No local Agent routines need setup.'));
258
+ return;
259
+ }
234
260
  if (sub === 'discover' || sub === 'discovered') {
235
261
  ctx.print(renderDiscoveredRoutines(await discoverRoutines(requireShellPaths(ctx))));
236
262
  return;
@@ -284,6 +310,10 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
284
310
  steps,
285
311
  triggers: splitList(parsed.flags.get('triggers')),
286
312
  tags: splitList(parsed.flags.get('tags')),
313
+ requirements: buildAgentSkillRequirements({
314
+ env: splitList(parsed.flags.get('requires-env')),
315
+ commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
316
+ }),
287
317
  enabled: parsed.flags.get('enabled') === 'true',
288
318
  source: 'user',
289
319
  provenance: 'slash-command',
@@ -304,6 +334,12 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
304
334
  steps: parsed.flags.get('steps'),
305
335
  triggers: parsed.flags.has('triggers') ? splitList(parsed.flags.get('triggers')) : undefined,
306
336
  tags: parsed.flags.has('tags') ? splitList(parsed.flags.get('tags')) : undefined,
337
+ requirements: parsed.flags.has('requires-env') || parsed.flags.has('requires-command') || parsed.flags.has('requires-commands')
338
+ ? buildAgentSkillRequirements({
339
+ env: splitList(parsed.flags.get('requires-env')),
340
+ commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
341
+ })
342
+ : undefined,
307
343
  provenance: 'slash-command',
308
344
  });
309
345
  ctx.print(`Updated Agent routine ${updated.id}: ${updated.name}`);
@@ -326,8 +362,10 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
326
362
  return;
327
363
  }
328
364
  const routine = routineRegistry.markStarted(id);
365
+ const readiness = evaluateAgentRoutineReadiness(routine);
329
366
  ctx.print([
330
367
  `Started Agent routine ${routine.id}: ${routine.name}`,
368
+ ` readiness: ${readiness.ready ? 'ready' : `needs setup (${readiness.missing.map(formatAgentSkillRequirement).join(', ')})`}`,
331
369
  ' policy: same main conversation; no hidden job, runtime mutation, or external side effect was started',
332
370
  '',
333
371
  routine.steps,
@@ -373,7 +411,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
373
411
  ctx.print(`Deleted Agent routine ${removed.id}: ${removed.name}`);
374
412
  return;
375
413
  }
376
- ctx.print('Usage: /routines [list|enabled|discover|import-discovered|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]');
414
+ ctx.print('Usage: /routines [list|enabled|attention|discover|import-discovered|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]');
377
415
  } catch (error) {
378
416
  printError(ctx, error);
379
417
  }
@@ -384,7 +422,7 @@ export function registerRoutinesRuntimeCommands(registry: CommandRegistry): void
384
422
  name: 'routines',
385
423
  aliases: ['routine'],
386
424
  description: 'Manage local GoodVibes Agent routines',
387
- usage: '[list|enabled|discover|import-discovered <name> --yes|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps>|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]',
425
+ usage: '[list|enabled|attention|discover|import-discovered <name> --yes|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps> [--requires-env A,B] [--requires-command gh,jq]|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]',
388
426
  handler: runRoutinesRuntimeCommand,
389
427
  });
390
428
  }
@@ -22,7 +22,6 @@ import { GOODVIBES_AGENT_SURFACE_ROOT } from '../../config/surface.ts';
22
22
  import type { ProviderApi } from '@pellux/goodvibes-sdk/platform/providers';
23
23
  import type {
24
24
  ShellAgentManagerService,
25
- ShellAcpManagerService,
26
25
  ShellAutomationManagerService,
27
26
  ShellAutomationManagerRuntimeService,
28
27
  ShellModeManagerService,
@@ -32,7 +31,7 @@ import type {
32
31
 
33
32
  function requireContextValue<T>(value: T | null | undefined, name: string): T {
34
33
  if (value == null) {
35
- throw new Error(`commandContext.${name} is required but was not wired at bootstrap`);
34
+ throw new Error(`commandContext.${name} is unavailable in this Agent runtime`);
36
35
  }
37
36
  return value;
38
37
  }
@@ -274,10 +273,6 @@ export function requireAgentManager(context: CommandContext): ShellAgentManagerS
274
273
  return requireContextValue(context.ops.agentManager, 'ops.agentManager') as ShellAgentManagerService;
275
274
  }
276
275
 
277
- export function requireAcpManager(context: CommandContext): ShellAcpManagerService {
278
- return requireContextValue(context.ops.acpManager, 'ops.acpManager') as ShellAcpManagerService;
279
- }
280
-
281
276
  export function requireModeManager(context: CommandContext): ShellModeManagerService {
282
277
  return requireContextValue(context.ops.modeManager, 'ops.modeManager') as ShellModeManagerService;
283
278
  }
@@ -285,11 +280,3 @@ export function requireModeManager(context: CommandContext): ShellModeManagerSer
285
280
  export function requireAutomationManager(context: CommandContext): ShellAutomationManagerRuntimeService {
286
281
  return requireContextValue(context.ops.automationManager, 'ops.automationManager') as ShellAutomationManagerRuntimeService;
287
282
  }
288
-
289
- export function requireSandboxSessionRegistry(context: CommandContext) {
290
- return requireContextValue(context.workspace.sandboxSessionRegistry, 'workspace.sandboxSessionRegistry');
291
- }
292
-
293
- export function requireWorktreeRegistry(context: CommandContext) {
294
- return requireContextValue(context.workspace.worktreeRegistry, 'workspace.worktreeRegistry');
295
- }
@@ -10,16 +10,11 @@ export function registerSecurityRuntimeCommands(registry: CommandRegistry): void
10
10
  description: 'Inspect security posture, attack paths, and review state',
11
11
  usage: '[review | attack-paths | tokens]',
12
12
  handler(args, ctx) {
13
- if (args.length === 0) {
14
- if (ctx.openSecurityPanel) {
15
- ctx.openSecurityPanel();
16
- return;
17
- }
18
- ctx.print('Security panel is not available in this runtime.');
13
+ const subcommand = args[0]?.toLowerCase() ?? 'review';
14
+ if (subcommand === 'open' || subcommand === 'panel') {
15
+ ctx.print('Security panels are not part of the Agent workspace. Use /security review.');
19
16
  return;
20
17
  }
21
-
22
- const subcommand = args[0]?.toLowerCase() ?? 'review';
23
18
  const audit = requireTokenAuditor(ctx).auditAll(Date.now());
24
19
  const securitySnapshot = requireReadModels(ctx).security.getSnapshot();
25
20
  const policySnapshot = ctx.extensions.policyRuntimeState?.getSnapshot();
@@ -144,7 +144,7 @@ export function registerSessionContentCommands(registry: CommandRegistry): void
144
144
  if (meta.title) ctx.session.conversationManager.title = meta.title;
145
145
  ctx.session.conversationManager.rebuildHistory();
146
146
  ctx.renderRequest();
147
- ctx.print(`Session loaded: ${args[0]} (${messages.length} messages)${agentRecords.length > 0 ? ` [ignored ${agentRecords.length} service-owned local agent record${agentRecords.length !== 1 ? 's' : ''}]` : ''}`);
147
+ ctx.print(`Session loaded: ${args[0]} (${messages.length} messages)${agentRecords.length > 0 ? ` [ignored ${agentRecords.length} host-owned local agent record${agentRecords.length !== 1 ? 's' : ''}]` : ''}`);
148
148
  } catch (e) {
149
149
  ctx.print(`Failed to load session: ${summarizeError(e)}`);
150
150
  }
@@ -6,7 +6,7 @@ import type { TranscriptEventKind } from '@pellux/goodvibes-sdk/platform/core';
6
6
  import type { ConversationTitleSource } from '../../core/conversation';
7
7
  import type { SessionReturnContextSummary } from '@/runtime/index.ts';
8
8
  import { formatReturnContextForDisplay, getReturnContextMode, maybeAssistReturnContextSummary } from '@/runtime/index.ts';
9
- import { requirePanelManager, requireProviderApi, requireSessionManager } from './runtime-services.ts';
9
+ import { requireProviderApi, requireSessionManager } from './runtime-services.ts';
10
10
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
11
11
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
12
12
 
@@ -81,18 +81,8 @@ function buildTranscriptReviewLines(
81
81
 
82
82
  function reopenPanelsFromReturnContext(ctx: CommandContext, summary: SessionReturnContextSummary | undefined): string[] {
83
83
  if (!summary?.openPanels || summary.openPanels.length === 0) return [];
84
- const panelManager = requirePanelManager(ctx);
85
- const reopened: string[] = [];
86
- for (const panelId of summary.openPanels.slice(0, 4)) {
87
- try {
88
- panelManager.open(panelId);
89
- reopened.push(panelId);
90
- } catch {
91
- // Ignore unknown or currently unavailable panel ids during resume.
92
- }
93
- }
94
- if (reopened.length > 0) panelManager.show();
95
- return reopened;
84
+ ctx.print(` Saved panel state ignored: ${summary.openPanels.slice(0, 4).join(', ')}. Use /agent for the Agent operator workspace.`);
85
+ return [];
96
86
  }
97
87
 
98
88
  function printSessionExport(
@@ -182,7 +172,7 @@ export async function handleSessionWorkflowCommand(args: string[], ctx: CommandC
182
172
  session.returnContext.activeTasks ? `active=${session.returnContext.activeTasks}` : null,
183
173
  session.returnContext.blockedTasks ? `blocked=${session.returnContext.blockedTasks}` : null,
184
174
  session.returnContext.pendingApprovals ? `approvals=${session.returnContext.pendingApprovals}` : null,
185
- session.returnContext.openPanels?.length ? `panels=${session.returnContext.openPanels.slice(0, 3).join(',')}` : null,
175
+ session.returnContext.openPanels?.length ? `saved-panel-state-ignored=${session.returnContext.openPanels.slice(0, 3).join(',')}` : null,
186
176
  ].filter(Boolean).join(' ');
187
177
  if (posture) lines.push(` posture: ${posture}`);
188
178
  }
@@ -258,6 +248,7 @@ export async function handleSessionWorkflowCommand(args: string[], ctx: CommandC
258
248
  const returnContextMode = getReturnContextMode(ctx.platform.configManager);
259
249
  if (returnContextMode !== 'off' && meta.returnContext) {
260
250
  for (const line of formatReturnContextForDisplay(meta.returnContext)) {
251
+ if (line.startsWith('Open panels:')) continue;
261
252
  ctx.print(` ${line}`);
262
253
  }
263
254
  if (reopenedPanels.length > 0) {
@@ -115,6 +115,10 @@ export function registerShellCoreCommands(registry: CommandRegistry): void {
115
115
  if (ctx.openSelection) {
116
116
  const items: SelectionItem[] = [
117
117
  { id: '/agent', label: '/agent', detail: 'Open the Agent operator workspace', category: 'Agent Operator' },
118
+ { id: '/agent setup', label: '/agent setup', detail: 'Open the Agent setup workspace', category: 'Agent Operator' },
119
+ { id: '/agent channels', label: '/agent channels', detail: 'Open channel readiness and delivery safety', category: 'Agent Operator' },
120
+ { id: '/agent knowledge', label: '/agent knowledge', detail: 'Open isolated Agent Knowledge workflows', category: 'Agent Operator' },
121
+ { id: '/agent voice-media', label: '/agent voice-media', detail: 'Open voice, TTS, image, browser, and media setup', category: 'Agent Operator' },
118
122
  { id: '/home', label: '/home', detail: 'Alias for the Agent operator workspace', category: 'Agent Operator' },
119
123
  { id: '/brief', label: '/brief', detail: 'Show a concise Agent operator briefing and next actions', category: 'Agent Operator' },
120
124
  { id: '/knowledge', label: '/knowledge', detail: 'Inspect isolated Agent Knowledge status, ask/search, and ingest flows', category: 'Agent Operator' },
@@ -124,7 +128,7 @@ export function registerShellCoreCommands(registry: CommandRegistry): void {
124
128
  { id: '/routines', label: '/routines', detail: 'Create, review, start, and promote Agent routines explicitly', category: 'Agent Operator' },
125
129
  { id: '/delegate', label: '/delegate [task]', detail: 'Explicit build/fix/review handoff to GoodVibes TUI', category: 'Agent Operator' },
126
130
  { id: '/channels', label: '/channels', detail: 'Inspect messaging-channel readiness without sending messages', category: 'Agent Operator' },
127
- { id: '/pair', label: '/pair', detail: 'Pair companion clients through connected GoodVibes services', category: 'Agent Operator' },
131
+ { id: '/pair', label: '/pair', detail: 'Pair companion clients through connected GoodVibes host', category: 'Agent Operator' },
128
132
  { id: '/model', label: '/model [id]', detail: 'Select LLM model', category: 'Model & Provider' },
129
133
  { id: '/provider', label: '/provider [name]', detail: 'Switch provider', category: 'Model & Provider' },
130
134
  { id: '/effort', label: '/effort [level]', detail: 'Reasoning effort (instant/low/medium/high)', category: 'Model & Provider' },
@@ -156,7 +160,9 @@ export function registerShellCoreCommands(registry: CommandRegistry): void {
156
160
  { id: '/paste', label: '/paste', detail: 'Insert clipboard text or image into the prompt', category: 'Tools & System' },
157
161
  { id: '/shortcuts', label: '/shortcuts', detail: 'View keyboard shortcuts reference', category: 'Tools & System' },
158
162
  { id: '/commands', label: '/commands', detail: 'Browse all commands in a scrollable list', category: 'Tools & System' },
163
+ { id: '/compat', label: '/compat', detail: 'Inspect connected-host and Agent Knowledge compatibility', category: 'Tools & System' },
159
164
  { id: '/secrets', label: '/secrets set|link|get|test|list|delete', detail: 'Manage encrypted and provider-backed secrets', category: 'Tools & System' },
165
+ { id: '/bundle', label: '/bundle export|inspect|import', detail: 'Manage redacted Agent support bundles', category: 'Tools & System' },
160
166
  { id: '/help', label: '/help', detail: 'This help', category: 'Tools & System' },
161
167
  { id: '/quit', label: '/quit', detail: 'Exit', category: 'Tools & System' },
162
168
  ];
@@ -172,7 +178,7 @@ export function registerShellCoreCommands(registry: CommandRegistry): void {
172
178
  });
173
179
  return;
174
180
  }
175
- ctx.print('Use /help to open the help modal. Commands: /agent, /brief, /knowledge, /memory, /personas, /agent-skills, /routines, /channels, /delegate, /model, /provider, /config, /paste, /sessions, /bookmarks, /save, /load, /undo, /redo, /retry, /clear, /reset, /compact, /export, /title, /effort, /expand, /collapse, /quit');
181
+ ctx.print('Use /help to open the help modal. Commands: /agent, /brief, /knowledge, /memory, /personas, /agent-skills, /routines, /channels, /delegate, /model, /provider, /config, /compat, /bundle, /paste, /sessions, /bookmarks, /save, /load, /undo, /redo, /retry, /clear, /reset, /compact, /export, /title, /effort, /expand, /collapse, /quit');
176
182
  },
177
183
  });
178
184