@vibesdotdev/runtime-surface-cli 0.0.1

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.
@@ -0,0 +1,66 @@
1
+ /**
2
+ * CLI Bootstrap
3
+ *
4
+ * Composition function for initializing the Vibes CLI application.
5
+ * Handles runtime initialization, plugin loading, and CLISurface setup.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { createVibesCliApp } from '@vibesdotdev/runtime-surface-cli';
10
+ *
11
+ * const app = await createVibesCliApp();
12
+ * await app.cli.run(process.argv);
13
+ * ```
14
+ */
15
+ import { VibesRuntime } from "@vibesdotdev/runtime";
16
+ import type { RuntimeLoader, RuntimePlugin } from "@vibesdotdev/runtime";
17
+ import { Command } from "commander";
18
+ import { CLISurface } from "@vibesdotdev/cli/surface";
19
+ /**
20
+ * Plugin loader: a function returning either a `RuntimePlugin` directly or a
21
+ * module whose `default` export is one. Used by both `defaultPlugins` (the
22
+ * binary's statically-imported set) and `config.plugins` (project overrides).
23
+ */
24
+ export type CliPluginLoader = () => Promise<RuntimePlugin | {
25
+ default: RuntimePlugin;
26
+ }>;
27
+ export interface VibesCliAppOptions {
28
+ /** Runtime loader (default: dynamic-import `@vibesdotdev/runtime-bun`) */
29
+ loader?: RuntimeLoader;
30
+ /** Verbose logging (default: false) */
31
+ verbose?: boolean;
32
+ /** Output format (default: 'table') */
33
+ format?: "json" | "yaml" | "table" | "markdown";
34
+ /** Config file path (default: vibes.config.ts in cwd) */
35
+ configPath?: string;
36
+ /** Plugin specifiers to load by import string (project overrides) */
37
+ plugins?: string[];
38
+ /**
39
+ * Statically-imported plugin set the binary ships with. Used when the
40
+ * project's config does not declare `plugins`. Required for `bun build
41
+ * --compile` since plugin selection must be statically analyzable.
42
+ */
43
+ defaultPlugins?: ReadonlyArray<CliPluginLoader>;
44
+ /** Include descriptors marked `internal: true` (default: false) */
45
+ includeInternal?: boolean;
46
+ /**
47
+ * Treat orphan group/command refs as errors. Default: false (warn-only).
48
+ * Project-level configs can produce partial plugin sets, so orphans are a
49
+ * routine outcome — strict mode is reserved for CI / descriptor audits.
50
+ * Overridable via env var `VIBES_CLI_STRICT=1`.
51
+ */
52
+ strict?: boolean;
53
+ }
54
+ export interface VibesCliApp {
55
+ runtime: VibesRuntime;
56
+ program: Command;
57
+ cli: CLISurface;
58
+ }
59
+ /**
60
+ * Create and initialize the Vibes CLI application.
61
+ *
62
+ * @param options - CLI app options
63
+ * @returns Initialized CLI app with runtime, program, and surface
64
+ */
65
+ export declare function createVibesCliApp(options?: VibesCliAppOptions): Promise<VibesCliApp>;
66
+ //# sourceMappingURL=cli-bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-bootstrap.d.ts","sourceRoot":"","sources":["../src/cli-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAkC,MAAM,sBAAsB,CAAC;AACpF,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,UAAU,EAA0B,MAAM,0BAA0B,CAAC;AAgB9E;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CACzC,aAAa,GAAG;IAAE,OAAO,EAAE,aAAa,CAAA;CAAE,CAC3C,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IAChD,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAChD,mEAAmE;IACnE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,WAAW,CAAC,CA2HtB"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * CLI Bootstrap
3
+ *
4
+ * Composition function for initializing the Vibes CLI application.
5
+ * Handles runtime initialization, plugin loading, and CLISurface setup.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { createVibesCliApp } from '@vibesdotdev/runtime-surface-cli';
10
+ *
11
+ * const app = await createVibesCliApp();
12
+ * await app.cli.run(process.argv);
13
+ * ```
14
+ */
15
+ import { VibesRuntime, getVibesRuntime, getRuntimeEnv } from "@vibesdotdev/runtime";
16
+ import { markVibesRuntimeBootstrapped } from "@vibesdotdev/runtime/bootstrap";
17
+ import { Command } from "commander";
18
+ import path from "node:path";
19
+ import { CLISurface } from "@vibesdotdev/cli/surface";
20
+ import { registerBunEnvironment } from "@vibesdotdev/runtime-environment-bun";
21
+ import { VIBES_VERSION } from "@vibesdotdev/cli/version";
22
+ const BAKED_WORKSPACE_CONFIG_JSON = typeof __VIBES_BAKED_CONFIG__ !== "undefined" ? __VIBES_BAKED_CONFIG__ : "{}";
23
+ /**
24
+ * Create and initialize the Vibes CLI application.
25
+ *
26
+ * @param options - CLI app options
27
+ * @returns Initialized CLI app with runtime, program, and surface
28
+ */
29
+ export async function createVibesCliApp(options = {}) {
30
+ // Honor `--profile <name>` / `--profile=<name>` before any runtime/config
31
+ // setup that resolves storage paths from VIBES_PROFILE. Commander parses the
32
+ // global flag later, but by then `loadConfig`/`registerCorePlugins` have
33
+ // already chosen profile-scoped paths off the default profile.
34
+ applyProfileFromArgv(process.argv);
35
+ const loaderModule = await import("@vibesdotdev/runtime-bun");
36
+ const loader = options.loader ?? loaderModule.createBunLoader();
37
+ const runtime = getVibesRuntime();
38
+ runtime.setScope({ surface: "cli", hardware: "consumer", purpose: "direct", qualifiers: { environmentTier: "local" } });
39
+ registerBunEnvironment(runtime, {});
40
+ runtime.setLoader(loader);
41
+ const config = await loadConfig(options.configPath, loader);
42
+ const effectiveConfig = resolveEffectiveConfig(config, loader, options.verbose);
43
+ if (options.verbose) {
44
+ loader.log("info", `Config loaded: ${Object.keys(config).join(", ") || "(empty)"}`);
45
+ loader.log("info", `Config.plugins: ${config.plugins ? "array" : "undefined"}`);
46
+ }
47
+ await registerCorePlugins(runtime);
48
+ // Surface `config.config.plugins.<name>` from vibes.config.ts as
49
+ // `plugins.<name>` contexts so umbrella plugins (plugins-infra,
50
+ // plugins-comms, ...) read the project's intent instead of falling
51
+ // back to hardware-based defaults. Without this the CLI inherits the
52
+ // "consumer" defaults even when the user explicitly toggled subsystems
53
+ // on (e.g. `infra.cloudflare: true`).
54
+ registerAppConfigContexts(runtime, effectiveConfig);
55
+ // Plugin set: project config wins when present, otherwise the binary's
56
+ // statically-imported defaults. Skip defaults when config provides an
57
+ // explicit (even empty) array so projects can opt out of the full set.
58
+ const configPlugins = Array.isArray(config.plugins) ? config.plugins : null;
59
+ const pluginLoaders = configPlugins ?? options.defaultPlugins ?? [];
60
+ for (const loaderFn of pluginLoaders) {
61
+ try {
62
+ const pluginModule = await loaderFn();
63
+ const pluginObj = pluginModule.default ??
64
+ pluginModule;
65
+ await runtime.registerPlugin(pluginObj);
66
+ if (options.verbose) {
67
+ loader.log("info", `Loaded plugin: ${pluginObj.id}`);
68
+ }
69
+ }
70
+ catch (error) {
71
+ // Plugin-load failures are routinely informational (optional / missing
72
+ // peer plugins). They should only surface in default mode if the user
73
+ // opts in via -v. Always route to stderr (loader.log uses console.warn).
74
+ if (options.verbose) {
75
+ loader.log("warn", `Failed to load plugin`, { error: String(error) });
76
+ }
77
+ }
78
+ }
79
+ if (options.plugins) {
80
+ for (const specifier of options.plugins) {
81
+ try {
82
+ const plugin = await loader.importModule(specifier);
83
+ const pluginObj = plugin.default ??
84
+ plugin;
85
+ await runtime.registerPlugin(pluginObj);
86
+ if (options.verbose) {
87
+ loader.log("info", `Loaded plugin: ${specifier}`);
88
+ }
89
+ }
90
+ catch (error) {
91
+ if (options.verbose) {
92
+ loader.log("warn", `Failed to load plugin ${specifier}`, {
93
+ error: String(error),
94
+ });
95
+ }
96
+ }
97
+ }
98
+ }
99
+ const program = new Command()
100
+ .name("vibes")
101
+ .description("Vibes Developer CLI")
102
+ .version(VIBES_VERSION)
103
+ .exitOverride()
104
+ .option("-v, --verbose", "Enable verbose logging")
105
+ .option("--format <format>", "Output format (json|yaml|table|markdown)", options.format ?? "table")
106
+ .option("--profile <name>", "Active vibes profile (overrides $VIBES_PROFILE for this invocation)");
107
+ const strict = options.strict ?? getRuntimeEnv('VIBES_CLI_STRICT') === "1";
108
+ const surfaceOptions = {
109
+ verbose: options.verbose ?? false,
110
+ format: options.format ?? "table",
111
+ includeInternal: options.includeInternal ?? false,
112
+ enablePatterns: true,
113
+ strictCommandGroups: strict,
114
+ strictGroupParents: strict,
115
+ };
116
+ // Activate plugins so onActivate hooks fire — they register the deferred
117
+ // `runtime/client` loaders (e.g. cloudflare-workers-deploy) that command
118
+ // impls resolve via `getVibesClient()`. Without this, `vibes infra deploy run`
119
+ // can't reach the CF Workers API client.
120
+ await runtime.activatePlugins();
121
+ markVibesRuntimeBootstrapped();
122
+ const cli = new CLISurface(runtime, program, surfaceOptions);
123
+ return { runtime, program, cli };
124
+ }
125
+ async function loadConfig(configPath, loader) {
126
+ if (configPath) {
127
+ try {
128
+ const mod = await loader.importModule(configPath);
129
+ const config = mod.default ??
130
+ mod;
131
+ return config;
132
+ }
133
+ catch (error) {
134
+ loader.log("warn", `Failed to load config from ${configPath}`, {
135
+ error: String(error),
136
+ });
137
+ }
138
+ }
139
+ const cwd = loader.getCwd();
140
+ const defaultPaths = [
141
+ getRuntimeEnv('VIBES_CONFIG_PATH'),
142
+ path.resolve(cwd, "vibes.config.ts"),
143
+ path.resolve(cwd, "vibes.config.js"),
144
+ path.resolve(cwd, "vibes.config.json"),
145
+ ].filter((p) => p !== undefined);
146
+ for (const candidate of defaultPaths) {
147
+ try {
148
+ const mod = await loader.importModule(candidate);
149
+ const config = mod.default ??
150
+ mod;
151
+ return config;
152
+ }
153
+ catch (error) {
154
+ loader.log("debug", `Config not found at ${candidate}`, {
155
+ error: String(error),
156
+ });
157
+ }
158
+ }
159
+ loader.log("debug", "No vibes.config.ts found, using defaultPlugins");
160
+ return {};
161
+ }
162
+ /**
163
+ * Pick the config object to use for plugin-umbrella context registration.
164
+ *
165
+ * Order of precedence:
166
+ * 1. External `vibes.config.ts` that successfully imported with a non-empty
167
+ * `config` field — full user intent, treat as authoritative.
168
+ * 2. The build-time baked workspace config (compiled binaries only).
169
+ * Used when the standalone executable can't resolve workspace specifiers
170
+ * from `vibes.config.ts` at runtime, so external load returns `(empty)`.
171
+ * 3. Empty — fall through to hardware-tier defaults inside umbrella plugins.
172
+ *
173
+ * We deliberately do NOT merge external and baked: if the user shipped a
174
+ * config, their intent is total.
175
+ */
176
+ function resolveEffectiveConfig(external, loader, verbose) {
177
+ const externalHasConfig = external.config !== undefined && external.config !== null;
178
+ if (externalHasConfig)
179
+ return external;
180
+ if (BAKED_WORKSPACE_CONFIG_JSON && BAKED_WORKSPACE_CONFIG_JSON !== "{}") {
181
+ try {
182
+ const baked = JSON.parse(BAKED_WORKSPACE_CONFIG_JSON);
183
+ if (verbose) {
184
+ loader.log("info", `Using baked workspace config (${Object.keys(baked).join(", ") || "(empty)"})`);
185
+ }
186
+ return { ...external, config: baked };
187
+ }
188
+ catch (error) {
189
+ loader.log("warn", `Failed to parse __VIBES_BAKED_CONFIG__; falling back to external/empty`, { error: String(error) });
190
+ }
191
+ }
192
+ return external;
193
+ }
194
+ /**
195
+ * Mirror of `registerAppConfigContexts` from `@vibesdotdev/runtime/bootstrap/app`.
196
+ * Inlined to avoid a circular dependency through `bootstrap/index` (which
197
+ * would re-register core plugins).
198
+ *
199
+ * Walks `config.config.plugins` and registers each subtree as a
200
+ * `plugins.<name>` context. Umbrella plugins read these contexts to
201
+ * decide which sub-plugins to load.
202
+ */
203
+ function registerAppConfigContexts(runtime, config) {
204
+ const top = config.config;
205
+ const pluginConfig = top?.plugins;
206
+ if (!pluginConfig || typeof pluginConfig !== "object")
207
+ return;
208
+ if (!runtime.hasKind("context"))
209
+ return;
210
+ for (const [name, value] of Object.entries(pluginConfig)) {
211
+ if (value === undefined)
212
+ continue;
213
+ const id = `plugins.${name}`;
214
+ runtime.registerDescriptor("context", {
215
+ kind: "context",
216
+ id,
217
+ name: `Plugin config: ${name}`,
218
+ description: `Runtime app configuration for the ${name} plugin umbrella.`,
219
+ });
220
+ runtime.registerLoader("context", id, async () => ({
221
+ impl: {
222
+ provide: () => value,
223
+ },
224
+ }));
225
+ }
226
+ }
227
+ async function registerCorePlugins(runtime) {
228
+ // Only the true zero-dependency foundation + surface-specific CLI plugin.
229
+ // All other core plugins (logging, hooks, runtime-client, config, system,
230
+ // tools, workers, storage, filesystem, paths, workspace, resolver, runtime/docs)
231
+ // are owned by @vibesdotdev/plugins-core which depends on 'context'.
232
+ const contextPlugin = (await import("@vibesdotdev/runtime/context/context.plugin")).default;
233
+ await runtime.registerPlugin(contextPlugin);
234
+ const cliPlugin = (await import("@vibesdotdev/cli/cli.plugin")).default;
235
+ await runtime.registerPlugin(cliPlugin);
236
+ }
237
+ /**
238
+ * Pre-parse `--profile <name>` / `--profile=<name>` and surface it through
239
+ * the `VIBES_PROFILE` env var so downstream profile-aware code (path
240
+ * resolution, config discovery) sees the active profile on this invocation.
241
+ *
242
+ * Commander parses the same flag later when `program.parseAsync` runs, but
243
+ * by then `loadConfig` and `registerCorePlugins` have already chosen
244
+ * profile-scoped paths off whatever was set in the environment.
245
+ *
246
+ * Strict: ignores anything that looks like another flag (`--profile --foo`).
247
+ */
248
+ function applyProfileFromArgv(argv) {
249
+ for (let i = 2; i < argv.length; i++) {
250
+ const token = argv[i];
251
+ if (token === "--")
252
+ break;
253
+ if (token === "--profile") {
254
+ const next = argv[i + 1];
255
+ if (next && !next.startsWith("-")) {
256
+ process.env.VIBES_PROFILE = next;
257
+ }
258
+ return;
259
+ }
260
+ if (token.startsWith("--profile=")) {
261
+ const value = token.slice("--profile=".length);
262
+ if (value)
263
+ process.env.VIBES_PROFILE = value;
264
+ return;
265
+ }
266
+ }
267
+ }
268
+ //# sourceMappingURL=cli-bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-bootstrap.js","sourceRoot":"","sources":["../src/cli-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Runtime Surface: CLI
3
+ *
4
+ * Official blessed entrypoint for bootstrapping a Vibes CLI runtime.
5
+ * Re-exports the CLI application factory (createVibesCliApp) and related
6
+ * types after the surface layer is fully implemented.
7
+ *
8
+ * Consumers (cli-bin, shield-cli, internal CLI commands) should import from here
9
+ * rather than directly from @vibesdotdev/cli/bootstrap or raw runtime bootstrap symbols.
10
+ */
11
+ /**
12
+ * Runtime Surface — CLI
13
+ *
14
+ * The blessed way to bootstrap a full Vibes CLI application.
15
+ * Re-exports createVibesCliApp and related types from the implementation
16
+ * that now lives in this surface package.
17
+ *
18
+ * All production CLI entrypoints (cli-bin, shield-cli, internal tools)
19
+ * should import from here.
20
+ */
21
+ export { createVibesCliApp, type VibesCliAppOptions, type VibesCliApp, type CliPluginLoader } from './cli-bootstrap.ts';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;GASG;AACH,OAAO,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Runtime Surface: CLI
3
+ *
4
+ * Official blessed entrypoint for bootstrapping a Vibes CLI runtime.
5
+ * Re-exports the CLI application factory (createVibesCliApp) and related
6
+ * types after the surface layer is fully implemented.
7
+ *
8
+ * Consumers (cli-bin, shield-cli, internal CLI commands) should import from here
9
+ * rather than directly from @vibesdotdev/cli/bootstrap or raw runtime bootstrap symbols.
10
+ */
11
+ /**
12
+ * Runtime Surface — CLI
13
+ *
14
+ * The blessed way to bootstrap a full Vibes CLI application.
15
+ * Re-exports createVibesCliApp and related types from the implementation
16
+ * that now lives in this surface package.
17
+ *
18
+ * All production CLI entrypoints (cli-bin, shield-cli, internal tools)
19
+ * should import from here.
20
+ */
21
+ export { createVibesCliApp } from "./cli-bootstrap.js";
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;GASG;AACH,OAAO,EAAE,iBAAiB,EAAmE,MAAM,oBAAoB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@vibesdotdev/runtime-surface-cli",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "bun": "./src/index.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc -p tsconfig.json",
17
+ "check": "bun --bun tsc -p tsconfig.json --noEmit"
18
+ },
19
+ "dependencies": {
20
+ "@vibesdotdev/runtime": "0.0.1",
21
+ "@vibesdotdev/runtime-environment-bun": "0.0.0",
22
+ "@vibesdotdev/cli": "0.0.1"
23
+ },
24
+ "license": "MIT",
25
+ "files": [
26
+ "dist",
27
+ "src",
28
+ "bin",
29
+ "README.md",
30
+ "SPEC.md",
31
+ "LICENSE",
32
+ "!src/**/__tests__/**",
33
+ "!src/**/__stubs__/**",
34
+ "!src/**/*.test.ts",
35
+ "!src/**/*.test.tsx",
36
+ "!src/**/*.spec.ts",
37
+ "!src/**/*.spec.tsx",
38
+ "!dist/**/__tests__/**",
39
+ "!dist/**/__stubs__/**",
40
+ "!dist/**/*.test.js",
41
+ "!dist/**/*.test.js.map",
42
+ "!dist/**/*.test.d.ts",
43
+ "!dist/**/*.test.d.ts.map",
44
+ "!dist/**/*.spec.js",
45
+ "!dist/**/*.spec.js.map",
46
+ "!dist/**/*.spec.d.ts",
47
+ "!dist/**/*.spec.d.ts.map"
48
+ ],
49
+ "publishConfig": {
50
+ "registry": "https://registry.npmjs.org",
51
+ "access": "public"
52
+ },
53
+ "vibes": {
54
+ "visibility": "public-framework"
55
+ }
56
+ }
@@ -0,0 +1,380 @@
1
+ /**
2
+ * CLI Bootstrap
3
+ *
4
+ * Composition function for initializing the Vibes CLI application.
5
+ * Handles runtime initialization, plugin loading, and CLISurface setup.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { createVibesCliApp } from '@vibesdotdev/runtime-surface-cli';
10
+ *
11
+ * const app = await createVibesCliApp();
12
+ * await app.cli.run(process.argv);
13
+ * ```
14
+ */
15
+
16
+ import { VibesRuntime, getVibesRuntime, getRuntimeEnv } from "@vibesdotdev/runtime";
17
+ import type { RuntimeLoader, RuntimePlugin } from "@vibesdotdev/runtime";
18
+ import { markVibesRuntimeBootstrapped } from "@vibesdotdev/runtime/bootstrap";
19
+ import { Command } from "commander";
20
+ import path from "node:path";
21
+ import { CLISurface, type CLISurfaceOptions } from "@vibesdotdev/cli/surface";
22
+ import { registerBunEnvironment } from "@vibesdotdev/runtime-environment-bun";
23
+ import { VIBES_VERSION } from "@vibesdotdev/cli/version";
24
+
25
+ /**
26
+ * Workspace `config.config` subtree captured at build time.
27
+ *
28
+ * Replaced literally by Bun's `--define` flag during `apps/cli-bin/scripts/build.ts`.
29
+ * Outside the compiled binary (dev mode, tests) the symbol is undefined and we
30
+ * fall through to the empty default. Stored as a JSON string so the substitution
31
+ * stays a simple literal even though the data is structured.
32
+ */
33
+ declare const __VIBES_BAKED_CONFIG__: string;
34
+ const BAKED_WORKSPACE_CONFIG_JSON: string =
35
+ typeof __VIBES_BAKED_CONFIG__ !== "undefined" ? __VIBES_BAKED_CONFIG__ : "{}";
36
+
37
+ /**
38
+ * Plugin loader: a function returning either a `RuntimePlugin` directly or a
39
+ * module whose `default` export is one. Used by both `defaultPlugins` (the
40
+ * binary's statically-imported set) and `config.plugins` (project overrides).
41
+ */
42
+ export type CliPluginLoader = () => Promise<
43
+ RuntimePlugin | { default: RuntimePlugin }
44
+ >;
45
+
46
+ export interface VibesCliAppOptions {
47
+ /** Runtime loader (default: dynamic-import `@vibesdotdev/runtime-bun`) */
48
+ loader?: RuntimeLoader;
49
+ /** Verbose logging (default: false) */
50
+ verbose?: boolean;
51
+ /** Output format (default: 'table') */
52
+ format?: "json" | "yaml" | "table" | "markdown";
53
+ /** Config file path (default: vibes.config.ts in cwd) */
54
+ configPath?: string;
55
+ /** Plugin specifiers to load by import string (project overrides) */
56
+ plugins?: string[];
57
+ /**
58
+ * Statically-imported plugin set the binary ships with. Used when the
59
+ * project's config does not declare `plugins`. Required for `bun build
60
+ * --compile` since plugin selection must be statically analyzable.
61
+ */
62
+ defaultPlugins?: ReadonlyArray<CliPluginLoader>;
63
+ /** Include descriptors marked `internal: true` (default: false) */
64
+ includeInternal?: boolean;
65
+ /**
66
+ * Treat orphan group/command refs as errors. Default: false (warn-only).
67
+ * Project-level configs can produce partial plugin sets, so orphans are a
68
+ * routine outcome — strict mode is reserved for CI / descriptor audits.
69
+ * Overridable via env var `VIBES_CLI_STRICT=1`.
70
+ */
71
+ strict?: boolean;
72
+ }
73
+
74
+ export interface VibesCliApp {
75
+ runtime: VibesRuntime;
76
+ program: Command;
77
+ cli: CLISurface;
78
+ }
79
+
80
+ /**
81
+ * Create and initialize the Vibes CLI application.
82
+ *
83
+ * @param options - CLI app options
84
+ * @returns Initialized CLI app with runtime, program, and surface
85
+ */
86
+ export async function createVibesCliApp(
87
+ options: VibesCliAppOptions = {},
88
+ ): Promise<VibesCliApp> {
89
+ // Honor `--profile <name>` / `--profile=<name>` before any runtime/config
90
+ // setup that resolves storage paths from VIBES_PROFILE. Commander parses the
91
+ // global flag later, but by then `loadConfig`/`registerCorePlugins` have
92
+ // already chosen profile-scoped paths off the default profile.
93
+ applyProfileFromArgv(process.argv);
94
+
95
+ const loaderModule = await import("@vibesdotdev/runtime-bun");
96
+ const loader = options.loader ?? loaderModule.createBunLoader();
97
+
98
+ const runtime = getVibesRuntime();
99
+ runtime.setScope({ surface: "cli", hardware: "consumer", purpose: "direct", qualifiers: { environmentTier: "local" } });
100
+ registerBunEnvironment(runtime, {});
101
+ runtime.setLoader(loader);
102
+
103
+ const config = await loadConfig(options.configPath, loader);
104
+ const effectiveConfig = resolveEffectiveConfig(config, loader, options.verbose);
105
+ if (options.verbose) {
106
+ loader.log(
107
+ "info",
108
+ `Config loaded: ${Object.keys(config).join(", ") || "(empty)"}`,
109
+ );
110
+ loader.log(
111
+ "info",
112
+ `Config.plugins: ${config.plugins ? "array" : "undefined"}`,
113
+ );
114
+ }
115
+
116
+ await registerCorePlugins(runtime);
117
+
118
+ // Surface `config.config.plugins.<name>` from vibes.config.ts as
119
+ // `plugins.<name>` contexts so umbrella plugins (plugins-infra,
120
+ // plugins-comms, ...) read the project's intent instead of falling
121
+ // back to hardware-based defaults. Without this the CLI inherits the
122
+ // "consumer" defaults even when the user explicitly toggled subsystems
123
+ // on (e.g. `infra.cloudflare: true`).
124
+ registerAppConfigContexts(runtime, effectiveConfig);
125
+
126
+ // Plugin set: project config wins when present, otherwise the binary's
127
+ // statically-imported defaults. Skip defaults when config provides an
128
+ // explicit (even empty) array so projects can opt out of the full set.
129
+ const configPlugins = Array.isArray(config.plugins) ? config.plugins : null;
130
+ const pluginLoaders: ReadonlyArray<CliPluginLoader> =
131
+ configPlugins ?? options.defaultPlugins ?? [];
132
+
133
+ for (const loaderFn of pluginLoaders) {
134
+ try {
135
+ const pluginModule = await loaderFn();
136
+ const pluginObj =
137
+ (pluginModule as { default?: RuntimePlugin }).default ??
138
+ (pluginModule as RuntimePlugin);
139
+ await runtime.registerPlugin(pluginObj);
140
+ if (options.verbose) {
141
+ loader.log("info", `Loaded plugin: ${pluginObj.id}`);
142
+ }
143
+ } catch (error) {
144
+ // Plugin-load failures are routinely informational (optional / missing
145
+ // peer plugins). They should only surface in default mode if the user
146
+ // opts in via -v. Always route to stderr (loader.log uses console.warn).
147
+ if (options.verbose) {
148
+ loader.log("warn", `Failed to load plugin`, { error: String(error) });
149
+ }
150
+ }
151
+ }
152
+
153
+ if (options.plugins) {
154
+ for (const specifier of options.plugins) {
155
+ try {
156
+ const plugin = await loader.importModule(specifier);
157
+ const pluginObj =
158
+ (plugin as { default?: RuntimePlugin }).default ??
159
+ (plugin as RuntimePlugin);
160
+ await runtime.registerPlugin(pluginObj);
161
+ if (options.verbose) {
162
+ loader.log("info", `Loaded plugin: ${specifier}`);
163
+ }
164
+ } catch (error) {
165
+ if (options.verbose) {
166
+ loader.log("warn", `Failed to load plugin ${specifier}`, {
167
+ error: String(error),
168
+ });
169
+ }
170
+ }
171
+ }
172
+ }
173
+
174
+ const program = new Command()
175
+ .name("vibes")
176
+ .description("Vibes Developer CLI")
177
+ .version(VIBES_VERSION)
178
+ .exitOverride()
179
+ .option("-v, --verbose", "Enable verbose logging")
180
+ .option(
181
+ "--format <format>",
182
+ "Output format (json|yaml|table|markdown)",
183
+ options.format ?? "table",
184
+ )
185
+ .option(
186
+ "--profile <name>",
187
+ "Active vibes profile (overrides $VIBES_PROFILE for this invocation)",
188
+ );
189
+
190
+ const strict = options.strict ?? getRuntimeEnv('VIBES_CLI_STRICT') === "1";
191
+ const surfaceOptions: CLISurfaceOptions = {
192
+ verbose: options.verbose ?? false,
193
+ format: options.format ?? "table",
194
+ includeInternal: options.includeInternal ?? false,
195
+ enablePatterns: true,
196
+ strictCommandGroups: strict,
197
+ strictGroupParents: strict,
198
+ };
199
+
200
+ // Activate plugins so onActivate hooks fire — they register the deferred
201
+ // `runtime/client` loaders (e.g. cloudflare-workers-deploy) that command
202
+ // impls resolve via `getVibesClient()`. Without this, `vibes infra deploy run`
203
+ // can't reach the CF Workers API client.
204
+ await runtime.activatePlugins();
205
+
206
+ markVibesRuntimeBootstrapped();
207
+
208
+ const cli = new CLISurface(runtime, program, surfaceOptions);
209
+
210
+ return { runtime, program, cli };
211
+ }
212
+
213
+ async function loadConfig(
214
+ configPath: string | undefined,
215
+ loader: RuntimeLoader,
216
+ ): Promise<Record<string, unknown>> {
217
+ if (configPath) {
218
+ try {
219
+ const mod = await loader.importModule(configPath);
220
+ const config =
221
+ (mod as { default?: Record<string, unknown> }).default ??
222
+ (mod as Record<string, unknown>);
223
+ return config;
224
+ } catch (error) {
225
+ loader.log("warn", `Failed to load config from ${configPath}`, {
226
+ error: String(error),
227
+ });
228
+ }
229
+ }
230
+
231
+ const cwd = loader.getCwd();
232
+ const defaultPaths = [
233
+ getRuntimeEnv('VIBES_CONFIG_PATH'),
234
+ path.resolve(cwd, "vibes.config.ts"),
235
+ path.resolve(cwd, "vibes.config.js"),
236
+ path.resolve(cwd, "vibes.config.json"),
237
+ ].filter((p): p is string => p !== undefined);
238
+
239
+ for (const candidate of defaultPaths) {
240
+ try {
241
+ const mod = await loader.importModule(candidate);
242
+ const config =
243
+ (mod as { default?: Record<string, unknown> }).default ??
244
+ (mod as Record<string, unknown>);
245
+ return config;
246
+ } catch (error) {
247
+ loader.log("debug", `Config not found at ${candidate}`, {
248
+ error: String(error),
249
+ });
250
+ }
251
+ }
252
+
253
+ loader.log("debug", "No vibes.config.ts found, using defaultPlugins");
254
+ return {};
255
+ }
256
+
257
+ /**
258
+ * Pick the config object to use for plugin-umbrella context registration.
259
+ *
260
+ * Order of precedence:
261
+ * 1. External `vibes.config.ts` that successfully imported with a non-empty
262
+ * `config` field — full user intent, treat as authoritative.
263
+ * 2. The build-time baked workspace config (compiled binaries only).
264
+ * Used when the standalone executable can't resolve workspace specifiers
265
+ * from `vibes.config.ts` at runtime, so external load returns `(empty)`.
266
+ * 3. Empty — fall through to hardware-tier defaults inside umbrella plugins.
267
+ *
268
+ * We deliberately do NOT merge external and baked: if the user shipped a
269
+ * config, their intent is total.
270
+ */
271
+ function resolveEffectiveConfig(
272
+ external: Record<string, unknown>,
273
+ loader: RuntimeLoader,
274
+ verbose: boolean | undefined,
275
+ ): Record<string, unknown> {
276
+ const externalHasConfig =
277
+ external.config !== undefined && external.config !== null;
278
+ if (externalHasConfig) return external;
279
+
280
+ if (BAKED_WORKSPACE_CONFIG_JSON && BAKED_WORKSPACE_CONFIG_JSON !== "{}") {
281
+ try {
282
+ const baked = JSON.parse(BAKED_WORKSPACE_CONFIG_JSON);
283
+ if (verbose) {
284
+ loader.log(
285
+ "info",
286
+ `Using baked workspace config (${Object.keys(baked).join(", ") || "(empty)"})`,
287
+ );
288
+ }
289
+ return { ...external, config: baked };
290
+ } catch (error) {
291
+ loader.log(
292
+ "warn",
293
+ `Failed to parse __VIBES_BAKED_CONFIG__; falling back to external/empty`,
294
+ { error: String(error) },
295
+ );
296
+ }
297
+ }
298
+
299
+ return external;
300
+ }
301
+
302
+ /**
303
+ * Mirror of `registerAppConfigContexts` from `@vibesdotdev/runtime/bootstrap/app`.
304
+ * Inlined to avoid a circular dependency through `bootstrap/index` (which
305
+ * would re-register core plugins).
306
+ *
307
+ * Walks `config.config.plugins` and registers each subtree as a
308
+ * `plugins.<name>` context. Umbrella plugins read these contexts to
309
+ * decide which sub-plugins to load.
310
+ */
311
+ function registerAppConfigContexts(
312
+ runtime: VibesRuntime,
313
+ config: Record<string, unknown>,
314
+ ): void {
315
+ const top = config.config as { plugins?: Record<string, unknown> } | undefined;
316
+ const pluginConfig = top?.plugins;
317
+ if (!pluginConfig || typeof pluginConfig !== "object") return;
318
+ if (!runtime.hasKind("context")) return;
319
+
320
+ for (const [name, value] of Object.entries(pluginConfig)) {
321
+ if (value === undefined) continue;
322
+
323
+ const id = `plugins.${name}`;
324
+ runtime.registerDescriptor("context", {
325
+ kind: "context",
326
+ id,
327
+ name: `Plugin config: ${name}`,
328
+ description: `Runtime app configuration for the ${name} plugin umbrella.`,
329
+ });
330
+ runtime.registerLoader("context", id, async () => ({
331
+ impl: {
332
+ provide: () => value,
333
+ },
334
+ }));
335
+ }
336
+ }
337
+
338
+ async function registerCorePlugins(runtime: VibesRuntime): Promise<void> {
339
+ // Only the true zero-dependency foundation + surface-specific CLI plugin.
340
+ // All other core plugins (logging, hooks, runtime-client, config, system,
341
+ // tools, workers, storage, filesystem, paths, workspace, resolver, runtime/docs)
342
+ // are owned by @vibesdotdev/plugins-core which depends on 'context'.
343
+ const contextPlugin = (
344
+ await import("@vibesdotdev/runtime/context/context.plugin")
345
+ ).default;
346
+ await runtime.registerPlugin(contextPlugin);
347
+
348
+ const cliPlugin = (await import("@vibesdotdev/cli/cli.plugin")).default;
349
+ await runtime.registerPlugin(cliPlugin);
350
+ }
351
+
352
+ /**
353
+ * Pre-parse `--profile <name>` / `--profile=<name>` and surface it through
354
+ * the `VIBES_PROFILE` env var so downstream profile-aware code (path
355
+ * resolution, config discovery) sees the active profile on this invocation.
356
+ *
357
+ * Commander parses the same flag later when `program.parseAsync` runs, but
358
+ * by then `loadConfig` and `registerCorePlugins` have already chosen
359
+ * profile-scoped paths off whatever was set in the environment.
360
+ *
361
+ * Strict: ignores anything that looks like another flag (`--profile --foo`).
362
+ */
363
+ function applyProfileFromArgv(argv: ReadonlyArray<string>): void {
364
+ for (let i = 2; i < argv.length; i++) {
365
+ const token = argv[i];
366
+ if (token === "--") break;
367
+ if (token === "--profile") {
368
+ const next = argv[i + 1];
369
+ if (next && !next.startsWith("-")) {
370
+ process.env.VIBES_PROFILE = next;
371
+ }
372
+ return;
373
+ }
374
+ if (token.startsWith("--profile=")) {
375
+ const value = token.slice("--profile=".length);
376
+ if (value) process.env.VIBES_PROFILE = value;
377
+ return;
378
+ }
379
+ }
380
+ }
package/src/index.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Runtime Surface: CLI
3
+ *
4
+ * Official blessed entrypoint for bootstrapping a Vibes CLI runtime.
5
+ * Re-exports the CLI application factory (createVibesCliApp) and related
6
+ * types after the surface layer is fully implemented.
7
+ *
8
+ * Consumers (cli-bin, shield-cli, internal CLI commands) should import from here
9
+ * rather than directly from @vibesdotdev/cli/bootstrap or raw runtime bootstrap symbols.
10
+ */
11
+
12
+ /**
13
+ * Runtime Surface — CLI
14
+ *
15
+ * The blessed way to bootstrap a full Vibes CLI application.
16
+ * Re-exports createVibesCliApp and related types from the implementation
17
+ * that now lives in this surface package.
18
+ *
19
+ * All production CLI entrypoints (cli-bin, shield-cli, internal tools)
20
+ * should import from here.
21
+ */
22
+ export { createVibesCliApp, type VibesCliAppOptions, type VibesCliApp, type CliPluginLoader } from './cli-bootstrap.ts';