@otonix/cli 2.1.1 → 2.1.3

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.
@@ -1,13 +1,9 @@
1
- import { confirm, input } from "@inquirer/prompts";
1
+ import { confirm } from "@inquirer/prompts";
2
2
  import ora from "ora";
3
3
  import chalk from "chalk";
4
4
  import { loadConfig, saveConfig, OTONIX_TREASURY } from "../lib/config.js";
5
- import { generateWallet, getEthBalance, getOtxBalance, formatOtx, OTX_REQUIRED, publicClient, OTX_ADDRESS, } from "../lib/chain.js";
5
+ import { generateWallet, getEthBalance, getOtxBalance, formatOtx, sendOtx, OTX_REQUIRED, publicClient, } from "../lib/chain.js";
6
6
  import { header, row, success, failure, info, br, warn, mono } from "../lib/display.js";
7
- import { parseAbi, decodeEventLog } from "viem";
8
- const transferAbi = parseAbi([
9
- "event Transfer(address indexed from, address indexed to, uint256 value)",
10
- ]);
11
7
  export function agentCommand(program) {
12
8
  program
13
9
  .command("agent:create")
@@ -56,14 +52,13 @@ export function agentCommand(program) {
56
52
  console.log(chalk.dim("Next — register this agent by sending 200 $OTX to:"));
57
53
  console.log(" " + chalk.white(OTONIX_TREASURY));
58
54
  br();
59
- console.log(chalk.dim("Then submit the tx hash to activate:"));
60
- console.log(" " + mono(`otonix agent:register --name ${name} --tx <txhash>`));
55
+ console.log(chalk.dim("Then register (auto-sends 200 $OTX):"));
56
+ console.log(" " + mono(`otonix agent:register --name ${name}`));
61
57
  });
62
58
  program
63
59
  .command("agent:register")
64
- .description("Activate an agent by submitting proof of 200 $OTX payment")
60
+ .description("Register an agent auto-sends 200 $OTX to Otonix treasury and activates it")
65
61
  .requiredOption("--name <name>", "Agent name to register")
66
- .option("--tx <hash>", "Transaction hash of your 200 $OTX transfer to Otonix treasury")
67
62
  .action(async (opts) => {
68
63
  header("Agent Registration");
69
64
  const cfg = loadConfig();
@@ -74,6 +69,8 @@ export function agentCommand(program) {
74
69
  }
75
70
  if (agent.registered) {
76
71
  success(`Agent "${opts.name}" is already registered!`);
72
+ br();
73
+ row("Status", chalk.green("✓ Registered & Active"));
77
74
  row("Tx hash", agent.registerTxHash ?? "—");
78
75
  row("Registered at", agent.registeredAt ? new Date(agent.registeredAt).toLocaleString() : "—");
79
76
  return;
@@ -82,67 +79,67 @@ export function agentCommand(program) {
82
79
  failure("No creator wallet found. Run: otonix wallet generate");
83
80
  process.exit(1);
84
81
  }
85
- let txHash = opts.tx;
86
- if (!txHash) {
87
- br();
88
- console.log(chalk.dim("Send 200 $OTX from your creator wallet to the Otonix treasury:"));
89
- console.log(" " + chalk.white(OTONIX_TREASURY));
90
- br();
91
- txHash = await input({ message: "Paste your transaction hash (0x...):" });
82
+ const balSpinner = ora("Checking creator wallet balance...").start();
83
+ let otxBal;
84
+ let ethBal;
85
+ try {
86
+ [otxBal, ethBal] = await Promise.all([
87
+ getOtxBalance(cfg.wallet.address),
88
+ getEthBalance(cfg.wallet.address),
89
+ ]);
90
+ }
91
+ catch {
92
+ balSpinner.stop();
93
+ failure("Failed to fetch balances. Check your connection.");
94
+ process.exit(1);
95
+ }
96
+ balSpinner.stop();
97
+ br();
98
+ row("Creator wallet", cfg.wallet.address);
99
+ row("$OTX balance", formatOtx(otxBal) + " OTX");
100
+ row("ETH balance", parseFloat(ethBal).toFixed(6) + " ETH (for gas)");
101
+ row("Registration fee", "200 $OTX → Otonix treasury");
102
+ row("Treasury", OTONIX_TREASURY);
103
+ br();
104
+ if (otxBal < OTX_REQUIRED) {
105
+ failure(`Insufficient $OTX. Need 200.000, have ${formatOtx(otxBal)}.`);
106
+ info("Buy $OTX at: https://dexscreener.com/base/0xF7E2a6226Ffe0693DD85406AC3A8917cbea5DC40");
107
+ process.exit(1);
108
+ }
109
+ if (parseFloat(ethBal) < 0.0001) {
110
+ failure("Insufficient ETH for gas. Send a small amount of ETH (Base) to your creator wallet.");
111
+ info("Creator wallet: " + cfg.wallet.address);
112
+ process.exit(1);
113
+ }
114
+ const confirmed = await confirm({
115
+ message: `Send 200 $OTX from your creator wallet to Otonix treasury to activate "${opts.name}"?`,
116
+ default: true,
117
+ });
118
+ if (!confirmed) {
119
+ info("Cancelled.");
120
+ return;
121
+ }
122
+ const sendSpinner = ora("Sending 200 $OTX to Otonix treasury...").start();
123
+ let txHash;
124
+ try {
125
+ txHash = await sendOtx(cfg.wallet.privateKey, OTONIX_TREASURY, OTX_REQUIRED);
92
126
  }
93
- if (!txHash.startsWith("0x") || txHash.length !== 66) {
94
- failure("Invalid tx hash. Must be 0x followed by 64 hex characters.");
127
+ catch (err) {
128
+ sendSpinner.stop();
129
+ const msg = err instanceof Error ? err.message : String(err);
130
+ failure("Failed to send $OTX: " + msg.slice(0, 120));
95
131
  process.exit(1);
96
132
  }
97
- const spinner = ora("Verifying transaction on Base...").start();
133
+ sendSpinner.text = `Waiting for confirmation... (${txHash.slice(0, 18)}...)`;
98
134
  try {
99
- const receipt = await publicClient.getTransactionReceipt({
135
+ const receipt = await publicClient.waitForTransactionReceipt({
100
136
  hash: txHash,
137
+ timeout: 60_000,
101
138
  });
139
+ sendSpinner.stop();
102
140
  if (receipt.status !== "success") {
103
- spinner.fail("Transaction failed on-chain.");
104
- failure("The tx hash you provided is a failed transaction.");
105
- process.exit(1);
106
- }
107
- let verified = false;
108
- let transferredAmount = 0n;
109
- for (const log of receipt.logs) {
110
- if (log.address.toLowerCase() !== OTX_ADDRESS.toLowerCase())
111
- continue;
112
- try {
113
- const decoded = decodeEventLog({
114
- abi: transferAbi,
115
- data: log.data,
116
- topics: log.topics,
117
- });
118
- if (decoded.eventName === "Transfer" &&
119
- decoded.args.from.toLowerCase() === cfg.wallet.address.toLowerCase() &&
120
- decoded.args.to.toLowerCase() === OTONIX_TREASURY.toLowerCase()) {
121
- transferredAmount = decoded.args.value;
122
- if (transferredAmount >= OTX_REQUIRED) {
123
- verified = true;
124
- break;
125
- }
126
- }
127
- }
128
- catch {
129
- continue;
130
- }
131
- }
132
- spinner.stop();
133
- if (!verified) {
134
- br();
135
- failure("Verification failed.");
136
- if (transferredAmount > 0n) {
137
- console.log(chalk.dim(` Found transfer of ${formatOtx(transferredAmount)} $OTX — need 200.000 $OTX minimum.`));
138
- }
139
- else {
140
- console.log(chalk.dim(" No valid $OTX transfer found in this tx."));
141
- console.log(chalk.dim(" Make sure you sent from your creator wallet:"));
142
- console.log(" " + chalk.white(cfg.wallet.address));
143
- console.log(chalk.dim(" to Otonix treasury:"));
144
- console.log(" " + chalk.white(OTONIX_TREASURY));
145
- }
141
+ failure("Transaction failed on-chain.");
142
+ info("Tx: https://basescan.org/tx/" + txHash);
146
143
  process.exit(1);
147
144
  }
148
145
  cfg.agents[opts.name].registered = true;
@@ -154,22 +151,21 @@ export function agentCommand(program) {
154
151
  br();
155
152
  row("Agent name", opts.name);
156
153
  row("Status", chalk.green("✓ Registered & Active"));
157
- row("OTX sent", formatOtx(transferredAmount) + " OTX");
154
+ row("OTX sent", "200.000 OTX");
158
155
  row("Tx hash", txHash);
159
- row("Treasury", OTONIX_TREASURY);
156
+ row("Basescan", "https://basescan.org/tx/" + txHash);
157
+ br();
158
+ console.log(chalk.dim("You can now deploy tokens. Fund the agent with ETH first:"));
159
+ console.log(" " + chalk.dim("Agent address:") + " " + chalk.white(agent.address));
160
160
  br();
161
- console.log(chalk.dim("You can now deploy tokens with this agent:"));
161
+ console.log(chalk.dim("Then deploy:"));
162
162
  console.log(" " + mono(`otonix launch token --agent ${opts.name} --name "MyToken" --ticker "MTK" --image "https://..." --description "..."`));
163
163
  }
164
164
  catch (err) {
165
- spinner.stop();
165
+ sendSpinner.stop();
166
166
  const msg = err instanceof Error ? err.message : String(err);
167
- if (msg.includes("not found") || msg.includes("cannot find")) {
168
- failure("Transaction not found on Base. Wait a moment and try again.");
169
- }
170
- else {
171
- failure("Failed to verify tx: " + msg.slice(0, 100));
172
- }
167
+ failure("Tx sent but confirmation timed out: " + msg.slice(0, 100));
168
+ info("Check manually: https://basescan.org/tx/" + txHash);
173
169
  process.exit(1);
174
170
  }
175
171
  });
@@ -207,9 +203,9 @@ export function agentCommand(program) {
207
203
  br();
208
204
  const ethNum = parseFloat(eth);
209
205
  if (!agent.registered) {
210
- console.log(warn("⊘ ") + chalk.dim("Send 200 $OTX to treasury to register:"));
211
- console.log(" " + chalk.white(OTONIX_TREASURY));
212
- console.log(" " + chalk.dim(`Then: otonix agent:register --name ${name} --tx <txhash>`));
206
+ console.log(warn("⊘ ") + chalk.dim("Not registered run this to activate:"));
207
+ console.log(" " + chalk.cyan(`otonix agent:register --name ${name}`));
208
+ console.log(" " + chalk.dim("(auto-sends 200 $OTX from your creator wallet)"));
213
209
  }
214
210
  else if (ethNum < 0.0005) {
215
211
  console.log(warn("⚠ ") + chalk.dim("Low ETH — fund this address with ≥0.001 ETH for gas:"));
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ const program = new Command();
15
15
  program
16
16
  .name("otonix")
17
17
  .description(chalk.bold.hex("#4d6fff")("OTONIX CLI") + chalk.dim(" — Web4 Autonomous Agent Infrastructure"))
18
- .version("2.1.1", "-v, --version")
18
+ .version("2.1.3", "-v, --version")
19
19
  .configureOutput({
20
20
  writeOut: str => process.stdout.write(str),
21
21
  writeErr: str => process.stderr.write(str),
@@ -1965,6 +1965,7 @@ export declare const publicClient: {
1965
1965
  withdrawals?: import("viem").Withdrawal[] | undefined | undefined;
1966
1966
  withdrawalsRoot?: `0x${string}` | undefined;
1967
1967
  transactions: includeTransactions extends true ? ({
1968
+ v: bigint;
1968
1969
  yParity: number;
1969
1970
  from: import("abitype").Address;
1970
1971
  gas: bigint;
@@ -1975,7 +1976,6 @@ export declare const publicClient: {
1975
1976
  s: import("viem").Hex;
1976
1977
  to: import("abitype").Address | null;
1977
1978
  typeHex: import("viem").Hex | null;
1978
- v: bigint;
1979
1979
  value: bigint;
1980
1980
  type: "deposit";
1981
1981
  gasPrice?: undefined | undefined;
@@ -1989,6 +1989,7 @@ export declare const publicClient: {
1989
1989
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
1990
1990
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
1991
1991
  } | {
1992
+ v: bigint;
1992
1993
  yParity?: undefined | undefined;
1993
1994
  from: import("abitype").Address;
1994
1995
  gas: bigint;
@@ -1999,7 +2000,6 @@ export declare const publicClient: {
1999
2000
  s: import("viem").Hex;
2000
2001
  to: import("abitype").Address | null;
2001
2002
  typeHex: import("viem").Hex | null;
2002
- v: bigint;
2003
2003
  value: bigint;
2004
2004
  accessList?: undefined | undefined;
2005
2005
  authorizationList?: undefined | undefined;
@@ -2017,6 +2017,7 @@ export declare const publicClient: {
2017
2017
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2018
2018
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2019
2019
  } | {
2020
+ v: bigint;
2020
2021
  yParity: number;
2021
2022
  from: import("abitype").Address;
2022
2023
  gas: bigint;
@@ -2027,7 +2028,6 @@ export declare const publicClient: {
2027
2028
  s: import("viem").Hex;
2028
2029
  to: import("abitype").Address | null;
2029
2030
  typeHex: import("viem").Hex | null;
2030
- v: bigint;
2031
2031
  value: bigint;
2032
2032
  accessList: import("viem").AccessList;
2033
2033
  authorizationList?: undefined | undefined;
@@ -2045,6 +2045,7 @@ export declare const publicClient: {
2045
2045
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2046
2046
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2047
2047
  } | {
2048
+ v: bigint;
2048
2049
  yParity: number;
2049
2050
  from: import("abitype").Address;
2050
2051
  gas: bigint;
@@ -2055,7 +2056,6 @@ export declare const publicClient: {
2055
2056
  s: import("viem").Hex;
2056
2057
  to: import("abitype").Address | null;
2057
2058
  typeHex: import("viem").Hex | null;
2058
- v: bigint;
2059
2059
  value: bigint;
2060
2060
  accessList: import("viem").AccessList;
2061
2061
  authorizationList?: undefined | undefined;
@@ -2073,6 +2073,7 @@ export declare const publicClient: {
2073
2073
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2074
2074
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2075
2075
  } | {
2076
+ v: bigint;
2076
2077
  yParity: number;
2077
2078
  from: import("abitype").Address;
2078
2079
  gas: bigint;
@@ -2083,7 +2084,6 @@ export declare const publicClient: {
2083
2084
  s: import("viem").Hex;
2084
2085
  to: import("abitype").Address | null;
2085
2086
  typeHex: import("viem").Hex | null;
2086
- v: bigint;
2087
2087
  value: bigint;
2088
2088
  accessList: import("viem").AccessList;
2089
2089
  authorizationList?: undefined | undefined;
@@ -2101,6 +2101,7 @@ export declare const publicClient: {
2101
2101
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2102
2102
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2103
2103
  } | {
2104
+ v: bigint;
2104
2105
  yParity: number;
2105
2106
  from: import("abitype").Address;
2106
2107
  gas: bigint;
@@ -2111,7 +2112,6 @@ export declare const publicClient: {
2111
2112
  s: import("viem").Hex;
2112
2113
  to: import("abitype").Address | null;
2113
2114
  typeHex: import("viem").Hex | null;
2114
- v: bigint;
2115
2115
  value: bigint;
2116
2116
  accessList: import("viem").AccessList;
2117
2117
  authorizationList: import("viem").SignedAuthorizationList;
@@ -2472,6 +2472,7 @@ export declare const publicClient: {
2472
2472
  } | undefined) => Promise<import("viem").EstimateMaxPriorityFeePerGasReturnType>;
2473
2473
  getStorageAt: (args: import("viem").GetStorageAtParameters) => Promise<import("viem").GetStorageAtReturnType>;
2474
2474
  getTransaction: <blockTag extends import("viem").BlockTag = "latest">(args: import("viem").GetTransactionParameters<blockTag>) => Promise<{
2475
+ v: bigint;
2475
2476
  yParity: number;
2476
2477
  from: import("abitype").Address;
2477
2478
  gas: bigint;
@@ -2482,7 +2483,6 @@ export declare const publicClient: {
2482
2483
  s: import("viem").Hex;
2483
2484
  to: import("abitype").Address | null;
2484
2485
  typeHex: import("viem").Hex | null;
2485
- v: bigint;
2486
2486
  value: bigint;
2487
2487
  type: "deposit";
2488
2488
  gasPrice?: undefined | undefined;
@@ -2496,6 +2496,7 @@ export declare const publicClient: {
2496
2496
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2497
2497
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2498
2498
  } | {
2499
+ v: bigint;
2499
2500
  yParity?: undefined | undefined;
2500
2501
  from: import("abitype").Address;
2501
2502
  gas: bigint;
@@ -2506,7 +2507,6 @@ export declare const publicClient: {
2506
2507
  s: import("viem").Hex;
2507
2508
  to: import("abitype").Address | null;
2508
2509
  typeHex: import("viem").Hex | null;
2509
- v: bigint;
2510
2510
  value: bigint;
2511
2511
  accessList?: undefined | undefined;
2512
2512
  authorizationList?: undefined | undefined;
@@ -2524,6 +2524,7 @@ export declare const publicClient: {
2524
2524
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2525
2525
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2526
2526
  } | {
2527
+ v: bigint;
2527
2528
  yParity: number;
2528
2529
  from: import("abitype").Address;
2529
2530
  gas: bigint;
@@ -2534,7 +2535,6 @@ export declare const publicClient: {
2534
2535
  s: import("viem").Hex;
2535
2536
  to: import("abitype").Address | null;
2536
2537
  typeHex: import("viem").Hex | null;
2537
- v: bigint;
2538
2538
  value: bigint;
2539
2539
  accessList: import("viem").AccessList;
2540
2540
  authorizationList?: undefined | undefined;
@@ -2552,6 +2552,7 @@ export declare const publicClient: {
2552
2552
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2553
2553
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2554
2554
  } | {
2555
+ v: bigint;
2555
2556
  yParity: number;
2556
2557
  from: import("abitype").Address;
2557
2558
  gas: bigint;
@@ -2562,7 +2563,6 @@ export declare const publicClient: {
2562
2563
  s: import("viem").Hex;
2563
2564
  to: import("abitype").Address | null;
2564
2565
  typeHex: import("viem").Hex | null;
2565
- v: bigint;
2566
2566
  value: bigint;
2567
2567
  accessList: import("viem").AccessList;
2568
2568
  authorizationList?: undefined | undefined;
@@ -2580,6 +2580,7 @@ export declare const publicClient: {
2580
2580
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2581
2581
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2582
2582
  } | {
2583
+ v: bigint;
2583
2584
  yParity: number;
2584
2585
  from: import("abitype").Address;
2585
2586
  gas: bigint;
@@ -2590,7 +2591,6 @@ export declare const publicClient: {
2590
2591
  s: import("viem").Hex;
2591
2592
  to: import("abitype").Address | null;
2592
2593
  typeHex: import("viem").Hex | null;
2593
- v: bigint;
2594
2594
  value: bigint;
2595
2595
  accessList: import("viem").AccessList;
2596
2596
  authorizationList?: undefined | undefined;
@@ -2608,6 +2608,7 @@ export declare const publicClient: {
2608
2608
  blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
2609
2609
  transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
2610
2610
  } | {
2611
+ v: bigint;
2611
2612
  yParity: number;
2612
2613
  from: import("abitype").Address;
2613
2614
  gas: bigint;
@@ -2618,7 +2619,6 @@ export declare const publicClient: {
2618
2619
  s: import("viem").Hex;
2619
2620
  to: import("abitype").Address | null;
2620
2621
  typeHex: import("viem").Hex | null;
2621
- v: bigint;
2622
2622
  value: bigint;
2623
2623
  accessList: import("viem").AccessList;
2624
2624
  authorizationList: import("viem").SignedAuthorizationList;
@@ -1,4 +1,7 @@
1
1
  import chalk from "chalk";
2
+ import { createRequire } from "module";
3
+ const _require = createRequire(import.meta.url);
4
+ const { version: CLI_VERSION } = _require("../../package.json");
2
5
  const BLUE = "#4d6fff";
3
6
  const BLUE_DIM = "#3a50cc";
4
7
  export const brand = chalk.bold.hex(BLUE);
@@ -25,7 +28,7 @@ export function printBanner() {
25
28
  console.log(" " +
26
29
  chalk.hex(BLUE_DIM)("web4 autonomous agent infrastructure") +
27
30
  " " +
28
- chalk.dim("v0.1.0"));
31
+ chalk.dim("v" + CLI_VERSION));
29
32
  console.log(" " + chalk.dim("─".repeat(48)));
30
33
  console.log();
31
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otonix/cli",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Otonix CLI — deploy autonomous agent tokens on Base via Clanker v4",
5
5
  "type": "module",
6
6
  "bin": {