@pellux/goodvibes-agent 0.1.9 → 0.1.11

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 (97) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +1 -1
  3. package/docs/getting-started.md +1 -1
  4. package/docs/release-and-publishing.md +2 -2
  5. package/package.json +4 -1
  6. package/src/cli/agent-knowledge-command.ts +46 -20
  7. package/src/cli/help.ts +15 -2
  8. package/src/cli/management-commands.ts +3 -3
  9. package/src/cli/management.ts +7 -1
  10. package/src/cli/parser.ts +3 -0
  11. package/src/cli/service-posture.ts +6 -6
  12. package/src/cli/status.ts +9 -9
  13. package/src/cli/surface-command.ts +3 -3
  14. package/src/cli/types.ts +2 -0
  15. package/src/input/commands/cloudflare-runtime.ts +20 -5
  16. package/src/input/commands/confirmation.ts +24 -0
  17. package/src/input/commands/discovery-runtime.ts +16 -7
  18. package/src/input/commands/eval.ts +27 -14
  19. package/src/input/commands/experience-runtime.ts +66 -27
  20. package/src/input/commands/health-runtime.ts +1 -1
  21. package/src/input/commands/hooks-runtime.ts +79 -20
  22. package/src/input/commands/incident-runtime.ts +17 -6
  23. package/src/input/commands/integration-runtime.ts +93 -50
  24. package/src/input/commands/knowledge.ts +38 -12
  25. package/src/input/commands/local-auth-runtime.ts +36 -13
  26. package/src/input/commands/local-provider-runtime.ts +22 -11
  27. package/src/input/commands/local-runtime.ts +21 -11
  28. package/src/input/commands/local-setup.ts +35 -16
  29. package/src/input/commands/managed-runtime.ts +51 -20
  30. package/src/input/commands/marketplace-runtime.ts +31 -16
  31. package/src/input/commands/mcp-runtime.ts +65 -34
  32. package/src/input/commands/memory-product-runtime.ts +72 -35
  33. package/src/input/commands/memory.ts +9 -9
  34. package/src/input/commands/notify-runtime.ts +27 -8
  35. package/src/input/commands/operator-runtime.ts +85 -17
  36. package/src/input/commands/planning-runtime.ts +14 -2
  37. package/src/input/commands/platform-access-runtime.ts +88 -45
  38. package/src/input/commands/platform-services-runtime.ts +51 -25
  39. package/src/input/commands/product-runtime.ts +54 -27
  40. package/src/input/commands/profile-sync-runtime.ts +17 -6
  41. package/src/input/commands/recall-bundle.ts +38 -17
  42. package/src/input/commands/recall-query.ts +15 -4
  43. package/src/input/commands/recall-review.ts +9 -3
  44. package/src/input/commands/remote-runtime-setup.ts +45 -18
  45. package/src/input/commands/remote-runtime.ts +25 -9
  46. package/src/input/commands/replay-runtime.ts +9 -2
  47. package/src/input/commands/services-runtime.ts +21 -10
  48. package/src/input/commands/session-content.ts +53 -51
  49. package/src/input/commands/session-workflow.ts +10 -4
  50. package/src/input/commands/session.ts +1 -1
  51. package/src/input/commands/settings-sync-runtime.ts +40 -17
  52. package/src/input/commands/share-runtime.ts +12 -4
  53. package/src/input/commands/shell-core.ts +3 -3
  54. package/src/input/commands/subscription-runtime.ts +35 -20
  55. package/src/input/commands/teleport-runtime.ts +16 -5
  56. package/src/input/commands/work-plan-runtime.ts +23 -12
  57. package/src/input/handler-content-actions.ts +11 -62
  58. package/src/input/handler-interactions.ts +1 -1
  59. package/src/input/handler-onboarding-cloudflare.ts +48 -117
  60. package/src/input/handler.ts +1 -0
  61. package/src/input/keybindings.ts +1 -1
  62. package/src/input/mcp-workspace.ts +25 -49
  63. package/src/input/onboarding/onboarding-runtime-status.ts +8 -8
  64. package/src/input/onboarding/onboarding-wizard-apply.ts +13 -53
  65. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +12 -12
  66. package/src/input/onboarding/onboarding-wizard-cloudflare.ts +2 -7
  67. package/src/input/onboarding/onboarding-wizard-constants.ts +7 -7
  68. package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +4 -4
  69. package/src/input/onboarding/onboarding-wizard-steps.ts +13 -13
  70. package/src/input/profile-picker-modal.ts +13 -31
  71. package/src/input/session-picker-modal.ts +4 -30
  72. package/src/input/settings-modal-agent-policy.ts +18 -0
  73. package/src/input/settings-modal-subscriptions.ts +3 -3
  74. package/src/input/settings-modal-types.ts +17 -0
  75. package/src/input/settings-modal.ts +30 -29
  76. package/src/main.ts +3 -26
  77. package/src/panels/incident-review-panel.ts +1 -1
  78. package/src/panels/local-auth-panel.ts +4 -4
  79. package/src/panels/provider-account-snapshot.ts +1 -1
  80. package/src/panels/provider-health-domains.ts +2 -2
  81. package/src/panels/settings-sync-panel.ts +2 -2
  82. package/src/panels/subscription-panel.ts +7 -7
  83. package/src/renderer/block-actions.ts +1 -1
  84. package/src/renderer/help-overlay.ts +2 -2
  85. package/src/renderer/mcp-workspace.ts +12 -12
  86. package/src/renderer/process-modal.ts +17 -8
  87. package/src/renderer/profile-picker-modal.ts +3 -11
  88. package/src/renderer/session-picker-modal.ts +2 -10
  89. package/src/renderer/settings-modal.ts +12 -8
  90. package/src/renderer/ui-factory.ts +4 -32
  91. package/src/runtime/bootstrap-shell.ts +0 -13
  92. package/src/runtime/bootstrap.ts +0 -10
  93. package/src/runtime/onboarding/derivation.ts +6 -6
  94. package/src/verification/live-verifier.ts +148 -13
  95. package/src/version.ts +10 -3
  96. package/src/input/commands/quit-shared.ts +0 -162
  97. package/src/renderer/git-status.ts +0 -89
package/CHANGELOG.md CHANGED
@@ -2,6 +2,47 @@
2
2
 
3
3
  All notable changes to GoodVibes Agent will be recorded here.
4
4
 
5
+ ## 0.1.11 - 2026-05-31
6
+
7
+ - d20a93e Allow explicit recall review without yes
8
+ - 601f41c Require confirmation for eval execution
9
+ - f41befb Block Cloudflare onboarding mutations
10
+ - 79071ec Block implicit block file saves
11
+ - 40aca02 Block inline diff file edits in Agent
12
+ - 854eda8 Block MCP workspace config mutations
13
+ - 665c423 Require confirmation for CLI Agent Knowledge ingest
14
+ - f07255a Require confirmation for recall review mutations
15
+ - 6e78ec3 Require confirmation for Agent Knowledge mutations
16
+ - c1e5ac1 Require confirmation for operator control mutations
17
+ - 5d6fc3c Require confirmation for local state mutations
18
+ - 3afd788 Require confirmation for remaining export paths
19
+ - d36ae96 Require confirmation for portable state bundles
20
+ - 1f0caab Require confirmation for setup and remote exports
21
+ - 2e149c9 Require confirmation for incident and handoff exports
22
+ - b439c55 Require confirmation for settings mutations
23
+ - f7c8fe6 Require confirmation for platform auth mutations
24
+ - 09064e0 Require confirmation for auth and service mutations
25
+ - 55e8b8d Require confirmation for marketplace mutations
26
+ - 88becca Require confirmation for plugin mutations
27
+ - 89c0584 Require confirmation for local provider mutations
28
+ - 7f3af1b Require confirmation for managed hook mutations
29
+ - 323426c Require confirmation for destructive workplan cleanup
30
+ - 191350e Require confirmation for side-effecting slash commands
31
+
32
+ ## 0.1.10 - 2026-05-31
33
+
34
+ - 93aba19 Block agent-spawning hook authoring
35
+ - 735839a Prune git header renderer from Agent
36
+ - 95d22fd Remove unused git shell bootstrap wiring
37
+ - 1392ebc Remove Agent write-quit commit helper
38
+ - df6572f Remove coding header posture from Agent shell
39
+ - 2b8e679 Align live verification with Agent routes
40
+ - 70eb800 Add stable typecheck release scripts
41
+ - 6b57500 Hide local agent activity in Agent UI
42
+ - 7166188 Add Agent Knowledge CLI shortcuts
43
+ - 386c19d Align service diagnostics with Agent boundaries
44
+ - e8b19db Lock daemon-owned settings in Agent
45
+
5
46
  ## 0.1.9 - 2026-05-31
6
47
 
7
48
  - 75e5d4a Align shell surface delegation test
package/README.md CHANGED
@@ -35,7 +35,7 @@ bun run dev
35
35
  Useful checks:
36
36
 
37
37
  ```sh
38
- bunx tsc --noEmit
38
+ bun run typecheck
39
39
  bun run build
40
40
  bun run package:install-check
41
41
  bun run publish:check
@@ -1,6 +1,6 @@
1
1
  # Getting Started
2
2
 
3
- GoodVibes Agent `0.1.7` is the current installable public alpha of the personal operator assistant built on the GoodVibes TUI foundation.
3
+ GoodVibes Agent `0.1.9` is the current installable public alpha of the personal operator assistant built on the GoodVibes TUI foundation.
4
4
 
5
5
  ## Requirements
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Release And Publishing
2
2
 
3
- GoodVibes Agent `0.1.7` is the current installable public alpha release.
3
+ GoodVibes Agent `0.1.9` is the current installable public alpha release.
4
4
 
5
5
  ## Package Identity
6
6
 
@@ -17,7 +17,7 @@ Before any release candidate:
17
17
 
18
18
  ```sh
19
19
  bun install
20
- bunx tsc --noEmit
20
+ bun run typecheck
21
21
  bun run build
22
22
  bun run package:install-check
23
23
  bun run publish:check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-agent",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "private": false,
5
5
  "description": "Near-fork GoodVibes operator assistant with the GoodVibes TUI shell, renderer, input, fullscreen workspace, and daemon-connected Agent product brain.",
6
6
  "type": "module",
@@ -40,6 +40,8 @@
40
40
  "dev": "bun run src/main.ts",
41
41
  "tui": "bun run src/main.ts",
42
42
  "dev:watch": "bun --watch src/main.ts",
43
+ "typecheck": "bunx tsc --noEmit",
44
+ "check:types": "bun run typecheck",
43
45
  "prebuild": "bun run scripts/prebuild.ts",
44
46
  "build": "bun build src/main.ts --compile --outfile dist/goodvibes-agent",
45
47
  "build:linux-x64": "bun build src/main.ts --compile --target=bun-linux-x64 --outfile dist/goodvibes-agent-linux-x64",
@@ -61,6 +63,7 @@
61
63
  "build:all": "bun run scripts/build.ts --all",
62
64
  "perf:check": "bun run scripts/perf-check.ts",
63
65
  "architecture:check": "bun run scripts/check-architecture.ts",
66
+ "audit:home": "bun run scripts/audit-goodvibes-home.ts",
64
67
  "foundation:artifacts": "bun run scripts/export-foundation-artifacts.ts",
65
68
  "verification:ledger": "bun run scripts/verification-ledger.ts",
66
69
  "verification:live": "bun run scripts/verify-live.ts",
@@ -1,8 +1,8 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
2
+ import { join } from 'node:path';
4
3
  import { createBrowserAgentSdk } from '@pellux/goodvibes-sdk/browser/agent';
5
4
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
5
+ import { SDK_VERSION, VERSION } from '../version.ts';
6
6
  import type { CliCommandOutput } from './types.ts';
7
7
  import type { CliCommandRuntime } from './management.ts';
8
8
  import { formatJsonOrText, yesNo } from './management.ts';
@@ -149,24 +149,21 @@ function hasFlag(args: readonly string[], flag: string): boolean {
149
149
  return args.includes(flag);
150
150
  }
151
151
 
152
- function packageJsonPath(): string {
153
- return join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json');
152
+ function stripCommandFlag(args: readonly string[], flag: string): { readonly rest: readonly string[]; readonly present: boolean } {
153
+ const rest: string[] = [];
154
+ let present = false;
155
+ for (const arg of args) {
156
+ if (arg === flag) {
157
+ present = true;
158
+ continue;
159
+ }
160
+ rest.push(arg);
161
+ }
162
+ return { rest, present };
154
163
  }
155
164
 
156
165
  function readPackageMetadata(): { readonly version: string; readonly sdkVersion: string } {
157
- try {
158
- const parsed = JSON.parse(readFileSync(packageJsonPath(), 'utf-8')) as unknown;
159
- if (!isRecord(parsed)) return { version: 'unknown', sdkVersion: 'unknown' };
160
- const dependencies = isRecord(parsed.dependencies) ? parsed.dependencies : {};
161
- return {
162
- version: typeof parsed.version === 'string' ? parsed.version : 'unknown',
163
- sdkVersion: typeof dependencies['@pellux/goodvibes-sdk'] === 'string'
164
- ? dependencies['@pellux/goodvibes-sdk']
165
- : 'unknown',
166
- };
167
- } catch {
168
- return { version: 'unknown', sdkVersion: 'unknown' };
169
- }
166
+ return { version: VERSION, sdkVersion: SDK_VERSION };
170
167
  }
171
168
 
172
169
  function resolveDaemonConnection(runtime: CliCommandRuntime): AgentDaemonConnection {
@@ -460,7 +457,9 @@ async function runKnowledgeCall<TData>(
460
457
  }
461
458
 
462
459
  export async function handleAgentKnowledgeCommand(runtime: CliCommandRuntime): Promise<CliCommandOutput> {
463
- const [sub = 'status', ...rest] = runtime.cli.commandArgs;
460
+ const [sub = 'status', ...rawRest] = runtime.cli.commandArgs;
461
+ const confirmation = stripCommandFlag(rawRest, '--yes');
462
+ const rest = confirmation.rest;
464
463
  const normalized = sub.toLowerCase();
465
464
  const json = runtime.cli.flags.outputFormat === 'json';
466
465
  const disallowedScopeFlag = findDisallowedKnowledgeScopeFlag(rest);
@@ -528,7 +527,19 @@ export async function handleAgentKnowledgeCommand(runtime: CliCommandRuntime): P
528
527
  if (normalized === 'ingest-url') {
529
528
  const values = commandValues(rest);
530
529
  const url = values[0];
531
- if (!url) return { output: 'Usage: goodvibes-agent knowledge ingest-url <url> [--title <title>] [--tags a,b]', exitCode: 2 };
530
+ if (!url) return { output: 'Usage: goodvibes-agent knowledge ingest-url <url> [--title <title>] [--tags a,b] --yes', exitCode: 2 };
531
+ if (!confirmation.present) {
532
+ const failure = {
533
+ ok: false,
534
+ kind: 'confirmation_required',
535
+ error: `Refusing to ingest URL into Agent Knowledge ${url} without --yes.`,
536
+ route: AGENT_KNOWLEDGE_METHODS.ingestUrl.route,
537
+ };
538
+ return {
539
+ output: json ? JSON.stringify(failure, null, 2) : `${failure.error}\nUsage: goodvibes-agent knowledge ingest-url <url> [--title <title>] [--tags a,b] --yes`,
540
+ exitCode: 2,
541
+ };
542
+ }
532
543
  const title = readOptionValue(rest, '--title');
533
544
  const tags = readStringList(rest, '--tags');
534
545
  const result = await runKnowledgeCall(runtime, AGENT_KNOWLEDGE_METHODS.ingestUrl, async (connection) => (
@@ -548,11 +559,26 @@ export async function handleAgentKnowledgeCommand(runtime: CliCommandRuntime): P
548
559
  }
549
560
 
550
561
  return {
551
- output: 'Usage: goodvibes-agent knowledge [status|ask <question>|search <query>|ingest-url <url>]',
562
+ output: 'Usage: goodvibes-agent knowledge [status|ask <question>|search <query>|ingest-url <url> --yes]',
552
563
  exitCode: 2,
553
564
  };
554
565
  }
555
566
 
567
+ export async function handleAgentKnowledgeShortcutCommand(
568
+ runtime: CliCommandRuntime,
569
+ subcommand: 'ask' | 'search',
570
+ ): Promise<CliCommandOutput> {
571
+ return handleAgentKnowledgeCommand({
572
+ ...runtime,
573
+ cli: {
574
+ ...runtime.cli,
575
+ command: 'knowledge',
576
+ rawCommand: 'knowledge',
577
+ commandArgs: [subcommand, ...runtime.cli.commandArgs],
578
+ },
579
+ });
580
+ }
581
+
556
582
  export async function handleCompatCommand(runtime: CliCommandRuntime): Promise<CliCommandOutput> {
557
583
  const connection = resolveDaemonConnection(runtime);
558
584
  const metadata = readPackageMetadata();
package/src/cli/help.ts CHANGED
@@ -41,6 +41,7 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
41
41
  ' auth Inspect and manage local users, sessions, and bootstrap auth',
42
42
  ' compat Inspect Agent SDK pin, daemon version, and Agent knowledge route readiness',
43
43
  ' knowledge Use isolated Agent Knowledge/Wiki routes',
44
+ ' ask|search Shortcuts for isolated Agent Knowledge ask/search',
44
45
  ' delegate Explicitly delegate build/fix/review work to GoodVibes TUI',
45
46
  ' subscription Start/finish/logout provider subscription sessions',
46
47
  ' secrets List, set, link, delete, and test GoodVibes secret refs',
@@ -95,6 +96,8 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
95
96
  ` ${binary} compat`,
96
97
  ` ${binary} knowledge status`,
97
98
  ` ${binary} knowledge ask "What is GoodVibes Agent?"`,
99
+ ` ${binary} ask "What is GoodVibes Agent?"`,
100
+ ` ${binary} search "release checklist"`,
98
101
  ` ${binary} delegate --wrfc "fix the failing tests in ~/work/project"`,
99
102
  ` ${binary} surfaces`,
100
103
  ` ${binary} surfaces check`,
@@ -164,16 +167,26 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
164
167
  'knowledge status',
165
168
  'knowledge ask <question> [--limit <n>] [--mode concise|standard|detailed]',
166
169
  'knowledge search <query> [--limit <n>]',
167
- 'knowledge ingest-url <url> [--title <title>] [--tags a,b]',
170
+ 'knowledge ingest-url <url> [--title <title>] [--tags a,b] --yes',
168
171
  ],
169
172
  summary: 'Call isolated Agent Knowledge/Wiki routes under /api/goodvibes-agent/knowledge. No default wiki or HomeGraph fallback.',
170
173
  examples: [
171
174
  'knowledge status',
172
175
  'knowledge ask "What is GoodVibes Agent?"',
173
176
  'knowledge search "release checklist"',
174
- 'knowledge ingest-url https://example.com/page --title "Reference"',
177
+ 'knowledge ingest-url https://example.com/page --title "Reference" --yes',
175
178
  ],
176
179
  },
180
+ ask: {
181
+ usage: ['ask <question> [--limit <n>] [--mode concise|standard|detailed]'],
182
+ summary: 'Shortcut for isolated Agent Knowledge ask. This never queries default Knowledge/Wiki or HomeGraph.',
183
+ examples: ['ask "What is GoodVibes Agent?"', 'ask "release checklist" --mode concise'],
184
+ },
185
+ search: {
186
+ usage: ['search <query> [--limit <n>]'],
187
+ summary: 'Shortcut for isolated Agent Knowledge search. This never queries default Knowledge/Wiki or HomeGraph.',
188
+ examples: ['search "release checklist"', 'search "operator workspace" --limit 5'],
189
+ },
177
190
  delegate: {
178
191
  usage: ['delegate [--wrfc] <build/fix/review task>'],
179
192
  summary: 'Create one shared-session task request for GoodVibes TUI. WRFC is requested only with --wrfc.',
@@ -329,9 +329,9 @@ export async function buildControlPlaneStatusResult(runtime: CliCommandRuntime):
329
329
  };
330
330
  const issues: string[] = [];
331
331
  if (enabled === true && !reachable) issues.push(`Control plane is enabled but not reachable on ${binding.host}:${binding.port}.`);
332
- if (enabled === true && service.enabled !== true) issues.push('Control plane is enabled but service mode is off.');
333
- if (enabled === true && service.autostart !== true) issues.push('Control plane is enabled but service autostart is off.');
334
- if (enabled === true && service.restartOnFailure !== true) issues.push('Control plane is enabled but service restart-on-failure is off.');
332
+ if (enabled === true && service.enabled !== true) issues.push('Control plane is enabled on the external daemon config, but Agent service ownership is disabled.');
333
+ if (enabled === true && service.autostart !== true) issues.push('Control plane is enabled on the external daemon config, but daemon autostart is off.');
334
+ if (enabled === true && service.restartOnFailure !== true) issues.push('Control plane is enabled on the external daemon config, but restart-on-failure is off.');
335
335
  if (isNetworkFacing(enabled, binding) && !auth.userStorePresent) issues.push('Network-facing control plane has no local auth user store.');
336
336
  if (isNetworkFacing(enabled, binding) && auth.bootstrapCredentialPresent) issues.push('Network-facing control plane still has a bootstrap credential file.');
337
337
  return {
@@ -32,7 +32,7 @@ import { handleServiceCommand } from './service-command.ts';
32
32
  import { handleBundleCommand } from './bundle-command.ts';
33
33
  import { buildListenerTestResult, formatListenerTestResult, handleSurfacesCommand } from './surface-command.ts';
34
34
  import { buildControlPlaneStatusResult, formatControlPlaneStatus, handleSecrets, handleSessions, handleTasks, renderPairing, renderRemote, renderSubscriptions, renderWeb } from './management-commands.ts';
35
- import { handleAgentKnowledgeCommand, handleCompatCommand, handleDelegateCommand } from './agent-knowledge-command.ts';
35
+ import { handleAgentKnowledgeCommand, handleAgentKnowledgeShortcutCommand, handleCompatCommand, handleDelegateCommand } from './agent-knowledge-command.ts';
36
36
  import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
37
37
 
38
38
  export interface CliCommandRuntime {
@@ -703,6 +703,12 @@ export async function handleGoodVibesCliCommand(runtime: CliCommandRuntime): Pro
703
703
  console.log(result.output);
704
704
  return { handled: true, exitCode: result.exitCode };
705
705
  }
706
+ case 'ask':
707
+ case 'search': {
708
+ const result = await handleAgentKnowledgeShortcutCommand(runtime, runtime.cli.command);
709
+ console.log(result.output);
710
+ return { handled: true, exitCode: result.exitCode };
711
+ }
706
712
  case 'delegate': {
707
713
  const result = await handleDelegateCommand(runtime);
708
714
  console.log(result.output);
package/src/cli/parser.ts CHANGED
@@ -31,6 +31,9 @@ const COMMAND_ALIASES: Readonly<Record<string, GoodVibesCliCommand>> = {
31
31
  knowledge: 'knowledge',
32
32
  know: 'knowledge',
33
33
  kb: 'knowledge',
34
+ ask: 'ask',
35
+ search: 'search',
36
+ find: 'search',
34
37
  delegate: 'delegate',
35
38
  build: 'delegate',
36
39
  subscription: 'subscription',
@@ -397,19 +397,19 @@ export async function buildCliServicePosture(
397
397
  const issues: string[] = [];
398
398
 
399
399
  if (serverBackedEnabled && !config.enabled) {
400
- issues.push('Server-backed surfaces are enabled but service mode is off.');
400
+ issues.push('Daemon-owned surfaces are configured, but Agent service ownership is disabled.');
401
401
  }
402
402
  if (config.enabled && !config.autostart) {
403
- issues.push('Service mode is enabled but autostart is off.');
403
+ issues.push('External daemon service config has autostart off.');
404
404
  }
405
405
  if (config.enabled && !config.restartOnFailure) {
406
- issues.push('Service mode is enabled but restart-on-failure is off.');
406
+ issues.push('External daemon service config has restart-on-failure off.');
407
407
  }
408
408
  if (config.enabled && !status.installed) {
409
- issues.push('Service mode is enabled but no platform service definition is installed.');
409
+ issues.push('External daemon service config is enabled, but no platform service definition is installed.');
410
410
  }
411
411
  if (config.enabled && !status.running) {
412
- issues.push('Service mode is enabled but the managed service is not running.');
412
+ issues.push('External daemon service config is enabled, but the managed service is not running.');
413
413
  }
414
414
  if (status.actionError) {
415
415
  issues.push(`Service manager reported an error: ${status.actionError}`);
@@ -454,7 +454,7 @@ function yesNo(value: boolean): string {
454
454
  export function formatCliServicePosture(posture: CliServicePosture, json = false): string {
455
455
  if (json) return JSON.stringify(posture, null, 2);
456
456
  return [
457
- 'GoodVibes service',
457
+ 'GoodVibes external daemon service',
458
458
  ` enabled: ${yesNo(posture.config.enabled)}`,
459
459
  ` autostart: ${yesNo(posture.config.autostart)}`,
460
460
  ` restartOnFailure: ${yesNo(posture.config.restartOnFailure)}`,
package/src/cli/status.ts CHANGED
@@ -122,10 +122,10 @@ export function buildCliDoctorFindings(options: CliStatusOptions): readonly CliD
122
122
  id: 'service-disabled-for-server-surfaces',
123
123
  area: 'service',
124
124
  severity: 'warning',
125
- summary: 'Server-backed surfaces are enabled but service mode is off.',
125
+ summary: 'Daemon-owned surfaces are configured while Agent service ownership is disabled.',
126
126
  cause: 'One or more daemon, control-plane, listener, or web settings are enabled while service.enabled is false.',
127
- impact: 'The configured surfaces may not start automatically or survive restarts.',
128
- action: 'Enable service mode or disable the server-backed surfaces you do not want.',
127
+ impact: 'The external daemon host must own availability for those surfaces; Agent will not start or enable them.',
128
+ action: 'Manage surface/service posture from GoodVibes TUI or the daemon host, then use Agent for read-only diagnostics.',
129
129
  });
130
130
  }
131
131
 
@@ -134,10 +134,10 @@ export function buildCliDoctorFindings(options: CliStatusOptions): readonly CliD
134
134
  id: 'service-autostart-disabled',
135
135
  area: 'service',
136
136
  severity: 'warning',
137
- summary: 'Service mode is enabled but autostart is off.',
137
+ summary: 'External daemon service config has autostart off.',
138
138
  cause: 'service.enabled is true and service.autostart is false.',
139
139
  impact: 'The external GoodVibes daemon may not be available after login or reboot even though service mode is selected.',
140
- action: 'Enable service.autostart if the daemon/listener/web surfaces should stay available.',
140
+ action: 'Configure daemon autostart from GoodVibes TUI or the daemon host; Agent will not mutate this setting.',
141
141
  });
142
142
  }
143
143
 
@@ -146,10 +146,10 @@ export function buildCliDoctorFindings(options: CliStatusOptions): readonly CliD
146
146
  id: 'service-restart-disabled',
147
147
  area: 'service',
148
148
  severity: 'warning',
149
- summary: 'Service restart-on-failure is off.',
149
+ summary: 'External daemon service config has restart-on-failure off.',
150
150
  cause: 'service.enabled is true and service.restartOnFailure is false.',
151
151
  impact: 'A crashed daemon or listener may stay down until manually restarted.',
152
- action: 'Enable service.restartOnFailure for durable daemon/listener operation.',
152
+ action: 'Configure restart-on-failure from GoodVibes TUI or the daemon host; Agent will not mutate this setting.',
153
153
  });
154
154
  }
155
155
 
@@ -163,7 +163,7 @@ export function buildCliDoctorFindings(options: CliStatusOptions): readonly CliD
163
163
  summary: issue,
164
164
  cause: 'The service lifecycle inspection found a mismatch between configured service/surface state and observed host state.',
165
165
  impact: 'Daemon, control-plane, listener, or web availability may not match the configuration.',
166
- action: 'Run goodvibes-agent service check, then manage the daemon from GoodVibes TUI or your daemon host tooling.',
166
+ action: 'Use goodvibes-agent service check for read-only detail, then manage the daemon from GoodVibes TUI or your daemon host tooling.',
167
167
  });
168
168
  }
169
169
  }
@@ -326,7 +326,7 @@ export function renderCliStatus(options: CliStatusOptions): string {
326
326
  ? ` operatorTokens: ${options.auth.operatorTokenPresent ? 'present' : 'missing'} (${options.auth.operatorTokenPath})`
327
327
  : ' operatorTokens: unknown',
328
328
  '',
329
- 'Service:',
329
+ 'External Daemon Service:',
330
330
  ` enabled: ${yesNo(serviceEnabled)}`,
331
331
  ` autostart: ${yesNo(serviceAutostart)}`,
332
332
  ` restartOnFailure: ${yesNo(restartOnFailure)}`,
@@ -217,9 +217,9 @@ export async function buildListenerTestResult(runtime: CliCommandRuntime): Promi
217
217
  }).filter((surface) => surface.enabled === true);
218
218
  const issues: string[] = [];
219
219
  if (enabled !== true) issues.push('HTTP listener is disabled.');
220
- if (enabled === true && service.enabled !== true) issues.push('HTTP listener is enabled but service mode is off.');
221
- if (enabled === true && service.autostart !== true) issues.push('HTTP listener is enabled but service autostart is off.');
222
- if (enabled === true && service.restartOnFailure !== true) issues.push('HTTP listener is enabled but service restart-on-failure is off.');
220
+ if (enabled === true && service.enabled !== true) issues.push('HTTP listener is enabled on the external daemon config, but Agent service ownership is disabled.');
221
+ if (enabled === true && service.autostart !== true) issues.push('HTTP listener is enabled on the external daemon config, but daemon autostart is off.');
222
+ if (enabled === true && service.restartOnFailure !== true) issues.push('HTTP listener is enabled on the external daemon config, but restart-on-failure is off.');
223
223
  if (isNetworkFacing(enabled, binding) && !auth.userStorePresent) issues.push('Network-facing listener has no local auth user store.');
224
224
  if (isNetworkFacing(enabled, binding) && auth.bootstrapCredentialPresent) issues.push('Network-facing listener still has a bootstrap credential file.');
225
225
  for (const surface of surfaces) {
package/src/cli/types.ts CHANGED
@@ -12,6 +12,8 @@ export type GoodVibesCliCommand =
12
12
  | 'auth'
13
13
  | 'compat'
14
14
  | 'knowledge'
15
+ | 'ask'
16
+ | 'search'
15
17
  | 'delegate'
16
18
  | 'subscription'
17
19
  | 'secrets'
@@ -11,6 +11,7 @@ import {
11
11
  } from '../../runtime/cloudflare-control-plane.ts';
12
12
  import type { CommandContext, CommandRegistry } from '../command-registry.ts';
13
13
  import { requireShellPaths } from './runtime-services.ts';
14
+ import { requireYesFlag, stripYesFlag } from './confirmation.ts';
14
15
 
15
16
  interface ParsedCloudflareArgs {
16
17
  readonly positional: readonly string[];
@@ -22,10 +23,12 @@ export function registerCloudflareRuntimeCommands(registry: CommandRegistry): vo
22
23
  name: 'cloudflare',
23
24
  aliases: ['cf'],
24
25
  description: 'Inspect and manage optional Cloudflare batch/control-plane integration through daemon SDK routes',
25
- usage: '[status|setup|requirements|create-token|discover|validate|provision|verify|disable] [flags]',
26
+ usage: '[status|setup|requirements|create-token --yes|discover|validate|provision --yes|verify|disable --yes] [flags]',
26
27
  async handler(args, ctx) {
27
- const subcommand = (args[0] ?? 'status').toLowerCase();
28
- const parsed = parseCloudflareArgs(args.slice(1));
28
+ const confirmation = stripYesFlag(args);
29
+ const commandArgs = [...confirmation.rest];
30
+ const subcommand = (commandArgs[0] ?? 'status').toLowerCase();
31
+ const parsed = parseCloudflareArgs(commandArgs.slice(1));
29
32
  if (subcommand === 'setup' || subcommand === 'onboarding') {
30
33
  ctx.openOnboardingWizard?.({ mode: 'edit', reset: true });
31
34
  ctx.print('Opening onboarding wizard. Select the Cloudflare batch capability to configure Cloudflare.');
@@ -80,9 +83,13 @@ export function registerCloudflareRuntimeCommands(registry: CommandRegistry): vo
80
83
  }
81
84
 
82
85
  if (subcommand === 'create-token') {
86
+ if (!confirmation.yes) {
87
+ requireYesFlag(ctx, 'create and store a Cloudflare operational token', '/cloudflare create-token [flags] --yes');
88
+ return;
89
+ }
83
90
  const bootstrapToken = getFlag(parsed, 'bootstrap-token') || readTokenEnv(parsed, 'bootstrap-env');
84
91
  if (!bootstrapToken) {
85
- ctx.print('Usage: /cloudflare create-token --account <account-id> --bootstrap-token <token> or --bootstrap-env <env-name>');
92
+ ctx.print('Usage: /cloudflare create-token --account <account-id> (--bootstrap-token <token> | --bootstrap-env <env-name>) --yes');
86
93
  return;
87
94
  }
88
95
  const result = await client.createOperationalToken({
@@ -141,6 +148,10 @@ export function registerCloudflareRuntimeCommands(registry: CommandRegistry): vo
141
148
  }
142
149
 
143
150
  if (subcommand === 'provision') {
151
+ if (!confirmation.yes) {
152
+ requireYesFlag(ctx, 'provision Cloudflare resources and persist config', '/cloudflare provision [flags] --yes');
153
+ return;
154
+ }
144
155
  const result = await client.provision({
145
156
  ...cloudflareAuthInput(parsed),
146
157
  components: componentsFromArgs(parsed),
@@ -212,6 +223,10 @@ export function registerCloudflareRuntimeCommands(registry: CommandRegistry): vo
212
223
  }
213
224
 
214
225
  if (subcommand === 'disable') {
226
+ if (!confirmation.yes) {
227
+ requireYesFlag(ctx, 'disable Cloudflare integration and persist config', '/cloudflare disable [flags] --yes');
228
+ return;
229
+ }
215
230
  const result = await client.disable({
216
231
  ...cloudflareAuthInput(parsed),
217
232
  ...optionalString('workerName', getFlag(parsed, 'worker-name')),
@@ -227,7 +242,7 @@ export function registerCloudflareRuntimeCommands(registry: CommandRegistry): vo
227
242
  return;
228
243
  }
229
244
 
230
- ctx.print('Usage: /cloudflare [status|setup|requirements|create-token|discover|validate|provision|verify|disable] [flags]');
245
+ ctx.print('Usage: /cloudflare [status|setup|requirements|create-token --yes|discover|validate|provision --yes|verify|disable --yes] [flags]');
231
246
  } catch (error) {
232
247
  ctx.print(`Cloudflare ${subcommand} failed: ${formatCloudflareError(error)}`);
233
248
  }
@@ -0,0 +1,24 @@
1
+ import type { CommandContext } from '../command-registry.ts';
2
+
3
+ export interface ConfirmationArgs {
4
+ readonly rest: readonly string[];
5
+ readonly yes: boolean;
6
+ }
7
+
8
+ export function stripYesFlag(args: readonly string[]): ConfirmationArgs {
9
+ const rest: string[] = [];
10
+ let yes = false;
11
+ for (const token of args) {
12
+ if (token === '--yes') {
13
+ yes = true;
14
+ continue;
15
+ }
16
+ rest.push(token);
17
+ }
18
+ return { rest, yes };
19
+ }
20
+
21
+ export function requireYesFlag(ctx: CommandContext, action: string, usage: string): boolean {
22
+ ctx.print(`Refusing to ${action} without --yes.\nUsage: ${usage}`);
23
+ return false;
24
+ }
@@ -3,13 +3,16 @@ import { scan, persistProviders } from '@pellux/goodvibes-sdk/platform/discovery
3
3
  import { requireProviderApi, requireShellPaths } from './runtime-services.ts';
4
4
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
5
5
  import { GOODVIBES_AGENT_SURFACE_ROOT } from '../../config/surface.ts';
6
+ import { requireYesFlag, stripYesFlag } from './confirmation.ts';
6
7
 
7
8
  export function registerDiscoveryRuntimeCommands(registry: CommandRegistry): void {
8
9
  registry.register({
9
10
  name: 'scan',
10
11
  aliases: [],
11
12
  description: 'Scan localhost and LAN for local LLM servers',
12
- async handler(_args, ctx) {
13
+ usage: '[--yes]',
14
+ async handler(args, ctx) {
15
+ const { yes } = stripYesFlag(args);
13
16
  ctx.print('Scanning for local LLM servers...');
14
17
  ctx.renderRequest();
15
18
 
@@ -33,18 +36,24 @@ export function registerDiscoveryRuntimeCommands(registry: CommandRegistry): voi
33
36
  ctx.print(lines.join('\n'));
34
37
  }
35
38
 
36
- try {
37
- await requireProviderApi(ctx).registerDiscoveredProviders(result.servers);
38
- } catch (err) {
39
- ctx.print(`[Scan] Warning: failed to register some providers: ${summarizeError(err)}`);
40
- }
41
-
42
39
  if (result.servers.length > 0) {
40
+ if (!yes) {
41
+ requireYesFlag(ctx, 'persist discovered local provider configuration', '/scan --yes');
42
+ ctx.print('[Scan] Discovery results were not saved. Rerun /scan --yes to register and persist providers.');
43
+ ctx.renderRequest();
44
+ return;
45
+ }
46
+ try {
47
+ await requireProviderApi(ctx).registerDiscoveredProviders(result.servers);
48
+ } catch (err) {
49
+ ctx.print(`[Scan] Warning: failed to register some providers: ${summarizeError(err)}`);
50
+ }
43
51
  const shellPaths = requireShellPaths(ctx);
44
52
  persistProviders({
45
53
  homeDirectory: shellPaths.homeDirectory,
46
54
  surfaceRoot: GOODVIBES_AGENT_SURFACE_ROOT,
47
55
  }, result.servers);
56
+ ctx.print('[Scan] Discovered providers registered and persisted.');
48
57
  }
49
58
  ctx.renderRequest();
50
59
  },