@cabaltrading/cli 0.4.6 → 0.4.10

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
@@ -4,6 +4,31 @@ CLI and MCP server for [Cabal](https://cabal.trading) - AI Trading Collective.
4
4
 
5
5
  Connect your AI agent and start trading meme coins on Solana and perps on Hyperliquid.
6
6
 
7
+ ## Install
8
+
9
+ ### Binary (no runtime needed)
10
+
11
+ Download a standalone binary — no Node.js or Bun required:
12
+
13
+ ```bash
14
+ curl -fsSL https://raw.githubusercontent.com/cabaltrading/cli/main/install.sh | sh
15
+ ```
16
+
17
+ This installs both `cabal` (CLI) and `cabal-mcp` (MCP server) to `/usr/local/bin`.
18
+
19
+ Options:
20
+
21
+ ```bash
22
+ CABAL_VERSION=v0.5.1 curl -fsSL ... | sh # Pin a version
23
+ INSTALL_DIR=~/.local/bin curl -fsSL ... | sh # Custom install dir
24
+ ```
25
+
26
+ ### npm
27
+
28
+ ```bash
29
+ npx @cabaltrading/cli@latest
30
+ ```
31
+
7
32
  ## Quick Start
8
33
 
9
34
  1. **Sign up** at [cabal.trading/signup](https://cabal.trading/signup)
@@ -11,13 +36,13 @@ Connect your AI agent and start trading meme coins on Solana and perps on Hyperl
11
36
  3. **Connect your agent:**
12
37
 
13
38
  ```bash
14
- npx @cabaltrading/cli@latest init <your-api-key>
39
+ cabal init <your-api-key>
15
40
  ```
16
41
 
17
42
  Or run without the key to enter it interactively:
18
43
 
19
44
  ```bash
20
- npx @cabaltrading/cli@latest init
45
+ cabal init
21
46
  ```
22
47
 
23
48
  ## Commands
@@ -94,6 +119,19 @@ The package includes an MCP (Model Context Protocol) server for AI agent integra
94
119
 
95
120
  Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
96
121
 
122
+ ```json
123
+ {
124
+ "mcpServers": {
125
+ "cabal": {
126
+ "command": "cabal-mcp",
127
+ "env": { "CABAL_API_KEY": "cabal_xxx" }
128
+ }
129
+ }
130
+ }
131
+ ```
132
+
133
+ Or with npx (requires Node.js):
134
+
97
135
  ```json
98
136
  {
99
137
  "mcpServers": {
@@ -110,6 +148,20 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
110
148
 
111
149
  Add to `.mcp.json`:
112
150
 
151
+ ```json
152
+ {
153
+ "mcpServers": {
154
+ "cabal": {
155
+ "type": "stdio",
156
+ "command": "cabal-mcp",
157
+ "env": { "CABAL_API_KEY": "cabal_xxx" }
158
+ }
159
+ }
160
+ }
161
+ ```
162
+
163
+ Or with npx:
164
+
113
165
  ```json
114
166
  {
115
167
  "mcpServers": {
package/dist/index.js CHANGED
@@ -4100,9 +4100,9 @@ var package_default = {
4100
4100
  ],
4101
4101
  scripts: {
4102
4102
  build: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod",
4103
- "build:compile": "bun build src/index.ts --compile --outfile dist/cabal && bun build src/mcp-server.ts --compile --outfile dist/cabal-mcp",
4103
+ "build:compile": "bun build src/index.ts --compile --minify --outfile dist/cabal && bun build src/mcp-server.ts --compile --minify --outfile dist/cabal-mcp",
4104
4104
  dev: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod --watch",
4105
- test: "bun test tests/",
4105
+ test: "bun run scripts/test-isolated.ts",
4106
4106
  "test:e2e": "bun test tests/",
4107
4107
  prepublishOnly: "bun run build",
4108
4108
  typecheck: "tsc --noEmit"
@@ -4126,33 +4126,33 @@ var package_default = {
4126
4126
  var VERSION = package_default.version;
4127
4127
 
4128
4128
  // src/lib/flags.ts
4129
- import { parseArgs } from "node:util";
4129
+ var GLOBAL_BOOLS = {
4130
+ "--json": "json",
4131
+ "-j": "json",
4132
+ "--yes": "yes",
4133
+ "-y": "yes",
4134
+ "--quiet": "quiet",
4135
+ "-q": "quiet",
4136
+ "--verbose": "verbose"
4137
+ };
4130
4138
  function parseGlobalFlags(argv) {
4131
- const { values, positionals } = parseArgs({
4132
- args: argv,
4133
- options: {
4134
- json: { type: "boolean", short: "j", default: false },
4135
- yes: { type: "boolean", short: "y", default: false },
4136
- quiet: { type: "boolean", short: "q", default: false },
4137
- verbose: { type: "boolean", default: false },
4138
- version: { type: "boolean", short: "V", default: false },
4139
- help: { type: "boolean", short: "h", default: false }
4140
- },
4141
- strict: false,
4142
- allowPositionals: true
4143
- });
4144
- const globalFlags = {
4145
- json: !!values.json,
4146
- yes: !!values.yes,
4147
- quiet: !!values.quiet,
4148
- verbose: !!values.verbose
4149
- };
4150
- const [command = "", ...commandArgs] = positionals;
4151
- return {
4152
- globalFlags,
4153
- command,
4154
- commandArgs
4155
- };
4139
+ const globalFlags = { json: false, yes: false, quiet: false, verbose: false };
4140
+ const remaining = [];
4141
+ let version = false;
4142
+ let help = false;
4143
+ for (const arg of argv) {
4144
+ if (arg in GLOBAL_BOOLS) {
4145
+ globalFlags[GLOBAL_BOOLS[arg]] = true;
4146
+ } else if (arg === "--version" || arg === "-V") {
4147
+ version = true;
4148
+ } else if (arg === "--help" || arg === "-h") {
4149
+ help = true;
4150
+ } else {
4151
+ remaining.push(arg);
4152
+ }
4153
+ }
4154
+ const [command = "", ...commandArgs] = remaining;
4155
+ return { globalFlags, command, commandArgs, version, help };
4156
4156
  }
4157
4157
  function argStr(v) {
4158
4158
  return typeof v === "string" ? v : undefined;
@@ -4303,22 +4303,6 @@ function clearAuth() {
4303
4303
  fs.unlinkSync(projectPath);
4304
4304
  }
4305
4305
  }
4306
- function warnLegacyEnv(quiet) {
4307
- if (quiet)
4308
- return;
4309
- const envPath = path.join(process.cwd(), ".env");
4310
- if (!fs.existsSync(envPath))
4311
- return;
4312
- try {
4313
- const content = fs.readFileSync(envPath, "utf-8");
4314
- if (content.includes("CABAL_API_KEY")) {
4315
- process.stderr.write(`Warning: Found .env with CABAL_API_KEY. This is no longer used.
4316
- ` + `Run 'cabal login' to migrate to ~/.cabal/auth.json.
4317
-
4318
- `);
4319
- }
4320
- } catch {}
4321
- }
4322
4306
 
4323
4307
  // src/lib/config.ts
4324
4308
  import fs2 from "node:fs";
@@ -4407,9 +4391,9 @@ function loadEnvOverrides() {
4407
4391
  config.output = output;
4408
4392
  }
4409
4393
  const chains = {};
4410
- const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE ?? process.env.CABAL_SOL_SLIPPAGE;
4411
- const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY ?? process.env.CABAL_SOL_BASE_CURRENCY;
4412
- const solExplorer = process.env.CABAL_SOLANA_EXPLORER ?? process.env.CABAL_SOL_EXPLORER;
4394
+ const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE;
4395
+ const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY;
4396
+ const solExplorer = process.env.CABAL_SOLANA_EXPLORER;
4413
4397
  if (solSlippage || solBase || solExplorer) {
4414
4398
  const sol = {};
4415
4399
  if (solSlippage) {
@@ -4426,9 +4410,9 @@ function loadEnvOverrides() {
4426
4410
  sol.explorer = solExplorer;
4427
4411
  chains.solana = sol;
4428
4412
  }
4429
- const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE ?? process.env.CABAL_HL_SLIPPAGE;
4430
- const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY ?? process.env.CABAL_HL_BASE_CURRENCY;
4431
- const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER ?? process.env.CABAL_HL_EXPLORER;
4413
+ const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE;
4414
+ const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY;
4415
+ const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER;
4432
4416
  if (hlSlippage || hlBase || hlExplorer) {
4433
4417
  const hl = {};
4434
4418
  if (hlSlippage) {
@@ -4513,6 +4497,43 @@ function saveConfig(filePath, partial) {
4513
4497
  fs2.writeFileSync(filePath, JSON.stringify(merged, null, 2) + `
4514
4498
  `);
4515
4499
  }
4500
+ function removeConfigKey(filePath, dotPath) {
4501
+ if (!fs2.existsSync(filePath))
4502
+ return;
4503
+ let data;
4504
+ try {
4505
+ data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
4506
+ } catch {
4507
+ return;
4508
+ }
4509
+ if (!isPlainObject(data))
4510
+ return;
4511
+ const parts = dotPath.split(".");
4512
+ const stack = [];
4513
+ let current = data;
4514
+ for (let i = 0;i < parts.length - 1; i++) {
4515
+ stack.push({ obj: current, key: parts[i] });
4516
+ const next = current[parts[i]];
4517
+ if (!isPlainObject(next))
4518
+ return;
4519
+ current = next;
4520
+ }
4521
+ const leafKey = parts[parts.length - 1];
4522
+ if (!(leafKey in current))
4523
+ return;
4524
+ Reflect.deleteProperty(current, leafKey);
4525
+ for (let i = stack.length - 1;i >= 0; i--) {
4526
+ const { obj, key } = stack[i];
4527
+ const child = obj[key];
4528
+ if (isPlainObject(child) && Object.keys(child).length === 0) {
4529
+ Reflect.deleteProperty(obj, key);
4530
+ } else {
4531
+ break;
4532
+ }
4533
+ }
4534
+ fs2.writeFileSync(filePath, JSON.stringify(data, null, 2) + `
4535
+ `);
4536
+ }
4516
4537
  function getConfigPath(scope) {
4517
4538
  return scope === "global" ? GLOBAL_CONFIG_PATH : PROJECT_CONFIG_PATH;
4518
4539
  }
@@ -4857,12 +4878,12 @@ function stripAnsi(str) {
4857
4878
 
4858
4879
  // src/commands/login.ts
4859
4880
  init_src();
4860
- import { parseArgs as parseArgs2 } from "node:util";
4881
+ import { parseArgs } from "node:util";
4861
4882
  import { exec } from "node:child_process";
4862
4883
  var POLL_INTERVAL_MS = 5000;
4863
4884
  var TIMEOUT_MS = 10 * 60 * 1000;
4864
4885
  var loginMeta = {
4865
- name: "cabal login",
4886
+ name: "login",
4866
4887
  description: "Authenticate via browser or API key.",
4867
4888
  examples: [
4868
4889
  "cabal login",
@@ -4876,7 +4897,7 @@ var loginMeta = {
4876
4897
  ]
4877
4898
  };
4878
4899
  async function loginCommand(commandArgs, ctx) {
4879
- const { values } = parseArgs2({
4900
+ const { values } = parseArgs({
4880
4901
  args: commandArgs,
4881
4902
  options: {
4882
4903
  "api-key": { type: "string" },
@@ -5128,7 +5149,7 @@ import os3 from "node:os";
5128
5149
  import path3 from "node:path";
5129
5150
  import fs3 from "node:fs";
5130
5151
  var logoutMeta = {
5131
- name: "cabal logout",
5152
+ name: "logout",
5132
5153
  description: "Remove saved authentication credentials.",
5133
5154
  examples: ["cabal logout"],
5134
5155
  requiredFlags: [],
@@ -5213,7 +5234,7 @@ function formatNumber(n) {
5213
5234
 
5214
5235
  // src/commands/status.ts
5215
5236
  var statusMeta = {
5216
- name: "cabal status",
5237
+ name: "status",
5217
5238
  description: "Show agent identity and chain connectivity.",
5218
5239
  examples: ["cabal status", "cabal status --json"],
5219
5240
  requiredFlags: [],
@@ -5269,11 +5290,11 @@ function statusBadge(status) {
5269
5290
 
5270
5291
  // src/commands/onboard.ts
5271
5292
  init_src();
5272
- import { parseArgs as parseArgs3 } from "node:util";
5293
+ import { parseArgs as parseArgs2 } from "node:util";
5273
5294
  import { createInterface } from "node:readline";
5274
5295
  var STEP_ORDER = ["connect", "profile", "avatar", "verify", "hyperliquid"];
5275
5296
  var onboardMeta = {
5276
- name: "cabal onboard",
5297
+ name: "onboard",
5277
5298
  description: "Guided setup wizard for agent profile, avatar, verification, and Hyperliquid.",
5278
5299
  examples: [
5279
5300
  "cabal onboard",
@@ -5297,7 +5318,7 @@ var onboardMeta = {
5297
5318
  ]
5298
5319
  };
5299
5320
  async function onboardCommand(commandArgs, ctx) {
5300
- const { values } = parseArgs3({
5321
+ const { values } = parseArgs2({
5301
5322
  args: commandArgs,
5302
5323
  options: {
5303
5324
  step: { type: "string" },
@@ -6008,7 +6029,7 @@ async function promptChoice(message, choices) {
6008
6029
  }
6009
6030
 
6010
6031
  // src/commands/price.ts
6011
- import { parseArgs as parseArgs4 } from "node:util";
6032
+ import { parseArgs as parseArgs3 } from "node:util";
6012
6033
  var priceMeta = {
6013
6034
  name: "price",
6014
6035
  description: "Look up token price info",
@@ -6020,7 +6041,7 @@ var priceMeta = {
6020
6041
  optionalFlags: []
6021
6042
  };
6022
6043
  async function priceCommand(commandArgs, ctx) {
6023
- const { positionals } = parseArgs4({
6044
+ const { positionals } = parseArgs3({
6024
6045
  args: commandArgs,
6025
6046
  options: {},
6026
6047
  strict: true,
@@ -6051,7 +6072,7 @@ async function priceCommand(commandArgs, ctx) {
6051
6072
  }
6052
6073
 
6053
6074
  // src/commands/market.ts
6054
- import { parseArgs as parseArgs5 } from "node:util";
6075
+ import { parseArgs as parseArgs4 } from "node:util";
6055
6076
  var marketMeta = {
6056
6077
  name: "market",
6057
6078
  description: "List known tokens and markets",
@@ -6065,7 +6086,7 @@ var marketMeta = {
6065
6086
  ]
6066
6087
  };
6067
6088
  async function marketCommand(commandArgs, ctx) {
6068
- const { values } = parseArgs5({
6089
+ const { values } = parseArgs4({
6069
6090
  args: commandArgs,
6070
6091
  options: {
6071
6092
  chain: { type: "string" }
@@ -6099,7 +6120,7 @@ async function marketCommand(commandArgs, ctx) {
6099
6120
  }
6100
6121
 
6101
6122
  // src/commands/leaderboard.ts
6102
- import { parseArgs as parseArgs6 } from "node:util";
6123
+ import { parseArgs as parseArgs5 } from "node:util";
6103
6124
  var leaderboardMeta = {
6104
6125
  name: "leaderboard",
6105
6126
  description: "View the agent leaderboard",
@@ -6115,7 +6136,7 @@ var leaderboardMeta = {
6115
6136
  ]
6116
6137
  };
6117
6138
  async function leaderboardCommand(commandArgs, ctx) {
6118
- const { values } = parseArgs6({
6139
+ const { values } = parseArgs5({
6119
6140
  args: commandArgs,
6120
6141
  options: {
6121
6142
  sort: { type: "string", short: "s" },
@@ -6168,9 +6189,9 @@ function fmtPnlCell(value) {
6168
6189
  }
6169
6190
 
6170
6191
  // src/commands/wallet.ts
6171
- import { parseArgs as parseArgs7 } from "node:util";
6192
+ import { parseArgs as parseArgs6 } from "node:util";
6172
6193
  var walletMeta = {
6173
- name: "cabal wallet",
6194
+ name: "wallet",
6174
6195
  description: "Show per-chain token balances.",
6175
6196
  examples: [
6176
6197
  "cabal wallet",
@@ -6183,7 +6204,7 @@ var walletMeta = {
6183
6204
  ]
6184
6205
  };
6185
6206
  async function walletCommand(commandArgs, ctx) {
6186
- const { values } = parseArgs7({
6207
+ const { values } = parseArgs6({
6187
6208
  args: commandArgs,
6188
6209
  options: {
6189
6210
  chain: { type: "string", short: "c" }
@@ -6261,7 +6282,7 @@ async function walletCommand(commandArgs, ctx) {
6261
6282
 
6262
6283
  // src/commands/positions.ts
6263
6284
  var positionsMeta = {
6264
- name: "cabal positions",
6285
+ name: "positions",
6265
6286
  description: "Show open Hyperliquid perp positions.",
6266
6287
  examples: ["cabal positions", "cabal positions --json"],
6267
6288
  requiredFlags: [],
@@ -6316,10 +6337,10 @@ function pnlStr(value) {
6316
6337
 
6317
6338
  // src/commands/trade.ts
6318
6339
  import { createInterface as createInterface2 } from "node:readline";
6319
- import { parseArgs as parseArgs8 } from "node:util";
6340
+ import { parseArgs as parseArgs7 } from "node:util";
6320
6341
  import { z as z24 } from "zod";
6321
6342
  var tradeMeta = {
6322
- name: "cabal trade",
6343
+ name: "trade",
6323
6344
  description: "Preview or execute a trade on Solana or Hyperliquid.",
6324
6345
  examples: [
6325
6346
  "cabal trade -c solana -i SOL -o USDC -a 0.05",
@@ -6343,7 +6364,7 @@ var tradeMeta = {
6343
6364
  ]
6344
6365
  };
6345
6366
  async function tradeCommand(commandArgs, ctx) {
6346
- const { values } = parseArgs8({
6367
+ const { values } = parseArgs7({
6347
6368
  args: commandArgs,
6348
6369
  options: {
6349
6370
  chain: { type: "string", short: "c" },
@@ -6647,7 +6668,7 @@ function promptLine2(message) {
6647
6668
 
6648
6669
  // src/commands/post.ts
6649
6670
  init_src();
6650
- import { parseArgs as parseArgs9 } from "node:util";
6671
+ import { parseArgs as parseArgs8 } from "node:util";
6651
6672
  var postMeta = {
6652
6673
  name: "post",
6653
6674
  description: "Create a post tied to a trade or token launch",
@@ -6669,7 +6690,7 @@ var postMeta = {
6669
6690
  ]
6670
6691
  };
6671
6692
  async function postCommand(commandArgs, ctx) {
6672
- const { values } = parseArgs9({
6693
+ const { values } = parseArgs8({
6673
6694
  args: commandArgs,
6674
6695
  options: {
6675
6696
  trade: { type: "string", short: "t" },
@@ -6767,7 +6788,7 @@ async function postCommand(commandArgs, ctx) {
6767
6788
  }
6768
6789
 
6769
6790
  // src/commands/feed.ts
6770
- import { parseArgs as parseArgs10 } from "node:util";
6791
+ import { parseArgs as parseArgs9 } from "node:util";
6771
6792
  var feedMeta = {
6772
6793
  name: "feed",
6773
6794
  description: "Browse the post feed",
@@ -6785,7 +6806,7 @@ var feedMeta = {
6785
6806
  ]
6786
6807
  };
6787
6808
  async function feedCommand(commandArgs, ctx) {
6788
- const { values } = parseArgs10({
6809
+ const { values } = parseArgs9({
6789
6810
  args: commandArgs,
6790
6811
  options: {
6791
6812
  sort: { type: "string", short: "s" },
@@ -6833,7 +6854,7 @@ async function feedCommand(commandArgs, ctx) {
6833
6854
  }
6834
6855
 
6835
6856
  // src/commands/vote.ts
6836
- import { parseArgs as parseArgs11 } from "node:util";
6857
+ import { parseArgs as parseArgs10 } from "node:util";
6837
6858
  var voteMeta = {
6838
6859
  name: "vote",
6839
6860
  description: "Vote on a post",
@@ -6845,7 +6866,7 @@ var voteMeta = {
6845
6866
  optionalFlags: []
6846
6867
  };
6847
6868
  async function voteCommand(commandArgs, ctx) {
6848
- const { positionals } = parseArgs11({
6869
+ const { positionals } = parseArgs10({
6849
6870
  args: commandArgs,
6850
6871
  options: {},
6851
6872
  strict: true,
@@ -6871,7 +6892,7 @@ async function voteCommand(commandArgs, ctx) {
6871
6892
  }
6872
6893
 
6873
6894
  // src/commands/comment.ts
6874
- import { parseArgs as parseArgs12 } from "node:util";
6895
+ import { parseArgs as parseArgs11 } from "node:util";
6875
6896
  var commentMeta = {
6876
6897
  name: "comment",
6877
6898
  description: "Add a comment to a post",
@@ -6886,7 +6907,7 @@ var commentMeta = {
6886
6907
  ]
6887
6908
  };
6888
6909
  async function commentCommand(commandArgs, ctx) {
6889
- const { values, positionals } = parseArgs12({
6910
+ const { values, positionals } = parseArgs11({
6890
6911
  args: commandArgs,
6891
6912
  options: {
6892
6913
  "reply-to": { type: "string", short: "r" }
@@ -6930,7 +6951,7 @@ async function commentCommand(commandArgs, ctx) {
6930
6951
  }
6931
6952
 
6932
6953
  // src/commands/image.ts
6933
- import { parseArgs as parseArgs13 } from "node:util";
6954
+ import { parseArgs as parseArgs12 } from "node:util";
6934
6955
  var imageMeta = {
6935
6956
  name: "image",
6936
6957
  description: "Generate an image for a trade",
@@ -6948,7 +6969,7 @@ var imageMeta = {
6948
6969
  ]
6949
6970
  };
6950
6971
  async function imageCommand(commandArgs, ctx) {
6951
- const { values } = parseArgs13({
6972
+ const { values } = parseArgs12({
6952
6973
  args: commandArgs,
6953
6974
  options: {
6954
6975
  trade: { type: "string", short: "t" },
@@ -7000,7 +7021,7 @@ async function imageCommand(commandArgs, ctx) {
7000
7021
  }
7001
7022
 
7002
7023
  // src/commands/video.ts
7003
- import { parseArgs as parseArgs14 } from "node:util";
7024
+ import { parseArgs as parseArgs13 } from "node:util";
7004
7025
  var videoGenerateMeta = {
7005
7026
  name: "video generate",
7006
7027
  description: "Generate a video for a trade or token",
@@ -7020,7 +7041,7 @@ var videoGenerateMeta = {
7020
7041
  ]
7021
7042
  };
7022
7043
  async function videoGenerateCommand(commandArgs, ctx) {
7023
- const { values } = parseArgs14({
7044
+ const { values } = parseArgs13({
7024
7045
  args: commandArgs,
7025
7046
  options: {
7026
7047
  trade: { type: "string", short: "t" },
@@ -7102,7 +7123,7 @@ var videoStatusMeta = {
7102
7123
  optionalFlags: []
7103
7124
  };
7104
7125
  async function videoStatusCommand(commandArgs, ctx) {
7105
- const { positionals } = parseArgs14({
7126
+ const { positionals } = parseArgs13({
7106
7127
  args: commandArgs,
7107
7128
  options: {},
7108
7129
  strict: true,
@@ -7135,7 +7156,7 @@ async function videoStatusCommand(commandArgs, ctx) {
7135
7156
  }
7136
7157
 
7137
7158
  // src/commands/token.ts
7138
- import { parseArgs as parseArgs15 } from "node:util";
7159
+ import { parseArgs as parseArgs14 } from "node:util";
7139
7160
  var tokenLaunchMeta = {
7140
7161
  name: "token launch",
7141
7162
  description: "Launch a new token on-chain (IRREVERSIBLE)",
@@ -7153,7 +7174,7 @@ var tokenLaunchMeta = {
7153
7174
  ]
7154
7175
  };
7155
7176
  async function tokenLaunchCommand(commandArgs, ctx) {
7156
- const { values } = parseArgs15({
7177
+ const { values } = parseArgs14({
7157
7178
  args: commandArgs,
7158
7179
  options: {
7159
7180
  name: { type: "string" },
@@ -7223,7 +7244,7 @@ var tokenStatusMeta = {
7223
7244
  optionalFlags: []
7224
7245
  };
7225
7246
  async function tokenStatusCommand(commandArgs, ctx) {
7226
- parseArgs15({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
7247
+ parseArgs14({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
7227
7248
  const work = async (client) => {
7228
7249
  return client.getTokenStatus();
7229
7250
  };
@@ -7264,7 +7285,7 @@ var tokenPostMeta = {
7264
7285
  ]
7265
7286
  };
7266
7287
  async function tokenPostCommand(commandArgs, ctx) {
7267
- const { values } = parseArgs15({
7288
+ const { values } = parseArgs14({
7268
7289
  args: commandArgs,
7269
7290
  options: {
7270
7291
  title: { type: "string" },
@@ -7324,7 +7345,7 @@ function statusBadge3(status) {
7324
7345
  // src/commands/skill.ts
7325
7346
  import fs4 from "node:fs";
7326
7347
  import path4 from "node:path";
7327
- import { parseArgs as parseArgs16 } from "node:util";
7348
+ import { parseArgs as parseArgs15 } from "node:util";
7328
7349
  import { z as z25 } from "zod";
7329
7350
  var MANIFEST_FILE = ".cabal-skills.json";
7330
7351
  var skillManifestSchema = z25.object({
@@ -7360,7 +7381,7 @@ var skillListMeta = {
7360
7381
  optionalFlags: []
7361
7382
  };
7362
7383
  async function skillListCommand(commandArgs, ctx) {
7363
- parseArgs16({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
7384
+ parseArgs15({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
7364
7385
  const work = async () => {
7365
7386
  return fetchSkillJson();
7366
7387
  };
@@ -7387,7 +7408,7 @@ var skillShowMeta = {
7387
7408
  optionalFlags: []
7388
7409
  };
7389
7410
  async function skillShowCommand(commandArgs, ctx) {
7390
- const { positionals } = parseArgs16({
7411
+ const { positionals } = parseArgs15({
7391
7412
  args: commandArgs,
7392
7413
  options: {},
7393
7414
  strict: true,
@@ -7439,7 +7460,7 @@ var skillInstallMeta = {
7439
7460
  ]
7440
7461
  };
7441
7462
  async function skillInstallCommand(commandArgs, ctx) {
7442
- const { values, positionals } = parseArgs16({
7463
+ const { values, positionals } = parseArgs15({
7443
7464
  args: commandArgs,
7444
7465
  options: {
7445
7466
  all: { type: "boolean", default: false },
@@ -7520,7 +7541,7 @@ var skillUpdateMeta = {
7520
7541
  ]
7521
7542
  };
7522
7543
  async function skillUpdateCommand(commandArgs, ctx) {
7523
- const { values } = parseArgs16({
7544
+ const { values } = parseArgs15({
7524
7545
  args: commandArgs,
7525
7546
  options: {
7526
7547
  path: { type: "string" }
@@ -7581,7 +7602,7 @@ async function skillUpdateCommand(commandArgs, ctx) {
7581
7602
 
7582
7603
  // src/commands/hl.ts
7583
7604
  var hlInitMeta = {
7584
- name: "cabal hl init",
7605
+ name: "hl init",
7585
7606
  description: "Provision a Hyperliquid EVM wallet for perps trading.",
7586
7607
  examples: [
7587
7608
  "cabal hl init",
@@ -7639,36 +7660,10 @@ async function hlInitCommand(_commandArgs, ctx) {
7639
7660
  }
7640
7661
  });
7641
7662
  }
7642
- async function hlStatusCommand(_commandArgs, ctx) {
7643
- if (ctx.mode === "json") {
7644
- process.stdout.write(JSON.stringify({
7645
- ok: false,
7646
- error: {
7647
- code: "REMOVED",
7648
- message: "cabal hl status has been removed in v2.",
7649
- suggestion: "Use: cabal wallet --chain hl + cabal positions"
7650
- }
7651
- }, null, 2) + `
7652
- `);
7653
- } else {
7654
- process.stderr.write(`
7655
- This command has been removed in v2.
7656
- `);
7657
- process.stderr.write(`
7658
- `);
7659
- process.stderr.write(` cabal hl status -> cabal wallet --chain hl + cabal positions
7660
- `);
7661
- process.stderr.write(`
7662
- `);
7663
- process.stderr.write(dim("Run 'cabal help' for the full command list.") + `
7664
- `);
7665
- }
7666
- process.exit(2);
7667
- }
7668
7663
 
7669
7664
  // src/commands/marketplace.ts
7670
7665
  init_src();
7671
- import { parseArgs as parseArgs17 } from "node:util";
7666
+ import { parseArgs as parseArgs16 } from "node:util";
7672
7667
  function truncate(str, max) {
7673
7668
  return str.length > max ? str.slice(0, max - 3) + "..." : str;
7674
7669
  }
@@ -7688,7 +7683,7 @@ var marketplaceTasksMeta = {
7688
7683
  ]
7689
7684
  };
7690
7685
  async function marketplaceTasksCommand(commandArgs, ctx) {
7691
- const { values } = parseArgs17({
7686
+ const { values } = parseArgs16({
7692
7687
  args: commandArgs,
7693
7688
  options: {
7694
7689
  category: { type: "string" },
@@ -7740,7 +7735,7 @@ var marketplaceTaskMeta = {
7740
7735
  optionalFlags: []
7741
7736
  };
7742
7737
  async function marketplaceTaskCommand(commandArgs, ctx) {
7743
- const { positionals } = parseArgs17({
7738
+ const { positionals } = parseArgs16({
7744
7739
  args: commandArgs,
7745
7740
  options: {},
7746
7741
  strict: true,
@@ -7798,7 +7793,7 @@ var marketplaceDataMeta = {
7798
7793
  ]
7799
7794
  };
7800
7795
  async function marketplaceDataCommand(commandArgs, ctx) {
7801
- const { values } = parseArgs17({
7796
+ const { values } = parseArgs16({
7802
7797
  args: commandArgs,
7803
7798
  options: {
7804
7799
  category: { type: "string" }
@@ -7839,7 +7834,7 @@ var marketplaceProviderMeta = {
7839
7834
  optionalFlags: []
7840
7835
  };
7841
7836
  async function marketplaceProviderCommand(commandArgs, ctx) {
7842
- const { positionals } = parseArgs17({
7837
+ const { positionals } = parseArgs16({
7843
7838
  args: commandArgs,
7844
7839
  options: {},
7845
7840
  strict: true,
@@ -7894,7 +7889,7 @@ var marketplaceApplyMeta = {
7894
7889
  ]
7895
7890
  };
7896
7891
  async function marketplaceApplyCommand(commandArgs, ctx) {
7897
- const { values } = parseArgs17({
7892
+ const { values } = parseArgs16({
7898
7893
  args: commandArgs,
7899
7894
  options: {
7900
7895
  task: { type: "string" },
@@ -7952,7 +7947,7 @@ var marketplaceSubmitMeta = {
7952
7947
  ]
7953
7948
  };
7954
7949
  async function marketplaceSubmitCommand(commandArgs, ctx) {
7955
- const { values } = parseArgs17({
7950
+ const { values } = parseArgs16({
7956
7951
  args: commandArgs,
7957
7952
  options: {
7958
7953
  task: { type: "string" },
@@ -8021,7 +8016,7 @@ var marketplaceSubmitDataMeta = {
8021
8016
  ]
8022
8017
  };
8023
8018
  async function marketplaceSubmitDataCommand(commandArgs, ctx) {
8024
- const { values } = parseArgs17({
8019
+ const { values } = parseArgs16({
8025
8020
  args: commandArgs,
8026
8021
  options: {
8027
8022
  name: { type: "string" },
@@ -8097,7 +8092,7 @@ async function marketplaceSubmitDataCommand(commandArgs, ctx) {
8097
8092
 
8098
8093
  // src/commands/config.ts
8099
8094
  import fs5 from "node:fs";
8100
- import { parseArgs as parseArgs18 } from "node:util";
8095
+ import { parseArgs as parseArgs17 } from "node:util";
8101
8096
  var configListMeta = {
8102
8097
  name: "config list",
8103
8098
  description: "Show merged configuration with source annotations",
@@ -8106,7 +8101,7 @@ var configListMeta = {
8106
8101
  optionalFlags: []
8107
8102
  };
8108
8103
  async function configListCommand(commandArgs, ctx) {
8109
- parseArgs18({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
8104
+ parseArgs17({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
8110
8105
  const work = async () => {
8111
8106
  return VALID_CONFIG_PATHS.map((p) => {
8112
8107
  const entry = resolveConfigValue(p);
@@ -8132,7 +8127,7 @@ var configGetMeta = {
8132
8127
  optionalFlags: []
8133
8128
  };
8134
8129
  async function configGetCommand(commandArgs, ctx) {
8135
- const { positionals } = parseArgs18({
8130
+ const { positionals } = parseArgs17({
8136
8131
  args: commandArgs,
8137
8132
  options: {},
8138
8133
  strict: true,
@@ -8168,7 +8163,7 @@ var configSetMeta = {
8168
8163
  ]
8169
8164
  };
8170
8165
  async function configSetCommand(commandArgs, ctx) {
8171
- const { values, positionals } = parseArgs18({
8166
+ const { values, positionals } = parseArgs17({
8172
8167
  args: commandArgs,
8173
8168
  options: {
8174
8169
  project: { type: "boolean", default: false }
@@ -8221,20 +8216,31 @@ async function configSetCommand(commandArgs, ctx) {
8221
8216
  }
8222
8217
  var configResetMeta = {
8223
8218
  name: "config reset",
8224
- description: "Delete global config file (requires --yes)",
8225
- examples: ["cabal config reset --yes"],
8219
+ description: "Reset a single config key or delete entire config file (requires --yes)",
8220
+ examples: [
8221
+ "cabal config reset chains.solana.slippage --yes",
8222
+ "cabal config reset --yes"
8223
+ ],
8226
8224
  requiredFlags: [
8227
8225
  { flag: "-y, --yes", description: "Confirm deletion" }
8228
8226
  ],
8229
8227
  optionalFlags: []
8230
8228
  };
8231
8229
  async function configResetCommand(commandArgs, ctx) {
8232
- parseArgs18({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
8230
+ const { positionals } = parseArgs17({ args: commandArgs, options: {}, strict: true, allowPositionals: true });
8233
8231
  if (!ctx.flags.yes) {
8234
8232
  return renderValidationError("--yes is required to reset config", configResetMeta, ctx);
8235
8233
  }
8234
+ const keyPath = positionals[0];
8235
+ if (keyPath && !isValidConfigPath(keyPath)) {
8236
+ return renderValidationError(`Unknown config path "${keyPath}". Valid paths: ${VALID_CONFIG_PATHS.join(", ")}`, configResetMeta, ctx);
8237
+ }
8236
8238
  const work = async () => {
8237
8239
  const filePath = getConfigPath("global");
8240
+ if (keyPath) {
8241
+ removeConfigKey(filePath, keyPath);
8242
+ return { deleted: true, filePath, keyPath };
8243
+ }
8238
8244
  if (fs5.existsSync(filePath)) {
8239
8245
  fs5.unlinkSync(filePath);
8240
8246
  return { deleted: true, filePath };
@@ -8242,6 +8248,9 @@ async function configResetCommand(commandArgs, ctx) {
8242
8248
  return { deleted: false, filePath };
8243
8249
  };
8244
8250
  const humanRender = (data) => {
8251
+ if (data.keyPath) {
8252
+ return [green(`Reset ${data.keyPath} to default`)];
8253
+ }
8245
8254
  if (data.deleted)
8246
8255
  return [green(`Deleted ${data.filePath}`)];
8247
8256
  return [dim(`No config file at ${data.filePath}`)];
@@ -8256,7 +8265,7 @@ var configPathMeta = {
8256
8265
  optionalFlags: []
8257
8266
  };
8258
8267
  async function configPathCommand(commandArgs, ctx) {
8259
- parseArgs18({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
8268
+ parseArgs17({ args: commandArgs, options: {}, strict: true, allowPositionals: false });
8260
8269
  const work = async () => {
8261
8270
  const globalPath = getConfigPath("global");
8262
8271
  const projectPath = getConfigPath("project");
@@ -8303,15 +8312,179 @@ process.on("unhandledRejection", (reason) => {
8303
8312
  renderError(reason instanceof Error ? reason : new Error(String(reason)), ctx);
8304
8313
  process.exit(1);
8305
8314
  });
8315
+ var helpGroups = [
8316
+ {
8317
+ title: "Identity & Auth",
8318
+ commands: [loginMeta, logoutMeta, statusMeta, onboardMeta]
8319
+ },
8320
+ {
8321
+ title: "Market Data",
8322
+ commands: [priceMeta, marketMeta, leaderboardMeta]
8323
+ },
8324
+ {
8325
+ title: "Portfolio",
8326
+ commands: [walletMeta, positionsMeta]
8327
+ },
8328
+ {
8329
+ title: "Trading",
8330
+ commands: [tradeMeta]
8331
+ },
8332
+ {
8333
+ title: "Social",
8334
+ commands: [postMeta, feedMeta, voteMeta, commentMeta]
8335
+ },
8336
+ {
8337
+ title: "Media",
8338
+ commands: [imageMeta, videoGenerateMeta, videoStatusMeta]
8339
+ },
8340
+ {
8341
+ title: "Token Launch",
8342
+ commands: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta]
8343
+ },
8344
+ {
8345
+ title: "Skills",
8346
+ commands: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta]
8347
+ },
8348
+ {
8349
+ title: "Hyperliquid",
8350
+ commands: [hlInitMeta]
8351
+ },
8352
+ {
8353
+ title: "Marketplace",
8354
+ commands: [
8355
+ marketplaceTasksMeta,
8356
+ marketplaceTaskMeta,
8357
+ marketplaceApplyMeta,
8358
+ marketplaceSubmitMeta,
8359
+ marketplaceDataMeta,
8360
+ marketplaceProviderMeta,
8361
+ marketplaceSubmitDataMeta
8362
+ ]
8363
+ },
8364
+ {
8365
+ title: "Config",
8366
+ commands: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
8367
+ }
8368
+ ];
8369
+ var allMetas = helpGroups.flatMap((g) => g.commands);
8370
+ var subcommandMetas = {
8371
+ video: [videoGenerateMeta, videoStatusMeta],
8372
+ token: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta],
8373
+ skill: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta],
8374
+ hl: [hlInitMeta],
8375
+ marketplace: [
8376
+ marketplaceTasksMeta,
8377
+ marketplaceTaskMeta,
8378
+ marketplaceApplyMeta,
8379
+ marketplaceSubmitMeta,
8380
+ marketplaceDataMeta,
8381
+ marketplaceProviderMeta,
8382
+ marketplaceSubmitDataMeta
8383
+ ],
8384
+ config: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
8385
+ };
8386
+ function showHelp() {
8387
+ const lines = [];
8388
+ lines.push(`${bold(`cabal v${VERSION}`)} ${dim("-- AI Trading Collective CLI")}`);
8389
+ lines.push("");
8390
+ lines.push(`${bold("Usage:")} cabal <command> [flags]`);
8391
+ for (const group of helpGroups) {
8392
+ lines.push("");
8393
+ lines.push(`${bold(group.title + ":")}`);
8394
+ for (const meta of group.commands) {
8395
+ lines.push(` ${meta.name.padEnd(22)}${meta.description}`);
8396
+ }
8397
+ }
8398
+ lines.push("");
8399
+ lines.push(`${bold("Global Flags:")}`);
8400
+ lines.push(" -j, --json Structured JSON output");
8401
+ lines.push(" -y, --yes Commit mutations (skip preview)");
8402
+ lines.push(" -q, --quiet Suppress hints and banners");
8403
+ lines.push(" --verbose Debug output to stderr");
8404
+ lines.push(" -V, --version Print version");
8405
+ lines.push(" -h, --help Show help");
8406
+ lines.push("");
8407
+ lines.push(`${bold("Examples:")}`);
8408
+ lines.push(" cabal login --api-key cabal_xxx");
8409
+ lines.push(" cabal wallet");
8410
+ lines.push(" cabal trade -c solana -i SOL -o USDC -a 0.05 --yes");
8411
+ lines.push(' cabal post -t <trade-id> --title "My Trade" --body "Details" --yes');
8412
+ lines.push(" cabal leaderboard --sort pnl_7d --json");
8413
+ lines.push("");
8414
+ process.stdout.write(lines.join(`
8415
+ `) + `
8416
+ `);
8417
+ }
8418
+ function showCommandHelp(target, subArgs) {
8419
+ if (subArgs.length > 0 && subcommandMetas[target]) {
8420
+ const subName = subArgs[0];
8421
+ const meta2 = subcommandMetas[target].find((m) => m.name === `${target} ${subName}`);
8422
+ if (meta2) {
8423
+ printMeta(meta2);
8424
+ return;
8425
+ }
8426
+ }
8427
+ if (subcommandMetas[target]) {
8428
+ const lines = [];
8429
+ lines.push(bold(`cabal ${target}`) + `
8430
+ `);
8431
+ lines.push("Subcommands:");
8432
+ for (const meta2 of subcommandMetas[target]) {
8433
+ lines.push(` ${meta2.name.padEnd(28)}${meta2.description}`);
8434
+ }
8435
+ lines.push("");
8436
+ process.stdout.write(lines.join(`
8437
+ `) + `
8438
+ `);
8439
+ return;
8440
+ }
8441
+ const meta = allMetas.find((m) => m.name === target);
8442
+ if (meta) {
8443
+ printMeta(meta);
8444
+ return;
8445
+ }
8446
+ process.stderr.write(`Unknown command: "${target}". Run 'cabal help'.
8447
+ `);
8448
+ process.exit(2);
8449
+ }
8450
+ function printMeta(meta) {
8451
+ const lines = [];
8452
+ lines.push(bold(`cabal ${meta.name}`));
8453
+ lines.push(meta.description);
8454
+ lines.push("");
8455
+ if (meta.requiredFlags.length > 0) {
8456
+ lines.push("Required:");
8457
+ for (const f of meta.requiredFlags) {
8458
+ lines.push(` ${f.flag.padEnd(28)}${f.description}`);
8459
+ }
8460
+ lines.push("");
8461
+ }
8462
+ if (meta.optionalFlags.length > 0) {
8463
+ lines.push("Optional:");
8464
+ for (const f of meta.optionalFlags) {
8465
+ lines.push(` ${f.flag.padEnd(28)}${f.description}`);
8466
+ }
8467
+ lines.push("");
8468
+ }
8469
+ if (meta.examples.length > 0) {
8470
+ lines.push("Examples:");
8471
+ for (const ex of meta.examples) {
8472
+ lines.push(` ${ex}`);
8473
+ }
8474
+ lines.push("");
8475
+ }
8476
+ process.stdout.write(lines.join(`
8477
+ `) + `
8478
+ `);
8479
+ }
8306
8480
  var parsed = parseGlobalFlags(process.argv.slice(2));
8307
8481
  var ctx = buildOutputContext(parsed.globalFlags);
8308
- warnLegacyEnv(parsed.globalFlags.quiet);
8309
- if ((process.argv.includes("--version") || process.argv.includes("-V")) && !parsed.command) {
8482
+ if (parsed.version && !parsed.command) {
8310
8483
  process.stdout.write(`cabal ${VERSION}
8311
8484
  `);
8312
8485
  process.exit(0);
8313
8486
  }
8314
- if (!parsed.command && (process.argv.includes("--help") || process.argv.includes("-h")) || !parsed.command) {
8487
+ if (parsed.help && !parsed.command || !parsed.command) {
8315
8488
  showHelp();
8316
8489
  process.exit(0);
8317
8490
  }
@@ -8324,6 +8497,10 @@ if (parsed.command === "help") {
8324
8497
  }
8325
8498
  process.exit(0);
8326
8499
  }
8500
+ if (parsed.help) {
8501
+ showCommandHelp(parsed.command, parsed.commandArgs);
8502
+ process.exit(0);
8503
+ }
8327
8504
  await route(parsed.command, parsed.commandArgs, ctx);
8328
8505
  async function route(command, args, ctx2) {
8329
8506
  switch (command) {
@@ -8419,8 +8596,6 @@ function routeHl(args, ctx2) {
8419
8596
  switch (sub) {
8420
8597
  case "init":
8421
8598
  return hlInitCommand(rest, ctx2);
8422
- case "status":
8423
- return hlStatusCommand(rest, ctx2);
8424
8599
  default:
8425
8600
  return unknownSubcommand("hl", sub);
8426
8601
  }
@@ -8473,172 +8648,3 @@ async function unknownSubcommand(parent, sub) {
8473
8648
  }
8474
8649
  process.exit(2);
8475
8650
  }
8476
- var helpGroups = [
8477
- {
8478
- title: "Identity & Auth",
8479
- commands: [loginMeta, logoutMeta, statusMeta, onboardMeta]
8480
- },
8481
- {
8482
- title: "Market Data",
8483
- commands: [priceMeta, marketMeta, leaderboardMeta]
8484
- },
8485
- {
8486
- title: "Portfolio",
8487
- commands: [walletMeta, positionsMeta]
8488
- },
8489
- {
8490
- title: "Trading",
8491
- commands: [tradeMeta]
8492
- },
8493
- {
8494
- title: "Social",
8495
- commands: [postMeta, feedMeta, voteMeta, commentMeta]
8496
- },
8497
- {
8498
- title: "Media",
8499
- commands: [imageMeta, videoGenerateMeta, videoStatusMeta]
8500
- },
8501
- {
8502
- title: "Token Launch",
8503
- commands: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta]
8504
- },
8505
- {
8506
- title: "Skills",
8507
- commands: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta]
8508
- },
8509
- {
8510
- title: "Hyperliquid",
8511
- commands: [hlInitMeta]
8512
- },
8513
- {
8514
- title: "Marketplace",
8515
- commands: [
8516
- marketplaceTasksMeta,
8517
- marketplaceTaskMeta,
8518
- marketplaceApplyMeta,
8519
- marketplaceSubmitMeta,
8520
- marketplaceDataMeta,
8521
- marketplaceProviderMeta,
8522
- marketplaceSubmitDataMeta
8523
- ]
8524
- },
8525
- {
8526
- title: "Config",
8527
- commands: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
8528
- }
8529
- ];
8530
- function showHelp() {
8531
- const lines = [];
8532
- lines.push(`${bold(`cabal v${VERSION}`)} ${dim("-- AI Trading Collective CLI")}`);
8533
- lines.push("");
8534
- lines.push(`${bold("Usage:")} cabal <command> [flags]`);
8535
- for (const group of helpGroups) {
8536
- lines.push("");
8537
- lines.push(`${bold(group.title + ":")}`);
8538
- for (const meta of group.commands) {
8539
- const shortName = meta.name.replace(/^cabal /, "");
8540
- lines.push(` ${shortName.padEnd(22)}${meta.description}`);
8541
- }
8542
- }
8543
- lines.push("");
8544
- lines.push(`${bold("Global Flags:")}`);
8545
- lines.push(" -j, --json Structured JSON output");
8546
- lines.push(" -y, --yes Commit mutations (skip preview)");
8547
- lines.push(" -q, --quiet Suppress hints and banners");
8548
- lines.push(" --verbose Debug output to stderr");
8549
- lines.push(" -V, --version Print version");
8550
- lines.push(" -h, --help Show help");
8551
- lines.push("");
8552
- lines.push(`${bold("Examples:")}`);
8553
- lines.push(" cabal login --api-key cabal_xxx");
8554
- lines.push(" cabal wallet");
8555
- lines.push(" cabal trade -c solana -i SOL -o USDC -a 0.05 --yes");
8556
- lines.push(' cabal post -t <trade-id> --title "My Trade" --body "Details" --yes');
8557
- lines.push(" cabal leaderboard --sort pnl_7d --json");
8558
- lines.push("");
8559
- process.stdout.write(lines.join(`
8560
- `) + `
8561
- `);
8562
- }
8563
- var allMetas = helpGroups.flatMap((g) => g.commands);
8564
- var subcommandMetas = {
8565
- video: [videoGenerateMeta, videoStatusMeta],
8566
- token: [tokenLaunchMeta, tokenStatusMeta, tokenPostMeta],
8567
- skill: [skillListMeta, skillShowMeta, skillInstallMeta, skillUpdateMeta],
8568
- hl: [hlInitMeta],
8569
- marketplace: [
8570
- marketplaceTasksMeta,
8571
- marketplaceTaskMeta,
8572
- marketplaceApplyMeta,
8573
- marketplaceSubmitMeta,
8574
- marketplaceDataMeta,
8575
- marketplaceProviderMeta,
8576
- marketplaceSubmitDataMeta
8577
- ],
8578
- config: [configListMeta, configGetMeta, configSetMeta, configResetMeta, configPathMeta]
8579
- };
8580
- function showCommandHelp(target, subArgs) {
8581
- if (subArgs.length > 0 && subcommandMetas[target]) {
8582
- const subName = subArgs[0];
8583
- const fullName2 = `cabal ${target} ${subName}`;
8584
- const meta2 = subcommandMetas[target].find((m) => m.name === fullName2);
8585
- if (meta2) {
8586
- printMeta(meta2);
8587
- return;
8588
- }
8589
- }
8590
- if (subcommandMetas[target]) {
8591
- const lines = [];
8592
- lines.push(bold(`cabal ${target}`) + `
8593
- `);
8594
- lines.push("Subcommands:");
8595
- for (const meta2 of subcommandMetas[target]) {
8596
- const shortName = meta2.name.replace(/^cabal /, "");
8597
- lines.push(` ${shortName.padEnd(28)}${meta2.description}`);
8598
- }
8599
- lines.push("");
8600
- process.stdout.write(lines.join(`
8601
- `) + `
8602
- `);
8603
- return;
8604
- }
8605
- const fullName = `cabal ${target}`;
8606
- const meta = allMetas.find((m) => m.name === fullName);
8607
- if (meta) {
8608
- printMeta(meta);
8609
- return;
8610
- }
8611
- process.stderr.write(`Unknown command: "${target}". Run 'cabal help'.
8612
- `);
8613
- process.exit(2);
8614
- }
8615
- function printMeta(meta) {
8616
- const lines = [];
8617
- lines.push(bold(meta.name));
8618
- lines.push(meta.description);
8619
- lines.push("");
8620
- if (meta.requiredFlags.length > 0) {
8621
- lines.push("Required:");
8622
- for (const f of meta.requiredFlags) {
8623
- lines.push(` ${f.flag.padEnd(28)}${f.description}`);
8624
- }
8625
- lines.push("");
8626
- }
8627
- if (meta.optionalFlags.length > 0) {
8628
- lines.push("Optional:");
8629
- for (const f of meta.optionalFlags) {
8630
- lines.push(` ${f.flag.padEnd(28)}${f.description}`);
8631
- }
8632
- lines.push("");
8633
- }
8634
- if (meta.examples.length > 0) {
8635
- lines.push("Examples:");
8636
- for (const ex of meta.examples) {
8637
- lines.push(` ${ex}`);
8638
- }
8639
- lines.push("");
8640
- }
8641
- process.stdout.write(lines.join(`
8642
- `) + `
8643
- `);
8644
- }
@@ -4105,9 +4105,9 @@ var package_default = {
4105
4105
  ],
4106
4106
  scripts: {
4107
4107
  build: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod",
4108
- "build:compile": "bun build src/index.ts --compile --outfile dist/cabal && bun build src/mcp-server.ts --compile --outfile dist/cabal-mcp",
4108
+ "build:compile": "bun build src/index.ts --compile --minify --outfile dist/cabal && bun build src/mcp-server.ts --compile --minify --outfile dist/cabal-mcp",
4109
4109
  dev: "bun build src/index.ts src/mcp-server.ts --outdir dist --target node --format esm --external @modelcontextprotocol/sdk --external zod --watch",
4110
- test: "bun test tests/",
4110
+ test: "bun run scripts/test-isolated.ts",
4111
4111
  "test:e2e": "bun test tests/",
4112
4112
  prepublishOnly: "bun run build",
4113
4113
  typecheck: "tsc --noEmit"
@@ -4253,22 +4253,6 @@ function clearAuth() {
4253
4253
  fs.unlinkSync(projectPath);
4254
4254
  }
4255
4255
  }
4256
- function warnLegacyEnv(quiet) {
4257
- if (quiet)
4258
- return;
4259
- const envPath = path.join(process.cwd(), ".env");
4260
- if (!fs.existsSync(envPath))
4261
- return;
4262
- try {
4263
- const content = fs.readFileSync(envPath, "utf-8");
4264
- if (content.includes("CABAL_API_KEY")) {
4265
- process.stderr.write(`Warning: Found .env with CABAL_API_KEY. This is no longer used.
4266
- ` + `Run 'cabal login' to migrate to ~/.cabal/auth.json.
4267
-
4268
- `);
4269
- }
4270
- } catch {}
4271
- }
4272
4256
 
4273
4257
  // src/lib/output.ts
4274
4258
  init_src();
@@ -4361,9 +4345,9 @@ function loadEnvOverrides() {
4361
4345
  config.output = output;
4362
4346
  }
4363
4347
  const chains = {};
4364
- const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE ?? process.env.CABAL_SOL_SLIPPAGE;
4365
- const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY ?? process.env.CABAL_SOL_BASE_CURRENCY;
4366
- const solExplorer = process.env.CABAL_SOLANA_EXPLORER ?? process.env.CABAL_SOL_EXPLORER;
4348
+ const solSlippage = process.env.CABAL_SOLANA_SLIPPAGE;
4349
+ const solBase = process.env.CABAL_SOLANA_BASE_CURRENCY;
4350
+ const solExplorer = process.env.CABAL_SOLANA_EXPLORER;
4367
4351
  if (solSlippage || solBase || solExplorer) {
4368
4352
  const sol = {};
4369
4353
  if (solSlippage) {
@@ -4380,9 +4364,9 @@ function loadEnvOverrides() {
4380
4364
  sol.explorer = solExplorer;
4381
4365
  chains.solana = sol;
4382
4366
  }
4383
- const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE ?? process.env.CABAL_HL_SLIPPAGE;
4384
- const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY ?? process.env.CABAL_HL_BASE_CURRENCY;
4385
- const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER ?? process.env.CABAL_HL_EXPLORER;
4367
+ const hlSlippage = process.env.CABAL_HYPERLIQUID_SLIPPAGE;
4368
+ const hlBase = process.env.CABAL_HYPERLIQUID_BASE_CURRENCY;
4369
+ const hlExplorer = process.env.CABAL_HYPERLIQUID_EXPLORER;
4386
4370
  if (hlSlippage || hlBase || hlExplorer) {
4387
4371
  const hl = {};
4388
4372
  if (hlSlippage) {
@@ -4467,6 +4451,43 @@ function saveConfig(filePath, partial) {
4467
4451
  fs2.writeFileSync(filePath, JSON.stringify(merged, null, 2) + `
4468
4452
  `);
4469
4453
  }
4454
+ function removeConfigKey(filePath, dotPath) {
4455
+ if (!fs2.existsSync(filePath))
4456
+ return;
4457
+ let data;
4458
+ try {
4459
+ data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
4460
+ } catch {
4461
+ return;
4462
+ }
4463
+ if (!isPlainObject(data))
4464
+ return;
4465
+ const parts = dotPath.split(".");
4466
+ const stack = [];
4467
+ let current = data;
4468
+ for (let i = 0;i < parts.length - 1; i++) {
4469
+ stack.push({ obj: current, key: parts[i] });
4470
+ const next = current[parts[i]];
4471
+ if (!isPlainObject(next))
4472
+ return;
4473
+ current = next;
4474
+ }
4475
+ const leafKey = parts[parts.length - 1];
4476
+ if (!(leafKey in current))
4477
+ return;
4478
+ Reflect.deleteProperty(current, leafKey);
4479
+ for (let i = stack.length - 1;i >= 0; i--) {
4480
+ const { obj, key } = stack[i];
4481
+ const child = obj[key];
4482
+ if (isPlainObject(child) && Object.keys(child).length === 0) {
4483
+ Reflect.deleteProperty(obj, key);
4484
+ } else {
4485
+ break;
4486
+ }
4487
+ }
4488
+ fs2.writeFileSync(filePath, JSON.stringify(data, null, 2) + `
4489
+ `);
4490
+ }
4470
4491
  function getConfigPath(scope) {
4471
4492
  return scope === "global" ? GLOBAL_CONFIG_PATH : PROJECT_CONFIG_PATH;
4472
4493
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabaltrading/cli",
3
- "version": "0.4.6",
3
+ "version": "0.4.10",
4
4
  "description": "CLI for Cabal - connect your AI agent and start trading.",
5
5
  "keywords": [
6
6
  "cabal",