@vibecodr/cli 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,17 +1,17 @@
1
- # Changelog
2
-
3
- ## Unreleased
4
-
5
- - rename the npm package to `@vibecodr/cli` while keeping `vibecodr` as the primary executable and `vibecodr-mcp` as a compatibility alias
6
-
7
- ## 0.1.8
8
-
9
- - report the actual package version in MCP client metadata instead of a stale hardcoded value
10
- - publish the CLI after redeploying the hosted Vibecodr MCP gateway
11
-
12
- ## 0.1.7
13
-
14
- - add the `pulse-setup` command for live Pulse setup guidance
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ - rename the npm package to `@vibecodr/cli` while keeping `vibecodr` as the primary executable and `vibecodr-mcp` as a compatibility alias
6
+
7
+ ## 0.1.8
8
+
9
+ - report the actual package version in MCP client metadata instead of a stale hardcoded value
10
+ - publish the CLI after redeploying the hosted Vibecodr MCP gateway
11
+
12
+ ## 0.1.7
13
+
14
+ - add the `pulse-setup` command for live Pulse setup guidance
15
15
  - align CLI Pulse setup docs with the gateway runtime contract for policy-bound secrets, Stripe-first webhook helper guidance, generic HMAC presets, and provider-scoped connections
16
16
  - refresh release-lock coverage for current in-range MCP SDK, keyring, and Node type packages before publishing
17
17
 
package/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
 
4
4
 
5
5
 
6
- # Vibecodr CLI
6
+ # Vibecodr CLI
7
7
 
8
- Direct terminal client for the hosted Vibecodr MCP server.
8
+ Direct terminal client for the hosted Vibecodr MCP server.
9
9
 
10
10
  This repository is intentionally separate from the PolyForm-licensed server implementation. The CLI is a client and installer surface, not a second server. It talks to the same hosted Vibecodr MCP gateway used by Codex, Cursor, VS Code, Windsurf, ChatGPT, and other MCP-capable clients.
11
11
 
@@ -30,21 +30,21 @@ Currently implemented command surface:
30
30
  - `install`
31
31
  - `uninstall`
32
32
 
33
- Primary executable:
34
-
35
- - `vibecodr`
36
-
37
- Compatibility alias:
38
-
39
- - `vibecodr-mcp`
40
-
41
- Published package:
42
-
43
- - `@vibecodr/cli`
44
-
45
- Legacy package compatibility:
46
-
47
- - `@vibecodr/mcp`
33
+ Primary executable:
34
+
35
+ - `vibecodr`
36
+
37
+ Compatibility alias:
38
+
39
+ - `vibecodr-mcp`
40
+
41
+ Published package:
42
+
43
+ - `@vibecodr/cli`
44
+
45
+ Legacy package compatibility:
46
+
47
+ - `@vibecodr/mcp`
48
48
 
49
49
  The runtime path talks directly to `https://openai.vibecodr.space/mcp`. Editor installers are not part of the runtime path.
50
50
 
@@ -23,6 +23,28 @@ function computeExpiresAt(expiresIn) {
23
23
  return undefined;
24
24
  return new Date(Date.now() + expiresIn * 1000).toISOString();
25
25
  }
26
+ function normalizeServerUrlForSessionMatch(value) {
27
+ if (!value)
28
+ return undefined;
29
+ try {
30
+ const url = new URL(value);
31
+ url.hash = "";
32
+ url.search = "";
33
+ url.pathname = url.pathname.replace(/\/+$/, "") || "/";
34
+ return url.toString();
35
+ }
36
+ catch {
37
+ return value.replace(/\/+$/, "");
38
+ }
39
+ }
40
+ function sessionMatchesServer(session, serverUrl) {
41
+ if (!serverUrl)
42
+ return true;
43
+ const target = normalizeServerUrlForSessionMatch(serverUrl);
44
+ const sessionServer = normalizeServerUrlForSessionMatch(session.serverUrl);
45
+ const sessionResource = normalizeServerUrlForSessionMatch(session.resourceUrl);
46
+ return Boolean(target && (target === sessionServer || target === sessionResource));
47
+ }
26
48
  async function startLoopbackListener(timeoutSec) {
27
49
  const callbackPath = "/oauth/callback/vibecodr";
28
50
  const server = createServer();
@@ -108,11 +130,17 @@ export class TokenManager {
108
130
  return {
109
131
  profileName: name,
110
132
  profile,
111
- serverUrl: globalOptions.serverUrl || profile.serverUrl
133
+ serverUrl: profile.serverUrl
112
134
  };
113
135
  }
114
- async getSession(profileName) {
115
- return await this.secretStore.get(profileName);
136
+ async getSession(profileName, serverUrl) {
137
+ const session = await this.secretStore.get(profileName);
138
+ if (!session)
139
+ return undefined;
140
+ // SECURITY: Never replay a stored bearer token to a different MCP origin.
141
+ // Profiles may be repointed during development; the existing token remains
142
+ // valid only for the server/resource that issued it.
143
+ return sessionMatchesServer(session, serverUrl) ? session : undefined;
116
144
  }
117
145
  sessionState(session) {
118
146
  if (!session)
@@ -16,6 +16,7 @@ import { runConfigCommand } from "../commands/config.js";
16
16
  import { runInstallCommand } from "../commands/install.js";
17
17
  import { runUninstallCommand } from "../commands/uninstall.js";
18
18
  import { runPulseSetupCommand } from "../commands/pulse-setup.js";
19
+ import { runPulsePublishCommand } from "../commands/pulse-publish.js";
19
20
  function helpText() {
20
21
  return [
21
22
  "vibecodr <command> [options]",
@@ -32,10 +33,12 @@ function helpText() {
32
33
  " uninstall <client>",
33
34
  " config",
34
35
  " pulse-setup [--descriptor-setup-json <json> | --descriptor-setup-file <path>]",
36
+ " pulse-publish --name <name> (--code <source> | --code-file <path>) --confirm",
37
+ " Publishes a standalone Pulse with private source/metadata visibility by default.",
38
+ " The runtime URL is still public HTTP unless the Pulse code rejects callers.",
35
39
  "",
36
40
  "Global flags:",
37
41
  " --profile <name>",
38
- " --server-url <url>",
39
42
  " --json",
40
43
  " --verbose",
41
44
  " --non-interactive"
@@ -91,6 +94,9 @@ async function main() {
91
94
  case "pulse-setup":
92
95
  await runPulseSetupCommand(commandArgs, context);
93
96
  return;
97
+ case "pulse-publish":
98
+ await runPulsePublishCommand(commandArgs, context);
99
+ return;
94
100
  default:
95
101
  throw new CliError("usage.command", `Unknown command: ${command}`, EXIT_CODES.usage);
96
102
  }
package/dist/cli/parse.js CHANGED
@@ -55,12 +55,9 @@ export function parseGlobalOptions(argv) {
55
55
  continue;
56
56
  }
57
57
  if (token === "--server-url") {
58
- const value = argv[index + 1];
59
- if (!value)
60
- throw new CliError("usage.missing_server_url", "Missing value for --server-url.", EXIT_CODES.usage);
61
- globalOptions.serverUrl = value;
62
- index += 1;
63
- continue;
58
+ throw new CliError("usage.unknown_global_flag", "--server-url is no longer accepted as a global runtime override.", EXIT_CODES.usage, {
59
+ nextStep: "Create a separate profile with `vibecodr config profile create <name> --server-url <url>` and login to that profile. Stored tokens are bound to the server they were issued for."
60
+ });
64
61
  }
65
62
  if (token === "--json") {
66
63
  globalOptions.json = true;
@@ -32,7 +32,7 @@ async function readStdin() {
32
32
  }
33
33
  export async function callToolWithRetry(context, toolName, input, allowLogin) {
34
34
  const { profileName, serverUrl } = await context.tokenManager.resolveProfile(context.globalOptions);
35
- const existingSession = await context.tokenManager.getSession(profileName);
35
+ const existingSession = await context.tokenManager.getSession(profileName, serverUrl);
36
36
  try {
37
37
  return {
38
38
  result: await context.runtimeClient.callTool(serverUrl, existingSession?.accessToken, toolName, input),
@@ -54,7 +54,7 @@ export async function callToolWithRetry(context, toolName, input, allowLogin) {
54
54
  await context.tokenManager.login(context.globalOptions, {
55
55
  scope
56
56
  });
57
- const nextSession = await context.tokenManager.getSession(profileName);
57
+ const nextSession = await context.tokenManager.getSession(profileName, serverUrl);
58
58
  return {
59
59
  result: await context.runtimeClient.callTool(serverUrl, nextSession?.accessToken, toolName, input),
60
60
  ...(nextSession ? { session: nextSession } : {})
@@ -65,7 +65,7 @@ export async function callToolWithRetry(context, toolName, input, allowLogin) {
65
65
  }
66
66
  async function listToolsWithRetry(context, allowLogin) {
67
67
  const { profileName, serverUrl } = await context.tokenManager.resolveProfile(context.globalOptions);
68
- const existingSession = await context.tokenManager.getSession(profileName);
68
+ const existingSession = await context.tokenManager.getSession(profileName, serverUrl);
69
69
  try {
70
70
  return await context.runtimeClient.listTools(serverUrl, existingSession?.accessToken);
71
71
  }
@@ -80,7 +80,7 @@ async function listToolsWithRetry(context, allowLogin) {
80
80
  await context.tokenManager.login(context.globalOptions, {
81
81
  scope: challengedScope(error)
82
82
  });
83
- const nextSession = await context.tokenManager.getSession(profileName);
83
+ const nextSession = await context.tokenManager.getSession(profileName, serverUrl);
84
84
  return await context.runtimeClient.listTools(serverUrl, nextSession?.accessToken);
85
85
  }
86
86
  throw error;
@@ -0,0 +1,90 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { CliError, EXIT_CODES } from "../cli/errors.js";
3
+ import { parseFlags } from "../cli/parse.js";
4
+ import { renderToolResult } from "../core/renderers.js";
5
+ import { callToolWithRetry } from "./call.js";
6
+ const PUBLISH_STANDALONE_PULSE_TOOL_NAME = "publish_standalone_pulse";
7
+ const PULSE_VISIBILITIES = new Set(["public", "unlisted", "private"]);
8
+ const DEFAULT_PULSE_VISIBILITY = "private";
9
+ function parseJsonObject(raw, source) {
10
+ let parsed;
11
+ try {
12
+ parsed = JSON.parse(raw);
13
+ }
14
+ catch (error) {
15
+ throw new CliError("usage.invalid_json", `${source} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`, EXIT_CODES.usage);
16
+ }
17
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
18
+ throw new CliError("usage.invalid_json", `${source} must be a JSON object.`, EXIT_CODES.usage);
19
+ }
20
+ return parsed;
21
+ }
22
+ async function parsePulsePublishInput(args) {
23
+ const { flags } = parseFlags(args, {
24
+ valueFlags: ["name", "code", "code-file", "descriptor-json", "descriptor-file", "slug", "visibility"],
25
+ booleanFlags: ["confirm"]
26
+ });
27
+ const name = typeof flags["name"] === "string" ? flags["name"].trim() : "";
28
+ if (!name) {
29
+ throw new CliError("usage.pulse_name_required", "Usage: pulse-publish --name <name> (--code <source> | --code-file <path>) --confirm", EXIT_CODES.usage);
30
+ }
31
+ const hasCode = typeof flags["code"] === "string";
32
+ const hasCodeFile = typeof flags["code-file"] === "string";
33
+ if (hasCode === hasCodeFile) {
34
+ throw new CliError("usage.pulse_code_required", "Use exactly one of --code or --code-file.", EXIT_CODES.usage);
35
+ }
36
+ const code = hasCode ? String(flags["code"]) : await readFile(String(flags["code-file"]), "utf8");
37
+ if (!code.trim()) {
38
+ throw new CliError("usage.pulse_code_empty", "Pulse source code cannot be empty.", EXIT_CODES.usage);
39
+ }
40
+ const hasDescriptorJson = typeof flags["descriptor-json"] === "string";
41
+ const hasDescriptorFile = typeof flags["descriptor-file"] === "string";
42
+ if (hasDescriptorJson && hasDescriptorFile) {
43
+ throw new CliError("usage.duplicate_descriptor", "Use either --descriptor-json or --descriptor-file, not both.", EXIT_CODES.usage);
44
+ }
45
+ const input = {
46
+ name,
47
+ code,
48
+ visibility: DEFAULT_PULSE_VISIBILITY,
49
+ confirmed: flags["confirm"] === true
50
+ };
51
+ if (hasDescriptorJson) {
52
+ input["descriptor"] = parseJsonObject(String(flags["descriptor-json"]), "--descriptor-json");
53
+ }
54
+ else if (hasDescriptorFile) {
55
+ input["descriptor"] = parseJsonObject(await readFile(String(flags["descriptor-file"]), "utf8"), "--descriptor-file");
56
+ }
57
+ if (typeof flags["slug"] === "string" && flags["slug"].trim()) {
58
+ input["slug"] = flags["slug"].trim();
59
+ }
60
+ if (typeof flags["visibility"] === "string") {
61
+ if (!PULSE_VISIBILITIES.has(flags["visibility"])) {
62
+ throw new CliError("usage.invalid_visibility", "Pulse visibility must be public, unlisted, or private.", EXIT_CODES.usage);
63
+ }
64
+ input["visibility"] = flags["visibility"];
65
+ }
66
+ if (input["confirmed"] !== true) {
67
+ throw new CliError("usage.confirmation_required", "Publishing a standalone Pulse requires explicit confirmation. Re-run with --confirm after the user confirms.", EXIT_CODES.usage, {
68
+ nextStep: "Ask one clear confirmation question, then pass --confirm only after the user says yes."
69
+ });
70
+ }
71
+ return input;
72
+ }
73
+ function redactPulsePublishArguments(input) {
74
+ const { code: _code, descriptor: _descriptor, ...safe } = input;
75
+ return {
76
+ ...safe,
77
+ ...(input["descriptor"] ? { descriptorProvided: true } : {}),
78
+ sourceProvided: true
79
+ };
80
+ }
81
+ export async function runPulsePublishCommand(args, context) {
82
+ const input = await parsePulsePublishInput(args);
83
+ const { result } = await callToolWithRetry(context, PUBLISH_STANDALONE_PULSE_TOOL_NAME, input, true);
84
+ context.output.success({
85
+ schemaVersion: 1,
86
+ tool: PUBLISH_STANDALONE_PULSE_TOOL_NAME,
87
+ arguments: redactPulsePublishArguments(input),
88
+ result
89
+ }, [renderToolResult(result)]);
90
+ }
@@ -27,7 +27,7 @@ export async function runStatusCommand(args, context) {
27
27
  booleanFlags: ["probe", "show-installs"]
28
28
  });
29
29
  const { profileName, profile, serverUrl } = await context.tokenManager.resolveProfile(context.globalOptions);
30
- const session = await context.tokenManager.getSession(profileName);
30
+ const session = await context.tokenManager.getSession(profileName, serverUrl);
31
31
  const sessionState = context.tokenManager.sessionState(session);
32
32
  const installs = flags["show-installs"]
33
33
  ? await Promise.all((await new InstallManifestStore().find(() => true)).map((entry) => inspectInstall(entry)))
@@ -9,7 +9,7 @@ function challengedScope(error) {
9
9
  }
10
10
  async function loadToolsWithRetry(context, allowLogin) {
11
11
  const { profileName, serverUrl } = await context.tokenManager.resolveProfile(context.globalOptions);
12
- const existingSession = await context.tokenManager.getSession(profileName);
12
+ const existingSession = await context.tokenManager.getSession(profileName, serverUrl);
13
13
  try {
14
14
  return {
15
15
  tools: await context.runtimeClient.listTools(serverUrl, existingSession?.accessToken),
@@ -30,7 +30,7 @@ async function loadToolsWithRetry(context, allowLogin) {
30
30
  await context.tokenManager.login(context.globalOptions, {
31
31
  scope: challengedScope(error)
32
32
  });
33
- const nextSession = await context.tokenManager.getSession(profileName);
33
+ const nextSession = await context.tokenManager.getSession(profileName, serverUrl);
34
34
  return {
35
35
  tools: await context.runtimeClient.listTools(serverUrl, nextSession?.accessToken),
36
36
  ...(nextSession ? { session: nextSession } : {})
@@ -1,35 +1,35 @@
1
- # Architecture
2
-
3
- The Vibecodr CLI is a client of the hosted Vibecodr MCP gateway.
4
-
5
- ## Boundary
6
-
7
- - hosted MCP gateway/server repo: `Vibecodr-MCP`
8
- - CLI client repo: `Vibecodr-MCP-CLI`
9
- - CLI package: `@vibecodr/cli`
10
- - primary executable: `vibecodr`
11
- - compatibility executable: `vibecodr-mcp`
12
- - legacy package compatibility: `@vibecodr/mcp`
13
- - default MCP URL: `https://openai.vibecodr.space/mcp`
14
-
15
- This repo does not run the hosted server. It installs client config, performs CLI-owned OAuth, discovers the live tool catalog, and calls tools over Streamable HTTP MCP.
16
-
17
- ## Auth Ownership
18
-
19
- `vibecodr login` stores OAuth tokens for the CLI profile only.
20
-
21
- Codex, Cursor, VS Code, Windsurf, ChatGPT, and other MCP clients own separate OAuth sessions. Installing MCP config into those clients points them at the same server, but it does not copy CLI tokens into them.
22
-
23
- ## Why The Repos Are Separate
24
-
25
- The CLI is permissively licensed and safe to distribute as a public client package. The hosted gateway implementation is source-available under a different license because it contains server-side orchestration, OAuth gateway behavior, Cloudflare deployment wiring, and Vibecodr API integration code.
26
-
27
- The package name is `@vibecodr/cli` because this repo distributes the user-facing command-line client. The older `@vibecodr/mcp` package name is kept only as a compatibility/deprecation surface; the bare `vibecodr` executable remains the canonical user command.
28
-
29
- Local config directories and secure-token service names intentionally keep their historical `vibecodr-mcp` / `@vibecodr/mcp` identifiers during this migration. Those names are storage compatibility keys, not the public npm package identity.
30
-
31
- Keeping the repos separate makes the contract clear:
32
-
33
- - users can use the hosted service normally
34
- - users can install and inspect the CLI freely under this repo license
35
- - commercial reuse of the gateway implementation remains governed by the server repo license
1
+ # Architecture
2
+
3
+ The Vibecodr CLI is a client of the hosted Vibecodr MCP gateway.
4
+
5
+ ## Boundary
6
+
7
+ - hosted MCP gateway/server repo: `Vibecodr-MCP`
8
+ - CLI client repo: `Vibecodr-MCP-CLI`
9
+ - CLI package: `@vibecodr/cli`
10
+ - primary executable: `vibecodr`
11
+ - compatibility executable: `vibecodr-mcp`
12
+ - legacy package compatibility: `@vibecodr/mcp`
13
+ - default MCP URL: `https://openai.vibecodr.space/mcp`
14
+
15
+ This repo does not run the hosted server. It installs client config, performs CLI-owned OAuth, discovers the live tool catalog, and calls tools over Streamable HTTP MCP.
16
+
17
+ ## Auth Ownership
18
+
19
+ `vibecodr login` stores OAuth tokens for the CLI profile only.
20
+
21
+ Codex, Cursor, VS Code, Windsurf, ChatGPT, and other MCP clients own separate OAuth sessions. Installing MCP config into those clients points them at the same server, but it does not copy CLI tokens into them.
22
+
23
+ ## Why The Repos Are Separate
24
+
25
+ The CLI is permissively licensed and safe to distribute as a public client package. The hosted gateway implementation is source-available under a different license because it contains server-side orchestration, OAuth gateway behavior, Cloudflare deployment wiring, and Vibecodr API integration code.
26
+
27
+ The package name is `@vibecodr/cli` because this repo distributes the user-facing command-line client. The older `@vibecodr/mcp` package name is kept only as a compatibility/deprecation surface; the bare `vibecodr` executable remains the canonical user command.
28
+
29
+ Local config directories and secure-token service names intentionally keep their historical `vibecodr-mcp` / `@vibecodr/mcp` identifiers during this migration. Those names are storage compatibility keys, not the public npm package identity.
30
+
31
+ Keeping the repos separate makes the contract clear:
32
+
33
+ - users can use the hosted service normally
34
+ - users can install and inspect the CLI freely under this repo license
35
+ - commercial reuse of the gateway implementation remains governed by the server repo license
package/docs/auth.md CHANGED
@@ -1,33 +1,33 @@
1
1
  # Auth
2
2
 
3
- `vibecodr login` authenticates the CLI itself to the hosted Vibecodr MCP server. It does not log Codex, Cursor, VS Code, Windsurf, ChatGPT, or any other MCP client into MCP.
3
+ `vibecodr login` authenticates the CLI itself to the hosted Vibecodr MCP server. It does not log Codex, Cursor, VS Code, Windsurf, ChatGPT, or any other MCP client into MCP.
4
+
5
+ Vibecodr has one hosted MCP gateway. The CLI is one client of that gateway, with its own local OAuth token store.
4
6
 
5
- Vibecodr has one hosted MCP gateway. The CLI is one client of that gateway, with its own local OAuth token store.
6
-
7
- Compatibility alias:
8
-
9
- - `vibecodr-mcp login`
7
+ Compatibility alias:
8
+
9
+ - `vibecodr-mcp login`
10
10
 
11
11
  ## Implemented now
12
12
 
13
13
  - protected-resource and authorization-server discovery against the MCP server
14
14
  - PKCE S256 enforcement
15
15
  - loopback callback on `127.0.0.1`
16
- - secure token storage in the OS credential store via `@napi-rs/keyring`
17
- - proactive refresh before protected runtime commands when a refresh token is available
18
- - `logout` local token deletion plus best-effort revocation
19
-
20
- The plaintext file secret store is for local automated tests only. It is ignored unless both `VIBECDR_MCP_INSECURE_SECRET_STORE_PATH` and `VIBECDR_MCP_ENABLE_INSECURE_SECRET_STORE=true` are set.
21
-
22
- The local config and secure-token storage keys intentionally keep their historical `vibecodr-mcp` / `@vibecodr/mcp` names during the `@vibecodr/cli` package rename. That preserves existing CLI sessions instead of forcing users to re-authenticate for a package-name migration.
23
-
24
- Supported OS credential stores:
25
-
26
- - macOS: Keychain
27
- - Windows: Credential Manager
28
- - Linux: Secret Service through a desktop keyring such as GNOME Keyring or KWallet
29
-
30
- Linux systems need a running, unlocked keyring on the current D-Bus session. Headless Linux should use a real Secret Service setup for persistent CLI login, or let the target MCP client own its own OAuth flow instead of storing CLI tokens.
16
+ - secure token storage in the OS credential store via `@napi-rs/keyring`
17
+ - proactive refresh before protected runtime commands when a refresh token is available
18
+ - `logout` local token deletion plus best-effort revocation
19
+
20
+ The plaintext file secret store is for local automated tests only. It is ignored unless both `VIBECDR_MCP_INSECURE_SECRET_STORE_PATH` and `VIBECDR_MCP_ENABLE_INSECURE_SECRET_STORE=true` are set.
21
+
22
+ The local config and secure-token storage keys intentionally keep their historical `vibecodr-mcp` / `@vibecodr/mcp` names during the `@vibecodr/cli` package rename. That preserves existing CLI sessions instead of forcing users to re-authenticate for a package-name migration.
23
+
24
+ Supported OS credential stores:
25
+
26
+ - macOS: Keychain
27
+ - Windows: Credential Manager
28
+ - Linux: Secret Service through a desktop keyring such as GNOME Keyring or KWallet
29
+
30
+ Linux systems need a running, unlocked keyring on the current D-Bus session. Headless Linux should use a real Secret Service setup for persistent CLI login, or let the target MCP client own its own OAuth flow instead of storing CLI tokens.
31
31
 
32
32
  ## Registration modes
33
33
 
package/docs/commands.md CHANGED
@@ -4,13 +4,16 @@ This page documents the command surface implemented in the current repo.
4
4
 
5
5
  ## Global flags
6
6
 
7
- All commands accept:
8
-
9
- - `--profile <name>`
10
- - `--server-url <url>`
11
- - `--json`
12
- - `--verbose`
13
- - `--non-interactive`
7
+ All commands accept:
8
+
9
+ - `--profile <name>`
10
+ - `--json`
11
+ - `--verbose`
12
+ - `--non-interactive`
13
+
14
+ Alternate MCP servers are profile-scoped, not runtime overrides. Use
15
+ `vibecodr config profile create <name> --server-url <url>` and then login to
16
+ that profile; stored tokens are bound to the server that issued them.
14
17
 
15
18
  ## Commands
16
19
 
package/docs/install.md CHANGED
@@ -15,14 +15,14 @@ node dist/bin/vibecodr-mcp.js install codex --json
15
15
  After the package is published:
16
16
 
17
17
  ```bash
18
- npx -y -p @vibecodr/cli vibecodr install codex
18
+ npx -y -p @vibecodr/cli vibecodr install codex
19
19
  ```
20
20
 
21
21
  Direct CLI-only usage:
22
22
 
23
23
  ```bash
24
- npx -y -p @vibecodr/cli vibecodr login
25
- npx -y -p @vibecodr/cli vibecodr tools --json
24
+ npx -y -p @vibecodr/cli vibecodr login
25
+ npx -y -p @vibecodr/cli vibecodr tools --json
26
26
  ```
27
27
 
28
28
  ## Client commands
package/docs/licensing.md CHANGED
@@ -1,20 +1,20 @@
1
1
  # Licensing
2
2
 
3
- This repository is the public Vibecodr CLI surface.
4
-
5
- - Package name: `@vibecodr/cli`
6
- - Primary executable name: `vibecodr`
7
- - Compatibility executable name: `vibecodr-mcp`
8
- - Legacy package compatibility: `@vibecodr/mcp`
3
+ This repository is the public Vibecodr CLI surface.
4
+
5
+ - Package name: `@vibecodr/cli`
6
+ - Primary executable name: `vibecodr`
7
+ - Compatibility executable name: `vibecodr-mcp`
8
+ - Legacy package compatibility: `@vibecodr/mcp`
9
9
  - Repo scope: direct CLI runtime, auth, diagnostics, and later thin installer adapters
10
10
  - License: Apache-2.0
11
11
 
12
- The hosted MCP gateway/server remains separate from this repo. That separation keeps hosted-service use distinct from any source-code reuse terms applied to the server implementation repo.
13
-
14
- Practical split:
15
-
16
- - this CLI repo governs distribution, modification, and reuse of the public client code
17
- - the hosted Vibecodr MCP service remains governed by Vibecodr service terms for account holders
18
- - the server implementation repo can carry different source-available terms without changing whether a commercial team may use the hosted service
12
+ The hosted MCP gateway/server remains separate from this repo. That separation keeps hosted-service use distinct from any source-code reuse terms applied to the server implementation repo.
19
13
 
20
- See [`architecture.md`](./architecture.md) for the client/server boundary.
14
+ Practical split:
15
+
16
+ - this CLI repo governs distribution, modification, and reuse of the public client code
17
+ - the hosted Vibecodr MCP service remains governed by Vibecodr service terms for account holders
18
+ - the server implementation repo can carry different source-available terms without changing whether a commercial team may use the hosted service
19
+
20
+ See [`architecture.md`](./architecture.md) for the client/server boundary.
@@ -30,15 +30,15 @@ Run:
30
30
  vibecodr doctor --json
31
31
  ```
32
32
 
33
- If the `secret-store` check fails, the CLI cannot safely store tokens yet.
34
-
35
- The plaintext file secret store is intentionally test-only. If `VIBECDR_MCP_INSECURE_SECRET_STORE_PATH` is set without `VIBECDR_MCP_ENABLE_INSECURE_SECRET_STORE=true`, the CLI refuses to start rather than silently storing tokens outside the OS credential store.
36
-
37
- Platform notes:
38
-
39
- - macOS uses Keychain. Unlock the login keychain and approve Terminal or Node access if prompted.
40
- - Windows uses Credential Manager. Run from a normal signed-in desktop session with Credential Manager available.
41
- - Linux uses Secret Service. Install libsecret support and run from a session with an unlocked GNOME Keyring or KWallet. Headless Linux needs an explicit Secret Service setup for persistent CLI login.
33
+ If the `secret-store` check fails, the CLI cannot safely store tokens yet.
34
+
35
+ The plaintext file secret store is intentionally test-only. If `VIBECDR_MCP_INSECURE_SECRET_STORE_PATH` is set without `VIBECDR_MCP_ENABLE_INSECURE_SECRET_STORE=true`, the CLI refuses to start rather than silently storing tokens outside the OS credential store.
36
+
37
+ Platform notes:
38
+
39
+ - macOS uses Keychain. Unlock the login keychain and approve Terminal or Node access if prompted.
40
+ - Windows uses Credential Manager. Run from a normal signed-in desktop session with Credential Manager available.
41
+ - Linux uses Secret Service. Install libsecret support and run from a session with an unlocked GNOME Keyring or KWallet. Headless Linux needs an explicit Secret Service setup for persistent CLI login.
42
42
 
43
43
  ## Proxy or TLS issues
44
44
 
@@ -81,9 +81,9 @@ The CLI writes the native path.
81
81
 
82
82
  Codex config install and CLI login are separate.
83
83
 
84
- - `install codex` configures Codex
85
- - `login` authenticates the Vibecodr CLI only
86
- - Codex will still own its own OAuth behavior when you use the server inside Codex
84
+ - `install codex` configures Codex
85
+ - `login` authenticates the Vibecodr CLI only
86
+ - Codex will still own its own OAuth behavior when you use the server inside Codex
87
87
 
88
88
  ## VS Code CLI not found
89
89
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecodr/cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Vibecodr CLI for login, live MCP tool discovery, and live tool invocation.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",