@protoboxai/cli 1.0.0 → 1.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.
package/README.md CHANGED
@@ -1,77 +1,71 @@
1
- # @chanl/cli
1
+ # @protoboxai/cli
2
2
 
3
- Command-line interface for the [Chanl AI](https://chanl.ai) platform.
3
+ Command-line interface for [Protobox](https://protobox.ai) — manage your hosted MCP server: tools, toolsets, knowledge, prompts, workspaces, and API keys, all from your terminal.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install -g @chanl/cli
8
+ npm install -g @protoboxai/cli
9
9
  ```
10
10
 
11
11
  Or run directly:
12
12
 
13
13
  ```bash
14
- npx @chanl/cli
14
+ npx @protoboxai/cli
15
15
  ```
16
16
 
17
17
  ## Quick Start
18
18
 
19
19
  ```bash
20
- # Authenticate
21
- chanl login
20
+ # Authenticate (API key or browser)
21
+ protobox auth login
22
22
 
23
- # Check health
24
- chanl health
23
+ # Check API health
24
+ protobox health
25
25
 
26
- # List agents
27
- chanl agents list
26
+ # Manage tools and toolsets
27
+ protobox tools list
28
+ protobox toolsets list
28
29
 
29
- # Chat with an agent
30
- chanl chat <agent-id>
30
+ # Knowledge base + prompts
31
+ protobox kb list
32
+ protobox prompts list
31
33
 
32
- # Run test scenarios
33
- chanl scenarios list
34
- chanl scenarios run <id>
35
-
36
- # Manage tools
37
- chanl tools list
38
- chanl toolsets list
34
+ # Connect your MCP client (Claude, Cursor, …)
35
+ protobox mcp config --format claude
39
36
  ```
40
37
 
41
38
  ## Commands
42
39
 
43
40
  | Command | Description |
44
41
  |---------|-------------|
45
- | `chanl login` | Authenticate with API key or browser |
46
- | `chanl health` | Check API health |
47
- | `chanl agents` | Manage AI agents |
48
- | `chanl tools` | Manage MCP tools |
49
- | `chanl toolsets` | Manage tool collections |
50
- | `chanl scenarios` | Run test scenarios |
51
- | `chanl calls` | Import and analyze calls |
52
- | `chanl call <phone>` | Make an outbound AI call |
53
- | `chanl chat <agent>` | Interactive chat session |
54
- | `chanl kb` | Manage knowledge base |
55
- | `chanl memory` | Manage agent memory |
56
- | `chanl scorecards` | Manage evaluation scorecards |
57
- | `chanl prompts` | Manage prompt templates |
58
- | `chanl config` | CLI configuration |
59
- | `chanl mcp` | MCP server status |
42
+ | `protobox auth` | Authenticate with API key or browser |
43
+ | `protobox health` | Check API health |
44
+ | `protobox workspaces` | Manage workspaces |
45
+ | `protobox tools` | Manage MCP tools |
46
+ | `protobox toolsets` | Manage tool collections |
47
+ | `protobox kb` | Manage knowledge base |
48
+ | `protobox prompts` | Manage prompt templates |
49
+ | `protobox mcp` | MCP server status + client config |
50
+ | `protobox chat` | Interactive chat session |
51
+ | `protobox config` | CLI configuration |
60
52
 
61
53
  ## Configuration
62
54
 
63
55
  ```bash
64
- chanl config show # Show current config
65
- chanl config set baseUrl <url> # Custom API endpoint
66
- chanl config reset # Reset to production
56
+ protobox config show # Show current config
57
+ protobox config set baseUrl <url> # Custom API endpoint
58
+ protobox config reset # Reset to production
67
59
  ```
68
60
 
69
- Default API: `https://platform.chanl.ai`
61
+ Default API: `https://platform.protobox.ai`
62
+
63
+ Environment overrides: `PROTOBOX_API_KEY`, `PROTOBOX_BASE_URL`, `PROTOBOX_WORKSPACE_ID`.
70
64
 
71
65
  ## Documentation
72
66
 
73
- - [Chanl Platform](https://chanl.ai)
74
- - [GitHub](https://github.com/chanl-ai/chanl-sdk)
67
+ - [Protobox](https://protobox.ai)
68
+ - [Docs](https://docs.protobox.ai)
75
69
 
76
70
  ## License
77
71
 
@@ -3,7 +3,7 @@ import { select } from "@inquirer/prompts";
3
3
  import ora from "ora";
4
4
  import chalk from "chalk";
5
5
  import http from "node:http";
6
- import { ChanlSDK } from "@protoboxai/sdk";
6
+ import { ProtoboxSDK } from "@protoboxai/sdk";
7
7
  import { configStore } from "../utils/config-store.js";
8
8
  import {
9
9
  printSuccess,
@@ -21,7 +21,7 @@ function createAuthCommand() {
21
21
  return auth;
22
22
  }
23
23
  function createLoginCommand() {
24
- return new Command("login").description("Authenticate with Chanl API").option("-k, --api-key <key>", "API key to use for authentication").option("--browser", "Force browser-based login (email/password or Google/Microsoft)").option("--base-url <url>", "Override the API base URL").addHelpText(
24
+ return new Command("login").description("Authenticate with Protobox API").option("-k, --api-key <key>", "API key to use for authentication").option("--browser", "Force browser-based login (email/password or Google/Microsoft)").option("--base-url <url>", "Override the API base URL").addHelpText(
25
25
  "after",
26
26
  `
27
27
  Login Methods:
@@ -29,9 +29,9 @@ Login Methods:
29
29
  --api-key <key> Use an API key directly (skips browser)
30
30
 
31
31
  Examples:
32
- $ chanl login # Browser login (recommended)
33
- $ chanl login --api-key ak_xxx # API key login
34
- $ chanl login --base-url http://localhost:3100 # Custom API URL`
32
+ $ protobox login # Browser login (recommended)
33
+ $ protobox login --api-key ak_xxx # API key login
34
+ $ protobox login --base-url http://localhost:3100 # Custom API URL`
35
35
  ).action(handleLogin);
36
36
  }
37
37
  function createLogoutCommand() {
@@ -51,7 +51,7 @@ async function handleApiKeyLogin(apiKey) {
51
51
  const baseUrl = configStore.getBaseUrl();
52
52
  const spinner = ora("Validating API key...").start();
53
53
  try {
54
- const sdk = new ChanlSDK({ apiKey, baseUrl });
54
+ const sdk = new ProtoboxSDK({ apiKey, baseUrl });
55
55
  const healthResponse = await sdk.health.getHealth();
56
56
  if (!healthResponse.success) {
57
57
  spinner.fail("Cannot connect to API");
@@ -97,7 +97,7 @@ async function handleBrowserLogin() {
97
97
  const spinner = ora("Waiting for authentication...").start();
98
98
  const token = await firebaseToken;
99
99
  spinner.text = "Exchanging token...";
100
- const sdk = new ChanlSDK({ baseUrl });
100
+ const sdk = new ProtoboxSDK({ baseUrl });
101
101
  const response = await sdk.auth.exchangeFirebaseToken(token);
102
102
  if (!response.success || !response.data) {
103
103
  spinner.fail("Token exchange failed");
@@ -257,8 +257,8 @@ async function handleAuthStatus() {
257
257
  if (!authMethod) {
258
258
  printLabel("Status", chalk.yellow("Not authenticated"));
259
259
  printBlank();
260
- printInfo("Run 'chanl login' to authenticate via browser");
261
- printInfo("Run 'chanl login --api-key <key>' to use an API key");
260
+ printInfo("Run 'protobox login' to authenticate via browser");
261
+ printInfo("Run 'protobox login --api-key <key>' to use an API key");
262
262
  return;
263
263
  }
264
264
  printLabel("Status", chalk.green("Authenticated"));
@@ -276,7 +276,7 @@ async function handleAuthStatus() {
276
276
  } else {
277
277
  sdkConfig.jwtToken = configStore.getJwtToken();
278
278
  }
279
- const sdk = new ChanlSDK(sdkConfig);
279
+ const sdk = new ProtoboxSDK(sdkConfig);
280
280
  const response = await sdk.workspace.getById(workspaceId);
281
281
  if (response.success && response.data?.name) {
282
282
  printLabel("Workspace Name", response.data.name);
@@ -17,7 +17,7 @@ function createChatCommand() {
17
17
  `
18
18
  What is Chat?
19
19
  Chat lets you test an AI agent via text in your terminal. It creates a session
20
- on the Chanl platform, which manages the full lifecycle including
20
+ on the Protobox platform, which manages the full lifecycle including
21
21
  transcription, billing, and post-chat evaluation.
22
22
 
23
23
  Modes:
@@ -31,12 +31,12 @@ Streaming:
31
31
  Note: streaming responses do not include tool call metadata.
32
32
 
33
33
  Examples:
34
- $ chanl chat abc123 # Interactive chat
35
- $ chanl chat abc123 --stream # Interactive with streaming
36
- $ chanl chat abc123 --message "Hello" # Single message mode
37
- $ chanl chat abc123 --message "Hi" --stream # Single message, streamed
38
- $ chanl chat abc123 --message "Hi" --json # Single message, JSON output
39
- $ chanl chat abc123 --workspace ws_456 # Override workspace`
34
+ $ protobox chat abc123 # Interactive chat
35
+ $ protobox chat abc123 --stream # Interactive with streaming
36
+ $ protobox chat abc123 --message "Hello" # Single message mode
37
+ $ protobox chat abc123 --message "Hi" --stream # Single message, streamed
38
+ $ protobox chat abc123 --message "Hi" --json # Single message, JSON output
39
+ $ protobox chat abc123 --workspace ws_456 # Override workspace`
40
40
  ).action(handleChat);
41
41
  return chat;
42
42
  }
@@ -21,13 +21,13 @@ const VALID_KEYS = [
21
21
  "defaultFormat"
22
22
  ];
23
23
  const ENVIRONMENT_PRESETS = {
24
- production: "https://platform.chanl.ai"
24
+ production: "https://platform.protobox.ai"
25
25
  };
26
26
  const KEY_DESCRIPTIONS = {
27
- apiKey: "Chanl API key for authentication",
27
+ apiKey: "Protobox API key for authentication",
28
28
  jwtToken: "JWT access token (from browser login)",
29
29
  refreshToken: "JWT refresh token (from browser login)",
30
- baseUrl: "Base URL for the Chanl API",
30
+ baseUrl: "Base URL for the Protobox API",
31
31
  server: "Alias for baseUrl (e.g. http://localhost:18005)",
32
32
  deployment: "local | cloud \u2014 local rewrites /api/v1 paths for OSS scenario servers",
33
33
  apiPrefix: "Override API prefix; empty string for flat /scenarios routes",
@@ -197,9 +197,9 @@ function isValidKey(key) {
197
197
  }
198
198
  function getConfigSource(key) {
199
199
  const envVarMap = {
200
- apiKey: "CHANL_API_KEY",
201
- baseUrl: "CHANL_BASE_URL",
202
- workspaceId: "CHANL_WORKSPACE_ID"
200
+ apiKey: "PROTOBOX_API_KEY",
201
+ baseUrl: "PROTOBOX_BASE_URL",
202
+ workspaceId: "PROTOBOX_WORKSPACE_ID"
203
203
  };
204
204
  const envVar = envVarMap[key];
205
205
  if (envVar && process.env[envVar]) {
@@ -1,7 +1,7 @@
1
1
  import { Command } from "commander";
2
2
  import ora from "ora";
3
3
  import chalk from "chalk";
4
- import { ChanlSDK } from "@protoboxai/sdk";
4
+ import { ProtoboxSDK } from "@protoboxai/sdk";
5
5
  import { configStore } from "../utils/config-store.js";
6
6
  import {
7
7
  printSuccess,
@@ -16,7 +16,7 @@ function createHealthCommand() {
16
16
  }
17
17
  async function handleHealth() {
18
18
  const baseUrl = configStore.getBaseUrl();
19
- const sdk = new ChanlSDK({ baseUrl });
19
+ const sdk = new ProtoboxSDK({ baseUrl });
20
20
  const spinner = ora("Checking API health...").start();
21
21
  try {
22
22
  const response = await sdk.health.getHealth();
@@ -3,7 +3,7 @@ import ora from "ora";
3
3
  import chalk from "chalk";
4
4
  import { readFileSync, existsSync } from "fs";
5
5
  import { resolve } from "path";
6
- import { ChanlSDK } from "@protoboxai/sdk";
6
+ import { ProtoboxSDK } from "@protoboxai/sdk";
7
7
  import { configStore } from "../utils/config-store.js";
8
8
  import {
9
9
  printError,
@@ -25,11 +25,11 @@ What is Knowledge Base?
25
25
  can search and retrieve during conversations. Supports text, URLs, and files.
26
26
 
27
27
  Quick Start:
28
- $ chanl kb list # List all entries
29
- $ chanl kb add --text "FAQ content" --title "FAQ" # Add text content
30
- $ chanl kb add --url https://docs.example.com # Add from URL
31
- $ chanl kb add --file ./docs/guide.pdf # Upload file
32
- $ chanl kb search "how do I reset password" # Search KB
28
+ $ protobox kb list # List all entries
29
+ $ protobox kb add --text "FAQ content" --title "FAQ" # Add text content
30
+ $ protobox kb add --url https://docs.example.com # Add from URL
31
+ $ protobox kb add --file ./docs/guide.pdf # Upload file
32
+ $ protobox kb search "how do I reset password" # Search KB
33
33
 
34
34
  Workflow:
35
35
  1. Add content via text, URL, or file upload
@@ -40,43 +40,43 @@ Workflow:
40
40
  "after",
41
41
  `
42
42
  Examples:
43
- $ chanl kb list # List all entries
44
- $ chanl kb list --source url # Only URL-sourced entries
45
- $ chanl kb list --status completed # Only fully processed
46
- $ chanl kb list --json # Output as JSON`
43
+ $ protobox kb list # List all entries
44
+ $ protobox kb list --source url # Only URL-sourced entries
45
+ $ protobox kb list --status completed # Only fully processed
46
+ $ protobox kb list --json # Output as JSON`
47
47
  ).action(handleKnowledgeList);
48
48
  knowledge.command("get <id>").description("Get knowledge entry details").option("--chunks", "Include chunk details").addHelpText(
49
49
  "after",
50
50
  `
51
51
  Examples:
52
- $ chanl kb get abc123 # Get entry details
53
- $ chanl kb get abc123 --chunks # Include chunks
54
- $ chanl kb get abc123 --json # Output as JSON`
52
+ $ protobox kb get abc123 # Get entry details
53
+ $ protobox kb get abc123 --chunks # Include chunks
54
+ $ protobox kb get abc123 --json # Output as JSON`
55
55
  ).action(handleKnowledgeGet);
56
56
  knowledge.command("add").description("Add knowledge content (text, URL, or file)").option("-t, --title <title>", "Title for the entry").option("--text <content>", "Direct text content").option("--url <url>", "URL to fetch content from").option("-f, --file <path>", "File to upload (PDF, TXT, HTML, MD)").option("--folder <folderId>", "Folder ID to organize entry").option("--tags <tags>", "Comma-separated tags").option("--category <category>", "Category for organization").option("--crawl-depth <depth>", "URL crawl depth (0-2)", "0").option("--max-pages <pages>", "Max pages to crawl (1-50)", "10").addHelpText(
57
57
  "after",
58
58
  `
59
59
  Examples:
60
- $ chanl kb add --text "Content here" --title "FAQ"
61
- $ chanl kb add --url https://docs.example.com --title "Docs"
62
- $ chanl kb add --url https://docs.example.com --crawl-depth 1 --max-pages 20
63
- $ chanl kb add --file ./guide.pdf --title "User Guide"
64
- $ chanl kb add --text "Content" --tags "faq,support" --category "support"`
60
+ $ protobox kb add --text "Content here" --title "FAQ"
61
+ $ protobox kb add --url https://docs.example.com --title "Docs"
62
+ $ protobox kb add --url https://docs.example.com --crawl-depth 1 --max-pages 20
63
+ $ protobox kb add --file ./guide.pdf --title "User Guide"
64
+ $ protobox kb add --text "Content" --tags "faq,support" --category "support"`
65
65
  ).action(handleKnowledgeAdd);
66
66
  knowledge.command("update <id>").description("Update a knowledge entry").option("-t, --title <title>", "New title").option("--content <content>", "New content (text entries only)").option("--tags <tags>", "Comma-separated tags").option("--category <category>", "Category").option("--enabled <boolean>", "Enable/disable for search").addHelpText(
67
67
  "after",
68
68
  `
69
69
  Examples:
70
- $ chanl kb update abc123 --title "New Title"
71
- $ chanl kb update abc123 --enabled false
72
- $ chanl kb update abc123 --tags "updated,important"`
70
+ $ protobox kb update abc123 --title "New Title"
71
+ $ protobox kb update abc123 --enabled false
72
+ $ protobox kb update abc123 --tags "updated,important"`
73
73
  ).action(handleKnowledgeUpdate);
74
74
  knowledge.command("delete <id>").description("Delete a knowledge entry").option("-y, --yes", "Skip confirmation prompt").addHelpText(
75
75
  "after",
76
76
  `
77
77
  Examples:
78
- $ chanl kb delete abc123
79
- $ chanl kb delete abc123 --yes # Skip confirmation`
78
+ $ protobox kb delete abc123
79
+ $ protobox kb delete abc123 --yes # Skip confirmation`
80
80
  ).action(handleKnowledgeDelete);
81
81
  knowledge.command("search <query>").description("Search the knowledge base").option("-m, --mode <mode>", "Search mode: hybrid, vector, text", "hybrid").option("-l, --limit <number>", "Max results", "10").option("--min-score <score>", "Minimum similarity score (0-1)").addHelpText(
82
82
  "after",
@@ -87,26 +87,26 @@ Search Modes:
87
87
  text - Full-text keyword search
88
88
 
89
89
  Examples:
90
- $ chanl kb search "how to reset password"
91
- $ chanl kb search "API authentication" --mode vector
92
- $ chanl kb search "billing" --limit 5 --min-score 0.7`
90
+ $ protobox kb search "how to reset password"
91
+ $ protobox kb search "API authentication" --mode vector
92
+ $ protobox kb search "billing" --limit 5 --min-score 0.7`
93
93
  ).action(handleKnowledgeSearch);
94
94
  knowledge.command("status <taskId>").description("Check processing status of async upload").addHelpText(
95
95
  "after",
96
96
  `
97
97
  Examples:
98
- $ chanl kb status abc123 # Check task status`
98
+ $ protobox kb status abc123 # Check task status`
99
99
  ).action(handleKnowledgeStatus);
100
100
  return knowledge;
101
101
  }
102
102
  async function handleKnowledgeList(options) {
103
103
  const apiKey = configStore.getApiKey();
104
104
  if (!apiKey) {
105
- printError("Not logged in", "Run: chanl auth login");
105
+ printError("Not logged in", "Run: protobox auth login");
106
106
  process.exitCode = 1;
107
107
  return;
108
108
  }
109
- const sdk = new ChanlSDK({
109
+ const sdk = new ProtoboxSDK({
110
110
  baseUrl: configStore.getBaseUrl(),
111
111
  apiKey
112
112
  });
@@ -163,11 +163,11 @@ async function handleKnowledgeList(options) {
163
163
  async function handleKnowledgeGet(id, options) {
164
164
  const apiKey = configStore.getApiKey();
165
165
  if (!apiKey) {
166
- printError("Not logged in", "Run: chanl auth login");
166
+ printError("Not logged in", "Run: protobox auth login");
167
167
  process.exitCode = 1;
168
168
  return;
169
169
  }
170
- const sdk = new ChanlSDK({
170
+ const sdk = new ProtoboxSDK({
171
171
  baseUrl: configStore.getBaseUrl(),
172
172
  apiKey
173
173
  });
@@ -231,7 +231,7 @@ async function handleKnowledgeGet(id, options) {
231
231
  async function handleKnowledgeAdd(options) {
232
232
  const apiKey = configStore.getApiKey();
233
233
  if (!apiKey) {
234
- printError("Not logged in", "Run: chanl auth login");
234
+ printError("Not logged in", "Run: protobox auth login");
235
235
  process.exitCode = 1;
236
236
  return;
237
237
  }
@@ -246,7 +246,7 @@ async function handleKnowledgeAdd(options) {
246
246
  process.exitCode = 1;
247
247
  return;
248
248
  }
249
- const sdk = new ChanlSDK({
249
+ const sdk = new ProtoboxSDK({
250
250
  baseUrl: configStore.getBaseUrl(),
251
251
  apiKey
252
252
  });
@@ -309,7 +309,7 @@ async function handleKnowledgeAdd(options) {
309
309
  printLabel("ID", entry.id);
310
310
  printLabel("Task ID", entry.taskId);
311
311
  printLabel("Status", formatStatus(entry.processingStatus));
312
- printInfo(`Track progress: chanl kb status ${entry.taskId}`);
312
+ printInfo(`Track progress: protobox kb status ${entry.taskId}`);
313
313
  } else {
314
314
  printSuccess(`Knowledge entry created`);
315
315
  printLabel("ID", entry.id);
@@ -327,11 +327,11 @@ async function handleKnowledgeAdd(options) {
327
327
  async function handleKnowledgeUpdate(id, options) {
328
328
  const apiKey = configStore.getApiKey();
329
329
  if (!apiKey) {
330
- printError("Not logged in", "Run: chanl auth login");
330
+ printError("Not logged in", "Run: protobox auth login");
331
331
  process.exitCode = 1;
332
332
  return;
333
333
  }
334
- const sdk = new ChanlSDK({
334
+ const sdk = new ProtoboxSDK({
335
335
  baseUrl: configStore.getBaseUrl(),
336
336
  apiKey
337
337
  });
@@ -377,7 +377,7 @@ async function handleKnowledgeUpdate(id, options) {
377
377
  async function handleKnowledgeDelete(id, options) {
378
378
  const apiKey = configStore.getApiKey();
379
379
  if (!apiKey) {
380
- printError("Not logged in", "Run: chanl auth login");
380
+ printError("Not logged in", "Run: protobox auth login");
381
381
  process.exitCode = 1;
382
382
  return;
383
383
  }
@@ -396,7 +396,7 @@ async function handleKnowledgeDelete(id, options) {
396
396
  return;
397
397
  }
398
398
  }
399
- const sdk = new ChanlSDK({
399
+ const sdk = new ProtoboxSDK({
400
400
  baseUrl: configStore.getBaseUrl(),
401
401
  apiKey
402
402
  });
@@ -421,11 +421,11 @@ async function handleKnowledgeDelete(id, options) {
421
421
  async function handleKnowledgeSearch(query, options) {
422
422
  const apiKey = configStore.getApiKey();
423
423
  if (!apiKey) {
424
- printError("Not logged in", "Run: chanl auth login");
424
+ printError("Not logged in", "Run: protobox auth login");
425
425
  process.exitCode = 1;
426
426
  return;
427
427
  }
428
- const sdk = new ChanlSDK({
428
+ const sdk = new ProtoboxSDK({
429
429
  baseUrl: configStore.getBaseUrl(),
430
430
  apiKey
431
431
  });
@@ -475,11 +475,11 @@ async function handleKnowledgeSearch(query, options) {
475
475
  async function handleKnowledgeStatus(taskId) {
476
476
  const apiKey = configStore.getApiKey();
477
477
  if (!apiKey) {
478
- printError("Not logged in", "Run: chanl auth login");
478
+ printError("Not logged in", "Run: protobox auth login");
479
479
  process.exitCode = 1;
480
480
  return;
481
481
  }
482
- const sdk = new ChanlSDK({
482
+ const sdk = new ProtoboxSDK({
483
483
  baseUrl: configStore.getBaseUrl(),
484
484
  apiKey
485
485
  });
@@ -21,31 +21,31 @@ function createMcpCommand() {
21
21
  `
22
22
  What is MCP?
23
23
  Model Context Protocol (MCP) lets AI agents (Claude, Cursor, etc.) use your
24
- Chanl tools, knowledge base, and prompts. The MCP server bridges your workspace
24
+ Protobox tools, knowledge base, and prompts. The MCP server bridges your workspace
25
25
  with AI clients.
26
26
 
27
27
  Quick Start:
28
- $ chanl mcp # Check server status
29
- $ chanl mcp test # Run protocol test
30
- $ chanl mcp config # Get config for your AI client
28
+ $ protobox mcp # Check server status
29
+ $ protobox mcp test # Run protocol test
30
+ $ protobox mcp config # Get config for your AI client
31
31
 
32
32
  Connecting AI Clients:
33
- 1. Run 'chanl mcp config --format claude' to get Claude Desktop config
33
+ 1. Run 'protobox mcp config --format claude' to get Claude Desktop config
34
34
  2. Add the JSON to Claude Desktop's settings
35
- 3. Your Chanl tools will appear in Claude!`
35
+ 3. Your Protobox tools will appear in Claude!`
36
36
  ).action(handleMcpDefault);
37
37
  mcp.command("info").description("Show MCP server URL, status, and resource counts").addHelpText(
38
38
  "after",
39
39
  `
40
40
  Example:
41
- $ chanl mcp info # Show server details
42
- $ chanl mcp info --json # Output as JSON`
41
+ $ protobox mcp info # Show server details
42
+ $ protobox mcp info --json # Output as JSON`
43
43
  ).action(handleMcpInfo);
44
44
  mcp.command("status").description("Health check the MCP server").addHelpText(
45
45
  "after",
46
46
  `
47
47
  Example:
48
- $ chanl mcp status # Quick health check`
48
+ $ protobox mcp status # Quick health check`
49
49
  ).action(handleMcpStatus);
50
50
  mcp.command("test").description("Run MCP protocol test with real MCP client").addHelpText(
51
51
  "after",
@@ -57,8 +57,8 @@ Tests the full MCP protocol handshake:
57
57
  4. List prompts
58
58
 
59
59
  Example:
60
- $ chanl mcp test # Run all protocol tests
61
- $ chanl mcp test --json # Output results as JSON`
60
+ $ protobox mcp test # Run all protocol tests
61
+ $ protobox mcp test --json # Output results as JSON`
62
62
  ).action(handleMcpTest);
63
63
  mcp.command("config").description("Output MCP configuration for AI clients").option("-f, --format <format>", "Format: claude, cursor, generic", "generic").addHelpText(
64
64
  "after",
@@ -71,13 +71,13 @@ Supported formats:
71
71
  generic - Generic MCP client format
72
72
 
73
73
  Examples:
74
- $ chanl mcp config # Generic format
75
- $ chanl mcp config --format claude # Claude Desktop format
76
- $ chanl mcp config --format cursor # Cursor IDE format
77
- $ chanl mcp config --format claude > config.json # Save to file
74
+ $ protobox mcp config # Generic format
75
+ $ protobox mcp config --format claude # Claude Desktop format
76
+ $ protobox mcp config --format cursor # Cursor IDE format
77
+ $ protobox mcp config --format claude > config.json # Save to file
78
78
 
79
79
  Setup Claude Desktop:
80
- 1. Run: chanl mcp config --format claude
80
+ 1. Run: protobox mcp config --format claude
81
81
  2. Copy the JSON output
82
82
  3. Paste into ~/Library/Application Support/Claude/claude_desktop_config.json`
83
83
  ).action(handleMcpConfig);
@@ -85,23 +85,23 @@ Setup Claude Desktop:
85
85
  "after",
86
86
  `
87
87
  Example:
88
- $ chanl mcp tools agent_123 # List tools for agent
89
- $ chanl mcp tools agent_123 --json # Output as JSON`
88
+ $ protobox mcp tools agent_123 # List tools for agent
89
+ $ protobox mcp tools agent_123 --json # Output as JSON`
90
90
  ).action(handleMcpTools);
91
91
  mcp.command("call <agent-id> <tool-name> [args]").description("Call an MCP tool by name").addHelpText(
92
92
  "after",
93
93
  `
94
94
  Example:
95
- $ chanl mcp call agent_123 get_weather '{"city":"London"}'
96
- $ chanl mcp call agent_123 ping
97
- $ chanl mcp call agent_123 get_weather '{"city":"London"}' --json`
95
+ $ protobox mcp call agent_123 get_weather '{"city":"London"}'
96
+ $ protobox mcp call agent_123 ping
97
+ $ protobox mcp call agent_123 get_weather '{"city":"London"}' --json`
98
98
  ).action(handleMcpCall);
99
99
  mcp.command("inspect <agent-id> <tool-name>").description("Show schema and details for a specific MCP tool").addHelpText(
100
100
  "after",
101
101
  `
102
102
  Example:
103
- $ chanl mcp inspect agent_123 get_weather
104
- $ chanl mcp inspect agent_123 get_weather --json`
103
+ $ protobox mcp inspect agent_123 get_weather
104
+ $ protobox mcp inspect agent_123 get_weather --json`
105
105
  ).action(handleMcpInspect);
106
106
  mcp.command("install").description("Generate MCP config snippet for editors (Cursor, VSCode, Claude)").option("-f, --format <format>", "Format: claude, cursor, vscode, generic", "generic").addHelpText(
107
107
  "after",
@@ -116,11 +116,11 @@ Supported formats:
116
116
  generic - Generic MCP client (default)
117
117
 
118
118
  Examples:
119
- $ chanl mcp install # Generic format
120
- $ chanl mcp install --format claude # Claude Desktop format
121
- $ chanl mcp install --format cursor # Cursor IDE format
122
- $ chanl mcp install --format vscode # VSCode format
123
- $ chanl mcp install --format claude > mcp.json # Save to file`
119
+ $ protobox mcp install # Generic format
120
+ $ protobox mcp install --format claude # Claude Desktop format
121
+ $ protobox mcp install --format cursor # Cursor IDE format
122
+ $ protobox mcp install --format vscode # VSCode format
123
+ $ protobox mcp install --format claude > mcp.json # Save to file`
124
124
  ).action(handleMcpInstall);
125
125
  return mcp;
126
126
  }
@@ -201,6 +201,19 @@ async function handleMcpStatus() {
201
201
  process.exitCode = 1;
202
202
  }
203
203
  }
204
+ function rebrandMcpServerKey(cfg) {
205
+ if (!cfg || typeof cfg !== "object") return cfg;
206
+ const obj = cfg;
207
+ const servers = obj["mcpServers"];
208
+ if (servers && typeof servers === "object" && !Array.isArray(servers)) {
209
+ const s = servers;
210
+ if ("chanl" in s && !("protobox" in s)) {
211
+ const { chanl, ...rest } = s;
212
+ return { ...obj, mcpServers: { protobox: chanl, ...rest } };
213
+ }
214
+ }
215
+ return cfg;
216
+ }
204
217
  async function handleMcpConfig(options) {
205
218
  const sdk = createSdk();
206
219
  if (!sdk) return;
@@ -228,11 +241,12 @@ async function handleMcpConfig(options) {
228
241
  output = config.agentConfigs.generic;
229
242
  break;
230
243
  }
244
+ output = rebrandMcpServerKey(output);
231
245
  printJson(output);
232
246
  if (!isJsonOutput()) {
233
247
  printBlank();
234
248
  printInfo(`Configuration for ${format} format. Copy and paste into your ${format === "claude" ? "Claude Desktop" : format === "cursor" ? "Cursor IDE" : "MCP client"} configuration.`);
235
- printInfo(`Replace \${CHANL_MCP_API_KEY} with your actual MCP API key.`);
249
+ printInfo(`Replace \${PROTOBOX_MCP_API_KEY} with your actual MCP API key.`);
236
250
  }
237
251
  } catch (error) {
238
252
  spinner.fail("Failed to fetch MCP configuration");
@@ -276,7 +290,7 @@ async function handleMcpDefault() {
276
290
  console.log(chalk.dim("\u2500".repeat(40)));
277
291
  printBlank();
278
292
  if (!status?.healthy) {
279
- printInfo("Run 'chanl mcp test' for detailed diagnostics");
293
+ printInfo("Run 'protobox mcp test' for detailed diagnostics");
280
294
  process.exitCode = 1;
281
295
  }
282
296
  } catch (error) {
@@ -432,11 +446,11 @@ async function handleMcpInspect(agentId, toolName) {
432
446
  async function handleMcpInstall(options) {
433
447
  const apiKey = configStore.getApiKey();
434
448
  if (!apiKey) {
435
- printError("Not authenticated", "Run 'chanl login' to authenticate first");
449
+ printError("Not authenticated", "Run 'protobox login' to authenticate first");
436
450
  process.exitCode = 1;
437
451
  return;
438
452
  }
439
- const baseUrl = configStore.getBaseUrl() || "https://api.chanl.ai";
453
+ const baseUrl = configStore.getBaseUrl() || "https://platform.protobox.ai";
440
454
  const mcpUrl = baseUrl.replace(/\/$/, "") + "/mcp";
441
455
  const format = options.format.toLowerCase();
442
456
  const serverConfig = {
@@ -449,21 +463,21 @@ async function handleMcpInstall(options) {
449
463
  case "claude":
450
464
  output = {
451
465
  mcpServers: {
452
- chanl: serverConfig
466
+ protobox: serverConfig
453
467
  }
454
468
  };
455
469
  break;
456
470
  case "cursor":
457
471
  output = {
458
472
  mcpServers: {
459
- chanl: serverConfig
473
+ protobox: serverConfig
460
474
  }
461
475
  };
462
476
  break;
463
477
  case "vscode":
464
478
  output = {
465
479
  mcpServers: {
466
- chanl: serverConfig
480
+ protobox: serverConfig
467
481
  }
468
482
  };
469
483
  break;
@@ -471,7 +485,7 @@ async function handleMcpInstall(options) {
471
485
  default:
472
486
  output = {
473
487
  mcpServers: {
474
- chanl: serverConfig
488
+ protobox: serverConfig
475
489
  }
476
490
  };
477
491
  break;
@@ -521,7 +535,7 @@ async function handleMcpTest() {
521
535
  }
522
536
  });
523
537
  const client = new Client(
524
- { name: "chanl-cli", version: "1.0.0" },
538
+ { name: "protobox-cli", version: "1.0.0" },
525
539
  { capabilities: {} }
526
540
  );
527
541
  spinner.text = "Connecting to MCP server...";
@@ -23,33 +23,33 @@ What are Prompts?
23
23
  variables, versioning, and categories for organizing across use cases.
24
24
 
25
25
  Quick Start:
26
- $ chanl prompts list # List all prompts
27
- $ chanl prompts get <id> # View prompt details
28
- $ chanl prompts create -f prompt.json # Create from JSON file
29
- $ chanl prompts update <id> -f data.json # Update a prompt
30
- $ chanl prompts delete <id> # Delete a prompt`
26
+ $ protobox prompts list # List all prompts
27
+ $ protobox prompts get <id> # View prompt details
28
+ $ protobox prompts create -f prompt.json # Create from JSON file
29
+ $ protobox prompts update <id> -f data.json # Update a prompt
30
+ $ protobox prompts delete <id> # Delete a prompt`
31
31
  );
32
32
  prompts.command("list").description("List all prompts").option("-c, --category <category>", "Filter by category (support, sales, onboarding, general)").option("-s, --status <status>", "Filter by status (active, draft, archived)").option("--search <query>", "Search by name or content").option("-l, --limit <number>", "Number of items per page", "20").option("--page <number>", "Page number", "1").addHelpText(
33
33
  "after",
34
34
  `
35
35
  Examples:
36
- $ chanl prompts list # List all prompts
37
- $ chanl prompts list --category support # Filter by category
38
- $ chanl prompts list --status active # Only active prompts
39
- $ chanl prompts list --json # Output as JSON`
36
+ $ protobox prompts list # List all prompts
37
+ $ protobox prompts list --category support # Filter by category
38
+ $ protobox prompts list --status active # Only active prompts
39
+ $ protobox prompts list --json # Output as JSON`
40
40
  ).action(handlePromptsList);
41
41
  prompts.command("get <id>").description("Get prompt details").addHelpText(
42
42
  "after",
43
43
  `
44
44
  Examples:
45
- $ chanl prompts get abc123 # Get prompt details
46
- $ chanl prompts get abc123 --json # Output as JSON`
45
+ $ protobox prompts get abc123 # Get prompt details
46
+ $ protobox prompts get abc123 --json # Output as JSON`
47
47
  ).action(handlePromptsGet);
48
48
  prompts.command("create").description("Create a new prompt").option("-f, --file <path>", "Path to JSON file with prompt data").addHelpText(
49
49
  "after",
50
50
  `
51
51
  Examples:
52
- $ chanl prompts create -f prompt.json # Create from file
52
+ $ protobox prompts create -f prompt.json # Create from file
53
53
 
54
54
  JSON file format:
55
55
  {
@@ -64,14 +64,14 @@ JSON file format:
64
64
  "after",
65
65
  `
66
66
  Examples:
67
- $ chanl prompts update abc123 -f updates.json`
67
+ $ protobox prompts update abc123 -f updates.json`
68
68
  ).action(handlePromptsUpdate);
69
69
  prompts.command("delete <id>").description("Delete a prompt").option("-y, --yes", "Skip confirmation prompt").addHelpText(
70
70
  "after",
71
71
  `
72
72
  Examples:
73
- $ chanl prompts delete abc123
74
- $ chanl prompts delete abc123 --yes # Skip confirmation`
73
+ $ protobox prompts delete abc123
74
+ $ protobox prompts delete abc123 --yes # Skip confirmation`
75
75
  ).action(handlePromptsDelete);
76
76
  return prompts;
77
77
  }
@@ -112,7 +112,7 @@ async function handlePromptsList(options) {
112
112
  }
113
113
  if (prompts.length === 0) {
114
114
  printInfo("No prompts found");
115
- printInfo("Use 'chanl prompts create -f prompt.json' to create a prompt");
115
+ printInfo("Use 'protobox prompts create -f prompt.json' to create a prompt");
116
116
  return;
117
117
  }
118
118
  printBlank();
@@ -60,30 +60,30 @@ const TOOL_TEMPLATES = {
60
60
  };
61
61
  function createToolsCommand() {
62
62
  const tools = new Command("tools").description("Manage MCP tools");
63
- tools.command("list").description("List all tools in the workspace").option("-t, --type <type>", "Filter by type: http, javascript, code").option("-e, --enabled", "Show only enabled tools").option("-d, --disabled", "Show only disabled tools").option("--tag <tag>", "Filter by tag (e.g., --tag api)").option("--no-system", "Exclude system tools (kb_search, chanl_reason, etc.)").option("-l, --limit <number>", "Items per page (default: 20)", "20").option("-p, --page <number>", "Page number (default: 1)", "1").addHelpText(
63
+ tools.command("list").description("List all tools in the workspace").option("-t, --type <type>", "Filter by type: http, javascript, code").option("-e, --enabled", "Show only enabled tools").option("-d, --disabled", "Show only disabled tools").option("--tag <tag>", "Filter by tag (e.g., --tag api)").option("--no-system", "Exclude system tools (e.g. kb_search)").option("-l, --limit <number>", "Items per page (default: 20)", "20").option("-p, --page <number>", "Page number (default: 1)", "1").addHelpText(
64
64
  "after",
65
65
  `
66
66
  Examples:
67
- $ chanl tools list # List all tools
68
- $ chanl tools list --enabled # Only enabled tools
69
- $ chanl tools list --type http # Only HTTP tools
70
- $ chanl tools list --tag api # Filter by tag
71
- $ chanl tools list --no-system # Exclude system tools
72
- $ chanl tools list --json # Output as JSON`
67
+ $ protobox tools list # List all tools
68
+ $ protobox tools list --enabled # Only enabled tools
69
+ $ protobox tools list --type http # Only HTTP tools
70
+ $ protobox tools list --tag api # Filter by tag
71
+ $ protobox tools list --no-system # Exclude system tools
72
+ $ protobox tools list --json # Output as JSON`
73
73
  ).action(handleToolsList);
74
74
  tools.command("get <id>").description("Get detailed info about a tool").addHelpText(
75
75
  "after",
76
76
  `
77
77
  Examples:
78
- $ chanl tools get 507f1f77bcf86cd799439011
79
- $ chanl tools get 507f1f77bcf86cd799439011 --json`
78
+ $ protobox tools get 507f1f77bcf86cd799439011
79
+ $ protobox tools get 507f1f77bcf86cd799439011 --json`
80
80
  ).action(handleToolsGet);
81
81
  tools.command("create").description("Create a new tool from JSON file").option("-f, --file <path>", "Path to JSON file with tool definition").option("--template [type]", "Output a sample JSON template (http or javascript)").addHelpText(
82
82
  "after",
83
83
  `
84
84
  Examples:
85
- $ chanl tools create --template http > my-tool.json # Generate template
86
- $ chanl tools create -f my-tool.json # Create from file
85
+ $ protobox tools create --template http > my-tool.json # Generate template
86
+ $ protobox tools create -f my-tool.json # Create from file
87
87
 
88
88
  Required JSON fields:
89
89
  name Tool name (used in MCP)
@@ -96,13 +96,13 @@ Optional fields:
96
96
  isEnabled Enable immediately (default: true)
97
97
  tags Array of category tags
98
98
 
99
- Run 'chanl tools create --template' to see full structure.`
99
+ Run 'protobox tools create --template' to see full structure.`
100
100
  ).action(handleToolsCreate);
101
101
  tools.command("update <id>").description("Update a tool from JSON file").requiredOption("-f, --file <path>", "Path to JSON file with updates").addHelpText(
102
102
  "after",
103
103
  `
104
104
  Examples:
105
- $ chanl tools update 507f1f77bcf86cd799439011 -f updates.json
105
+ $ protobox tools update 507f1f77bcf86cd799439011 -f updates.json
106
106
 
107
107
  The JSON file only needs fields you want to change:
108
108
  {"description": "Updated description", "isEnabled": false}`
@@ -111,28 +111,28 @@ The JSON file only needs fields you want to change:
111
111
  "after",
112
112
  `
113
113
  Examples:
114
- $ chanl tools delete 507f1f77bcf86cd799439011 # With confirmation
115
- $ chanl tools delete 507f1f77bcf86cd799439011 -y # Skip confirmation`
114
+ $ protobox tools delete 507f1f77bcf86cd799439011 # With confirmation
115
+ $ protobox tools delete 507f1f77bcf86cd799439011 -y # Skip confirmation`
116
116
  ).action(handleToolsDelete);
117
117
  tools.command("execute <id>").description("Execute a tool and get results").requiredOption("-i, --input <json>", "Input arguments as JSON string").addHelpText(
118
118
  "after",
119
119
  `
120
120
  Examples:
121
- $ chanl tools execute 507f1f77bcf86cd799439011 -i '{"query": "hello"}'
122
- $ chanl tools execute my-tool-id -i '{"location": "London"}' --json`
121
+ $ protobox tools execute 507f1f77bcf86cd799439011 -i '{"query": "hello"}'
122
+ $ protobox tools execute my-tool-id -i '{"location": "London"}' --json`
123
123
  ).action(handleToolsExecute);
124
124
  tools.command("test <id>").description("Test a tool execution (dry run)").requiredOption("-i, --input <json>", "Input arguments as JSON string").addHelpText(
125
125
  "after",
126
126
  `
127
127
  Examples:
128
- $ chanl tools test 507f1f77bcf86cd799439011 -i '{"message": "test"}'`
128
+ $ protobox tools test 507f1f77bcf86cd799439011 -i '{"message": "test"}'`
129
129
  ).action(handleToolsTest);
130
130
  tools.command("executions <id>").description("Get execution history for a tool").option("-l, --limit <number>", "Items per page (default: 10)", "10").option("-p, --page <number>", "Page number (default: 1)", "1").option("--status <status>", "Filter: pending, running, completed, failed").addHelpText(
131
131
  "after",
132
132
  `
133
133
  Examples:
134
- $ chanl tools executions 507f1f77bcf86cd799439011
135
- $ chanl tools executions my-tool-id --status failed --limit 5`
134
+ $ protobox tools executions 507f1f77bcf86cd799439011
135
+ $ protobox tools executions my-tool-id --status failed --limit 5`
136
136
  ).action(handleToolsExecutions);
137
137
  tools.command("enable <id>").description("Enable a tool (makes it available in MCP)").action(handleToolsEnable);
138
138
  tools.command("disable <id>").description("Disable a tool (hides from MCP)").action(handleToolsDisable);
@@ -168,7 +168,7 @@ async function handleToolsList(options) {
168
168
  process.exitCode = 1;
169
169
  return;
170
170
  }
171
- const { tools, total, pagination } = response.data;
171
+ const { items: tools, total, pagination } = response.data;
172
172
  if (isJsonOutput()) {
173
173
  printJson({ tools, total, pagination });
174
174
  return;
@@ -237,7 +237,7 @@ async function handleToolsCreate(options) {
237
237
  }
238
238
  if (!options.file) {
239
239
  printError("Missing required option", "Use '-f, --file <path>' or '--template' for sample JSON");
240
- printInfo("Run 'chanl tools create --help' for usage");
240
+ printInfo("Run 'protobox tools create --help' for usage");
241
241
  process.exitCode = 1;
242
242
  return;
243
243
  }
@@ -433,7 +433,7 @@ async function handleToolsExecutions(id, options) {
433
433
  process.exitCode = 1;
434
434
  return;
435
435
  }
436
- const { data: executions, total, pagination } = response.data;
436
+ const { items: executions, total, pagination } = response.data;
437
437
  if (isJsonOutput()) {
438
438
  printJson({ executions, total, pagination });
439
439
  return;
@@ -40,30 +40,30 @@ What are Toolsets?
40
40
  - Enable/disable entire groups of tools at once
41
41
 
42
42
  Examples:
43
- $ chanl toolsets list # List all toolsets
44
- $ chanl toolsets create -f toolset.json # Create new toolset
45
- $ chanl toolsets add-tools <id> -t id1,id2 # Add tools to toolset`
43
+ $ protobox toolsets list # List all toolsets
44
+ $ protobox toolsets create -f toolset.json # Create new toolset
45
+ $ protobox toolsets add-tools <id> -t id1,id2 # Add tools to toolset`
46
46
  );
47
47
  toolsets.command("list").description("List all toolsets in the workspace").option("-e, --enabled", "Show only enabled toolsets").option("-d, --disabled", "Show only disabled toolsets").option("--tag <tag>", "Filter by tag").option("-s, --search <search>", "Search by name or description").option("-l, --limit <number>", "Items per page (default: 20)", "20").option("-p, --page <number>", "Page number (default: 1)", "1").addHelpText(
48
48
  "after",
49
49
  `
50
50
  Examples:
51
- $ chanl toolsets list # List all
52
- $ chanl toolsets list --enabled # Only enabled
53
- $ chanl toolsets list --search "api" # Search by name`
51
+ $ protobox toolsets list # List all
52
+ $ protobox toolsets list --enabled # Only enabled
53
+ $ protobox toolsets list --search "api" # Search by name`
54
54
  ).action(handleToolsetsList);
55
55
  toolsets.command("get <id>").description("Get detailed info about a toolset").addHelpText(
56
56
  "after",
57
57
  `
58
58
  Example:
59
- $ chanl toolsets get 507f1f77bcf86cd799439011`
59
+ $ protobox toolsets get 507f1f77bcf86cd799439011`
60
60
  ).action(handleToolsetsGet);
61
61
  toolsets.command("create").description("Create a new toolset from JSON file").option("-f, --file <path>", "Path to JSON file with toolset definition").option("--template", "Output a sample JSON template").addHelpText(
62
62
  "after",
63
63
  `
64
64
  Examples:
65
- $ chanl toolsets create --template > my-toolset.json # Generate template
66
- $ chanl toolsets create -f my-toolset.json # Create from file
65
+ $ protobox toolsets create --template > my-toolset.json # Generate template
66
+ $ protobox toolsets create -f my-toolset.json # Create from file
67
67
 
68
68
  Required JSON fields:
69
69
  name Toolset name
@@ -79,14 +79,14 @@ Optional fields:
79
79
  "after",
80
80
  `
81
81
  Example:
82
- $ chanl toolsets update 507f1f77bcf86cd799439011 -f updates.json`
82
+ $ protobox toolsets update 507f1f77bcf86cd799439011 -f updates.json`
83
83
  ).action(handleToolsetsUpdate);
84
84
  toolsets.command("delete <id>").description("Delete a toolset permanently").option("-y, --yes", "Skip confirmation prompt").addHelpText(
85
85
  "after",
86
86
  `
87
87
  Examples:
88
- $ chanl toolsets delete 507f1f77bcf86cd799439011 # With confirmation
89
- $ chanl toolsets delete 507f1f77bcf86cd799439011 -y # Skip confirmation`
88
+ $ protobox toolsets delete 507f1f77bcf86cd799439011 # With confirmation
89
+ $ protobox toolsets delete 507f1f77bcf86cd799439011 -y # Skip confirmation`
90
90
  ).action(handleToolsetsDelete);
91
91
  toolsets.command("enable <id>").description("Enable a toolset (makes its tools available)").action(handleToolsetsEnable);
92
92
  toolsets.command("disable <id>").description("Disable a toolset (hides its tools)").action(handleToolsetsDisable);
@@ -94,13 +94,13 @@ Examples:
94
94
  "after",
95
95
  `
96
96
  Example:
97
- $ chanl toolsets add-tools 507f1f77bcf86cd799439011 -t tool1,tool2,tool3`
97
+ $ protobox toolsets add-tools 507f1f77bcf86cd799439011 -t tool1,tool2,tool3`
98
98
  ).action(handleToolsetsAddTools);
99
99
  toolsets.command("remove-tools <id>").description("Remove tools from a toolset").requiredOption("-t, --tools <ids>", "Comma-separated tool IDs").addHelpText(
100
100
  "after",
101
101
  `
102
102
  Example:
103
- $ chanl toolsets remove-tools 507f1f77bcf86cd799439011 -t tool1,tool2`
103
+ $ protobox toolsets remove-tools 507f1f77bcf86cd799439011 -t tool1,tool2`
104
104
  ).action(handleToolsetsRemoveTools);
105
105
  return toolsets;
106
106
  }
@@ -125,15 +125,9 @@ async function handleToolsetsList(options) {
125
125
  process.exitCode = 1;
126
126
  return;
127
127
  }
128
- const toolsets = response.data.items || response.data.data || [];
129
- const total = response.data.total ?? response.data.pagination?.total ?? toolsets.length;
130
- const pagination = response.data.pagination || {
131
- page: parseInt(options.page, 10),
132
- limit: parseInt(options.limit, 10),
133
- totalPages: Math.ceil(total / parseInt(options.limit, 10)),
134
- hasNext: false,
135
- hasPrev: false
136
- };
128
+ const toolsets = response.data.items;
129
+ const total = response.data.total;
130
+ const pagination = response.data.pagination;
137
131
  if (isJsonOutput()) {
138
132
  printJson({ toolsets, total, pagination });
139
133
  return;
@@ -195,7 +189,7 @@ async function handleToolsetsCreate(options) {
195
189
  }
196
190
  if (!options.file) {
197
191
  printError("Missing required option", "Use '-f, --file <path>' or '--template' for sample JSON");
198
- printInfo("Run 'chanl toolsets create --help' for usage");
192
+ printInfo("Run 'protobox toolsets create --help' for usage");
199
193
  process.exitCode = 1;
200
194
  return;
201
195
  }
@@ -23,29 +23,29 @@ What are Workspaces?
23
23
  configurations. Switch between workspaces to manage different projects.
24
24
 
25
25
  Quick Start:
26
- $ chanl workspaces list # List your workspaces
27
- $ chanl workspaces get <id> # View workspace details
28
- $ chanl workspaces use <id> # Set active workspace`
26
+ $ protobox workspaces list # List your workspaces
27
+ $ protobox workspaces get <id> # View workspace details
28
+ $ protobox workspaces use <id> # Set active workspace`
29
29
  );
30
30
  workspaces.command("list").description("List workspaces").addHelpText(
31
31
  "after",
32
32
  `
33
33
  Examples:
34
- $ chanl workspaces list # List all workspaces
35
- $ chanl workspaces list --json # Output as JSON`
34
+ $ protobox workspaces list # List all workspaces
35
+ $ protobox workspaces list --json # Output as JSON`
36
36
  ).action(handleWorkspacesList);
37
37
  workspaces.command("get <id>").description("Get workspace details").addHelpText(
38
38
  "after",
39
39
  `
40
40
  Examples:
41
- $ chanl workspaces get ws_abc123 # Get workspace details
42
- $ chanl workspaces get ws_abc123 --json # Output as JSON`
41
+ $ protobox workspaces get ws_abc123 # Get workspace details
42
+ $ protobox workspaces get ws_abc123 --json # Output as JSON`
43
43
  ).action(handleWorkspacesGet);
44
44
  workspaces.command("use <id>").description("Set active workspace (saves to config)").addHelpText(
45
45
  "after",
46
46
  `
47
47
  Examples:
48
- $ chanl workspaces use ws_abc123 # Switch to workspace
48
+ $ protobox workspaces use ws_abc123 # Switch to workspace
49
49
 
50
50
  This saves the workspace ID to your CLI config. All subsequent commands
51
51
  will use this workspace by default.`
@@ -87,7 +87,7 @@ class ConfigStore {
87
87
  }
88
88
  /**
89
89
  * Get API key with environment variable fallback
90
- * Priority: CHANL_API_KEY env var > config file
90
+ * Priority: PROTOBOX_API_KEY (CHANL_API_KEY fallback) > config file
91
91
  */
92
92
  getApiKey() {
93
93
  return process.env["PROTOBOX_API_KEY"] || process.env["CHANL_API_KEY"] || this.get("apiKey");
@@ -106,13 +106,13 @@ class ConfigStore {
106
106
  }
107
107
  /**
108
108
  * Get base URL with environment variable fallback
109
- * Priority: CHANL_BASE_URL env var > config file > default
109
+ * Priority: PROTOBOX_BASE_URL (CHANL_BASE_URL fallback) > config file > default
110
110
  */
111
111
  getBaseUrl() {
112
112
  return process.env["PROTOBOX_BASE_URL"] || process.env["CHANL_BASE_URL"] || this.get("server") || this.get("baseUrl");
113
113
  }
114
114
  getDeployment() {
115
- const d = process.env["CHANL_DEPLOYMENT"] || this.get("deployment");
115
+ const d = process.env["PROTOBOX_DEPLOYMENT"] || process.env["CHANL_DEPLOYMENT"] || this.get("deployment");
116
116
  if (d === "local" || d === "cloud") return d;
117
117
  const base = this.getBaseUrl();
118
118
  if (base.includes("localhost:18005") || base.includes("127.0.0.1:18005")) {
@@ -121,13 +121,13 @@ class ConfigStore {
121
121
  return void 0;
122
122
  }
123
123
  getApiPrefix() {
124
- const fromEnv = process.env["CHANL_API_PREFIX"];
124
+ const fromEnv = process.env["PROTOBOX_API_PREFIX"] ?? process.env["CHANL_API_PREFIX"];
125
125
  if (fromEnv !== void 0) return fromEnv;
126
126
  return this.get("apiPrefix");
127
127
  }
128
128
  /**
129
129
  * Get the app URL for browser-based flows (e.g., CLI auth)
130
- * Priority: CHANL_APP_URL env var > config file > derived from baseUrl
130
+ * Priority: PROTOBOX_APP_URL (CHANL_APP_URL fallback) > config file > derived from baseUrl
131
131
  */
132
132
  getAppUrl() {
133
133
  if (process.env["PROTOBOX_APP_URL"]) return process.env["PROTOBOX_APP_URL"];
@@ -140,7 +140,7 @@ class ConfigStore {
140
140
  }
141
141
  /**
142
142
  * Get workspace ID with environment variable fallback
143
- * Priority: CHANL_WORKSPACE_ID env var > config file
143
+ * Priority: PROTOBOX_WORKSPACE_ID (CHANL_WORKSPACE_ID fallback) > config file
144
144
  */
145
145
  getWorkspaceId() {
146
146
  return process.env["PROTOBOX_WORKSPACE_ID"] || process.env["CHANL_WORKSPACE_ID"] || this.get("workspaceId");
@@ -1,4 +1,4 @@
1
- import { ChanlSDK } from "@protoboxai/sdk";
1
+ import { ProtoboxSDK } from "@protoboxai/sdk";
2
2
  import { configStore } from "./config-store.js";
3
3
  import { printError } from "./output.js";
4
4
  function createSdk() {
@@ -6,7 +6,7 @@ function createSdk() {
6
6
  const jwtToken = configStore.getJwtToken();
7
7
  const baseUrl = configStore.getBaseUrl();
8
8
  if (!apiKey && !jwtToken) {
9
- printError("Not authenticated", "Run 'chanl login' to authenticate");
9
+ printError("Not authenticated", "Run 'protobox login' to authenticate");
10
10
  process.exitCode = 1;
11
11
  return null;
12
12
  }
@@ -14,16 +14,16 @@ function createSdk() {
14
14
  const apiPrefix = configStore.getApiPrefix();
15
15
  if (apiKey) {
16
16
  if (apiKey.startsWith("eyJ")) {
17
- return new ChanlSDK({
17
+ return new ProtoboxSDK({
18
18
  jwtToken: apiKey,
19
19
  baseUrl,
20
20
  deployment,
21
21
  apiPrefix
22
22
  });
23
23
  }
24
- return new ChanlSDK({ apiKey, baseUrl, deployment, apiPrefix });
24
+ return new ProtoboxSDK({ apiKey, baseUrl, deployment, apiPrefix });
25
25
  }
26
- return new ChanlSDK({
26
+ return new ProtoboxSDK({
27
27
  jwtToken,
28
28
  baseUrl,
29
29
  deployment,
@@ -33,7 +33,7 @@ function createSdk() {
33
33
  function getWorkspaceId() {
34
34
  const workspaceId = configStore.getWorkspaceId();
35
35
  if (!workspaceId) {
36
- printError("No workspace selected", "Run 'chanl config set workspaceId <id>' to select a workspace");
36
+ printError("No workspace selected", "Run 'protobox config set workspaceId <id>' to select a workspace");
37
37
  process.exitCode = 1;
38
38
  return null;
39
39
  }
package/package.json CHANGED
@@ -1,23 +1,12 @@
1
1
  {
2
2
  "name": "@protoboxai/cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Command-line interface for Protobox — MCP, tools, knowledge, agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
8
8
  "protobox": "./bin/protobox.js"
9
9
  },
10
- "scripts": {
11
- "build": "tsup",
12
- "dev": "tsup --watch",
13
- "clean": "rimraf dist",
14
- "prebuild": "npm run clean",
15
- "test": "vitest run",
16
- "test:watch": "vitest",
17
- "lint": "eslint src/**/*.ts",
18
- "format": "prettier --write src/**/*.ts",
19
- "typecheck": "tsc --noEmit"
20
- },
21
10
  "keywords": [
22
11
  "protobox",
23
12
  "cli",
@@ -29,7 +18,6 @@
29
18
  "author": "Protobox",
30
19
  "license": "MIT",
31
20
  "dependencies": {
32
- "@protoboxai/sdk": "workspace:*",
33
21
  "@inquirer/prompts": "^7.10.1",
34
22
  "@modelcontextprotocol/sdk": "^1.25.1",
35
23
  "chalk": "^5.3.0",
@@ -37,7 +25,8 @@
37
25
  "conf": "^13.0.1",
38
26
  "inquirer": "^12.2.0",
39
27
  "open": "^11.0.0",
40
- "ora": "^8.1.1"
28
+ "ora": "^8.1.1",
29
+ "@protoboxai/sdk": "^1.0.0"
41
30
  },
42
31
  "devDependencies": {
43
32
  "@types/inquirer": "^9.0.7",
@@ -58,5 +47,16 @@
58
47
  "publishConfig": {
59
48
  "registry": "https://registry.npmjs.org",
60
49
  "access": "public"
50
+ },
51
+ "scripts": {
52
+ "build": "tsup",
53
+ "dev": "tsup --watch",
54
+ "clean": "rimraf dist",
55
+ "prebuild": "npm run clean",
56
+ "test": "vitest run",
57
+ "test:watch": "vitest",
58
+ "lint": "eslint src/**/*.ts",
59
+ "format": "prettier --write src/**/*.ts",
60
+ "typecheck": "tsc --noEmit"
61
61
  }
62
- }
62
+ }